# 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
|