From mboxrd@z Thu Jan 1 00:00:00 1970 From: Andres Lagar-Cavilla Subject: [PATCH 2 of 3] x86/emulate: Relieve contention of p2m lock in emulation of rep movs Date: Tue, 24 Apr 2012 15:34:12 -0400 Message-ID: <2ffc676120b8b1e4c456.1335296052@xdev.gridcentric.ca> References: Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Return-path: In-Reply-To: List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Sender: xen-devel-bounces@lists.xen.org Errors-To: xen-devel-bounces@lists.xen.org To: xen-devel@lists.xen.org Cc: "Zhang, Yang Z" , keir@xen.org, andres@gridcentric.ca, tim@xen.org List-Id: xen-devel@lists.xenproject.org xen/arch/x86/hvm/emulate.c | 27 +++++++++------------------ 1 files changed, 9 insertions(+), 18 deletions(-) get_two_gfns is used to query the source and target physical addresses of the emulated rep movs. It is not necessary to hold onto the two gfn's for the duration of the emulation: further calls down the line will do the appropriate unsharing or paging in, and unwind correctly on failure. Signed-off-by: Andres Lagar-Cavilla diff -r 58fd70123787 -r 2ffc676120b8 xen/arch/x86/hvm/emulate.c --- a/xen/arch/x86/hvm/emulate.c +++ b/xen/arch/x86/hvm/emulate.c @@ -714,25 +714,23 @@ static int hvmemul_rep_movs( if ( rc != X86EMUL_OKAY ) return rc; + /* The query on the gfns is to establish the need for mmio. In the two mmio + * cases, a proper get_gfn for the "other" gfn will be enacted, with paging in + * or unsharing if necessary. In the memmove case, the gfn might change given + * the bytes mov'ed, and, again, proper get_gfn's will be enacted in + * __hvm_copy. */ get_two_gfns(current->domain, sgpa >> PAGE_SHIFT, &sp2mt, NULL, NULL, current->domain, dgpa >> PAGE_SHIFT, &dp2mt, NULL, NULL, P2M_ALLOC, &tg); - + put_two_gfns(&tg); + if ( !p2m_is_ram(sp2mt) && !p2m_is_grant(sp2mt) ) - { - rc = hvmemul_do_mmio( + return hvmemul_do_mmio( sgpa, reps, bytes_per_rep, dgpa, IOREQ_READ, df, NULL); - put_two_gfns(&tg); - return rc; - } if ( !p2m_is_ram(dp2mt) && !p2m_is_grant(dp2mt) ) - { - rc = hvmemul_do_mmio( + return hvmemul_do_mmio( dgpa, reps, bytes_per_rep, sgpa, IOREQ_WRITE, df, NULL); - put_two_gfns(&tg); - return rc; - } /* RAM-to-RAM copy: emulate as equivalent of memmove(dgpa, sgpa, bytes). */ bytes = *reps * bytes_per_rep; @@ -747,10 +745,7 @@ 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_two_gfns(&tg); return X86EMUL_UNHANDLEABLE; - } /* Adjust destination address for reverse copy. */ if ( df ) @@ -759,10 +754,7 @@ static int hvmemul_rep_movs( /* Allocate temporary buffer. Fall back to slow emulation if this fails. */ buf = xmalloc_bytes(bytes); if ( buf == NULL ) - { - put_two_gfns(&tg); return X86EMUL_UNHANDLEABLE; - } /* * We do a modicum of checking here, just for paranoia's sake and to @@ -773,7 +765,6 @@ static int hvmemul_rep_movs( rc = hvm_copy_to_guest_phys(dgpa, buf, bytes); xfree(buf); - put_two_gfns(&tg); if ( rc == HVMCOPY_gfn_paged_out ) return X86EMUL_RETRY;