WARNING - OLD ARCHIVES

This is an archived copy of the Xen.org mailing list, which we have preserved to ensure that existing links to archives are not broken. The live archive, which contains the latest emails, can be found at http://lists.xen.org/
   
 
 
Xen 
 
Home Products Support Community News
 
   
 

xen-changelog

[Xen-changelog] Linux 2.6 now always uses writable page tables (even SMP

To: xen-changelog@xxxxxxxxxxxxxxxxxxxxx
Subject: [Xen-changelog] Linux 2.6 now always uses writable page tables (even SMP builds). Also
From: BitKeeper Bot <riel@xxxxxxxxxxx>
Date: Fri, 18 Mar 2005 15:14:45 +0000
Delivery-date: Fri, 18 Mar 2005 16:05:41 +0000
Envelope-to: www-data@xxxxxxxxxxxxxxxxxxx
List-archive: <http://sourceforge.net/mailarchive/forum.php?forum=xen-changelog>
List-help: <mailto:xen-changelog-request@lists.sourceforge.net?subject=help>
List-id: <xen-changelog.lists.sourceforge.net>
List-post: <mailto:xen-changelog@lists.sourceforge.net>
List-subscribe: <https://lists.sourceforge.net/lists/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.sourceforge.net?subject=subscribe>
List-unsubscribe: <https://lists.sourceforge.net/lists/listinfo/xen-changelog>, <mailto:xen-changelog-request@lists.sourceforge.net?subject=unsubscribe>
Reply-to: Xen Development List <xen-devel@xxxxxxxxxxxxxxxxxxxxx>
Sender: xen-changelog-admin@xxxxxxxxxxxxxxxxxxxxx
ChangeSet 1.1321, 2005/03/18 15:14:45+00:00, kaf24@xxxxxxxxxxxxxxxxxxxx

        Linux 2.6 now always uses writable page tables (even SMP builds). Also
        use native definitions for atomic read-modify-write operations on
        ptes. Fixed instruction emulator in Xen.
        Signed-off-by: Keir Fraser <keir@xxxxxxxxxxxxx>



 linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/page.h           |   14 ---
 linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/pgtable-2level.h |   34 
--------
 linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/pgtable.h        |   41 
++--------
 tools/tests/test_x86_emulator.c                                   |   15 +++
 xen/arch/x86/mm.c                                                 |   30 
++++---
 xen/arch/x86/x86_emulate.c                                        |   27 +++---
 xen/include/asm-x86/page.h                                        |   21 ++++-
 xen/include/asm-x86/x86_32/page.h                                 |    5 -
 xen/include/asm-x86/x86_64/page.h                                 |    9 +-
 9 files changed, 89 insertions(+), 107 deletions(-)


diff -Nru a/linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/page.h 
b/linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/page.h
--- a/linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/page.h   2005-03-18 
11:03:51 -05:00
+++ b/linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/page.h   2005-03-18 
11:03:51 -05:00
@@ -116,17 +116,11 @@
 }
 #define pgprot_val(x)  ((x).pgprot)
 
-static inline pte_t __pte(unsigned long x)
-{
-       if (x & 1) x = phys_to_machine(x);
-       return ((pte_t) { (x) });
-}
+#define __pte(x) ({ unsigned long _x = (x); \
+    (((_x)&1) ? ((pte_t) {phys_to_machine(_x)}) : ((pte_t) {(_x)})); })
 #define __pte_ma(x)    ((pte_t) { (x) } )
-static inline pgd_t __pgd(unsigned long x)
-{
-       if ((x & 1)) x = phys_to_machine(x);
-       return ((pgd_t) { (x) });
-}
+#define __pgd(x) ({ unsigned long _x = (x); \
+    (((_x)&1) ? ((pgd_t) {phys_to_machine(_x)}) : ((pgd_t) {(_x)})); })
 #define __pgprot(x)    ((pgprot_t) { (x) } )
 
 #endif /* !__ASSEMBLY__ */
diff -Nru a/linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/pgtable-2level.h 
b/linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/pgtable-2level.h
--- a/linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/pgtable-2level.h 
2005-03-18 11:03:51 -05:00
+++ b/linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/pgtable-2level.h 
2005-03-18 11:03:51 -05:00
@@ -13,41 +13,13 @@
  * within a page table are directly modified.  Thus, the following
  * hook is made available.
  */
-#define set_pte_batched(pteptr, pteval) \
-       queue_l1_entry_update(pteptr, (pteval).pte_low)
-
-#ifdef CONFIG_SMP
-#define set_pte(pteptr, pteval) xen_l1_entry_update(pteptr, (pteval).pte_low)
-#if 0
-do { \
-  (*(pteptr) = pteval); \
-  HYPERVISOR_xen_version(0); \
-} while (0)
-#endif
-#define set_pte_atomic(pteptr, pteval) set_pte(pteptr, pteval)
-#else
 #define set_pte(pteptr, pteval) (*(pteptr) = pteval)
 #define set_pte_atomic(pteptr, pteval) set_pte(pteptr,pteval)
-#endif
 #define set_pmd(pmdptr, pmdval) xen_l2_entry_update((pmdptr), (pmdval))
+#define set_pte_batched(pteptr, pteval) \
+       queue_l1_entry_update(pteptr, (pteval).pte_low)
 
-/*
- * A note on implementation of this atomic 'get-and-clear' operation.
- * This is actually very simple because Xen Linux can only run on a single
- * processor. Therefore, we cannot race other processors setting the 'accessed'
- * or 'dirty' bits on a page-table entry.
- * Even if pages are shared between domains, that is not a problem because
- * each domain will have separate page tables, with their own versions of
- * accessed & dirty state.
- */
-static inline pte_t ptep_get_and_clear(pte_t *xp)
-{
-       pte_t pte = *xp;
-       if (pte.pte_low)
-               set_pte(xp, __pte_ma(0));
-       return pte;
-}
-
+#define ptep_get_and_clear(xp) __pte_ma(xchg(&(xp)->pte_low, 0))
 #define pte_same(a, b)         ((a).pte_low == (b).pte_low)
 /*
  * We detect special mappings in one of two ways:
diff -Nru a/linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/pgtable.h 
b/linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/pgtable.h
--- a/linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/pgtable.h        
2005-03-18 11:03:51 -05:00
+++ b/linux-2.6.11-xen-sparse/include/asm-xen/asm-i386/pgtable.h        
2005-03-18 11:03:51 -05:00
@@ -89,9 +89,6 @@
 # define VMALLOC_END   (FIXADDR_START-2*PAGE_SIZE)
 #endif
 
-extern void *high_memory;
-extern unsigned long vmalloc_earlyreserve;
-
 /*
  * The 4MB page is guessing..  Detailed in the infamous "Chapter H"
  * of the Pentium details, but assuming intel did the straightforward
@@ -214,7 +211,7 @@
 /* pmd_present doesn't just test the _PAGE_PRESENT bit since wr.p.t.
    can temporarily clear it. */
 #define pmd_present(x) (pmd_val(x))
-/* pmd_clear below */
+#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))
 
 
@@ -254,34 +251,20 @@
 
 static inline int ptep_test_and_clear_dirty(pte_t *ptep)
 {
-       pte_t pte = *ptep;
-       int ret = pte_dirty(pte);
-       if (ret)
-               xen_l1_entry_update(ptep, pte_mkclean(pte).pte_low);
-       return ret;
+       if (!pte_dirty(*ptep))
+               return 0;
+       return test_and_clear_bit(_PAGE_BIT_DIRTY, &ptep->pte_low);
 }
 
 static inline int ptep_test_and_clear_young(pte_t *ptep)
 {
-       pte_t pte = *ptep;
-       int ret = pte_young(pte);
-       if (ret)
-               xen_l1_entry_update(ptep, pte_mkold(pte).pte_low);
-       return ret;
+       if (!pte_young(*ptep))
+               return 0;
+       return test_and_clear_bit(_PAGE_BIT_ACCESSED, &ptep->pte_low);
 }
 
-static inline void ptep_set_wrprotect(pte_t *ptep)
-{
-       pte_t pte = *ptep;
-       if (pte_write(pte))
-               set_pte(ptep, pte_wrprotect(pte));
-}
-static inline void ptep_mkdirty(pte_t *ptep)
-{
-       pte_t pte = *ptep;
-       if (!pte_dirty(pte))
-               xen_l1_entry_update(ptep, pte_mkdirty(pte).pte_low);
-}
+static inline void ptep_set_wrprotect(pte_t *ptep)             { 
clear_bit(_PAGE_BIT_RW, &ptep->pte_low); }
+static inline void ptep_mkdirty(pte_t *ptep)                   { 
set_bit(_PAGE_BIT_DIRTY, &ptep->pte_low); }
 
 /*
  * Macro to mark a page protection value as "uncacheable".  On processors 
which do not support
@@ -316,11 +299,6 @@
 
 #define page_pte(page) page_pte_prot(page, __pgprot(0))
 
-#define pmd_clear(xp)  do {                                    \
-       set_pmd(xp, __pmd(0));                                  \
-       xen_flush_page_update_queue();                          \
-} while (0)
-
 #define pmd_large(pmd) \
 ((pmd_val(pmd) & (_PAGE_PSE|_PAGE_PRESENT)) == (_PAGE_PSE|_PAGE_PRESENT))
 
@@ -416,7 +394,6 @@
  */
 #define update_mmu_cache(vma,address,pte) do { } while (0)
 #define  __HAVE_ARCH_PTEP_SET_ACCESS_FLAGS
-
 #define ptep_set_access_flags(__vma, __address, __ptep, __entry, __dirty) \
        do {                                                              \
                if (__dirty) {                                            \
diff -Nru a/tools/tests/test_x86_emulator.c b/tools/tests/test_x86_emulator.c
--- a/tools/tests/test_x86_emulator.c   2005-03-18 11:03:51 -05:00
+++ b/tools/tests/test_x86_emulator.c   2005-03-18 11:03:51 -05:00
@@ -158,6 +158,21 @@
         goto fail;
     printf("okay\n");
 
+    printf("%-40s", "Testing btrl $0x1,(%edi)...");
+    instr[0] = 0x0f; instr[1] = 0xba; instr[2] = 0x37; instr[3] = 0x01;
+    res         = 0x2233445F;
+    regs.eflags = 0x200;
+    regs.eip    = (unsigned long)&instr[0];
+    regs.edi    = (unsigned long)&res;
+    cr2         = regs.edi;
+    rc = x86_emulate_memop(&regs, cr2, &emulops, 4);    
+    if ( (rc != 0) || 
+         (res != 0x2233445D) ||
+         ((regs.eflags&0x201) != 0x201) ||
+         (regs.eip != (unsigned long)&instr[4]) )
+        goto fail;
+    printf("okay\n");
+
     return 0;
 
  fail:
diff -Nru a/xen/arch/x86/mm.c b/xen/arch/x86/mm.c
--- a/xen/arch/x86/mm.c 2005-03-18 11:03:51 -05:00
+++ b/xen/arch/x86/mm.c 2005-03-18 11:03:51 -05:00
@@ -2560,18 +2560,15 @@
 /* Write page fault handler: check if guest is trying to modify a PTE. */
 int ptwr_do_page_fault(unsigned long addr)
 {
-    unsigned long    pte, pfn, l2e;
-    struct pfn_info *page;
-    l2_pgentry_t    *pl2e;
-    int              which, cpu = smp_processor_id();
-    u32              l2_idx;
-
-#ifdef __x86_64__
-    return 0; /* Writable pagetables need fixing for x86_64. */
-#endif
+    unsigned long       pte, pfn, l2e;
+    struct pfn_info    *page;
+    l2_pgentry_t       *pl2e;
+    int                 which, cpu = smp_processor_id();
+    u32                 l2_idx;
+    struct exec_domain *ed = current;
 
     /* Can't use linear_l2_table with external tables. */
-    BUG_ON(shadow_mode_external(current->domain));
+    BUG_ON(shadow_mode_external(ed->domain));
 
     /*
      * Attempt to read the PTE that maps the VA being accessed. By checking for
@@ -2595,6 +2592,15 @@
         return 0;
     }
 
+    /* x86/64: Writable pagetable code needs auditing. Use emulator for now. */
+#if defined(__x86_64__)
+    goto emulate;
+#endif
+
+    /* Writable pagetables are not yet SMP safe. Use emulator for now. */
+    if ( (ed->eid != 0) || (ed->ed_next_list != NULL) )
+        goto emulate;
+
     /* Get the L2 index at which this L1 p.t. is always mapped. */
     l2_idx = page->u.inuse.type_info & PGT_va_mask;
     if ( unlikely(l2_idx >= PGT_va_unknown) )
@@ -2640,7 +2646,7 @@
      * If last batch made no updates then we are probably stuck. Emulate this 
      * update to ensure we make progress.
      */
-    if ( (ptwr_info[cpu].ptinfo[which].prev_exec_domain == current) &&
+    if ( (ptwr_info[cpu].ptinfo[which].prev_exec_domain == ed) &&
          (ptwr_info[cpu].ptinfo[which].prev_nr_updates  == 0) )
     {
         /* Force non-emul next time, or we can get stuck emulating forever. */
@@ -2653,7 +2659,7 @@
     
     /* For safety, disconnect the L1 p.t. page from current space. */
     if ( (which == PTWR_PT_ACTIVE) && 
-         likely(!shadow_mode_enabled(current->domain)) )
+         likely(!shadow_mode_enabled(ed->domain)) )
     {
         *pl2e = mk_l2_pgentry(l2e & ~_PAGE_PRESENT);
         flush_tlb(); /* XXX Multi-CPU guests? */
diff -Nru a/xen/arch/x86/x86_emulate.c b/xen/arch/x86/x86_emulate.c
--- a/xen/arch/x86/x86_emulate.c        2005-03-18 11:03:51 -05:00
+++ b/xen/arch/x86/x86_emulate.c        2005-03-18 11:03:51 -05:00
@@ -18,12 +18,14 @@


-------------------------------------------------------
SF email is sponsored by - The IT Product Guide
Read honest & candid reviews on hundreds of IT Products from real users.
Discover which products truly live up to the hype. Start reading now.
http://ads.osdn.com/?ad_id=6595&alloc_id=14396&op=click
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxxxx
https://lists.sourceforge.net/lists/listinfo/xen-changelog

<Prev in Thread] Current Thread [Next in Thread>
  • [Xen-changelog] Linux 2.6 now always uses writable page tables (even SMP builds). Also, BitKeeper Bot <=