diff options
Diffstat (limited to 'arch/x86/kvm/emulate.c')
-rw-r--r-- | arch/x86/kvm/emulate.c | 31 |
1 files changed, 23 insertions, 8 deletions
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c index a335cc6cde72..8e517bba6a7c 100644 --- a/arch/x86/kvm/emulate.c +++ b/arch/x86/kvm/emulate.c | |||
@@ -132,8 +132,9 @@ | |||
132 | #define Priv (1<<27) /* instruction generates #GP if current CPL != 0 */ | 132 | #define Priv (1<<27) /* instruction generates #GP if current CPL != 0 */ |
133 | #define No64 (1<<28) | 133 | #define No64 (1<<28) |
134 | #define PageTable (1 << 29) /* instruction used to write page table */ | 134 | #define PageTable (1 << 29) /* instruction used to write page table */ |
135 | #define NotImpl (1 << 30) /* instruction is not implemented */ | ||
135 | /* Source 2 operand type */ | 136 | /* Source 2 operand type */ |
136 | #define Src2Shift (30) | 137 | #define Src2Shift (31) |
137 | #define Src2None (OpNone << Src2Shift) | 138 | #define Src2None (OpNone << Src2Shift) |
138 | #define Src2CL (OpCL << Src2Shift) | 139 | #define Src2CL (OpCL << Src2Shift) |
139 | #define Src2ImmByte (OpImmByte << Src2Shift) | 140 | #define Src2ImmByte (OpImmByte << Src2Shift) |
@@ -1578,12 +1579,21 @@ static int load_segment_descriptor(struct x86_emulate_ctxt *ctxt, | |||
1578 | 1579 | ||
1579 | memset(&seg_desc, 0, sizeof seg_desc); | 1580 | memset(&seg_desc, 0, sizeof seg_desc); |
1580 | 1581 | ||
1581 | if ((seg <= VCPU_SREG_GS && ctxt->mode == X86EMUL_MODE_VM86) | 1582 | if (ctxt->mode == X86EMUL_MODE_REAL) { |
1582 | || ctxt->mode == X86EMUL_MODE_REAL) { | 1583 | /* set real mode segment descriptor (keep limit etc. for |
1583 | /* set real mode segment descriptor */ | 1584 | * unreal mode) */ |
1584 | ctxt->ops->get_segment(ctxt, &dummy, &seg_desc, NULL, seg); | 1585 | ctxt->ops->get_segment(ctxt, &dummy, &seg_desc, NULL, seg); |
1585 | set_desc_base(&seg_desc, selector << 4); | 1586 | set_desc_base(&seg_desc, selector << 4); |
1586 | goto load; | 1587 | goto load; |
1588 | } else if (seg <= VCPU_SREG_GS && ctxt->mode == X86EMUL_MODE_VM86) { | ||
1589 | /* VM86 needs a clean new segment descriptor */ | ||
1590 | set_desc_base(&seg_desc, selector << 4); | ||
1591 | set_desc_limit(&seg_desc, 0xffff); | ||
1592 | seg_desc.type = 3; | ||
1593 | seg_desc.p = 1; | ||
1594 | seg_desc.s = 1; | ||
1595 | seg_desc.dpl = 3; | ||
1596 | goto load; | ||
1587 | } | 1597 | } |
1588 | 1598 | ||
1589 | rpl = selector & 3; | 1599 | rpl = selector & 3; |
@@ -3615,7 +3625,7 @@ static int check_perm_out(struct x86_emulate_ctxt *ctxt) | |||
3615 | #define DI(_y, _i) { .flags = (_y), .intercept = x86_intercept_##_i } | 3625 | #define DI(_y, _i) { .flags = (_y), .intercept = x86_intercept_##_i } |
3616 | #define DIP(_y, _i, _p) { .flags = (_y), .intercept = x86_intercept_##_i, \ | 3626 | #define DIP(_y, _i, _p) { .flags = (_y), .intercept = x86_intercept_##_i, \ |
3617 | .check_perm = (_p) } | 3627 | .check_perm = (_p) } |
3618 | #define N D(0) | 3628 | #define N D(NotImpl) |
3619 | #define EXT(_f, _e) { .flags = ((_f) | RMExt), .u.group = (_e) } | 3629 | #define EXT(_f, _e) { .flags = ((_f) | RMExt), .u.group = (_e) } |
3620 | #define G(_f, _g) { .flags = ((_f) | Group | ModRM), .u.group = (_g) } | 3630 | #define G(_f, _g) { .flags = ((_f) | Group | ModRM), .u.group = (_g) } |
3621 | #define GD(_f, _g) { .flags = ((_f) | GroupDual | ModRM), .u.gdual = (_g) } | 3631 | #define GD(_f, _g) { .flags = ((_f) | GroupDual | ModRM), .u.gdual = (_g) } |
@@ -3713,7 +3723,7 @@ static const struct opcode group5[] = { | |||
3713 | I(SrcMemFAddr | ImplicitOps | Stack, em_call_far), | 3723 | I(SrcMemFAddr | ImplicitOps | Stack, em_call_far), |
3714 | I(SrcMem | Stack, em_grp45), | 3724 | I(SrcMem | Stack, em_grp45), |
3715 | I(SrcMemFAddr | ImplicitOps, em_grp45), | 3725 | I(SrcMemFAddr | ImplicitOps, em_grp45), |
3716 | I(SrcMem | Stack, em_grp45), N, | 3726 | I(SrcMem | Stack, em_grp45), D(Undefined), |
3717 | }; | 3727 | }; |
3718 | 3728 | ||
3719 | static const struct opcode group6[] = { | 3729 | static const struct opcode group6[] = { |
@@ -4162,6 +4172,10 @@ static int decode_operand(struct x86_emulate_ctxt *ctxt, struct operand *op, | |||
4162 | break; | 4172 | break; |
4163 | case OpMem8: | 4173 | case OpMem8: |
4164 | ctxt->memop.bytes = 1; | 4174 | ctxt->memop.bytes = 1; |
4175 | if (ctxt->memop.type == OP_REG) { | ||
4176 | ctxt->memop.addr.reg = decode_register(ctxt, ctxt->modrm_rm, 1); | ||
4177 | fetch_register_operand(&ctxt->memop); | ||
4178 | } | ||
4165 | goto mem_common; | 4179 | goto mem_common; |
4166 | case OpMem16: | 4180 | case OpMem16: |
4167 | ctxt->memop.bytes = 2; | 4181 | ctxt->memop.bytes = 2; |
@@ -4373,7 +4387,7 @@ done_prefixes: | |||
4373 | ctxt->intercept = opcode.intercept; | 4387 | ctxt->intercept = opcode.intercept; |
4374 | 4388 | ||
4375 | /* Unrecognised? */ | 4389 | /* Unrecognised? */ |
4376 | if (ctxt->d == 0 || (ctxt->d & Undefined)) | 4390 | if (ctxt->d == 0 || (ctxt->d & NotImpl)) |
4377 | return EMULATION_FAILED; | 4391 | return EMULATION_FAILED; |
4378 | 4392 | ||
4379 | if (!(ctxt->d & VendorSpecific) && ctxt->only_vendor_specific_insn) | 4393 | if (!(ctxt->d & VendorSpecific) && ctxt->only_vendor_specific_insn) |
@@ -4511,7 +4525,8 @@ int x86_emulate_insn(struct x86_emulate_ctxt *ctxt) | |||
4511 | 4525 | ||
4512 | ctxt->mem_read.pos = 0; | 4526 | ctxt->mem_read.pos = 0; |
4513 | 4527 | ||
4514 | if (ctxt->mode == X86EMUL_MODE_PROT64 && (ctxt->d & No64)) { | 4528 | if ((ctxt->mode == X86EMUL_MODE_PROT64 && (ctxt->d & No64)) || |
4529 | (ctxt->d & Undefined)) { | ||
4515 | rc = emulate_ud(ctxt); | 4530 | rc = emulate_ud(ctxt); |
4516 | goto done; | 4531 | goto done; |
4517 | } | 4532 | } |