Use the shadow-code PT walker from the HAP functions
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
Signed-off-by Tim Deegan <[email protected]>
xen/arch/x86/mm/hap/guest_walk.c +46 -135
@@ -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
@@ -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(struunsigned 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