diff options
author | Keir Fraser <keir.fraser@citrix.com> | 2009-12-17 06:27:55 +0000 |
---|---|---|
committer | Keir Fraser <keir.fraser@citrix.com> | 2009-12-17 06:27:55 +0000 |
commit | 507c9e76fbb099599f606549f4f31f9cde3d2762 (patch) | |
tree | 074cf131a4d2a35680a7644d7d039ef8b9ff0a8c /xen/arch/x86/hvm/io.c | |
parent | 8992ab0adfe9b708574759383f3798121fdf977c (diff) | |
download | xen-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.c | 34 |
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; } /* |