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
|