lkml.org 
[lkml]   [2015]   [Jun]   [4]   [last100]   RSS Feed
Views: [wrap][no wrap]   [headers]  [forward] 
 
Messages in this thread
    Patch in this message
    /
    From
    Subject[PATCH v2 14/13] KVM: x86: latch INITs while in system management mode
    Date
    Do not process INITs immediately while in system management mode, keep
    it instead in apic->pending_events. Tell userspace if an INIT is
    pending when they issue GET_VCPU_EVENTS, and similarly handle the
    new field in SET_VCPU_EVENTS.

    Note that the same treatment should be done while in VMX non-root mode.

    Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
    ---
    Documentation/virtual/kvm/api.txt | 2 +-
    arch/x86/include/uapi/asm/kvm.h | 2 +-
    arch/x86/kvm/lapic.c | 13 ++++++++++++-
    arch/x86/kvm/lapic.h | 5 +++++
    arch/x86/kvm/x86.c | 11 ++++++++++-
    5 files changed, 29 insertions(+), 4 deletions(-)

    diff --git a/Documentation/virtual/kvm/api.txt b/Documentation/virtual/kvm/api.txt
    index 91ab5f2354aa..461956a0ee8e 100644
    --- a/Documentation/virtual/kvm/api.txt
    +++ b/Documentation/virtual/kvm/api.txt
    @@ -829,7 +829,7 @@ struct kvm_vcpu_events {
    __u8 smm;
    __u8 pending;
    __u8 smm_inside_nmi;
    - __u8 pad;
    + __u8 latched_init;
    } smi;
    };

    diff --git a/arch/x86/include/uapi/asm/kvm.h b/arch/x86/include/uapi/asm/kvm.h
    index 30100a3c1bed..a4ae82eb82aa 100644
    --- a/arch/x86/include/uapi/asm/kvm.h
    +++ b/arch/x86/include/uapi/asm/kvm.h
    @@ -316,7 +316,7 @@ struct kvm_vcpu_events {
    __u8 smm;
    __u8 pending;
    __u8 smm_inside_nmi;
    - __u8 pad;
    + __u8 latched_init;
    } smi;
    __u32 reserved[9];
    };
    diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
    index b8e47e2b1d94..beeef05bb4d9 100644
    --- a/arch/x86/kvm/lapic.c
    +++ b/arch/x86/kvm/lapic.c
    @@ -2057,8 +2057,19 @@ void kvm_apic_accept_events(struct kvm_vcpu *vcpu)
    if (!kvm_vcpu_has_lapic(vcpu) || !apic->pending_events)
    return;

    - pe = xchg(&apic->pending_events, 0);
    + /*
    + * INITs are latched while in SMM. Because an SMM CPU cannot
    + * be in KVM_MP_STATE_INIT_RECEIVED state, just eat SIPIs
    + * and delay processing of INIT until the next RSM.
    + */
    + if (is_smm(vcpu)) {
    + WARN_ON_ONCE(vcpu->arch.mp_state == KVM_MP_STATE_INIT_RECEIVED);
    + if (test_bit(KVM_APIC_SIPI, &apic->pending_events))
    + clear_bit(KVM_APIC_SIPI, &apic->pending_events);
    + return;
    + }

    + pe = xchg(&apic->pending_events, 0);
    if (test_bit(KVM_APIC_INIT, &pe)) {
    kvm_lapic_reset(vcpu, true);
    kvm_vcpu_reset(vcpu, true);
    diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h
    index 9d8fcde52027..f2f4e10ab772 100644
    --- a/arch/x86/kvm/lapic.h
    +++ b/arch/x86/kvm/lapic.h
    @@ -159,6 +159,11 @@ static inline bool kvm_lowest_prio_delivery(struct kvm_lapic_irq *irq)
    irq->msi_redir_hint);
    }

    +static inline int kvm_lapic_latched_init(struct kvm_vcpu *vcpu)
    +{
    + return kvm_vcpu_has_lapic(vcpu) && test_bit(KVM_APIC_INIT, &vcpu->arch.apic->pending_events);
    +}
    +
    bool kvm_apic_pending_eoi(struct kvm_vcpu *vcpu, int vector);

    void wait_lapic_expire(struct kvm_vcpu *vcpu);
    diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
    index 36962b7627df..5e6d19730ef9 100644
    --- a/arch/x86/kvm/x86.c
    +++ b/arch/x86/kvm/x86.c
    @@ -3240,7 +3240,7 @@ static void kvm_vcpu_ioctl_x86_get_vcpu_events(struct kvm_vcpu *vcpu,
    events->smi.pending = vcpu->arch.smi_pending;
    events->smi.smm_inside_nmi =
    !!(vcpu->arch.hflags & HF_SMM_INSIDE_NMI_MASK);
    - events->smi.pad = 0;
    + events->smi.latched_init = kvm_lapic_latched_init(vcpu);

    events->flags = (KVM_VCPUEVENT_VALID_NMI_PENDING
    | KVM_VCPUEVENT_VALID_SHADOW
    @@ -3289,6 +3289,12 @@ static int kvm_vcpu_ioctl_x86_set_vcpu_events(struct kvm_vcpu *vcpu,
    vcpu->arch.hflags |= HF_SMM_INSIDE_NMI_MASK;
    else
    vcpu->arch.hflags &= ~HF_SMM_INSIDE_NMI_MASK;
    + if (kvm_vcpu_has_lapic(vcpu)) {
    + if (events->smi.latched_init)
    + set_bit(KVM_APIC_INIT, &vcpu->arch.apic->pending_events);
    + else
    + clear_bit(KVM_APIC_INIT, &vcpu->arch.apic->pending_events);
    + }
    }

    kvm_make_request(KVM_REQ_EVENT, vcpu);
    @@ -5495,6 +5501,9 @@ static void kvm_smm_changed(struct kvm_vcpu *vcpu)
    if (unlikely(vcpu->arch.smi_pending)) {
    kvm_make_request(KVM_REQ_SMI, vcpu);
    vcpu->arch.smi_pending = 0;
    + } else {
    + /* Process a latched INIT, if any. */
    + kvm_make_request(KVM_REQ_EVENT, vcpu);
    }
    }

    --
    1.8.3.1


    \
     
     \ /
      Last update: 2015-06-04 11:21    [W:2.599 / U:0.036 seconds]
    ©2003-2020 Jasper Spaans|hosted at Digital Ocean and TransIP|Read the blog|Advertise on this site