diff options
author | kfraser@localhost.localdomain <kfraser@localhost.localdomain> | 2006-10-15 09:15:51 +0100 |
---|---|---|
committer | kfraser@localhost.localdomain <kfraser@localhost.localdomain> | 2006-10-15 09:15:51 +0100 |
commit | b2e0105ec94258ba525034d4e30d5e6a8bf390c0 (patch) | |
tree | ffdf655b26d9e5feb0f0dc48f5362964b1520499 | |
parent | ad5b45d12e6b55689692dd6bc2dc6fdfefc18938 (diff) | |
download | xen-b2e0105ec94258ba525034d4e30d5e6a8bf390c0.tar.gz xen-b2e0105ec94258ba525034d4e30d5e6a8bf390c0.tar.bz2 xen-b2e0105ec94258ba525034d4e30d5e6a8bf390c0.zip |
[HVM] Fix PIC IO intercept: addresses are physical, not virtual.
Signed-off-by: Xiaohui Xin <xiaohui.xin@intel.com>
Signed-off-by: Xiaowei Yang <xiaowei.yang@intel.com>
Signed-off-by: Xin Li <xin.b.li@intel.com>
-rw-r--r-- | xen/arch/x86/hvm/i8259.c | 45 | ||||
-rw-r--r-- | xen/arch/x86/hvm/platform.c | 20 |
2 files changed, 33 insertions, 32 deletions
diff --git a/xen/arch/x86/hvm/i8259.c b/xen/arch/x86/hvm/i8259.c index e90f365044..d54e7ae146 100644 --- a/xen/arch/x86/hvm/i8259.c +++ b/xen/arch/x86/hvm/i8259.c @@ -498,19 +498,19 @@ void pic_init(struct hvm_virpic *s, void (*irq_request)(void *, int), static int intercept_pic_io(ioreq_t *p) { - struct hvm_virpic *pic; - struct vcpu *v = current; + struct hvm_virpic *pic; uint32_t data; unsigned long flags; - - if ( p->size != 1 || p->count != 1) { + + if ( p->size != 1 || p->count != 1 ) { printk("PIC_IO wrong access size %d!\n", (int)p->size); return 1; } - pic = &v->domain->arch.hvm_domain.vpic; - if ( p->dir == 0 ) { - if (p->pdata_valid) - (void)hvm_copy_from_guest_virt( + + pic = ¤t->domain->arch.hvm_domain.vpic; + if ( p->dir == IOREQ_WRITE ) { + if ( p->pdata_valid ) + (void)hvm_copy_from_guest_phys( &data, (unsigned long)p->u.pdata, p->size); else data = p->u.data; @@ -524,10 +524,10 @@ static int intercept_pic_io(ioreq_t *p) data = pic_ioport_read( (void*)&pic->pics[p->addr>>7], (uint32_t) p->addr); spin_unlock_irqrestore(&pic->lock, flags); - if (p->pdata_valid) - (void)hvm_copy_to_guest_virt( + if ( p->pdata_valid ) + (void)hvm_copy_to_guest_phys( (unsigned long)p->u.pdata, &data, p->size); - else + else p->u.data = (u64)data; } return 1; @@ -535,42 +535,41 @@ static int intercept_pic_io(ioreq_t *p) static int intercept_elcr_io(ioreq_t *p) { - struct hvm_virpic *s; - struct vcpu *v = current; + struct hvm_virpic *s; uint32_t data; unsigned long flags; - + if ( p->size != 1 || p->count != 1 ) { printk("PIC_IO wrong access size %d!\n", (int)p->size); return 1; } - s = &v->domain->arch.hvm_domain.vpic; - if ( p->dir == 0 ) { - if (p->pdata_valid) - (void)hvm_copy_from_guest_virt( + s = ¤t->domain->arch.hvm_domain.vpic; + if ( p->dir == IOREQ_WRITE ) { + if ( p->pdata_valid ) + (void)hvm_copy_from_guest_phys( &data, (unsigned long)p->u.pdata, p->size); else data = p->u.data; spin_lock_irqsave(&s->lock, flags); elcr_ioport_write((void*)&s->pics[p->addr&1], (uint32_t) p->addr, (uint32_t)( data & 0xff)); - get_sp(current->domain)->sp_global.pic_elcr = + get_sp(current->domain)->sp_global.pic_elcr = s->pics[0].elcr | ((u16)s->pics[1].elcr << 8); spin_unlock_irqrestore(&s->lock, flags); } else { data = (u64) elcr_ioport_read( (void*)&s->pics[p->addr&1], (uint32_t) p->addr); - if (p->pdata_valid) - (void)hvm_copy_to_guest_virt( + if ( p->pdata_valid ) + (void)hvm_copy_to_guest_phys( (unsigned long)p->u.pdata, &data, p->size); - else + else p->u.data = (u64)data; - } return 1; } + void register_pic_io_hook (void) { register_portio_handler(0x20, 2, intercept_pic_io); diff --git a/xen/arch/x86/hvm/platform.c b/xen/arch/x86/hvm/platform.c index 3440765269..a480c16675 100644 --- a/xen/arch/x86/hvm/platform.c +++ b/xen/arch/x86/hvm/platform.c @@ -730,13 +730,13 @@ void send_pio_req(struct cpu_user_regs *regs, unsigned long port, vcpu_iodata_t *vio; ioreq_t *p; - if (size == 0 || count == 0) { + if ( size == 0 || count == 0 ) { printf("null pio request? port %lx, count %lx, size %d, value %lx, dir %d, pvalid %d.\n", port, count, size, value, dir, pvalid); } vio = get_vio(v->domain, v->vcpu_id); - if (vio == NULL) { + if ( vio == NULL ) { printk("bad shared page: %lx\n", (unsigned long) vio); domain_crash_synchronous(); } @@ -745,6 +745,7 @@ void send_pio_req(struct cpu_user_regs *regs, unsigned long port, if ( p->state != STATE_INVALID ) printk("WARNING: send pio with something already pending (%d)?\n", p->state); + p->dir = dir; p->pdata_valid = pvalid; @@ -752,19 +753,20 @@ void send_pio_req(struct cpu_user_regs *regs, unsigned long port, p->size = size; p->addr = port; p->count = count; - p->df = regs->eflags & EF_DF ? 1 : 0; + p->df = regs->eflags & X86_EFLAGS_DF ? 1 : 0; p->io_count++; - if (pvalid) { - if (hvm_paging_enabled(current)) - p->u.data = shadow_gva_to_gpa(current, value); + if ( pvalid ) /* get physical address of data */ + { + if ( hvm_paging_enabled(current) ) + p->u.pdata = (void *)shadow_gva_to_gpa(current, value); else - p->u.pdata = (void *) value; /* guest VA == guest PA */ - } else + p->u.pdata = (void *)value; /* guest VA == guest PA */ + } else if ( dir == IOREQ_WRITE ) p->u.data = value; - if (hvm_portio_intercept(p)) { + if ( hvm_portio_intercept(p) ) { p->state = STATE_IORESP_READY; hvm_io_assist(v); return; |