aboutsummaryrefslogtreecommitdiffstats
path: root/xen/arch/x86/hvm/emulate.c
diff options
context:
space:
mode:
authorAndres Lagar-Cavilla <andres@lagarcavilla.org>2012-01-26 13:21:27 +0000
committerAndres Lagar-Cavilla <andres@lagarcavilla.org>2012-01-26 13:21:27 +0000
commitbe1ff5e8f0f71f0927ec2681ec7f51ac2efe50d9 (patch)
tree2471304b8998d8daca6ac50fd5bcfc7564d06378 /xen/arch/x86/hvm/emulate.c
parent91279d9f230d7314e212a0e3aa0cee874edb6a3d (diff)
downloadxen-be1ff5e8f0f71f0927ec2681ec7f51ac2efe50d9.tar.gz
xen-be1ff5e8f0f71f0927ec2681ec7f51ac2efe50d9.tar.bz2
xen-be1ff5e8f0f71f0927ec2681ec7f51ac2efe50d9.zip
x86/mm: clean use of p2m unlocked queries
Limit such queries only to p2m_query types. This is more compatible with the name and intended semantics: perform only a lookup, and explicitly in an unlocked way. Signed-off-by: Andres Lagar-Cavilla <andres@lagarcavilla.org> Acked-by: Tim Deegan <tim@xen.org> Committed-by: Tim Deegan <tim@xen.org>
Diffstat (limited to 'xen/arch/x86/hvm/emulate.c')
-rw-r--r--xen/arch/x86/hvm/emulate.c35
1 files changed, 28 insertions, 7 deletions
diff --git a/xen/arch/x86/hvm/emulate.c b/xen/arch/x86/hvm/emulate.c
index 15f413c576..53cddbecf4 100644
--- a/xen/arch/x86/hvm/emulate.c
+++ b/xen/arch/x86/hvm/emulate.c
@@ -660,7 +660,7 @@ static int hvmemul_rep_movs(
{
struct hvm_emulate_ctxt *hvmemul_ctxt =
container_of(ctxt, struct hvm_emulate_ctxt, ctxt);
- unsigned long saddr, daddr, bytes;
+ unsigned long saddr, daddr, bytes, sgfn, dgfn;
paddr_t sgpa, dgpa;
uint32_t pfec = PFEC_page_present;
p2m_type_t p2mt;
@@ -693,17 +693,28 @@ static int hvmemul_rep_movs(
if ( rc != X86EMUL_OKAY )
return rc;
- /* Unlocked works here because we get_gfn for real in whatever
- * we call later. */
- (void)get_gfn_unlocked(current->domain, sgpa >> PAGE_SHIFT, &p2mt);
+ /* XXX In a fine-grained p2m locking scenario, we need to sort this
+ * get_gfn's, or else we might deadlock */
+ sgfn = sgpa >> PAGE_SHIFT;
+ (void)get_gfn(current->domain, sgfn, &p2mt);
if ( !p2m_is_ram(p2mt) && !p2m_is_grant(p2mt) )
- return hvmemul_do_mmio(
+ {
+ rc = hvmemul_do_mmio(
sgpa, reps, bytes_per_rep, dgpa, IOREQ_READ, df, NULL);
+ put_gfn(current->domain, sgfn);
+ return rc;
+ }
- (void)get_gfn_unlocked(current->domain, dgpa >> PAGE_SHIFT, &p2mt);
+ dgfn = dgpa >> PAGE_SHIFT;
+ (void)get_gfn(current->domain, dgfn, &p2mt);
if ( !p2m_is_ram(p2mt) && !p2m_is_grant(p2mt) )
- return hvmemul_do_mmio(
+ {
+ rc = hvmemul_do_mmio(
dgpa, reps, bytes_per_rep, sgpa, IOREQ_WRITE, df, NULL);
+ put_gfn(current->domain, sgfn);
+ put_gfn(current->domain, dgfn);
+ return rc;
+ }
/* RAM-to-RAM copy: emulate as equivalent of memmove(dgpa, sgpa, bytes). */
bytes = *reps * bytes_per_rep;
@@ -718,7 +729,11 @@ static int hvmemul_rep_movs(
* can be emulated by a source-to-buffer-to-destination block copy.
*/
if ( ((dgpa + bytes_per_rep) > sgpa) && (dgpa < (sgpa + bytes)) )
+ {
+ put_gfn(current->domain, sgfn);
+ put_gfn(current->domain, dgfn);
return X86EMUL_UNHANDLEABLE;
+ }
/* Adjust destination address for reverse copy. */
if ( df )
@@ -727,7 +742,11 @@ static int hvmemul_rep_movs(
/* Allocate temporary buffer. Fall back to slow emulation if this fails. */
buf = xmalloc_bytes(bytes);
if ( buf == NULL )
+ {
+ put_gfn(current->domain, sgfn);
+ put_gfn(current->domain, dgfn);
return X86EMUL_UNHANDLEABLE;
+ }
/*
* We do a modicum of checking here, just for paranoia's sake and to
@@ -738,6 +757,8 @@ static int hvmemul_rep_movs(
rc = hvm_copy_to_guest_phys(dgpa, buf, bytes);
xfree(buf);
+ put_gfn(current->domain, sgfn);
+ put_gfn(current->domain, dgfn);
if ( rc == HVMCOPY_gfn_paged_out )
return X86EMUL_RETRY;