aboutsummaryrefslogtreecommitdiffstats
path: root/xen/arch/x86/hvm/emulate.c
diff options
context:
space:
mode:
authorKeir Fraser <keir.fraser@citrix.com>2009-12-17 06:27:56 +0000
committerKeir Fraser <keir.fraser@citrix.com>2009-12-17 06:27:56 +0000
commit3e3ccc354377859506ad948df84572813204c99c (patch)
treeafd84dd673b7dd062f83a15cdab332a84b6555a6 /xen/arch/x86/hvm/emulate.c
parentaf909e7e16dd67452bde91bb71c8111c95c43983 (diff)
downloadxen-3e3ccc354377859506ad948df84572813204c99c.tar.gz
xen-3e3ccc354377859506ad948df84572813204c99c.tar.bz2
xen-3e3ccc354377859506ad948df84572813204c99c.zip
The internal Xen x86 emulator is fixed to handle shared/sharable pages corretly.
If pages cannot be unshared immediately (due to lack of free memory required to create private copies) the VCPU under emulation is paused, and the emulator returns X86EMUL_RETRY, which will get resolved after some memory is freed back to Xen (possibly through host paging). Signed-off-by: Grzegorz Milos <Grzegorz.Milos@citrix.com>
Diffstat (limited to 'xen/arch/x86/hvm/emulate.c')
-rw-r--r--xen/arch/x86/hvm/emulate.c14
1 files changed, 11 insertions, 3 deletions
diff --git a/xen/arch/x86/hvm/emulate.c b/xen/arch/x86/hvm/emulate.c
index a636c9bef6..88b1eb1946 100644
--- a/xen/arch/x86/hvm/emulate.c
+++ b/xen/arch/x86/hvm/emulate.c
@@ -62,12 +62,14 @@ static int hvmemul_do_io(
int rc;
/* Check for paged out page */
- ram_mfn = gfn_to_mfn(current->domain, ram_gfn, &p2mt);
+ ram_mfn = gfn_to_mfn_unshare(current->domain, ram_gfn, &p2mt, 0);
if ( p2m_is_paging(p2mt) )
{
p2m_mem_paging_populate(curr->domain, ram_gfn);
return X86EMUL_RETRY;
}
+ if ( p2m_is_shared(p2mt) )
+ return X86EMUL_RETRY;
/*
* Weird-sized accesses have undefined behaviour: we discard writes
@@ -282,7 +284,7 @@ static int hvmemul_linear_to_phys(
}
else if ( (pfn = paging_gva_to_gfn(curr, addr, &pfec)) == INVALID_GFN )
{
- if ( pfec == PFEC_page_paged )
+ if ( pfec == PFEC_page_paged || pfec == PFEC_page_shared )
return X86EMUL_RETRY;
hvm_inject_exception(TRAP_page_fault, pfec, addr);
return X86EMUL_EXCEPTION;
@@ -299,7 +301,7 @@ static int hvmemul_linear_to_phys(
/* Is it contiguous with the preceding PFNs? If not then we're done. */
if ( (npfn == INVALID_GFN) || (npfn != (pfn + (reverse ? -i : i))) )
{
- if ( pfec == PFEC_page_paged )
+ if ( pfec == PFEC_page_paged || pfec == PFEC_page_shared )
return X86EMUL_RETRY;
done /= bytes_per_rep;
if ( done == 0 )
@@ -441,6 +443,8 @@ static int __hvmemul_read(
return hvmemul_do_mmio(gpa, &reps, bytes, 0, IOREQ_READ, 0, p_data);
case HVMCOPY_gfn_paged_out:
return X86EMUL_RETRY;
+ case HVMCOPY_gfn_shared:
+ return X86EMUL_RETRY;
default:
break;
}
@@ -533,6 +537,8 @@ static int hvmemul_write(
IOREQ_WRITE, 0, p_data);
case HVMCOPY_gfn_paged_out:
return X86EMUL_RETRY;
+ case HVMCOPY_gfn_shared:
+ return X86EMUL_RETRY;
default:
break;
}
@@ -708,6 +714,8 @@ static int hvmemul_rep_movs(
if ( rc == HVMCOPY_gfn_paged_out )
return X86EMUL_RETRY;
+ if ( rc == HVMCOPY_gfn_shared )
+ return X86EMUL_RETRY;
if ( rc != HVMCOPY_okay )
{
gdprintk(XENLOG_WARNING, "Failed memory-to-memory REP MOVS: sgpa=%"