[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] x86: Use the shadow-code PT walker from the HAP functions
# 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
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |