[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-devel] [PATCH RFC V3 1/5] xen: Emulate with no writes
Added support for emulating an instruction with no memory writes. Additionally, introduced hvm_emulate_one_full(), which inspects possible return values from the hvm_emulate_one() functions (EXCEPTION, UNHANDLEABLE) and acts on them. Changes since V1: - Removed the Linux code that computes the length of an instruction. - Unused function parameters are no longer marked. - Refactored the code to eliminate redundancy. - Made the exception passed on to the guest by hvm_emulate_one_full() configurable. Changes since V2: - Renamed hvmemul_write_dummy() to hvmemul_write_discard(). - Fixed a comment (Xen coding style rules). - Renamed hvm_emulate_one_with_ops() to _hvm_emulate_one(). - Changed stack variable hvm_emulate_ops_no_write into a static const. - Modified struct hvm_emulate_ctxt ctx initialization syntax. - Renamed unhandleable_trapnr to trapnr and unhandleable_errcode to errcode. - Changed errcode's type to unsigned int. - Removed hvm_emulate_one() loop that went on until it returned something other than X86EMUL_RETRY (to prevent potential blocking against the time calibration rendezvous). Signed-off-by: Razvan Cojocaru <rcojocaru@xxxxxxxxxxxxxxx> --- xen/arch/x86/hvm/emulate.c | 91 +++++++++++++++++++++++++++++++++++-- xen/include/asm-x86/hvm/emulate.h | 5 ++ 2 files changed, 93 insertions(+), 3 deletions(-) diff --git a/xen/arch/x86/hvm/emulate.c b/xen/arch/x86/hvm/emulate.c index eac159f..f4be6cd 100644 --- a/xen/arch/x86/hvm/emulate.c +++ b/xen/arch/x86/hvm/emulate.c @@ -688,6 +688,17 @@ static int hvmemul_write( return X86EMUL_OKAY; } +static int hvmemul_write_discard( + enum x86_segment seg, + unsigned long offset, + void *p_data, + unsigned int bytes, + struct x86_emulate_ctxt *ctxt) +{ + /* Discarding the write. */ + return X86EMUL_OKAY; +} + static int hvmemul_cmpxchg( enum x86_segment seg, unsigned long offset, @@ -1138,8 +1149,33 @@ static const struct x86_emulate_ops hvm_emulate_ops = { .invlpg = hvmemul_invlpg }; -int hvm_emulate_one( - struct hvm_emulate_ctxt *hvmemul_ctxt) +static const struct x86_emulate_ops hvm_emulate_ops_no_write = { + .read = hvmemul_read, + .insn_fetch = hvmemul_insn_fetch, + .write = hvmemul_write_discard, + .cmpxchg = hvmemul_cmpxchg, + .rep_ins = hvmemul_rep_ins, + .rep_outs = hvmemul_rep_outs, + .rep_movs = hvmemul_rep_movs, + .read_segment = hvmemul_read_segment, + .write_segment = hvmemul_write_segment, + .read_io = hvmemul_read_io, + .write_io = hvmemul_write_io, + .read_cr = hvmemul_read_cr, + .write_cr = hvmemul_write_cr, + .read_msr = hvmemul_read_msr, + .write_msr = hvmemul_write_msr, + .wbinvd = hvmemul_wbinvd, + .cpuid = hvmemul_cpuid, + .inject_hw_exception = hvmemul_inject_hw_exception, + .inject_sw_interrupt = hvmemul_inject_sw_interrupt, + .get_fpu = hvmemul_get_fpu, + .put_fpu = hvmemul_put_fpu, + .invlpg = hvmemul_invlpg +}; + +static int _hvm_emulate_one(struct hvm_emulate_ctxt *hvmemul_ctxt, + const struct x86_emulate_ops *ops) { struct cpu_user_regs *regs = hvmemul_ctxt->ctxt.regs; struct vcpu *curr = current; @@ -1191,7 +1227,7 @@ int hvm_emulate_one( vio->mmio_retrying = vio->mmio_retry; vio->mmio_retry = 0; - rc = x86_emulate(&hvmemul_ctxt->ctxt, &hvm_emulate_ops); + rc = x86_emulate(&hvmemul_ctxt->ctxt, ops); if ( rc == X86EMUL_OKAY && vio->mmio_retry ) rc = X86EMUL_RETRY; @@ -1239,6 +1275,55 @@ int hvm_emulate_one( return X86EMUL_OKAY; } +int hvm_emulate_one( + struct hvm_emulate_ctxt *hvmemul_ctxt) +{ + return _hvm_emulate_one(hvmemul_ctxt, &hvm_emulate_ops); +} + +int hvm_emulate_one_no_write( + struct hvm_emulate_ctxt *hvmemul_ctxt) +{ + return _hvm_emulate_one(hvmemul_ctxt, &hvm_emulate_ops_no_write); +} + +void hvm_emulate_one_full(bool_t nowrite, unsigned int trapnr, + unsigned int errcode) +{ + struct hvm_emulate_ctxt ctx = {{ 0 }}; + int rc; + + hvm_emulate_prepare(&ctx, guest_cpu_user_regs()); + + if ( nowrite ) + rc = hvm_emulate_one_no_write(&ctx); + else + rc = hvm_emulate_one(&ctx); + + switch ( rc ) + { + case X86EMUL_UNHANDLEABLE: + gdprintk(XENLOG_DEBUG, "Emulation failed @ %04x:%lx: " + "%02x %02x %02x %02x %02x %02x %02x %02x %02x %02x\n", + hvmemul_get_seg_reg(x86_seg_cs, &ctx)->sel, + ctx.insn_buf_eip, + ctx.insn_buf[0], ctx.insn_buf[1], + ctx.insn_buf[2], ctx.insn_buf[3], + ctx.insn_buf[4], ctx.insn_buf[5], + ctx.insn_buf[6], ctx.insn_buf[7], + ctx.insn_buf[8], ctx.insn_buf[9]); + hvm_inject_hw_exception(trapnr, errcode); + break; + case X86EMUL_EXCEPTION: + if ( ctx.exn_pending ) + hvm_inject_hw_exception(ctx.exn_vector, ctx.exn_error_code); + /* fall through */ + default: + hvm_emulate_writeback(&ctx); + break; + } +} + void hvm_emulate_prepare( struct hvm_emulate_ctxt *hvmemul_ctxt, struct cpu_user_regs *regs) diff --git a/xen/include/asm-x86/hvm/emulate.h b/xen/include/asm-x86/hvm/emulate.h index 00a06cc..a74f310 100644 --- a/xen/include/asm-x86/hvm/emulate.h +++ b/xen/include/asm-x86/hvm/emulate.h @@ -37,6 +37,11 @@ struct hvm_emulate_ctxt { int hvm_emulate_one( struct hvm_emulate_ctxt *hvmemul_ctxt); +int hvm_emulate_one_no_write( + struct hvm_emulate_ctxt *hvmemul_ctxt); +void hvm_emulate_one_full(bool_t nowrite, + unsigned int trapnr, + unsigned int errcode); void hvm_emulate_prepare( struct hvm_emulate_ctxt *hvmemul_ctxt, struct cpu_user_regs *regs); -- 1.7.9.5 _______________________________________________ Xen-devel mailing list Xen-devel@xxxxxxxxxxxxx http://lists.xen.org/xen-devel
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |