diff -uNr xen-unstable.hg-orig/xen/arch/x86/hvm/stdvga.c xen-unstable.hg/xen/arch/x86/hvm/stdvga.c --- xen-unstable.hg-orig/xen/arch/x86/hvm/stdvga.c 2008-06-01 13:51:38.000000000 +0100 +++ xen-unstable.hg/xen/arch/x86/hvm/stdvga.c 2008-07-23 12:09:13.949344452 +0100 @@ -33,6 +33,10 @@ #include #include #include +#include + +#define VGA_MEM_BASE 0xa0000 +#define VGA_MEM_SIZE 0x20000 #define PAT(x) (x) static const uint32_t mask16[16] = { @@ -464,6 +468,7 @@ { int i; int sign = p->df ? -1 : 1; + p2m_type_t p2mt; if ( p->data_is_ptr ) { @@ -473,7 +478,17 @@ for ( i = 0; i < p->count; i++ ) { tmp = stdvga_mem_read(addr, p->size); - hvm_copy_to_guest_phys(data, &tmp, p->size); + if (hvm_copy_to_guest_phys(data, &tmp, p->size) == HVMCOPY_bad_gfn_to_mfn) + { + (void) gfn_to_mfn_current((data >> PAGE_SHIFT), &p2mt); + /* The only case we handle is vga_mem<->vga_mem. Anything else will cause + the caching to get turned off and the oddball mmios to get handed off to + the ioemu, which will hopefully be able to deal with it */ + if ( p2mt == p2m_mmio_dm && data >= VGA_MEM_BASE && data <= VGA_MEM_BASE + VGA_MEM_SIZE ) + stdvga_mem_write(data, tmp, p->size); + else + return 0; + } data += sign * p->size; addr += sign * p->size; } @@ -483,7 +498,14 @@ uint32_t addr = p->addr, data = p->data, tmp; for ( i = 0; i < p->count; i++ ) { - hvm_copy_from_guest_phys(&tmp, data, p->size); + if (hvm_copy_from_guest_phys(&tmp, data, p->size) == HVMCOPY_bad_gfn_to_mfn) + { + (void) gfn_to_mfn_current(data >> PAGE_SHIFT, &p2mt); + if ( p2mt == p2m_mmio_dm && data >= VGA_MEM_BASE && data <= VGA_MEM_BASE + VGA_MEM_SIZE ) + tmp = stdvga_mem_read(data, p->size); + else + return 0; + } stdvga_mem_write(addr, tmp, p->size); data += sign * p->size; addr += sign * p->size; @@ -536,6 +558,18 @@ { case IOREQ_TYPE_COPY: buf = mmio_move(s, p); + if (!buf) + { + gdprintk(XENLOG_WARNING,"mmio could not be handled: " + "addr:0x%04x data:0x%04x size:%d count:%d state:%d " + "isptr:%d dir:%d df:%d\n", + (int)p->addr, (int)p->data, (int)p->size, + (int)p->count, p->state, + p->data_is_ptr, p->dir, p->df); + s->cache = 0; + spin_unlock(&s->lock); + return X86EMUL_UNHANDLEABLE; + } break; default: gdprintk(XENLOG_WARNING, "unsupported mmio request type:%d " @@ -588,7 +622,7 @@ register_portio_handler(d, 0x3ce, 2, stdvga_intercept_pio); /* MMIO. */ register_buffered_io_handler( - d, 0xa0000, 0x20000, stdvga_intercept_mmio); + d, VGA_MEM_BASE, VGA_MEM_SIZE, stdvga_intercept_mmio); } }