public inbox for kvm@vger.kernel.org
 help / color / mirror / Atom feed
* [PATCH v2 0/9] KVM: x86: Clean up MSR_IA32_APICBASE_BASE code
@ 2024-11-01 18:35 Sean Christopherson
  2024-11-01 18:35 ` [PATCH v2 1/9] KVM: x86: Short-circuit all kvm_lapic_set_base() if MSR value isn't changing Sean Christopherson
                   ` (9 more replies)
  0 siblings, 10 replies; 14+ messages in thread
From: Sean Christopherson @ 2024-11-01 18:35 UTC (permalink / raw)
  To: Sean Christopherson, Paolo Bonzini; +Cc: kvm, linux-kernel, Kai Huang

Clean up code related to setting and getting MSR_IA32_APICBASE_BASE.

E.g. it's absurdly difficult to tease out that kvm_set_apic_base() exists
purely to avoid an extra call to kvm_recalculate_apic_map() (which may or
may not be worth the code, but whatever).

Simiarly, it's quite difficult to see that kvm_lapic_set_base() doesn't
do anything useful if the incoming MSR value is the same as the current
value.

v2:
 - Collect reviews. [Kai, Paolo]
 - Add a comment in kvm_lapic_reset() to explain its usage of the inner
   __kvm_apic_set_base() helper. [Paolo]
 - Unpack "struct msr_data" before calling kvm_apic_set_base(), e.g. so
   that __set_sregs_common() doesn't half-fill a structure and rely on
   kvm_apic_set_base() to ignore "index". [Kai]
 - Tack on a patch to short circuit all of kvm_apic_set_base() when the
   MSR isn't changing, to avoid the rare slow path of triggering an APIC
   map recalc due to some other task marking the map dirty.

v1: https://lore.kernel.org/all/20241009181742.1128779-1-seanjc@google.com

Sean Christopherson (9):
  KVM: x86: Short-circuit all kvm_lapic_set_base() if MSR value isn't
    changing
  KVM: x86: Drop superfluous kvm_lapic_set_base() call when setting APIC
    state
  KVM: x86: Get vcpu->arch.apic_base directly and drop
    kvm_get_apic_base()
  KVM: x86: Inline kvm_get_apic_mode() in lapic.h
  KVM: x86: Move kvm_set_apic_base() implementation to lapic.c (from
    x86.c)
  KVM: x86: Rename APIC base setters to better capture their
    relationship
  KVM: x86: Make kvm_recalculate_apic_map() local to lapic.c
  KVM: x86: Unpack msr_data structure prior to calling
    kvm_apic_set_base()
  KVM: x86: Short-circuit all of kvm_apic_set_base() if MSR value is
    unchanged

 arch/x86/kvm/lapic.c | 39 ++++++++++++++++++++++++++++++++++----
 arch/x86/kvm/lapic.h | 11 ++++++-----
 arch/x86/kvm/x86.c   | 45 +++++---------------------------------------
 3 files changed, 46 insertions(+), 49 deletions(-)


base-commit: e466901b947d529f7b091a3b00b19d2bdee206ee
-- 
2.47.0.163.g1226f6d8fa-goog


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

* [PATCH v2 1/9] KVM: x86: Short-circuit all kvm_lapic_set_base() if MSR value isn't changing
  2024-11-01 18:35 [PATCH v2 0/9] KVM: x86: Clean up MSR_IA32_APICBASE_BASE code Sean Christopherson
@ 2024-11-01 18:35 ` Sean Christopherson
  2024-11-01 18:35 ` [PATCH v2 2/9] KVM: x86: Drop superfluous kvm_lapic_set_base() call when setting APIC state Sean Christopherson
                   ` (8 subsequent siblings)
  9 siblings, 0 replies; 14+ messages in thread
From: Sean Christopherson @ 2024-11-01 18:35 UTC (permalink / raw)
  To: Sean Christopherson, Paolo Bonzini; +Cc: kvm, linux-kernel, Kai Huang

Do nothing in kvm_lapic_set_base() if the APIC base MSR value is the same
as the current value.  All flows except the handling of the base address
explicitly take effect if and only if relevant bits are changing.

For the base address, invoking kvm_lapic_set_base() before KVM initializes
the base to APIC_DEFAULT_PHYS_BASE during vCPU RESET would be a KVM bug,
i.e. KVM _must_ initialize apic->base_address before exposing the vCPU (to
userspace or KVM at-large).

Note, the inhibit is intended to be set if the base address is _changed_
from the default, i.e. is also covered by the RESET behavior.

Reviewed-by: Kai Huang <kai.huang@intel.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Link: https://lore.kernel.org/r/20241009181742.1128779-2-seanjc@google.com
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
 arch/x86/kvm/lapic.c | 3 +++
 1 file changed, 3 insertions(+)

diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 65412640cfc7..8fe63f719254 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -2582,6 +2582,9 @@ void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value)
 	u64 old_value = vcpu->arch.apic_base;
 	struct kvm_lapic *apic = vcpu->arch.apic;
 
+	if (old_value == value)
+		return;
+
 	vcpu->arch.apic_base = value;
 
 	if ((old_value ^ value) & MSR_IA32_APICBASE_ENABLE)
-- 
2.47.0.163.g1226f6d8fa-goog


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

* [PATCH v2 2/9] KVM: x86: Drop superfluous kvm_lapic_set_base() call when setting APIC state
  2024-11-01 18:35 [PATCH v2 0/9] KVM: x86: Clean up MSR_IA32_APICBASE_BASE code Sean Christopherson
  2024-11-01 18:35 ` [PATCH v2 1/9] KVM: x86: Short-circuit all kvm_lapic_set_base() if MSR value isn't changing Sean Christopherson
@ 2024-11-01 18:35 ` Sean Christopherson
  2024-11-01 18:35 ` [PATCH v2 3/9] KVM: x86: Get vcpu->arch.apic_base directly and drop kvm_get_apic_base() Sean Christopherson
                   ` (7 subsequent siblings)
  9 siblings, 0 replies; 14+ messages in thread
From: Sean Christopherson @ 2024-11-01 18:35 UTC (permalink / raw)
  To: Sean Christopherson, Paolo Bonzini; +Cc: kvm, linux-kernel, Kai Huang

Now that kvm_lapic_set_base() does nothing if the "new" APIC base MSR is
the same as the current value, drop the kvm_lapic_set_base() call in the
KVM_SET_LAPIC flow that passes in the current value, as it too does
nothing.

Note, the purpose of invoking kvm_lapic_set_base() was purely to set
apic->base_address (see commit 5dbc8f3fed0b ("KVM: use kvm_lapic_set_base()
to change apic_base")).  And there is no evidence that explicitly setting
apic->base_address in KVM_SET_LAPIC ever had any functional impact; even
in the original commit 96ad2cc61324 ("KVM: in-kernel LAPIC save and restore
support"), all flows that set apic_base also set apic->base_address to the
same address.  E.g. svm_create_vcpu() did open code a write to apic_base,

	svm->vcpu.apic_base = 0xfee00000 | MSR_IA32_APICBASE_ENABLE;

but it also called kvm_create_lapic() when irqchip_in_kernel() is true.

Reviewed-by: Kai Huang <kai.huang@intel.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Link: https://lore.kernel.org/r/20241009181742.1128779-3-seanjc@google.com
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
 arch/x86/kvm/lapic.c | 1 -
 1 file changed, 1 deletion(-)

diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 8fe63f719254..9f88a49654b0 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -3060,7 +3060,6 @@ int kvm_apic_set_state(struct kvm_vcpu *vcpu, struct kvm_lapic_state *s)
 
 	kvm_x86_call(apicv_pre_state_restore)(vcpu);
 
-	kvm_lapic_set_base(vcpu, vcpu->arch.apic_base);
 	/* set SPIV separately to get count of SW disabled APICs right */
 	apic_set_spiv(apic, *((u32 *)(s->regs + APIC_SPIV)));
 
-- 
2.47.0.163.g1226f6d8fa-goog


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

* [PATCH v2 3/9] KVM: x86: Get vcpu->arch.apic_base directly and drop kvm_get_apic_base()
  2024-11-01 18:35 [PATCH v2 0/9] KVM: x86: Clean up MSR_IA32_APICBASE_BASE code Sean Christopherson
  2024-11-01 18:35 ` [PATCH v2 1/9] KVM: x86: Short-circuit all kvm_lapic_set_base() if MSR value isn't changing Sean Christopherson
  2024-11-01 18:35 ` [PATCH v2 2/9] KVM: x86: Drop superfluous kvm_lapic_set_base() call when setting APIC state Sean Christopherson
@ 2024-11-01 18:35 ` Sean Christopherson
  2024-11-01 18:35 ` [PATCH v2 4/9] KVM: x86: Inline kvm_get_apic_mode() in lapic.h Sean Christopherson
                   ` (6 subsequent siblings)
  9 siblings, 0 replies; 14+ messages in thread
From: Sean Christopherson @ 2024-11-01 18:35 UTC (permalink / raw)
  To: Sean Christopherson, Paolo Bonzini; +Cc: kvm, linux-kernel, Kai Huang

Access KVM's emulated APIC base MSR value directly instead of bouncing
through a helper, as there is no reason to add a layer of indirection, and
there are other MSRs with a "set" but no "get", e.g. EFER.

No functional change intended.

Reviewed-by: Kai Huang <kai.huang@intel.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Link: https://lore.kernel.org/r/20241009181742.1128779-4-seanjc@google.com
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
 arch/x86/kvm/lapic.h |  1 -
 arch/x86/kvm/x86.c   | 13 ++++---------
 2 files changed, 4 insertions(+), 10 deletions(-)

diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h
index 1b8ef9856422..441abc4f4afd 100644
--- a/arch/x86/kvm/lapic.h
+++ b/arch/x86/kvm/lapic.h
@@ -117,7 +117,6 @@ bool kvm_irq_delivery_to_apic_fast(struct kvm *kvm, struct kvm_lapic *src,
 		struct kvm_lapic_irq *irq, int *r, struct dest_map *dest_map);
 void kvm_apic_send_ipi(struct kvm_lapic *apic, u32 icr_low, u32 icr_high);
 
-u64 kvm_get_apic_base(struct kvm_vcpu *vcpu);
 int kvm_set_apic_base(struct kvm_vcpu *vcpu, struct msr_data *msr_info);
 int kvm_apic_get_state(struct kvm_vcpu *vcpu, struct kvm_lapic_state *s);
 int kvm_apic_set_state(struct kvm_vcpu *vcpu, struct kvm_lapic_state *s);
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index e45040c2bf03..118e6eba35ba 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -668,14 +668,9 @@ static void drop_user_return_notifiers(void)
 		kvm_on_user_return(&msrs->urn);
 }
 
-u64 kvm_get_apic_base(struct kvm_vcpu *vcpu)
-{
-	return vcpu->arch.apic_base;
-}
-
 enum lapic_mode kvm_get_apic_mode(struct kvm_vcpu *vcpu)
 {
-	return kvm_apic_mode(kvm_get_apic_base(vcpu));
+	return kvm_apic_mode(vcpu->arch.apic_base);
 }
 EXPORT_SYMBOL_GPL(kvm_get_apic_mode);
 
@@ -4315,7 +4310,7 @@ int kvm_get_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
 		msr_info->data = 1 << 24;
 		break;
 	case MSR_IA32_APICBASE:
-		msr_info->data = kvm_get_apic_base(vcpu);
+		msr_info->data = vcpu->arch.apic_base;
 		break;
 	case APIC_BASE_MSR ... APIC_BASE_MSR + 0xff:
 		return kvm_x2apic_msr_read(vcpu, msr_info->index, &msr_info->data);
@@ -10173,7 +10168,7 @@ static void post_kvm_run_save(struct kvm_vcpu *vcpu)
 
 	kvm_run->if_flag = kvm_x86_call(get_if_flag)(vcpu);
 	kvm_run->cr8 = kvm_get_cr8(vcpu);
-	kvm_run->apic_base = kvm_get_apic_base(vcpu);
+	kvm_run->apic_base = vcpu->arch.apic_base;
 
 	kvm_run->ready_for_interrupt_injection =
 		pic_in_kernel(vcpu->kvm) ||
@@ -11725,7 +11720,7 @@ static void __get_sregs_common(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs)
 	sregs->cr4 = kvm_read_cr4(vcpu);
 	sregs->cr8 = kvm_get_cr8(vcpu);
 	sregs->efer = vcpu->arch.efer;
-	sregs->apic_base = kvm_get_apic_base(vcpu);
+	sregs->apic_base = vcpu->arch.apic_base;
 }
 
 static void __get_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs)
-- 
2.47.0.163.g1226f6d8fa-goog


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

* [PATCH v2 4/9] KVM: x86: Inline kvm_get_apic_mode() in lapic.h
  2024-11-01 18:35 [PATCH v2 0/9] KVM: x86: Clean up MSR_IA32_APICBASE_BASE code Sean Christopherson
                   ` (2 preceding siblings ...)
  2024-11-01 18:35 ` [PATCH v2 3/9] KVM: x86: Get vcpu->arch.apic_base directly and drop kvm_get_apic_base() Sean Christopherson
@ 2024-11-01 18:35 ` Sean Christopherson
  2024-11-01 18:35 ` [PATCH v2 5/9] KVM: x86: Move kvm_set_apic_base() implementation to lapic.c (from x86.c) Sean Christopherson
                   ` (5 subsequent siblings)
  9 siblings, 0 replies; 14+ messages in thread
From: Sean Christopherson @ 2024-11-01 18:35 UTC (permalink / raw)
  To: Sean Christopherson, Paolo Bonzini; +Cc: kvm, linux-kernel, Kai Huang

Inline kvm_get_apic_mode() in lapic.h to avoid a CALL+RET as well as an
export.  The underlying kvm_apic_mode() helper is public information, i.e.
there is no state/information that needs to be hidden from vendor modules.

No functional change intended.

Reviewed-by: Kai Huang <kai.huang@intel.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Link: https://lore.kernel.org/r/20241009181742.1128779-5-seanjc@google.com
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
 arch/x86/kvm/lapic.h | 6 +++++-
 arch/x86/kvm/x86.c   | 6 ------
 2 files changed, 5 insertions(+), 7 deletions(-)

diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h
index 441abc4f4afd..fc4bd36d44cf 100644
--- a/arch/x86/kvm/lapic.h
+++ b/arch/x86/kvm/lapic.h
@@ -120,7 +120,6 @@ void kvm_apic_send_ipi(struct kvm_lapic *apic, u32 icr_low, u32 icr_high);
 int kvm_set_apic_base(struct kvm_vcpu *vcpu, struct msr_data *msr_info);
 int kvm_apic_get_state(struct kvm_vcpu *vcpu, struct kvm_lapic_state *s);
 int kvm_apic_set_state(struct kvm_vcpu *vcpu, struct kvm_lapic_state *s);
-enum lapic_mode kvm_get_apic_mode(struct kvm_vcpu *vcpu);
 int kvm_lapic_find_highest_irr(struct kvm_vcpu *vcpu);
 
 u64 kvm_get_lapic_tscdeadline_msr(struct kvm_vcpu *vcpu);
@@ -270,6 +269,11 @@ static inline enum lapic_mode kvm_apic_mode(u64 apic_base)
 	return apic_base & (MSR_IA32_APICBASE_ENABLE | X2APIC_ENABLE);
 }
 
+static inline enum lapic_mode kvm_get_apic_mode(struct kvm_vcpu *vcpu)
+{
+	return kvm_apic_mode(vcpu->arch.apic_base);
+}
+
 static inline u8 kvm_xapic_id(struct kvm_lapic *apic)
 {
 	return kvm_lapic_get_reg(apic, APIC_ID) >> 24;
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 118e6eba35ba..95af45542355 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -668,12 +668,6 @@ static void drop_user_return_notifiers(void)
 		kvm_on_user_return(&msrs->urn);
 }
 
-enum lapic_mode kvm_get_apic_mode(struct kvm_vcpu *vcpu)
-{
-	return kvm_apic_mode(vcpu->arch.apic_base);
-}
-EXPORT_SYMBOL_GPL(kvm_get_apic_mode);
-
 int kvm_set_apic_base(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
 {
 	enum lapic_mode old_mode = kvm_get_apic_mode(vcpu);
-- 
2.47.0.163.g1226f6d8fa-goog


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

* [PATCH v2 5/9] KVM: x86: Move kvm_set_apic_base() implementation to lapic.c (from x86.c)
  2024-11-01 18:35 [PATCH v2 0/9] KVM: x86: Clean up MSR_IA32_APICBASE_BASE code Sean Christopherson
                   ` (3 preceding siblings ...)
  2024-11-01 18:35 ` [PATCH v2 4/9] KVM: x86: Inline kvm_get_apic_mode() in lapic.h Sean Christopherson
@ 2024-11-01 18:35 ` Sean Christopherson
  2024-11-01 18:35 ` [PATCH v2 6/9] KVM: x86: Rename APIC base setters to better capture their relationship Sean Christopherson
                   ` (4 subsequent siblings)
  9 siblings, 0 replies; 14+ messages in thread
From: Sean Christopherson @ 2024-11-01 18:35 UTC (permalink / raw)
  To: Sean Christopherson, Paolo Bonzini; +Cc: kvm, linux-kernel, Kai Huang

Move kvm_set_apic_base() to lapic.c so that the bulk of KVM's local APIC
code resides in lapic.c, regardless of whether or not KVM is emulating the
local APIC in-kernel.  This will also allow making various helpers visible
only to lapic.c.

No functional change intended.

Reviewed-by: Kai Huang <kai.huang@intel.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Link: https://lore.kernel.org/r/20241009181742.1128779-6-seanjc@google.com
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
 arch/x86/kvm/lapic.c | 21 +++++++++++++++++++++
 arch/x86/kvm/x86.c   | 21 ---------------------
 2 files changed, 21 insertions(+), 21 deletions(-)

diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 9f88a49654b0..b4cc5b0e8796 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -2628,6 +2628,27 @@ void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value)
 	}
 }
 
+int kvm_set_apic_base(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
+{
+	enum lapic_mode old_mode = kvm_get_apic_mode(vcpu);
+	enum lapic_mode new_mode = kvm_apic_mode(msr_info->data);
+	u64 reserved_bits = kvm_vcpu_reserved_gpa_bits_raw(vcpu) | 0x2ff |
+		(guest_cpuid_has(vcpu, X86_FEATURE_X2APIC) ? 0 : X2APIC_ENABLE);
+
+	if ((msr_info->data & reserved_bits) != 0 || new_mode == LAPIC_MODE_INVALID)
+		return 1;
+	if (!msr_info->host_initiated) {
+		if (old_mode == LAPIC_MODE_X2APIC && new_mode == LAPIC_MODE_XAPIC)
+			return 1;
+		if (old_mode == LAPIC_MODE_DISABLED && new_mode == LAPIC_MODE_X2APIC)
+			return 1;
+	}
+
+	kvm_lapic_set_base(vcpu, msr_info->data);
+	kvm_recalculate_apic_map(vcpu->kvm);
+	return 0;
+}
+
 void kvm_apic_update_apicv(struct kvm_vcpu *vcpu)
 {
 	struct kvm_lapic *apic = vcpu->arch.apic;
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 95af45542355..57dca2bdd40d 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -668,27 +668,6 @@ static void drop_user_return_notifiers(void)
 		kvm_on_user_return(&msrs->urn);
 }
 
-int kvm_set_apic_base(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
-{
-	enum lapic_mode old_mode = kvm_get_apic_mode(vcpu);
-	enum lapic_mode new_mode = kvm_apic_mode(msr_info->data);
-	u64 reserved_bits = kvm_vcpu_reserved_gpa_bits_raw(vcpu) | 0x2ff |
-		(guest_cpuid_has(vcpu, X86_FEATURE_X2APIC) ? 0 : X2APIC_ENABLE);
-
-	if ((msr_info->data & reserved_bits) != 0 || new_mode == LAPIC_MODE_INVALID)
-		return 1;
-	if (!msr_info->host_initiated) {
-		if (old_mode == LAPIC_MODE_X2APIC && new_mode == LAPIC_MODE_XAPIC)
-			return 1;
-		if (old_mode == LAPIC_MODE_DISABLED && new_mode == LAPIC_MODE_X2APIC)
-			return 1;
-	}
-
-	kvm_lapic_set_base(vcpu, msr_info->data);
-	kvm_recalculate_apic_map(vcpu->kvm);
-	return 0;
-}
-
 /*
  * Handle a fault on a hardware virtualization (VMX or SVM) instruction.
  *
-- 
2.47.0.163.g1226f6d8fa-goog


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

* [PATCH v2 6/9] KVM: x86: Rename APIC base setters to better capture their relationship
  2024-11-01 18:35 [PATCH v2 0/9] KVM: x86: Clean up MSR_IA32_APICBASE_BASE code Sean Christopherson
                   ` (4 preceding siblings ...)
  2024-11-01 18:35 ` [PATCH v2 5/9] KVM: x86: Move kvm_set_apic_base() implementation to lapic.c (from x86.c) Sean Christopherson
@ 2024-11-01 18:35 ` Sean Christopherson
  2024-11-01 18:35 ` [PATCH v2 7/9] KVM: x86: Make kvm_recalculate_apic_map() local to lapic.c Sean Christopherson
                   ` (3 subsequent siblings)
  9 siblings, 0 replies; 14+ messages in thread
From: Sean Christopherson @ 2024-11-01 18:35 UTC (permalink / raw)
  To: Sean Christopherson, Paolo Bonzini; +Cc: kvm, linux-kernel, Kai Huang

Rename kvm_set_apic_base() and kvm_lapic_set_base() to kvm_apic_set_base()
and __kvm_apic_set_base() respectively to capture that the underscores
version is a "special" variant (it exists purely to avoid recalculating
the optimized map multiple times when stuffing the RESET value).

Opportunistically add a comment explaining why kvm_lapic_reset() uses the
inner helper.  Note, KVM deliberately invokes kvm_arch_vcpu_create() while
kvm->lock is NOT held so that vCPU setup isn't serialized if userspace is
creating multiple/all vCPUs in parallel.  I.e. triggering an extra
recalculation is not limited to theoretical/rare edge cases, and so is
worth avoiding.

No functional change intended.

Reviewed-by: Kai Huang <kai.huang@intel.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Link: https://lore.kernel.org/r/20241009181742.1128779-7-seanjc@google.com
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
 arch/x86/kvm/lapic.c | 15 +++++++++++----
 arch/x86/kvm/lapic.h |  3 +--
 arch/x86/kvm/x86.c   |  4 ++--
 3 files changed, 14 insertions(+), 8 deletions(-)

diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index b4cc5b0e8796..0472a94e7b3b 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -2577,7 +2577,7 @@ u64 kvm_lapic_get_cr8(struct kvm_vcpu *vcpu)
 	return (tpr & 0xf0) >> 4;
 }
 
-void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value)
+static void __kvm_apic_set_base(struct kvm_vcpu *vcpu, u64 value)
 {
 	u64 old_value = vcpu->arch.apic_base;
 	struct kvm_lapic *apic = vcpu->arch.apic;
@@ -2628,7 +2628,7 @@ void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value)
 	}
 }
 
-int kvm_set_apic_base(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
+int kvm_apic_set_base(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
 {
 	enum lapic_mode old_mode = kvm_get_apic_mode(vcpu);
 	enum lapic_mode new_mode = kvm_apic_mode(msr_info->data);
@@ -2644,7 +2644,7 @@ int kvm_set_apic_base(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
 			return 1;
 	}
 
-	kvm_lapic_set_base(vcpu, msr_info->data);
+	__kvm_apic_set_base(vcpu, msr_info->data);
 	kvm_recalculate_apic_map(vcpu->kvm);
 	return 0;
 }
@@ -2740,7 +2740,14 @@ void kvm_lapic_reset(struct kvm_vcpu *vcpu, bool init_event)
 		msr_val = APIC_DEFAULT_PHYS_BASE | MSR_IA32_APICBASE_ENABLE;
 		if (kvm_vcpu_is_reset_bsp(vcpu))
 			msr_val |= MSR_IA32_APICBASE_BSP;
-		kvm_lapic_set_base(vcpu, msr_val);
+
+		/*
+		 * Use the inner helper to avoid an extra recalcuation of the
+		 * optimized APIC map if some other task has dirtied the map.
+		 * The recalculation needed for this vCPU will be done after
+		 * all APIC state has been initialized (see below).
+		 */
+		__kvm_apic_set_base(vcpu, msr_val);
 	}
 
 	if (!apic)
diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h
index fc4bd36d44cf..0dd5055852ad 100644
--- a/arch/x86/kvm/lapic.h
+++ b/arch/x86/kvm/lapic.h
@@ -95,7 +95,6 @@ void kvm_lapic_reset(struct kvm_vcpu *vcpu, bool init_event);
 u64 kvm_lapic_get_cr8(struct kvm_vcpu *vcpu);
 void kvm_lapic_set_tpr(struct kvm_vcpu *vcpu, unsigned long cr8);
 void kvm_lapic_set_eoi(struct kvm_vcpu *vcpu);
-void kvm_lapic_set_base(struct kvm_vcpu *vcpu, u64 value);
 void kvm_recalculate_apic_map(struct kvm *kvm);
 void kvm_apic_set_version(struct kvm_vcpu *vcpu);
 void kvm_apic_after_set_mcg_cap(struct kvm_vcpu *vcpu);
@@ -117,7 +116,7 @@ bool kvm_irq_delivery_to_apic_fast(struct kvm *kvm, struct kvm_lapic *src,
 		struct kvm_lapic_irq *irq, int *r, struct dest_map *dest_map);
 void kvm_apic_send_ipi(struct kvm_lapic *apic, u32 icr_low, u32 icr_high);
 
-int kvm_set_apic_base(struct kvm_vcpu *vcpu, struct msr_data *msr_info);
+int kvm_apic_set_base(struct kvm_vcpu *vcpu, struct msr_data *msr_info);
 int kvm_apic_get_state(struct kvm_vcpu *vcpu, struct kvm_lapic_state *s);
 int kvm_apic_set_state(struct kvm_vcpu *vcpu, struct kvm_lapic_state *s);
 int kvm_lapic_find_highest_irr(struct kvm_vcpu *vcpu);
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index 57dca2bdd40d..e01188dc82d1 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -3863,7 +3863,7 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
 	case MSR_MTRRdefType:
 		return kvm_mtrr_set_msr(vcpu, msr, data);
 	case MSR_IA32_APICBASE:
-		return kvm_set_apic_base(vcpu, msr_info);
+		return kvm_apic_set_base(vcpu, msr_info);
 	case APIC_BASE_MSR ... APIC_BASE_MSR + 0xff:
 		return kvm_x2apic_msr_write(vcpu, msr, data);
 	case MSR_IA32_TSC_DEADLINE:
@@ -11879,7 +11879,7 @@ static int __set_sregs_common(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs,
 
 	apic_base_msr.data = sregs->apic_base;
 	apic_base_msr.host_initiated = true;
-	if (kvm_set_apic_base(vcpu, &apic_base_msr))
+	if (kvm_apic_set_base(vcpu, &apic_base_msr))
 		return -EINVAL;
 
 	if (vcpu->arch.guest_state_protected)
-- 
2.47.0.163.g1226f6d8fa-goog


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

* [PATCH v2 7/9] KVM: x86: Make kvm_recalculate_apic_map() local to lapic.c
  2024-11-01 18:35 [PATCH v2 0/9] KVM: x86: Clean up MSR_IA32_APICBASE_BASE code Sean Christopherson
                   ` (5 preceding siblings ...)
  2024-11-01 18:35 ` [PATCH v2 6/9] KVM: x86: Rename APIC base setters to better capture their relationship Sean Christopherson
@ 2024-11-01 18:35 ` Sean Christopherson
  2024-11-01 18:35 ` [PATCH v2 8/9] KVM: x86: Unpack msr_data structure prior to calling kvm_apic_set_base() Sean Christopherson
                   ` (2 subsequent siblings)
  9 siblings, 0 replies; 14+ messages in thread
From: Sean Christopherson @ 2024-11-01 18:35 UTC (permalink / raw)
  To: Sean Christopherson, Paolo Bonzini; +Cc: kvm, linux-kernel, Kai Huang

Make kvm_recalculate_apic_map() local to lapic.c now that all external
callers are gone.

No functional change intended.

Reviewed-by: Kai Huang <kai.huang@intel.com>
Reviewed-by: Paolo Bonzini <pbonzini@redhat.com>
Link: https://lore.kernel.org/r/20241009181742.1128779-8-seanjc@google.com
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
 arch/x86/kvm/lapic.c | 2 +-
 arch/x86/kvm/lapic.h | 1 -
 2 files changed, 1 insertion(+), 2 deletions(-)

diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 0472a94e7b3b..7ddbebf78761 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -382,7 +382,7 @@ enum {
 	DIRTY
 };
 
-void kvm_recalculate_apic_map(struct kvm *kvm)
+static void kvm_recalculate_apic_map(struct kvm *kvm)
 {
 	struct kvm_apic_map *new, *old = NULL;
 	struct kvm_vcpu *vcpu;
diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h
index 0dd5055852ad..fdd6cf29a0be 100644
--- a/arch/x86/kvm/lapic.h
+++ b/arch/x86/kvm/lapic.h
@@ -95,7 +95,6 @@ void kvm_lapic_reset(struct kvm_vcpu *vcpu, bool init_event);
 u64 kvm_lapic_get_cr8(struct kvm_vcpu *vcpu);
 void kvm_lapic_set_tpr(struct kvm_vcpu *vcpu, unsigned long cr8);
 void kvm_lapic_set_eoi(struct kvm_vcpu *vcpu);
-void kvm_recalculate_apic_map(struct kvm *kvm);
 void kvm_apic_set_version(struct kvm_vcpu *vcpu);
 void kvm_apic_after_set_mcg_cap(struct kvm_vcpu *vcpu);
 bool kvm_apic_match_dest(struct kvm_vcpu *vcpu, struct kvm_lapic *source,
-- 
2.47.0.163.g1226f6d8fa-goog


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

* [PATCH v2 8/9] KVM: x86: Unpack msr_data structure prior to calling kvm_apic_set_base()
  2024-11-01 18:35 [PATCH v2 0/9] KVM: x86: Clean up MSR_IA32_APICBASE_BASE code Sean Christopherson
                   ` (6 preceding siblings ...)
  2024-11-01 18:35 ` [PATCH v2 7/9] KVM: x86: Make kvm_recalculate_apic_map() local to lapic.c Sean Christopherson
@ 2024-11-01 18:35 ` Sean Christopherson
  2024-11-04 10:28   ` Huang, Kai
  2024-11-01 18:35 ` [PATCH v2 9/9] KVM: x86: Short-circuit all of kvm_apic_set_base() if MSR value is unchanged Sean Christopherson
  2024-11-05  5:56 ` [PATCH v2 0/9] KVM: x86: Clean up MSR_IA32_APICBASE_BASE code Sean Christopherson
  9 siblings, 1 reply; 14+ messages in thread
From: Sean Christopherson @ 2024-11-01 18:35 UTC (permalink / raw)
  To: Sean Christopherson, Paolo Bonzini; +Cc: kvm, linux-kernel, Kai Huang

Pass in the new value and "host initiated" as separate parameters to
kvm_apic_set_base(), as forcing the KVM_SET_SREGS path to declare and fill
an msr_data structure is awkward and kludgy, e.g. __set_sregs_common()
doesn't even bother to set the proper MSR index.

No functional change intended.

Suggested-by: Kai Huang <kai.huang@intel.com>
Signed-off-by: Sean Christopherson <seanjc@google.com>
---
 arch/x86/kvm/lapic.c | 10 +++++-----
 arch/x86/kvm/lapic.h |  2 +-
 arch/x86/kvm/x86.c   |  7 ++-----
 3 files changed, 8 insertions(+), 11 deletions(-)

diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 7ddbebf78761..7b2342e40e4e 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -2628,23 +2628,23 @@ static void __kvm_apic_set_base(struct kvm_vcpu *vcpu, u64 value)
 	}
 }
 
-int kvm_apic_set_base(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
+int kvm_apic_set_base(struct kvm_vcpu *vcpu, u64 value, bool host_initiated)
 {
 	enum lapic_mode old_mode = kvm_get_apic_mode(vcpu);
-	enum lapic_mode new_mode = kvm_apic_mode(msr_info->data);
+	enum lapic_mode new_mode = kvm_apic_mode(value);
 	u64 reserved_bits = kvm_vcpu_reserved_gpa_bits_raw(vcpu) | 0x2ff |
 		(guest_cpuid_has(vcpu, X86_FEATURE_X2APIC) ? 0 : X2APIC_ENABLE);
 
-	if ((msr_info->data & reserved_bits) != 0 || new_mode == LAPIC_MODE_INVALID)
+	if ((value & reserved_bits) != 0 || new_mode == LAPIC_MODE_INVALID)
 		return 1;
-	if (!msr_info->host_initiated) {
+	if (!host_initiated) {
 		if (old_mode == LAPIC_MODE_X2APIC && new_mode == LAPIC_MODE_XAPIC)
 			return 1;
 		if (old_mode == LAPIC_MODE_DISABLED && new_mode == LAPIC_MODE_X2APIC)
 			return 1;
 	}
 
-	__kvm_apic_set_base(vcpu, msr_info->data);
+	__kvm_apic_set_base(vcpu, value);
 	kvm_recalculate_apic_map(vcpu->kvm);
 	return 0;
 }
diff --git a/arch/x86/kvm/lapic.h b/arch/x86/kvm/lapic.h
index fdd6cf29a0be..24add38beaf0 100644
--- a/arch/x86/kvm/lapic.h
+++ b/arch/x86/kvm/lapic.h
@@ -115,7 +115,7 @@ bool kvm_irq_delivery_to_apic_fast(struct kvm *kvm, struct kvm_lapic *src,
 		struct kvm_lapic_irq *irq, int *r, struct dest_map *dest_map);
 void kvm_apic_send_ipi(struct kvm_lapic *apic, u32 icr_low, u32 icr_high);
 
-int kvm_apic_set_base(struct kvm_vcpu *vcpu, struct msr_data *msr_info);
+int kvm_apic_set_base(struct kvm_vcpu *vcpu, u64 value, bool host_initiated);
 int kvm_apic_get_state(struct kvm_vcpu *vcpu, struct kvm_lapic_state *s);
 int kvm_apic_set_state(struct kvm_vcpu *vcpu, struct kvm_lapic_state *s);
 int kvm_lapic_find_highest_irr(struct kvm_vcpu *vcpu);
diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c
index e01188dc82d1..8637bc001096 100644
--- a/arch/x86/kvm/x86.c
+++ b/arch/x86/kvm/x86.c
@@ -3863,7 +3863,7 @@ int kvm_set_msr_common(struct kvm_vcpu *vcpu, struct msr_data *msr_info)
 	case MSR_MTRRdefType:
 		return kvm_mtrr_set_msr(vcpu, msr, data);
 	case MSR_IA32_APICBASE:
-		return kvm_apic_set_base(vcpu, msr_info);
+		return kvm_apic_set_base(vcpu, data, msr_info->host_initiated);
 	case APIC_BASE_MSR ... APIC_BASE_MSR + 0xff:
 		return kvm_x2apic_msr_write(vcpu, msr, data);
 	case MSR_IA32_TSC_DEADLINE:
@@ -11870,16 +11870,13 @@ static bool kvm_is_valid_sregs(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs)
 static int __set_sregs_common(struct kvm_vcpu *vcpu, struct kvm_sregs *sregs,
 		int *mmu_reset_needed, bool update_pdptrs)
 {
-	struct msr_data apic_base_msr;
 	int idx;
 	struct desc_ptr dt;
 
 	if (!kvm_is_valid_sregs(vcpu, sregs))
 		return -EINVAL;
 
-	apic_base_msr.data = sregs->apic_base;
-	apic_base_msr.host_initiated = true;
-	if (kvm_apic_set_base(vcpu, &apic_base_msr))
+	if (kvm_apic_set_base(vcpu, sregs->apic_base, true))
 		return -EINVAL;
 
 	if (vcpu->arch.guest_state_protected)
-- 
2.47.0.163.g1226f6d8fa-goog


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

* [PATCH v2 9/9] KVM: x86: Short-circuit all of kvm_apic_set_base() if MSR value is unchanged
  2024-11-01 18:35 [PATCH v2 0/9] KVM: x86: Clean up MSR_IA32_APICBASE_BASE code Sean Christopherson
                   ` (7 preceding siblings ...)
  2024-11-01 18:35 ` [PATCH v2 8/9] KVM: x86: Unpack msr_data structure prior to calling kvm_apic_set_base() Sean Christopherson
@ 2024-11-01 18:35 ` Sean Christopherson
  2024-11-04 10:59   ` Huang, Kai
  2024-11-05  5:56 ` [PATCH v2 0/9] KVM: x86: Clean up MSR_IA32_APICBASE_BASE code Sean Christopherson
  9 siblings, 1 reply; 14+ messages in thread
From: Sean Christopherson @ 2024-11-01 18:35 UTC (permalink / raw)
  To: Sean Christopherson, Paolo Bonzini; +Cc: kvm, linux-kernel, Kai Huang

Do nothing in from kvm_apic_set_base() if the incoming MSR value is the
same as the current value, as validating the mode transitions is obviously
unnecessary, and rejecting the write is pointless if the vCPU already has
an invalid value, e.g. if userspace is doing weird things and modified
guest CPUID after setting MSR_IA32_APICBASE.

Bailing early avoids kvm_recalculate_apic_map()'s slow path in the rare
scenario where the map is DIRTY due to some other vCPU dirtying the map,
in which case it's the other vCPU/task's responsibility to recalculate the
map.

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

diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 7b2342e40e4e..59a64b703aad 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -2582,9 +2582,6 @@ static void __kvm_apic_set_base(struct kvm_vcpu *vcpu, u64 value)
 	u64 old_value = vcpu->arch.apic_base;
 	struct kvm_lapic *apic = vcpu->arch.apic;
 
-	if (old_value == value)
-		return;
-
 	vcpu->arch.apic_base = value;
 
 	if ((old_value ^ value) & MSR_IA32_APICBASE_ENABLE)
@@ -2632,6 +2629,10 @@ int kvm_apic_set_base(struct kvm_vcpu *vcpu, u64 value, bool host_initiated)
 {
 	enum lapic_mode old_mode = kvm_get_apic_mode(vcpu);
 	enum lapic_mode new_mode = kvm_apic_mode(value);
+
+	if (vcpu->arch.apic_base == value)
+		return 0;
+
 	u64 reserved_bits = kvm_vcpu_reserved_gpa_bits_raw(vcpu) | 0x2ff |
 		(guest_cpuid_has(vcpu, X86_FEATURE_X2APIC) ? 0 : X2APIC_ENABLE);
 
-- 
2.47.0.163.g1226f6d8fa-goog


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

* Re: [PATCH v2 8/9] KVM: x86: Unpack msr_data structure prior to calling kvm_apic_set_base()
  2024-11-01 18:35 ` [PATCH v2 8/9] KVM: x86: Unpack msr_data structure prior to calling kvm_apic_set_base() Sean Christopherson
@ 2024-11-04 10:28   ` Huang, Kai
  0 siblings, 0 replies; 14+ messages in thread
From: Huang, Kai @ 2024-11-04 10:28 UTC (permalink / raw)
  To: pbonzini@redhat.com, seanjc@google.com
  Cc: kvm@vger.kernel.org, linux-kernel@vger.kernel.org

On Fri, 2024-11-01 at 11:35 -0700, Sean Christopherson wrote:
> Pass in the new value and "host initiated" as separate parameters to
> kvm_apic_set_base(), as forcing the KVM_SET_SREGS path to declare and fill
> an msr_data structure is awkward and kludgy, e.g. __set_sregs_common()
> doesn't even bother to set the proper MSR index.
> 
> No functional change intended.
> 
> Suggested-by: Kai Huang <kai.huang@intel.com>
> Signed-off-by: Sean Christopherson <seanjc@google.com>
> 


Reviewed-by: Kai Huang <kai.huang@intel.com>

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

* Re: [PATCH v2 9/9] KVM: x86: Short-circuit all of kvm_apic_set_base() if MSR value is unchanged
  2024-11-01 18:35 ` [PATCH v2 9/9] KVM: x86: Short-circuit all of kvm_apic_set_base() if MSR value is unchanged Sean Christopherson
@ 2024-11-04 10:59   ` Huang, Kai
  2024-11-04 23:03     ` Sean Christopherson
  0 siblings, 1 reply; 14+ messages in thread
From: Huang, Kai @ 2024-11-04 10:59 UTC (permalink / raw)
  To: pbonzini@redhat.com, seanjc@google.com
  Cc: kvm@vger.kernel.org, linux-kernel@vger.kernel.org

On Fri, 2024-11-01 at 11:35 -0700, Sean Christopherson wrote:
> Do nothing in from kvm_apic_set_base() if the incoming MSR value is the
> same as the current value, as validating the mode transitions is obviously
> unnecessary, and rejecting the write is pointless if the vCPU already has
> an invalid value, e.g. if userspace is doing weird things and modified
> guest CPUID after setting MSR_IA32_APICBASE.
> 
> Bailing early avoids kvm_recalculate_apic_map()'s slow path in the rare
> scenario where the map is DIRTY due to some other vCPU dirtying the map,
> in which case it's the other vCPU/task's responsibility to recalculate the
> map.
> 
> Signed-off-by: Sean Christopherson <seanjc@google.com>
> ---
>  arch/x86/kvm/lapic.c | 7 ++++---
>  1 file changed, 4 insertions(+), 3 deletions(-)
> 
> diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
> index 7b2342e40e4e..59a64b703aad 100644
> --- a/arch/x86/kvm/lapic.c
> +++ b/arch/x86/kvm/lapic.c
> @@ -2582,9 +2582,6 @@ static void __kvm_apic_set_base(struct kvm_vcpu *vcpu, u64 value)
>  	u64 old_value = vcpu->arch.apic_base;
>  	struct kvm_lapic *apic = vcpu->arch.apic;
>  
> -	if (old_value == value)
> -		return;
> -

Could you clarify why this is removed?  AFAICT kvm_lapic_reset() still calls
directly.

>  	vcpu->arch.apic_base = value;
>  
>  	if ((old_value ^ value) & MSR_IA32_APICBASE_ENABLE)
> @@ -2632,6 +2629,10 @@ int kvm_apic_set_base(struct kvm_vcpu *vcpu, u64 value, bool host_initiated)
>  {
>  	enum lapic_mode old_mode = kvm_get_apic_mode(vcpu);
>  	enum lapic_mode new_mode = kvm_apic_mode(value);
> +
> +	if (vcpu->arch.apic_base == value)
> +		return 0;
> +
>  	u64 reserved_bits = kvm_vcpu_reserved_gpa_bits_raw(vcpu) | 0x2ff |
>  		(guest_cpuid_has(vcpu, X86_FEATURE_X2APIC) ? 0 : X2APIC_ENABLE);
>  
> -- 
> 2.47.0.163.g1226f6d8fa-goog
> 


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

* Re: [PATCH v2 9/9] KVM: x86: Short-circuit all of kvm_apic_set_base() if MSR value is unchanged
  2024-11-04 10:59   ` Huang, Kai
@ 2024-11-04 23:03     ` Sean Christopherson
  0 siblings, 0 replies; 14+ messages in thread
From: Sean Christopherson @ 2024-11-04 23:03 UTC (permalink / raw)
  To: Kai Huang
  Cc: pbonzini@redhat.com, kvm@vger.kernel.org,
	linux-kernel@vger.kernel.org

On Mon, Nov 04, 2024, Kai Huang wrote:
> On Fri, 2024-11-01 at 11:35 -0700, Sean Christopherson wrote:
> > Do nothing in from kvm_apic_set_base() if the incoming MSR value is the
> > same as the current value, as validating the mode transitions is obviously
> > unnecessary, and rejecting the write is pointless if the vCPU already has
> > an invalid value, e.g. if userspace is doing weird things and modified
> > guest CPUID after setting MSR_IA32_APICBASE.
> > 
> > Bailing early avoids kvm_recalculate_apic_map()'s slow path in the rare
> > scenario where the map is DIRTY due to some other vCPU dirtying the map,
> > in which case it's the other vCPU/task's responsibility to recalculate the
> > map.
> > 
> > Signed-off-by: Sean Christopherson <seanjc@google.com>
> > ---
> >  arch/x86/kvm/lapic.c | 7 ++++---
> >  1 file changed, 4 insertions(+), 3 deletions(-)
> > 
> > diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
> > index 7b2342e40e4e..59a64b703aad 100644
> > --- a/arch/x86/kvm/lapic.c
> > +++ b/arch/x86/kvm/lapic.c
> > @@ -2582,9 +2582,6 @@ static void __kvm_apic_set_base(struct kvm_vcpu *vcpu, u64 value)
> >  	u64 old_value = vcpu->arch.apic_base;
> >  	struct kvm_lapic *apic = vcpu->arch.apic;
> >  
> > -	if (old_value == value)
> > -		return;
> > -
> 
> Could you clarify why this is removed?  AFAICT kvm_lapic_reset() still calls
> directly.

It does, but in that case, @old_value is guaranteed to be zero, and @value is
guaranteed to be non-zero, i.e. the check is unnecesary.  At that point, the
check in __kvm_apic_set_base() is 100% dead code, and I think it would do more
harm than good, e.g. might confuse readers.

I thought about adding a WARN, but that seems excessive.

That said, the changelog definitely needs to explain why the check is moved from
__kvm_apic_set_base(), as opposed to another check being added.  How about this?

--
Do nothing in all of kvm_apic_set_base(), not just __kvm_apic_set_base(),
if the incoming MSR value is the same as the current value.  Validating
the mode transitions is obviously unnecessary, and rejecting the write is
pointless if the vCPU already has an invalid value, e.g. if userspace is
doing weird things and modified guest CPUID after setting MSR_IA32_APICBASE.

Bailing early avoids kvm_recalculate_apic_map()'s slow path in the rare
scenario where the map is DIRTY due to some other vCPU dirtying the map,
in which case it's the other vCPU/task's responsibility to recalculate the
map.

Note, kvm_lapic_reset() calls __kvm_apic_set_base() only when emulating
RESET, in which case the old value is guaranteed to be zero, and the new
value is guaranteed to be non-zero.  I.e. all callers of
__kvm_apic_set_base() effectively pre-check for the MSR value actually
changing.  Don't bother keeping the check in __kvm_apic_set_base(), as no
additional callers are expected, and implying that the MSR might already
be non-zero at the time of kvm_lapic_reset() could confuse readers.
--

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

* Re: [PATCH v2 0/9] KVM: x86: Clean up MSR_IA32_APICBASE_BASE code
  2024-11-01 18:35 [PATCH v2 0/9] KVM: x86: Clean up MSR_IA32_APICBASE_BASE code Sean Christopherson
                   ` (8 preceding siblings ...)
  2024-11-01 18:35 ` [PATCH v2 9/9] KVM: x86: Short-circuit all of kvm_apic_set_base() if MSR value is unchanged Sean Christopherson
@ 2024-11-05  5:56 ` Sean Christopherson
  9 siblings, 0 replies; 14+ messages in thread
From: Sean Christopherson @ 2024-11-05  5:56 UTC (permalink / raw)
  To: Sean Christopherson, Paolo Bonzini; +Cc: kvm, linux-kernel, Kai Huang

On Fri, 01 Nov 2024 11:35:46 -0700, Sean Christopherson wrote:
> Clean up code related to setting and getting MSR_IA32_APICBASE_BASE.
> 
> E.g. it's absurdly difficult to tease out that kvm_set_apic_base() exists
> purely to avoid an extra call to kvm_recalculate_apic_map() (which may or
> may not be worth the code, but whatever).
> 
> Simiarly, it's quite difficult to see that kvm_lapic_set_base() doesn't
> do anything useful if the incoming MSR value is the same as the current
> value.
> 
> [...]

Applied to kvm-x86 misc.

Kai, please holler if you have any concerns with patch 9.  I'm more than happy
to tweak it as needed (or even drop it if necessary).  I applied it quickly
purely to get more soak time in -next.  Thanks for all the reviews!

[1/9] KVM: x86: Short-circuit all kvm_lapic_set_base() if MSR value isn't changing
      https://github.com/kvm-x86/linux/commit/d7d770bed98f
[2/9] KVM: x86: Drop superfluous kvm_lapic_set_base() call when setting APIC state
      https://github.com/kvm-x86/linux/commit/8166d2557912
[3/9] KVM: x86: Get vcpu->arch.apic_base directly and drop kvm_get_apic_base()
      https://github.com/kvm-x86/linux/commit/d91060e342a6
[4/9] KVM: x86: Inline kvm_get_apic_mode() in lapic.h
      https://github.com/kvm-x86/linux/commit/adfec1f4591c
[5/9] KVM: x86: Move kvm_set_apic_base() implementation to lapic.c (from x86.c)
      https://github.com/kvm-x86/linux/commit/c9c9acfcd573
[6/9] KVM: x86: Rename APIC base setters to better capture their relationship
      https://github.com/kvm-x86/linux/commit/7d1cb7cee94f
[7/9] KVM: x86: Make kvm_recalculate_apic_map() local to lapic.c
      https://github.com/kvm-x86/linux/commit/ff6ce56e1d88
[8/9] KVM: x86: Unpack msr_data structure prior to calling kvm_apic_set_base()
      https://github.com/kvm-x86/linux/commit/c9155eb012b9
[9/9] KVM: x86: Short-circuit all of kvm_apic_set_base() if MSR value is unchanged
      https://github.com/kvm-x86/linux/commit/a75b7bb46a83

--
https://github.com/kvm-x86/linux/tree/next

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

end of thread, other threads:[~2024-11-05  6:00 UTC | newest]

Thread overview: 14+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2024-11-01 18:35 [PATCH v2 0/9] KVM: x86: Clean up MSR_IA32_APICBASE_BASE code Sean Christopherson
2024-11-01 18:35 ` [PATCH v2 1/9] KVM: x86: Short-circuit all kvm_lapic_set_base() if MSR value isn't changing Sean Christopherson
2024-11-01 18:35 ` [PATCH v2 2/9] KVM: x86: Drop superfluous kvm_lapic_set_base() call when setting APIC state Sean Christopherson
2024-11-01 18:35 ` [PATCH v2 3/9] KVM: x86: Get vcpu->arch.apic_base directly and drop kvm_get_apic_base() Sean Christopherson
2024-11-01 18:35 ` [PATCH v2 4/9] KVM: x86: Inline kvm_get_apic_mode() in lapic.h Sean Christopherson
2024-11-01 18:35 ` [PATCH v2 5/9] KVM: x86: Move kvm_set_apic_base() implementation to lapic.c (from x86.c) Sean Christopherson
2024-11-01 18:35 ` [PATCH v2 6/9] KVM: x86: Rename APIC base setters to better capture their relationship Sean Christopherson
2024-11-01 18:35 ` [PATCH v2 7/9] KVM: x86: Make kvm_recalculate_apic_map() local to lapic.c Sean Christopherson
2024-11-01 18:35 ` [PATCH v2 8/9] KVM: x86: Unpack msr_data structure prior to calling kvm_apic_set_base() Sean Christopherson
2024-11-04 10:28   ` Huang, Kai
2024-11-01 18:35 ` [PATCH v2 9/9] KVM: x86: Short-circuit all of kvm_apic_set_base() if MSR value is unchanged Sean Christopherson
2024-11-04 10:59   ` Huang, Kai
2024-11-04 23:03     ` Sean Christopherson
2024-11-05  5:56 ` [PATCH v2 0/9] KVM: x86: Clean up MSR_IA32_APICBASE_BASE code Sean Christopherson

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox