[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] [Xen-changelog] [xen-unstable] vmx realmode: Plumb through I/O port accesses in emulated realmode.
# HG changeset patch # User Keir Fraser <keir.fraser@xxxxxxxxxx> # Date 1195991033 0 # Node ID 368bcf480772fb32b22fa9cb0bffcd10f0ed2c25 # Parent ce3e5e859d66455ab31b8db8f286933e455b4f7c vmx realmode: Plumb through I/O port accesses in emulated realmode. Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx> --- xen/arch/x86/hvm/io.c | 6 ++- xen/arch/x86/hvm/vmx/realmode.c | 62 ++++++++++++++++++++++++++++++++++--- xen/arch/x86/hvm/vmx/vmx.c | 1 xen/arch/x86/x86_emulate.c | 34 +++++++++++++++++--- xen/include/asm-x86/hvm/vcpu.h | 3 + xen/include/asm-x86/hvm/vmx/vmcs.h | 4 ++ xen/include/asm-x86/hvm/vmx/vmx.h | 1 7 files changed, 102 insertions(+), 9 deletions(-) diff -r ce3e5e859d66 -r 368bcf480772 xen/arch/x86/hvm/io.c --- a/xen/arch/x86/hvm/io.c Sun Nov 25 09:23:02 2007 +0000 +++ b/xen/arch/x86/hvm/io.c Sun Nov 25 11:43:53 2007 +0000 @@ -841,12 +841,16 @@ void hvm_io_assist(void) if ( p->state != STATE_IORESP_READY ) { gdprintk(XENLOG_ERR, "Unexpected HVM iorequest state %d.\n", p->state); - domain_crash_synchronous(); + domain_crash(v->domain); + goto out; } rmb(); /* see IORESP_READY /then/ read contents of ioreq */ p->state = STATE_IOREQ_NONE; + + if ( v->arch.hvm_vcpu.io_complete && v->arch.hvm_vcpu.io_complete() ) + goto out; switch ( p->type ) { diff -r ce3e5e859d66 -r 368bcf480772 xen/arch/x86/hvm/vmx/realmode.c --- a/xen/arch/x86/hvm/vmx/realmode.c Sun Nov 25 09:23:02 2007 +0000 +++ b/xen/arch/x86/hvm/vmx/realmode.c Sun Nov 25 11:43:53 2007 +0000 @@ -178,7 +178,24 @@ realmode_read_io( unsigned long *val, struct x86_emulate_ctxt *ctxt) { - return X86EMUL_UNHANDLEABLE; + struct vcpu *curr = current; + + if ( curr->arch.hvm_vmx.real_mode_io_in_progress ) + return X86EMUL_UNHANDLEABLE; + + if ( !curr->arch.hvm_vmx.real_mode_io_completed ) + { + curr->arch.hvm_vmx.real_mode_io_in_progress = 1; + send_pio_req(port, 1, bytes, 0, IOREQ_READ, 0, 0); + } + + if ( !curr->arch.hvm_vmx.real_mode_io_completed ) + return X86EMUL_UNHANDLEABLE; + + *val = curr->arch.hvm_vmx.real_mode_io_data; + curr->arch.hvm_vmx.real_mode_io_completed = 0; + + return X86EMUL_OKAY; } static int realmode_write_io( @@ -187,7 +204,15 @@ static int realmode_write_io( unsigned long val, struct x86_emulate_ctxt *ctxt) { - return X86EMUL_UNHANDLEABLE; + struct vcpu *curr = current; + + if ( curr->arch.hvm_vmx.real_mode_io_in_progress ) + return X86EMUL_UNHANDLEABLE; + + curr->arch.hvm_vmx.real_mode_io_in_progress = 1; + send_pio_req(port, 1, bytes, val, IOREQ_WRITE, 0, 0); + + return X86EMUL_OKAY; } static int @@ -259,8 +284,19 @@ int vmx_realmode(struct cpu_user_regs *r rm_ctxt.insn_buf[2], rm_ctxt.insn_buf[3], rm_ctxt.insn_buf[4], rm_ctxt.insn_buf[5]); - if ( x86_emulate(&rm_ctxt.ctxt, &realmode_emulator_ops) ) - { + rc = x86_emulate(&rm_ctxt.ctxt, &realmode_emulator_ops); + + if ( curr->arch.hvm_vmx.real_mode_io_in_progress ) + { + ioreq_t *p = &get_ioreq(curr)->vp_ioreq; + gdprintk(XENLOG_DEBUG, "RM I/O %d %c addr=%lx data=%lx\n", + p->type, p->dir ? 'R' : 'W', p->addr, p->data); + rc = 0; + break; + } + + if ( rc ) + { gdprintk(XENLOG_ERR, "Emulation failed\n"); rc = -EINVAL; break; @@ -272,3 +308,21 @@ int vmx_realmode(struct cpu_user_regs *r return rc; } + +int vmx_realmode_io_complete(void) +{ + struct vcpu *curr = current; + ioreq_t *p = &get_ioreq(curr)->vp_ioreq; + + if ( !curr->arch.hvm_vmx.real_mode_io_in_progress ) + return 0; + + curr->arch.hvm_vmx.real_mode_io_in_progress = 0; + if ( p->dir == IOREQ_READ ) + { + curr->arch.hvm_vmx.real_mode_io_completed = 1; + curr->arch.hvm_vmx.real_mode_io_data = p->data; + } + + return 1; +} diff -r ce3e5e859d66 -r 368bcf480772 xen/arch/x86/hvm/vmx/vmx.c --- a/xen/arch/x86/hvm/vmx/vmx.c Sun Nov 25 09:23:02 2007 +0000 +++ b/xen/arch/x86/hvm/vmx/vmx.c Sun Nov 25 11:43:53 2007 +0000 @@ -95,6 +95,7 @@ static int vmx_vcpu_initialise(struct vc #ifndef VMXASSIST if ( v->vcpu_id == 0 ) v->arch.guest_context.user_regs.eax = 1; + v->arch.hvm_vcpu.io_complete = vmx_realmode_io_complete; #endif return 0; diff -r ce3e5e859d66 -r 368bcf480772 xen/arch/x86/x86_emulate.c --- a/xen/arch/x86/x86_emulate.c Sun Nov 25 09:23:02 2007 +0000 +++ b/xen/arch/x86/x86_emulate.c Sun Nov 25 11:43:53 2007 +0000 @@ -264,6 +264,7 @@ struct operand { }; /* EFLAGS bit definitions. */ +#define EFLG_VM (1<<17) #define EFLG_RF (1<<16) #define EFLG_OF (1<<11) #define EFLG_DF (1<<10) @@ -478,10 +479,6 @@ do { /* In future we will be able to generate arbitrary exceptions. */ #define generate_exception_if(p, e) fail_if(p) -/* To be done... */ -#define mode_ring0() (0) -#define mode_iopl() (0) - /* Given byte has even parity (even number of 1s)? */ static int even_parity(uint8_t v) { @@ -678,6 +675,35 @@ test_cc( /* Odd condition identifiers (lsb == 1) have inverted sense. */ return (!!rc ^ (condition & 1)); } + +static int +get_cpl( + struct x86_emulate_ctxt *ctxt, + struct x86_emulate_ops *ops) +{ + struct segment_register reg; + + if ( ctxt->regs->eflags & EFLG_VM ) + return 3; + + if ( (ops->read_segment == NULL) || + ops->read_segment(x86_seg_ss, ®, ctxt) ) + return -1; + + return reg.attr.fields.dpl; +} + +static int +_mode_iopl( + struct x86_emulate_ctxt *ctxt, + struct x86_emulate_ops *ops) +{ + int cpl = get_cpl(ctxt, ops); + return ((cpl >= 0) && (cpl <= ((ctxt->regs->eflags >> 12) & 3))); +} + +#define mode_ring0() (get_cpl(ctxt, ops) == 0) +#define mode_iopl() _mode_iopl(ctxt, ops) static int in_realmode( diff -r ce3e5e859d66 -r 368bcf480772 xen/include/asm-x86/hvm/vcpu.h --- a/xen/include/asm-x86/hvm/vcpu.h Sun Nov 25 09:23:02 2007 +0000 +++ b/xen/include/asm-x86/hvm/vcpu.h Sun Nov 25 11:43:53 2007 +0000 @@ -59,6 +59,9 @@ struct hvm_vcpu { bool_t flag_dr_dirty; bool_t debug_state_latch; + /* Callback function for I/O completion. */ + int (*io_complete)(void); + union { struct arch_vmx_struct vmx; struct arch_svm_struct svm; diff -r ce3e5e859d66 -r 368bcf480772 xen/include/asm-x86/hvm/vmx/vmcs.h --- a/xen/include/asm-x86/hvm/vmx/vmcs.h Sun Nov 25 09:23:02 2007 +0000 +++ b/xen/include/asm-x86/hvm/vmx/vmcs.h Sun Nov 25 11:43:53 2007 +0000 @@ -92,6 +92,10 @@ struct arch_vmx_struct { unsigned long vmxassist_enabled:1; unsigned long irqbase_mode:1; unsigned char pm_irqbase[2]; +#else + bool_t real_mode_io_in_progress; + bool_t real_mode_io_completed; + unsigned long real_mode_io_data; #endif }; diff -r ce3e5e859d66 -r 368bcf480772 xen/include/asm-x86/hvm/vmx/vmx.h --- a/xen/include/asm-x86/hvm/vmx/vmx.h Sun Nov 25 09:23:02 2007 +0000 +++ b/xen/include/asm-x86/hvm/vmx/vmx.h Sun Nov 25 11:43:53 2007 +0000 @@ -34,6 +34,7 @@ void set_guest_time(struct vcpu *v, u64 void set_guest_time(struct vcpu *v, u64 gtime); void vmx_vlapic_msr_changed(struct vcpu *v); int vmx_realmode(struct cpu_user_regs *regs); +int vmx_realmode_io_complete(void); /* * Exit Reasons _______________________________________________ Xen-changelog mailing list Xen-changelog@xxxxxxxxxxxxxxxxxxx http://lists.xensource.com/xen-changelog
|
Lists.xenproject.org is hosted with RackSpace, monitoring our |