aboutsummaryrefslogtreecommitdiffstats
path: root/xen/arch/x86/hvm/io.c
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2009-12-17 06:27:55 +0000
committerKeir Fraser <keir.fraser@citrix.com>2009-12-17 06:27:55 +0000
commit507c9e76fbb099599f606549f4f31f9cde3d2762 (patch)
tree074cf131a4d2a35680a7644d7d039ef8b9ff0a8c /xen/arch/x86/hvm/io.c
parent8992ab0adfe9b708574759383f3798121fdf977c (diff)
downloadxen-507c9e76fbb099599f606549f4f31f9cde3d2762.tar.gz
xen-507c9e76fbb099599f606549f4f31f9cde3d2762.tar.bz2
xen-507c9e76fbb099599f606549f4f31f9cde3d2762.zip
Memory paging support for HVM guest emulation.
A new HVMCOPY return value, HVMCOPY_gfn_paged_out is defined to indicate that a gfn was paged out. This value and PFEC_page_paged, as appropriate, are caught and passed up as X86EMUL_RETRY to the emulator. This will cause the emulator to keep retrying the operation until is succeeds (once the page has been paged in). Signed-off-by: Patrick Colp <Patrick.Colp@citrix.com>
Diffstat (limited to 'xen/arch/x86/hvm/io.c')
-rw-r--r--xen/arch/x86/hvm/io.c34
1 files changed, 23 insertions, 11 deletions
diff --git a/xen/arch/x86/hvm/io.c b/xen/arch/x86/hvm/io.c
index 8519bfad51..29079f296d 100644
--- a/xen/arch/x86/hvm/io.c
+++ b/xen/arch/x86/hvm/io.c
@@ -239,7 +239,7 @@ void hvm_io_assist(void)
vcpu_end_shutdown_deferral(curr);
}
-static void dpci_ioport_read(uint32_t mport, ioreq_t *p)
+static int dpci_ioport_read(uint32_t mport, ioreq_t *p)
{
int i, sign = p->df ? -1 : 1;
uint32_t data = 0;
@@ -262,14 +262,19 @@ static void dpci_ioport_read(uint32_t mport, ioreq_t *p)
}
if ( p->data_is_ptr )
- (void)hvm_copy_to_guest_phys(
- p->data + (sign * i * p->size), &data, p->size);
+ {
+ if ( hvm_copy_to_guest_phys(p->data + (sign * i * p->size), &data,
+ p->size) == HVMCOPY_gfn_paged_out )
+ return X86EMUL_RETRY;
+ }
else
p->data = data;
}
+
+ return X86EMUL_OKAY;
}
-static void dpci_ioport_write(uint32_t mport, ioreq_t *p)
+static int dpci_ioport_write(uint32_t mport, ioreq_t *p)
{
int i, sign = p->df ? -1 : 1;
uint32_t data;
@@ -278,8 +283,11 @@ static void dpci_ioport_write(uint32_t mport, ioreq_t *p)
{
data = p->data;
if ( p->data_is_ptr )
- (void)hvm_copy_from_guest_phys(
- &data, p->data + (sign * i * p->size), p->size);
+ {
+ if ( hvm_copy_from_guest_phys(&data, p->data + (sign * i * p->size),
+ p->size) == HVMCOPY_gfn_paged_out )
+ return X86EMUL_RETRY;
+ }
switch ( p->size )
{
@@ -296,6 +304,8 @@ static void dpci_ioport_write(uint32_t mport, ioreq_t *p)
BUG();
}
}
+
+ return X86EMUL_OKAY;
}
int dpci_ioport_intercept(ioreq_t *p)
@@ -305,6 +315,7 @@ int dpci_ioport_intercept(ioreq_t *p)
struct g2m_ioport *g2m_ioport;
unsigned int mport, gport = p->addr;
unsigned int s = 0, e = 0;
+ int rc;
list_for_each_entry( g2m_ioport, &hd->g2m_ioport_list, list )
{
@@ -314,7 +325,7 @@ int dpci_ioport_intercept(ioreq_t *p)
goto found;
}
- return 0;
+ return X86EMUL_UNHANDLEABLE;
found:
mport = (gport - s) + g2m_ioport->mport;
@@ -323,22 +334,23 @@ int dpci_ioport_intercept(ioreq_t *p)
{
gdprintk(XENLOG_ERR, "Error: access to gport=0x%x denied!\n",
(uint32_t)p->addr);
- return 0;
+ return X86EMUL_UNHANDLEABLE;
}
switch ( p->dir )
{
case IOREQ_READ:
- dpci_ioport_read(mport, p);
+ rc = dpci_ioport_read(mport, p);
break;
case IOREQ_WRITE:
- dpci_ioport_write(mport, p);
+ rc = dpci_ioport_write(mport, p);
break;
default:
gdprintk(XENLOG_ERR, "Error: couldn't handle p->dir = %d", p->dir);
+ rc = X86EMUL_UNHANDLEABLE;
}
- return 1;
+ return rc;
}
/*