All of lore.kernel.org
 help / color / mirror / Atom feed
From: Gerd Hoffmann <kraxel@suse.de>
To: Jan Beulich <jbeulich@novell.com>
Cc: Xen devel list <xen-devel@lists.xensource.com>,
	Keir Fraser <keir@xensource.com>
Subject: Re: CONFIG_XEN_COMPAT_030002 broken?
Date: Tue, 14 Nov 2006 16:11:29 +0100	[thread overview]
Message-ID: <4559DCA1.6030102@suse.de> (raw)
In-Reply-To: <4559C55D.76E4.0078.0@novell.com>

[-- Attachment #1: Type: text/plain, Size: 447 bytes --]

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@suse.de>
http://www.suse.de/~kraxel/julika-dora.jpeg

[-- Attachment #2: user-page-fixup.diff --]
[-- Type: text/x-patch, Size: 6577 bytes --]

---
 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)
 

[-- Attachment #3: Type: text/plain, Size: 138 bytes --]

_______________________________________________
Xen-devel mailing list
Xen-devel@lists.xensource.com
http://lists.xensource.com/xen-devel

  parent reply	other threads:[~2006-11-14 15:11 UTC|newest]

Thread overview: 22+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2006-11-13 10:43 CONFIG_XEN_COMPAT_030002 broken? Gerd Hoffmann
2006-11-13 16:09 ` Gerd Hoffmann
2006-11-13 16:40   ` Keir Fraser
2006-11-13 16:47     ` Gerd Hoffmann
2006-11-13 16:56       ` Keir Fraser
2006-11-13 17:08         ` Gerd Hoffmann
2006-11-13 17:12           ` Keir Fraser
2006-11-14 11:14             ` Jan Beulich
2006-11-14 11:50               ` Keir Fraser
2006-11-14 12:32                 ` Jan Beulich
2006-11-14 12:42                   ` Keir Fraser
2006-11-14 13:02                     ` Jan Beulich
2006-11-14 13:12                       ` Keir Fraser
2006-11-14 15:11                   ` Gerd Hoffmann [this message]
2006-11-14 15:25                     ` Keir Fraser
2006-11-14 15:35                       ` Gerd Hoffmann
2006-11-14 16:06                         ` Gerd Hoffmann
2006-11-14 17:01                           ` Keir Fraser
2006-11-15 10:02                             ` Gerd Hoffmann
2006-11-15 10:10                               ` Keir Fraser
2006-11-14 15:43                       ` Jan Beulich
2006-11-14 15:40                     ` Jan Beulich

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=4559DCA1.6030102@suse.de \
    --to=kraxel@suse.de \
    --cc=jbeulich@novell.com \
    --cc=keir@xensource.com \
    --cc=xen-devel@lists.xensource.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.