aboutsummaryrefslogtreecommitdiffstats
path: root/xen
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2008-02-22 10:52:27 +0000
committerKeir Fraser <keir.fraser@citrix.com>2008-02-22 10:52:27 +0000
commitbfe958468352a53505c0445fbd16a61103a1319e (patch)
treeb048a0fdf62e5ecb9a67b8530f5454feff3fa23c /xen
parent7ef12531b88315fc53883c62c501931505b44a32 (diff)
downloadxen-bfe958468352a53505c0445fbd16a61103a1319e.tar.gz
xen-bfe958468352a53505c0445fbd16a61103a1319e.tar.bz2
xen-bfe958468352a53505c0445fbd16a61103a1319e.zip
x86 hvm: More emulation simplifications.
Signed-off-by: Keir Fraser <keir.fraser@citrix.com>
Diffstat (limited to 'xen')
-rw-r--r--xen/arch/x86/hvm/Makefile1
-rw-r--r--xen/arch/x86/hvm/emulate.c29
-rw-r--r--xen/arch/x86/hvm/hvm.c35
-rw-r--r--xen/arch/x86/hvm/intercept.c78
-rw-r--r--xen/arch/x86/hvm/io.c313
-rw-r--r--xen/arch/x86/hvm/platform.c273
-rw-r--r--xen/arch/x86/hvm/svm/emulate.c13
-rw-r--r--xen/arch/x86/hvm/svm/svm.c2
-rw-r--r--xen/arch/x86/hvm/vmx/realmode.c3
-rw-r--r--xen/include/asm-x86/hvm/io.h56
-rw-r--r--xen/include/asm-x86/hvm/vcpu.h5
11 files changed, 283 insertions, 525 deletions
diff --git a/xen/arch/x86/hvm/Makefile b/xen/arch/x86/hvm/Makefile
index 12db1da21a..a480d584ea 100644
--- a/xen/arch/x86/hvm/Makefile
+++ b/xen/arch/x86/hvm/Makefile
@@ -9,7 +9,6 @@ obj-y += io.o
obj-y += iommu.o
obj-y += irq.o
obj-y += mtrr.o
-obj-y += platform.o
obj-y += pmtimer.o
obj-y += rtc.o
obj-y += hpet.o
diff --git a/xen/arch/x86/hvm/emulate.c b/xen/arch/x86/hvm/emulate.c
index 752535ad10..f30c6fed1c 100644
--- a/xen/arch/x86/hvm/emulate.c
+++ b/xen/arch/x86/hvm/emulate.c
@@ -3,7 +3,7 @@
*
* HVM instruction emulation. Used for MMIO and VMX real mode.
*
- * Copyright (c) 2008 Citrix Systems, Inc.
+ * Copyright (c) 2008, Citrix Systems, Inc.
*
* Authors:
* Keir Fraser <keir.fraser@citrix.com>
@@ -310,18 +310,9 @@ static int hvmemul_rep_ins(
if ( curr->arch.hvm_vcpu.io_in_progress )
return X86EMUL_UNHANDLEABLE;
- if ( !curr->arch.hvm_vcpu.io_completed )
- {
- curr->arch.hvm_vcpu.io_in_progress = 1;
- send_pio_req(src_port, *reps, bytes_per_rep,
- gpa, IOREQ_READ,
- !!(ctxt->regs->eflags & X86_EFLAGS_DF), 1);
- }
-
- if ( !curr->arch.hvm_vcpu.io_completed )
- return X86EMUL_RETRY;
-
- curr->arch.hvm_vcpu.io_completed = 0;
+ curr->arch.hvm_vcpu.io_in_progress = 1;
+ send_pio_req(src_port, *reps, bytes_per_rep, gpa, IOREQ_READ,
+ !!(ctxt->regs->eflags & X86_EFLAGS_DF), 1);
return X86EMUL_OKAY;
}
@@ -408,18 +399,10 @@ static int hvmemul_rep_movs(
(void)gfn_to_mfn_current(sgpa >> PAGE_SHIFT, &p2mt);
if ( !p2m_is_ram(p2mt) )
{
- if ( !curr->arch.hvm_vcpu.io_completed )
- {
- curr->arch.hvm_vcpu.io_in_progress = 1;
- send_mmio_req(IOREQ_TYPE_COPY, sgpa, *reps, bytes_per_rep,
+ curr->arch.hvm_vcpu.io_in_progress = 1;
+ send_mmio_req(IOREQ_TYPE_COPY, sgpa, *reps, bytes_per_rep,
dgpa, IOREQ_READ,
!!(ctxt->regs->eflags & X86_EFLAGS_DF), 1);
- }
-
- if ( !curr->arch.hvm_vcpu.io_completed )
- return X86EMUL_RETRY;
-
- curr->arch.hvm_vcpu.io_completed = 0;
}
else
{
diff --git a/xen/arch/x86/hvm/hvm.c b/xen/arch/x86/hvm/hvm.c
index 22ffbb1bb9..82dc934c3f 100644
--- a/xen/arch/x86/hvm/hvm.c
+++ b/xen/arch/x86/hvm/hvm.c
@@ -3,7 +3,8 @@
*
* Copyright (c) 2004, Intel Corporation.
* Copyright (c) 2005, International Business Machines Corporation.
- *
+ * Copyright (c) 2008, Citrix Systems, Inc.
+ *
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
* version 2, as published by the Free Software Foundation.
@@ -1517,6 +1518,38 @@ enum hvm_copy_result hvm_fetch_from_guest_virt_nofault(
return __hvm_copy(buf, vaddr, size, 0, 1, hvm_nx_enabled(current));
}
+DEFINE_PER_CPU(int, guest_handles_in_xen_space);
+
+/* Note that copy_{to,from}_user_hvm require the PTE to be writable even
+ when they're only trying to read from it. The guest is expected to
+ deal with this. */
+unsigned long copy_to_user_hvm(void *to, const void *from, unsigned len)
+{
+ int rc;
+
+ if ( this_cpu(guest_handles_in_xen_space) )
+ {
+ memcpy(to, from, len);
+ return 0;
+ }
+
+ rc = hvm_copy_to_guest_virt_nofault((unsigned long)to, (void *)from, len);
+ return rc ? len : 0; /* fake a copy_to_user() return code */
+}
+
+unsigned long copy_from_user_hvm(void *to, const void *from, unsigned len)
+{
+ int rc;
+
+ if ( this_cpu(guest_handles_in_xen_space) )
+ {
+ memcpy(to, from, len);
+ return 0;
+ }
+
+ rc = hvm_copy_from_guest_virt_nofault(to, (unsigned long)from, len);
+ return rc ? len : 0; /* fake a copy_from_user() return code */
+}
/* HVM specific printbuf. Mostly used for hvmloader chit-chat. */
void hvm_print_line(struct vcpu *v, const char c)
diff --git a/xen/arch/x86/hvm/intercept.c b/xen/arch/x86/hvm/intercept.c
index e09d2991a0..e02a13001e 100644
--- a/xen/arch/x86/hvm/intercept.c
+++ b/xen/arch/x86/hvm/intercept.c
@@ -2,6 +2,7 @@
* intercept.c: Handle performance critical I/O packets in hypervisor space
*
* Copyright (c) 2004, Intel Corporation.
+ * Copyright (c) 2008, Citrix Systems, Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -93,83 +94,6 @@ static inline void hvm_mmio_access(struct vcpu *v,
}
}
-int hvm_buffered_io_send(ioreq_t *p)
-{
- struct vcpu *v = current;
- struct hvm_ioreq_page *iorp = &v->domain->arch.hvm_domain.buf_ioreq;
- buffered_iopage_t *pg = iorp->va;
- buf_ioreq_t bp;
- /* Timeoffset sends 64b data, but no address. Use two consecutive slots. */
- int qw = 0;
-
- /* Ensure buffered_iopage fits in a page */
- BUILD_BUG_ON(sizeof(buffered_iopage_t) > PAGE_SIZE);
-
- /*
- * Return 0 for the cases we can't deal with:
- * - 'addr' is only a 20-bit field, so we cannot address beyond 1MB
- * - we cannot buffer accesses to guest memory buffers, as the guest
- * may expect the memory buffer to be synchronously accessed
- * - the count field is usually used with data_is_ptr and since we don't
- * support data_is_ptr we do not waste space for the count field either
- */
- if ( (p->addr > 0xffffful) || p->data_is_ptr || (p->count != 1) )
- return 0;
-
- bp.type = p->type;
- bp.dir = p->dir;
- switch ( p->size )
- {
- case 1:
- bp.size = 0;
- break;
- case 2:
- bp.size = 1;
- break;
- case 4:
- bp.size = 2;
- break;
- case 8:
- bp.size = 3;
- qw = 1;
- break;
- default:
- gdprintk(XENLOG_WARNING, "unexpected ioreq size:%"PRId64"\n", p->size);
- return 0;
- }
-
- bp.data = p->data;
- bp.addr = p->addr;
-
- spin_lock(&iorp->lock);
-
- if ( (pg->write_pointer - pg->read_pointer) >=
- (IOREQ_BUFFER_SLOT_NUM - qw) )
- {
- /* The queue is full: send the iopacket through the normal path. */
- spin_unlock(&iorp->lock);
- return 0;
- }
-
- memcpy(&pg->buf_ioreq[pg->write_pointer % IOREQ_BUFFER_SLOT_NUM],
- &bp, sizeof(bp));
-
- if ( qw )
- {
- bp.data = p->data >> 32;
- memcpy(&pg->buf_ioreq[(pg->write_pointer+1) % IOREQ_BUFFER_SLOT_NUM],
- &bp, sizeof(bp));
- }
-
- /* Make the ioreq_t visible /before/ write_pointer. */
- wmb();
- pg->write_pointer += qw ? 2 : 1;
-
- spin_unlock(&iorp->lock);
-
- return 1;
-}
-
int hvm_mmio_intercept(ioreq_t *p)
{
struct vcpu *v = current;
diff --git a/xen/arch/x86/hvm/io.c b/xen/arch/x86/hvm/io.c
index 97ebfd0fff..48415c7690 100644
--- a/xen/arch/x86/hvm/io.c
+++ b/xen/arch/x86/hvm/io.c
@@ -3,6 +3,7 @@
*
* Copyright (c) 2004, Intel Corporation.
* Copyright (c) 2005, International Business Machines Corporation.
+ * Copyright (c) 2008, Citrix Systems, Inc.
*
* This program is free software; you can redistribute it and/or modify it
* under the terms and conditions of the GNU General Public License,
@@ -25,7 +26,6 @@
#include <xen/errno.h>
#include <xen/trace.h>
#include <xen/event.h>
-
#include <xen/hypercall.h>
#include <asm/current.h>
#include <asm/cpufeature.h>
@@ -41,79 +41,246 @@
#include <asm/hvm/vpic.h>
#include <asm/hvm/vlapic.h>
#include <asm/hvm/trace.h>
-
+#include <asm/hvm/emulate.h>
#include <public/sched.h>
#include <xen/iocap.h>
#include <public/hvm/ioreq.h>
-static void hvm_pio_assist(
- struct cpu_user_regs *regs, ioreq_t *p, struct hvm_io_op *pio_opp)
+int hvm_buffered_io_send(ioreq_t *p)
{
- if ( p->data_is_ptr || (pio_opp->flags & OVERLAP) )
+ struct vcpu *v = current;
+ struct hvm_ioreq_page *iorp = &v->domain->arch.hvm_domain.buf_ioreq;
+ buffered_iopage_t *pg = iorp->va;
+ buf_ioreq_t bp;
+ /* Timeoffset sends 64b data, but no address. Use two consecutive slots. */
+ int qw = 0;
+
+ /* Ensure buffered_iopage fits in a page */
+ BUILD_BUG_ON(sizeof(buffered_iopage_t) > PAGE_SIZE);
+
+ /*
+ * Return 0 for the cases we can't deal with:
+ * - 'addr' is only a 20-bit field, so we cannot address beyond 1MB
+ * - we cannot buffer accesses to guest memory buffers, as the guest
+ * may expect the memory buffer to be synchronously accessed
+ * - the count field is usually used with data_is_ptr and since we don't
+ * support data_is_ptr we do not waste space for the count field either
+ */
+ if ( (p->addr > 0xffffful) || p->data_is_ptr || (p->count != 1) )
+ return 0;
+
+ bp.type = p->type;
+ bp.dir = p->dir;
+ switch ( p->size )
{
- int sign = p->df ? -1 : 1;
+ case 1:
+ bp.size = 0;
+ break;
+ case 2:
+ bp.size = 1;
+ break;
+ case 4:
+ bp.size = 2;
+ break;
+ case 8:
+ bp.size = 3;
+ qw = 1;
+ break;
+ default:
+ gdprintk(XENLOG_WARNING, "unexpected ioreq size:%"PRId64"\n", p->size);
+ return 0;
+ }
+
+ bp.data = p->data;
+ bp.addr = p->addr;
+
+ spin_lock(&iorp->lock);
- if ( pio_opp->flags & REPZ )
- regs->ecx -= p->count;
+ if ( (pg->write_pointer - pg->read_pointer) >=
+ (IOREQ_BUFFER_SLOT_NUM - qw) )
+ {
+ /* The queue is full: send the iopacket through the normal path. */
+ spin_unlock(&iorp->lock);
+ return 0;
+ }
+
+ memcpy(&pg->buf_ioreq[pg->write_pointer % IOREQ_BUFFER_SLOT_NUM],
+ &bp, sizeof(bp));
+
+ if ( qw )
+ {
+ bp.data = p->data >> 32;
+ memcpy(&pg->buf_ioreq[(pg->write_pointer+1) % IOREQ_BUFFER_SLOT_NUM],
+ &bp, sizeof(bp));
+ }
- if ( p->dir == IOREQ_READ )
- {
- if ( pio_opp->flags & OVERLAP )
- {
- unsigned long addr = pio_opp->addr;
- if ( hvm_paging_enabled(current) )
- {
- int rv = hvm_copy_to_guest_virt(addr, &p->data, p->size);
- if ( rv == HVMCOPY_bad_gva_to_gfn )
- return; /* exception already injected */
- }
- else
- (void)hvm_copy_to_guest_phys(addr, &p->data, p->size);
- }
- regs->edi += sign * p->count * p->size;
- }
- else /* p->dir == IOREQ_WRITE */
- {
- ASSERT(p->dir == IOREQ_WRITE);
- regs->esi += sign * p->count * p->size;
- }
+ /* Make the ioreq_t visible /before/ write_pointer. */
+ wmb();
+ pg->write_pointer += qw ? 2 : 1;
+
+ spin_unlock(&iorp->lock);
+
+ return 1;
+}
+
+void send_pio_req(unsigned long port, unsigned long count, int size,
+ paddr_t value, int dir, int df, int value_is_ptr)
+{
+ struct vcpu *v = current;
+ vcpu_iodata_t *vio = get_ioreq(v);
+ ioreq_t *p = &vio->vp_ioreq;
+
+ if ( p->state != STATE_IOREQ_NONE )
+ gdprintk(XENLOG_WARNING,
+ "WARNING: send pio with something already pending (%d)?\n",
+ p->state);
+
+ p->dir = dir;
+ p->data_is_ptr = value_is_ptr;
+ p->type = IOREQ_TYPE_PIO;
+ p->size = size;
+ p->addr = port;
+ p->count = count;
+ p->df = df;
+ p->data = value;
+ p->io_count++;
+
+ if ( hvm_portio_intercept(p) )
+ {
+ p->state = STATE_IORESP_READY;
+ hvm_io_assist();
}
- else if ( p->dir == IOREQ_READ )
+ else
{
- unsigned long old_eax = regs->eax;
+ hvm_send_assist_req(v);
+ }
+}
- switch ( p->size )
- {
- case 1:
- regs->eax = (old_eax & ~0xff) | (p->data & 0xff);
- break;
- case 2:
- regs->eax = (old_eax & ~0xffff) | (p->data & 0xffff);
- break;
- case 4:
- regs->eax = (p->data & 0xffffffff);
- break;
- default:
- printk("Error: %s unknown port size\n", __FUNCTION__);
- domain_crash_synchronous();
- }
- HVMTRACE_1D(IO_ASSIST, current, p->data);
+void send_mmio_req(unsigned char type, paddr_t gpa,
+ unsigned long count, int size, paddr_t value,
+ int dir, int df, int value_is_ptr)
+{
+ struct vcpu *v = current;
+ vcpu_iodata_t *vio = get_ioreq(v);
+ ioreq_t *p = &vio->vp_ioreq;
+
+ if ( p->state != STATE_IOREQ_NONE )
+ gdprintk(XENLOG_WARNING,
+ "WARNING: send mmio with something already pending (%d)?\n",
+ p->state);
+
+ p->dir = dir;
+ p->data_is_ptr = value_is_ptr;
+ p->type = type;
+ p->size = size;
+ p->addr = gpa;
+ p->count = count;
+ p->df = df;
+ p->data = value;
+ p->io_count++;
+
+ if ( hvm_mmio_intercept(p) || hvm_buffered_io_intercept(p) )
+ {
+ p->state = STATE_IORESP_READY;
+ hvm_io_assist();
+ }
+ else
+ {
+ hvm_send_assist_req(v);
}
}
-void hvm_io_assist(void)
+void send_timeoffset_req(unsigned long timeoff)
{
+ ioreq_t p[1];
+
+ if ( timeoff == 0 )
+ return;
+
+ memset(p, 0, sizeof(*p));
+
+ p->type = IOREQ_TYPE_TIMEOFFSET;
+ p->size = 8;
+ p->count = 1;
+ p->dir = IOREQ_WRITE;
+ p->data = timeoff;
+
+ p->state = STATE_IOREQ_READY;
+
+ if ( !hvm_buffered_io_send(p) )
+ printk("Unsuccessful timeoffset update\n");
+}
+
+/* Ask ioemu mapcache to invalidate mappings. */
+void send_invalidate_req(void)
+{
+ struct vcpu *v = current;
vcpu_iodata_t *vio;
ioreq_t *p;
- struct cpu_user_regs *regs;
- struct hvm_io_op *io_opp;
- struct vcpu *v = current;
- io_opp = &v->arch.hvm_vcpu.io_op;
- regs = &io_opp->io_context;
- vio = get_ioreq(v);
+ vio = get_ioreq(v);
+ if ( vio == NULL )
+ {
+ printk("bad shared page: %lx\n", (unsigned long) vio);
+ domain_crash_synchronous();
+ }
p = &vio->vp_ioreq;
+ if ( p->state != STATE_IOREQ_NONE )
+ printk("WARNING: send invalidate req with something "
+ "already pending (%d)?\n", p->state);
+
+ p->type = IOREQ_TYPE_INVALIDATE;
+ p->size = 4;
+ p->dir = IOREQ_WRITE;
+ p->data = ~0UL; /* flush all */
+ p->io_count++;
+
+ hvm_send_assist_req(v);
+}
+
+int handle_mmio(void)
+{
+ struct hvm_emulate_ctxt ctxt;
+ struct vcpu *curr = current;
+ int rc;
+
+ hvm_emulate_prepare(&ctxt, guest_cpu_user_regs());
+
+ rc = hvm_emulate_one(&ctxt);
+
+ switch ( rc )
+ {
+ case X86EMUL_UNHANDLEABLE:
+ gdprintk(XENLOG_WARNING,
+ "MMIO emulation failed @ %04x:%lx: "
+ "%02x %02x %02x %02x %02x %02x\n",
+ hvmemul_get_seg_reg(x86_seg_cs, &ctxt)->sel,
+ ctxt.insn_buf_eip,
+ ctxt.insn_buf[0], ctxt.insn_buf[1],
+ ctxt.insn_buf[2], ctxt.insn_buf[3],
+ ctxt.insn_buf[4], ctxt.insn_buf[5]);
+ return 0;
+ case X86EMUL_EXCEPTION:
+ if ( ctxt.flags.exn_pending )
+ hvm_inject_exception(ctxt.exn_vector, 0, 0);
+ break;
+ default:
+ break;
+ }
+
+ hvm_emulate_writeback(&ctxt);
+
+ curr->arch.hvm_vcpu.mmio_in_progress = curr->arch.hvm_vcpu.io_in_progress;
+
+ return 1;
+}
+
+void hvm_io_assist(void)
+{
+ struct vcpu *v = current;
+ ioreq_t *p = &get_ioreq(v)->vp_ioreq;
+
if ( p->state != STATE_IORESP_READY )
{
gdprintk(XENLOG_ERR, "Unexpected HVM iorequest state %d.\n", p->state);
@@ -128,35 +295,15 @@ void hvm_io_assist(void)
if ( v->arch.hvm_vcpu.io_in_progress )
{
v->arch.hvm_vcpu.io_in_progress = 0;
- if ( p->dir == IOREQ_READ )
+ if ( (p->dir == IOREQ_READ) && !p->data_is_ptr )
{
v->arch.hvm_vcpu.io_completed = 1;
v->arch.hvm_vcpu.io_data = p->data;
+ if ( v->arch.hvm_vcpu.mmio_in_progress )
+ (void)handle_mmio();
}
- if ( v->arch.hvm_vcpu.mmio_in_progress )
- (void)handle_mmio();
- goto out;
- }
-
- switch ( p->type )
- {
- case IOREQ_TYPE_INVALIDATE:
- goto out;
- case IOREQ_TYPE_PIO:
- hvm_pio_assist(regs, p, io_opp);
- break;
- default:
- gdprintk(XENLOG_ERR, "Unexpected HVM iorequest state %d.\n", p->state);
- domain_crash(v->domain);
- goto out;
}
- /* Copy register changes back into current guest state. */
- regs->eflags &= ~X86_EFLAGS_RF;
- memcpy(guest_cpu_user_regs(), regs, HVM_CONTEXT_STACK_BYTES);
- if ( regs->eflags & X86_EFLAGS_TF )
- hvm_inject_exception(TRAP_debug, HVM_DELIVER_NO_ERROR_CODE, 0);
-
out:
vcpu_end_shutdown_deferral(v);
}
@@ -173,13 +320,13 @@ void dpci_ioport_read(uint32_t mport, ioreq_t *p)
switch ( p->size )
{
- case BYTE:
+ case 1:
z_data = (uint64_t)inb(mport);
break;
- case WORD:
+ case 2:
z_data = (uint64_t)inw(mport);
break;
- case LONG:
+ case 4:
z_data = (uint64_t)inl(mport);
break;
default:
@@ -218,13 +365,13 @@ void dpci_ioport_write(uint32_t mport, ioreq_t *p)
switch ( p->size )
{
- case BYTE:
+ case 1:
outb((uint8_t) z_data, mport);
break;
- case WORD:
+ case 2:
outw((uint16_t) z_data, mport);
break;
- case LONG:
+ case 4:
outl((uint32_t) z_data, mport);
break;
default:
diff --git a/xen/arch/x86/hvm/platform.c b/xen/arch/x86/hvm/platform.c
deleted file mode 100644
index d77d2061cb..0000000000
--- a/xen/arch/x86/hvm/platform.c
+++ /dev/null
@@ -1,273 +0,0 @@
-/*
- * platform.c: handling x86 platform related MMIO instructions
- *
- * Copyright (c) 2004, Intel Corporation.
- * Copyright (c) 2005, International Business Machines Corporation.
- *
- * This program is free software; you can redistribute it and/or modify it
- * under the terms and conditions of the GNU General Public License,
- * version 2, as published by the Free Software Foundation.
- *
- * This program is distributed in the hope it will be useful, but WITHOUT
- * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
- * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
- * more details.
- *
- * You should have received a copy of the GNU General Public License along with
- * this program; if not, write to the Free Software Foundation, Inc., 59 Temple
- * Place - Suite 330, Boston, MA 02111-1307 USA.
- */
-
-#include <xen/config.h>
-#include <xen/types.h>
-#include <xen/mm.h>
-#include <xen/domain_page.h>
-#include <asm/page.h>
-#include <xen/event.h>
-#include <xen/trace.h>
-#include <xen/sched.h>
-#include <asm/regs.h>
-#include <asm/x86_emulate.h>
-#include <asm/paging.h>
-#include <asm/hvm/hvm.h>
-#include <asm/hvm/support.h>
-#include <asm/hvm/io.h>
-#include <public/hvm/ioreq.h>
-#include <xen/lib.h>
-#include <xen/sched.h>
-#include <asm/hvm/emulate.h>
-
-int inst_copy_from_guest(
- unsigned char *buf, unsigned long guest_eip, int inst_len)
-{
- if ( inst_len > MAX_INST_LEN || inst_len <= 0 )
- return 0;
- if ( hvm_fetch_from_guest_virt_nofault(buf, guest_eip, inst_len) )
- return 0;
- return inst_len;
-}
-
-void send_pio_req(unsigned long port, unsigned long count, int size,
- paddr_t value, int dir, int df, int value_is_ptr)
-{
- struct vcpu *v = current;
- vcpu_iodata_t *vio;
- ioreq_t *p;
-
- if ( size == 0 || count == 0 ) {
- printk("null pio request? port %lx, count %lx, "
- "size %d, value %"PRIpaddr", dir %d, value_is_ptr %d.\n",
- port, count, size, value, dir, value_is_ptr);
- }
-
- vio = get_ioreq(v);
- if ( vio == NULL ) {
- printk("bad shared page: %lx\n", (unsigned long) vio);
- domain_crash_synchronous();
- }
-
- p = &vio->vp_ioreq;
- if ( p->state != STATE_IOREQ_NONE )
- printk("WARNING: send pio with something already pending (%d)?\n",
- p->state);
-
- p->dir = dir;
- p->data_is_ptr = value_is_ptr;
-
- p->type = IOREQ_TYPE_PIO;
- p->size = size;
- p->addr = port;
- p->count = count;
- p->df = df;
-
- p->io_count++;
-
- p->data = value;
-
- if ( hvm_portio_intercept(p) )
- {
- p->state = STATE_IORESP_READY;
- hvm_io_assist();
- return;
- }
-
- hvm_send_assist_req(v);
-}
-
-void send_mmio_req(unsigned char type, paddr_t gpa,
- unsigned long count, int size, paddr_t value,
- int dir, int df, int value_is_ptr)
-{
- struct vcpu *v = current;
- vcpu_iodata_t *vio;
- ioreq_t *p;
-
- if ( size == 0 || count == 0 ) {
- printk("null mmio request? type %d, gpa %"PRIpaddr", "
- "count %lx, size %d, value %"PRIpaddr", dir %d, "
- "value_is_ptr %d.\n",
- type, gpa, count, size, value, dir, value_is_ptr);
- }
-
- vio = get_ioreq(v);
- if (vio == NULL) {
- printk("bad shared page\n");
- domain_crash_synchronous();
- }
-
- p = &vio->vp_ioreq;
-
- if ( p->state != STATE_IOREQ_NONE )
- printk("WARNING: send mmio with something already pending (%d)?\n",
- p->state);
- p->dir = dir;
- p->data_is_ptr = value_is_ptr;
-
- p->type = type;
- p->size = size;
- p->addr = gpa;
- p->count = count;
- p->df = df;
-
- p->io_count++;
-
- p->data = value;
-
- if ( hvm_mmio_intercept(p) || hvm_buffered_io_intercept(p) )
- {
- p->state = STATE_IORESP_READY;
- hvm_io_assist();
- return;
- }
-
- hvm_send_assist_req(v);
-}
-
-void send_timeoffset_req(unsigned long timeoff)
-{
- ioreq_t p[1];
-
- if ( timeoff == 0 )
- return;
-
- memset(p, 0, sizeof(*p));
-
- p->type = IOREQ_TYPE_TIMEOFFSET;
- p->size = 8;
- p->count = 1;
- p->dir = IOREQ_WRITE;
- p->data = timeoff;
-
- p->state = STATE_IOREQ_READY;
-
- if ( !hvm_buffered_io_send(p) )
- printk("Unsuccessful timeoffset update\n");
-}
-
-/* Ask ioemu mapcache to invalidate mappings. */
-void send_invalidate_req(void)
-{
- struct vcpu *v = current;
- vcpu_iodata_t *vio;
- ioreq_t *p;
-
- vio = get_ioreq(v);
- if ( vio == NULL )
- {
- printk("bad shared page: %lx\n", (unsigned long) vio);
- domain_crash_synchronous();
- }
-
- p = &vio->vp_ioreq;
- if ( p->state != STATE_IOREQ_NONE )
- printk("WARNING: send invalidate req with something "
- "already pending (%d)?\n", p->state);
-
- p->type = IOREQ_TYPE_INVALIDATE;
- p->size = 4;
- p->dir = IOREQ_WRITE;
- p->data = ~0UL; /* flush all */
- p->io_count++;
-
- hvm_send_assist_req(v);
-}
-
-int handle_mmio(void)
-{
- struct hvm_emulate_ctxt ctxt;
- struct vcpu *curr = current;
- int rc;
-
- hvm_emulate_prepare(&ctxt, guest_cpu_user_regs());
-
- rc = hvm_emulate_one(&ctxt);
-
- switch ( rc )
- {
- case X86EMUL_UNHANDLEABLE:
- gdprintk(XENLOG_WARNING,
- "MMIO emulation failed @ %04x:%lx: "
- "%02x %02x %02x %02x %02x %02x\n",
- hvmemul_get_seg_reg(x86_seg_cs, &ctxt)->sel,
- ctxt.insn_buf_eip,
- ctxt.insn_buf[0], ctxt.insn_buf[1],
- ctxt.insn_buf[2], ctxt.insn_buf[3],
- ctxt.insn_buf[4], ctxt.insn_buf[5]);
- return 0;
- case X86EMUL_EXCEPTION:
- if ( ctxt.flags.exn_pending )
- hvm_inject_exception(ctxt.exn_vector, 0, 0);
- break;
- default:
- break;
- }
-
- hvm_emulate_writeback(&ctxt);
-
- curr->arch.hvm_vcpu.mmio_in_progress = curr->arch.hvm_vcpu.io_in_progress;
-
- return 1;
-}
-
-DEFINE_PER_CPU(int, guest_handles_in_xen_space);
-
-/* Note that copy_{to,from}_user_hvm require the PTE to be writable even
- when they're only trying to read from it. The guest is expected to
- deal with this. */
-unsigned long copy_to_user_hvm(void *to, const void *from, unsigned len)
-{
- int rc;
-
- if ( this_cpu(guest_handles_in_xen_space) )
- {
- memcpy(to, from, len);
- return 0;
- }
-
- rc = hvm_copy_to_guest_virt_nofault((unsigned long)to, (void *)from, len);
- return rc ? len : 0; /* fake a copy_to_user() return code */
-}
-
-unsigned long copy_from_user_hvm(void *to, const void *from, unsigned len)
-{
- int rc;
-
- if ( this_cpu(guest_handles_in_xen_space) )
- {
- memcpy(to, from, len);
- return 0;
- }
-
- rc = hvm_copy_from_guest_virt_nofault(to, (unsigned long)from, len);
- return rc ? len : 0; /* fake a copy_from_user() return code */
-}
-
-/*
- * Local variables:
- * mode: C
- * c-set-style: "BSD"
- * c-basic-offset: 4
- * tab-width: 4
- * indent-tabs-mode: nil
- * End:
- */
diff --git a/xen/arch/x86/hvm/svm/emulate.c b/xen/arch/x86/hvm/svm/emulate.c
index 5987681522..530ed4606a 100644
--- a/xen/arch/x86/hvm/svm/emulate.c
+++ b/xen/arch/x86/hvm/svm/emulate.c
@@ -27,8 +27,17 @@
#include <asm/hvm/svm/vmcb.h>
#include <asm/hvm/svm/emulate.h>
-int inst_copy_from_guest(
- unsigned char *buf, unsigned long guest_eip, int inst_len);
+#define MAX_INST_LEN 15
+
+static int inst_copy_from_guest(
+ unsigned char *buf, unsigned long guest_eip, int inst_len)
+{
+ if ( (inst_len > MAX_INST_LEN) || (inst_len <= 0) )
+ return 0;
+ if ( hvm_fetch_from_guest_virt_nofault(buf, guest_eip, inst_len) )
+ return 0;
+ return inst_len;
+}
static unsigned int is_prefix(u8 opc)
{
diff --git a/xen/arch/x86/hvm/svm/svm.c b/xen/arch/x86/hvm/svm/svm.c
index 27cc7771ad..fe4fd7e544 100644
--- a/xen/arch/x86/hvm/svm/svm.c
+++ b/xen/arch/x86/hvm/svm/svm.c
@@ -58,8 +58,6 @@ u32 svm_feature_flags;
enum handler_return { HNDL_done, HNDL_unhandled, HNDL_exception_raised };
-int inst_copy_from_guest(unsigned char *buf, unsigned long guest_eip,
- int inst_len);
asmlinkage void do_IRQ(struct cpu_user_regs *);
static void svm_update_guest_cr(struct vcpu *v, unsigned int cr);
diff --git a/xen/arch/x86/hvm/vmx/realmode.c b/xen/arch/x86/hvm/vmx/realmode.c
index 5020c72069..9ab137970f 100644
--- a/xen/arch/x86/hvm/vmx/realmode.c
+++ b/xen/arch/x86/hvm/vmx/realmode.c
@@ -221,8 +221,7 @@ void vmx_realmode(struct cpu_user_regs *regs)
hvm_emulate_prepare(&rm_ctxt.hvm, regs);
rm_ctxt.intr_shadow = __vmread(GUEST_INTERRUPTIBILITY_INFO);
- if ( curr->arch.hvm_vcpu.io_in_progress ||
- curr->arch.hvm_vcpu.io_completed )
+ if ( curr->arch.hvm_vcpu.io_completed )
realmode_emulate_one(&rm_ctxt);
/* Only deliver interrupts into emulated real mode. */
diff --git a/xen/include/asm-x86/hvm/io.h b/xen/include/asm-x86/hvm/io.h
index 863f460e23..8164742e01 100644
--- a/xen/include/asm-x86/hvm/io.h
+++ b/xen/include/asm-x86/hvm/io.h
@@ -25,61 +25,6 @@
#include <public/hvm/ioreq.h>
#include <public/event_channel.h>
-#define operand_size(operand) \
- ((operand >> 24) & 0xFF)
-
-#define operand_index(operand) \
- ((operand >> 16) & 0xFF)
-
-/* for instruction.operand[].size */
-#define BYTE 1
-#define WORD 2
-#define LONG 4
-#define QUAD 8
-#define BYTE_64 16
-
-/* for instruction.operand[].flag */
-#define REGISTER 0x1
-#define MEMORY 0x2
-#define IMMEDIATE 0x4
-
-/* for instruction.flags */
-#define REPZ 0x1
-#define REPNZ 0x2
-#define OVERLAP 0x4
-
-/* instruction type */
-#define INSTR_PIO 1
-#define INSTR_OR 2
-#define INSTR_AND 3
-#define INSTR_XOR 4
-#define INSTR_CMP 5
-#define INSTR_MOV 6
-#define INSTR_MOVS 7
-#define INSTR_MOVZX 8
-#define INSTR_MOVSX 9
-#define INSTR_STOS 10
-#define INSTR_LODS 11
-#define INSTR_TEST 12
-#define INSTR_BT 13
-#define INSTR_XCHG 14
-#define INSTR_SUB 15
-#define INSTR_ADD 16
-#define INSTR_PUSH 17
-
-#define MAX_INST_LEN 15 /* Maximum instruction length = 15 bytes */
-
-struct hvm_io_op {
- unsigned int instr; /* instruction */
- unsigned int flags;
- unsigned long addr; /* virt addr for overlap PIO/MMIO */
- struct {
- unsigned int operand[2]; /* operands */
- unsigned long immediate; /* immediate portion */
- };
- struct cpu_user_regs io_context; /* current context */
-};
-
#define MAX_IO_HANDLER 12
#define HVM_PORTIO 0
@@ -119,7 +64,6 @@ struct hvm_mmio_handler {
hvm_mmio_write_t write_handler;
};
-/* global io interception point in HV */
int hvm_io_intercept(ioreq_t *p, int type);
int register_io_handler(
struct domain *d, unsigned long addr, unsigned long size,
diff --git a/xen/include/asm-x86/hvm/vcpu.h b/xen/include/asm-x86/hvm/vcpu.h
index 003b7f84b4..7439434b85 100644
--- a/xen/include/asm-x86/hvm/vcpu.h
+++ b/xen/include/asm-x86/hvm/vcpu.h
@@ -42,7 +42,6 @@ struct hvm_vcpu {
*/
unsigned long hw_cr[5];
- struct hvm_io_op io_op;
struct vlapic vlapic;
s64 cache_tsc_offset;
u64 guest_time;
@@ -77,9 +76,5 @@ struct hvm_vcpu {
unsigned long io_data;
};
-#define ARCH_HVM_IO_WAIT 1 /* Waiting for I/O completion */
-
-#define HVM_CONTEXT_STACK_BYTES (offsetof(struct cpu_user_regs, ss))
-
#endif /* __ASM_X86_HVM_VCPU_H__ */