From mboxrd@z Thu Jan 1 00:00:00 1970 From: "Jan Beulich" Subject: [PATCH 01/17] x86emul: split instruction decoding from execution Date: Thu, 08 Sep 2016 07:04:40 -0600 Message-ID: <57D17E08020000780010D136@prv-mh.provo.novell.com> References: <57D17C78020000780010D127@prv-mh.provo.novell.com> Mime-Version: 1.0 Content-Type: multipart/mixed; boundary="=__Part7741FCF8.1__=" Return-path: Received: from mail6.bemta6.messagelabs.com ([193.109.254.103]) by lists.xenproject.org with esmtp (Exim 4.84_2) (envelope-from ) id 1bhz0X-0007wz-M3 for xen-devel@lists.xenproject.org; Thu, 08 Sep 2016 13:04:45 +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. --=__Part7741FCF8.1__= Content-Type: text/plain; charset=US-ASCII Content-Transfer-Encoding: quoted-printable Content-Disposition: inline This is only the mechanical part, a subsequent patch will make non- mechanical adjustments to actually do all decoding in this new function. Signed-off-by: Jan Beulich --- a/xen/arch/x86/x86_emulate/x86_emulate.c +++ b/xen/arch/x86/x86_emulate/x86_emulate.c @@ -48,7 +48,9 @@ /* All operands are implicit in the opcode. */ #define ImplicitOps (DstImplicit|SrcImplicit) =20 -static uint8_t opcode_table[256] =3D { +typedef uint8_t opcode_desc_t; + +static const opcode_desc_t opcode_table[256] =3D { /* 0x00 - 0x07 */ ByteOp|DstMem|SrcReg|ModRM, DstMem|SrcReg|ModRM, ByteOp|DstReg|SrcMem|ModRM, DstReg|SrcMem|ModRM, @@ -178,7 +180,7 @@ static uint8_t opcode_table[256] =3D { ImplicitOps, ImplicitOps, ByteOp|DstMem|SrcNone|ModRM, DstMem|SrcNone|= ModRM }; =20 -static uint8_t twobyte_table[256] =3D { +static const opcode_desc_t twobyte_table[256] =3D { /* 0x00 - 0x07 */ SrcMem16|ModRM, ImplicitOps|ModRM, 0, 0, 0, ImplicitOps, ImplicitOps, = 0, /* 0x08 - 0x0F */ @@ -607,7 +609,7 @@ do{ asm volatile ( }) #define truncate_ea(ea) truncate_word((ea), ad_bytes) =20 -#define mode_64bit() (def_ad_bytes =3D=3D 8) +#define mode_64bit() (ctxt->addr_size =3D=3D 64) =20 #define fail_if(p) \ do { \ @@ -1558,32 +1560,63 @@ int x86emul_unhandleable_rw( return X86EMUL_UNHANDLEABLE; } =20 -int -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 { + unsigned int op_bytes, ad_bytes; + + enum { ext_none, ext_0f, ext_0f38 } ext; + uint8_t opcode; + uint8_t modrm, modrm_mod, modrm_reg, modrm_rm; + uint8_t rex_prefix; + bool lock_prefix; + opcode_desc_t desc; + union vex vex; + int override_seg; =20 - uint8_t b, d, sib, sib_index, sib_base, rex_prefix =3D 0; - uint8_t modrm =3D 0, modrm_mod =3D 0, modrm_reg =3D 0, modrm_rm =3D = 0; - enum { ext_none, ext_0f, ext_0f38 } ext =3D ext_none; - union vex vex =3D {}; - unsigned int op_bytes, def_op_bytes, ad_bytes, def_ad_bytes; - bool_t lock_prefix =3D 0; - int override_seg =3D -1, rc =3D X86EMUL_OKAY; - struct operand src =3D { .reg =3D REG_POISON }; - struct operand dst =3D { .reg =3D REG_POISON }; - enum x86_swint_type swint_type; - struct x86_emulate_stub stub =3D {}; - DECLARE_ALIGNED(mmval_t, mmval); /* * Data operand effective address (usually computed from ModRM). * Default is a memory operand relative to segment DS. */ - struct operand ea =3D { .type =3D OP_MEM, .reg =3D REG_POISON }; - ea.mem.seg =3D x86_seg_ds; /* gcc may reject anon union initializer = */ + struct operand ea; + + /* Immediate operand values, if any. Use otherwise unused fields. */ +#define imm1 ea.val +#define imm2 ea.orig_val + + /* Shadow copy of register state. Committed on successful emulation. = */ + struct cpu_user_regs regs; +}; + +/* Helper definitions. */ +#define op_bytes (state->op_bytes) +#define ad_bytes (state->ad_bytes) +#define ext (state->ext) +#define modrm (state->modrm) +#define modrm_mod (state->modrm_mod) +#define modrm_reg (state->modrm_reg) +#define modrm_rm (state->modrm_rm) +#define rex_prefix (state->rex_prefix) +#define lock_prefix (state->lock_prefix) +#define vex (state->vex) +#define override_seg (state->override_seg) +#define ea (state->ea) +#define _regs (state->regs) + +static int +x86_decode( + struct x86_emulate_state *state, + struct x86_emulate_ctxt *ctxt, + const struct x86_emulate_ops *ops) +{ + uint8_t b, d, sib, sib_index, sib_base; + unsigned int def_op_bytes, def_ad_bytes; + int rc =3D X86EMUL_OKAY; + + memset(state, 0, sizeof(*state)); + override_seg =3D -1; + ea.type =3D OP_MEM; + ea.mem.seg =3D x86_seg_ds; + ea.reg =3D REG_POISON; + _regs =3D *ctxt->regs; =20 ctxt->retire.byte =3D 0; =20 @@ -1800,7 +1833,7 @@ x86_emulate( d =3D (d & ~(DstMask | SrcMask)) | DstMem | SrcReg | = Mov; break; default: /* Until it is worth making this table based ... */ - goto cannot_emulate; + return X86EMUL_UNHANDLEABLE; } break; =20 @@ -1932,6 +1965,61 @@ x86_emulate( if ( override_seg !=3D -1 && ea.type =3D=3D OP_MEM ) ea.mem.seg =3D override_seg; =20 + /* Fetch the immediate operand, if present. */ + switch ( d & SrcMask ) + { + unsigned int bytes; + + case SrcImm: + if ( !(d & ByteOp) ) + bytes =3D op_bytes !=3D 8 ? op_bytes : 4; + else + { + case SrcImmByte: + bytes =3D 1; + } + /* NB. Immediates are sign-extended as necessary. */ + switch ( bytes ) + { + case 1: imm1 =3D insn_fetch_type(int8_t); break; + case 2: imm1 =3D insn_fetch_type(int16_t); break; + case 4: imm1 =3D insn_fetch_type(int32_t); break; + } + break; + case SrcImm16: + imm1 =3D insn_fetch_type(uint16_t); + break; + } + + state->opcode =3D b; + state->desc =3D d; + + done: + return rc; +} + +int +x86_emulate( + struct x86_emulate_ctxt *ctxt, + const struct x86_emulate_ops *ops) +{ + struct x86_emulate_state state; + int rc; + uint8_t b, d; + struct operand src =3D { .reg =3D REG_POISON }; + struct operand dst =3D { .reg =3D REG_POISON }; + enum x86_swint_type swint_type; + struct x86_emulate_stub stub =3D {}; + DECLARE_ALIGNED(mmval_t, mmval); + + rc =3D x86_decode(&state, ctxt, ops); + if ( rc !=3D X86EMUL_OKAY) + return rc; + + b =3D state.opcode; + d =3D state.desc; +#define state (&state) + /* Decode and fetch the source operand: register, memory or immediate.= */ switch ( d & SrcMask ) { @@ -1987,18 +2075,12 @@ x86_emulate( src.bytes =3D 1; } src.type =3D OP_IMM; - /* NB. Immediates are sign-extended as necessary. */ - switch ( src.bytes ) - { - case 1: src.val =3D insn_fetch_type(int8_t); break; - case 2: src.val =3D insn_fetch_type(int16_t); break; - case 4: src.val =3D insn_fetch_type(int32_t); break; - } + src.val =3D imm1; break; case SrcImm16: src.type =3D OP_IMM; src.bytes =3D 2; - src.val =3D insn_fetch_type(uint16_t); + src.val =3D imm1; break; } =20 @@ -3892,8 +3974,8 @@ x86_emulate( /* Commit shadow register state. */ _regs.eflags &=3D ~EFLG_RF; =20 - /* Zero the upper 32 bits of %rip if not in long mode. */ - if ( def_ad_bytes < sizeof(_regs.eip) ) + /* Zero the upper 32 bits of %rip if not in 64-bit mode. */ + if ( !mode_64bit() ) _regs.eip =3D (uint32_t)_regs.eip; =20 *ctxt->regs =3D _regs; @@ -4876,4 +4958,19 @@ x86_emulate( _put_fpu(); put_stub(stub); return X86EMUL_UNHANDLEABLE; +#undef state } + +#undef op_bytes +#undef ad_bytes +#undef ext +#undef modrm +#undef modrm_mod +#undef modrm_reg +#undef modrm_rm +#undef rex_prefix +#undef lock_prefix +#undef vex +#undef override_seg +#undef ea +#undef _regs --=__Part7741FCF8.1__= Content-Type: text/plain; name="x86emul-split-decode.patch" Content-Transfer-Encoding: quoted-printable Content-Disposition: attachment; filename="x86emul-split-decode.patch" x86emul: split instruction decoding from execution=0A=0AThis is only the = mechanical part, a subsequent patch will make non-=0Amechanical adjustments= to actually do all decoding in this new=0Afunction.=0A=0ASigned-off-by: = Jan Beulich =0A=0A--- a/xen/arch/x86/x86_emulate/x86_emu= late.c=0A+++ b/xen/arch/x86/x86_emulate/x86_emulate.c=0A@@ -48,7 +48,9 = @@=0A /* All operands are implicit in the opcode. */=0A #define ImplicitOps= (DstImplicit|SrcImplicit)=0A =0A-static uint8_t opcode_table[256] =3D = {=0A+typedef uint8_t opcode_desc_t;=0A+=0A+static const opcode_desc_t = opcode_table[256] =3D {=0A /* 0x00 - 0x07 */=0A ByteOp|DstMem|SrcRe= g|ModRM, DstMem|SrcReg|ModRM,=0A ByteOp|DstReg|SrcMem|ModRM, DstReg|Src= Mem|ModRM,=0A@@ -178,7 +180,7 @@ static uint8_t opcode_table[256] =3D {=0A = ImplicitOps, ImplicitOps, ByteOp|DstMem|SrcNone|ModRM, DstMem|SrcNone|M= odRM=0A };=0A =0A-static uint8_t twobyte_table[256] =3D {=0A+static const = opcode_desc_t twobyte_table[256] =3D {=0A /* 0x00 - 0x07 */=0A = SrcMem16|ModRM, ImplicitOps|ModRM, 0, 0, 0, ImplicitOps, ImplicitOps, = 0,=0A /* 0x08 - 0x0F */=0A@@ -607,7 +609,7 @@ do{ asm volatile (=0A = })=0A #define truncate_ea(ea) truncate_word((ea), ad_bytes)=0A =0A-#define = mode_64bit() (def_ad_bytes =3D=3D 8)=0A+#define mode_64bit() (ctxt->addr_si= ze =3D=3D 64)=0A =0A #define fail_if(p) = \=0A do { \=0A@@ = -1558,32 +1560,63 @@ int x86emul_unhandleable_rw(=0A return X86EMUL_UNH= ANDLEABLE;=0A }=0A =0A-int=0A-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 = {=0A+ unsigned int op_bytes, ad_bytes;=0A+=0A+ enum { ext_none, = ext_0f, ext_0f38 } ext;=0A+ uint8_t opcode;=0A+ uint8_t modrm, = modrm_mod, modrm_reg, modrm_rm;=0A+ uint8_t rex_prefix;=0A+ bool = lock_prefix;=0A+ opcode_desc_t desc;=0A+ union vex vex;=0A+ int = override_seg;=0A =0A- uint8_t b, d, sib, sib_index, sib_base, rex_prefix= =3D 0;=0A- uint8_t modrm =3D 0, modrm_mod =3D 0, modrm_reg =3D 0, = modrm_rm =3D 0;=0A- enum { ext_none, ext_0f, ext_0f38 } ext =3D = ext_none;=0A- union vex vex =3D {};=0A- unsigned int op_bytes, = def_op_bytes, ad_bytes, def_ad_bytes;=0A- bool_t lock_prefix =3D 0;=0A- = int override_seg =3D -1, rc =3D X86EMUL_OKAY;=0A- struct operand src = =3D { .reg =3D REG_POISON };=0A- struct operand dst =3D { .reg =3D = REG_POISON };=0A- enum x86_swint_type swint_type;=0A- struct = x86_emulate_stub stub =3D {};=0A- DECLARE_ALIGNED(mmval_t, mmval);=0A = /*=0A * Data operand effective address (usually computed from = ModRM).=0A * Default is a memory operand relative to segment DS.=0A = */=0A- struct operand ea =3D { .type =3D OP_MEM, .reg =3D REG_POISON = };=0A- ea.mem.seg =3D x86_seg_ds; /* gcc may reject anon union = initializer */=0A+ struct operand ea;=0A+=0A+ /* Immediate operand = values, if any. Use otherwise unused fields. */=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+};=0A+=0A+/* Helper definitions. */=0A+#define op_bytes (state->op= _bytes)=0A+#define ad_bytes (state->ad_bytes)=0A+#define ext (state->ext)= =0A+#define modrm (state->modrm)=0A+#define modrm_mod (state->modrm_mod)=0A= +#define modrm_reg (state->modrm_reg)=0A+#define modrm_rm (state->modrm_rm)= =0A+#define rex_prefix (state->rex_prefix)=0A+#define lock_prefix = (state->lock_prefix)=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(=0A+ struct x86_emulate_state = *state,=0A+ struct x86_emulate_ctxt *ctxt,=0A+ const struct = x86_emulate_ops *ops)=0A+{=0A+ uint8_t b, d, sib, sib_index, = sib_base;=0A+ unsigned int def_op_bytes, def_ad_bytes;=0A+ int rc = =3D X86EMUL_OKAY;=0A+=0A+ memset(state, 0, sizeof(*state));=0A+ = override_seg =3D -1;=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 = =0A ctxt->retire.byte =3D 0;=0A =0A@@ -1800,7 +1833,7 @@ x86_emulate(= =0A d =3D (d & ~(DstMask | SrcMask)) | DstMem | SrcReg = | Mov;=0A break;=0A default: /* Until it is = worth making this table based ... */=0A- goto cannot_emulate= ;=0A+ return X86EMUL_UNHANDLEABLE;=0A }=0A = break;=0A =0A@@ -1932,6 +1965,61 @@ x86_emulate(=0A if ( = override_seg !=3D -1 && ea.type =3D=3D OP_MEM )=0A ea.mem.seg =3D = override_seg;=0A =0A+ /* Fetch the immediate operand, if present. = */=0A+ switch ( d & SrcMask )=0A+ {=0A+ unsigned int = bytes;=0A+=0A+ case SrcImm:=0A+ if ( !(d & ByteOp) )=0A+ = bytes =3D op_bytes !=3D 8 ? op_bytes : 4;=0A+ else=0A+ = {=0A+ case SrcImmByte:=0A+ bytes =3D 1;=0A+ }=0A+ = /* NB. Immediates are sign-extended as necessary. */=0A+ switch = ( bytes )=0A+ {=0A+ case 1: imm1 =3D insn_fetch_type(int8_t);= break;=0A+ case 2: imm1 =3D insn_fetch_type(int16_t); break;=0A+ = case 4: imm1 =3D insn_fetch_type(int32_t); break;=0A+ }=0A+ = break;=0A+ case SrcImm16:=0A+ imm1 =3D insn_fetch_type(uint1= 6_t);=0A+ break;=0A+ }=0A+=0A+ state->opcode =3D b;=0A+ = state->desc =3D d;=0A+=0A+ done:=0A+ return rc;=0A+}=0A+=0A+int=0A+x86_e= mulate(=0A+ struct x86_emulate_ctxt *ctxt,=0A+ const struct = x86_emulate_ops *ops)=0A+{=0A+ struct x86_emulate_state state;=0A+ = int rc;=0A+ uint8_t b, d;=0A+ struct operand src =3D { .reg =3D = REG_POISON };=0A+ struct operand dst =3D { .reg =3D REG_POISON };=0A+ = enum x86_swint_type swint_type;=0A+ struct x86_emulate_stub stub =3D = {};=0A+ DECLARE_ALIGNED(mmval_t, mmval);=0A+=0A+ rc =3D x86_decode(&s= tate, ctxt, ops);=0A+ if ( rc !=3D X86EMUL_OKAY)=0A+ return = rc;=0A+=0A+ b =3D state.opcode;=0A+ d =3D state.desc;=0A+#define = state (&state)=0A+=0A /* Decode and fetch the source operand: = register, memory or immediate. */=0A switch ( d & SrcMask )=0A = {=0A@@ -1987,18 +2075,12 @@ x86_emulate(=0A src.bytes =3D = 1;=0A }=0A src.type =3D OP_IMM;=0A- /* NB. = Immediates are sign-extended as necessary. */=0A- switch ( = src.bytes )=0A- {=0A- case 1: src.val =3D insn_fetch_type(int= 8_t); break;=0A- case 2: src.val =3D insn_fetch_type(int16_t); = break;=0A- case 4: src.val =3D insn_fetch_type(int32_t); break;=0A- = }=0A+ src.val =3D imm1;=0A break;=0A case = SrcImm16:=0A src.type =3D OP_IMM;=0A src.bytes =3D 2;=0A- = src.val =3D insn_fetch_type(uint16_t);=0A+ src.val =3D = imm1;=0A break;=0A }=0A =0A@@ -3892,8 +3974,8 @@ x86_emulate(= =0A /* Commit shadow register state. */=0A _regs.eflags &=3D = ~EFLG_RF;=0A =0A- /* Zero the upper 32 bits of %rip if not in long = mode. */=0A- if ( def_ad_bytes < sizeof(_regs.eip) )=0A+ /* Zero the = upper 32 bits of %rip if not in 64-bit mode. */=0A+ if ( !mode_64bit() = )=0A _regs.eip =3D (uint32_t)_regs.eip;=0A =0A *ctxt->regs =3D = _regs;=0A@@ -4876,4 +4958,19 @@ x86_emulate(=0A _put_fpu();=0A = put_stub(stub);=0A return X86EMUL_UNHANDLEABLE;=0A+#undef state=0A = }=0A+=0A+#undef op_bytes=0A+#undef ad_bytes=0A+#undef ext=0A+#undef = modrm=0A+#undef modrm_mod=0A+#undef modrm_reg=0A+#undef modrm_rm=0A+#undef = rex_prefix=0A+#undef lock_prefix=0A+#undef vex=0A+#undef override_seg=0A+#u= ndef ea=0A+#undef _regs=0A --=__Part7741FCF8.1__= Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: base64 Content-Disposition: inline X19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX19fX18KWGVuLWRldmVs IG1haWxpbmcgbGlzdApYZW4tZGV2ZWxAbGlzdHMueGVuLm9yZwpodHRwczovL2xpc3RzLnhlbi5v cmcveGVuLWRldmVsCg== --=__Part7741FCF8.1__=--