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/intercept.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/intercept.c')
-rw-r--r-- | xen/arch/x86/hvm/intercept.c | 41 |
1 files changed, 23 insertions, 18 deletions
diff --git a/xen/arch/x86/hvm/intercept.c b/xen/arch/x86/hvm/intercept.c index 06421fe462..841dec8921 100644 --- a/xen/arch/x86/hvm/intercept.c +++ b/xen/arch/x86/hvm/intercept.c @@ -72,30 +72,31 @@ static int hvm_mmio_access(struct vcpu *v, { for ( i = 0; i < p->count; i++ ) { - rc = read_handler( - v, - p->addr + (sign * i * p->size), - p->size, &data); + 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); + if ( hvm_copy_to_guest_phys(p->data + (sign * i * p->size), &data, + p->size) == HVMCOPY_gfn_paged_out ) + { + rc = X86EMUL_RETRY; + break; + } } } else { for ( i = 0; i < p->count; i++ ) { - (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 ( hvm_copy_from_guest_phys(&data, + p->data + (sign * i * p->size), + p->size) == HVMCOPY_gfn_paged_out ) + { + rc = X86EMUL_RETRY; + break; + } + rc = write_handler(v, p->addr + (sign * i * p->size), p->size, + data); if ( rc != X86EMUL_OKAY ) break; } @@ -190,8 +191,12 @@ int hvm_io_intercept(ioreq_t *p, int type) int i; unsigned long addr, size; - if ( (type == HVM_PORTIO) && (dpci_ioport_intercept(p)) ) - return X86EMUL_OKAY; + if ( type == HVM_PORTIO ) + { + int rc = dpci_ioport_intercept(p); + if ( (rc == X86EMUL_OKAY) || (rc == X86EMUL_RETRY) ) + return rc; + } for ( i = 0; i < handler->num_slot; i++ ) { |