[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v1] x86/mm: Suppresses vm_events caused by page-walks
The original version of the patch emulated the current instruction (which, as a side-effect, emulated the page-walk as well), however we need finer-grained control. We want to emulate the page-walk, but still get an EPT violation event if the current instruction would trigger one. This patch performs just the page-walk emulation. Signed-off-by: Alexandru Isaila <aisaila@xxxxxxxxxxxxxxx> --- xen/arch/x86/mm/guest_walk.c | 7 ++++++- xen/arch/x86/mm/hap/guest_walk.c | 32 +++++++++++++++++++++++++++++++- xen/arch/x86/mm/hap/hap.c | 12 ++++++++---- xen/arch/x86/mm/hap/private.h | 10 ++++++++++ xen/arch/x86/mm/mem_access.c | 15 ++++++++++++++- xen/arch/x86/mm/shadow/multi.c | 6 +++--- xen/include/asm-x86/guest_pt.h | 3 ++- xen/include/asm-x86/paging.h | 5 ++++- 8 files changed, 78 insertions(+), 12 deletions(-) diff --git a/xen/arch/x86/mm/guest_walk.c b/xen/arch/x86/mm/guest_walk.c index f67aeda..54140b9 100644 --- a/xen/arch/x86/mm/guest_walk.c +++ b/xen/arch/x86/mm/guest_walk.c @@ -82,7 +82,7 @@ static bool set_ad_bits(guest_intpte_t *guest_p, guest_intpte_t *walk_p, bool guest_walk_tables(struct vcpu *v, struct p2m_domain *p2m, unsigned long va, walk_t *gw, - uint32_t walk, mfn_t top_mfn, void *top_map) + uint32_t walk, mfn_t top_mfn, void *top_map, uint32_t *gf) { struct domain *d = v->domain; p2m_type_t p2mt; @@ -361,6 +361,11 @@ guest_walk_tables(struct vcpu *v, struct p2m_domain *p2m, * see whether the access should succeed. */ ar = (ar_and & AR_ACCUM_AND) | (ar_or & AR_ACCUM_OR); + if ( gf ) + { + *gf = ar; + goto out; + } /* * Sanity check. If EFER.NX is disabled, _PAGE_NX_BIT is reserved and diff --git a/xen/arch/x86/mm/hap/guest_walk.c b/xen/arch/x86/mm/hap/guest_walk.c index cb3f9ce..c916b67 100644 --- a/xen/arch/x86/mm/hap/guest_walk.c +++ b/xen/arch/x86/mm/hap/guest_walk.c @@ -29,6 +29,9 @@ asm(".file \"" __OBJECT_FILE__ "\""); #define _hap_gva_to_gfn(levels) hap_gva_to_gfn_##levels##_levels #define hap_gva_to_gfn(levels) _hap_gva_to_gfn(levels) +#define _hap_pte_flags(levels) hap_pte_flags_##levels##_levels +#define hap_pte_flags(levels) _hap_pte_flags(levels) + #define _hap_p2m_ga_to_gfn(levels) hap_p2m_ga_to_gfn_##levels##_levels #define hap_p2m_ga_to_gfn(levels) _hap_p2m_ga_to_gfn(levels) @@ -39,6 +42,33 @@ asm(".file \"" __OBJECT_FILE__ "\""); #include <asm/guest_pt.h> #include <asm/p2m.h> +bool hap_pte_flags(GUEST_PAGING_LEVELS)( + struct vcpu *v, struct p2m_domain *p2m, + unsigned long va, uint32_t walk, unsigned long cr3, + uint32_t *gf) +{ + walk_t gw; + mfn_t top_mfn; + void *top_map; + gfn_t top_gfn; + struct page_info *top_page; + p2m_type_t p2mt; + + top_gfn = _gfn(cr3 >> PAGE_SHIFT); + top_page = p2m_get_page_from_gfn(p2m, top_gfn, &p2mt, NULL, + P2M_ALLOC | P2M_UNSHARE); + top_mfn = page_to_mfn(top_page); + + /* Map the top-level table and call the tree-walker */ + ASSERT(mfn_valid(top_mfn)); + top_map = map_domain_page(top_mfn); +#if GUEST_PAGING_LEVELS == 3 + top_map += (cr3 & ~(PAGE_MASK | 31)); +#endif + + return guest_walk_tables(v, p2m, va, &gw, walk, top_mfn, top_map, gf); +} + unsigned long hap_gva_to_gfn(GUEST_PAGING_LEVELS)( struct vcpu *v, struct p2m_domain *p2m, unsigned long gva, uint32_t *pfec) { @@ -91,7 +121,7 @@ unsigned long hap_p2m_ga_to_gfn(GUEST_PAGING_LEVELS)( #if GUEST_PAGING_LEVELS == 3 top_map += (cr3 & ~(PAGE_MASK | 31)); #endif - walk_ok = guest_walk_tables(v, p2m, ga, &gw, *pfec, top_mfn, top_map); + walk_ok = guest_walk_tables(v, p2m, ga, &gw, *pfec, top_mfn, top_map, NULL); unmap_domain_page(top_map); put_page(top_page); diff --git a/xen/arch/x86/mm/hap/hap.c b/xen/arch/x86/mm/hap/hap.c index 812a840..2da7b63 100644 --- a/xen/arch/x86/mm/hap/hap.c +++ b/xen/arch/x86/mm/hap/hap.c @@ -767,7 +767,8 @@ static const struct paging_mode hap_paging_real_mode = { .update_cr3 = hap_update_cr3, .update_paging_modes = hap_update_paging_modes, .write_p2m_entry = hap_write_p2m_entry, - .guest_levels = 1 + .guest_levels = 1, + .pte_flags = hap_pte_flags_2_levels }; static const struct paging_mode hap_paging_protected_mode = { @@ -778,7 +779,8 @@ static const struct paging_mode hap_paging_protected_mode = { .update_cr3 = hap_update_cr3, .update_paging_modes = hap_update_paging_modes, .write_p2m_entry = hap_write_p2m_entry, - .guest_levels = 2 + .guest_levels = 2, + .pte_flags = hap_pte_flags_2_levels }; static const struct paging_mode hap_paging_pae_mode = { @@ -789,7 +791,8 @@ static const struct paging_mode hap_paging_pae_mode = { .update_cr3 = hap_update_cr3, .update_paging_modes = hap_update_paging_modes, .write_p2m_entry = hap_write_p2m_entry, - .guest_levels = 3 + .guest_levels = 3, + .pte_flags = hap_pte_flags_3_levels }; static const struct paging_mode hap_paging_long_mode = { @@ -800,7 +803,8 @@ static const struct paging_mode hap_paging_long_mode = { .update_cr3 = hap_update_cr3, .update_paging_modes = hap_update_paging_modes, .write_p2m_entry = hap_write_p2m_entry, - .guest_levels = 4 + .guest_levels = 4, + .pte_flags = hap_pte_flags_4_levels }; /* diff --git a/xen/arch/x86/mm/hap/private.h b/xen/arch/x86/mm/hap/private.h index 973fbe8..615b02a 100644 --- a/xen/arch/x86/mm/hap/private.h +++ b/xen/arch/x86/mm/hap/private.h @@ -47,4 +47,14 @@ unsigned long hap_p2m_ga_to_gfn_4_levels(struct vcpu *v, struct p2m_domain *p2m, unsigned long cr3, paddr_t ga, uint32_t *pfec, unsigned int *page_order); +bool hap_pte_flags_2_levels(struct vcpu *v, struct p2m_domain *p2m, + unsigned long va, uint32_t walk, unsigned long cr3, + uint32_t *gf); +bool hap_pte_flags_3_levels(struct vcpu *v, struct p2m_domain *p2m, + unsigned long va, uint32_t walk, unsigned long cr3, + uint32_t *gf); +bool hap_pte_flags_4_levels(struct vcpu *v, struct p2m_domain *p2m, + unsigned long va, uint32_t walk, unsigned long cr3, + uint32_t *gf); + #endif /* __HAP_PRIVATE_H__ */ diff --git a/xen/arch/x86/mm/mem_access.c b/xen/arch/x86/mm/mem_access.c index 03a864156..b01194d 100644 --- a/xen/arch/x86/mm/mem_access.c +++ b/xen/arch/x86/mm/mem_access.c @@ -212,7 +212,20 @@ bool p2m_mem_access_check(paddr_t gpa, unsigned long gla, d->arch.monitor.inguest_pagefault_disabled && npfec.kind != npfec_kind_with_gla ) /* don't send a mem_event */ { - hvm_emulate_one_vm_event(EMUL_KIND_NORMAL, TRAP_invalid_op, X86_EVENT_NO_EC); + struct hvm_hw_cpu ctxt; + uint32_t pfec = PFEC_page_present; + unsigned long gfn; + uint32_t gflags; + + hvm_funcs.save_cpu_ctxt(v, &ctxt); + paging_get_hostmode(v)->pte_flags(v, p2m, gla, 0, ctxt.cr3, &gflags); + if ( gflags & _PAGE_RW ) + pfec |= PFEC_write_access; + + if ( gflags & _PAGE_USER ) + pfec |= PFEC_user_mode; + + gfn = paging_ga_to_gfn_cr3(v, ctxt.cr3, gla, &pfec, NULL); return true; } diff --git a/xen/arch/x86/mm/shadow/multi.c b/xen/arch/x86/mm/shadow/multi.c index 021ae25..199873f3 100644 --- a/xen/arch/x86/mm/shadow/multi.c +++ b/xen/arch/x86/mm/shadow/multi.c @@ -178,12 +178,12 @@ sh_walk_guest_tables(struct vcpu *v, unsigned long va, walk_t *gw, return guest_walk_tables(v, p2m_get_hostp2m(v->domain), va, gw, pfec, #if GUEST_PAGING_LEVELS == 3 /* PAE */ INVALID_MFN, - v->arch.paging.shadow.gl3e + v->arch.paging.shadow.gl3e, #else /* 32 or 64 */ pagetable_get_mfn(v->arch.guest_table), - v->arch.paging.shadow.guest_vtable + v->arch.paging.shadow.guest_vtable, #endif - ); + NULL ); } /* This validation is called with lock held, and after write permission diff --git a/xen/include/asm-x86/guest_pt.h b/xen/include/asm-x86/guest_pt.h index 08031c8..523ae34 100644 --- a/xen/include/asm-x86/guest_pt.h +++ b/xen/include/asm-x86/guest_pt.h @@ -425,7 +425,8 @@ static inline unsigned int guest_walk_to_page_order(const walk_t *gw) bool guest_walk_tables(struct vcpu *v, struct p2m_domain *p2m, unsigned long va, - walk_t *gw, uint32_t pfec, mfn_t top_mfn, void *top_map); + walk_t *gw, uint32_t pfec, mfn_t top_mfn, void *top_map, + uint32_t *gf); /* Pretty-print the contents of a guest-walk */ static inline void print_gw(const walk_t *gw) diff --git a/xen/include/asm-x86/paging.h b/xen/include/asm-x86/paging.h index f008551..e5f21c9 100644 --- a/xen/include/asm-x86/paging.h +++ b/xen/include/asm-x86/paging.h @@ -122,7 +122,10 @@ struct paging_mode { void (*write_p2m_entry )(struct domain *d, unsigned long gfn, l1_pgentry_t *p, l1_pgentry_t new, unsigned int level); - + bool (*pte_flags )(struct vcpu *v, + struct p2m_domain *p2m, + unsigned long va, uint32_t walk, + unsigned long cr3, uint32_t *gf); unsigned int guest_levels; /* paging support extension */ -- 2.7.4 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxxxxxxxxx https://lists.xenproject.org/mailman/listinfo/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |