[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] CONFIG_XEN_COMPAT_030002 broken?



Gerd Hoffmann wrote:
>> So far we have maintained the COMPAT code to be easily entirely strippable.
>> So the change to pmd_bad() should either use kernel_page_user rather than
>> _PAGE_USER, or its definition should be conditional on the COMPAT flag.
> 
> Both ways should have the same effect as kernel_page_user is defined to
> 0 for the non-compat case.

Well, thinko in there, wasn't that simple.  Went with the #ifdef, new
version attached.

cheers,
  Gerd

-- 
Gerd Hoffmann <kraxel@xxxxxxx>
http://www.suse.de/~kraxel/julika-dora.jpeg
---
 linux-2.6-xen-sparse/arch/i386/mm/ioremap-xen.c                |    3 
 linux-2.6-xen-sparse/arch/x86_64/mm/init-xen.c                 |   51 
+++++++++-
 linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/pgtable.h |   22 +++-
 3 files changed, 70 insertions(+), 6 deletions(-)

Index: build-64-testing-11774/linux-2.6-xen-sparse/arch/i386/mm/ioremap-xen.c
===================================================================
--- build-64-testing-11774.orig/linux-2.6-xen-sparse/arch/i386/mm/ioremap-xen.c
+++ build-64-testing-11774/linux-2.6-xen-sparse/arch/i386/mm/ioremap-xen.c
@@ -250,6 +250,9 @@ void __iomem * __ioremap(unsigned long p
        area->phys_addr = phys_addr;
        addr = (void __iomem *) area->addr;
        flags |= _PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED;
+#if defined(__x86_64__)
+       flags |= kernel_page_user;
+#endif
        if (__direct_remap_pfn_range(&init_mm, (unsigned long)addr,
                                     phys_addr>>PAGE_SHIFT,
                                     size, __pgprot(flags), domid)) {
Index: build-64-testing-11774/linux-2.6-xen-sparse/arch/x86_64/mm/init-xen.c
===================================================================
--- build-64-testing-11774.orig/linux-2.6-xen-sparse/arch/x86_64/mm/init-xen.c
+++ build-64-testing-11774/linux-2.6-xen-sparse/arch/x86_64/mm/init-xen.c
@@ -56,6 +56,11 @@
 struct dma_mapping_ops* dma_ops;
 EXPORT_SYMBOL(dma_ops);
 
+#ifdef CONFIG_XEN_COMPAT_030002
+unsigned long kernel_page_user = _PAGE_USER;
+EXPORT_SYMBOL(kernel_page_user);
+#endif
+
 extern unsigned long *contiguous_bitmap;
 
 static unsigned long dma_reserve __initdata;
@@ -507,7 +512,49 @@ static void __meminit phys_pud_init(pud_
                spin_unlock(&init_mm.page_table_lock);
        }
        __flush_tlb();
-} 
+}
+
+#ifdef CONFIG_XEN_COMPAT_030002
+/*
+ * should we set _PAGE_USER for kernel pages?
+ *   - must be set when running on xen 3.0.2
+ *   - should not be set on xen 3.0.3 (kills tlb flush optimization).
+ */
+static void __init check_page_user_flag(unsigned long *pmd)
+{
+       unsigned long addr, *pte;
+        mmu_update_t u;
+
+       addr = pmd[pmd_index(__START_KERNEL_map)];
+       addr_to_page(addr, pte);
+
+       /* try to clear _PAGE_USER */
+        u.ptr = virt_to_machine(pte);
+        u.val = pte[0] & ~_PAGE_USER;
+       if (HYPERVISOR_mmu_update(&u, 1, NULL, DOMID_SELF) < 0) {
+               printk("%s: clear _PAGE_USER: mmu_update failed\n", 
__FUNCTION__);
+               return;
+       }
+
+       if (pte[0] & _PAGE_USER) {
+               /* xen 3.0.3 automagically sets _PAGE_USER */
+               printk("%s: xen 3.0.3+ detected\n", __FUNCTION__);
+               kernel_page_user = 0;
+               return;
+       }
+       printk("%s: xen 3.0.2 detected\n", __FUNCTION__);
+       kernel_page_user = _PAGE_USER;
+
+       /* restore previous state */
+       u.ptr = virt_to_machine(pte);
+       u.val = pte[0] | _PAGE_USER;
+       if (HYPERVISOR_mmu_update(&u, 1, NULL, DOMID_SELF) < 0) {
+               printk("%s: set _PAGE_USER: mmu_update failed\n", __FUNCTION__);
+       }
+}
+#else
+static void __init check_page_user_flag(unsigned long *pmd) {}
+#endif
 
 void __init xen_init_pt(void)
 {
@@ -524,6 +571,8 @@ void __init xen_init_pt(void)
        addr = page[pud_index(__START_KERNEL_map)];
        addr_to_page(addr, page);
 
+       check_page_user_flag(page);
+
        /* Construct mapping of initial pte page in our own directories. */
        init_level4_pgt[pgd_index(__START_KERNEL_map)] = 
                mk_kernel_pgd(__pa_symbol(level3_kernel_pgt));
Index: 
build-64-testing-11774/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/pgtable.h
===================================================================
--- 
build-64-testing-11774.orig/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/pgtable.h
+++ 
build-64-testing-11774/linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/pgtable.h
@@ -205,8 +205,14 @@ static inline pte_t ptep_get_and_clear_f
 #define _PAGE_PROTNONE 0x080   /* If not present */
 #define _PAGE_NX        (1UL<<_PAGE_BIT_NX)
 
+#ifdef CONFIG_XEN_COMPAT_030002
+extern unsigned long kernel_page_user;
+#else
+#define kernel_page_user 0
+#endif
+
 #define _PAGE_TABLE    (_PAGE_PRESENT | _PAGE_RW | _PAGE_USER | _PAGE_ACCESSED 
| _PAGE_DIRTY)
-#define _KERNPG_TABLE  (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | 
_PAGE_DIRTY)
+#define _KERNPG_TABLE  (_PAGE_PRESENT | _PAGE_RW | _PAGE_ACCESSED | 
_PAGE_DIRTY | kernel_page_user)
 
 #define _PAGE_CHG_MASK (PTE_MASK | _PAGE_ACCESSED | _PAGE_DIRTY)
 
@@ -218,14 +224,15 @@ static inline pte_t ptep_get_and_clear_f
 #define PAGE_COPY_EXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
 #define PAGE_READONLY  __pgprot(_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | 
_PAGE_NX)
 #define PAGE_READONLY_EXEC __pgprot(_PAGE_PRESENT | _PAGE_USER | 
_PAGE_ACCESSED)
+
 #define __PAGE_KERNEL \
-       (_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_NX)
+       (_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_NX | 
kernel_page_user )
 #define __PAGE_KERNEL_EXEC \
-       (_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED)
+       (_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_ACCESSED | 
kernel_page_user )
 #define __PAGE_KERNEL_NOCACHE \
-       (_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_PCD | _PAGE_ACCESSED | 
_PAGE_NX)
+       (_PAGE_PRESENT | _PAGE_RW | _PAGE_DIRTY | _PAGE_PCD | _PAGE_ACCESSED | 
_PAGE_NX | kernel_page_user )
 #define __PAGE_KERNEL_RO \
-       (_PAGE_PRESENT | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_NX)
+       (_PAGE_PRESENT | _PAGE_DIRTY | _PAGE_ACCESSED | _PAGE_NX | 
kernel_page_user )
 #define __PAGE_KERNEL_VSYSCALL \
        (_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED)
 #define __PAGE_KERNEL_VSYSCALL_NOCACHE \
@@ -235,6 +242,7 @@ static inline pte_t ptep_get_and_clear_f
 #define __PAGE_KERNEL_LARGE_EXEC \
        (__PAGE_KERNEL_EXEC | _PAGE_PSE)
 
+
 /*
  * We don't support GLOBAL page in xenolinux64
  */
@@ -422,7 +430,11 @@ static inline pud_t *pud_offset_k(pgd_t 
    can temporarily clear it. */
 #define pmd_present(x) (pmd_val(x))
 #define pmd_clear(xp)  do { set_pmd(xp, __pmd(0)); } while (0)
+#ifdef CONFIG_XEN_COMPAT_030002
+#define        pmd_bad(x)      ((pmd_val(x) & (~PAGE_MASK & ~_PAGE_USER & 
~_PAGE_PRESENT)) != (_KERNPG_TABLE & ~_PAGE_USER & ~_PAGE_PRESENT))
+#else
 #define        pmd_bad(x)      ((pmd_val(x) & (~PAGE_MASK & ~_PAGE_USER & 
~_PAGE_PRESENT)) != (_KERNPG_TABLE & ~_PAGE_PRESENT))
+#endif
 #define pfn_pmd(nr,prot) (__pmd(((nr) << PAGE_SHIFT) | pgprot_val(prot)))
 #define pmd_pfn(x)  ((pmd_val(x) & __PHYSICAL_MASK) >> PAGE_SHIFT)
 
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.