aboutsummaryrefslogtreecommitdiffstats
path: root/xen/arch/x86/hvm/intercept.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/intercept.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/intercept.c')
-rw-r--r--xen/arch/x86/hvm/intercept.c41
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++ )
{