From mboxrd@z Thu Jan 1 00:00:00 1970 From: "Jan Beulich" Subject: [PATCH 04/17] x86emul: track only rIP in emulator state Date: Thu, 08 Sep 2016 07:08:37 -0600 Message-ID: <57D17EF5020000780010D150@prv-mh.provo.novell.com> References: <57D17C78020000780010D127@prv-mh.provo.novell.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=__Part497FC2C5.1__=" Return-path: Received: from mail6.bemta5.messagelabs.com ([195.245.231.135]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1bhz4L-0008Dd-Op for xen-devel@lists.xenproject.org; Thu, 08 Sep 2016 13:08:41 +0000 In-Reply-To: <57D17C78020000780010D127@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 , Jan Beulich Cc: Andrew Cooper 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. --=__Part497FC2C5.1__= Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: quoted-printable Content-Disposition: inline Now that all decoding happens in x86_decode() there's no need to keep the local registers copy in struct x86_emulate_state. Only rIP gets updated in the decode phase, so only that register needs tracking there. All other (read-only) registers can be read from the original structure (but sadly, due to it getting passed to decode_register(), the pointer can't be made point to "const" to make the compiler help ensure no modification happens). Signed-off-by: Jan Beulich --- a/xen/arch/x86/x86_emulate/x86_emulate.c +++ b/xen/arch/x86/x86_emulate/x86_emulate.c @@ -590,9 +590,9 @@ do{ asm volatile ( =20 /* Fetch next part of the instruction being emulated. */ #define insn_fetch_bytes(_size) \ -({ unsigned long _x =3D 0, _eip =3D _regs.eip; = \ - _regs.eip +=3D (_size); /* real hardware doesn't truncate */ = \ - generate_exception_if((uint8_t)(_regs.eip - \ +({ unsigned long _x =3D 0, _eip =3D state->eip; = \ + state->eip +=3D (_size); /* real hardware doesn't truncate */ = \ + generate_exception_if((uint8_t)(state->eip - \ ctxt->regs->eip) > MAX_INST_LEN, \ EXC_GP, 0); \ rc =3D ops->insn_fetch(x86_seg_cs, _eip, &_x, (_size), ctxt); = \ @@ -1582,8 +1582,8 @@ struct x86_emulate_state { #define imm1 ea.val #define imm2 ea.orig_val =20 - /* Shadow copy of register state. Committed on successful emulation. = */ - struct cpu_user_regs regs; + unsigned long eip; + struct cpu_user_regs *regs; }; =20 /* Helper definitions. */ @@ -1599,7 +1599,6 @@ struct x86_emulate_state { #define vex (state->vex) #define override_seg (state->override_seg) #define ea (state->ea) -#define _regs (state->regs) =20 static int x86_decode_base( @@ -1655,7 +1654,8 @@ x86_decode( ea.type =3D OP_MEM; ea.mem.seg =3D x86_seg_ds; ea.reg =3D REG_POISON; - _regs =3D *ctxt->regs; + state->regs =3D ctxt->regs; + state->eip =3D ctxt->regs->eip; =20 ctxt->retire.byte =3D 0; =20 @@ -1759,7 +1759,7 @@ x86_decode( default: BUG(); case 2: - if ( in_realmode(ctxt, ops) || (_regs.eflags & EFLG_VM) ) + if ( in_realmode(ctxt, ops) || (state->regs->eflags & = EFLG_VM) ) break; /* fall through */ case 4: @@ -1885,7 +1885,7 @@ x86_decode( modrm_rm |=3D (rex_prefix & 1) << 3; ea.type =3D OP_REG; ea.reg =3D decode_register( - modrm_rm, &_regs, (d & ByteOp) && (rex_prefix =3D=3D 0)); + modrm_rm, state->regs, (d & ByteOp) && (rex_prefix =3D=3D = 0)); } else if ( ad_bytes =3D=3D 2 ) { @@ -1893,33 +1893,33 @@ x86_decode( switch ( modrm_rm ) { case 0: - ea.mem.off =3D _regs.ebx + _regs.esi; + ea.mem.off =3D state->regs->ebx + state->regs->esi; break; case 1: - ea.mem.off =3D _regs.ebx + _regs.edi; + ea.mem.off =3D state->regs->ebx + state->regs->edi; break; case 2: ea.mem.seg =3D x86_seg_ss; - ea.mem.off =3D _regs.ebp + _regs.esi; + ea.mem.off =3D state->regs->ebp + state->regs->esi; break; case 3: ea.mem.seg =3D x86_seg_ss; - ea.mem.off =3D _regs.ebp + _regs.edi; + ea.mem.off =3D state->regs->ebp + state->regs->edi; break; case 4: - ea.mem.off =3D _regs.esi; + ea.mem.off =3D state->regs->esi; break; case 5: - ea.mem.off =3D _regs.edi; + ea.mem.off =3D state->regs->edi; break; case 6: if ( modrm_mod =3D=3D 0 ) break; ea.mem.seg =3D x86_seg_ss; - ea.mem.off =3D _regs.ebp; + ea.mem.off =3D state->regs->ebp; break; case 7: - ea.mem.off =3D _regs.ebx; + ea.mem.off =3D state->regs->ebx; break; } switch ( modrm_mod ) @@ -1946,14 +1946,15 @@ x86_decode( sib_index =3D ((sib >> 3) & 7) | ((rex_prefix << 2) & 8); sib_base =3D (sib & 7) | ((rex_prefix << 3) & 8); if ( sib_index !=3D 4 ) - ea.mem.off =3D *(long*)decode_register(sib_index, = &_regs, 0); + ea.mem.off =3D *(long *)decode_register(sib_index, + state->regs, = 0); ea.mem.off <<=3D (sib >> 6) & 3; if ( (modrm_mod =3D=3D 0) && ((sib_base & 7) =3D=3D 5) ) ea.mem.off +=3D insn_fetch_type(int32_t); else if ( sib_base =3D=3D 4 ) { ea.mem.seg =3D x86_seg_ss; - ea.mem.off +=3D _regs.esp; + ea.mem.off +=3D state->regs->esp; if ( !ext && (b =3D=3D 0x8f) ) /* POP computes its EA post increment. */ ea.mem.off +=3D ((mode_64bit() && (op_bytes = =3D=3D 4)) @@ -1962,15 +1963,17 @@ x86_decode( else if ( sib_base =3D=3D 5 ) { ea.mem.seg =3D x86_seg_ss; - ea.mem.off +=3D _regs.ebp; + ea.mem.off +=3D state->regs->ebp; } else - ea.mem.off +=3D *(long*)decode_register(sib_base, = &_regs, 0); + ea.mem.off +=3D *(long *)decode_register(sib_base, + state->regs, = 0); } else { modrm_rm |=3D (rex_prefix & 1) << 3; - ea.mem.off =3D *(long *)decode_register(modrm_rm, &_regs, = 0); + ea.mem.off =3D *(long *)decode_register(modrm_rm, + state->regs, 0); if ( (modrm_rm =3D=3D 5) && (modrm_mod !=3D 0) ) ea.mem.seg =3D x86_seg_ss; } @@ -1983,7 +1986,7 @@ x86_decode( if ( !mode_64bit() ) break; /* Relative to RIP of next instruction. Argh! */ - ea.mem.off +=3D _regs.eip; + ea.mem.off +=3D state->eip; if ( (d & SrcMask) =3D=3D SrcImm ) ea.mem.off +=3D (d & ByteOp) ? 1 : ((op_bytes =3D=3D 8) ? 4 : op_bytes); @@ -2061,6 +2064,8 @@ x86_emulate( struct x86_emulate_ctxt *ctxt, const struct x86_emulate_ops *ops) { + /* Shadow copy of register state. Committed on successful emulation. = */ + struct cpu_user_regs _regs =3D *ctxt->regs; struct x86_emulate_state state; int rc; uint8_t b, d; @@ -2074,10 +2079,21 @@ x86_emulate( if ( rc !=3D X86EMUL_OKAY) return rc; =20 + /* Sync rIP to post decode value. */ + _regs.eip =3D state.eip; + b =3D state.opcode; d =3D state.desc; #define state (&state) =20 + /* Re-vector ea's register pointer into our shadow registers. */ + if ( ea.type =3D=3D OP_REG ) + { + unsigned int offs =3D (void *)ea.reg - (void *)state->regs; + + ea.reg =3D (void *)&_regs + offs; + } + /* Decode and fetch the source operand: register, memory or immediate.= */ switch ( d & SrcMask ) { @@ -5003,4 +5019,3 @@ x86_emulate( #undef vex #undef override_seg #undef ea -#undef _regs --=__Part497FC2C5.1__= Content-Type: text/plain; name="x86emul-decode-regs-pointer.patch" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="x86emul-decode-regs-pointer.patch" x86emul: track only rIP in emulator state=0A=0ANow that all decoding = happens in x86_decode() there's no need to keep=0Athe local registers copy = in struct x86_emulate_state. Only rIP gets=0Aupdated in the decode phase, = so only that register needs tracking=0Athere. All other (read-only) = registers can be read from the original=0Astructure (but sadly, due to it = getting passed to decode_register(),=0Athe pointer can't be made point to = "const" to make the compiler help=0Aensure no modification happens).=0A=0AS= igned-off-by: Jan Beulich =0A=0A--- a/xen/arch/x86/x86_e= mulate/x86_emulate.c=0A+++ b/xen/arch/x86/x86_emulate/x86_emulate.c=0A@@ = -590,9 +590,9 @@ do{ asm volatile (=0A =0A /* Fetch next part of the = instruction being emulated. */=0A #define insn_fetch_bytes(_size) = \=0A-({ unsigned long _x =3D 0, _eip =3D = _regs.eip; \=0A- _regs.eip +=3D (_size); /* = real hardware doesn't truncate */ \=0A- generate_exception_if((= uint8_t)(_regs.eip - \=0A+({ unsigned long _x =3D = 0, _eip =3D state->eip; \=0A+ state->eip = +=3D (_size); /* real hardware doesn't truncate */ \=0A+ = generate_exception_if((uint8_t)(state->eip - \=0A = ctxt->regs->eip) > MAX_INST_LEN, = \=0A EXC_GP, 0); = \=0A rc =3D ops->insn_fetch(x86_seg_cs, _eip, &_x, (_size), ctxt); = \=0A@@ -1582,8 +1582,8 @@ struct x86_emulate_state {=0A #define imm1 = ea.val=0A #define imm2 ea.orig_val=0A =0A- /* Shadow copy of register = state. Committed on successful emulation. */=0A- struct cpu_user_regs = regs;=0A+ unsigned long eip;=0A+ struct cpu_user_regs *regs;=0A = };=0A =0A /* Helper definitions. */=0A@@ -1599,7 +1599,6 @@ struct = x86_emulate_state {=0A #define vex (state->vex)=0A #define override_seg = (state->override_seg)=0A #define ea (state->ea)=0A-#define _regs (state->re= gs)=0A =0A static int=0A x86_decode_base(=0A@@ -1655,7 +1654,8 @@ = x86_decode(=0A ea.type =3D OP_MEM;=0A ea.mem.seg =3D x86_seg_ds;=0A= ea.reg =3D REG_POISON;=0A- _regs =3D *ctxt->regs;=0A+ state->reg= s =3D ctxt->regs;=0A+ state->eip =3D ctxt->regs->eip;=0A =0A = ctxt->retire.byte =3D 0;=0A =0A@@ -1759,7 +1759,7 @@ x86_decode(=0A = default:=0A BUG();=0A case 2:=0A- = if ( in_realmode(ctxt, ops) || (_regs.eflags & EFLG_VM) )=0A+ = if ( in_realmode(ctxt, ops) || (state->regs->eflags & EFLG_VM) = )=0A break;=0A /* fall through */=0A = case 4:=0A@@ -1885,7 +1885,7 @@ x86_decode(=0A = modrm_rm |=3D (rex_prefix & 1) << 3;=0A ea.type =3D OP_REG;=0A = ea.reg =3D decode_register(=0A- modrm_rm, = &_regs, (d & ByteOp) && (rex_prefix =3D=3D 0));=0A+ = modrm_rm, state->regs, (d & ByteOp) && (rex_prefix =3D=3D 0));=0A = }=0A else if ( ad_bytes =3D=3D 2 )=0A {=0A@@ -1893,33 = +1893,33 @@ x86_decode(=0A switch ( modrm_rm )=0A = {=0A case 0:=0A- ea.mem.off =3D _regs.ebx + = _regs.esi;=0A+ ea.mem.off =3D state->regs->ebx + state->regs= ->esi;=0A break;=0A case 1:=0A- = ea.mem.off =3D _regs.ebx + _regs.edi;=0A+ ea.mem.off =3D = state->regs->ebx + state->regs->edi;=0A break;=0A = case 2:=0A ea.mem.seg =3D x86_seg_ss;=0A- = ea.mem.off =3D _regs.ebp + _regs.esi;=0A+ ea.mem.off =3D = state->regs->ebp + state->regs->esi;=0A break;=0A = case 3:=0A ea.mem.seg =3D x86_seg_ss;=0A- = ea.mem.off =3D _regs.ebp + _regs.edi;=0A+ ea.mem.off =3D = state->regs->ebp + state->regs->edi;=0A break;=0A = case 4:=0A- ea.mem.off =3D _regs.esi;=0A+ = ea.mem.off =3D state->regs->esi;=0A break;=0A = case 5:=0A- ea.mem.off =3D _regs.edi;=0A+ = ea.mem.off =3D state->regs->edi;=0A break;=0A = case 6:=0A if ( modrm_mod =3D=3D 0 )=0A = break;=0A ea.mem.seg =3D x86_seg_ss;=0A- = ea.mem.off =3D _regs.ebp;=0A+ ea.mem.off =3D state->regs->eb= p;=0A break;=0A case 7:=0A- = ea.mem.off =3D _regs.ebx;=0A+ ea.mem.off =3D state->regs->eb= x;=0A break;=0A }=0A switch ( = modrm_mod )=0A@@ -1946,14 +1946,15 @@ x86_decode(=0A = sib_index =3D ((sib >> 3) & 7) | ((rex_prefix << 2) & 8);=0A = sib_base =3D (sib & 7) | ((rex_prefix << 3) & 8);=0A if = ( sib_index !=3D 4 )=0A- ea.mem.off =3D *(long*)decode_r= egister(sib_index, &_regs, 0);=0A+ ea.mem.off =3D = *(long *)decode_register(sib_index,=0A+ = state->regs, 0);=0A ea.mem.off <<=3D = (sib >> 6) & 3;=0A if ( (modrm_mod =3D=3D 0) && ((sib_base = & 7) =3D=3D 5) )=0A ea.mem.off +=3D insn_fetch_type(int= 32_t);=0A else if ( sib_base =3D=3D 4 )=0A = {=0A ea.mem.seg =3D x86_seg_ss;=0A- = ea.mem.off +=3D _regs.esp;=0A+ ea.mem.off +=3D = state->regs->esp;=0A if ( !ext && (b =3D=3D 0x8f) )=0A = /* POP computes its EA post increment. */=0A = ea.mem.off +=3D ((mode_64bit() && (op_bytes =3D=3D = 4))=0A@@ -1962,15 +1963,17 @@ x86_decode(=0A else if ( = sib_base =3D=3D 5 )=0A {=0A ea.mem.seg = =3D x86_seg_ss;=0A- ea.mem.off +=3D _regs.ebp;=0A+ = ea.mem.off +=3D state->regs->ebp;=0A }=0A = else=0A- ea.mem.off +=3D *(long*)decode_re= gister(sib_base, &_regs, 0);=0A+ ea.mem.off +=3D *(long = *)decode_register(sib_base,=0A+ = state->regs, 0);=0A }=0A else=0A = {=0A modrm_rm |=3D (rex_prefix & 1) << 3;=0A- = ea.mem.off =3D *(long *)decode_register(modrm_rm, &_regs, = 0);=0A+ ea.mem.off =3D *(long *)decode_register(modrm_rm,=0A= + state->regs, 0);=0A = if ( (modrm_rm =3D=3D 5) && (modrm_mod !=3D 0) )=0A = ea.mem.seg =3D x86_seg_ss;=0A }=0A@@ -1983,7 = +1986,7 @@ x86_decode(=0A if ( !mode_64bit() )=0A = break;=0A /* Relative to RIP of next instruction= . Argh! */=0A- ea.mem.off +=3D _regs.eip;=0A+ = ea.mem.off +=3D state->eip;=0A if ( (d & SrcMask) =3D=3D = SrcImm )=0A ea.mem.off +=3D (d & ByteOp) ? 1 :=0A = ((op_bytes =3D=3D 8) ? 4 : op_bytes);=0A@@ -2061,6 = +2064,8 @@ x86_emulate(=0A struct x86_emulate_ctxt *ctxt,=0A const = struct x86_emulate_ops *ops)=0A {=0A+ /* Shadow copy of register state. = Committed on successful emulation. */=0A+ struct cpu_user_regs _regs = =3D *ctxt->regs;=0A struct x86_emulate_state state;=0A int rc;=0A = uint8_t b, d;=0A@@ -2074,10 +2079,21 @@ x86_emulate(=0A if ( rc = !=3D X86EMUL_OKAY)=0A return rc;=0A =0A+ /* Sync rIP to post = decode value. */=0A+ _regs.eip =3D state.eip;=0A+=0A b =3D = state.opcode;=0A d =3D state.desc;=0A #define state (&state)=0A =0A+ = /* Re-vector ea's register pointer into our shadow registers. */=0A+ = if ( ea.type =3D=3D OP_REG )=0A+ {=0A+ unsigned int offs =3D = (void *)ea.reg - (void *)state->regs;=0A+=0A+ ea.reg =3D (void = *)&_regs + offs;=0A+ }=0A+=0A /* Decode and fetch the source = operand: register, memory or immediate. */=0A switch ( d & SrcMask = )=0A {=0A@@ -5003,4 +5019,3 @@ x86_emulate(=0A #undef vex=0A #undef = override_seg=0A #undef ea=0A-#undef _regs=0A --=__Part497FC2C5.1__= Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: base64 Content-Disposition: inline X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KWGVuLWRldmVs IG1haWxpbmcgbGlzdApYZW4tZGV2ZWxAbGlzdHMueGVuLm9yZwpodHRwczovL2xpc3RzLnhlbi5v cmcveGVuLWRldmVsCg== --=__Part497FC2C5.1__=--