aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAvi Kivity <avi@redhat.com>2012-06-12 13:03:23 -0400
committerAvi Kivity <avi@redhat.com>2012-07-09 07:19:03 -0400
commit612e89f01569f562dfa76cd5b76310a42b34a214 (patch)
tree44dffc8c7aaa386a3e2e147499cad2b1adf3d386
parent51ddff50cbd77568fe40e17a966b3a2ef1231b36 (diff)
KVM: x86 emulator: implement ENTER
Opcode C8. Only ENTER with lexical nesting depth 0 is implemented, since others are very rare. We'll fail emulation if nonzero lexical depth is used so data is not corrupted. Signed-off-by: Avi Kivity <avi@redhat.com>
-rw-r--r--arch/x86/kvm/emulate.c28
1 files changed, 27 insertions, 1 deletions
diff --git a/arch/x86/kvm/emulate.c b/arch/x86/kvm/emulate.c
index acc647d63701..b4b326ebc835 100644
--- a/arch/x86/kvm/emulate.c
+++ b/arch/x86/kvm/emulate.c
@@ -454,6 +454,11 @@ static ulong stack_mask(struct x86_emulate_ctxt *ctxt)
454 return ~0U >> ((ss.d ^ 1) * 16); /* d=0: 0xffff; d=1: 0xffffffff */ 454 return ~0U >> ((ss.d ^ 1) * 16); /* d=0: 0xffff; d=1: 0xffffffff */
455} 455}
456 456
457static int stack_size(struct x86_emulate_ctxt *ctxt)
458{
459 return (__fls(stack_mask(ctxt)) + 1) >> 3;
460}
461
457/* Access/update address held in a register, based on addressing mode. */ 462/* Access/update address held in a register, based on addressing mode. */
458static inline unsigned long 463static inline unsigned long
459address_mask(struct x86_emulate_ctxt *ctxt, unsigned long reg) 464address_mask(struct x86_emulate_ctxt *ctxt, unsigned long reg)
@@ -1592,6 +1597,26 @@ static int em_popf(struct x86_emulate_ctxt *ctxt)
1592 return emulate_popf(ctxt, &ctxt->dst.val, ctxt->op_bytes); 1597 return emulate_popf(ctxt, &ctxt->dst.val, ctxt->op_bytes);
1593} 1598}
1594 1599
1600static int em_enter(struct x86_emulate_ctxt *ctxt)
1601{
1602 int rc;
1603 unsigned frame_size = ctxt->src.val;
1604 unsigned nesting_level = ctxt->src2.val & 31;
1605
1606 if (nesting_level)
1607 return X86EMUL_UNHANDLEABLE;
1608
1609 rc = push(ctxt, &ctxt->regs[VCPU_REGS_RBP], stack_size(ctxt));
1610 if (rc != X86EMUL_CONTINUE)
1611 return rc;
1612 assign_masked(&ctxt->regs[VCPU_REGS_RBP], ctxt->regs[VCPU_REGS_RSP],
1613 stack_mask(ctxt));
1614 assign_masked(&ctxt->regs[VCPU_REGS_RSP],
1615 ctxt->regs[VCPU_REGS_RSP] - frame_size,
1616 stack_mask(ctxt));
1617 return X86EMUL_CONTINUE;
1618}
1619
1595static int em_leave(struct x86_emulate_ctxt *ctxt) 1620static int em_leave(struct x86_emulate_ctxt *ctxt)
1596{ 1621{
1597 assign_masked(&ctxt->regs[VCPU_REGS_RSP], ctxt->regs[VCPU_REGS_RBP], 1622 assign_masked(&ctxt->regs[VCPU_REGS_RSP], ctxt->regs[VCPU_REGS_RBP],
@@ -3657,7 +3682,8 @@ static struct opcode opcode_table[256] = {
3657 I(DstReg | SrcMemFAddr | ModRM | No64 | Src2DS, em_lseg), 3682 I(DstReg | SrcMemFAddr | ModRM | No64 | Src2DS, em_lseg),
3658 G(ByteOp, group11), G(0, group11), 3683 G(ByteOp, group11), G(0, group11),
3659 /* 0xC8 - 0xCF */ 3684 /* 0xC8 - 0xCF */
3660 N, I(Stack, em_leave), N, I(ImplicitOps | Stack, em_ret_far), 3685 I(Stack | SrcImmU16 | Src2ImmByte, em_enter), I(Stack, em_leave),
3686 N, I(ImplicitOps | Stack, em_ret_far),
3661 D(ImplicitOps), DI(SrcImmByte, intn), 3687 D(ImplicitOps), DI(SrcImmByte, intn),
3662 D(ImplicitOps | No64), II(ImplicitOps, em_iret, iret), 3688 D(ImplicitOps | No64), II(ImplicitOps, em_iret, iret),
3663 /* 0xD0 - 0xD7 */ 3689 /* 0xD0 - 0xD7 */