# HG changeset patch
# User Keir Fraser <keir.fraser@xxxxxxxxxx>
# Date 1196025888 0
# Node ID bb961bda7eff2bec637a23990caa9cf1bdaf596a
# Parent 6d129d0933942ca2ff672c1f23cf26379c1db129
vmx realmode: Detect and correctly plumb mmio accesses from emulated
realmode. Also correctly handle debug output to I/O port 0xe9.
Signed-off-by: Keir Fraser <keir.fraser@xxxxxxxxxx>
---
xen/arch/x86/hvm/platform.c | 6 +--
xen/arch/x86/hvm/vmx/realmode.c | 63 ++++++++++++++++++++++++++++++++++++++--
xen/include/asm-x86/hvm/io.h | 7 +++-
3 files changed, 69 insertions(+), 7 deletions(-)
diff -r 6d129d093394 -r bb961bda7eff xen/arch/x86/hvm/platform.c
--- a/xen/arch/x86/hvm/platform.c Sun Nov 25 18:07:33 2007 +0000
+++ b/xen/arch/x86/hvm/platform.c Sun Nov 25 21:24:48 2007 +0000
@@ -885,9 +885,9 @@ void send_pio_req(unsigned long port, un
hvm_send_assist_req(v);
}
-static void send_mmio_req(unsigned char type, unsigned long gpa,
- unsigned long count, int size, paddr_t value,
- int dir, int df, int value_is_ptr)
+void send_mmio_req(unsigned char type, unsigned long gpa,
+ unsigned long count, int size, paddr_t value,
+ int dir, int df, int value_is_ptr)
{
struct vcpu *v = current;
vcpu_iodata_t *vio;
diff -r 6d129d093394 -r bb961bda7eff xen/arch/x86/hvm/vmx/realmode.c
--- a/xen/arch/x86/hvm/vmx/realmode.c Sun Nov 25 18:07:33 2007 +0000
+++ b/xen/arch/x86/hvm/vmx/realmode.c Sun Nov 25 21:24:48 2007 +0000
@@ -108,8 +108,39 @@ realmode_read(
struct realmode_emulate_ctxt *rm_ctxt)
{
uint32_t addr = rm_ctxt->seg_reg[seg].base + offset;
+ int todo;
+
*val = 0;
- (void)hvm_copy_from_guest_phys(val, addr, bytes);
+ todo = hvm_copy_from_guest_phys(val, addr, bytes);
+
+ if ( todo )
+ {
+ struct vcpu *curr = current;
+
+ if ( todo != bytes )
+ {
+ gdprintk(XENLOG_WARNING, "RM: Partial read at %08x (%d/%d)\n",
+ addr, todo, bytes);
+ return X86EMUL_UNHANDLEABLE;
+ }
+
+ 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_mmio_req(IOREQ_TYPE_COPY, addr, 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;
}
@@ -161,7 +192,29 @@ realmode_emulate_write(
struct realmode_emulate_ctxt *rm_ctxt =
container_of(ctxt, struct realmode_emulate_ctxt, ctxt);
uint32_t addr = rm_ctxt->seg_reg[seg].base + offset;
- (void)hvm_copy_to_guest_phys(addr, &val, bytes);
+ int todo;
+
+ todo = hvm_copy_to_guest_phys(addr, &val, bytes);
+
+ if ( todo )
+ {
+ struct vcpu *curr = current;
+
+ if ( todo != bytes )
+ {
+ gdprintk(XENLOG_WARNING, "RM: Partial write at %08x (%d/%d)\n",
+ addr, todo, bytes);
+ return X86EMUL_UNHANDLEABLE;
+ }
+
+ if ( curr->arch.hvm_vmx.real_mode_io_in_progress )
+ return X86EMUL_UNHANDLEABLE;
+
+ curr->arch.hvm_vmx.real_mode_io_in_progress = 1;
+ send_mmio_req(IOREQ_TYPE_COPY, addr, 1, bytes,
+ val, IOREQ_WRITE, 0, 0);
+ }
+
return X86EMUL_OKAY;
}
@@ -243,6 +296,12 @@ static int realmode_write_io(
struct x86_emulate_ctxt *ctxt)
{
struct vcpu *curr = current;
+
+ if ( port == 0xe9 )
+ {
+ hvm_print_line(curr, val);
+ return X86EMUL_OKAY;
+ }
if ( curr->arch.hvm_vmx.real_mode_io_in_progress )
return X86EMUL_UNHANDLEABLE;
diff -r 6d129d093394 -r bb961bda7eff xen/include/asm-x86/hvm/io.h
--- a/xen/include/asm-x86/hvm/io.h Sun Nov 25 18:07:33 2007 +0000
+++ b/xen/include/asm-x86/hvm/io.h Sun Nov 25 21:24:48 2007 +0000
@@ -149,8 +149,11 @@ static inline int register_buffered_io_h
return register_io_handler(d, addr, size, action, HVM_BUFFERED_IO);
}
-extern void send_pio_req(unsigned long port, unsigned long count, int size,
- paddr_t value, int dir, int df, int value_is_ptr);
+void send_mmio_req(unsigned char type, unsigned long gpa,
+ unsigned long count, int size, paddr_t value,
+ int dir, int df, int value_is_ptr);
+void send_pio_req(unsigned long port, unsigned long count, int size,
+ paddr_t value, int dir, int df, int value_is_ptr);
void send_timeoffset_req(unsigned long timeoff);
void send_invalidate_req(void);
extern void handle_mmio(unsigned long gpa);
_______________________________________________
Xen-changelog mailing list
Xen-changelog@xxxxxxxxxxxxxxxxxxx
http://lists.xensource.com/xen-changelog
|