From mboxrd@z Thu Jan 1 00:00:00 1970 From: "Jan Beulich" Subject: [PATCH 02/17] x86emul: fetch all insn bytes during the decode phase Date: Thu, 08 Sep 2016 07:07:50 -0600 Message-ID: <57D17EC6020000780010D14C@prv-mh.provo.novell.com> References: <57D17C78020000780010D127@prv-mh.provo.novell.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=__Part3A0CB1B6.1__=" Return-path: Received: from mail6.bemta3.messagelabs.com ([195.245.230.39]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1bhz3b-00087n-Ca for xen-devel@lists.xenproject.org; Thu, 08 Sep 2016 13:07:55 +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 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. --=__Part3A0CB1B6.1__= Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: quoted-printable Content-Disposition: inline This way we can offer to callers the service of just sizing instructions, and we also can better guarantee not to raise the wrong fault due to not having read all relevant bytes. Signed-off-by: Jan Beulich --- a/xen/arch/x86/x86_emulate/x86_emulate.c +++ b/xen/arch/x86/x86_emulate/x86_emulate.c @@ -129,8 +129,8 @@ static const opcode_desc_t opcode_table[ ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps|Mov, ImplicitOps|Mov, ImplicitOps, ImplicitOps, /* 0xA0 - 0xA7 */ - ByteOp|DstEax|SrcImplicit|Mov, DstEax|SrcImplicit|Mov, - ByteOp|ImplicitOps|Mov, ImplicitOps|Mov, + ByteOp|DstEax|SrcMem|Mov, DstEax|SrcMem|Mov, + ByteOp|DstMem|SrcEax|Mov, DstMem|SrcEax|Mov, ByteOp|ImplicitOps|Mov, ImplicitOps|Mov, ByteOp|ImplicitOps, ImplicitOps, /* 0xA8 - 0xAF */ @@ -1602,6 +1602,45 @@ struct x86_emulate_state { #define _regs (state->regs) =20 static int +x86_decode_base( + struct x86_emulate_state *state, + struct x86_emulate_ctxt *ctxt, + const struct x86_emulate_ops *ops) +{ + int rc =3D X86EMUL_OKAY; + + switch ( state->opcode ) + { + case 0x9a: /* call (far, absolute) */ + case 0xea: /* jmp (far, absolute) */ + generate_exception_if(mode_64bit(), EXC_UD, -1); + + imm1 =3D insn_fetch_bytes(op_bytes); + imm2 =3D insn_fetch_type(uint16_t); + break; + + case 0xa0: case 0xa1: /* mov mem.offs,{%al,%ax,%eax,%rax} */ + case 0xa2: case 0xa3: /* mov {%al,%ax,%eax,%rax},mem.offs */ + /* Source EA is not encoded via ModRM. */ + ea.mem.off =3D insn_fetch_bytes(ad_bytes); + break; + + case 0xb8 ... 0xbf: /* mov imm{16,32,64},r{16,32,64} */ + if ( op_bytes =3D=3D 8 ) /* Fetch more bytes to obtain imm64. */ + imm1 =3D ((uint32_t)imm1 | + ((uint64_t)insn_fetch_type(uint32_t) << 32)); + break; + + case 0xc8: /* enter imm16,imm8 */ + imm2 =3D insn_fetch_type(uint8_t); + break; + } + + done: + return rc; +} + +static int x86_decode( struct x86_emulate_state *state, struct x86_emulate_ctxt *ctxt, @@ -1994,10 +2033,29 @@ x86_decode( state->opcode =3D b; state->desc =3D d; =20 + switch ( ext ) + { + case ext_none: + rc =3D x86_decode_base(state, ctxt, ops); + break; + + case ext_0f: + case ext_0f38: + break; + + default: + ASSERT_UNREACHABLE(); + return X86EMUL_UNHANDLEABLE; + } + done: return rc; } =20 +/* No insn fetching past this point. */ +#undef insn_fetch_bytes +#undef insn_fetch_type + int x86_emulate( struct x86_emulate_ctxt *ctxt, @@ -2560,6 +2618,8 @@ x86_emulate( case 0xc6 ... 0xc7: /* mov (sole member of Grp11) */ generate_exception_if((modrm_reg & 7) !=3D 0, EXC_UD, -1); case 0x88 ... 0x8b: /* mov */ + case 0xa0 ... 0xa1: /* mov mem.offs,{%al,%ax,%eax,%rax} */ + case 0xa2 ... 0xa3: /* mov {%al,%ax,%eax,%rax},mem.offs */ dst.val =3D src.val; break; =20 @@ -2644,18 +2704,13 @@ x86_emulate( =20 case 0x9a: /* call (far, absolute) */ { struct segment_register reg; - uint16_t sel; - uint32_t eip; =20 - generate_exception_if(mode_64bit(), EXC_UD, -1); + ASSERT(!mode_64bit()); fail_if(ops->read_segment =3D=3D NULL); =20 - eip =3D insn_fetch_bytes(op_bytes); - sel =3D insn_fetch_type(uint16_t); - if ( (rc =3D ops->read_segment(x86_seg_cs, ®, ctxt)) || - (rc =3D load_seg(x86_seg_cs, sel, 0, &cs, ctxt, ops)) || - (validate_far_branch(&cs, eip), + (rc =3D load_seg(x86_seg_cs, imm2, 0, &cs, ctxt, ops)) || + (validate_far_branch(&cs, imm1), rc =3D ops->write(x86_seg_ss, sp_pre_dec(op_bytes), ®.sel, op_bytes, ctxt)) || (rc =3D ops->write(x86_seg_ss, sp_pre_dec(op_bytes), @@ -2663,7 +2718,7 @@ x86_emulate( (rc =3D ops->write_segment(x86_seg_cs, &cs, ctxt)) ) goto done; =20 - _regs.eip =3D eip; + _regs.eip =3D imm1; break; } =20 @@ -2706,23 +2761,6 @@ x86_emulate( ((uint8_t *)&_regs.eax)[1] =3D (_regs.eflags & 0xd7) | 0x02; break; =20 - case 0xa0 ... 0xa1: /* mov mem.offs,{%al,%ax,%eax,%rax} */ - /* Source EA is not encoded via ModRM. */ - dst.bytes =3D (d & ByteOp) ? 1 : op_bytes; - if ( (rc =3D read_ulong(ea.mem.seg, insn_fetch_bytes(ad_bytes), - &dst.val, dst.bytes, ctxt, ops)) !=3D 0 ) - goto done; - break; - - case 0xa2 ... 0xa3: /* mov {%al,%ax,%eax,%rax},mem.offs */ - /* Destination EA is not encoded via ModRM. */ - dst.type =3D OP_MEM; - dst.mem.seg =3D ea.mem.seg; - dst.mem.off =3D insn_fetch_bytes(ad_bytes); - dst.bytes =3D (d & ByteOp) ? 1 : op_bytes; - dst.val =3D (unsigned long)_regs.eax; - break; - case 0xa4 ... 0xa5: /* movs */ { unsigned long nr_reps =3D get_rep_prefix(); dst.bytes =3D (d & ByteOp) ? 1 : op_bytes; @@ -2840,9 +2878,6 @@ x86_emulate( break; =20 case 0xb8 ... 0xbf: /* mov imm{16,32,64},r{16,32,64} */ - if ( dst.bytes =3D=3D 8 ) /* Fetch more bytes to obtain imm64 */ - src.val =3D ((uint32_t)src.val | - ((uint64_t)insn_fetch_type(uint32_t) << 32)); dst.reg =3D decode_register( (b & 7) | ((rex_prefix & 1) << 3), &_regs, 0); dst.val =3D src.val; @@ -2906,7 +2941,7 @@ x86_emulate( goto les; =20 case 0xc8: /* enter imm16,imm8 */ { - uint8_t depth =3D insn_fetch_type(uint8_t) & 31; + uint8_t depth =3D imm2 & 31; int i; =20 dst.type =3D OP_REG; @@ -3627,17 +3662,12 @@ x86_emulate( jmp_rel((int32_t)src.val); break; =20 - case 0xea: /* jmp (far, absolute) */ { - uint16_t sel; - uint32_t eip; - generate_exception_if(mode_64bit(), EXC_UD, -1); - eip =3D insn_fetch_bytes(op_bytes); - sel =3D insn_fetch_type(uint16_t); - if ( (rc =3D load_seg(x86_seg_cs, sel, 0, &cs, ctxt, ops)) || - (rc =3D commit_far_branch(&cs, eip)) ) + case 0xea: /* jmp (far, absolute) */ + ASSERT(!mode_64bit()); + if ( (rc =3D load_seg(x86_seg_cs, imm2, 0, &cs, ctxt, ops)) || + (rc =3D commit_far_branch(&cs, imm1)) ) goto done; break; - } =20 case 0xf1: /* int1 (icebp) */ src.val =3D EXC_DB; --=__Part3A0CB1B6.1__= Content-Type: text/plain; name="x86emul-decode-base.patch" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="x86emul-decode-base.patch" x86emul: fetch all insn bytes during the decode phase=0A=0AThis way we can = offer to callers the service of just sizing=0Ainstructions, and we also = can better guarantee not to raise the wrong=0Afault due to not having read = all relevant bytes.=0A=0ASigned-off-by: Jan Beulich =0A= =0A--- a/xen/arch/x86/x86_emulate/x86_emulate.c=0A+++ b/xen/arch/x86/x86_em= ulate/x86_emulate.c=0A@@ -129,8 +129,8 @@ static const opcode_desc_t = opcode_table[=0A ImplicitOps, ImplicitOps, ImplicitOps, ImplicitOps,=0A= ImplicitOps|Mov, ImplicitOps|Mov, ImplicitOps, ImplicitOps,=0A /* = 0xA0 - 0xA7 */=0A- ByteOp|DstEax|SrcImplicit|Mov, DstEax|SrcImplicit|Mov= ,=0A- ByteOp|ImplicitOps|Mov, ImplicitOps|Mov,=0A+ ByteOp|DstEax|SrcM= em|Mov, DstEax|SrcMem|Mov,=0A+ ByteOp|DstMem|SrcEax|Mov, DstMem|SrcEax|M= ov,=0A ByteOp|ImplicitOps|Mov, ImplicitOps|Mov,=0A ByteOp|ImplicitO= ps, ImplicitOps,=0A /* 0xA8 - 0xAF */=0A@@ -1602,6 +1602,45 @@ struct = x86_emulate_state {=0A #define _regs (state->regs)=0A =0A static int=0A+x86= _decode_base(=0A+ struct x86_emulate_state *state,=0A+ struct = x86_emulate_ctxt *ctxt,=0A+ const struct x86_emulate_ops *ops)=0A+{=0A+ = int rc =3D X86EMUL_OKAY;=0A+=0A+ switch ( state->opcode )=0A+ = {=0A+ case 0x9a: /* call (far, absolute) */=0A+ case 0xea: /* jmp = (far, absolute) */=0A+ generate_exception_if(mode_64bit(), EXC_UD, = -1);=0A+=0A+ imm1 =3D insn_fetch_bytes(op_bytes);=0A+ imm2 = =3D insn_fetch_type(uint16_t);=0A+ break;=0A+=0A+ case 0xa0: = case 0xa1: /* mov mem.offs,{%al,%ax,%eax,%rax} */=0A+ case 0xa2: case = 0xa3: /* mov {%al,%ax,%eax,%rax},mem.offs */=0A+ /* Source EA is = not encoded via ModRM. */=0A+ ea.mem.off =3D insn_fetch_bytes(ad_byt= es);=0A+ break;=0A+=0A+ case 0xb8 ... 0xbf: /* mov imm{16,32,64},= r{16,32,64} */=0A+ if ( op_bytes =3D=3D 8 ) /* Fetch more bytes to = obtain imm64. */=0A+ imm1 =3D ((uint32_t)imm1 |=0A+ = ((uint64_t)insn_fetch_type(uint32_t) << 32));=0A+ break;=0A+= =0A+ case 0xc8: /* enter imm16,imm8 */=0A+ imm2 =3D insn_fetch_ty= pe(uint8_t);=0A+ break;=0A+ }=0A+=0A+ done:=0A+ return = rc;=0A+}=0A+=0A+static int=0A x86_decode(=0A struct x86_emulate_state = *state,=0A struct x86_emulate_ctxt *ctxt,=0A@@ -1994,10 +2033,29 @@ = x86_decode(=0A state->opcode =3D b;=0A state->desc =3D d;=0A =0A+ = switch ( ext )=0A+ {=0A+ case ext_none:=0A+ rc =3D = x86_decode_base(state, ctxt, ops);=0A+ break;=0A+=0A+ case = ext_0f:=0A+ case ext_0f38:=0A+ break;=0A+=0A+ default:=0A+ = ASSERT_UNREACHABLE();=0A+ return X86EMUL_UNHANDLEABLE;=0A+ = }=0A+=0A done:=0A return rc;=0A }=0A =0A+/* No insn fetching past = this point. */=0A+#undef insn_fetch_bytes=0A+#undef insn_fetch_type=0A+=0A = int=0A x86_emulate(=0A struct x86_emulate_ctxt *ctxt,=0A@@ -2560,6 = +2618,8 @@ x86_emulate(=0A case 0xc6 ... 0xc7: /* mov (sole member of = Grp11) */=0A generate_exception_if((modrm_reg & 7) !=3D 0, EXC_UD, = -1);=0A case 0x88 ... 0x8b: /* mov */=0A+ case 0xa0 ... 0xa1: /* = mov mem.offs,{%al,%ax,%eax,%rax} */=0A+ case 0xa2 ... 0xa3: /* mov = {%al,%ax,%eax,%rax},mem.offs */=0A dst.val =3D src.val;=0A = break;=0A =0A@@ -2644,18 +2704,13 @@ x86_emulate(=0A =0A case 0x9a: /* = call (far, absolute) */ {=0A struct segment_register reg;=0A- = uint16_t sel;=0A- uint32_t eip;=0A =0A- generate_exception_= if(mode_64bit(), EXC_UD, -1);=0A+ ASSERT(!mode_64bit());=0A = fail_if(ops->read_segment =3D=3D NULL);=0A =0A- eip =3D insn_fetch_b= ytes(op_bytes);=0A- sel =3D insn_fetch_type(uint16_t);=0A-=0A = if ( (rc =3D ops->read_segment(x86_seg_cs, ®, ctxt)) ||=0A- = (rc =3D load_seg(x86_seg_cs, sel, 0, &cs, ctxt, ops)) ||=0A- = (validate_far_branch(&cs, eip),=0A+ (rc =3D load_seg(x86_seg_cs= , imm2, 0, &cs, ctxt, ops)) ||=0A+ (validate_far_branch(&cs, = imm1),=0A rc =3D ops->write(x86_seg_ss, sp_pre_dec(op_bytes),= =0A ®.sel, op_bytes, ctxt)) ||=0A = (rc =3D ops->write(x86_seg_ss, sp_pre_dec(op_bytes),=0A@@ -2663,7 = +2718,7 @@ x86_emulate(=0A (rc =3D ops->write_segment(x86_seg_= cs, &cs, ctxt)) )=0A goto done;=0A =0A- _regs.eip =3D = eip;=0A+ _regs.eip =3D imm1;=0A break;=0A }=0A =0A@@ = -2706,23 +2761,6 @@ x86_emulate(=0A ((uint8_t *)&_regs.eax)[1] =3D = (_regs.eflags & 0xd7) | 0x02;=0A break;=0A =0A- case 0xa0 ... = 0xa1: /* mov mem.offs,{%al,%ax,%eax,%rax} */=0A- /* Source EA is = not encoded via ModRM. */=0A- dst.bytes =3D (d & ByteOp) ? 1 : = op_bytes;=0A- if ( (rc =3D read_ulong(ea.mem.seg, insn_fetch_bytes(a= d_bytes),=0A- &dst.val, dst.bytes, ctxt, = ops)) !=3D 0 )=0A- goto done;=0A- break;=0A-=0A- case = 0xa2 ... 0xa3: /* mov {%al,%ax,%eax,%rax},mem.offs */=0A- /* = Destination EA is not encoded via ModRM. */=0A- dst.type =3D = OP_MEM;=0A- dst.mem.seg =3D ea.mem.seg;=0A- dst.mem.off =3D = insn_fetch_bytes(ad_bytes);=0A- dst.bytes =3D (d & ByteOp) ? 1 : = op_bytes;=0A- dst.val =3D (unsigned long)_regs.eax;=0A- = break;=0A-=0A case 0xa4 ... 0xa5: /* movs */ {=0A unsigned = long nr_reps =3D get_rep_prefix();=0A dst.bytes =3D (d & ByteOp) ? = 1 : op_bytes;=0A@@ -2840,9 +2878,6 @@ x86_emulate(=0A break;=0A = =0A case 0xb8 ... 0xbf: /* mov imm{16,32,64},r{16,32,64} */=0A- = if ( dst.bytes =3D=3D 8 ) /* Fetch more bytes to obtain imm64 */=0A- = src.val =3D ((uint32_t)src.val |=0A- ((uint64_t)= insn_fetch_type(uint32_t) << 32));=0A dst.reg =3D decode_register(= =0A (b & 7) | ((rex_prefix & 1) << 3), &_regs, 0);=0A = dst.val =3D src.val;=0A@@ -2906,7 +2941,7 @@ x86_emulate(=0A goto = les;=0A =0A case 0xc8: /* enter imm16,imm8 */ {=0A- uint8_t = depth =3D insn_fetch_type(uint8_t) & 31;=0A+ uint8_t depth =3D imm2 = & 31;=0A int i;=0A =0A dst.type =3D OP_REG;=0A@@ -3627,17 = +3662,12 @@ x86_emulate(=0A jmp_rel((int32_t)src.val);=0A = break;=0A =0A- case 0xea: /* jmp (far, absolute) */ {=0A- = uint16_t sel;=0A- uint32_t eip;=0A- generate_exception_if(mod= e_64bit(), EXC_UD, -1);=0A- eip =3D insn_fetch_bytes(op_bytes);=0A- = sel =3D insn_fetch_type(uint16_t);=0A- if ( (rc =3D = load_seg(x86_seg_cs, sel, 0, &cs, ctxt, ops)) ||=0A- (rc =3D = commit_far_branch(&cs, eip)) )=0A+ case 0xea: /* jmp (far, absolute) = */=0A+ ASSERT(!mode_64bit());=0A+ if ( (rc =3D load_seg(x86_s= eg_cs, imm2, 0, &cs, ctxt, ops)) ||=0A+ (rc =3D commit_far_bran= ch(&cs, imm1)) )=0A goto done;=0A break;=0A- }=0A = =0A case 0xf1: /* int1 (icebp) */=0A src.val =3D EXC_DB;=0A --=__Part3A0CB1B6.1__= Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: base64 Content-Disposition: inline X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KWGVuLWRldmVs IG1haWxpbmcgbGlzdApYZW4tZGV2ZWxAbGlzdHMueGVuLm9yZwpodHRwczovL2xpc3RzLnhlbi5v cmcveGVuLWRldmVsCg== --=__Part3A0CB1B6.1__=--