aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/emulate.c
diff options
context:
space:
mode:
authorAvi Kivity <avi@redhat.com>2011-09-13 03:45:49 -0400
committerAvi Kivity <avi@redhat.com>2011-09-25 12:52:56 -0400
commitc191a7a0f4d3b17cc6cee1d3f721dfe23fc7d6c6 (patch)
tree7d71811d87b84250b3f205a12ab68fd59f00b803 /arch/x86/kvm/emulate.c
parent41ddf9784cb91c9e4d3a218eef3551bebe9c7362 (diff)
KVM: x86 emulator: streamline decode of segment registers
The opcodes push %seg pop %seg l%seg, %mem, %reg (e.g. lds/les/lss/lfs/lgs) all have an segment register encoded in the instruction. To allow reuse, decode the segment number into src2 during the decode stage instead of the execution stage. Signed-off-by: Avi Kivity <avi@redhat.com> Signed-off-by: Marcelo Tosatti <mtosatti@redhat.com>
Diffstat (limited to 'arch/x86/kvm/emulate.c')
-rw-r--r--arch/x86/kvm/emulate.c99
1 files changed, 57 insertions, 42 deletions
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index 1c95935fe1b7..ab48611b79cf 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -51,6 +51,12 @@
51#define OpImmFAddr 17ull /* Immediate far address */ 51#define OpImmFAddr 17ull /* Immediate far address */
52#define OpMemFAddr 18ull /* Far address in memory */ 52#define OpMemFAddr 18ull /* Far address in memory */
53#define OpImmU16 19ull /* Immediate operand, 16 bits, zero extended */ 53#define OpImmU16 19ull /* Immediate operand, 16 bits, zero extended */
54#define OpES 20ull /* ES */
55#define OpCS 21ull /* CS */
56#define OpSS 22ull /* SS */
57#define OpDS 23ull /* DS */
58#define OpFS 24ull /* FS */
59#define OpGS 25ull /* GS */
54 60
55#define OpBits 5 /* Width of operand field */ 61#define OpBits 5 /* Width of operand field */
56#define OpMask ((1ull << OpBits) - 1) 62#define OpMask ((1ull << OpBits) - 1)
@@ -126,6 +132,12 @@
126#define Src2ImmByte (OpImmByte << Src2Shift) 132#define Src2ImmByte (OpImmByte << Src2Shift)
127#define Src2One (OpOne << Src2Shift) 133#define Src2One (OpOne << Src2Shift)
128#define Src2Imm (OpImm << Src2Shift) 134#define Src2Imm (OpImm << Src2Shift)
135#define Src2ES (OpES << Src2Shift)
136#define Src2CS (OpCS << Src2Shift)
137#define Src2SS (OpSS << Src2Shift)
138#define Src2DS (OpDS << Src2Shift)
139#define Src2FS (OpFS << Src2Shift)
140#define Src2GS (OpGS << Src2Shift)
129#define Src2Mask (OpMask << Src2Shift) 141#define Src2Mask (OpMask << Src2Shift)
130 142
131#define X2(x...) x, x 143#define X2(x...) x, x
@@ -3101,16 +3113,19 @@ static struct gprefix pfx_0f_6f_0f_7f = {
3101static struct opcode opcode_table[256] = { 3113static struct opcode opcode_table[256] = {
3102 /* 0x00 - 0x07 */ 3114 /* 0x00 - 0x07 */
3103 I6ALU(Lock, em_add), 3115 I6ALU(Lock, em_add),
3104 D(ImplicitOps | Stack | No64), D(ImplicitOps | Stack | No64), 3116 D(ImplicitOps | Stack | No64 | Src2ES),
3117 D(ImplicitOps | Stack | No64 | Src2ES),
3105 /* 0x08 - 0x0F */ 3118 /* 0x08 - 0x0F */
3106 I6ALU(Lock, em_or), 3119 I6ALU(Lock, em_or),
3107 D(ImplicitOps | Stack | No64), N, 3120 D(ImplicitOps | Stack | No64 | Src2CS), N,
3108 /* 0x10 - 0x17 */ 3121 /* 0x10 - 0x17 */
3109 I6ALU(Lock, em_adc), 3122 I6ALU(Lock, em_adc),
3110 D(ImplicitOps | Stack | No64), D(ImplicitOps | Stack | No64), 3123 D(ImplicitOps | Stack | No64 | Src2SS),
3124 D(ImplicitOps | Stack | No64 | Src2SS),
3111 /* 0x18 - 0x1F */ 3125 /* 0x18 - 0x1F */
3112 I6ALU(Lock, em_sbb), 3126 I6ALU(Lock, em_sbb),
3113 D(ImplicitOps | Stack | No64), D(ImplicitOps | Stack | No64), 3127 D(ImplicitOps | Stack | No64 | Src2DS),
3128 D(ImplicitOps | Stack | No64 | Src2DS),
3114 /* 0x20 - 0x27 */ 3129 /* 0x20 - 0x27 */
3115 I6ALU(Lock, em_and), N, N, 3130 I6ALU(Lock, em_and), N, N,
3116 /* 0x28 - 0x2F */ 3131 /* 0x28 - 0x2F */
@@ -3178,7 +3193,8 @@ static struct opcode opcode_table[256] = {
3178 D2bv(DstMem | SrcImmByte | ModRM), 3193 D2bv(DstMem | SrcImmByte | ModRM),
3179 I(ImplicitOps | Stack | SrcImmU16, em_ret_near_imm), 3194 I(ImplicitOps | Stack | SrcImmU16, em_ret_near_imm),
3180 I(ImplicitOps | Stack, em_ret), 3195 I(ImplicitOps | Stack, em_ret),
3181 D(DstReg | SrcMemFAddr | ModRM | No64), D(DstReg | SrcMemFAddr | ModRM | No64), 3196 D(DstReg | SrcMemFAddr | ModRM | No64 | Src2ES),
3197 D(DstReg | SrcMemFAddr | ModRM | No64 | Src2DS),
3182 G(ByteOp, group11), G(0, group11), 3198 G(ByteOp, group11), G(0, group11),
3183 /* 0xC8 - 0xCF */ 3199 /* 0xC8 - 0xCF */
3184 N, N, N, I(ImplicitOps | Stack, em_ret_far), 3200 N, N, N, I(ImplicitOps | Stack, em_ret_far),
@@ -3253,20 +3269,22 @@ static struct opcode twobyte_table[256] = {
3253 /* 0x90 - 0x9F */ 3269 /* 0x90 - 0x9F */
3254 X16(D(ByteOp | DstMem | SrcNone | ModRM| Mov)), 3270 X16(D(ByteOp | DstMem | SrcNone | ModRM| Mov)),
3255 /* 0xA0 - 0xA7 */ 3271 /* 0xA0 - 0xA7 */
3256 D(ImplicitOps | Stack), D(ImplicitOps | Stack), 3272 D(Stack | Src2FS), D(Stack | Src2FS),
3257 DI(ImplicitOps, cpuid), D(DstMem | SrcReg | ModRM | BitOp), 3273 DI(ImplicitOps, cpuid), D(DstMem | SrcReg | ModRM | BitOp),
3258 D(DstMem | SrcReg | Src2ImmByte | ModRM), 3274 D(DstMem | SrcReg | Src2ImmByte | ModRM),
3259 D(DstMem | SrcReg | Src2CL | ModRM), N, N, 3275 D(DstMem | SrcReg | Src2CL | ModRM), N, N,
3260 /* 0xA8 - 0xAF */ 3276 /* 0xA8 - 0xAF */
3261 D(ImplicitOps | Stack), D(ImplicitOps | Stack), 3277 D(Stack | Src2GS), D(Stack | Src2GS),
3262 DI(ImplicitOps, rsm), D(DstMem | SrcReg | ModRM | BitOp | Lock), 3278 DI(ImplicitOps, rsm), D(DstMem | SrcReg | ModRM | BitOp | Lock),
3263 D(DstMem | SrcReg | Src2ImmByte | ModRM), 3279 D(DstMem | SrcReg | Src2ImmByte | ModRM),
3264 D(DstMem | SrcReg | Src2CL | ModRM), 3280 D(DstMem | SrcReg | Src2CL | ModRM),
3265 D(ModRM), I(DstReg | SrcMem | ModRM, em_imul), 3281 D(ModRM), I(DstReg | SrcMem | ModRM, em_imul),
3266 /* 0xB0 - 0xB7 */ 3282 /* 0xB0 - 0xB7 */
3267 D2bv(DstMem | SrcReg | ModRM | Lock), 3283 D2bv(DstMem | SrcReg | ModRM | Lock),
3268 D(DstReg | SrcMemFAddr | ModRM), D(DstMem | SrcReg | ModRM | BitOp | Lock), 3284 D(DstReg | SrcMemFAddr | ModRM | Src2SS),
3269 D(DstReg | SrcMemFAddr | ModRM), D(DstReg | SrcMemFAddr | ModRM), 3285 D(DstMem | SrcReg | ModRM | BitOp | Lock),
3286 D(DstReg | SrcMemFAddr | ModRM | Src2FS),
3287 D(DstReg | SrcMemFAddr | ModRM | Src2GS),
3270 D(ByteOp | DstReg | SrcMem | ModRM | Mov), D(DstReg | SrcMem16 | ModRM | Mov), 3288 D(ByteOp | DstReg | SrcMem | ModRM | Mov), D(DstReg | SrcMem16 | ModRM | Mov),
3271 /* 0xB8 - 0xBF */ 3289 /* 0xB8 - 0xBF */
3272 N, N, 3290 N, N,
@@ -3436,6 +3454,24 @@ static int decode_operand(struct x86_emulate_ctxt *ctxt, struct operand *op,
3436 case OpMemFAddr: 3454 case OpMemFAddr:
3437 ctxt->memop.bytes = ctxt->op_bytes + 2; 3455 ctxt->memop.bytes = ctxt->op_bytes + 2;
3438 goto mem_common; 3456 goto mem_common;
3457 case OpES:
3458 op->val = VCPU_SREG_ES;
3459 break;
3460 case OpCS:
3461 op->val = VCPU_SREG_CS;
3462 break;
3463 case OpSS:
3464 op->val = VCPU_SREG_SS;
3465 break;
3466 case OpDS:
3467 op->val = VCPU_SREG_DS;
3468 break;
3469 case OpFS:
3470 op->val = VCPU_SREG_FS;
3471 break;
3472 case OpGS:
3473 op->val = VCPU_SREG_GS;
3474 break;
3439 case OpImplicit: 3475 case OpImplicit:
3440 /* Special instructions do their own operand decoding. */ 3476 /* Special instructions do their own operand decoding. */
3441 default: 3477 default:
@@ -3803,26 +3839,15 @@ special_insn:
3803 3839
3804 switch (ctxt->b) { 3840 switch (ctxt->b) {
3805 case 0x06: /* push es */ 3841 case 0x06: /* push es */
3806 rc = emulate_push_sreg(ctxt, VCPU_SREG_ES);
3807 break;
3808 case 0x07: /* pop es */
3809 rc = emulate_pop_sreg(ctxt, VCPU_SREG_ES);
3810 break;
3811 case 0x0e: /* push cs */ 3842 case 0x0e: /* push cs */
3812 rc = emulate_push_sreg(ctxt, VCPU_SREG_CS);
3813 break;
3814 case 0x16: /* push ss */ 3843 case 0x16: /* push ss */
3815 rc = emulate_push_sreg(ctxt, VCPU_SREG_SS);
3816 break;
3817 case 0x17: /* pop ss */
3818 rc = emulate_pop_sreg(ctxt, VCPU_SREG_SS);
3819 break;
3820 case 0x1e: /* push ds */ 3844 case 0x1e: /* push ds */
3821 rc = emulate_push_sreg(ctxt, VCPU_SREG_DS); 3845 rc = emulate_push_sreg(ctxt, ctxt->src2.val);
3822 break; 3846 break;
3847 case 0x07: /* pop es */
3848 case 0x17: /* pop ss */
3823 case 0x1f: /* pop ds */ 3849 case 0x1f: /* pop ds */
3824 rc = emulate_pop_sreg(ctxt, VCPU_SREG_DS); 3850 rc = emulate_pop_sreg(ctxt, ctxt->src2.val);
3825 break;
3826 case 0x40 ... 0x47: /* inc r16/r32 */ 3851 case 0x40 ... 0x47: /* inc r16/r32 */
3827 emulate_1op(ctxt, "inc"); 3852 emulate_1op(ctxt, "inc");
3828 break; 3853 break;
@@ -3869,10 +3894,8 @@ special_insn:
3869 rc = em_grp2(ctxt); 3894 rc = em_grp2(ctxt);
3870 break; 3895 break;
3871 case 0xc4: /* les */ 3896 case 0xc4: /* les */
3872 rc = emulate_load_segment(ctxt, VCPU_SREG_ES);
3873 break;
3874 case 0xc5: /* lds */ 3897 case 0xc5: /* lds */
3875 rc = emulate_load_segment(ctxt, VCPU_SREG_DS); 3898 rc = emulate_load_segment(ctxt, ctxt->src2.val);
3876 break; 3899 break;
3877 case 0xcc: /* int3 */ 3900 case 0xcc: /* int3 */
3878 rc = emulate_int(ctxt, 3); 3901 rc = emulate_int(ctxt, 3);
@@ -4078,10 +4101,12 @@ twobyte_insn:
4078 ctxt->dst.val = test_cc(ctxt->b, ctxt->eflags); 4101 ctxt->dst.val = test_cc(ctxt->b, ctxt->eflags);
4079 break; 4102 break;
4080 case 0xa0: /* push fs */ 4103 case 0xa0: /* push fs */
4081 rc = emulate_push_sreg(ctxt, VCPU_SREG_FS); 4104 case 0xa8: /* push gs */
4105 rc = emulate_push_sreg(ctxt, ctxt->src2.val);
4082 break; 4106 break;
4083 case 0xa1: /* pop fs */ 4107 case 0xa1: /* pop fs */
4084 rc = emulate_pop_sreg(ctxt, VCPU_SREG_FS); 4108 case 0xa9: /* pop gs */
4109 rc = emulate_pop_sreg(ctxt, ctxt->src2.val);
4085 break; 4110 break;
4086 case 0xa3: 4111 case 0xa3:
4087 bt: /* bt */ 4112 bt: /* bt */
@@ -4094,12 +4119,6 @@ twobyte_insn:
4094 case 0xa5: /* shld cl, r, r/m */ 4119 case 0xa5: /* shld cl, r, r/m */
4095 emulate_2op_cl(ctxt, "shld"); 4120 emulate_2op_cl(ctxt, "shld");
4096 break; 4121 break;
4097 case 0xa8: /* push gs */
4098 rc = emulate_push_sreg(ctxt, VCPU_SREG_GS);
4099 break;
4100 case 0xa9: /* pop gs */
4101 rc = emulate_pop_sreg(ctxt, VCPU_SREG_GS);
4102 break;
4103 case 0xab: 4122 case 0xab:
4104 bts: /* bts */ 4123 bts: /* bts */
4105 emulate_2op_SrcV_nobyte(ctxt, "bts"); 4124 emulate_2op_SrcV_nobyte(ctxt, "bts");
@@ -4128,18 +4147,14 @@ twobyte_insn:
4128 } 4147 }
4129 break; 4148 break;
4130 case 0xb2: /* lss */ 4149 case 0xb2: /* lss */
4131 rc = emulate_load_segment(ctxt, VCPU_SREG_SS); 4150 case 0xb4: /* lfs */
4151 case 0xb5: /* lgs */
4152 rc = emulate_load_segment(ctxt, ctxt->src2.val);
4132 break; 4153 break;
4133 case 0xb3: 4154 case 0xb3:
4134 btr: /* btr */ 4155 btr: /* btr */
4135 emulate_2op_SrcV_nobyte(ctxt, "btr"); 4156 emulate_2op_SrcV_nobyte(ctxt, "btr");
4136 break; 4157 break;
4137 case 0xb4: /* lfs */
4138 rc = emulate_load_segment(ctxt, VCPU_SREG_FS);
4139 break;
4140 case 0xb5: /* lgs */
4141 rc = emulate_load_segment(ctxt, VCPU_SREG_GS);
4142 break;
4143 case 0xb6 ... 0xb7: /* movzx */ 4158 case 0xb6 ... 0xb7: /* movzx */
4144 ctxt->dst.bytes = ctxt->op_bytes; 4159 ctxt->dst.bytes = ctxt->op_bytes;
4145 ctxt->dst.val = (ctxt->d & ByteOp) ? (u8) ctxt->src.val 4160 ctxt->dst.val = (ctxt->d & ByteOp) ? (u8) ctxt->src.val