xref: /linux/arch/x86/kvm/vmx/common.h (revision bba2c3615bd6cfee7456d1130f2e6b01b3f4e9ba)
1 /* SPDX-License-Identifier: GPL-2.0-only */
2 #ifndef __KVM_X86_VMX_COMMON_H
3 #define __KVM_X86_VMX_COMMON_H
4 
5 #include <linux/kvm_host.h>
6 #include <asm/posted_intr.h>
7 
8 #include "mmu.h"
9 
10 union vmx_exit_reason {
11 	struct {
12 		u32	basic			: 16;
13 		u32	reserved16		: 1;
14 		u32	reserved17		: 1;
15 		u32	reserved18		: 1;
16 		u32	reserved19		: 1;
17 		u32	reserved20		: 1;
18 		u32	reserved21		: 1;
19 		u32	reserved22		: 1;
20 		u32	reserved23		: 1;
21 		u32	reserved24		: 1;
22 		u32	reserved25		: 1;
23 		u32	bus_lock_detected	: 1;
24 		u32	enclave_mode		: 1;
25 		u32	smi_pending_mtf		: 1;
26 		u32	smi_from_vmx_root	: 1;
27 		u32	reserved30		: 1;
28 		u32	failed_vmentry		: 1;
29 	};
30 	u32 full;
31 };
32 
33 struct vcpu_vt {
34 	/* Posted interrupt descriptor */
35 	struct pi_desc pi_desc;
36 
37 	/* Used if this vCPU is waiting for PI notification wakeup. */
38 	struct list_head pi_wakeup_list;
39 
40 	union vmx_exit_reason exit_reason;
41 
42 	unsigned long	exit_qualification;
43 	u32		exit_intr_info;
44 
45 	/*
46 	 * If true, guest state has been loaded into hardware, and host state
47 	 * saved into vcpu_{vt,vmx,tdx}.  If false, host state is loaded into
48 	 * hardware.
49 	 */
50 	bool		guest_state_loaded;
51 	bool		emulation_required;
52 
53 #ifdef CONFIG_X86_64
54 	u64		msr_host_kernel_gs_base;
55 #endif
56 };
57 
58 #ifdef CONFIG_KVM_INTEL_TDX
59 
60 static __always_inline bool is_td(struct kvm *kvm)
61 {
62 	return kvm->arch.vm_type == KVM_X86_TDX_VM;
63 }
64 
65 static __always_inline bool is_td_vcpu(struct kvm_vcpu *vcpu)
66 {
67 	return is_td(vcpu->kvm);
68 }
69 
70 #else
71 
72 static __always_inline bool is_td(struct kvm *kvm) { return false; }
73 static __always_inline bool is_td_vcpu(struct kvm_vcpu *vcpu) { return false; }
74 
75 #endif
76 
77 static inline bool vt_is_tdx_private_gpa(struct kvm *kvm, gpa_t gpa)
78 {
79 	/* For TDX the direct mask is the shared mask. */
80 	return !kvm_is_addr_direct(kvm, gpa);
81 }
82 
83 static inline int __vmx_handle_ept_violation(struct kvm_vcpu *vcpu, gpa_t gpa,
84 					     unsigned long exit_qualification)
85 {
86 	u64 error_code;
87 
88 	/* Is it a write fault? */
89 	error_code = (exit_qualification & EPT_VIOLATION_ACC_WRITE)
90 		      ? PFERR_WRITE_MASK : 0;
91 	/* Is it a fetch fault? */
92 	error_code |= (exit_qualification & EPT_VIOLATION_ACC_INSTR)
93 		      ? PFERR_FETCH_MASK : 0;
94 	/* ept page table entry is present?  */
95 	error_code |= (exit_qualification &
96 		       (EPT_VIOLATION_PROT_MASK & ~EPT_VIOLATION_PROT_USER_EXEC))
97 		      ? PFERR_PRESENT_MASK : 0;
98 
99 	if (mmu_has_mbec(vcpu->arch.mmu))
100 		error_code |= (exit_qualification & EPT_VIOLATION_PROT_USER_EXEC)
101 			      ? PFERR_PRESENT_MASK : 0;
102 
103 	if (exit_qualification & EPT_VIOLATION_GVA_IS_VALID) {
104 		if (exit_qualification & EPT_VIOLATION_GVA_TRANSLATED) {
105 			error_code |= PFERR_GUEST_FINAL_MASK;
106 			if (exit_qualification & EPT_VIOLATION_GVA_USER)
107 				error_code |= PFERR_USER_MASK;
108 		} else {
109 			error_code |= PFERR_GUEST_PAGE_MASK;
110 		}
111 	}
112 
113 	if (vt_is_tdx_private_gpa(vcpu->kvm, gpa))
114 		error_code |= PFERR_PRIVATE_ACCESS;
115 
116 	return kvm_mmu_page_fault(vcpu, gpa, error_code, NULL, 0);
117 }
118 
119 static inline void kvm_vcpu_trigger_posted_interrupt(struct kvm_vcpu *vcpu,
120 						     int pi_vec)
121 {
122 #ifdef CONFIG_SMP
123 	if (vcpu->mode == IN_GUEST_MODE) {
124 		/*
125 		 * The vector of the virtual has already been set in the PIR.
126 		 * Send a notification event to deliver the virtual interrupt
127 		 * unless the vCPU is the currently running vCPU, i.e. the
128 		 * event is being sent from a fastpath VM-Exit handler, in
129 		 * which case the PIR will be synced to the vIRR before
130 		 * re-entering the guest.
131 		 *
132 		 * When the target is not the running vCPU, the following
133 		 * possibilities emerge:
134 		 *
135 		 * Case 1: vCPU stays in non-root mode. Sending a notification
136 		 * event posts the interrupt to the vCPU.
137 		 *
138 		 * Case 2: vCPU exits to root mode and is still runnable. The
139 		 * PIR will be synced to the vIRR before re-entering the guest.
140 		 * Sending a notification event is ok as the host IRQ handler
141 		 * will ignore the spurious event.
142 		 *
143 		 * Case 3: vCPU exits to root mode and is blocked. vcpu_block()
144 		 * has already synced PIR to vIRR and never blocks the vCPU if
145 		 * the vIRR is not empty. Therefore, a blocked vCPU here does
146 		 * not wait for any requested interrupts in PIR, and sending a
147 		 * notification event also results in a benign, spurious event.
148 		 */
149 
150 		if (vcpu != kvm_get_running_vcpu())
151 			__apic_send_IPI_mask(get_cpu_mask(vcpu->cpu), pi_vec);
152 		return;
153 	}
154 #endif
155 	/*
156 	 * The vCPU isn't in the guest; wake the vCPU in case it is blocking,
157 	 * otherwise do nothing as KVM will grab the highest priority pending
158 	 * IRQ via ->sync_pir_to_irr() in vcpu_enter_guest().
159 	 */
160 	kvm_vcpu_wake_up(vcpu);
161 }
162 
163 /*
164  * Post an interrupt to a vCPU's PIR and trigger the vCPU to process the
165  * interrupt if necessary.
166  */
167 static inline void __vmx_deliver_posted_interrupt(struct kvm_vcpu *vcpu,
168 						  struct pi_desc *pi_desc, int vector)
169 {
170 	if (pi_test_and_set_pir(vector, pi_desc))
171 		return;
172 
173 	/* If a previous notification has sent the IPI, nothing to do.  */
174 	if (pi_test_and_set_on(pi_desc))
175 		return;
176 
177 	/*
178 	 * The implied barrier in pi_test_and_set_on() pairs with the smp_mb_*()
179 	 * after setting vcpu->mode in vcpu_enter_guest(), thus the vCPU is
180 	 * guaranteed to see PID.ON=1 and sync the PIR to IRR if triggering a
181 	 * posted interrupt "fails" because vcpu->mode != IN_GUEST_MODE.
182 	 */
183 	kvm_vcpu_trigger_posted_interrupt(vcpu, POSTED_INTR_VECTOR);
184 }
185 
186 noinstr void vmx_handle_nmi(struct kvm_vcpu *vcpu);
187 
188 #endif /* __KVM_X86_VMX_COMMON_H */
189