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
|