Skip to contentSkip to conversation

Add hugetlb support for PV

PATCH In review Dave McCracken 3 participants 6 messages Jul 24, 2008

Subsystems (3)
lore
Share & tools
lore
#0 lore raw

cover Add hugetlb support for PV

Here is a set of small patches that enables hugetlb on PV machines. They are against xen-unstable and linux-2.6.18-xen.

The patches are specifically for x86_64.

I originally had these patches working back in May, but recently for some reason my machine now refuses to boot the baseline xen-unstable, so I've been unable to verify them. However, they should still work.

Comments, bug reports, and suggestions are welcome.

Dave McCracken
Oracle Corp.

#1 lore raw

PATCH 1/2 PV Hugetlb support - Hypervisor portion

Here is the hypervisor portion of hugetlb support for PV machines.

./fs/Kconfig +1 -1
@@ -870,7 +870,7 @@ config TMPFS
 config HUGETLBFS
 	bool "HugeTLB file system support"
 	depends X86 || IA64 || PPC64 || SPARC64 || SUPERH || BROKEN
-	depends on !XEN
+#	depends on !XEN
 	help
 	  hugetlbfs is a filesystem backing for HugeTLB pages, based on
 	  ramfs. For architectures that support it, say Y here and read
./include/asm-x86_64/mach-xen/asm/page.h +2 -0
@@ -62,6 +62,8 @@
 #define HPAGE_MASK	(~(HPAGE_SIZE - 1))
 #define HUGETLB_PAGE_ORDER	(HPAGE_SHIFT - PAGE_SHIFT)
 
+#define ARCH_HAS_SETCLEAR_HUGE_PTE
+
 #ifdef __KERNEL__
 #ifndef __ASSEMBLY__
 
./include/asm-x86_64/mach-xen/asm/pgtable.h +19 -0
@@ -261,6 +261,12 @@ static inline unsigned long pud_bad(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_pmd((pmd_t *)ptep, (pmd_t){__pte_val(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)
@@ -296,6 +302,19 @@ static inline pte_t ptep_get_and_clear(s
 	return pte;
 }
 
+static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
+{
+	pte_t pte = *ptep;
+	if (!pte_none(pte)) {
+		if ((mm != &init_mm) ||
+		    HYPERVISOR_update_va_mapping(addr, __pte(0), 0)) {
+			pte = *ptep;
+			set_pmd((pmd_t *)ptep, __pmd(0));
+		}
+	}
+	return pte;
+}
+
 static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm, unsigned long addr, pte_t *ptep, int full)
 {
 	if (full) {
./arch/x86_64/mm/pageattr-xen.c +2 -0
@@ -62,6 +62,8 @@ static void _pin_lock(struct mm_struct *
 
 					if (pmd_none(*pmd))
 						continue;
+					if (pte_huge(*(pte_t *)pmd))
+						continue;
 					ptl = pte_lockptr(0, pmd);
 					if (lock)
 						spin_lock(ptl);
./mm/hugetlb.c +4 -2
@@ -294,12 +294,14 @@ static pte_t make_huge_pte(struct vm_are
 				int writable)
 {
 	pte_t entry;
+	pgprot_t pgprot;
 
+	pgprot = __pgprot(pgprot_val(vma->vm_page_prot) | _PAGE_PRESENT);
 	if (writable) {
 		entry =
-		    pte_mkwrite(pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
+		    pte_mkwrite(pte_mkdirty(mk_pte(page, pgprot)));
 	} else {
-		entry = pte_wrprotect(mk_pte(page, vma->vm_page_prot));
+		entry = pte_wrprotect(mk_pte(page, pgprot));
 	}
 	entry = pte_mkyoung(entry);
 	entry = pte_mkhuge(entry);

_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel

#2 lore raw

PATCH 1/2 PV Hugetlb support - Hypervisor portion

Quoted 1 line · Dave McCracken

Here is the hypervisor portion of hugetlb support for PV machines.

Oops. Here's really the hypervisor portion. The first one was a copy of the kernel portion.

Dave McCracken
Oracle Corp.

./xen/include/asm-x86/x86_32/page.h +1 -1
@@ -112,7 +112,7 @@ extern unsigned int PAGE_HYPERVISOR_NOCA
  * Disallow unused flag bits plus PAT/PSE, PCD, PWT and GLOBAL.
  * Permit the NX bit if the hardware supports it.
  */
-#define BASE_DISALLOW_MASK (0xFFFFF198U & ~_PAGE_NX)
+#define BASE_DISALLOW_MASK (0xFFFFF118U & ~_PAGE_NX)
 
 #define L1_DISALLOW_MASK (BASE_DISALLOW_MASK | _PAGE_GNTTAB)
 #define L2_DISALLOW_MASK (BASE_DISALLOW_MASK)
./xen/include/asm-x86/x86_64/page.h +1 -1
@@ -109,7 +109,7 @@ typedef l4_pgentry_t root_pgentry_t;
  * Permit the NX bit if the hardware supports it.
  * Note that range [62:52] is available for software use on x86/64.
  */
-#define BASE_DISALLOW_MASK (0xFF800198U & ~_PAGE_NX)
+#define BASE_DISALLOW_MASK (0xFF800118U & ~_PAGE_NX)
 
 #define L1_DISALLOW_MASK (BASE_DISALLOW_MASK | _PAGE_GNTTAB)
 #define L2_DISALLOW_MASK (BASE_DISALLOW_MASK)
./xen/arch/x86/mm.c +4 -0
@@ -755,6 +755,9 @@ get_page_from_l2e(
         MEM_LOG("Bad L2 flags %x", l2e_get_flags(l2e) & L2_DISALLOW_MASK);
         return 0;
     }
+    if ( l2e_get_flags(l2e) & _PAGE_PSE )
+        return 1;
+
 
     rc = get_page_and_type_from_pagenr(l2e_get_pfn(l2e), PGT_l1_page_table, d);
     if ( unlikely(!rc) )
@@ -948,6 +951,7 @@ void put_page_from_l1e(l1_pgentry_t l1e,
 static void put_page_from_l2e(l2_pgentry_t l2e, unsigned long pfn)
 {
     if ( (l2e_get_flags(l2e) & _PAGE_PRESENT) && 
+	 (!(l2e_get_flags(l2e) & _PAGE_PSE)) && 
          (l2e_get_pfn(l2e) != pfn) )
         put_page_and_type(l2e_get_page(l2e));
 }

_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel

#3 lore raw

PATCH 2/2 PV hugetlb support - kernel portion

In reply to Dave McCracken

Here is the patch against the kernel that enables hugetlb support for PV machines.

Dave McCracken
Oracle Corp.

./fs/Kconfig +1 -1
@@ -870,7 +870,7 @@ config TMPFS
 config HUGETLBFS
 	bool "HugeTLB file system support"
 	depends X86 || IA64 || PPC64 || SPARC64 || SUPERH || BROKEN
-	depends on !XEN
+#	depends on !XEN
 	help
 	  hugetlbfs is a filesystem backing for HugeTLB pages, based on
 	  ramfs. For architectures that support it, say Y here and read
./include/asm-x86_64/mach-xen/asm/page.h +2 -0
@@ -62,6 +62,8 @@
 #define HPAGE_MASK	(~(HPAGE_SIZE - 1))
 #define HUGETLB_PAGE_ORDER	(HPAGE_SHIFT - PAGE_SHIFT)
 
+#define ARCH_HAS_SETCLEAR_HUGE_PTE
+
 #ifdef __KERNEL__
 #ifndef __ASSEMBLY__
 
./include/asm-x86_64/mach-xen/asm/pgtable.h +19 -0
@@ -261,6 +261,12 @@ static inline unsigned long pud_bad(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_pmd((pmd_t *)ptep, (pmd_t){__pte_val(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)
@@ -296,6 +302,19 @@ static inline pte_t ptep_get_and_clear(s
 	return pte;
 }
 
+static inline pte_t huge_ptep_get_and_clear(struct mm_struct *mm, unsigned long addr, pte_t *ptep)
+{
+	pte_t pte = *ptep;
+	if (!pte_none(pte)) {
+		if ((mm != &init_mm) ||
+		    HYPERVISOR_update_va_mapping(addr, __pte(0), 0)) {
+			pte = *ptep;
+			set_pmd((pmd_t *)ptep, __pmd(0));
+		}
+	}
+	return pte;
+}
+
 static inline pte_t ptep_get_and_clear_full(struct mm_struct *mm, unsigned long addr, pte_t *ptep, int full)
 {
 	if (full) {
./arch/x86_64/mm/pageattr-xen.c +2 -0
@@ -62,6 +62,8 @@ static void _pin_lock(struct mm_struct *
 
 					if (pmd_none(*pmd))
 						continue;
+					if (pte_huge(*(pte_t *)pmd))
+						continue;
 					ptl = pte_lockptr(0, pmd);
 					if (lock)
 						spin_lock(ptl);
./mm/hugetlb.c +4 -2
@@ -294,12 +294,14 @@ static pte_t make_huge_pte(struct vm_are
 				int writable)
 {
 	pte_t entry;
+	pgprot_t pgprot;
 
+	pgprot = __pgprot(pgprot_val(vma->vm_page_prot) | _PAGE_PRESENT);
 	if (writable) {
 		entry =
-		    pte_mkwrite(pte_mkdirty(mk_pte(page, vma->vm_page_prot)));
+		    pte_mkwrite(pte_mkdirty(mk_pte(page, pgprot)));
 	} else {
-		entry = pte_wrprotect(mk_pte(page, vma->vm_page_prot));
+		entry = pte_wrprotect(mk_pte(page, pgprot));
 	}
 	entry = pte_mkyoung(entry);
 	entry = pte_mkhuge(entry);

_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel

#4 lore raw
In reply to Dave McCracken
Quoted 5 lines
Quoted 1 line
Quoted 1 line

Dave McCracken <[email protected]> 24.07.08 15:45 >>>

Here is a set of small patches that enables hugetlb on PV machines. They are against xen-unstable and linux-2.6.18-xen.

Quoted 7 lines

The patches are specifically for x86_64.

I originally had these patches working back in May, but recently for some reason my machine now refuses to boot the baseline xen-unstable, so I've been unable to verify them. However, they should still work.

Comments, bug reports, and suggestions are welcome.

I must be missing something, but I can't see how you guarantee the super pages to be contiguous in machine memory. And even if you did, the hypervisor would still need to do accounting on all the 4k portions a super page consists of when it gets mapped/unmapped.

Jan

#5 lore raw
Quoted 8 lines · Jan Beulich
Quoted 8 lines
Quoted 2 lines
Quoted 2 lines

Dave McCracken <[email protected]> 24.07.08 15:45 >>>

Here is a set of small patches that enables hugetlb on PV machines. They are against xen-unstable and linux-2.6.18-xen.

The patches are specifically for x86_64.

I originally had these patches working back in May, but recently for some reason my machine now refuses to boot the baseline xen-unstable, so I've been unable to verify them. However, they should still work.

Quoted 8 lines
Quoted 2 lines

Comments, bug reports, and suggestions are welcome.

I must be missing something, but I can't see how you guarantee the super pages to be contiguous in machine memory. And even if you did, the hypervisor would still need to do accounting on all the 4k portions a super page consists of when it gets mapped/unmapped.

Yeah, I'm pretty sure there has to be a lot more to it than that.

J