From: Keir Fraser Date: Sun, 25 Nov 2007 21:24:48 +0000 (+0000) Subject: vmx realmode: Detect and correctly plumb mmio accesses from emulated X-Git-Tag: archive/raspbian/4.8.0-1+rpi1~1^2~14696 X-Git-Url: https://dgit.raspbian.org/?a=commitdiff_plain;h=93bae2aebcac2870ca9a9c192b3b820b57b20ab8;p=xen.git 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 --- diff --git a/xen/arch/x86/hvm/platform.c b/xen/arch/x86/hvm/platform.c index e22f3f3ebb..7a61dc0437 100644 --- a/xen/arch/x86/hvm/platform.c +++ b/xen/arch/x86/hvm/platform.c @@ -885,9 +885,9 @@ void send_pio_req(unsigned long port, unsigned long count, int size, 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 --git a/xen/arch/x86/hvm/vmx/realmode.c b/xen/arch/x86/hvm/vmx/realmode.c index 1de0b372f6..840200eaf7 100644 --- a/xen/arch/x86/hvm/vmx/realmode.c +++ b/xen/arch/x86/hvm/vmx/realmode.c @@ -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; } @@ -244,6 +297,12 @@ static int realmode_write_io( { 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 --git a/xen/include/asm-x86/hvm/io.h b/xen/include/asm-x86/hvm/io.h index daea36d3bb..26614e7d78 100644 --- a/xen/include/asm-x86/hvm/io.h +++ b/xen/include/asm-x86/hvm/io.h @@ -149,8 +149,11 @@ static inline int register_buffered_io_handler( 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);