From 6742db6e6819687ab311199bfe76476947ed75ed Mon Sep 17 00:00:00 2001 From: Keir Fraser Date: Tue, 15 Apr 2008 13:28:02 +0100 Subject: x86, hvm: I/O emulation handlers return X86EMUL_* return codes. Signed-off-by: Keir Fraser --- xen/arch/x86/hvm/emulate.c | 73 +++++++++++++-------- xen/arch/x86/hvm/hpet.c | 21 ++++-- xen/arch/x86/hvm/hvm.c | 2 +- xen/arch/x86/hvm/i8254.c | 12 ++-- xen/arch/x86/hvm/intercept.c | 149 +++++++++++++++++++++++-------------------- xen/arch/x86/hvm/io.c | 61 +++++++----------- xen/arch/x86/hvm/pmtimer.c | 8 +-- xen/arch/x86/hvm/rtc.c | 8 +-- xen/arch/x86/hvm/stdvga.c | 22 +++---- xen/arch/x86/hvm/vioapic.c | 21 +++--- xen/arch/x86/hvm/vlapic.c | 26 ++++---- xen/arch/x86/hvm/vpic.c | 12 ++-- xen/include/asm-x86/hvm/io.h | 21 +++--- 13 files changed, 232 insertions(+), 204 deletions(-) diff --git a/xen/arch/x86/hvm/emulate.c b/xen/arch/x86/hvm/emulate.c index 46aebf951b..036583d90c 100644 --- a/xen/arch/x86/hvm/emulate.c +++ b/xen/arch/x86/hvm/emulate.c @@ -20,12 +20,13 @@ #include static int hvmemul_do_io( - int is_mmio, paddr_t addr, unsigned long count, int size, + int is_mmio, paddr_t addr, unsigned long *reps, int size, paddr_t value, int dir, int df, int value_is_ptr, unsigned long *val) { struct vcpu *curr = current; vcpu_iodata_t *vio = get_ioreq(curr); ioreq_t *p = &vio->vp_ioreq; + int rc; switch ( curr->arch.hvm_vcpu.io_state ) { @@ -56,40 +57,58 @@ static int hvmemul_do_io( p->type = is_mmio ? IOREQ_TYPE_COPY : IOREQ_TYPE_PIO; p->size = size; p->addr = addr; - p->count = count; + p->count = *reps; p->df = df; p->data = value; p->io_count++; - if ( is_mmio - ? (hvm_mmio_intercept(p) || hvm_buffered_io_intercept(p)) - : hvm_portio_intercept(p) ) + if ( is_mmio ) + { + rc = hvm_mmio_intercept(p); + if ( rc == X86EMUL_UNHANDLEABLE ) + rc = hvm_buffered_io_intercept(p); + } + else + { + rc = hvm_portio_intercept(p); + } + + switch ( rc ) { + case X86EMUL_OKAY: + *reps = p->count; p->state = STATE_IORESP_READY; hvm_io_assist(); if ( val != NULL ) *val = curr->arch.hvm_vcpu.io_data; curr->arch.hvm_vcpu.io_state = HVMIO_none; - return X86EMUL_OKAY; + break; + case X86EMUL_UNHANDLEABLE: + hvm_send_assist_req(curr); + rc = (val != NULL) ? X86EMUL_RETRY : X86EMUL_OKAY; + break; + case X86EMUL_RETRY: + break; + default: + BUG(); } - hvm_send_assist_req(curr); - return (val != NULL) ? X86EMUL_RETRY : X86EMUL_OKAY; + return rc; } static int hvmemul_do_pio( - unsigned long port, unsigned long count, int size, + unsigned long port, unsigned long *reps, int size, paddr_t value, int dir, int df, int value_is_ptr, unsigned long *val) { - return hvmemul_do_io(0, port, count, size, value, + return hvmemul_do_io(0, port, reps, size, value, dir, df, value_is_ptr, val); } static int hvmemul_do_mmio( - paddr_t gpa, unsigned long count, int size, + paddr_t gpa, unsigned long *reps, int size, paddr_t value, int dir, int df, int value_is_ptr, unsigned long *val) { - return hvmemul_do_io(1, gpa, count, size, value, + return hvmemul_do_io(1, gpa, reps, size, value, dir, df, value_is_ptr, val); } @@ -209,7 +228,7 @@ static int __hvmemul_read( struct hvm_emulate_ctxt *hvmemul_ctxt) { struct vcpu *curr = current; - unsigned long addr; + unsigned long addr, reps = 1; uint32_t pfec = PFEC_page_present; paddr_t gpa; int rc; @@ -229,7 +248,8 @@ static int __hvmemul_read( return X86EMUL_UNHANDLEABLE; gpa = (((paddr_t)curr->arch.hvm_vcpu.mmio_gpfn << PAGE_SHIFT) | off); if ( (off + bytes) <= PAGE_SIZE ) - return hvmemul_do_mmio(gpa, 1, bytes, 0, IOREQ_READ, 0, 0, val); + return hvmemul_do_mmio(gpa, &reps, bytes, 0, + IOREQ_READ, 0, 0, val); } if ( (seg != x86_seg_none) && @@ -254,7 +274,7 @@ static int __hvmemul_read( if ( rc != X86EMUL_OKAY ) return rc; - return hvmemul_do_mmio(gpa, 1, bytes, 0, IOREQ_READ, 0, 0, val); + return hvmemul_do_mmio(gpa, &reps, bytes, 0, IOREQ_READ, 0, 0, val); } return X86EMUL_OKAY; @@ -305,7 +325,7 @@ static int hvmemul_write( struct hvm_emulate_ctxt *hvmemul_ctxt = container_of(ctxt, struct hvm_emulate_ctxt, ctxt); struct vcpu *curr = current; - unsigned long addr; + unsigned long addr, reps = 1; uint32_t pfec = PFEC_page_present | PFEC_write_access; paddr_t gpa; int rc; @@ -321,8 +341,8 @@ static int hvmemul_write( unsigned int off = addr & (PAGE_SIZE - 1); gpa = (((paddr_t)curr->arch.hvm_vcpu.mmio_gpfn << PAGE_SHIFT) | off); if ( (off + bytes) <= PAGE_SIZE ) - return hvmemul_do_mmio(gpa, 1, bytes, val, IOREQ_WRITE, - 0, 0, NULL); + return hvmemul_do_mmio(gpa, &reps, bytes, val, + IOREQ_WRITE, 0, 0, NULL); } if ( (seg != x86_seg_none) && @@ -342,7 +362,8 @@ static int hvmemul_write( if ( rc != X86EMUL_OKAY ) return rc; - return hvmemul_do_mmio(gpa, 1, bytes, val, IOREQ_WRITE, 0, 0, NULL); + return hvmemul_do_mmio(gpa, &reps, bytes, val, + IOREQ_WRITE, 0, 0, NULL); } return X86EMUL_OKAY; @@ -389,7 +410,7 @@ static int hvmemul_rep_ins( if ( rc != X86EMUL_OKAY ) return rc; - return hvmemul_do_pio(src_port, *reps, bytes_per_rep, gpa, IOREQ_READ, + return hvmemul_do_pio(src_port, reps, bytes_per_rep, gpa, IOREQ_READ, !!(ctxt->regs->eflags & X86_EFLAGS_DF), 1, NULL); } @@ -422,7 +443,7 @@ static int hvmemul_rep_outs( if ( rc != X86EMUL_OKAY ) return rc; - return hvmemul_do_pio(dst_port, *reps, bytes_per_rep, gpa, IOREQ_WRITE, + return hvmemul_do_pio(dst_port, reps, bytes_per_rep, gpa, IOREQ_WRITE, !!(ctxt->regs->eflags & X86_EFLAGS_DF), 1, NULL); } @@ -472,14 +493,14 @@ static int hvmemul_rep_movs( (void)gfn_to_mfn_current(sgpa >> PAGE_SHIFT, &p2mt); if ( !p2m_is_ram(p2mt) ) return hvmemul_do_mmio( - sgpa, *reps, bytes_per_rep, dgpa, IOREQ_READ, + sgpa, reps, bytes_per_rep, dgpa, IOREQ_READ, !!(ctxt->regs->eflags & X86_EFLAGS_DF), 1, NULL); (void)gfn_to_mfn_current(dgpa >> PAGE_SHIFT, &p2mt); if ( p2m_is_ram(p2mt) ) return X86EMUL_UNHANDLEABLE; return hvmemul_do_mmio( - dgpa, *reps, bytes_per_rep, sgpa, IOREQ_WRITE, + dgpa, reps, bytes_per_rep, sgpa, IOREQ_WRITE, !!(ctxt->regs->eflags & X86_EFLAGS_DF), 1, NULL); } @@ -516,7 +537,8 @@ static int hvmemul_read_io( unsigned long *val, struct x86_emulate_ctxt *ctxt) { - return hvmemul_do_pio(port, 1, bytes, 0, IOREQ_READ, 0, 0, val); + unsigned long reps = 1; + return hvmemul_do_pio(port, &reps, bytes, 0, IOREQ_READ, 0, 0, val); } static int hvmemul_write_io( @@ -525,7 +547,8 @@ static int hvmemul_write_io( unsigned long val, struct x86_emulate_ctxt *ctxt) { - return hvmemul_do_pio(port, 1, bytes, val, IOREQ_WRITE, 0, 0, NULL); + unsigned long reps = 1; + return hvmemul_do_pio(port, &reps, bytes, val, IOREQ_WRITE, 0, 0, NULL); } static int hvmemul_read_cr( diff --git a/xen/arch/x86/hvm/hpet.c b/xen/arch/x86/hvm/hpet.c index 49ca998d37..03dfbf3bd8 100644 --- a/xen/arch/x86/hvm/hpet.c +++ b/xen/arch/x86/hvm/hpet.c @@ -150,8 +150,9 @@ static inline uint64_t hpet_read_maincounter(HPETState *h) return h->hpet.mc64; } -static unsigned long hpet_read( - struct vcpu *v, unsigned long addr, unsigned long length) +static int hpet_read( + struct vcpu *v, unsigned long addr, unsigned long length, + unsigned long *pval) { HPETState *h = &v->domain->arch.hvm_domain.pl_time.vhpet; unsigned long result; @@ -160,7 +161,10 @@ static unsigned long hpet_read( addr &= HPET_MMAP_SIZE-1; if ( hpet_check_access_length(addr, length) != 0 ) - return ~0UL; + { + result = ~0ul; + goto out; + } spin_lock(&h->lock); @@ -174,7 +178,9 @@ static unsigned long hpet_read( spin_unlock(&h->lock); - return result; + out: + *pval = result; + return X86EMUL_OKAY; } static void hpet_stop_timer(HPETState *h, unsigned int tn) @@ -234,7 +240,7 @@ static inline uint64_t hpet_fixup_reg( return new; } -static void hpet_write( +static int hpet_write( struct vcpu *v, unsigned long addr, unsigned long length, unsigned long val) { @@ -245,7 +251,7 @@ static void hpet_write( addr &= HPET_MMAP_SIZE-1; if ( hpet_check_access_length(addr, length) != 0 ) - return; + goto out; spin_lock(&h->lock); @@ -349,6 +355,9 @@ static void hpet_write( } spin_unlock(&h->lock); + + out: + return X86EMUL_OKAY; } static int hpet_range(struct vcpu *v, unsigned long addr) diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c index 3730710346..74c8d43e41 100644 --- a/xen/arch/x86/hvm/hvm.c +++ b/xen/arch/x86/hvm/hvm.c @@ -277,7 +277,7 @@ static int hvm_print_line( } spin_unlock(&hd->pbuf_lock); - return 1; + return X86EMUL_OKAY; } int hvm_domain_initialise(struct domain *d) diff --git a/xen/arch/x86/hvm/i8254.c b/xen/arch/x86/hvm/i8254.c index 3cfd9dd47e..493b7317b9 100644 --- a/xen/arch/x86/hvm/i8254.c +++ b/xen/arch/x86/hvm/i8254.c @@ -487,7 +487,7 @@ static int handle_pit_io( if ( bytes != 1 ) { gdprintk(XENLOG_WARNING, "PIT bad access\n"); - return 1; + return X86EMUL_OKAY; } if ( dir == IOREQ_WRITE ) @@ -502,7 +502,7 @@ static int handle_pit_io( gdprintk(XENLOG_WARNING, "PIT: read A1:A0=3!\n"); } - return 1; + return X86EMUL_OKAY; } static void speaker_ioport_write( @@ -526,11 +526,7 @@ static int handle_speaker_io( { struct PITState *vpit = vcpu_vpit(current); - if ( bytes != 1 ) - { - gdprintk(XENLOG_WARNING, "PIT_SPEAKER bad access\n"); - return 1; - } + BUG_ON(bytes != 1); spin_lock(&vpit->lock); @@ -541,7 +537,7 @@ static int handle_speaker_io( spin_unlock(&vpit->lock); - return 1; + return X86EMUL_OKAY; } int pv_pit_handler(int port, int data, int write) diff --git a/xen/arch/x86/hvm/intercept.c b/xen/arch/x86/hvm/intercept.c index 8084214d1f..0e110e00dc 100644 --- a/xen/arch/x86/hvm/intercept.c +++ b/xen/arch/x86/hvm/intercept.c @@ -45,53 +45,63 @@ static struct hvm_mmio_handler *hvm_mmio_handlers[HVM_MMIO_HANDLER_NR] = &vioapic_mmio_handler }; -static inline void hvm_mmio_access(struct vcpu *v, - ioreq_t *p, - hvm_mmio_read_t read_handler, - hvm_mmio_write_t write_handler) +static int hvm_mmio_access(struct vcpu *v, + ioreq_t *p, + hvm_mmio_read_t read_handler, + hvm_mmio_write_t write_handler) { unsigned long data; + int rc = X86EMUL_OKAY, i, sign = p->df ? -1 : 1; if ( !p->data_is_ptr ) { if ( p->dir == IOREQ_READ ) - p->data = read_handler(v, p->addr, p->size); - else /* p->dir == IOREQ_WRITE */ - write_handler(v, p->addr, p->size, p->data); + { + rc = read_handler(v, p->addr, p->size, &data); + p->data = data; + } + else /* p->dir == IOREQ_WRITE */ + rc = write_handler(v, p->addr, p->size, p->data); + return rc; } - else - { - int i, sign = (p->df) ? -1 : 1; - if ( p->dir == IOREQ_READ ) + if ( p->dir == IOREQ_READ ) + { + for ( i = 0; i < p->count; i++ ) { - for ( i = 0; i < p->count; i++ ) - { - data = read_handler( - v, - p->addr + (sign * i * p->size), - p->size); - (void)hvm_copy_to_guest_phys( - p->data + (sign * i * p->size), - &data, - p->size); - } + rc = read_handler( + v, + p->addr + (sign * i * p->size), + p->size, &data); + if ( rc != X86EMUL_OKAY ) + break; + (void)hvm_copy_to_guest_phys( + p->data + (sign * i * p->size), + &data, + p->size); } - else + } + else + { + for ( i = 0; i < p->count; i++ ) { - for ( i = 0; i < p->count; i++ ) - { - (void)hvm_copy_from_guest_phys( - &data, - p->data + (sign * i * p->size), - p->size); - write_handler( - v, - p->addr + (sign * i * p->size), - p->size, data); - } + (void)hvm_copy_from_guest_phys( + &data, + p->data + (sign * i * p->size), + p->size); + rc = write_handler( + v, + p->addr + (sign * i * p->size), + p->size, data); + if ( rc != X86EMUL_OKAY ) + break; } } + + if ( (p->count = i) != 0 ) + rc = X86EMUL_OKAY; + + return rc; } int hvm_mmio_intercept(ioreq_t *p) @@ -100,60 +110,62 @@ int hvm_mmio_intercept(ioreq_t *p) int i; for ( i = 0; i < HVM_MMIO_HANDLER_NR; i++ ) - { if ( hvm_mmio_handlers[i]->check_handler(v, p->addr) ) - { - hvm_mmio_access(v, p, - hvm_mmio_handlers[i]->read_handler, - hvm_mmio_handlers[i]->write_handler); - return 1; - } - } + return hvm_mmio_access( + v, p, + hvm_mmio_handlers[i]->read_handler, + hvm_mmio_handlers[i]->write_handler); - return 0; + return X86EMUL_UNHANDLEABLE; } static int process_portio_intercept(portio_action_t action, ioreq_t *p) { - int rc = 1, i, sign = p->df ? -1 : 1; + int rc = X86EMUL_OKAY, i, sign = p->df ? -1 : 1; uint32_t data; - if ( p->dir == IOREQ_READ ) + if ( !p->data_is_ptr ) { - if ( !p->data_is_ptr ) + if ( p->dir == IOREQ_READ ) { rc = action(IOREQ_READ, p->addr, p->size, &data); p->data = data; } else { - for ( i = 0; i < p->count; i++ ) - { - rc = action(IOREQ_READ, p->addr, p->size, &data); - (void)hvm_copy_to_guest_phys(p->data + sign*i*p->size, - &data, p->size); - } + data = p->data; + rc = action(IOREQ_WRITE, p->addr, p->size, &data); } + return rc; } - else /* p->dir == IOREQ_WRITE */ + + if ( p->dir == IOREQ_READ ) { - if ( !p->data_is_ptr ) + for ( i = 0; i < p->count; i++ ) { - data = p->data; - rc = action(IOREQ_WRITE, p->addr, p->size, &data); + rc = action(IOREQ_READ, p->addr, p->size, &data); + if ( rc != X86EMUL_OKAY ) + break; + (void)hvm_copy_to_guest_phys(p->data + sign*i*p->size, + &data, p->size); } - else + } + else /* p->dir == IOREQ_WRITE */ + { + for ( i = 0; i < p->count; i++ ) { - for ( i = 0; i < p->count; i++ ) - { - data = 0; - (void)hvm_copy_from_guest_phys(&data, p->data + sign*i*p->size, - p->size); - rc = action(IOREQ_WRITE, p->addr, p->size, &data); - } + data = 0; + (void)hvm_copy_from_guest_phys(&data, p->data + sign*i*p->size, + p->size); + rc = action(IOREQ_WRITE, p->addr, p->size, &data); + if ( rc != X86EMUL_OKAY ) + break; } } + if ( (p->count = i) != 0 ) + rc = X86EMUL_OKAY; + return rc; } @@ -170,7 +182,7 @@ int hvm_io_intercept(ioreq_t *p, int type) unsigned long addr, size; if ( (type == HVM_PORTIO) && (dpci_ioport_intercept(p)) ) - return 1; + return X86EMUL_OKAY; for ( i = 0; i < handler->num_slot; i++ ) { @@ -188,10 +200,10 @@ int hvm_io_intercept(ioreq_t *p, int type) } } - return 0; + return X86EMUL_UNHANDLEABLE; } -int register_io_handler( +void register_io_handler( struct domain *d, unsigned long addr, unsigned long size, void *action, int type) { @@ -207,9 +219,8 @@ int register_io_handler( else handler->hdl_list[num].action.mmio = action; handler->num_slot++; - - return 1; } + /* * Local variables: * mode: C diff --git a/xen/arch/x86/hvm/io.c b/xen/arch/x86/hvm/io.c index 9ff2958ca7..6a8e0885c0 100644 --- a/xen/arch/x86/hvm/io.c +++ b/xen/arch/x86/hvm/io.c @@ -246,74 +246,59 @@ void hvm_io_assist(void) void dpci_ioport_read(uint32_t mport, ioreq_t *p) { - uint64_t i; - uint64_t z_data; - uint64_t length = (p->count * p->size); + int i, sign = p->df ? -1 : 1; + uint32_t data = 0; - for ( i = 0; i < length; i += p->size ) + for ( i = 0; i < p->count; i++ ) { - z_data = ~0ULL; - switch ( p->size ) { case 1: - z_data = (uint64_t)inb(mport); + data = inb(mport); break; case 2: - z_data = (uint64_t)inw(mport); + data = inw(mport); break; case 4: - z_data = (uint64_t)inl(mport); + data = inl(mport); break; default: - gdprintk(XENLOG_ERR, "Error: unable to handle size: %" - PRId64 "\n", p->size); - return; + BUG(); } - p->data = z_data; - if ( p->data_is_ptr && - hvm_copy_to_guest_phys(p->data + i, (void *)&z_data, - (int)p->size) ) - { - gdprintk(XENLOG_ERR, "Error: couldn't copy to hvm phys\n"); - return; - } + if ( p->data_is_ptr ) + (void)hvm_copy_to_guest_phys( + p->data + (sign * i * p->size), &data, p->size); + else + p->data = data; } } void dpci_ioport_write(uint32_t mport, ioreq_t *p) { - uint64_t i; - uint64_t z_data = 0; - uint64_t length = (p->count * p->size); + int i, sign = p->df ? -1 : 1; + uint32_t data; - for ( i = 0; i < length; i += p->size ) + for ( i = 0; i < p->count; i++ ) { - z_data = p->data; - if ( p->data_is_ptr && - hvm_copy_from_guest_phys((void *)&z_data, - p->data + i, (int)p->size) ) - { - gdprintk(XENLOG_ERR, "Error: couldn't copy from hvm phys\n"); - return; - } + data = p->data; + if ( p->data_is_ptr ) + (void)hvm_copy_from_guest_phys( + &data, p->data + (sign * i & p->size), p->size); switch ( p->size ) { case 1: - outb((uint8_t) z_data, mport); + outb(data, mport); break; case 2: - outw((uint16_t) z_data, mport); + outw(data, mport); break; case 4: - outl((uint32_t) z_data, mport); + outl(data, mport); break; default: - gdprintk(XENLOG_ERR, "Error: unable to handle size: %" - PRId64 "\n", p->size); - break; + BUG(); } } } diff --git a/xen/arch/x86/hvm/pmtimer.c b/xen/arch/x86/hvm/pmtimer.c index 8d3fff8f44..4924a80687 100644 --- a/xen/arch/x86/hvm/pmtimer.c +++ b/xen/arch/x86/hvm/pmtimer.c @@ -169,7 +169,7 @@ static int handle_evt_io( spin_unlock(&s->lock); - return 1; + return X86EMUL_OKAY; } @@ -183,7 +183,7 @@ static int handle_pmt_io( if ( bytes != 4 ) { gdprintk(XENLOG_WARNING, "HVM_PMT bad access\n"); - return 1; + return X86EMUL_OKAY; } if ( dir == IOREQ_READ ) @@ -192,10 +192,10 @@ static int handle_pmt_io( pmt_update_time(s); *val = s->pm.tmr_val; spin_unlock(&s->lock); - return 1; + return X86EMUL_OKAY; } - return 0; + return X86EMUL_UNHANDLEABLE; } static int pmtimer_save(struct domain *d, hvm_domain_context_t *h) diff --git a/xen/arch/x86/hvm/rtc.c b/xen/arch/x86/hvm/rtc.c index b9e4b4a241..e196c72866 100644 --- a/xen/arch/x86/hvm/rtc.c +++ b/xen/arch/x86/hvm/rtc.c @@ -403,21 +403,21 @@ static int handle_rtc_io( if ( bytes != 1 ) { gdprintk(XENLOG_WARNING, "HVM_RTC bas access\n"); - return 1; + return X86EMUL_OKAY; } if ( dir == IOREQ_WRITE ) { if ( rtc_ioport_write(vrtc, port, (uint8_t)*val) ) - return 1; + return X86EMUL_OKAY; } else if ( vrtc->hw.cmos_index < RTC_CMOS_SIZE ) { *val = rtc_ioport_read(vrtc, port); - return 1; + return X86EMUL_OKAY; } - return 0; + return X86EMUL_UNHANDLEABLE; } void rtc_migrate_timers(struct vcpu *v) diff --git a/xen/arch/x86/hvm/stdvga.c b/xen/arch/x86/hvm/stdvga.c index 514444cc34..25b16bddac 100644 --- a/xen/arch/x86/hvm/stdvga.c +++ b/xen/arch/x86/hvm/stdvga.c @@ -167,19 +167,19 @@ static void stdvga_out(uint32_t port, uint32_t bytes, uint32_t val) } } -int stdvga_intercept_pio( +static int stdvga_intercept_pio( int dir, uint32_t port, uint32_t bytes, uint32_t *val) { struct hvm_hw_stdvga *s = ¤t->domain->arch.hvm_domain.stdvga; - if ( dir == IOREQ_READ ) - return 0; - - spin_lock(&s->lock); - stdvga_out(port, bytes, *val); - spin_unlock(&s->lock); + if ( dir == IOREQ_WRITE ) + { + spin_lock(&s->lock); + stdvga_out(port, bytes, *val); + spin_unlock(&s->lock); + } - return 0; /* propagate to external ioemu */ + return X86EMUL_UNHANDLEABLE; /* propagate to external ioemu */ } #define GET_PLANE(data, p) (((data) >> ((p) * 8)) & 0xff) @@ -459,7 +459,7 @@ static int mmio_move(struct hvm_hw_stdvga *s, ioreq_t *p) return 1; } -int stdvga_intercept_mmio(ioreq_t *p) +static int stdvga_intercept_mmio(ioreq_t *p) { struct domain *d = current->domain; struct hvm_hw_stdvga *s = &d->arch.hvm_domain.stdvga; @@ -468,7 +468,7 @@ int stdvga_intercept_mmio(ioreq_t *p) if ( p->size > 8 ) { gdprintk(XENLOG_WARNING, "invalid mmio size %d\n", (int)p->size); - return 0; + return X86EMUL_UNHANDLEABLE; } spin_lock(&s->lock); @@ -499,7 +499,7 @@ int stdvga_intercept_mmio(ioreq_t *p) spin_unlock(&s->lock); - return rc; + return rc ? X86EMUL_OKAY : X86EMUL_UNHANDLEABLE; } void stdvga_init(struct domain *d) diff --git a/xen/arch/x86/hvm/vioapic.c b/xen/arch/x86/hvm/vioapic.c index fbdfe0c931..8ebaa260cf 100644 --- a/xen/arch/x86/hvm/vioapic.c +++ b/xen/arch/x86/hvm/vioapic.c @@ -88,9 +88,9 @@ static unsigned long vioapic_read_indirect(struct hvm_hw_vioapic *vioapic, return result; } -static unsigned long vioapic_read(struct vcpu *v, - unsigned long addr, - unsigned long length) +static int vioapic_read( + struct vcpu *v, unsigned long addr, + unsigned long length, unsigned long *pval) { struct hvm_hw_vioapic *vioapic = domain_vioapic(v->domain); uint32_t result; @@ -114,11 +114,13 @@ static unsigned long vioapic_read(struct vcpu *v, break; } - return result; + *pval = result; + return X86EMUL_OKAY; } static void vioapic_write_redirent( - struct hvm_hw_vioapic *vioapic, unsigned int idx, int top_word, uint32_t val) + struct hvm_hw_vioapic *vioapic, unsigned int idx, + int top_word, uint32_t val) { struct domain *d = vioapic_domain(vioapic); struct hvm_irq *hvm_irq = &d->arch.hvm_domain.irq; @@ -196,10 +198,9 @@ static void vioapic_write_indirect( } } -static void vioapic_write(struct vcpu *v, - unsigned long addr, - unsigned long length, - unsigned long val) +static int vioapic_write( + struct vcpu *v, unsigned long addr, + unsigned long length, unsigned long val) { struct hvm_hw_vioapic *vioapic = domain_vioapic(v->domain); @@ -224,6 +225,8 @@ static void vioapic_write(struct vcpu *v, default: break; } + + return X86EMUL_OKAY; } static int vioapic_range(struct vcpu *v, unsigned long addr) diff --git a/xen/arch/x86/hvm/vlapic.c b/xen/arch/x86/hvm/vlapic.c index d66e3c26cf..424ee4dd5d 100644 --- a/xen/arch/x86/hvm/vlapic.c +++ b/xen/arch/x86/hvm/vlapic.c @@ -466,17 +466,18 @@ static void vlapic_read_aligned( } } -static unsigned long vlapic_read(struct vcpu *v, unsigned long address, - unsigned long len) +static int vlapic_read( + struct vcpu *v, unsigned long address, + unsigned long len, unsigned long *pval) { unsigned int alignment; unsigned int tmp; - unsigned long result; + unsigned long result = 0; struct vlapic *vlapic = vcpu_vlapic(v); unsigned int offset = address - vlapic_base_address(vlapic); if ( offset > (APIC_TDCR + 0x3) ) - return 0; + goto out; alignment = offset & 0x3; @@ -508,14 +509,16 @@ static unsigned long vlapic_read(struct vcpu *v, unsigned long address, HVM_DBG_LOG(DBG_LEVEL_VLAPIC, "offset 0x%x with length 0x%lx, " "and the result is 0x%lx", offset, len, result); - return result; + out: + *pval = result; + return X86EMUL_OKAY; unaligned_exit_and_crash: gdprintk(XENLOG_ERR, "Unaligned LAPIC read len=0x%lx at offset=0x%x.\n", len, offset); exit_and_crash: domain_crash(v->domain); - return 0; + return X86EMUL_OKAY; } void vlapic_pt_cb(struct vcpu *v, void *data) @@ -523,8 +526,8 @@ void vlapic_pt_cb(struct vcpu *v, void *data) *(s_time_t *)data = hvm_get_guest_time(v); } -static void vlapic_write(struct vcpu *v, unsigned long address, - unsigned long len, unsigned long val) +static int vlapic_write(struct vcpu *v, unsigned long address, + unsigned long len, unsigned long val) { struct vlapic *vlapic = vcpu_vlapic(v); unsigned int offset = address - vlapic_base_address(vlapic); @@ -541,13 +544,13 @@ static void vlapic_write(struct vcpu *v, unsigned long address, val = (uint32_t)val; if ( len != 4 ) { - unsigned int tmp; + unsigned long tmp; unsigned char alignment; gdprintk(XENLOG_INFO, "Notice: Local APIC write with len = %lx\n",len); alignment = offset & 0x3; - tmp = vlapic_read(v, offset & ~0x3, 4); + (void)vlapic_read(v, offset & ~0x3, 4, &tmp); switch ( len ) { @@ -670,13 +673,14 @@ static void vlapic_write(struct vcpu *v, unsigned long address, break; } - return; + return X86EMUL_OKAY; unaligned_exit_and_crash: gdprintk(XENLOG_ERR, "Unaligned LAPIC write len=0x%lx at offset=0x%x.\n", len, offset); exit_and_crash: domain_crash(v->domain); + return X86EMUL_OKAY; } static int vlapic_range(struct vcpu *v, unsigned long addr) diff --git a/xen/arch/x86/hvm/vpic.c b/xen/arch/x86/hvm/vpic.c index f7bc2eb34f..a3d6f2d9ca 100644 --- a/xen/arch/x86/hvm/vpic.c +++ b/xen/arch/x86/hvm/vpic.c @@ -319,7 +319,7 @@ static int vpic_intercept_pic_io( if ( bytes != 1 ) { gdprintk(XENLOG_WARNING, "PIC_IO bad access size %d\n", bytes); - return 1; + return X86EMUL_OKAY; } vpic = ¤t->domain->arch.hvm_domain.vpic[port >> 7]; @@ -329,7 +329,7 @@ static int vpic_intercept_pic_io( else *val = (uint8_t)vpic_ioport_read(vpic, port); - return 1; + return X86EMUL_OKAY; } static int vpic_intercept_elcr_io( @@ -338,11 +338,7 @@ static int vpic_intercept_elcr_io( struct hvm_hw_vpic *vpic; uint32_t data; - if ( bytes != 1 ) - { - gdprintk(XENLOG_WARNING, "PIC_IO bad access size %d\n", bytes); - return 1; - } + BUG_ON(bytes != 1); vpic = ¤t->domain->arch.hvm_domain.vpic[port & 1]; @@ -360,7 +356,7 @@ static int vpic_intercept_elcr_io( *val = vpic->elcr & vpic_elcr_mask(vpic); } - return 1; + return X86EMUL_OKAY; } static int vpic_save(struct domain *d, hvm_domain_context_t *h) diff --git a/xen/include/asm-x86/hvm/io.h b/xen/include/asm-x86/hvm/io.h index 9ef4f645a1..249fd2bcc3 100644 --- a/xen/include/asm-x86/hvm/io.h +++ b/xen/include/asm-x86/hvm/io.h @@ -30,13 +30,14 @@ #define HVM_PORTIO 0 #define HVM_BUFFERED_IO 2 -typedef unsigned long (*hvm_mmio_read_t)(struct vcpu *v, - unsigned long addr, - unsigned long length); -typedef void (*hvm_mmio_write_t)(struct vcpu *v, +typedef int (*hvm_mmio_read_t)(struct vcpu *v, unsigned long addr, unsigned long length, - unsigned long val); + unsigned long *val); +typedef int (*hvm_mmio_write_t)(struct vcpu *v, + unsigned long addr, + unsigned long length, + unsigned long val); typedef int (*hvm_mmio_check_t)(struct vcpu *v, unsigned long addr); typedef int (*portio_action_t)( @@ -64,7 +65,7 @@ struct hvm_mmio_handler { }; int hvm_io_intercept(ioreq_t *p, int type); -int register_io_handler( +void register_io_handler( struct domain *d, unsigned long addr, unsigned long size, void *action, int type); @@ -81,18 +82,18 @@ static inline int hvm_buffered_io_intercept(ioreq_t *p) int hvm_mmio_intercept(ioreq_t *p); int hvm_buffered_io_send(ioreq_t *p); -static inline int register_portio_handler( +static inline void register_portio_handler( struct domain *d, unsigned long addr, unsigned long size, portio_action_t action) { - return register_io_handler(d, addr, size, action, HVM_PORTIO); + register_io_handler(d, addr, size, action, HVM_PORTIO); } -static inline int register_buffered_io_handler( +static inline void register_buffered_io_handler( struct domain *d, unsigned long addr, unsigned long size, mmio_action_t action) { - return register_io_handler(d, addr, size, action, HVM_BUFFERED_IO); + register_io_handler(d, addr, size, action, HVM_BUFFERED_IO); } void send_timeoffset_req(unsigned long timeoff); -- cgit v1.2.3