diff -r 56b42d68518e xen/arch/x86/hvm/i8254.c --- a/xen/arch/x86/hvm/i8254.c Thu Jan 10 22:53:43 2008 +0000 +++ b/xen/arch/x86/hvm/i8254.c Fri Jan 11 14:00:29 2008 +0100 @@ -527,24 +527,46 @@ void pit_deinit(struct domain *d) /* the intercept action for PIT DM retval:0--not handled; 1--handled */ static int handle_pit_io(ioreq_t *p) { + uint32_t value; struct PITState *vpit = vcpu_vpit(current); - if ( (p->size != 1) || p->data_is_ptr || (p->type != IOREQ_TYPE_PIO) ) + if ( (p->size != 1) || (p->type != IOREQ_TYPE_PIO) || (p->count > 4) ) { gdprintk(XENLOG_WARNING, "PIT bad access\n"); return 1; } - if ( p->dir == IOREQ_WRITE ) - { - pit_ioport_write(vpit, p->addr, p->data); - } - else - { - if ( (p->addr & 3) != 3 ) - p->data = pit_ioport_read(vpit, p->addr); + switch (p->dir) { + case IOREQ_WRITE: + + if ( p->data_is_ptr ) + hvm_copy_from_guest_phys(&value, p->data, p->size * p->count); else + value = p->data; + + pit_ioport_write(vpit, p->addr, value); + break; + + case IOREQ_READ: + + if ( !((p->addr & 3) != 3) ) { gdprintk(XENLOG_WARNING, "PIT: read A1:A0=3!\n"); + return 1; + } + + value = pit_ioport_read(vpit, p->addr); + + if ( p->data_is_ptr ) { + hvm_copy_to_guest_phys(p->data, &value, p->size * p->count); + } else + p->data = value; + + break; + + default: + /* Unknown/Invalid operation */ + gdprintk(XENLOG_ERR, "PIT access: p->dir: %d\n", p->dir); + BUG(); } return 1;