Commit 0de4a0ee authored by Paolo Bonzini's avatar Paolo Bonzini
Browse files

Merge tag 'kvm-x86-fixes-6.19-rc8' of https://github.com/kvm-x86/linux into HEAD

Final KVM fixes for 6.19:

 - Fix a bug where AVIC is incorrectly inhibited when running with x2AVIC
   disabled via module param (or on a system without x2AVIC).

 - Fix a dangling device posted IRQs bug by explicitly checking if the irqfd is
   still active (on the list) when handling an eventfd signal, instead of
   zeroing the irqfd's routing information when the irqfd is deassigned.
   Zeroing the irqfd's routing info causes arm64 and x86's to not disable
   posting for the IRQ (kvm_arch_irq_bypass_del_producer() looks for an MSI),
   incorrectly leaving the IRQ in posted mode (and leading to use-after-free
   and memory leaks on AMD in particular).

   This is both the most pressing and scariest, but it's been in -next for
   a while.

 - Disable FORTIFY_SOURCE for KVM selftests to prevent the compiler from
   generating calls to the checked versions of memset() and friends, which
   leads to unexpected page faults in guest code due e.g. __memset_chk@plt
   not being resolved.

 - Explicitly configure the support XSS from within {svm,vmx}_set_cpu_caps() to
   fix a bug where VMX will compute the reference VMCS configuration with SHSTK
   and IBT enabled, but then compute each CPUs local config with SHSTK and IBT
   disabled if not all CET xfeatures are enabled, e.g. if the kernel is built
   with X86_KERNEL_IBT=n.  The mismatch in features results in differing nVMX
   setting, and ultimately causes kvm-intel.ko to refuse to load with nested=1.
parents e89f0e9a f8ade833
Loading
Loading
Loading
Loading
+2 −1
Original line number Diff line number Diff line
@@ -514,7 +514,8 @@ void kvm_arch_irq_bypass_del_producer(struct irq_bypass_consumer *cons,
	 */
	spin_lock_irq(&kvm->irqfds.lock);

	if (irqfd->irq_entry.type == KVM_IRQ_ROUTING_MSI) {
	if (irqfd->irq_entry.type == KVM_IRQ_ROUTING_MSI ||
	    WARN_ON_ONCE(irqfd->irq_bypass_vcpu)) {
		ret = kvm_pi_update_irte(irqfd, NULL);
		if (ret)
			pr_info("irq bypass consumer (eventfd %p) unregistration fails: %d\n",
+2 −2
Original line number Diff line number Diff line
@@ -376,6 +376,7 @@ void avic_init_vmcb(struct vcpu_svm *svm, struct vmcb *vmcb)

static int avic_init_backing_page(struct kvm_vcpu *vcpu)
{
	u32 max_id = x2avic_enabled ? x2avic_max_physical_id : AVIC_MAX_PHYSICAL_ID;
	struct kvm_svm *kvm_svm = to_kvm_svm(vcpu->kvm);
	struct vcpu_svm *svm = to_svm(vcpu);
	u32 id = vcpu->vcpu_id;
@@ -388,8 +389,7 @@ static int avic_init_backing_page(struct kvm_vcpu *vcpu)
	 * avic_vcpu_load() expects to be called if and only if the vCPU has
	 * fully initialized AVIC.
	 */
	if ((!x2avic_enabled && id > AVIC_MAX_PHYSICAL_ID) ||
	    (id > x2avic_max_physical_id)) {
	if (id > max_id) {
		kvm_set_apicv_inhibit(vcpu->kvm, APICV_INHIBIT_REASON_PHYSICAL_ID_TOO_BIG);
		vcpu->arch.apic->apicv_active = false;
		return 0;
+2 −0
Original line number Diff line number Diff line
@@ -5284,6 +5284,8 @@ static __init void svm_set_cpu_caps(void)
	 */
	kvm_cpu_cap_clear(X86_FEATURE_BUS_LOCK_DETECT);
	kvm_cpu_cap_clear(X86_FEATURE_MSR_IMM);

	kvm_setup_xss_caps();
}

static __init int svm_hardware_setup(void)
+2 −0
Original line number Diff line number Diff line
@@ -8051,6 +8051,8 @@ static __init void vmx_set_cpu_caps(void)
		kvm_cpu_cap_clear(X86_FEATURE_SHSTK);
		kvm_cpu_cap_clear(X86_FEATURE_IBT);
	}

	kvm_setup_xss_caps();
}

static bool vmx_is_io_intercepted(struct kvm_vcpu *vcpu,
+17 −13
Original line number Diff line number Diff line
@@ -9953,6 +9953,23 @@ static struct notifier_block pvclock_gtod_notifier = {
};
#endif

void kvm_setup_xss_caps(void)
{
	if (!kvm_cpu_cap_has(X86_FEATURE_XSAVES))
		kvm_caps.supported_xss = 0;

	if (!kvm_cpu_cap_has(X86_FEATURE_SHSTK) &&
	    !kvm_cpu_cap_has(X86_FEATURE_IBT))
		kvm_caps.supported_xss &= ~XFEATURE_MASK_CET_ALL;

	if ((kvm_caps.supported_xss & XFEATURE_MASK_CET_ALL) != XFEATURE_MASK_CET_ALL) {
		kvm_cpu_cap_clear(X86_FEATURE_SHSTK);
		kvm_cpu_cap_clear(X86_FEATURE_IBT);
		kvm_caps.supported_xss &= ~XFEATURE_MASK_CET_ALL;
	}
}
EXPORT_SYMBOL_FOR_KVM_INTERNAL(kvm_setup_xss_caps);

static inline void kvm_ops_update(struct kvm_x86_init_ops *ops)
{
	memcpy(&kvm_x86_ops, ops->runtime_ops, sizeof(kvm_x86_ops));
@@ -10125,19 +10142,6 @@ int kvm_x86_vendor_init(struct kvm_x86_init_ops *ops)
	if (!tdp_enabled)
		kvm_caps.supported_quirks &= ~KVM_X86_QUIRK_IGNORE_GUEST_PAT;

	if (!kvm_cpu_cap_has(X86_FEATURE_XSAVES))
		kvm_caps.supported_xss = 0;

	if (!kvm_cpu_cap_has(X86_FEATURE_SHSTK) &&
	    !kvm_cpu_cap_has(X86_FEATURE_IBT))
		kvm_caps.supported_xss &= ~XFEATURE_MASK_CET_ALL;

	if ((kvm_caps.supported_xss & XFEATURE_MASK_CET_ALL) != XFEATURE_MASK_CET_ALL) {
		kvm_cpu_cap_clear(X86_FEATURE_SHSTK);
		kvm_cpu_cap_clear(X86_FEATURE_IBT);
		kvm_caps.supported_xss &= ~XFEATURE_MASK_CET_ALL;
	}

	if (kvm_caps.has_tsc_control) {
		/*
		 * Make sure the user can only configure tsc_khz values that
Loading