Sophie

Sophie

distrib > Scientific%20Linux > 5x > x86_64 > by-pkgid > fc11cd6e1c513a17304da94a5390f3cd > files > 4109

kernel-2.6.18-194.11.1.el5.src.rpm

From: Jim Paradis <jparadis@redhat.com>
Date: Wed, 7 Oct 2009 16:59:15 -0400
Subject: [x86_64] fix hugepage memory tracking
Message-id: 20091007205915.14356.25143.sendpatchset@localhost.localdomain
O-Subject: [RHEL5.5 PATCH] Fix hugepage memory tracking
Bugzilla: 518671
RH-Acked-by: Rik van Riel <riel@redhat.com>

https://bugzilla.redhat.com/show_bug.cgi?id=518671

This bug is the RHEL5 equivalent of Bug 497204, where unmap_page_range was
incorrectly calling mm_track_pte() rather than mm_track_pmd() when tracking
a hugepage.  This patch fixes.  Although we add new routines to handle
hugepages, if memory tracking is not enabled then these routines execute
exatly the same code as before.

 mach-xen/asm/pgtable.h |   21 +++++++++++++++++++++
 page.h                 |    2 ++
 pgtable.h              |   18 ++++++++++++++++++
 3 files changed, 41 insertions(+)

diff --git a/include/asm-x86_64/mach-xen/asm/pgtable.h b/include/asm-x86_64/mach-xen/asm/pgtable.h
index be9deec..ee0570d 100644
--- a/include/asm-x86_64/mach-xen/asm/pgtable.h
+++ b/include/asm-x86_64/mach-xen/asm/pgtable.h
@@ -107,6 +107,12 @@ static inline void set_pte(pte_t *dst, pte_t val)
 	*dst = val;
 }
 
+static inline void set_huge_pte(pte_t *dst, pte_t val)
+{
+	mm_track_pmd( (pmd_t *)dst);
+	*dst = val;
+} 
+
 static inline void set_pmd(pmd_t *pmdptr, pmd_t pmdval)
 {
 	mm_track_pmd(pmdptr);
@@ -154,6 +160,13 @@ static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
 	return __pte_ma(xchg(&(xp)->pte, 0));
 }
 
+static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm,
+					    unsigned long addr, pte_t *xp)
+{
+	mm_track_pmd( (pmd_t *)xp);
+	return __pte_ma(xchg(&(xp)->pte, 0));
+}
+
 #if 0
 static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *xp)
 {
@@ -319,6 +332,14 @@ static inline unsigned long pud_bad(pud_t pud)
 		set_pte((ptep), (pteval));				\
 } while (0)
 
+static inline void set_huge_pte_at(struct mm_struct *_mm, unsigned long addr,
+				   pte_t *ptep, pte_t pteval)
+{
+	if (((_mm) != current->mm && (_mm) != &init_mm) ||
+	    HYPERVISOR_update_va_mapping((addr), (pteval), 0))
+		set_huge_pte(ptep, pteval);
+}
+
 #define pte_none(x)	(!(x).pte)
 #define pte_present(x)	((x).pte & (_PAGE_PRESENT | _PAGE_PROTNONE))
 #define pte_clear(mm,addr,xp)	do { set_pte_at(mm, addr, xp, __pte(0)); } while (0)
diff --git a/include/asm-x86_64/page.h b/include/asm-x86_64/page.h
index 383747f..5beb71d 100644
--- a/include/asm-x86_64/page.h
+++ b/include/asm-x86_64/page.h
@@ -38,6 +38,8 @@
 #define HPAGE_MASK	(~(HPAGE_SIZE - 1))
 #define HUGETLB_PAGE_ORDER	(HPAGE_SHIFT - PAGE_SHIFT)
 
+#define ARCH_HAS_SETCLEAR_HUGE_PTE
+
 #ifndef __ASSEMBLY__
 
 extern unsigned long end_pfn;
diff --git a/include/asm-x86_64/pgtable.h b/include/asm-x86_64/pgtable.h
index e61d0d8..eb55ef5 100644
--- a/include/asm-x86_64/pgtable.h
+++ b/include/asm-x86_64/pgtable.h
@@ -83,6 +83,18 @@ static inline void set_pte(pte_t *dst, pte_t val)
 } 
 #define set_pte_at(mm,addr,ptep,pteval) set_pte(ptep,pteval)
 
+static inline void set_huge_pte(pte_t *dst, pte_t val)
+{
+	mm_track_pmd( (pmd_t *)dst);
+	pte_val(*dst) = pte_val(val);
+} 
+
+static inline void set_huge_pte_at(struct mm_struct *mm, unsigned long addr,
+                                   pte_t *ptep, pte_t pte)
+{
+	set_huge_pte(ptep, pte);
+} 
+
 static inline void set_pmd(pmd_t *dst, pmd_t val)
 {
 	mm_track_pmd(dst);
@@ -120,6 +132,12 @@ static inline pte_t ptep_get_and_clear(struct mm_struct *mm, unsigned long addr,
 	return __pte(xchg(&(xp)->pte, 0));
 }
 
+static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *xp)
+{
+	mm_track_pmd( (pmd_t *)xp);
+	return __pte(xchg(&(xp)->pte, 0));
+}
+
 struct mm_struct;
 
 static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm, unsigned long addr, pte_t *ptep, int full)