From f21399e148386ecf3826ab81159eca58cfab2147 Mon Sep 17 00:00:00 2001 From: Jan Beulich Date: Mon, 14 Oct 2013 09:50:16 +0200 Subject: x86/HVM: properly handle backward string instruction emulation Multiplying a signed 32-bit quantity with an unsigned 32-bit quantity produces an unsigned 32-bit result, yet for emulation of backward string instructions we need the result sign extended before getting added to the base address. Signed-off-by: Jan Beulich Reviewed-by: Andrew Cooper Acked-by: Keir Fraser --- xen/arch/x86/hvm/stdvga.c | 34 +++++++++++----------------------- 1 file changed, 11 insertions(+), 23 deletions(-) (limited to 'xen/arch/x86/hvm/stdvga.c') diff --git a/xen/arch/x86/hvm/stdvga.c b/xen/arch/x86/hvm/stdvga.c index 331fca0ff4..19e80ed607 100644 --- a/xen/arch/x86/hvm/stdvga.c +++ b/xen/arch/x86/hvm/stdvga.c @@ -467,15 +467,17 @@ static uint32_t read_data; static int mmio_move(struct hvm_hw_stdvga *s, ioreq_t *p) { int i; - int sign = p->df ? -1 : 1; + uint64_t addr = p->addr; p2m_type_t p2mt; struct domain *d = current->domain; if ( p->data_is_ptr ) { + uint64_t data = p->data, tmp; + int step = p->df ? -p->size : p->size; + if ( p->dir == IOREQ_READ ) { - uint64_t addr = p->addr, data = p->data, tmp; for ( i = 0; i < p->count; i++ ) { tmp = stdvga_mem_read(addr, p->size); @@ -498,13 +500,12 @@ static int mmio_move(struct hvm_hw_stdvga *s, ioreq_t *p) ASSERT(!dp); stdvga_mem_write(data, tmp, p->size); } - data += sign * p->size; - addr += sign * p->size; + data += step; + addr += step; } } else { - uint32_t addr = p->addr, data = p->data, tmp; for ( i = 0; i < p->count; i++ ) { if ( hvm_copy_from_guest_phys(&tmp, data, p->size) != @@ -523,31 +524,18 @@ static int mmio_move(struct hvm_hw_stdvga *s, ioreq_t *p) tmp = stdvga_mem_read(data, p->size); } stdvga_mem_write(addr, tmp, p->size); - data += sign * p->size; - addr += sign * p->size; + data += step; + addr += step; } } } else { + ASSERT(p->count == 1); if ( p->dir == IOREQ_READ ) - { - uint32_t addr = p->addr; - for ( i = 0; i < p->count; i++ ) - { - p->data = stdvga_mem_read(addr, p->size); - addr += sign * p->size; - } - } + p->data = stdvga_mem_read(addr, p->size); else - { - uint32_t addr = p->addr; - for ( i = 0; i < p->count; i++ ) - { - stdvga_mem_write(addr, p->data, p->size); - addr += sign * p->size; - } - } + stdvga_mem_write(addr, p->data, p->size); } read_data = p->data; -- cgit v1.2.3