Skip to contentSkip to conversation

Use the shadow-code PT walker from the HAP functions

PATCH New Tim Deegan 1 participant 1 message Nov 13, 2008

lore
Share & tools
lore

Tim Deegan

author
#0 lore raw

PATCH 3/3 Use the shadow-code PT walker from the HAP functions

Replace the guts of the HAP pagetable walker with a call to the newly-commonified walker from the shadow code. This reduces duplication, and gives HAP guests proper access control and A/D-bit setting for memory accesses from the emulator

xen/arch/x86/mm/hap/guest_walk.c +46 -135
diff -r 6008cf2c52f6 xen/arch/x86/mm/hap/guest_walk.c
@@ -19,25 +19,58 @@
  * Place - Suite 330, Boston, MA 02111-1307 USA.
  */
 
+
+#include <xen/domain_page.h>
+#include <xen/paging.h>
 #include <xen/config.h>
-#include <xen/types.h>
-#include <xen/mm.h>
-#include <xen/domain_page.h>
-#include <asm/page.h>
-#include <xen/event.h>
 #include <xen/sched.h>
-#include <asm/hvm/svm/vmcb.h>
-#include <asm/domain.h>
-#include <asm/paging.h>
-#include <asm/p2m.h>
-#include <asm/hap.h>
-
-#include "private.h"
 
 #define _hap_gva_to_gfn(levels) hap_gva_to_gfn_##levels##level
 #define hap_gva_to_gfn(levels) _hap_gva_to_gfn(levels)
 
-#if GUEST_PAGING_LEVELS > CONFIG_PAGING_LEVELS
+#if GUEST_PAGING_LEVELS <= CONFIG_PAGING_LEVELS
+
+#include <asm/guest_pt.h>
+
+unsigned long hap_gva_to_gfn(GUEST_PAGING_LEVELS)(
+    struct vcpu *v, unsigned long gva, uint32_t *pfec)
+{
+    unsigned long cr3;
+    uint32_t missing;
+    mfn_t top_mfn;
+    void *top_map;
+    p2m_type_t p2mt;
+    walk_t gw;
+
+    /* Get the top-level table's MFN */
+    cr3 = v->arch.hvm_vcpu.guest_cr[3];
+    top_mfn = gfn_to_mfn(v->domain, _gfn(cr3 >> PAGE_SHIFT), &p2mt);
+    if ( !p2m_is_ram(p2mt) )
+    {
+        pfec[0] &= ~PFEC_page_present;
+        return INVALID_GFN;
+    }
+
+    /* Map the top-level table and call the tree-walker */
+    ASSERT(mfn_valid(mfn_x(top_mfn)));
+    top_map = map_domain_page(mfn_x(top_mfn));
+#if GUEST_PAGING_LEVELS == 3
+    top_map += (cr3 & ~(PAGE_MASK | 31));
+#endif
+    missing = guest_walk_tables(v, gva, &gw, pfec[0], top_mfn, top_map);
+    unmap_domain_page(top_map);
+
+    /* Interpret the answer */
+    if ( missing == 0 ) 
+        return gfn_x(guest_l1e_get_gfn(gw.l1e));
+    
+    if ( missing & _PAGE_PRESENT )
+        pfec[0] &= ~PFEC_page_present;
+    
+    return INVALID_GFN;
+}
+
+#else
 
 unsigned long hap_gva_to_gfn(GUEST_PAGING_LEVELS)(
     struct vcpu *v, unsigned long gva, uint32_t *pfec)
@@ -48,130 +81,8 @@ unsigned long hap_gva_to_gfn(GUEST_PAGIN
     return INVALID_GFN;
 }
 
-#else
-
-#if GUEST_PAGING_LEVELS == 2
-#include "../page-guest32.h"
-#define l1_pgentry_t l1_pgentry_32_t
-#define l2_pgentry_t l2_pgentry_32_t
-#undef l2e_get_flags
-#define l2e_get_flags(x) l2e_get_flags_32(x)
-#undef l1e_get_flags
-#define l1e_get_flags(x) l1e_get_flags_32(x)
 #endif
 
-unsigned long hap_gva_to_gfn(GUEST_PAGING_LEVELS)(
-    struct vcpu *v, unsigned long gva, uint32_t *pfec)
-{
-    unsigned long gcr3 = v->arch.hvm_vcpu.guest_cr[3];
-    int mode = GUEST_PAGING_LEVELS;
-    int lev, index;
-    paddr_t gpa = 0;
-    unsigned long gpfn, mfn;
-    p2m_type_t p2mt;
-    int success = 1;
-
-    l1_pgentry_t *l1e;
-    l2_pgentry_t *l2e;
-#if GUEST_PAGING_LEVELS >= 3
-    l3_pgentry_t *l3e;
-#endif
-#if GUEST_PAGING_LEVELS >= 4
-    l4_pgentry_t *l4e;
-#endif
-
-    gpfn = (gcr3 >> PAGE_SHIFT);
-    for ( lev = mode; lev >= 1; lev-- )
-    {
-        mfn = mfn_x(gfn_to_mfn(v->domain, gpfn, &p2mt));
-        if ( !p2m_is_ram(p2mt) )
-        {
-            HAP_PRINTK("bad pfn=0x%lx from gva=0x%lx at lev%d\n", gpfn, gva,
-                       lev);
-            success = 0;
-            break;
-        }
-        ASSERT(mfn_valid(mfn));
-
-        index = (gva >> PT_SHIFT[mode][lev]) & (PT_ENTRIES[mode][lev]-1);
-
-#if GUEST_PAGING_LEVELS >= 4
-        if ( lev == 4 )
-        {
-            l4e = map_domain_page(mfn);
-            if ( !(l4e_get_flags(l4e[index]) & _PAGE_PRESENT) )
-            {
-                HAP_PRINTK("Level 4 entry not present at index = %d\n", index);
-                success = 0;
-            }
-            gpfn = l4e_get_pfn(l4e[index]);
-            unmap_domain_page(l4e);
-        }
-#endif
-
-#if GUEST_PAGING_LEVELS >= 3
-        if ( lev == 3 )
-        {
-            l3e = map_domain_page(mfn);
-#if GUEST_PAGING_LEVELS == 3
-            index += ((gcr3 >> 5) & 127) * 4;
-#endif
-            if ( !(l3e_get_flags(l3e[index]) & _PAGE_PRESENT) )
-            {
-                HAP_PRINTK("Level 3 entry not present at index = %d\n", index);
-                success = 0;
-            }
-            gpfn = l3e_get_pfn(l3e[index]);
-            unmap_domain_page(l3e);
-        }
-#endif
-
-        if ( lev == 2 )
-        {
-            l2e = map_domain_page(mfn);
-            if ( !(l2e_get_flags(l2e[index]) & _PAGE_PRESENT) )
-            {
-                HAP_PRINTK("Level 2 entry not present at index = %d\n", index);
-                success = 0;
-            }
-
-            if ( l2e_get_flags(l2e[index]) & _PAGE_PSE )
-            {
-                paddr_t mask = ((paddr_t)1 << PT_SHIFT[mode][2]) - 1;
-                HAP_PRINTK("guest page table is PSE\n");
-                gpa = (l2e_get_intpte(l2e[index]) & ~mask) + (gva & mask);
-                unmap_domain_page(l2e);
-                break; /* last level page table, jump out from here */
-            }
-
-            gpfn = l2e_get_pfn(l2e[index]);
-            unmap_domain_page(l2e);
-        }
-
-        if ( lev == 1 )
-        {
-            l1e = map_domain_page(mfn);
-            if ( !(l1e_get_flags(l1e[index]) & _PAGE_PRESENT) )
-            {
-                HAP_PRINTK("Level 1 entry not present at index = %d\n", index);
-                success = 0;
-            }
-            gpfn = l1e_get_pfn(l1e[index]);
-            gpa = (l1e_get_intpte(l1e[index]) & PAGE_MASK) + (gva &~PAGE_MASK);
-            unmap_domain_page(l1e);
-        }
-
-        if ( success != 1 ) /* error happened, jump out */
-            break;
-    }
-
-    gpa &= PADDR_MASK;
-    HAP_PRINTK("success = %d, gva = %lx, gpa = %lx\n", success, gva, gpa);
-
-    return (!success ? INVALID_GFN : ((paddr_t)gpa >> PAGE_SHIFT));
-}
-
-#endif
 
 /*
  * Local variables:
xen/arch/x86/mm/hap/private.h +0 -34
diff -r 6008cf2c52f6 xen/arch/x86/mm/hap/private.h
@@ -20,9 +20,6 @@
 #ifndef __HAP_PRIVATE_H__
 #define __HAP_PRIVATE_H__
 
-#include <asm/flushtlb.h>
-#include <asm/hvm/support.h>
-
 /********************************************/
 /*          GUEST TRANSLATION FUNCS         */
 /********************************************/
@@ -33,36 +30,5 @@ unsigned long hap_gva_to_gfn_4level(stru
 unsigned long hap_gva_to_gfn_4level(struct vcpu *v, unsigned long gva,
                                     uint32_t *pfec);
 
-/********************************************/
-/*            MISC DEFINITIONS              */
-/********************************************/
-
-/* PT_SHIFT describes the amount by which a virtual address is shifted right 
- * to right justify the portion to be used for indexing into a page 
- * table, given the guest memory model (i.e. number of levels) and the level 
- * of the page table being accessed. The idea is from Virtual Iron's code.
- */
-static const int PT_SHIFT[][5] =
-  {   /*     ------  level ------           nr_levels  */
-    /*         1     2     3     4                   */
-    {    0,    0,    0,    0,    0},   /* 0 not used */
-    {    0,    0,    0,    0,    0},   /* 1 not used */
-    {    0,   12,   22,    0,    0},   /* 2  */
-    {    0,   12,   21,   30,    0},   /* 3  */
-    {    0,   12,   21,   30,   39}    /* 4  */
-  };
-
-/* PT_ENTRIES describes the number of entries in a page table, given the 
- * memory model (i.e. number of levels) and the level of the page table 
- * being considered. This idea from Virtual Iron's shadow code*/
-static const int PT_ENTRIES[][5] =
-  {   /*     ------  level ------           nr_levels  */
-    /*         1     2     3     4                   */
-    {    0,    0,    0,    0,    0},   /* 0 not used */
-    {    0,    0,    0,    0,    0},   /* 1 not used */
-    {    0, 1024, 1024,    0,    0},   /* 2  */
-    {    0,  512,  512,    4,    0},   /* 3  */
-    {    0,  512,  512,  512,  512}    /* 4  */
-  };
 
 #endif /* __SVM_NPT_H__ */
xen/arch/x86/mm/page-guest32.h deleted +0 -100

100 lines not on this page · raw message

_______________________________________________
Xen-devel mailing list
[email protected]
http://lists.xensource.com/xen-devel