[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Xen-devel] [PATCH] x86/emul: Calculate not_64bit during instruction decode



... rather than repeating "generate_exception_if(mode_64bit(), EXC_UD);" in
the emulation switch statement.

Bloat-o-meter shows:

  add/remove: 0/0 grow/shrink: 1/2 up/down: 8/-495 (-487)
  function                                     old     new   delta
  per_cpu__state                                98     106      +8
  x86_decode                                  6782    6726     -56
  x86_emulate                                57160   56721    -439

The reason for x86_decode() getting smaller is that this change alters the
x86_decode_onebyte() switch statement from a chain of if()/else's to a jump
table.  The jump table adds 250 bytes of data which bloat-o-meter clearly
can't see.

Signed-off-by: Andrew Cooper <andrew.cooper3@xxxxxxxxxx>
---
CC: Jan Beulich <JBeulich@xxxxxxxx>

I am also considering doing similar for vcpu cpuid checks, to split apart the
logic deciding on the feature to check from the emulation logic.  This will
simplify some of the larger blocks, especially the mov emulation.
---
 xen/arch/x86/x86_emulate/x86_emulate.c | 47 +++++++++++++++++++++-------------
 1 file changed, 29 insertions(+), 18 deletions(-)

diff --git a/xen/arch/x86/x86_emulate/x86_emulate.c 
b/xen/arch/x86/x86_emulate/x86_emulate.c
index 445dcac..e9ac1fc 100644
--- a/xen/arch/x86/x86_emulate/x86_emulate.c
+++ b/xen/arch/x86/x86_emulate/x86_emulate.c
@@ -1907,6 +1907,7 @@ struct x86_emulate_state {
     uint8_t modrm, modrm_mod, modrm_reg, modrm_rm;
     uint8_t rex_prefix;
     bool lock_prefix;
+    bool not_64bit; /* Instruction not available in 64bit. */
     opcode_desc_t desc;
     union vex vex;
     union evex evex;
@@ -1957,6 +1958,30 @@ x86_decode_onebyte(
 
     switch ( ctxt->opcode )
     {
+    case 0x06: /* push %%es */
+    case 0x07: /* pop %%es */
+    case 0x0e: /* push %%cs */
+    case 0x16: /* push %%ss */
+    case 0x17: /* pop %%ss */
+    case 0x1e: /* push %%ds */
+    case 0x1f: /* pop %%ds */
+    case 0x27: /* daa */
+    case 0x2f: /* das */
+    case 0x37: /* aaa */
+    case 0x3f: /* aas */
+    case 0x60: /* pusha */
+    case 0x61: /* popa */
+    case 0x62: /* bound */
+    case 0x82: /* Grp1 (x86/32 only) */
+    case 0xc4: /* les */
+    case 0xc5: /* lds */
+    case 0xce: /* into */
+    case 0xd4: /* aam */
+    case 0xd5: /* aad */
+    case 0xd6: /* salc */
+        state->not_64bit = true;
+        break;
+
     case 0x90: /* nop / pause */
         if ( repe_prefix() )
             ctxt->opcode |= X86EMUL_OPC_F3(0, 0);
@@ -2624,6 +2649,8 @@ x86_emulate(
     d = state.desc;
 #define state (&state)
 
+    generate_exception_if(state->not_64bit && mode_64bit(), EXC_UD);
+
     if ( ea.type == OP_REG )
         ea.reg = decode_register(modrm_rm, &_regs,
                                  (d & ByteOp) && !rex_prefix);
@@ -2832,8 +2859,6 @@ x86_emulate(
     case 0x0e: /* push %%cs */
     case 0x16: /* push %%ss */
     case 0x1e: /* push %%ds */
-        generate_exception_if(mode_64bit(), EXC_UD);
-        /* fall through */
     case X86EMUL_OPC(0x0f, 0xa0): /* push %%fs */
     case X86EMUL_OPC(0x0f, 0xa8): /* push %%gs */
         fail_if(ops->read_segment == NULL);
@@ -2846,8 +2871,6 @@ x86_emulate(
     case 0x07: /* pop %%es */
     case 0x17: /* pop %%ss */
     case 0x1f: /* pop %%ds */
-        generate_exception_if(mode_64bit(), EXC_UD);
-        /* fall through */
     case X86EMUL_OPC(0x0f, 0xa1): /* pop %%fs */
     case X86EMUL_OPC(0x0f, 0xa9): /* pop %%gs */
         fail_if(ops->write_segment == NULL);
@@ -2868,7 +2891,6 @@ x86_emulate(
         uint8_t al = _regs.al;
         unsigned int eflags = _regs._eflags;
 
-        generate_exception_if(mode_64bit(), EXC_UD);
         _regs._eflags &= ~(EFLG_CF|EFLG_AF|EFLG_SF|EFLG_ZF|EFLG_PF);
         if ( ((al & 0x0f) > 9) || (eflags & EFLG_AF) )
         {
@@ -2890,7 +2912,6 @@ x86_emulate(
 
     case 0x37: /* aaa */
     case 0x3f: /* aas */
-        generate_exception_if(mode_64bit(), EXC_UD);
         _regs._eflags &= ~EFLG_CF;
         if ( (_regs.al > 9) || (_regs._eflags & EFLG_AF) )
         {
@@ -2935,7 +2956,6 @@ x86_emulate(
             _regs._eax, _regs._ecx, _regs._edx, _regs._ebx,
             _regs._esp, _regs._ebp, _regs._esi, _regs._edi };
 
-        generate_exception_if(mode_64bit(), EXC_UD);
         fail_if(!ops->write);
         for ( i = 0; i < 8; i++ )
             if ( (rc = ops->write(x86_seg_ss, sp_pre_dec(op_bytes),
@@ -2950,7 +2970,6 @@ x86_emulate(
             &_regs._edi, &_regs._esi, &_regs._ebp, &dummy_esp,
             &_regs._ebx, &_regs._edx, &_regs._ecx, &_regs._eax };
 
-        generate_exception_if(mode_64bit(), EXC_UD);
         for ( i = 0; i < 8; i++ )
         {
             if ( (rc = read_ulong(x86_seg_ss, sp_post_inc(op_bytes),
@@ -2967,8 +2986,7 @@ x86_emulate(
     case 0x62: /* bound */ {
         unsigned long src_val2;
         int lb, ub, idx;
-        generate_exception_if(mode_64bit() || (src.type != OP_MEM),
-                              EXC_UD);
+        generate_exception_if(src.type != OP_MEM, EXC_UD);
         if ( (rc = read_ulong(src.mem.seg, src.mem.off + op_bytes,
                               &src_val2, op_bytes, ctxt, ops)) )
             goto done;
@@ -3127,10 +3145,7 @@ x86_emulate(
         adjust_bnd(ctxt, ops, vex.pfx);
         break;
 
-    case 0x82: /* Grp1 (x86/32 only) */
-        generate_exception_if(mode_64bit(), EXC_UD);
-        /* Fallthrough. */
-    case 0x80: case 0x81: case 0x83: /* Grp1 */
+    case 0x80: case 0x81: case 0x82: case 0x83: /* Grp1 */
         switch ( modrm_reg & 7 )
         {
         case 0: goto add;
@@ -3518,7 +3533,6 @@ x86_emulate(
 
     case 0xc4: /* les */
     case 0xc5: /* lds */
-        generate_exception_if(mode_64bit(), EXC_UD);
         seg = (b & 1) * 3; /* es = 0, ds = 3 */
     les:
         generate_exception_if(src.type != OP_MEM, EXC_UD);
@@ -3606,7 +3620,6 @@ x86_emulate(
         goto done;
 
     case 0xce: /* into */
-        generate_exception_if(mode_64bit(), EXC_UD);
         if ( !(_regs._eflags & EFLG_OF) )
             break;
         src.val = EXC_OF;
@@ -3648,7 +3661,6 @@ x86_emulate(
     case 0xd5: /* aad */ {
         unsigned int base = (uint8_t)src.val;
 
-        generate_exception_if(mode_64bit(), EXC_UD);
         if ( b & 0x01 )
         {
             uint16_t ax = _regs.ax;
@@ -3670,7 +3682,6 @@ x86_emulate(
     }
 
     case 0xd6: /* salc */
-        generate_exception_if(mode_64bit(), EXC_UD);
         _regs.al = (_regs._eflags & EFLG_CF) ? 0xff : 0x00;
         break;
 
-- 
2.1.4


_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
https://lists.xen.org/xen-devel

 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.