Commit 58b7075d authored by Nadav Amit's avatar Nadav Amit Committed by Paolo Bonzini

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: default avatarNadav Amit <namit@cs.technion.ac.il>
Signed-off-by: default avatarPaolo Bonzini <pbonzini@redhat.com>
parent f7784046
...@@ -166,6 +166,7 @@ ...@@ -166,6 +166,7 @@
#define CheckPerm ((u64)1 << 49) /* Has valid check_perm field */ #define CheckPerm ((u64)1 << 49) /* Has valid check_perm field */
#define NoBigReal ((u64)1 << 50) /* No big real mode */ #define NoBigReal ((u64)1 << 50) /* No big real mode */
#define PrivUD ((u64)1 << 51) /* #UD instead of #GP on CPL > 0 */ #define PrivUD ((u64)1 << 51) /* #UD instead of #GP on CPL > 0 */
#define NearBranch ((u64)1 << 52) /* Near branches */
#define DstXacc (DstAccLo | SrcAccHi | SrcWrite) #define DstXacc (DstAccLo | SrcAccHi | SrcWrite)
...@@ -3771,9 +3772,9 @@ static const struct opcode group4[] = { ...@@ -3771,9 +3772,9 @@ static const struct opcode group4[] = {
static const struct opcode group5[] = { static const struct opcode group5[] = {
F(DstMem | SrcNone | Lock, em_inc), F(DstMem | SrcNone | Lock, em_inc),
F(DstMem | SrcNone | Lock, em_dec), F(DstMem | SrcNone | Lock, em_dec),
I(SrcMem | Stack, em_call_near_abs), I(SrcMem | NearBranch, em_call_near_abs),
I(SrcMemFAddr | ImplicitOps | Stack, em_call_far), I(SrcMemFAddr | ImplicitOps | Stack, em_call_far),
I(SrcMem | Stack, em_jmp_abs), I(SrcMem | NearBranch, em_jmp_abs),
I(SrcMemFAddr | ImplicitOps, em_jmp_far), I(SrcMemFAddr | ImplicitOps, em_jmp_far),
I(SrcMem | Stack, em_push), D(Undefined), I(SrcMem | Stack, em_push), D(Undefined),
}; };
...@@ -3955,7 +3956,7 @@ static const struct opcode opcode_table[256] = { ...@@ -3955,7 +3956,7 @@ static const struct opcode opcode_table[256] = {
I2bvIP(DstDI | SrcDX | Mov | String | Unaligned, em_in, ins, check_perm_in), /* insb, insw/insd */ I2bvIP(DstDI | SrcDX | Mov | String | Unaligned, em_in, ins, check_perm_in), /* insb, insw/insd */
I2bvIP(SrcSI | DstDX | String, em_out, outs, check_perm_out), /* outsb, outsw/outsd */ I2bvIP(SrcSI | DstDX | String, em_out, outs, check_perm_out), /* outsb, outsw/outsd */
/* 0x70 - 0x7F */ /* 0x70 - 0x7F */
X16(D(SrcImmByte)), X16(D(SrcImmByte | NearBranch)),
/* 0x80 - 0x87 */ /* 0x80 - 0x87 */
G(ByteOp | DstMem | SrcImm, group1), G(ByteOp | DstMem | SrcImm, group1),
G(DstMem | SrcImm, group1), G(DstMem | SrcImm, group1),
...@@ -3994,8 +3995,8 @@ static const struct opcode opcode_table[256] = { ...@@ -3994,8 +3995,8 @@ static const struct opcode opcode_table[256] = {
X8(I(DstReg | SrcImm64 | Mov, em_mov)), X8(I(DstReg | SrcImm64 | Mov, em_mov)),
/* 0xC0 - 0xC7 */ /* 0xC0 - 0xC7 */
G(ByteOp | Src2ImmByte, group2), G(Src2ImmByte, group2), G(ByteOp | Src2ImmByte, group2), G(Src2ImmByte, group2),
I(ImplicitOps | Stack | SrcImmU16, em_ret_near_imm), I(ImplicitOps | NearBranch | SrcImmU16, em_ret_near_imm),
I(ImplicitOps | Stack, em_ret), I(ImplicitOps | NearBranch, em_ret),
I(DstReg | SrcMemFAddr | ModRM | No64 | Src2ES, em_lseg), I(DstReg | SrcMemFAddr | ModRM | No64 | Src2ES, em_lseg),
I(DstReg | SrcMemFAddr | ModRM | No64 | Src2DS, em_lseg), I(DstReg | SrcMemFAddr | ModRM | No64 | Src2DS, em_lseg),
G(ByteOp, group11), G(0, group11), G(ByteOp, group11), G(0, group11),
...@@ -4015,13 +4016,14 @@ static const struct opcode opcode_table[256] = { ...@@ -4015,13 +4016,14 @@ static const struct opcode opcode_table[256] = {
/* 0xD8 - 0xDF */ /* 0xD8 - 0xDF */
N, E(0, &escape_d9), N, E(0, &escape_db), N, E(0, &escape_dd), N, N, N, E(0, &escape_d9), N, E(0, &escape_db), N, E(0, &escape_dd), N, N,
/* 0xE0 - 0xE7 */ /* 0xE0 - 0xE7 */
X3(I(SrcImmByte, em_loop)), X3(I(SrcImmByte | NearBranch, em_loop)),
I(SrcImmByte, em_jcxz), I(SrcImmByte | NearBranch, em_jcxz),
I2bvIP(SrcImmUByte | DstAcc, em_in, in, check_perm_in), I2bvIP(SrcImmUByte | DstAcc, em_in, in, check_perm_in),
I2bvIP(SrcAcc | DstImmUByte, em_out, out, check_perm_out), I2bvIP(SrcAcc | DstImmUByte, em_out, out, check_perm_out),
/* 0xE8 - 0xEF */ /* 0xE8 - 0xEF */
I(SrcImm | Stack, em_call), D(SrcImm | ImplicitOps), I(SrcImm | NearBranch, em_call), D(SrcImm | ImplicitOps | NearBranch),
I(SrcImmFAddr | No64, em_jmp_far), D(SrcImmByte | ImplicitOps), I(SrcImmFAddr | No64, em_jmp_far),
D(SrcImmByte | ImplicitOps | NearBranch),
I2bvIP(SrcDX | DstAcc, em_in, in, check_perm_in), I2bvIP(SrcDX | DstAcc, em_in, in, check_perm_in),
I2bvIP(SrcAcc | DstDX, em_out, out, check_perm_out), I2bvIP(SrcAcc | DstDX, em_out, out, check_perm_out),
/* 0xF0 - 0xF7 */ /* 0xF0 - 0xF7 */
...@@ -4081,7 +4083,7 @@ static const struct opcode twobyte_table[256] = { ...@@ -4081,7 +4083,7 @@ static const struct opcode twobyte_table[256] = {
N, N, N, N, N, N, N, N,
N, N, N, GP(SrcReg | DstMem | ModRM | Mov, &pfx_0f_6f_0f_7f), N, N, N, GP(SrcReg | DstMem | ModRM | Mov, &pfx_0f_6f_0f_7f),
/* 0x80 - 0x8F */ /* 0x80 - 0x8F */
X16(D(SrcImm)), X16(D(SrcImm | NearBranch)),
/* 0x90 - 0x9F */ /* 0x90 - 0x9F */
X16(D(ByteOp | DstMem | SrcNone | ModRM| Mov)), X16(D(ByteOp | DstMem | SrcNone | ModRM| Mov)),
/* 0xA0 - 0xA7 */ /* 0xA0 - 0xA7 */
...@@ -4550,7 +4552,7 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len) ...@@ -4550,7 +4552,7 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len)
return EMULATION_FAILED; return EMULATION_FAILED;
if (unlikely(ctxt->d & if (unlikely(ctxt->d &
(NotImpl|Stack|Op3264|Sse|Mmx|Intercept|CheckPerm))) { (NotImpl|Stack|Op3264|Sse|Mmx|Intercept|CheckPerm|NearBranch))) {
/* /*
* These are copied unconditionally here, and checked unconditionally * These are copied unconditionally here, and checked unconditionally
* in x86_emulate_insn. * in x86_emulate_insn.
...@@ -4561,8 +4563,12 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len) ...@@ -4561,8 +4563,12 @@ int x86_decode_insn(struct x86_emulate_ctxt *ctxt, void *insn, int insn_len)
if (ctxt->d & NotImpl) if (ctxt->d & NotImpl)
return EMULATION_FAILED; return EMULATION_FAILED;
if (mode == X86EMUL_MODE_PROT64 && (ctxt->d & Stack)) if (mode == X86EMUL_MODE_PROT64) {
ctxt->op_bytes = 8; if (ctxt->op_bytes == 4 && (ctxt->d & Stack))
ctxt->op_bytes = 8;
else if (ctxt->d & NearBranch)
ctxt->op_bytes = 8;
}
if (ctxt->d & Op3264) { if (ctxt->d & Op3264) {
if (mode == X86EMUL_MODE_PROT64) if (mode == X86EMUL_MODE_PROT64)
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment