linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH 0/2] KVM: x86: Revert to fix apic_hw_disabled underflow
@ 2021-10-13  0:35 Sean Christopherson
  2021-10-13  0:35 ` [PATCH 1/2] Revert "KVM: x86: Open code necessary bits of kvm_lapic_set_base() at vCPU RESET" Sean Christopherson
                   ` (2 more replies)
  0 siblings, 3 replies; 4+ messages in thread
From: Sean Christopherson @ 2021-10-13  0:35 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Sean Christopherson, Vitaly Kuznetsov, Wanpeng Li, Jim Mattson,
	Joerg Roedel, kvm, linux-kernel, syzbot+9fc046ab2b0cf295a063,
	Tetsuo Handa

Revert (mostly) a patch from the vCPU RESET cleanup that open coded some
APIC shenanigans to avoid stuffing vcpu->arch.apic_base at vCPU creation,
and completely overlooked the side effects on apic_hw_disabled.  I went
for a revert as I think the original behavior is the least awful solution,
just somewhat poorly documented.

The second patch adds WARNs to detect "overflow", where "overflow" means
KVM incorrectly increments apic_hw_disabled.

Sean Christopherson (2):
  Revert "KVM: x86: Open code necessary bits of kvm_lapic_set_base() at
    vCPU RESET"
  KVM: x86: WARN if APIC HW/SW disable static keys are non-zero on
    unload

 arch/x86/kvm/lapic.c | 20 +++++++++++++-------
 1 file changed, 13 insertions(+), 7 deletions(-)

-- 
2.33.0.1079.g6e70778dc9-goog


^ permalink raw reply	[flat|nested] 4+ messages in thread

* [PATCH 1/2] Revert "KVM: x86: Open code necessary bits of kvm_lapic_set_base() at vCPU RESET"
  2021-10-13  0:35 [PATCH 0/2] KVM: x86: Revert to fix apic_hw_disabled underflow Sean Christopherson
@ 2021-10-13  0:35 ` Sean Christopherson
  2021-10-13  0:35 ` [PATCH 2/2] KVM: x86: WARN if APIC HW/SW disable static keys are non-zero on unload Sean Christopherson
  2021-10-15  9:02 ` [PATCH 0/2] KVM: x86: Revert to fix apic_hw_disabled underflow Paolo Bonzini
  2 siblings, 0 replies; 4+ messages in thread
From: Sean Christopherson @ 2021-10-13  0:35 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Sean Christopherson, Vitaly Kuznetsov, Wanpeng Li, Jim Mattson,
	Joerg Roedel, kvm, linux-kernel, syzbot+9fc046ab2b0cf295a063,
	Tetsuo Handa

Revert a change to open code bits of kvm_lapic_set_base() when emulating
APIC RESET to fix an apic_hw_disabled underflow bug due to arch.apic_base
and apic_hw_disabled being unsyncrhonized when the APIC is created.  If
kvm_arch_vcpu_create() fails after creating the APIC, kvm_free_lapic()
will see the initialized-to-zero vcpu->arch.apic_base and decrement
apic_hw_disabled without KVM ever having incremented apic_hw_disabled.

Using kvm_lapic_set_base() in kvm_lapic_reset() is also desirable for a
potential future where KVM supports RESET outside of vCPU creation, in
which case all the side effects of kvm_lapic_set_base() are needed, e.g.
to handle the transition from x2APIC => xAPIC.

Alternatively, KVM could temporarily increment apic_hw_disabled (and call
kvm_lapic_set_base() at RESET), but that's a waste of cycles and would
impact the performance of other vCPUs and VMs.  The other subtle side
effect is that updating the xAPIC ID needs to be done at RESET regardless
of whether the APIC was previously enabled, i.e. kvm_lapic_reset() needs
an explicit call to kvm_apic_set_xapic_id() regardless of whether or not
kvm_lapic_set_base() also performs the update.  That makes stuffing the
enable bit at vCPU creation slightly more palatable, as doing so affects
only the apic_hw_disabled key.

Opportunistically tweak the comment to explicitly call out the connection
between vcpu->arch.apic_base and apic_hw_disabled, and add a comment to
call out the need to always do kvm_apic_set_xapic_id() at RESET.

Underflow scenario:

  kvm_vm_ioctl() {
    kvm_vm_ioctl_create_vcpu() {
      kvm_arch_vcpu_create() {
        if (something_went_wrong)
          goto fail_free_lapic;
        /* vcpu->arch.apic_base is initialized when something_went_wrong is false. */
        kvm_vcpu_reset() {
          kvm_lapic_reset(struct kvm_vcpu *vcpu, bool init_event) {
            vcpu->arch.apic_base = APIC_DEFAULT_PHYS_BASE | MSR_IA32_APICBASE_ENABLE;
          }
        }
        return 0;
      fail_free_lapic:
        kvm_free_lapic() {
          /* vcpu->arch.apic_base is not yet initialized when something_went_wrong is true. */
          if (!(vcpu->arch.apic_base & MSR_IA32_APICBASE_ENABLE))
            static_branch_slow_dec_deferred(&apic_hw_disabled); // <= underflow bug.
        }
        return r;
      }
    }
  }

This (mostly) reverts commit 421221234ada41b4a9f0beeb08e30b07388bd4bd.

Fixes: 421221234ada ("KVM: x86: Open code necessary bits of kvm_lapic_set_base() at vCPU RESET")
Reported-by: syzbot+9fc046ab2b0cf295a063@syzkaller.appspotmail.com
Debugged-by: Tetsuo Handa <penguin-kernel@i-love.sakura.ne.jp>
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
 arch/x86/kvm/lapic.c | 18 +++++++++++-------
 1 file changed, 11 insertions(+), 7 deletions(-)

diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 76fb00921203..7af25304bda9 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -2321,13 +2321,14 @@ EXPORT_SYMBOL_GPL(kvm_apic_update_apicv);
 void kvm_lapic_reset(struct kvm_vcpu *vcpu, bool init_event)
 {
 	struct kvm_lapic *apic = vcpu->arch.apic;
+	u64 msr_val;
 	int i;
 
 	if (!init_event) {
-		vcpu->arch.apic_base = APIC_DEFAULT_PHYS_BASE |
-				       MSR_IA32_APICBASE_ENABLE;
+		msr_val = APIC_DEFAULT_PHYS_BASE | MSR_IA32_APICBASE_ENABLE;
 		if (kvm_vcpu_is_reset_bsp(vcpu))
-			vcpu->arch.apic_base |= MSR_IA32_APICBASE_BSP;
+			msr_val |= MSR_IA32_APICBASE_BSP;
+		kvm_lapic_set_base(vcpu, msr_val);
 	}
 
 	if (!apic)
@@ -2336,11 +2337,9 @@ void kvm_lapic_reset(struct kvm_vcpu *vcpu, bool init_event)
 	/* Stop the timer in case it's a reset to an active apic */
 	hrtimer_cancel(&apic->lapic_timer.timer);
 
-	if (!init_event) {
-		apic->base_address = APIC_DEFAULT_PHYS_BASE;
-
+	/* The xAPIC ID is set at RESET even if the APIC was already enabled. */
+	if (!init_event)
 		kvm_apic_set_xapic_id(apic, vcpu->vcpu_id);
-	}
 	kvm_apic_set_version(apic->vcpu);
 
 	for (i = 0; i < KVM_APIC_LVT_NUM; i++)
@@ -2481,6 +2480,11 @@ int kvm_create_lapic(struct kvm_vcpu *vcpu, int timer_advance_ns)
 		lapic_timer_advance_dynamic = false;
 	}
 
+	/*
+	 * Stuff the APIC ENABLE bit in lieu of temporarily incrementing
+	 * apic_hw_disabled; the full RESET value is set by kvm_lapic_reset().
+	 */
+	vcpu->arch.apic_base = MSR_IA32_APICBASE_ENABLE;
 	static_branch_inc(&apic_sw_disabled.key); /* sw disabled at reset */
 	kvm_iodevice_init(&apic->dev, &apic_mmio_ops);
 
-- 
2.33.0.1079.g6e70778dc9-goog


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* [PATCH 2/2] KVM: x86: WARN if APIC HW/SW disable static keys are non-zero on unload
  2021-10-13  0:35 [PATCH 0/2] KVM: x86: Revert to fix apic_hw_disabled underflow Sean Christopherson
  2021-10-13  0:35 ` [PATCH 1/2] Revert "KVM: x86: Open code necessary bits of kvm_lapic_set_base() at vCPU RESET" Sean Christopherson
@ 2021-10-13  0:35 ` Sean Christopherson
  2021-10-15  9:02 ` [PATCH 0/2] KVM: x86: Revert to fix apic_hw_disabled underflow Paolo Bonzini
  2 siblings, 0 replies; 4+ messages in thread
From: Sean Christopherson @ 2021-10-13  0:35 UTC (permalink / raw)
  To: Paolo Bonzini
  Cc: Sean Christopherson, Vitaly Kuznetsov, Wanpeng Li, Jim Mattson,
	Joerg Roedel, kvm, linux-kernel, syzbot+9fc046ab2b0cf295a063,
	Tetsuo Handa

WARN if the static keys used to track if any vCPU has disabled its APIC
are left elevated at module exit.  Unlike the underflow case, nothing in
the static key infrastructure will complain if a key is left elevated,
and because an elevated key only affects performance, nothing in KVM will
fail if either ey is improperly incremented.

Signed-off-by: Sean Christopherson <seanjc@google.com>
---
 arch/x86/kvm/lapic.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 7af25304bda9..d6ac32f3f650 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -2946,5 +2946,7 @@ int kvm_apic_accept_events(struct kvm_vcpu *vcpu)
 void kvm_lapic_exit(void)
 {
 	static_key_deferred_flush(&apic_hw_disabled);
+	WARN_ON(static_branch_unlikely(&apic_hw_disabled.key));
 	static_key_deferred_flush(&apic_sw_disabled);
+	WARN_ON(static_branch_unlikely(&apic_sw_disabled.key));
 }
-- 
2.33.0.1079.g6e70778dc9-goog


^ permalink raw reply related	[flat|nested] 4+ messages in thread

* Re: [PATCH 0/2] KVM: x86: Revert to fix apic_hw_disabled underflow
  2021-10-13  0:35 [PATCH 0/2] KVM: x86: Revert to fix apic_hw_disabled underflow Sean Christopherson
  2021-10-13  0:35 ` [PATCH 1/2] Revert "KVM: x86: Open code necessary bits of kvm_lapic_set_base() at vCPU RESET" Sean Christopherson
  2021-10-13  0:35 ` [PATCH 2/2] KVM: x86: WARN if APIC HW/SW disable static keys are non-zero on unload Sean Christopherson
@ 2021-10-15  9:02 ` Paolo Bonzini
  2 siblings, 0 replies; 4+ messages in thread
From: Paolo Bonzini @ 2021-10-15  9:02 UTC (permalink / raw)
  To: Sean Christopherson
  Cc: Vitaly Kuznetsov, Wanpeng Li, Jim Mattson, Joerg Roedel, kvm,
	linux-kernel, syzbot+9fc046ab2b0cf295a063, Tetsuo Handa

On 13/10/21 02:35, Sean Christopherson wrote:
> Revert (mostly) a patch from the vCPU RESET cleanup that open coded some
> APIC shenanigans to avoid stuffing vcpu->arch.apic_base at vCPU creation,
> and completely overlooked the side effects on apic_hw_disabled.  I went
> for a revert as I think the original behavior is the least awful solution,
> just somewhat poorly documented.
> 
> The second patch adds WARNs to detect "overflow", where "overflow" means
> KVM incorrectly increments apic_hw_disabled.
> 
> Sean Christopherson (2):
>    Revert "KVM: x86: Open code necessary bits of kvm_lapic_set_base() at
>      vCPU RESET"
>    KVM: x86: WARN if APIC HW/SW disable static keys are non-zero on
>      unload
> 
>   arch/x86/kvm/lapic.c | 20 +++++++++++++-------
>   1 file changed, 13 insertions(+), 7 deletions(-)
> 

Queued for 5.15, thanks.

Paolo


^ permalink raw reply	[flat|nested] 4+ messages in thread

end of thread, other threads:[~2021-10-15  9:02 UTC | newest]

Thread overview: 4+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2021-10-13  0:35 [PATCH 0/2] KVM: x86: Revert to fix apic_hw_disabled underflow Sean Christopherson
2021-10-13  0:35 ` [PATCH 1/2] Revert "KVM: x86: Open code necessary bits of kvm_lapic_set_base() at vCPU RESET" Sean Christopherson
2021-10-13  0:35 ` [PATCH 2/2] KVM: x86: WARN if APIC HW/SW disable static keys are non-zero on unload Sean Christopherson
2021-10-15  9:02 ` [PATCH 0/2] KVM: x86: Revert to fix apic_hw_disabled underflow Paolo Bonzini

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).