[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen master] x86emul: New return code for unimplemented instruction
commit 63e49e966fafc4057deb8968b63b2bbe9bb6fd1e Author: Petre Pircalabu <ppircalabu@xxxxxxxxxxxxxxx> AuthorDate: Mon Oct 2 16:04:54 2017 +0100 Commit: George Dunlap <george.dunlap@xxxxxxxxxx> CommitDate: Mon Oct 2 16:04:54 2017 +0100 x86emul: New return code for unimplemented instruction Enforce the distinction between an instruction not implemented by the emulator and the failure to emulate that instruction by defining a new return code, X86EMUL_UNIMPLEMENTED. This value should only be returned by the core emulator when a valid opcode is found but the execution logic for that instruction is missing. It should NOT be returned by any of the x86_emulate_ops callbacks. e.g. hvm_process_io_intercept should not return X86EMUL_UNIMPLEMENTED. The return value of this function depends on either the return code of one of the hvm_io_ops handlers (read/write) or the value returned by hvm_copy_guest_from_phys / hvm_copy_to_guest_phys. Similary, none of this functions should return X86EMUL_UNIMPLEMENTED. - hvm_io_intercept - hvmemul_do_io - hvm_send_buffered_ioreq - hvm_send_ioreq - hvm_broadcast_ioreq - hvmemul_do_io_buffer - hvmemul_validate Also the behavior of hvm_emulate_one_insn and vmx_realmode_emulate_one was modified to generate an Invalid Opcode trap when X86EMUL_UNRECOGNIZED is returned by the emulator instead of just crash the domain. Signed-off-by: Petre Pircalabu <ppircalabu@xxxxxxxxxxxxxxx> Reviewed-by: Paul Durrant <paul.durrant@xxxxxxxxxx> Reviewed-by: Jan Beulich <jbeulich@xxxxxxxx> Reviewed-by: George Dunlap <george.dunlap@xxxxxxxxxx> --- xen/arch/x86/hvm/emulate.c | 12 ++++++++ xen/arch/x86/hvm/hvm.c | 1 + xen/arch/x86/hvm/io.c | 5 ++++ xen/arch/x86/hvm/vmx/realmode.c | 9 ++++++ xen/arch/x86/mm/shadow/multi.c | 2 +- xen/arch/x86/x86_emulate/x86_emulate.c | 51 +++++++++++++++++++--------------- xen/arch/x86/x86_emulate/x86_emulate.h | 17 ++++++++++++ 7 files changed, 74 insertions(+), 23 deletions(-) diff --git a/xen/arch/x86/hvm/emulate.c b/xen/arch/x86/hvm/emulate.c index cc874ce..385fe1e 100644 --- a/xen/arch/x86/hvm/emulate.c +++ b/xen/arch/x86/hvm/emulate.c @@ -284,10 +284,15 @@ static int hvmemul_do_io( } break; } + case X86EMUL_UNIMPLEMENTED: + ASSERT_UNREACHABLE(); + /* Fall-through */ default: BUG(); } + ASSERT(rc != X86EMUL_UNIMPLEMENTED); + if ( rc != X86EMUL_OKAY ) return rc; @@ -313,6 +318,9 @@ static int hvmemul_do_io_buffer( rc = hvmemul_do_io(is_mmio, addr, reps, size, dir, df, 0, (uintptr_t)buffer); + + ASSERT(rc != X86EMUL_UNIMPLEMENTED); + if ( rc == X86EMUL_UNHANDLEABLE && dir == IOREQ_READ ) memset(buffer, 0xff, size); @@ -405,6 +413,8 @@ static int hvmemul_do_io_addr( rc = hvmemul_do_io(is_mmio, addr, &count, size, dir, df, 1, ram_gpa); + ASSERT(rc != X86EMUL_UNIMPLEMENTED); + if ( rc == X86EMUL_OKAY ) v->arch.hvm_vcpu.hvm_io.mmio_retry = (count < *reps); @@ -2045,6 +2055,7 @@ int hvm_emulate_one_mmio(unsigned long mfn, unsigned long gla) switch ( rc ) { case X86EMUL_UNHANDLEABLE: + case X86EMUL_UNIMPLEMENTED: hvm_dump_emulation_state(XENLOG_G_WARNING, "MMCFG", &ctxt); break; case X86EMUL_EXCEPTION: @@ -2102,6 +2113,7 @@ void hvm_emulate_one_vm_event(enum emul_kind kind, unsigned int trapnr, * consistent with X86EMUL_RETRY. */ return; + case X86EMUL_UNIMPLEMENTED: case X86EMUL_UNHANDLEABLE: hvm_dump_emulation_state(XENLOG_G_DEBUG, "Mem event", &ctx); hvm_inject_hw_exception(trapnr, errcode); diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c index 887f0e5..b0a46d7 100644 --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -3735,6 +3735,7 @@ void hvm_ud_intercept(struct cpu_user_regs *regs) switch ( hvm_emulate_one(&ctxt) ) { case X86EMUL_UNHANDLEABLE: + case X86EMUL_UNIMPLEMENTED: hvm_inject_hw_exception(TRAP_invalid_op, X86_EVENT_NO_EC); break; case X86EMUL_EXCEPTION: diff --git a/xen/arch/x86/hvm/io.c b/xen/arch/x86/hvm/io.c index 1ddcaba..508e28f 100644 --- a/xen/arch/x86/hvm/io.c +++ b/xen/arch/x86/hvm/io.c @@ -99,6 +99,11 @@ bool hvm_emulate_one_insn(hvm_emulate_validate_t *validate, const char *descr) hvm_dump_emulation_state(XENLOG_G_WARNING, descr, &ctxt); return false; + case X86EMUL_UNRECOGNIZED: + hvm_dump_emulation_state(XENLOG_G_WARNING, descr, &ctxt); + hvm_inject_hw_exception(TRAP_invalid_op, X86_EVENT_NO_EC); + break; + case X86EMUL_EXCEPTION: hvm_inject_event(&ctxt.ctxt.event); break; diff --git a/xen/arch/x86/hvm/vmx/realmode.c b/xen/arch/x86/hvm/vmx/realmode.c index 12d43ad..b73fc80 100644 --- a/xen/arch/x86/hvm/vmx/realmode.c +++ b/xen/arch/x86/hvm/vmx/realmode.c @@ -112,6 +112,15 @@ void vmx_realmode_emulate_one(struct hvm_emulate_ctxt *hvmemul_ctxt) goto fail; } + if ( rc == X86EMUL_UNRECOGNIZED ) + { + gdprintk(XENLOG_ERR, "Unrecognized insn.\n"); + if ( curr->arch.hvm_vcpu.guest_cr[0] & X86_CR0_PE ) + goto fail; + + realmode_deliver_exception(TRAP_invalid_op, 0, hvmemul_ctxt); + } + if ( rc == X86EMUL_EXCEPTION ) { if ( unlikely(curr->domain->debugger_attached) && diff --git a/xen/arch/x86/mm/shadow/multi.c b/xen/arch/x86/mm/shadow/multi.c index 8d4f244..2557e21 100644 --- a/xen/arch/x86/mm/shadow/multi.c +++ b/xen/arch/x86/mm/shadow/multi.c @@ -3488,7 +3488,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 ) + if ( r == X86EMUL_UNHANDLEABLE || r == X86EMUL_UNIMPLEMENTED ) { perfc_incr(shadow_fault_emulate_failed); #if SHADOW_OPTIMIZATIONS & SHOPT_FAST_EMULATION diff --git a/xen/arch/x86/x86_emulate/x86_emulate.c b/xen/arch/x86/x86_emulate/x86_emulate.c index ff1a401..a68676c 100644 --- a/xen/arch/x86/x86_emulate/x86_emulate.c +++ b/xen/arch/x86/x86_emulate/x86_emulate.c @@ -848,7 +848,8 @@ do{ asm volatile ( \ stub.func); \ generate_exception_if(res_.fields.trapnr == EXC_UD, EXC_UD); \ domain_crash(current->domain); \ - goto cannot_emulate; \ + rc = X86EMUL_UNHANDLEABLE; \ + goto done; \ } \ } while (0) #else @@ -2585,7 +2586,7 @@ x86_decode( d = twobyte_table[0x3a].desc; break; default: - rc = X86EMUL_UNHANDLEABLE; + rc = X86EMUL_UNRECOGNIZED; goto done; } } @@ -2599,7 +2600,7 @@ x86_decode( } else { - rc = X86EMUL_UNHANDLEABLE; + rc = X86EMUL_UNRECOGNIZED; goto done; } @@ -2879,7 +2880,7 @@ x86_decode( default: ASSERT_UNREACHABLE(); - return X86EMUL_UNHANDLEABLE; + return X86EMUL_UNIMPLEMENTED; } if ( ea.type == OP_MEM ) @@ -4193,7 +4194,7 @@ x86_emulate( break; case 4: /* fldenv - TODO */ state->fpu_ctrl = true; - goto cannot_emulate; + goto unimplemented_insn; case 5: /* fldcw m2byte */ state->fpu_ctrl = true; if ( (rc = ops->read(ea.mem.seg, ea.mem.off, &src.val, @@ -4204,7 +4205,7 @@ x86_emulate( break; case 6: /* fnstenv - TODO */ state->fpu_ctrl = true; - goto cannot_emulate; + goto unimplemented_insn; case 7: /* fnstcw m2byte */ state->fpu_ctrl = true; emulate_fpu_insn_memdst("fnstcw", dst.val); @@ -4440,7 +4441,7 @@ x86_emulate( case 4: /* frstor - TODO */ case 6: /* fnsave - TODO */ state->fpu_ctrl = true; - goto cannot_emulate; + goto unimplemented_insn; case 7: /* fnstsw m2byte */ state->fpu_ctrl = true; emulate_fpu_insn_memdst("fnstsw", dst.val); @@ -5199,7 +5200,7 @@ x86_emulate( #undef _GRP7 default: - goto cannot_emulate; + goto unimplemented_insn; } break; } @@ -6197,7 +6198,7 @@ x86_emulate( /* vpsll{w,d} $imm8,{x,y}mm,{x,y}mm */ break; default: - goto cannot_emulate; + goto unrecognized_insn; } simd_0f_shift_imm: generate_exception_if(ea.type != OP_REG, EXC_UD); @@ -6245,7 +6246,7 @@ x86_emulate( case 6: /* psllq $imm8,mm */ goto simd_0f_shift_imm; } - goto cannot_emulate; + goto unrecognized_insn; case X86EMUL_OPC_66(0x0f, 0x73): case X86EMUL_OPC_VEX_66(0x0f, 0x73): @@ -6261,7 +6262,7 @@ x86_emulate( /* vpslldq $imm8,{x,y}mm,{x,y}mm */ goto simd_0f_shift_imm; } - goto cannot_emulate; + goto unrecognized_insn; case X86EMUL_OPC(0x0f, 0x77): /* emms */ case X86EMUL_OPC_VEX(0x0f, 0x77): /* vzero{all,upper} */ @@ -6325,7 +6326,7 @@ x86_emulate( case 0: /* extrq $imm8,$imm8,xmm */ break; default: - goto cannot_emulate; + goto unrecognized_insn; } /* fall through */ case X86EMUL_OPC_F2(0x0f, 0x78): /* insertq $imm8,$imm8,xmm,xmm */ @@ -6520,7 +6521,7 @@ x86_emulate( goto done; break; default: - goto cannot_emulate; + goto unimplemented_insn; } break; @@ -6536,7 +6537,7 @@ x86_emulate( vcpu_must_have(avx); goto stmxcsr; } - goto cannot_emulate; + goto unrecognized_insn; case X86EMUL_OPC_F3(0x0f, 0xae): /* Grp15 */ fail_if(modrm_mod != 3); @@ -6779,10 +6780,10 @@ x86_emulate( switch ( modrm_reg & 7 ) { default: - goto cannot_emulate; + goto unrecognized_insn; -#ifdef HAVE_GAS_RDRAND case 6: /* rdrand */ +#ifdef HAVE_GAS_RDRAND generate_exception_if(rep_prefix(), EXC_UD); host_and_vcpu_must_have(rdrand); dst = ea; @@ -6807,6 +6808,8 @@ x86_emulate( if ( carry ) _regs.eflags |= X86_EFLAGS_CF; break; +#else + goto unimplemented_insn; #endif case 7: /* rdseed / rdpid */ @@ -7361,7 +7364,7 @@ x86_emulate( host_and_vcpu_must_have(bmi1); break; default: - goto cannot_emulate; + goto unrecognized_insn; } generate_exception_if(vex.l, EXC_UD); @@ -7672,7 +7675,7 @@ x86_emulate( host_and_vcpu_must_have(tbm); break; default: - goto cannot_emulate; + goto unrecognized_insn; } xop_09_rm_rv: @@ -7706,7 +7709,7 @@ x86_emulate( host_and_vcpu_must_have(tbm); goto xop_09_rm_rv; } - goto cannot_emulate; + goto unrecognized_insn; case X86EMUL_OPC_XOP(0a, 0x10): /* bextr imm,r/m,r */ { @@ -7738,8 +7741,11 @@ x86_emulate( } default: - cannot_emulate: - rc = X86EMUL_UNHANDLEABLE; + unimplemented_insn: + rc = X86EMUL_UNIMPLEMENTED; + goto done; + unrecognized_insn: + rc = X86EMUL_UNRECOGNIZED; goto done; } @@ -7791,7 +7797,8 @@ x86_emulate( if ( (d & DstMask) != DstMem ) { ASSERT_UNREACHABLE(); - goto cannot_emulate; + rc = X86EMUL_UNHANDLEABLE; + goto done; } break; } diff --git a/xen/arch/x86/x86_emulate/x86_emulate.h b/xen/arch/x86/x86_emulate/x86_emulate.h index 4ddf111..0c8c80a 100644 --- a/xen/arch/x86/x86_emulate/x86_emulate.h +++ b/xen/arch/x86/x86_emulate/x86_emulate.h @@ -133,6 +133,23 @@ struct x86_emul_fpu_aux { * Undefined behavior when used anywhere else. */ #define X86EMUL_DONE 4 + /* + * Current instruction is not implemented by the emulator. + * This value should only be returned by the core emulator when a valid + * opcode is found but the execution logic for that instruction is missing. + * It should NOT be returned by any of the x86_emulate_ops callbacks. + */ +#define X86EMUL_UNIMPLEMENTED 5 + /* + * The current instruction's opcode is not valid. + * If this error code is returned by a function, an #UD trap should be + * raised by the final consumer of it. + * + * TODO: For the moment X86EMUL_UNRECOGNIZED and X86EMUL_UNIMPLEMENTED + * can be used interchangeably therefore raising an #UD trap is not + * strictly expected for now. + */ +#define X86EMUL_UNRECOGNIZED X86EMUL_UNIMPLEMENTED /* FPU sub-types which may be requested via ->get_fpu(). */ enum x86_emulate_fpu_type { -- generated by git-patchbot for /home/xen/git/xen.git#master _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxx https://lists.xenproject.org/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |