Commit 208a352a authored by Paolo Bonzini's avatar Paolo Bonzini
Browse files

Merge tag 'kvm-x86-vmx-6.11' of https://github.com/kvm-x86/linux into HEAD

KVM VMX changes for 6.11

 - Remove an unnecessary EPT TLB flush when enabling hardware.

 - Fix a series of bugs that cause KVM to fail to detect nested pending posted
   interrupts as valid wake eents for a vCPU executing HLT in L2 (with
   HLT-exiting disable by L1).

 - Misc cleanups
parents 1229cbef 45405155
Loading
Loading
Loading
Loading
+0 −1
Original line number Diff line number Diff line
@@ -85,7 +85,6 @@ KVM_X86_OP_OPTIONAL(update_cr8_intercept)
KVM_X86_OP(refresh_apicv_exec_ctrl)
KVM_X86_OP_OPTIONAL(hwapic_irr_update)
KVM_X86_OP_OPTIONAL(hwapic_isr_update)
KVM_X86_OP_OPTIONAL_RET0(guest_apic_has_interrupt)
KVM_X86_OP_OPTIONAL(load_eoi_exitmap)
KVM_X86_OP_OPTIONAL(set_virtual_apic_mode)
KVM_X86_OP_OPTIONAL(set_apic_access_page_addr)
+1 −2
Original line number Diff line number Diff line
@@ -1731,7 +1731,6 @@ struct kvm_x86_ops {
	void (*refresh_apicv_exec_ctrl)(struct kvm_vcpu *vcpu);
	void (*hwapic_irr_update)(struct kvm_vcpu *vcpu, int max_irr);
	void (*hwapic_isr_update)(int isr);
	bool (*guest_apic_has_interrupt)(struct kvm_vcpu *vcpu);
	void (*load_eoi_exitmap)(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap);
	void (*set_virtual_apic_mode)(struct kvm_vcpu *vcpu);
	void (*set_apic_access_page_addr)(struct kvm_vcpu *vcpu);
@@ -1837,7 +1836,7 @@ struct kvm_x86_nested_ops {
	bool (*is_exception_vmexit)(struct kvm_vcpu *vcpu, u8 vector,
				    u32 error_code);
	int (*check_events)(struct kvm_vcpu *vcpu);
	bool (*has_events)(struct kvm_vcpu *vcpu);
	bool (*has_events)(struct kvm_vcpu *vcpu, bool for_injection);
	void (*triple_fault)(struct kvm_vcpu *vcpu);
	int (*get_state)(struct kvm_vcpu *vcpu,
			 struct kvm_nested_state __user *user_kvm_nested_state,
+0 −1
Original line number Diff line number Diff line
@@ -97,7 +97,6 @@ struct kvm_x86_ops vt_x86_ops __initdata = {
	.required_apicv_inhibits = VMX_REQUIRED_APICV_INHIBITS,
	.hwapic_irr_update = vmx_hwapic_irr_update,
	.hwapic_isr_update = vmx_hwapic_isr_update,
	.guest_apic_has_interrupt = vmx_guest_apic_has_interrupt,
	.sync_pir_to_irr = vmx_sync_pir_to_irr,
	.deliver_interrupt = vmx_deliver_interrupt,
	.dy_apicv_has_pending_interrupt = pi_has_pending_interrupt,
+42 −5
Original line number Diff line number Diff line
@@ -12,6 +12,7 @@
#include "mmu.h"
#include "nested.h"
#include "pmu.h"
#include "posted_intr.h"
#include "sgx.h"
#include "trace.h"
#include "vmx.h"
@@ -3899,8 +3900,8 @@ static int vmx_complete_nested_posted_interrupt(struct kvm_vcpu *vcpu)
	if (!pi_test_and_clear_on(vmx->nested.pi_desc))
		return 0;

	max_irr = find_last_bit((unsigned long *)vmx->nested.pi_desc->pir, 256);
	if (max_irr != 256) {
	max_irr = pi_find_highest_vector(vmx->nested.pi_desc);
	if (max_irr > 0) {
		vapic_page = vmx->nested.virtual_apic_map.hva;
		if (!vapic_page)
			goto mmio_needed;
@@ -4031,10 +4032,46 @@ static bool nested_vmx_preemption_timer_pending(struct kvm_vcpu *vcpu)
	       to_vmx(vcpu)->nested.preemption_timer_expired;
}

static bool vmx_has_nested_events(struct kvm_vcpu *vcpu)
static bool vmx_has_nested_events(struct kvm_vcpu *vcpu, bool for_injection)
{
	return nested_vmx_preemption_timer_pending(vcpu) ||
	       to_vmx(vcpu)->nested.mtf_pending;
	struct vcpu_vmx *vmx = to_vmx(vcpu);
	void *vapic = vmx->nested.virtual_apic_map.hva;
	int max_irr, vppr;

	if (nested_vmx_preemption_timer_pending(vcpu) ||
	    vmx->nested.mtf_pending)
		return true;

	/*
	 * Virtual Interrupt Delivery doesn't require manual injection.  Either
	 * the interrupt is already in GUEST_RVI and will be recognized by CPU
	 * at VM-Entry, or there is a KVM_REQ_EVENT pending and KVM will move
	 * the interrupt from the PIR to RVI prior to entering the guest.
	 */
	if (for_injection)
		return false;

	if (!nested_cpu_has_vid(get_vmcs12(vcpu)) ||
	    __vmx_interrupt_blocked(vcpu))
		return false;

	if (!vapic)
		return false;

	vppr = *((u32 *)(vapic + APIC_PROCPRI));

	max_irr = vmx_get_rvi();
	if ((max_irr & 0xf0) > (vppr & 0xf0))
		return true;

	if (vmx->nested.pi_pending && vmx->nested.pi_desc &&
	    pi_test_on(vmx->nested.pi_desc)) {
		max_irr = pi_find_highest_vector(vmx->nested.pi_desc);
		if (max_irr > 0 && (max_irr & 0xf0) > (vppr & 0xf0))
			return true;
	}

	return false;
}

/*
+10 −0
Original line number Diff line number Diff line
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __KVM_X86_VMX_POSTED_INTR_H
#define __KVM_X86_VMX_POSTED_INTR_H

#include <linux/find.h>
#include <asm/posted_intr.h>

void vmx_vcpu_pi_load(struct kvm_vcpu *vcpu, int cpu);
@@ -12,4 +14,12 @@ int vmx_pi_update_irte(struct kvm *kvm, unsigned int host_irq,
		       uint32_t guest_irq, bool set);
void vmx_pi_start_assignment(struct kvm *kvm);

static inline int pi_find_highest_vector(struct pi_desc *pi_desc)
{
	int vec;

	vec = find_last_bit((unsigned long *)pi_desc->pir, 256);
	return vec < 256 ? vec : -1;
}

#endif /* __KVM_X86_VMX_POSTED_INTR_H */
Loading