# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1226581396 0
# Node ID 48879ca5884866c38b99a984ddf2854dfc6f9ff0
# Parent 7fb33d15dc9bc5892e4708011beded66dd756be3
x86: 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
Signed-off-by: Tim Deegan <Tim.Deegan@xxxxxxxxxx>
---
xen/arch/x86/mm/page-guest32.h | 100 ---------------------
xen/arch/x86/mm/hap/guest_walk.c | 181 +++++++++------------------------------
xen/arch/x86/mm/hap/private.h | 34 -------
3 files changed, 46 insertions(+), 269 deletions(-)
diff -r 7fb33d15dc9b -r 48879ca58848 xen/arch/x86/mm/hap/guest_walk.c
--- a/xen/arch/x86/mm/hap/guest_walk.c Thu Nov 13 13:02:08 2008 +0000
+++ b/xen/arch/x86/mm/hap/guest_walk.c Thu Nov 13 13:03:16 2008 +0000
@@ -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:
diff -r 7fb33d15dc9b -r 48879ca58848 xen/arch/x86/mm/hap/private.h
--- a/xen/arch/x86/mm/hap/private.h Thu Nov 13 13:02:08 2008 +0000
+++ b/xen/arch/x86/mm/hap/private.h Thu Nov 13 13:03:16 2008 +0000
@@ -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__ */
diff -r 7fb33d15dc9b -r 48879ca58848 xen/arch/x86/mm/page-guest32.h
--- a/xen/arch/x86/mm/page-guest32.h Thu Nov 13 13:02:08 2008 +0000
+++ /dev/null Thu Jan 01 00:00:00 1970 +0000
@@ -1,100 +0,0 @@
-
-#ifndef __X86_PAGE_GUEST_H__
-#define __X86_PAGE_GUEST_H__
-
-#ifndef __ASSEMBLY__
-# include <asm/types.h>
-#endif
-
-#define PAGETABLE_ORDER_32 10
-#define L1_PAGETABLE_ENTRIES_32 (1<<PAGETABLE_ORDER_32)
-#define L2_PAGETABLE_ENTRIES_32 (1<<PAGETABLE_ORDER_32)
-#define ROOT_PAGETABLE_ENTRIES_32 L2_PAGETABLE_ENTRIES_32
-
-
-#define L1_PAGETABLE_SHIFT_32 12
-#define L2_PAGETABLE_SHIFT_32 22
-
-/* Extract flags into 12-bit integer, or turn 12-bit flags into a pte mask. */
-
-#ifndef __ASSEMBLY__
-
-typedef u32 intpte_32_t;
-
-typedef struct { intpte_32_t l1; } l1_pgentry_32_t;
-typedef struct { intpte_32_t l2; } l2_pgentry_32_t;
-typedef l2_pgentry_t root_pgentry_32_t;
-#endif
-
-#define get_pte_flags_32(x) ((u32)(x) & 0xFFF)
-#define put_pte_flags_32(x) ((intpte_32_t)(x))
-
-/* Get pte access flags (unsigned int). */
-#define l1e_get_flags_32(x) (get_pte_flags_32((x).l1))
-#define l2e_get_flags_32(x) (get_pte_flags_32((x).l2))
-
-#define l1e_get_paddr_32(x) \
- ((paddr_t)(((x).l1 & (PADDR_MASK&PAGE_MASK))))
-#define l2e_get_paddr_32(x) \
- ((paddr_t)(((x).l2 & (PADDR_MASK&PAGE_MASK))))
-
-/* Construct an empty pte. */
-#define l1e_empty_32() ((l1_pgentry_32_t) { 0 })
-#define l2e_empty_32() ((l2_pgentry_32_t) { 0 })
-
-/* Construct a pte from a pfn and access flags. */
-#define l1e_from_pfn_32(pfn, flags) \
- ((l1_pgentry_32_t) { ((intpte_32_t)(pfn) << PAGE_SHIFT) |
put_pte_flags_32(flags) })
-#define l2e_from_pfn_32(pfn, flags) \
- ((l2_pgentry_32_t) { ((intpte_32_t)(pfn) << PAGE_SHIFT) |
put_pte_flags_32(flags) })
-
-/* Construct a pte from a physical address and access flags. */
-#ifndef __ASSEMBLY__
-static inline l1_pgentry_32_t l1e_from_paddr_32(paddr_t pa, unsigned int flags)
-{
- ASSERT((pa & ~(PADDR_MASK & PAGE_MASK)) == 0);
- return (l1_pgentry_32_t) { pa | put_pte_flags_32(flags) };
-}
-static inline l2_pgentry_32_t l2e_from_paddr_32(paddr_t pa, unsigned int flags)
-{
- ASSERT((pa & ~(PADDR_MASK & PAGE_MASK)) == 0);
- return (l2_pgentry_32_t) { pa | put_pte_flags_32(flags) };
-}
-#endif /* !__ASSEMBLY__ */
-
-
-/* Construct a pte from a page pointer and access flags. */
-#define l1e_from_page_32(page, flags)
(l1e_from_pfn_32(page_to_mfn(page),(flags)))
-#define l2e_from_page_32(page, flags)
(l2e_from_pfn_32(page_to_mfn(page),(flags)))
-
-/* Add extra flags to an existing pte. */
-#define l1e_add_flags_32(x, flags) ((x).l1 |= put_pte_flags_32(flags))
-#define l2e_add_flags_32(x, flags) ((x).l2 |= put_pte_flags_32(flags))
-
-/* Remove flags from an existing pte. */
-#define l1e_remove_flags_32(x, flags) ((x).l1 &= ~put_pte_flags_32(flags))
-#define l2e_remove_flags_32(x, flags) ((x).l2 &= ~put_pte_flags_32(flags))
-
-/* Check if a pte's page mapping or significant access flags have changed. */
-#define l1e_has_changed_32(x,y,flags) \
- ( !!(((x).l1 ^ (y).l1) & ((PADDR_MASK&PAGE_MASK)|put_pte_flags_32(flags)))
)
-#define l2e_has_changed_32(x,y,flags) \
- ( !!(((x).l2 ^ (y).l2) & ((PADDR_MASK&PAGE_MASK)|put_pte_flags_32(flags)))
)
-
-/* Given a virtual address, get an entry offset into a page table. */
-#define l1_table_offset_32(a) \
- (((a) >> L1_PAGETABLE_SHIFT_32) & (L1_PAGETABLE_ENTRIES_32 - 1))
-#define l2_table_offset_32(a) \
- (((a) >> L2_PAGETABLE_SHIFT_32) & (L2_PAGETABLE_ENTRIES_32 - 1))
-
-#endif /* __X86_PAGE_GUEST_H__ */
-
-/*
- * Local variables:
- * mode: C
- * c-set-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|