linux/i386: allow CONFIG_HIGHPTE on i386
authorkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Fri, 12 Jan 2007 10:28:54 +0000 (10:28 +0000)
committerkfraser@localhost.localdomain <kfraser@localhost.localdomain>
Fri, 12 Jan 2007 10:28:54 +0000 (10:28 +0000)
While, as discussed, the performance impact of this option is
certainly higher than on native Linux, the option should not be
entirely disallowed if people want to sacrifice performance for less
lowmem pressure.

Signed-off-by: Jan Beulich <jbeulich@novell.com>
linux-2.6-xen-sparse/arch/i386/Kconfig
linux-2.6-xen-sparse/arch/i386/mm/highmem-xen.c
linux-2.6-xen-sparse/arch/i386/mm/pgtable-xen.c
linux-2.6-xen-sparse/include/asm-i386/mach-xen/asm/pgalloc.h

index 8c712269d0dea77ae09ccea94c27c1bd805d9eec..4c0d2f8c80943401d3ddf4abbde597f6af397fc0 100644 (file)
@@ -594,7 +594,7 @@ config HAVE_ARCH_EARLY_PFN_TO_NID
 
 config HIGHPTE
        bool "Allocate 3rd-level pagetables from highmem"
-       depends on (HIGHMEM4G || HIGHMEM64G) && !X86_XEN
+       depends on HIGHMEM4G || HIGHMEM64G
        help
          The VM uses one page table entry for each page of physical memory.
          For systems with a lot of RAM, this can be wasteful of precious
index 23f0e1b2e926fbeb4bd1c7ed7fe62595badcf245..ee7deae2a77611c228ab2f59c68029099588f5c4 100644 (file)
@@ -129,5 +129,6 @@ struct page *kmap_atomic_to_page(void *ptr)
 EXPORT_SYMBOL(kmap);
 EXPORT_SYMBOL(kunmap);
 EXPORT_SYMBOL(kmap_atomic);
+EXPORT_SYMBOL(kmap_atomic_pte);
 EXPORT_SYMBOL(kunmap_atomic);
 EXPORT_SYMBOL(kmap_atomic_to_page);
index 0ff01f52f8d8b76360a169cf63a6c127da909e6f..8f2239b4278445d0cedbc1b5ba31a31dc2ce9c17 100644 (file)
@@ -238,23 +238,41 @@ struct page *pte_alloc_one(struct mm_struct *mm, unsigned long address)
 
 #ifdef CONFIG_HIGHPTE
        pte = alloc_pages(GFP_KERNEL|__GFP_HIGHMEM|__GFP_REPEAT|__GFP_ZERO, 0);
+       if (pte && PageHighMem(pte)) {
+               struct mmuext_op op;
+
+               kmap_flush_unused();
+               op.cmd = MMUEXT_PIN_L1_TABLE;
+               op.arg1.mfn = pfn_to_mfn(page_to_pfn(pte));
+               BUG_ON(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0);
+       }
 #else
        pte = alloc_pages(GFP_KERNEL|__GFP_REPEAT|__GFP_ZERO, 0);
+#endif
        if (pte) {
                SetPageForeign(pte, pte_free);
                set_page_count(pte, 1);
        }
-#endif
        return pte;
 }
 
 void pte_free(struct page *pte)
 {
-       unsigned long va = (unsigned long)__va(page_to_pfn(pte)<<PAGE_SHIFT);
+       unsigned long pfn = page_to_pfn(pte);
 
-       if (!pte_write(*virt_to_ptep(va)))
-               BUG_ON(HYPERVISOR_update_va_mapping(
-                       va, pfn_pte(page_to_pfn(pte), PAGE_KERNEL), 0));
+       if (!PageHighMem(pte)) {
+               unsigned long va = (unsigned long)__va(pfn << PAGE_SHIFT);
+
+               if (!pte_write(*virt_to_ptep(va)))
+                       BUG_ON(HYPERVISOR_update_va_mapping(
+                              va, pfn_pte(pfn, PAGE_KERNEL), 0));
+       } else {
+               struct mmuext_op op;
+
+               op.cmd = MMUEXT_UNPIN_TABLE;
+               op.arg1.mfn = pfn_to_mfn(pfn);
+               BUG_ON(HYPERVISOR_mmuext_op(&op, 1, NULL, DOMID_SELF) < 0);
+       }
 
        ClearPageForeign(pte);
        set_page_count(pte, 1);
index 95f8d9dadba23998143bdab3ed5681bee5979533..39252d1ad86b20ff8d026de910b2e3759832b5d9 100644 (file)
@@ -42,7 +42,7 @@ extern struct page *pte_alloc_one(struct mm_struct *, unsigned long);
 static inline void pte_free_kernel(pte_t *pte)
 {
        free_page((unsigned long)pte);
-       make_page_writable(pte, XENFEAT_writable_page_tables);
+       make_lowmem_page_writable(pte, XENFEAT_writable_page_tables);
 }
 
 extern void pte_free(struct page *pte);