diff options
author | Avi Kivity <avi@redhat.com> | 2011-09-13 03:45:49 -0400 |
---|---|---|
committer | Avi Kivity <avi@redhat.com> | 2011-09-25 12:52:56 -0400 |
commit | c191a7a0f4d3b17cc6cee1d3f721dfe23fc7d6c6 (patch) | |
tree | 7d71811d87b84250b3f205a12ab68fd59f00b803 /arch/x86/kvm/emulate.c | |
parent | 41ddf9784cb91c9e4d3a218eef3551bebe9c7362 (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.c | 99 |
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 = { | |||
3101 | static struct opcode opcode_table[256] = { | 3113 | static 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 |