From mboxrd@z Thu Jan 1 00:00:00 1970 From: "Jan Beulich" Subject: [PATCH 2/2] x86/HVM: use available linear->phys translations in REP MOVS/STOS handling Date: Wed, 08 Jun 2016 07:10:11 -0600 Message-ID: <5758355302000078000F30FE@prv-mh.provo.novell.com> References: <575833E402000078000F30E7@prv-mh.provo.novell.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=__Part5D6B5F23.1__=" Return-path: Received: from mail6.bemta14.messagelabs.com ([193.109.254.103]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1bAdFR-0001nr-Ok for xen-devel@lists.xenproject.org; Wed, 08 Jun 2016 13:10:17 +0000 In-Reply-To: <575833E402000078000F30E7@prv-mh.provo.novell.com> List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xen.org Sender: "Xen-devel" To: xen-devel Cc: Paul Durrant List-Id: xen-devel@lists.xenproject.org This is a MIME message. If you are reading this text, you may want to consider changing to a mail reader or gateway that understands how to properly handle MIME multipart messages. --=__Part5D6B5F23.1__= Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: quoted-printable Content-Disposition: inline If we have the translation result available already, we should also use is here. In my tests with Linux guests this eliminates all calls to hvmemul_linear_to_phys() out of the two functions being changed. Signed-off-by: Jan Beulich --- a/xen/arch/x86/hvm/emulate.c +++ b/xen/arch/x86/hvm/emulate.c @@ -1156,6 +1156,7 @@ static int hvmemul_rep_movs( { struct hvm_emulate_ctxt *hvmemul_ctxt =3D container_of(ctxt, struct hvm_emulate_ctxt, ctxt); + struct hvm_vcpu_io *vio =3D ¤t->arch.hvm_vcpu.hvm_io; unsigned long saddr, daddr, bytes; paddr_t sgpa, dgpa; uint32_t pfec =3D PFEC_page_present; @@ -1178,16 +1179,43 @@ static int hvmemul_rep_movs( if ( hvmemul_ctxt->seg_reg[x86_seg_ss].attr.fields.dpl =3D=3D 3 ) pfec |=3D PFEC_user_mode; =20 - rc =3D hvmemul_linear_to_phys( - saddr, &sgpa, bytes_per_rep, reps, pfec, hvmemul_ctxt); - if ( rc !=3D X86EMUL_OKAY ) - return rc; + bytes =3D PAGE_SIZE - (saddr & ~PAGE_MASK); + if ( vio->mmio_access.read_access && + (vio->mmio_gva =3D=3D (saddr & PAGE_MASK)) && + bytes >=3D bytes_per_rep ) + { + sgpa =3D pfn_to_paddr(vio->mmio_gpfn) | (saddr & ~PAGE_MASK); + if ( *reps * bytes_per_rep > bytes ) + *reps =3D bytes / bytes_per_rep; + } + else + { + rc =3D hvmemul_linear_to_phys(saddr, &sgpa, bytes_per_rep, reps, = pfec, + hvmemul_ctxt); + if ( rc !=3D X86EMUL_OKAY ) + return rc; =20 - rc =3D hvmemul_linear_to_phys( - daddr, &dgpa, bytes_per_rep, reps, - pfec | PFEC_write_access, hvmemul_ctxt); - if ( rc !=3D X86EMUL_OKAY ) - return rc; + latch_linear_to_phys(vio, saddr, sgpa, 0); + } + + bytes =3D PAGE_SIZE - (daddr & ~PAGE_MASK); + if ( vio->mmio_access.write_access && + (vio->mmio_gva =3D=3D (daddr & PAGE_MASK)) && + bytes >=3D bytes_per_rep ) + { + dgpa =3D pfn_to_paddr(vio->mmio_gpfn) | (daddr & ~PAGE_MASK); + if ( *reps * bytes_per_rep > bytes ) + *reps =3D bytes / bytes_per_rep; + } + else + { + rc =3D hvmemul_linear_to_phys(daddr, &dgpa, bytes_per_rep, reps, + pfec | PFEC_write_access, hvmemul_ctxt= ); + if ( rc !=3D X86EMUL_OKAY ) + return rc; + + latch_linear_to_phys(vio, daddr, dgpa, 1); + } =20 /* Check for MMIO ops */ (void) get_gfn_query_unlocked(current->domain, sgpa >> PAGE_SHIFT, = &sp2mt); @@ -1279,25 +1307,40 @@ static int hvmemul_rep_stos( { struct hvm_emulate_ctxt *hvmemul_ctxt =3D container_of(ctxt, struct hvm_emulate_ctxt, ctxt); - unsigned long addr; + struct hvm_vcpu_io *vio =3D ¤t->arch.hvm_vcpu.hvm_io; + unsigned long addr, bytes; paddr_t gpa; p2m_type_t p2mt; bool_t df =3D !!(ctxt->regs->eflags & X86_EFLAGS_DF); int rc =3D hvmemul_virtual_to_linear(seg, offset, bytes_per_rep, = reps, hvm_access_write, hvmemul_ctxt, = &addr); =20 - if ( rc =3D=3D X86EMUL_OKAY ) + if ( rc !=3D X86EMUL_OKAY ) + return rc; + + bytes =3D PAGE_SIZE - (addr & ~PAGE_MASK); + if ( vio->mmio_access.write_access && + (vio->mmio_gva =3D=3D (addr & PAGE_MASK)) && + bytes >=3D bytes_per_rep ) + { + gpa =3D pfn_to_paddr(vio->mmio_gpfn) | (addr & ~PAGE_MASK); + if ( *reps * bytes_per_rep > bytes ) + *reps =3D bytes / bytes_per_rep; + } + else { uint32_t pfec =3D PFEC_page_present | PFEC_write_access; =20 if ( hvmemul_ctxt->seg_reg[x86_seg_ss].attr.fields.dpl =3D=3D 3 ) pfec |=3D PFEC_user_mode; =20 - rc =3D hvmemul_linear_to_phys( - addr, &gpa, bytes_per_rep, reps, pfec, hvmemul_ctxt); + rc =3D hvmemul_linear_to_phys(addr, &gpa, bytes_per_rep, reps, = pfec, + hvmemul_ctxt); + if ( rc !=3D X86EMUL_OKAY ) + return rc; + + latch_linear_to_phys(vio, addr, gpa, 1); } - if ( rc !=3D X86EMUL_OKAY ) - return rc; =20 /* Check for MMIO op */ (void)get_gfn_query_unlocked(current->domain, gpa >> PAGE_SHIFT, = &p2mt); --=__Part5D6B5F23.1__= Content-Type: text/plain; name="x86-HVM-emul-REP-use-addresses.patch" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="x86-HVM-emul-REP-use-addresses.patch" x86/HVM: use available linear->phys translations in REP MOVS/STOS = handling=0A=0AIf we have the translation result available already, we = should also use=0Ais here. In my tests with Linux guests this eliminates = all calls to=0Ahvmemul_linear_to_phys() out of the two functions being = changed.=0A=0ASigned-off-by: Jan Beulich =0A=0A--- = a/xen/arch/x86/hvm/emulate.c=0A+++ b/xen/arch/x86/hvm/emulate.c=0A@@ = -1156,6 +1156,7 @@ static int hvmemul_rep_movs(=0A {=0A struct = hvm_emulate_ctxt *hvmemul_ctxt =3D=0A container_of(ctxt, struct = hvm_emulate_ctxt, ctxt);=0A+ struct hvm_vcpu_io *vio =3D ¤t->arch.= hvm_vcpu.hvm_io;=0A unsigned long saddr, daddr, bytes;=0A paddr_t = sgpa, dgpa;=0A uint32_t pfec =3D PFEC_page_present;=0A@@ -1178,16 = +1179,43 @@ static int hvmemul_rep_movs(=0A if ( hvmemul_ctxt->seg_reg[= x86_seg_ss].attr.fields.dpl =3D=3D 3 )=0A pfec |=3D PFEC_user_mode;= =0A =0A- rc =3D hvmemul_linear_to_phys(=0A- saddr, &sgpa, = bytes_per_rep, reps, pfec, hvmemul_ctxt);=0A- if ( rc !=3D X86EMUL_OKAY = )=0A- return rc;=0A+ bytes =3D PAGE_SIZE - (saddr & ~PAGE_MASK);= =0A+ if ( vio->mmio_access.read_access &&=0A+ (vio->mmio_gva = =3D=3D (saddr & PAGE_MASK)) &&=0A+ bytes >=3D bytes_per_rep )=0A+ = {=0A+ sgpa =3D pfn_to_paddr(vio->mmio_gpfn) | (saddr & ~PAGE_MASK)= ;=0A+ if ( *reps * bytes_per_rep > bytes )=0A+ *reps =3D = bytes / bytes_per_rep;=0A+ }=0A+ else=0A+ {=0A+ rc =3D = hvmemul_linear_to_phys(saddr, &sgpa, bytes_per_rep, reps, pfec,=0A+ = hvmemul_ctxt);=0A+ if ( rc !=3D = X86EMUL_OKAY )=0A+ return rc;=0A =0A- rc =3D hvmemul_linear_t= o_phys(=0A- daddr, &dgpa, bytes_per_rep, reps,=0A- pfec | = PFEC_write_access, hvmemul_ctxt);=0A- if ( rc !=3D X86EMUL_OKAY )=0A- = return rc;=0A+ latch_linear_to_phys(vio, saddr, sgpa, 0);=0A+ = }=0A+=0A+ bytes =3D PAGE_SIZE - (daddr & ~PAGE_MASK);=0A+ if ( = vio->mmio_access.write_access &&=0A+ (vio->mmio_gva =3D=3D (daddr = & PAGE_MASK)) &&=0A+ bytes >=3D bytes_per_rep )=0A+ {=0A+ = dgpa =3D pfn_to_paddr(vio->mmio_gpfn) | (daddr & ~PAGE_MASK);=0A+ = if ( *reps * bytes_per_rep > bytes )=0A+ *reps =3D bytes / = bytes_per_rep;=0A+ }=0A+ else=0A+ {=0A+ rc =3D hvmemul_line= ar_to_phys(daddr, &dgpa, bytes_per_rep, reps,=0A+ = pfec | PFEC_write_access, hvmemul_ctxt);=0A+ if ( rc !=3D = X86EMUL_OKAY )=0A+ return rc;=0A+=0A+ latch_linear_to_phy= s(vio, daddr, dgpa, 1);=0A+ }=0A =0A /* Check for MMIO ops */=0A = (void) get_gfn_query_unlocked(current->domain, sgpa >> PAGE_SHIFT, = &sp2mt);=0A@@ -1279,25 +1307,40 @@ static int hvmemul_rep_stos(=0A {=0A = struct hvm_emulate_ctxt *hvmemul_ctxt =3D=0A container_of(ctxt, = struct hvm_emulate_ctxt, ctxt);=0A- unsigned long addr;=0A+ struct = hvm_vcpu_io *vio =3D ¤t->arch.hvm_vcpu.hvm_io;=0A+ unsigned long = addr, bytes;=0A paddr_t gpa;=0A p2m_type_t p2mt;=0A bool_t df = =3D !!(ctxt->regs->eflags & X86_EFLAGS_DF);=0A int rc =3D hvmemul_virtu= al_to_linear(seg, offset, bytes_per_rep, reps,=0A = hvm_access_write, hvmemul_ctxt, &addr);=0A =0A- if ( rc = =3D=3D X86EMUL_OKAY )=0A+ if ( rc !=3D X86EMUL_OKAY )=0A+ return = rc;=0A+=0A+ bytes =3D PAGE_SIZE - (addr & ~PAGE_MASK);=0A+ if ( = vio->mmio_access.write_access &&=0A+ (vio->mmio_gva =3D=3D (addr & = PAGE_MASK)) &&=0A+ bytes >=3D bytes_per_rep )=0A+ {=0A+ = gpa =3D pfn_to_paddr(vio->mmio_gpfn) | (addr & ~PAGE_MASK);=0A+ if = ( *reps * bytes_per_rep > bytes )=0A+ *reps =3D bytes / = bytes_per_rep;=0A+ }=0A+ else=0A {=0A uint32_t pfec =3D = PFEC_page_present | PFEC_write_access;=0A =0A if ( hvmemul_ctxt->se= g_reg[x86_seg_ss].attr.fields.dpl =3D=3D 3 )=0A pfec |=3D = PFEC_user_mode;=0A =0A- rc =3D hvmemul_linear_to_phys(=0A- = addr, &gpa, bytes_per_rep, reps, pfec, hvmemul_ctxt);=0A+ rc =3D = hvmemul_linear_to_phys(addr, &gpa, bytes_per_rep, reps, pfec,=0A+ = hvmemul_ctxt);=0A+ if ( rc !=3D X86EMUL_OK= AY )=0A+ return rc;=0A+=0A+ latch_linear_to_phys(vio, = addr, gpa, 1);=0A }=0A- if ( rc !=3D X86EMUL_OKAY )=0A- = return rc;=0A =0A /* Check for MMIO op */=0A (void)get_gfn_query_un= locked(current->domain, gpa >> PAGE_SHIFT, &p2mt);=0A --=__Part5D6B5F23.1__= Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: base64 Content-Disposition: inline X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KWGVuLWRldmVs IG1haWxpbmcgbGlzdApYZW4tZGV2ZWxAbGlzdHMueGVuLm9yZwpodHRwOi8vbGlzdHMueGVuLm9y Zy94ZW4tZGV2ZWwK --=__Part5D6B5F23.1__=--