[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH v2 13/19] x86/shadow: Avoid raising faults behind the emulators back
Use x86_emul_{hw_exception,pagefault}() rather than {pv,hvm}_inject_page_fault() and hvm_inject_hw_exception() to cause raised faults to be known to the emulator. This requires altering the callers of x86_emulate() to properly re-inject the event. While fixing this, fix the singlestep behaviour. Previously, an otherwise successful emulation would fail if singlestepping was active, as the emulator couldn't raise #DB. This is unreasonable from the point of view of the guest. We therefore tolerate #PF/#GP/SS and #DB being raised by the emulator, but reject anything else as unexpected. Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx> --- CC: Jan Beulich <JBeulich@xxxxxxxx> CC: Tim Deegan <tim@xxxxxxx> v2: * New --- xen/arch/x86/mm/shadow/common.c | 13 ++++----- xen/arch/x86/mm/shadow/multi.c | 61 ++++++++++++++++++++++++++++++++++++++++- 2 files changed, 66 insertions(+), 8 deletions(-) diff --git a/xen/arch/x86/mm/shadow/common.c b/xen/arch/x86/mm/shadow/common.c index f07803b..e509cc1 100644 --- a/xen/arch/x86/mm/shadow/common.c +++ b/xen/arch/x86/mm/shadow/common.c @@ -162,8 +162,9 @@ static int hvm_translate_linear_addr( if ( !okay ) { - hvm_inject_hw_exception( - (seg == x86_seg_ss) ? TRAP_stack_error : TRAP_gp_fault, 0); + x86_emul_hw_exception( + (seg == x86_seg_ss) ? TRAP_stack_error : TRAP_gp_fault, + 0, &sh_ctxt->ctxt); return X86EMUL_EXCEPTION; } @@ -323,7 +324,7 @@ pv_emulate_read(enum x86_segment seg, if ( (rc = copy_from_user(p_data, (void *)offset, bytes)) != 0 ) { - pv_inject_page_fault(0, offset + bytes - rc); /* Read fault. */ + x86_emul_pagefault(0, offset + bytes - rc, ctxt); /* Read fault. */ return X86EMUL_EXCEPTION; } @@ -1720,10 +1721,8 @@ static mfn_t emulate_gva_to_mfn(struct vcpu *v, unsigned long vaddr, gfn = paging_get_hostmode(v)->gva_to_gfn(v, NULL, vaddr, &pfec); if ( gfn == gfn_x(INVALID_GFN) ) { - if ( is_hvm_vcpu(v) ) - hvm_inject_page_fault(pfec, vaddr); - else - pv_inject_page_fault(pfec, vaddr); + x86_emul_pagefault(pfec, vaddr, &sh_ctxt->ctxt); + return _mfn(BAD_GVA_TO_GFN); } diff --git a/xen/arch/x86/mm/shadow/multi.c b/xen/arch/x86/mm/shadow/multi.c index 13fa1bf..50705a0 100644 --- a/xen/arch/x86/mm/shadow/multi.c +++ b/xen/arch/x86/mm/shadow/multi.c @@ -3390,7 +3390,7 @@ static int sh_page_fault(struct vcpu *v, * would be a good unshadow hint. If we *do* decide to unshadow-on-fault * then it must be 'failable': we cannot require the unshadow to succeed. */ - if ( r == X86EMUL_UNHANDLEABLE || emul_ctxt.ctxt.event_pending ) + if ( r == X86EMUL_UNHANDLEABLE ) { perfc_incr(shadow_fault_emulate_failed); #if SHADOW_OPTIMIZATIONS & SHOPT_FAST_EMULATION @@ -3434,6 +3434,34 @@ static int sh_page_fault(struct vcpu *v, v->arch.paging.last_write_emul_ok = 0; #endif + if ( r == X86EMUL_EXCEPTION && emul_ctxt.ctxt.event_pending ) + { + /* + * This emulation covers writes to shadow pagetables. We tolerate #PF + * (from hitting adjacent pages), #GP/#SS (from segmentation errors), + * and #DB (from singlestepping). Anything else is an emulation bug, + * or a guest playing with the instruction stream under Xen's feet. + */ + if ( emul_ctxt.ctxt.event.type == X86_EVENTTYPE_HW_EXCEPTION && + (emul_ctxt.ctxt.event.vector < 32) && + ((1u << emul_ctxt.ctxt.event.vector) & + ((1u << TRAP_debug) | (1u << TRAP_stack_error) | + (1u << TRAP_gp_fault) | (1u << TRAP_page_fault))) ) + { + if ( is_hvm_vcpu(v) ) + hvm_inject_event(&emul_ctxt.ctxt.event); + else + pv_inject_event(&emul_ctxt.ctxt.event); + } + else + { + if ( is_hvm_vcpu(v) ) + hvm_inject_hw_exception(TRAP_gp_fault, 0); + else + pv_inject_hw_exception(TRAP_gp_fault, 0); + } + } + #if GUEST_PAGING_LEVELS == 3 /* PAE guest */ if ( r == X86EMUL_OKAY ) { int i, emulation_count=0; @@ -3475,6 +3503,37 @@ static int sh_page_fault(struct vcpu *v, { perfc_incr(shadow_em_ex_fail); TRACE_SHADOW_PATH_FLAG(TRCE_SFLAG_EMULATION_LAST_FAILED); + + if ( r == X86EMUL_EXCEPTION && emul_ctxt.ctxt.event_pending ) + { + /* + * This emulation covers writes to shadow pagetables. We + * tolerate #PF (from hitting adjacent pages), #GP/#SS + * (from segmentation errors), and #DB (from + * singlestepping). Anything else is an emulation bug, or + * a guest playing with the instruction stream under Xen's + * feet. + */ + if ( emul_ctxt.ctxt.event.type == X86_EVENTTYPE_HW_EXCEPTION && + (emul_ctxt.ctxt.event.vector < 32) && + ((1u << emul_ctxt.ctxt.event.vector) & + ((1u << TRAP_debug) | (1u << TRAP_stack_error) | + (1u << TRAP_gp_fault) | (1u << TRAP_page_fault))) ) + { + if ( is_hvm_vcpu(v) ) + hvm_inject_event(&emul_ctxt.ctxt.event); + else + pv_inject_event(&emul_ctxt.ctxt.event); + } + else + { + if ( is_hvm_vcpu(v) ) + hvm_inject_hw_exception(TRAP_gp_fault, 0); + else + pv_inject_hw_exception(TRAP_gp_fault, 0); + } + } + break; /* Don't emulate again if we failed! */ } } -- 2.1.4 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx https://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |