[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] CONFIG_XEN_COMPAT_030002 broken?
Jan Beulich wrote: > not nice for use in (early) feature detection. Maybe it'd be better to try > and write > a page table entry without PAGE_USER, and check whether that bit got turned > on implicitly... Patch attached, seems to work ok, survived quick test with ttylinux on both 3.0.3 and 3.0.2 without crashing and detected both versions correctly. 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 | 4 linux-2.6-xen-sparse/arch/x86_64/mm/init-xen.c | 52 +++++++++- linux-2.6-xen-sparse/include/asm-x86_64/mach-xen/asm/pgtable.h | 26 +++-- 3 files changed, 73 insertions(+), 9 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,10 @@ 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__) && defined(CONFIG_XEN_COMPAT_030002) + if (kernel_pages_need_user_flag) + flags |= _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,12 @@ struct dma_mapping_ops* dma_ops; EXPORT_SYMBOL(dma_ops); +#ifdef CONFIG_XEN_COMPAT_030002 +int kernel_pages_need_user_flag = 1; +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 +513,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_pages_need_user_flag = 0; + kernel_page_user = 0; + return; + } + printk("%s: xen 3.0.2 detected\n", __FUNCTION__); + + /* 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 +572,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,16 @@ 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 int kernel_pages_need_user_flag; +extern unsigned long kernel_page_user; +#else +#define kernel_pages_need_user_flag 0 +#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,22 +226,24 @@ 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 \ (_PAGE_PRESENT | _PAGE_USER | _PAGE_ACCESSED | _PAGE_PCD) #define __PAGE_KERNEL_LARGE \ - (__PAGE_KERNEL | _PAGE_PSE) + (__PAGE_KERNEL | _PAGE_PSE | kernel_page_user ) #define __PAGE_KERNEL_LARGE_EXEC \ - (__PAGE_KERNEL_EXEC | _PAGE_PSE) + (__PAGE_KERNEL_EXEC | _PAGE_PSE | kernel_page_user ) + /* * We don't support GLOBAL page in xenolinux64 @@ -422,7 +432,7 @@ 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) -#define pmd_bad(x) ((pmd_val(x) & (~PAGE_MASK & ~_PAGE_USER & ~_PAGE_PRESENT)) != (_KERNPG_TABLE & ~_PAGE_PRESENT)) +#define pmd_bad(x) ((pmd_val(x) & (~PAGE_MASK & ~_PAGE_USER & ~_PAGE_PRESENT)) != (_KERNPG_TABLE & ~_PAGE_USER & ~_PAGE_PRESENT)) #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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |