lkml.org 
[lkml]   [2009]   [Aug]   [19]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH 29/47] KVM: x86 emulator: Add sysenter emulation
    Date
    From: Andre Przywara <andre.przywara@amd.com>

    Handle #UD intercept of the sysenter instruction in 32bit compat mode on
    an AMD host.
    Setup the segment descriptors for CS and SS and the EIP/ESP registers
    according to the manual.

    Signed-off-by: Christoph Egger <christoph.egger@amd.com>
    Signed-off-by: Amit Shah <amit.shah@redhat.com>
    Signed-off-by: Andre Przywara <andre.przywara@amd.com>
    Signed-off-by: Avi Kivity <avi@redhat.com>
    ---
    arch/x86/kvm/x86_emulate.c | 70 +++++++++++++++++++++++++++++++++++++++++++-
    1 files changed, 69 insertions(+), 1 deletions(-)

    diff --git a/arch/x86/kvm/x86_emulate.c b/arch/x86/kvm/x86_emulate.c
    index 4d7256d..7a9bddb 100644
    --- a/arch/x86/kvm/x86_emulate.c
    +++ b/arch/x86/kvm/x86_emulate.c
    @@ -1476,6 +1476,71 @@ emulate_syscall(struct x86_emulate_ctxt *ctxt)
    return 0;
    }

    +static int
    +emulate_sysenter(struct x86_emulate_ctxt *ctxt)
    +{
    + struct decode_cache *c = &ctxt->decode;
    + struct kvm_segment cs, ss;
    + u64 msr_data;
    +
    + /* inject #UD if LOCK prefix is used */
    + if (c->lock_prefix)
    + return -1;
    +
    + /* inject #GP if in real mode or paging is disabled */
    + if (ctxt->mode == X86EMUL_MODE_REAL ||
    + !(ctxt->vcpu->arch.cr0 & X86_CR0_PE)) {
    + kvm_inject_gp(ctxt->vcpu, 0);
    + return -1;
    + }
    +
    + /* XXX sysenter/sysexit have not been tested in 64bit mode.
    + * Therefore, we inject an #UD.
    + */
    + if (ctxt->mode == X86EMUL_MODE_PROT64)
    + return -1;
    +
    + setup_syscalls_segments(ctxt, &cs, &ss);
    +
    + kvm_x86_ops->get_msr(ctxt->vcpu, MSR_IA32_SYSENTER_CS, &msr_data);
    + switch (ctxt->mode) {
    + case X86EMUL_MODE_PROT32:
    + if ((msr_data & 0xfffc) == 0x0) {
    + kvm_inject_gp(ctxt->vcpu, 0);
    + return -1;
    + }
    + break;
    + case X86EMUL_MODE_PROT64:
    + if (msr_data == 0x0) {
    + kvm_inject_gp(ctxt->vcpu, 0);
    + return -1;
    + }
    + break;
    + }
    +
    + ctxt->eflags &= ~(EFLG_VM | EFLG_IF | EFLG_RF);
    + cs.selector = (u16)msr_data;
    + cs.selector &= ~SELECTOR_RPL_MASK;
    + ss.selector = cs.selector + 8;
    + ss.selector &= ~SELECTOR_RPL_MASK;
    + if (ctxt->mode == X86EMUL_MODE_PROT64
    + || is_long_mode(ctxt->vcpu)) {
    + cs.db = 0;
    + cs.l = 1;
    + }
    +
    + kvm_x86_ops->set_segment(ctxt->vcpu, &cs, VCPU_SREG_CS);
    + kvm_x86_ops->set_segment(ctxt->vcpu, &ss, VCPU_SREG_SS);
    +
    + kvm_x86_ops->get_msr(ctxt->vcpu, MSR_IA32_SYSENTER_EIP, &msr_data);
    + c->eip = msr_data;
    +
    + kvm_x86_ops->get_msr(ctxt->vcpu, MSR_IA32_SYSENTER_ESP, &msr_data);
    + c->regs[VCPU_REGS_RSP] = msr_data;
    +
    + return 0;
    +}
    +
    int
    x86_emulate_insn(struct x86_emulate_ctxt *ctxt, struct x86_emulate_ops *ops)
    {
    @@ -2144,7 +2209,10 @@ twobyte_insn:
    c->dst.type = OP_NONE;
    break;
    case 0x34: /* sysenter */
    - goto cannot_emulate;
    + if (emulate_sysenter(ctxt) == -1)
    + goto cannot_emulate;
    + else
    + goto writeback;
    break;
    case 0x35: /* sysexit */
    goto cannot_emulate;
    --
    1.6.3.3


    \
     
     \ /
      Last update: 2009-08-19 15:09    [W:0.026 / U:53.632 seconds]
    ©2003-2017 Jasper Spaans. hosted at Digital OceanAdvertise on this site