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

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

KVM x86 fixes for 6.18:

 - Inject #UD if the guest attempts to execute SEAMCALL or TDCALL as KVM
   doesn't support virtualization the instructions, but the instructions
   are gated only by VMXON, i.e. will VM-Exit instead of taking a #UD and
   thus result in KVM exiting to userspace with an emulation error.

 - Unload the "FPU" when emulating INIT of XSTATE features if and only if
   the FPU is actually loaded, instead of trying to predict when KVM will
   emulate an INIT (CET support missed the MP_STATE path).  Add sanity
   checks to detect and harden against similar bugs in the future.

 - Unregister KVM's GALog notifier (for AVIC) when kvm-amd.ko is unloaded.

 - Use a raw spinlock for svm->ir_list_lock as the lock is taken during
   schedule(), and "normal" spinlocks are sleepable locks when PREEMPT_RT=y.

 - Remove guest_memfd bindings on memslot deletion when a gmem file is dying
   to fix a use-after-free race found by syzkaller.

 - Fix a goof in the EPT Violation handler where KVM checks the wrong
   variable when determining if the reported GVA is valid.
parents 36567f1d d0164c16
Loading
Loading
Loading
Loading
+1 −0
Original line number Diff line number Diff line
@@ -93,6 +93,7 @@
#define EXIT_REASON_TPAUSE              68
#define EXIT_REASON_BUS_LOCK            74
#define EXIT_REASON_NOTIFY              75
#define EXIT_REASON_SEAMCALL            76
#define EXIT_REASON_TDCALL              77
#define EXIT_REASON_MSR_READ_IMM        84
#define EXIT_REASON_MSR_WRITE_IMM       85
+15 −9
Original line number Diff line number Diff line
@@ -216,7 +216,7 @@ static void avic_deactivate_vmcb(struct vcpu_svm *svm)
 * This function is called from IOMMU driver to notify
 * SVM to schedule in a particular vCPU of a particular VM.
 */
int avic_ga_log_notifier(u32 ga_tag)
static int avic_ga_log_notifier(u32 ga_tag)
{
	unsigned long flags;
	struct kvm_svm *kvm_svm;
@@ -788,7 +788,7 @@ int avic_init_vcpu(struct vcpu_svm *svm)
	struct kvm_vcpu *vcpu = &svm->vcpu;

	INIT_LIST_HEAD(&svm->ir_list);
	spin_lock_init(&svm->ir_list_lock);
	raw_spin_lock_init(&svm->ir_list_lock);

	if (!enable_apicv || !irqchip_in_kernel(vcpu->kvm))
		return 0;
@@ -816,9 +816,9 @@ static void svm_ir_list_del(struct kvm_kernel_irqfd *irqfd)
	if (!vcpu)
		return;

	spin_lock_irqsave(&to_svm(vcpu)->ir_list_lock, flags);
	raw_spin_lock_irqsave(&to_svm(vcpu)->ir_list_lock, flags);
	list_del(&irqfd->vcpu_list);
	spin_unlock_irqrestore(&to_svm(vcpu)->ir_list_lock, flags);
	raw_spin_unlock_irqrestore(&to_svm(vcpu)->ir_list_lock, flags);
}

int avic_pi_update_irte(struct kvm_kernel_irqfd *irqfd, struct kvm *kvm,
@@ -855,7 +855,7 @@ int avic_pi_update_irte(struct kvm_kernel_irqfd *irqfd, struct kvm *kvm,
		 * list of IRQs being posted to the vCPU, to ensure the IRTE
		 * isn't programmed with stale pCPU/IsRunning information.
		 */
		guard(spinlock_irqsave)(&svm->ir_list_lock);
		guard(raw_spinlock_irqsave)(&svm->ir_list_lock);

		/*
		 * Update the target pCPU for IOMMU doorbells if the vCPU is
@@ -972,7 +972,7 @@ static void __avic_vcpu_load(struct kvm_vcpu *vcpu, int cpu,
	 * up-to-date entry information, or that this task will wait until
	 * svm_ir_list_add() completes to set the new target pCPU.
	 */
	spin_lock_irqsave(&svm->ir_list_lock, flags);
	raw_spin_lock_irqsave(&svm->ir_list_lock, flags);

	entry = svm->avic_physical_id_entry;
	WARN_ON_ONCE(entry & AVIC_PHYSICAL_ID_ENTRY_IS_RUNNING_MASK);
@@ -997,7 +997,7 @@ static void __avic_vcpu_load(struct kvm_vcpu *vcpu, int cpu,

	avic_update_iommu_vcpu_affinity(vcpu, h_physical_id, action);

	spin_unlock_irqrestore(&svm->ir_list_lock, flags);
	raw_spin_unlock_irqrestore(&svm->ir_list_lock, flags);
}

void avic_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
@@ -1035,7 +1035,7 @@ static void __avic_vcpu_put(struct kvm_vcpu *vcpu, enum avic_vcpu_action action)
	 * or that this task will wait until svm_ir_list_add() completes to
	 * mark the vCPU as not running.
	 */
	spin_lock_irqsave(&svm->ir_list_lock, flags);
	raw_spin_lock_irqsave(&svm->ir_list_lock, flags);

	avic_update_iommu_vcpu_affinity(vcpu, -1, action);

@@ -1059,7 +1059,7 @@ static void __avic_vcpu_put(struct kvm_vcpu *vcpu, enum avic_vcpu_action action)

	svm->avic_physical_id_entry = entry;

	spin_unlock_irqrestore(&svm->ir_list_lock, flags);
	raw_spin_unlock_irqrestore(&svm->ir_list_lock, flags);
}

void avic_vcpu_put(struct kvm_vcpu *vcpu)
@@ -1243,3 +1243,9 @@ bool __init avic_hardware_setup(void)

	return true;
}

void avic_hardware_unsetup(void)
{
	if (avic)
		amd_iommu_register_ga_log_notifier(NULL);
}
+9 −6
Original line number Diff line number Diff line
@@ -921,6 +921,8 @@ static void svm_hardware_unsetup(void)
{
	int cpu;

	avic_hardware_unsetup();

	sev_hardware_unsetup();

	for_each_possible_cpu(cpu)
@@ -5386,12 +5388,6 @@ static __init int svm_hardware_setup(void)

	svm_hv_hardware_setup();

	for_each_possible_cpu(cpu) {
		r = svm_cpu_init(cpu);
		if (r)
			goto err;
	}

	enable_apicv = avic_hardware_setup();
	if (!enable_apicv) {
		enable_ipiv = false;
@@ -5435,6 +5431,13 @@ static __init int svm_hardware_setup(void)
	svm_set_cpu_caps();

	kvm_caps.inapplicable_quirks &= ~KVM_X86_QUIRK_CD_NW_CLEARED;

	for_each_possible_cpu(cpu) {
		r = svm_cpu_init(cpu);
		if (r)
			goto err;
	}

	return 0;

err:
+2 −2
Original line number Diff line number Diff line
@@ -329,7 +329,7 @@ struct vcpu_svm {
	 * back into remapped mode).
	 */
	struct list_head ir_list;
	spinlock_t ir_list_lock;
	raw_spinlock_t ir_list_lock;

	struct vcpu_sev_es_state sev_es;

@@ -805,7 +805,7 @@ extern struct kvm_x86_nested_ops svm_nested_ops;
)

bool __init avic_hardware_setup(void);
int avic_ga_log_notifier(u32 ga_tag);
void avic_hardware_unsetup(void);
void avic_vm_destroy(struct kvm *kvm);
int avic_vm_init(struct kvm *kvm);
void avic_init_vmcb(struct vcpu_svm *svm, struct vmcb *vmcb);
+1 −1
Original line number Diff line number Diff line
@@ -98,7 +98,7 @@ static inline int __vmx_handle_ept_violation(struct kvm_vcpu *vcpu, gpa_t gpa,
	error_code |= (exit_qualification & EPT_VIOLATION_PROT_MASK)
		      ? PFERR_PRESENT_MASK : 0;

	if (error_code & EPT_VIOLATION_GVA_IS_VALID)
	if (exit_qualification & EPT_VIOLATION_GVA_IS_VALID)
		error_code |= (exit_qualification & EPT_VIOLATION_GVA_TRANSLATED) ?
			      PFERR_GUEST_FINAL_MASK : PFERR_GUEST_PAGE_MASK;

Loading