diff options
author | Nadav Amit <namit@cs.technion.ac.il> | 2014-10-24 04:35:09 -0400 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2014-11-03 06:07:20 -0500 |
commit | 58b7075d059f7d37ca86c76fb1446fa3447b9f4f (patch) | |
tree | 57b978e405103e5bfd274655aaf569b782b6156a | |
parent | f7784046ab7cfc1645f4110b6ed14fbdffc2abee (diff) |
KVM: x86: Distinguish between stack operation and near branches
In 64-bit, stack operations default to 64-bits, but can be overriden (to
16-bit) using opsize override prefix. In contrast, near-branches are always
64-bit. This patch distinguish between the different behaviors.
Signed-off-by: Nadav Amit <namit@cs.technion.ac.il>
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
-rw-r--r-- | arch/x86/kvm/emulate.c | 32 |
1 files changed, 19 insertions, 13 deletions
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index 147f3fdfb5ce..a90fa188aeea 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c | |||
@@ -166,6 +166,7 @@ | |||
166 | #define CheckPerm ((u64)1 << 49) /* Has valid check_perm field */ | 166 | #define CheckPerm ((u64)1 << 49) /* Has valid check_perm field */ |
167 | #define NoBigReal ((u64)1 << 50) /* No big real mode */ | 167 | #define NoBigReal ((u64)1 << 50) /* No big real mode */ |
168 | #define PrivUD ((u64)1 << 51) /* #UD instead of #GP on CPL > 0 */ | 168 | #define PrivUD ((u64)1 << 51) /* #UD instead of #GP on CPL > 0 */ |
169 | #define NearBranch ((u64)1 << 52) /* Near branches */ | ||
169 | 170 | ||
170 | #define DstXacc (DstAccLo | SrcAccHi | SrcWrite) | 171 | #define DstXacc (DstAccLo | SrcAccHi | SrcWrite) |
171 | 172 | ||
@@ -3771,9 +3772,9 @@ static const struct opcode group4[] = { | |||
3771 | static const struct opcode group5[] = { | 3772 | static const struct opcode group5[] = { |
3772 | F(DstMem | SrcNone | Lock, em_inc), | 3773 | F(DstMem | SrcNone | Lock, em_inc), |
3773 | F(DstMem | SrcNone | Lock, em_dec), | 3774 | F(DstMem | SrcNone | Lock, em_dec), |
3774 | I(SrcMem | Stack, em_call_near_abs), | 3775 | I(SrcMem | NearBranch, em_call_near_abs), |
3775 | I(SrcMemFAddr | ImplicitOps | Stack, em_call_far), | 3776 | I(SrcMemFAddr | ImplicitOps | Stack, em_call_far), |
3776 | I(SrcMem | Stack, em_jmp_abs), | 3777 | I(SrcMem | NearBranch, em_jmp_abs), |
3777 | I(SrcMemFAddr | ImplicitOps, em_jmp_far), | 3778 | I(SrcMemFAddr | ImplicitOps, em_jmp_far), |
3778 | I(SrcMem | Stack, em_push), D(Undefined), | 3779 | I(SrcMem | Stack, em_push), D(Undefined), |
3779 | }; | 3780 | }; |
@@ -3955,7 +3956,7 @@ static const struct opcode opcode_table[256] = { | |||
3955 | I2bvIP(DstDI | SrcDX | Mov | String | Unaligned, em_in, ins, check_perm_in), /* insb, insw/insd */ | 3956 | I2bvIP(DstDI | SrcDX | Mov | String | Unaligned, em_in, ins, check_perm_in), /* insb, insw/insd */ |
3956 | I2bvIP(SrcSI | DstDX | String, em_out, outs, check_perm_out), /* outsb, outsw/outsd */ | 3957 | I2bvIP(SrcSI | DstDX | String, em_out, outs, check_perm_out), /* outsb, outsw/outsd */ |
3957 | /* 0x70 - 0x7F */ | 3958 | /* 0x70 - 0x7F */ |
3958 | X16(D(SrcImmByte)), | 3959 | X16(D(SrcImmByte | NearBranch)), |
3959 | /* 0x80 - 0x87 */ | 3960 | /* 0x80 - 0x87 */ |
3960 | G(ByteOp | DstMem | SrcImm, group1), | 3961 | G(ByteOp | DstMem | SrcImm, group1), |
3961 | G(DstMem | SrcImm, group1), | 3962 | G(DstMem | SrcImm, group1), |
@@ -3994,8 +3995,8 @@ static const struct opcode opcode_table[256] = { | |||
3994 | X8(I(DstReg | SrcImm64 | Mov, em_mov)), | 3995 | X8(I(DstReg | SrcImm64 | Mov, em_mov)), |
3995 | /* 0xC0 - 0xC7 */ | 3996 | /* 0xC0 - 0xC7 */ |
3996 | G(ByteOp | Src2ImmByte, group2), G(Src2ImmByte, group2), | 3997 | G(ByteOp | Src2ImmByte, group2), G(Src2ImmByte, group2), |
3997 | I(ImplicitOps | Stack | SrcImmU16, em_ret_near_imm), | 3998 | I(ImplicitOps | NearBranch | SrcImmU16, em_ret_near_imm), |
3998 | I(ImplicitOps | Stack, em_ret), | 3999 | I(ImplicitOps | NearBranch, em_ret), |
3999 | I(DstReg | SrcMemFAddr | ModRM | No64 | Src2ES, em_lseg), | 4000 | I(DstReg | SrcMemFAddr | ModRM | No64 | Src2ES, em_lseg), |
4000 | I(DstReg | SrcMemFAddr | ModRM | No64 | Src2DS, em_lseg), | 4001 | I(DstReg | SrcMemFAddr | ModRM | No64 | Src2DS, em_lseg), |
4001 | G(ByteOp, group11), G(0, group11), | 4002 | G(ByteOp, group11), G(0, group11), |
@@ -4015,13 +4016,14 @@ static const struct opcode opcode_table[256] = { | |||
4015 | /* 0xD8 - 0xDF */ | 4016 | /* 0xD8 - 0xDF */ |
4016 | N, E(0, &escape_d9), N, E(0, &escape_db), N, E(0, &escape_dd), N, N, | 4017 | N, E(0, &escape_d9), N, E(0, &escape_db), N, E(0, &escape_dd), N, N, |
4017 | /* 0xE0 - 0xE7 */ | 4018 | /* 0xE0 - 0xE7 */ |
4018 | X3(I(SrcImmByte, em_loop)), | 4019 | X3(I(SrcImmByte | NearBranch, em_loop)), |
4019 | I(SrcImmByte, em_jcxz), | 4020 | I(SrcImmByte | NearBranch, em_jcxz), |
4020 | I2bvIP(SrcImmUByte | DstAcc, em_in, in, check_perm_in), | 4021 | I2bvIP(SrcImmUByte | DstAcc, em_in, in, check_perm_in), |
4021 | I2bvIP(SrcAcc | DstImmUByte, em_out, out, check_perm_out), | 4022 | I2bvIP(SrcAcc | DstImmUByte, em_out, out, check_perm_out), |
4022 | /* 0xE8 - 0xEF */ | 4023 | /* 0xE8 - 0xEF */ |
4023 | I(SrcImm | Stack, em_call), D(SrcImm | ImplicitOps), | 4024 | I(SrcImm | NearBranch, em_call), D(SrcImm | ImplicitOps | NearBranch), |
4024 | I(SrcImmFAddr | No64, em_jmp_far), D(SrcImmByte | ImplicitOps), | 4025 | I(SrcImmFAddr | No64, em_jmp_far), |
4026 | D(SrcImmByte | ImplicitOps | NearBranch), | ||
4025 | I2bvIP(SrcDX | DstAcc, em_in, in, check_perm_in), | 4027 | I2bvIP(SrcDX | DstAcc, em_in, in, check_perm_in), |
4026 | I2bvIP(SrcAcc | DstDX, em_out, out, check_perm_out), | 4028 | I2bvIP(SrcAcc | DstDX, em_out, out, check_perm_out), |
4027 | /* 0xF0 - 0xF7 */ | 4029 | /* 0xF0 - 0xF7 */ |
@@ -4081,7 +4083,7 @@ static const struct opcode twobyte_table[256] = { | |||
4081 | N, N, N, N, | 4083 | N, N, N, N, |
4082 | N, N, N, GP(SrcReg | DstMem | ModRM | Mov, &pfx_0f_6f_0f_7f), | 4084 | N, N, N, GP(SrcReg | DstMem | ModRM | Mov, &pfx_0f_6f_0f_7f), |
4083 | /* 0x80 - 0x8F */ | 4085 | /* 0x80 - 0x8F */ |
4084 | X16(D(SrcImm)), | 4086 | X16(D(SrcImm | NearBranch)), |
4085 | /* 0x90 - 0x9F */ | 4087 | /* 0x90 - 0x9F */ |
4086 | X16(D(ByteOp | DstMem | SrcNone | ModRM| Mov)), | 4088 | X16(D(ByteOp | DstMem | SrcNone | ModRM| Mov)), |
4087 | /* 0xA0 - 0xA7 */ | 4089 | /* 0xA0 - 0xA7 */ |
@@ -4550,7 +4552,7 @@ done_prefixes: | |||
4550 | return EMULATION_FAILED; | 4552 | return EMULATION_FAILED; |
4551 | 4553 | ||
4552 | if (unlikely(ctxt->d & | 4554 | if (unlikely(ctxt->d & |
4553 | (NotImpl|Stack|Op3264|Sse|Mmx|Intercept|CheckPerm))) { | 4555 | (NotImpl|Stack|Op3264|Sse|Mmx|Intercept|CheckPerm|NearBranch))) { |
4554 | /* | 4556 | /* |
4555 | * These are copied unconditionally here, and checked unconditionally | 4557 | * These are copied unconditionally here, and checked unconditionally |
4556 | * in x86_emulate_insn. | 4558 | * in x86_emulate_insn. |
@@ -4561,8 +4563,12 @@ done_prefixes: | |||
4561 | if (ctxt->d & NotImpl) | 4563 | if (ctxt->d & NotImpl) |
4562 | return EMULATION_FAILED; | 4564 | return EMULATION_FAILED; |
4563 | 4565 | ||
4564 | if (mode == X86EMUL_MODE_PROT64 && (ctxt->d & Stack)) | 4566 | if (mode == X86EMUL_MODE_PROT64) { |
4565 | ctxt->op_bytes = 8; | 4567 | if (ctxt->op_bytes == 4 && (ctxt->d & Stack)) |
4568 | ctxt->op_bytes = 8; | ||
4569 | else if (ctxt->d & NearBranch) | ||
4570 | ctxt->op_bytes = 8; | ||
4571 | } | ||
4566 | 4572 | ||
4567 | if (ctxt->d & Op3264) { | 4573 | if (ctxt->d & Op3264) { |
4568 | if (mode == X86EMUL_MODE_PROT64) | 4574 | if (mode == X86EMUL_MODE_PROT64) |