| Seq | Timestamp | Type | Name | Duration |
|---|---|---|---|---|
| 0/0 | 2026/09/05 09:24 | flow | patch-triage |
0mArgs:null Results: {
"EnableConfigs": [
"KVM",
"KVM_INTEL"
],
"FocusSymbols": [
"vt_handle_exit_irqoff",
"vt_handle_nmi",
"vt_vcpu_pi_load",
"vt_vcpu_pi_put",
"vt_pi_start_bypass",
"vt_pi_update_irte",
"vmx_handle_exit",
"vmx_vcpu_run",
"nested_vmx_reflect_vmexit"
],
"KMSANReasoning": "The patch is a refactoring of KVM Intel VMX and TDX code to consolidate common virtualization infrastructure (VT) between standard VMX and TDX vCPUs:\n1. It defines a common wrapper layout `struct vcpu_vmx_tdx` with compile-time assertions (`static_assert`) ensuring offset matching of `struct vcpu_vt` across `vcpu_vmx` and `vcpu_tdx`.\n2. It moves and renames helper functions (`to_vt`, `vt_get_exit_reason`, `vt_get_exit_qual`, `vt_get_intr_info`, etc.) from `vmx.h`/`vmx.c` to `common.h`/`main.c`.\n3. It moves common exit and interrupt handling functions (`vt_handle_exit_irqoff`, `vt_handle_nmi`, `handle_external_interrupt_irqoff`, etc.) to `main.c`.\n4. It renames posted interrupt routines to use the `vt_` prefix across the codebase.\n\nNone of these changes allocate uninitialized memory, expose uninitialized fields or padding to user space, or alter buffer bounds. Any potential issues with struct layout or offsets are guarded at compile time by `static_assert` or would manifest as memory corruption/OOB access detectable by standard builds and KASAN. Therefore, a dedicated KMSAN fuzzing session is not warranted.",
"NeedsKMSAN": false,
"Reasoning": "The patch refactors KVM Intel (VMX/TDX) virtualization logic by consolidating exit status handling, exit IRQ-off processing, posted interrupt helpers, and VMCS exit qualification accessors under common vt_* abstractions. This affects core KVM VM exit handling and nested virtualization reachable on amd64.",
"WorthFuzzing": true
} |
| 1/1 | 2026/09/05 09:24 | action | read-patch-diff |
0mArgs:null Results: {
"PatchDiff": "commit 9d25f06a93aabe64fbad0ded74f73000f4a47cc3\nAuthor: syz-cluster \u003ctriage@syzkaller.com\u003e\nDate: Sat Sep 5 09:24:22 2026 +0000\n\n syz-cluster: applied patch under review\n\ndiff --git a/arch/x86/kvm/vmx/common.h b/arch/x86/kvm/vmx/common.h\nindex 08005676702c2..3e68fa12aca65 100644\n--- a/arch/x86/kvm/vmx/common.h\n+++ b/arch/x86/kvm/vmx/common.h\n@@ -2,10 +2,12 @@\n #ifndef __KVM_X86_VMX_COMMON_H\n #define __KVM_X86_VMX_COMMON_H\n \n+#include \u003clinux/container_of.h\u003e\n #include \u003clinux/kvm_host.h\u003e\n #include \u003casm/posted_intr.h\u003e\n \n #include \"mmu.h\"\n+#include \"vmx_ops.h\"\n \n union vmx_exit_reason {\n \tstruct {\n@@ -74,14 +76,62 @@ static __always_inline bool is_td_vcpu(struct kvm_vcpu *vcpu) { return false; }\n \n #endif\n \n+struct vcpu_vmx_tdx {\n+\tstruct kvm_vcpu vcpu;\n+\tstruct vcpu_vt vt;\n+};\n+\n+static __always_inline struct vcpu_vt *to_vt(struct kvm_vcpu *vcpu)\n+{\n+\treturn \u0026(container_of(vcpu, struct vcpu_vmx_tdx, vcpu)-\u003evt);\n+}\n+\n+static __always_inline struct kvm_vcpu *vt_to_vcpu(struct vcpu_vt *vt)\n+{\n+\treturn \u0026(container_of(vt, struct vcpu_vmx_tdx, vt)-\u003evcpu);\n+}\n+\n+static __always_inline union vmx_exit_reason vt_get_exit_reason(struct kvm_vcpu *vcpu)\n+{\n+\treturn to_vt(vcpu)-\u003eexit_reason;\n+}\n+\n+static __always_inline unsigned long vt_get_exit_qual(struct kvm_vcpu *vcpu)\n+{\n+\tstruct vcpu_vt *vt = to_vt(vcpu);\n+\n+\tif (!kvm_register_test_and_mark_available(vcpu, VCPU_REG_EXIT_INFO_1) \u0026\u0026\n+\t !WARN_ON_ONCE(is_td_vcpu(vcpu)))\n+\t\tvt-\u003eexit_qualification = vmcs_readl(EXIT_QUALIFICATION);\n+\n+\treturn vt-\u003eexit_qualification;\n+}\n+\n+static __always_inline u32 vt_get_intr_info(struct kvm_vcpu *vcpu)\n+{\n+\tstruct vcpu_vt *vt = to_vt(vcpu);\n+\n+\tif (!kvm_register_test_and_mark_available(vcpu, VCPU_REG_EXIT_INFO_2) \u0026\u0026\n+\t !WARN_ON_ONCE(is_td_vcpu(vcpu)))\n+\t\tvt-\u003eexit_intr_info = vmcs_read32(VM_EXIT_INTR_INFO);\n+\n+\treturn vt-\u003eexit_intr_info;\n+}\n+\n+static inline bool is_xfd_nm_fault(struct kvm_vcpu *vcpu)\n+{\n+\treturn vcpu-\u003earch.guest_fpu.fpstate-\u003exfd \u0026\u0026\n+\t !kvm_is_cr0_bit_set(vcpu, X86_CR0_TS);\n+}\n+\n static inline bool vt_is_tdx_private_gpa(struct kvm *kvm, gpa_t gpa)\n {\n \t/* For TDX the direct mask is the shared mask. */\n \treturn !kvm_is_addr_direct(kvm, gpa);\n }\n \n-static inline int __vmx_handle_ept_violation(struct kvm_vcpu *vcpu, gpa_t gpa,\n-\t\t\t\t\t unsigned long exit_qualification)\n+static inline int __vt_handle_ept_violation(struct kvm_vcpu *vcpu, gpa_t gpa,\n+\t\t\t\t\t unsigned long exit_qualification)\n {\n \tu64 error_code;\n \n@@ -164,8 +214,8 @@ static inline void kvm_vcpu_trigger_posted_interrupt(struct kvm_vcpu *vcpu,\n * Post an interrupt to a vCPU's PIR and trigger the vCPU to process the\n * interrupt if necessary.\n */\n-static inline void __vmx_deliver_posted_interrupt(struct kvm_vcpu *vcpu,\n-\t\t\t\t\t\t struct pi_desc *pi_desc, int vector)\n+static inline void __vt_deliver_posted_interrupt(struct kvm_vcpu *vcpu,\n+\t\t\t\t\t\t struct pi_desc *pi_desc, int vector)\n {\n \tif (pi_test_and_set_pir(vector, pi_desc))\n \t\treturn;\n@@ -183,6 +233,6 @@ static inline void __vmx_deliver_posted_interrupt(struct kvm_vcpu *vcpu,\n \tkvm_vcpu_trigger_posted_interrupt(vcpu, POSTED_INTR_VECTOR);\n }\n \n-noinstr void vmx_handle_nmi(struct kvm_vcpu *vcpu);\n+noinstr void vt_handle_nmi(struct kvm_vcpu *vcpu);\n \n #endif /* __KVM_X86_VMX_COMMON_H */\ndiff --git a/arch/x86/kvm/vmx/main.c b/arch/x86/kvm/vmx/main.c\nindex 4c52ab8d07869..6e0b3959d73ab 100644\n--- a/arch/x86/kvm/vmx/main.c\n+++ b/arch/x86/kvm/vmx/main.c\n@@ -1,4 +1,5 @@\n // SPDX-License-Identifier: GPL-2.0\n+#include \u003clinux/entry-common.h\u003e\n #include \u003clinux/moduleparam.h\u003e\n \n #include \"x86_ops.h\"\n@@ -10,8 +11,12 @@\n #include \"tdx.h\"\n #include \"tdx_arch.h\"\n \n+#pragma GCC poison to_vmx\n+\n+static_assert(offsetof(struct vcpu_vmx_tdx, vt) == offsetof(struct vcpu_vmx, vt));\n+\n #ifdef CONFIG_KVM_INTEL_TDX\n-static_assert(offsetof(struct vcpu_vmx, vt) == offsetof(struct vcpu_tdx, vt));\n+static_assert(offsetof(struct vcpu_vmx_tdx, vt) == offsetof(struct vcpu_tdx, vt));\n \n static void vt_disable_virtualization_cpu(void)\n {\n@@ -876,6 +881,85 @@ static int vt_gmem_max_mapping_level(struct kvm *kvm, kvm_pfn_t pfn,\n #define vt_op_tdx_only(name) NULL\n #endif /* CONFIG_KVM_INTEL_TDX */\n \n+static void handle_nm_fault_irqoff(struct kvm_vcpu *vcpu)\n+{\n+\t/*\n+\t * Save xfd_err to guest_fpu before interrupt is enabled, so the\n+\t * MSR value is not clobbered by the host activity before the guest\n+\t * has chance to consume it.\n+\t *\n+\t * Update the guest's XFD_ERR if and only if XFD is enabled, as the #NM\n+\t * interception may have been caused by L1 interception. Per the SDM,\n+\t * XFD_ERR is not modified for non-XFD #NM, i.e. if CR0.TS=1.\n+\t *\n+\t * Note, XFD_ERR is updated _before_ the #NM interception check, i.e.\n+\t * unlike CR2 and DR6, the value is not a payload that is attached to\n+\t * the #NM exception.\n+\t */\n+\tif (is_xfd_nm_fault(vcpu))\n+\t\trdmsrq(MSR_IA32_XFD_ERR, vcpu-\u003earch.guest_fpu.xfd_err);\n+}\n+\n+static void handle_exception_irqoff(struct kvm_vcpu *vcpu, u32 intr_info)\n+{\n+\t/* if exit due to PF check for async PF */\n+\tif (is_page_fault(intr_info))\n+\t\tvcpu-\u003earch.apf.host_apf_flags = kvm_read_and_reset_apf_flags();\n+\t/* if exit due to NM, handle before interrupts are enabled */\n+\telse if (is_nm_fault(intr_info))\n+\t\thandle_nm_fault_irqoff(vcpu);\n+\t/* Handle machine checks before interrupts are enabled */\n+\telse if (is_machine_check(intr_info))\n+\t\tkvm_machine_check();\n+}\n+\n+static void handle_external_interrupt_irqoff(struct kvm_vcpu *vcpu,\n+\t\t\t\t\t u32 intr_info)\n+{\n+\tunsigned int vector = intr_info \u0026 INTR_INFO_VECTOR_MASK;\n+\n+\tif (KVM_BUG(!is_external_intr(intr_info), vcpu-\u003ekvm,\n+\t \"unexpected VM-Exit interrupt info: 0x%x\", intr_info))\n+\t\treturn;\n+\n+\tkvm_before_interrupt(vcpu, KVM_HANDLING_IRQ);\n+\tx86_entry_from_kvm(EVENT_TYPE_EXTINT, vector);\n+\tkvm_after_interrupt(vcpu);\n+\n+\tvcpu-\u003earch.at_instruction_boundary = true;\n+}\n+\n+static void vt_handle_exit_irqoff(struct kvm_vcpu *vcpu)\n+{\n+\tif (to_vt(vcpu)-\u003eemulation_required)\n+\t\treturn;\n+\n+\tswitch (vt_get_exit_reason(vcpu).basic) {\n+\tcase EXIT_REASON_EXTERNAL_INTERRUPT:\n+\t\thandle_external_interrupt_irqoff(vcpu, vt_get_intr_info(vcpu));\n+\t\tbreak;\n+\tcase EXIT_REASON_EXCEPTION_NMI:\n+\t\thandle_exception_irqoff(vcpu, vt_get_intr_info(vcpu));\n+\t\tbreak;\n+\tcase EXIT_REASON_MCE_DURING_VMENTRY:\n+\t\tkvm_machine_check();\n+\t\tbreak;\n+\tdefault:\n+\t\tbreak;\n+\t}\n+}\n+\n+noinstr void vt_handle_nmi(struct kvm_vcpu *vcpu)\n+{\n+\tif ((u16)vt_get_exit_reason(vcpu).basic != EXIT_REASON_EXCEPTION_NMI ||\n+\t !is_nmi(vt_get_intr_info(vcpu)))\n+\t\treturn;\n+\n+\tkvm_before_interrupt(vcpu, KVM_HANDLING_NMI);\n+\tx86_entry_from_kvm(EVENT_TYPE_NMI, NMI_VECTOR);\n+\tkvm_after_interrupt(vcpu);\n+}\n+\n #define VMX_REQUIRED_APICV_INHIBITS\t\t\t\t\\\n \t(BIT(APICV_INHIBIT_REASON_DISABLED) |\t\t\t\\\n \t BIT(APICV_INHIBIT_REASON_ABSENT) |\t\t\t\\\n@@ -1000,12 +1084,12 @@ struct kvm_x86_ops vt_x86_ops __initdata = {\n \t.load_mmu_pgd = vt_op(load_mmu_pgd),\n \n \t.check_intercept = vmx_check_intercept,\n-\t.handle_exit_irqoff = vmx_handle_exit_irqoff,\n+\t.handle_exit_irqoff = vt_handle_exit_irqoff,\n \n \t.update_cpu_dirty_logging = vt_op(update_cpu_dirty_logging),\n \n-\t.pi_update_irte = vmx_pi_update_irte,\n-\t.pi_start_bypass = vmx_pi_start_bypass,\n+\t.pi_update_irte = vt_pi_update_irte,\n+\t.pi_start_bypass = vt_pi_start_bypass,\n \n #ifdef CONFIG_X86_64\n \t.set_hv_timer = vt_op(set_hv_timer),\ndiff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c\nindex 151873407abd3..47599e7312cfd 100644\n--- a/arch/x86/kvm/vmx/nested.c\n+++ b/arch/x86/kvm/vmx/nested.c\n@@ -446,7 +446,7 @@ static void nested_ept_inject_page_fault(struct kvm_vcpu *vcpu,\n \t\t * \"NMI unblocking due to IRET\", i.e. the bit can be propagated\n \t\t * as-is from the original EXIT_QUALIFICATION.\n \t\t */\n-\t\texit_qualification = vmx_get_exit_qual(vcpu) \u0026 INTR_INFO_UNBLOCK_NMI;\n+\t\texit_qualification = vt_get_exit_qual(vcpu) \u0026 INTR_INFO_UNBLOCK_NMI;\n \t} else {\n \t\tif (fault-\u003eerror_code \u0026 PFERR_RSVD_MASK) {\n \t\t\tvm_exit_reason = EXIT_REASON_EPT_MISCONFIG;\n@@ -472,7 +472,7 @@ static void nested_ept_inject_page_fault(struct kvm_vcpu *vcpu,\n \t\t\t * and walks the faulting GPA.\n \t\t\t */\n \t\t\tif (from_hardware)\n-\t\t\t\texit_qualification |= vmx_get_exit_qual(vcpu) \u0026 mask;\n+\t\t\t\texit_qualification |= vt_get_exit_qual(vcpu) \u0026 mask;\n \t\t\telse\n \t\t\t\texit_qualification |= fault-\u003eexit_qualification \u0026 mask;\n \n@@ -4747,7 +4747,7 @@ static void prepare_vmcs12(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12,\n {\n \t/* update exit information fields: */\n \tvmcs12-\u003evm_exit_reason = vm_exit_reason;\n-\tif (vmx_get_exit_reason(vcpu).enclave_mode)\n+\tif (vt_get_exit_reason(vcpu).enclave_mode)\n \t\tvmcs12-\u003evm_exit_reason |= VMX_EXIT_REASONS_SGX_ENCLAVE_MODE;\n \tvmcs12-\u003eexit_qualification = exit_qualification;\n \n@@ -5373,7 +5373,7 @@ static int nested_vmx_get_vmptr(struct kvm_vcpu *vcpu, gpa_t *vmpointer,\n \tstruct x86_exception e;\n \tint r;\n \n-\tif (get_vmx_mem_address(vcpu, vmx_get_exit_qual(vcpu),\n+\tif (get_vmx_mem_address(vcpu, vt_get_exit_qual(vcpu),\n \t\t\t\tvmcs_read32(VMX_INSTRUCTION_INFO), false,\n \t\t\t\tsizeof(*vmpointer), \u0026gva)) {\n \t\t*ret = 1;\n@@ -5665,7 +5665,7 @@ static int handle_vmread(struct kvm_vcpu *vcpu)\n {\n \tstruct vmcs12 *vmcs12 = is_guest_mode(vcpu) ? get_shadow_vmcs12(vcpu)\n \t\t\t\t\t\t : get_vmcs12(vcpu);\n-\tunsigned long exit_qualification = vmx_get_exit_qual(vcpu);\n+\tunsigned long exit_qualification = vt_get_exit_qual(vcpu);\n \tu32 instr_info = vmcs_read32(VMX_INSTRUCTION_INFO);\n \tstruct vcpu_vmx *vmx = to_vmx(vcpu);\n \tstruct x86_exception e;\n@@ -5771,7 +5771,7 @@ static int handle_vmwrite(struct kvm_vcpu *vcpu)\n {\n \tstruct vmcs12 *vmcs12 = is_guest_mode(vcpu) ? get_shadow_vmcs12(vcpu)\n \t\t\t\t\t\t : get_vmcs12(vcpu);\n-\tunsigned long exit_qualification = vmx_get_exit_qual(vcpu);\n+\tunsigned long exit_qualification = vt_get_exit_qual(vcpu);\n \tu32 instr_info = vmcs_read32(VMX_INSTRUCTION_INFO);\n \tstruct vcpu_vmx *vmx = to_vmx(vcpu);\n \tstruct x86_exception e;\n@@ -5960,7 +5960,7 @@ static int handle_vmptrld(struct kvm_vcpu *vcpu)\n /* Emulate the VMPTRST instruction */\n static int handle_vmptrst(struct kvm_vcpu *vcpu)\n {\n-\tunsigned long exit_qual = vmx_get_exit_qual(vcpu);\n+\tunsigned long exit_qual = vt_get_exit_qual(vcpu);\n \tu32 instr_info = vmcs_read32(VMX_INSTRUCTION_INFO);\n \tgpa_t current_vmptr = to_vmx(vcpu)-\u003enested.current_vmptr;\n \tstruct x86_exception e;\n@@ -6021,7 +6021,7 @@ static int handle_invept(struct kvm_vcpu *vcpu)\n \t/* According to the Intel VMX instruction reference, the memory\n \t * operand is read even if it isn't needed (e.g., for type==global)\n \t */\n-\tif (get_vmx_mem_address(vcpu, vmx_get_exit_qual(vcpu),\n+\tif (get_vmx_mem_address(vcpu, vt_get_exit_qual(vcpu),\n \t\t\tvmx_instruction_info, false, sizeof(operand), \u0026gva))\n \t\treturn 1;\n \tr = kvm_read_guest_virt(vcpu, gva, \u0026operand, sizeof(operand), \u0026e);\n@@ -6104,7 +6104,7 @@ static int handle_invvpid(struct kvm_vcpu *vcpu)\n \t/* according to the intel vmx instruction reference, the memory\n \t * operand is read even if it isn't needed (e.g., for type==global)\n \t */\n-\tif (get_vmx_mem_address(vcpu, vmx_get_exit_qual(vcpu),\n+\tif (get_vmx_mem_address(vcpu, vt_get_exit_qual(vcpu),\n \t\t\tvmx_instruction_info, false, sizeof(operand), \u0026gva))\n \t\treturn 1;\n \tr = kvm_read_guest_virt(vcpu, gva, \u0026operand, sizeof(operand), \u0026e);\n@@ -6236,8 +6236,8 @@ static int handle_vmfunc(struct kvm_vcpu *vcpu)\n \t * EXIT_REASON_VMFUNC as the exit reason.\n \t */\n \tnested_vmx_vmexit(vcpu, vmx-\u003evt.exit_reason.full,\n-\t\t\t vmx_get_intr_info(vcpu),\n-\t\t\t vmx_get_exit_qual(vcpu));\n+\t\t\t vt_get_intr_info(vcpu),\n+\t\t\t vt_get_exit_qual(vcpu));\n \treturn 1;\n }\n \n@@ -6288,7 +6288,7 @@ static bool nested_vmx_exit_handled_io(struct kvm_vcpu *vcpu,\n \tif (!nested_cpu_has(vmcs12, CPU_BASED_USE_IO_BITMAPS))\n \t\treturn nested_cpu_has(vmcs12, CPU_BASED_UNCOND_IO_EXITING);\n \n-\texit_qualification = vmx_get_exit_qual(vcpu);\n+\texit_qualification = vt_get_exit_qual(vcpu);\n \n \tport = exit_qualification \u003e\u003e 16;\n \tsize = (exit_qualification \u0026 7) + 1;\n@@ -6314,7 +6314,7 @@ static bool nested_vmx_exit_handled_msr(struct kvm_vcpu *vcpu,\n \n \tif (exit_reason.basic == EXIT_REASON_MSR_READ_IMM ||\n \t exit_reason.basic == EXIT_REASON_MSR_WRITE_IMM)\n-\t\tmsr_index = vmx_get_exit_qual(vcpu);\n+\t\tmsr_index = vt_get_exit_qual(vcpu);\n \telse\n \t\tmsr_index = kvm_ecx_read(vcpu);\n \n@@ -6350,7 +6350,7 @@ static bool nested_vmx_exit_handled_msr(struct kvm_vcpu *vcpu,\n static bool nested_vmx_exit_handled_cr(struct kvm_vcpu *vcpu,\n \tstruct vmcs12 *vmcs12)\n {\n-\tunsigned long exit_qualification = vmx_get_exit_qual(vcpu);\n+\tunsigned long exit_qualification = vt_get_exit_qual(vcpu);\n \tint cr = exit_qualification \u0026 15;\n \tint reg;\n \tunsigned long val;\n@@ -6484,7 +6484,7 @@ static bool nested_vmx_l0_wants_exit(struct kvm_vcpu *vcpu,\n \n \tswitch ((u16)exit_reason.basic) {\n \tcase EXIT_REASON_EXCEPTION_NMI:\n-\t\tintr_info = vmx_get_intr_info(vcpu);\n+\t\tintr_info = vt_get_intr_info(vcpu);\n \t\tif (is_nmi(intr_info))\n \t\t\treturn true;\n \t\telse if (is_page_fault(intr_info))\n@@ -6567,7 +6567,7 @@ static bool nested_vmx_l1_wants_exit(struct kvm_vcpu *vcpu,\n \n \tswitch ((u16)exit_reason.basic) {\n \tcase EXIT_REASON_EXCEPTION_NMI:\n-\t\tintr_info = vmx_get_intr_info(vcpu);\n+\t\tintr_info = vt_get_intr_info(vcpu);\n \t\tif (is_nmi(intr_info))\n \t\t\treturn true;\n \t\telse if (is_page_fault(intr_info))\n@@ -6737,14 +6737,14 @@ bool nested_vmx_reflect_vmexit(struct kvm_vcpu *vcpu)\n \t * need to be synthesized by querying the in-kernel LAPIC, but external\n \t * interrupts are never reflected to L1 so it's a non-issue.\n \t */\n-\texit_intr_info = vmx_get_intr_info(vcpu);\n+\texit_intr_info = vt_get_intr_info(vcpu);\n \tif (is_exception_with_error_code(exit_intr_info)) {\n \t\tstruct vmcs12 *vmcs12 = get_vmcs12(vcpu);\n \n \t\tvmcs12-\u003evm_exit_intr_error_code =\n \t\t\tvmcs_read32(VM_EXIT_INTR_ERROR_CODE);\n \t}\n-\texit_qual = vmx_get_exit_qual(vcpu);\n+\texit_qual = vt_get_exit_qual(vcpu);\n \n reflect_vmexit:\n \tnested_vmx_vmexit(vcpu, exit_reason.full, exit_intr_info, exit_qual);\ndiff --git a/arch/x86/kvm/vmx/posted_intr.c b/arch/x86/kvm/vmx/posted_intr.c\nindex 4a6d9a17da238..2644add54b76b 100644\n--- a/arch/x86/kvm/vmx/posted_intr.c\n+++ b/arch/x86/kvm/vmx/posted_intr.c\n@@ -14,6 +14,8 @@\n #include \"vmx.h\"\n #include \"tdx.h\"\n \n+#pragma GCC poison to_vmx\n+\n /*\n * Maintain a per-CPU list of vCPUs that need to be awakened by wakeup_handler()\n * when a WAKEUP_VECTOR interrupted is posted. vCPUs are added to the list when\n@@ -54,7 +56,7 @@ static int pi_try_set_control(struct pi_desc *pi_desc, u64 *pold, u64 new)\n \treturn 0;\n }\n \n-void vmx_vcpu_pi_load(struct kvm_vcpu *vcpu, int cpu)\n+void vt_vcpu_pi_load(struct kvm_vcpu *vcpu, int cpu)\n {\n \tstruct pi_desc *pi_desc = vcpu_to_pi_desc(vcpu);\n \tstruct vcpu_vt *vt = to_vt(vcpu);\n@@ -144,11 +146,11 @@ void vmx_vcpu_pi_load(struct kvm_vcpu *vcpu, int cpu)\n \t\tpi_set_on(pi_desc);\n }\n \n-static bool vmx_can_use_vtd_pi(struct kvm *kvm)\n+static bool vt_can_use_vtd_pi(struct kvm *kvm)\n {\n \t/*\n \t * Note, reading the number of possible bypass IRQs can race with a\n-\t * bypass IRQ being attached to the VM. vmx_pi_start_bypass() ensures\n+\t * bypass IRQ being attached to the VM. vt_pi_start_bypass() ensures\n \t * blockng vCPUs will see an elevated count or get KVM_REQ_UNBLOCK.\n \t */\n \treturn irqchip_in_kernel(kvm) \u0026\u0026 kvm_arch_has_irq_bypass() \u0026\u0026\n@@ -206,7 +208,7 @@ static void pi_enable_wakeup_handler(struct kvm_vcpu *vcpu)\n \t\t__apic_send_IPI_self(POSTED_INTR_WAKEUP_VECTOR);\n }\n \n-static bool vmx_needs_pi_wakeup(struct kvm_vcpu *vcpu)\n+static bool vt_needs_pi_wakeup(struct kvm_vcpu *vcpu)\n {\n \t/*\n \t * The default posted interrupt vector does nothing when\n@@ -217,14 +219,14 @@ static bool vmx_needs_pi_wakeup(struct kvm_vcpu *vcpu)\n \t * back to the pi_wakeup_handler() function.\n \t */\n \treturn (vmx_can_use_ipiv(vcpu) \u0026\u0026 !is_td_vcpu(vcpu)) ||\n-\t\tvmx_can_use_vtd_pi(vcpu-\u003ekvm);\n+\t\tvt_can_use_vtd_pi(vcpu-\u003ekvm);\n }\n \n-void vmx_vcpu_pi_put(struct kvm_vcpu *vcpu)\n+void vt_vcpu_pi_put(struct kvm_vcpu *vcpu)\n {\n \tstruct pi_desc *pi_desc = vcpu_to_pi_desc(vcpu);\n \n-\tif (!vmx_needs_pi_wakeup(vcpu))\n+\tif (!vt_needs_pi_wakeup(vcpu))\n \t\treturn;\n \n \t/*\n@@ -292,17 +294,17 @@ bool pi_has_pending_interrupt(struct kvm_vcpu *vcpu)\n /*\n * Kick all vCPUs when the first possible bypass IRQ is attached to a VM, as\n * blocking vCPUs may scheduled out without reconfiguring PID.NV to the wakeup\n- * vector, i.e. if the bypass IRQ came along after vmx_vcpu_pi_put().\n+ * vector, i.e. if the bypass IRQ came along after vt_vcpu_pi_put().\n */\n-void vmx_pi_start_bypass(struct kvm *kvm)\n+void vt_pi_start_bypass(struct kvm *kvm)\n {\n-\tif (WARN_ON_ONCE(!vmx_can_use_vtd_pi(kvm)))\n+\tif (WARN_ON_ONCE(!vt_can_use_vtd_pi(kvm)))\n \t\treturn;\n \n \tkvm_make_all_cpus_request(kvm, KVM_REQ_UNBLOCK);\n }\n \n-int vmx_pi_update_irte(struct kvm_kernel_irqfd *irqfd, struct kvm *kvm,\n+int vt_pi_update_irte(struct kvm_kernel_irqfd *irqfd, struct kvm *kvm,\n \t\t unsigned int host_irq, uint32_t guest_irq,\n \t\t struct kvm_vcpu *vcpu, u32 vector)\n {\ndiff --git a/arch/x86/kvm/vmx/posted_intr.h b/arch/x86/kvm/vmx/posted_intr.h\nindex a4af39948cf04..c5860ea828ae9 100644\n--- a/arch/x86/kvm/vmx/posted_intr.h\n+++ b/arch/x86/kvm/vmx/posted_intr.h\n@@ -8,16 +8,16 @@\n \n #include \u003casm/posted_intr.h\u003e\n \n-void vmx_vcpu_pi_load(struct kvm_vcpu *vcpu, int cpu);\n-void vmx_vcpu_pi_put(struct kvm_vcpu *vcpu);\n+void vt_vcpu_pi_load(struct kvm_vcpu *vcpu, int cpu);\n+void vt_vcpu_pi_put(struct kvm_vcpu *vcpu);\n void pi_wakeup_handler(void);\n void __init pi_init_cpu(int cpu);\n void pi_apicv_pre_state_restore(struct kvm_vcpu *vcpu);\n bool pi_has_pending_interrupt(struct kvm_vcpu *vcpu);\n-int vmx_pi_update_irte(struct kvm_kernel_irqfd *irqfd, struct kvm *kvm,\n+int vt_pi_update_irte(struct kvm_kernel_irqfd *irqfd, struct kvm *kvm,\n \t\t unsigned int host_irq, uint32_t guest_irq,\n \t\t struct kvm_vcpu *vcpu, u32 vector);\n-void vmx_pi_start_bypass(struct kvm *kvm);\n+void vt_pi_start_bypass(struct kvm *kvm);\n \n static inline int pi_find_highest_vector(struct pi_desc *pi_desc)\n {\ndiff --git a/arch/x86/kvm/vmx/tdx.c b/arch/x86/kvm/vmx/tdx.c\nindex b272c20586a74..efbb1ac6f51ea 100644\n--- a/arch/x86/kvm/vmx/tdx.c\n+++ b/arch/x86/kvm/vmx/tdx.c\n@@ -716,7 +716,7 @@ void tdx_vcpu_load(struct kvm_vcpu *vcpu, int cpu)\n {\n \tstruct vcpu_tdx *tdx = to_tdx(vcpu);\n \n-\tvmx_vcpu_pi_load(vcpu, cpu);\n+\tvt_vcpu_pi_load(vcpu, cpu);\n \tif (vcpu-\u003ecpu == cpu || !is_hkid_assigned(to_kvm_tdx(vcpu-\u003ekvm)))\n \t\treturn;\n \n@@ -741,7 +741,7 @@ bool tdx_interrupt_allowed(struct kvm_vcpu *vcpu)\n \t * interrupt is always allowed unless TDX guest calls TDVMCALL with HLT,\n \t * which passes the interrupt blocked flag.\n \t */\n-\treturn vmx_get_exit_reason(vcpu).basic != EXIT_REASON_HLT ||\n+\treturn vt_get_exit_reason(vcpu).basic != EXIT_REASON_HLT ||\n \t !to_tdx(vcpu)-\u003evp_enter_args.r12;\n }\n \n@@ -759,7 +759,7 @@ static bool tdx_protected_apic_has_interrupt(struct kvm_vcpu *vcpu)\n \t * otherwise the interrupt would have been serviced at the instruction\n \t * boundary.\n \t */\n-\tif (vmx_get_exit_reason(vcpu).basic != EXIT_REASON_HLT ||\n+\tif (vt_get_exit_reason(vcpu).basic != EXIT_REASON_HLT ||\n \t to_tdx(vcpu)-\u003evp_enter_args.r12)\n \t\treturn false;\n \n@@ -826,7 +826,7 @@ static void tdx_prepare_switch_to_host(struct kvm_vcpu *vcpu)\n \n void tdx_vcpu_put(struct kvm_vcpu *vcpu)\n {\n-\tvmx_vcpu_pi_put(vcpu);\n+\tvt_vcpu_pi_put(vcpu);\n \ttdx_prepare_switch_to_host(vcpu);\n }\n \n@@ -974,15 +974,15 @@ static noinstr void tdx_vcpu_enter_exit(struct kvm_vcpu *vcpu)\n \ttdx-\u003eexit_gpa = tdx-\u003evp_enter_args.r8;\n \tvt-\u003eexit_intr_info = tdx-\u003evp_enter_args.r9;\n \n-\tvmx_handle_nmi(vcpu);\n+\tvt_handle_nmi(vcpu);\n \n \tguest_state_exit_irqoff();\n }\n \n static bool tdx_failed_vmentry(struct kvm_vcpu *vcpu)\n {\n-\treturn vmx_get_exit_reason(vcpu).failed_vmentry \u0026\u0026\n-\t vmx_get_exit_reason(vcpu).full != -1u;\n+\treturn vt_get_exit_reason(vcpu).failed_vmentry \u0026\u0026\n+\t vt_get_exit_reason(vcpu).full != -1u;\n }\n \n static fastpath_t tdx_exit_handlers_fastpath(struct kvm_vcpu *vcpu)\n@@ -1131,7 +1131,7 @@ void tdx_inject_nmi(struct kvm_vcpu *vcpu)\n \n static int tdx_handle_exception_nmi(struct kvm_vcpu *vcpu)\n {\n-\tu32 intr_info = vmx_get_intr_info(vcpu);\n+\tu32 intr_info = vt_get_intr_info(vcpu);\n \n \t/*\n \t * Machine checks are handled by handle_exception_irqoff(), or by\n@@ -1895,7 +1895,7 @@ void tdx_deliver_interrupt(struct kvm_lapic *apic, int delivery_mode,\n \tstruct vcpu_tdx *tdx = to_tdx(vcpu);\n \n \t/* TDX supports only posted interrupt. No lapic emulation. */\n-\t__vmx_deliver_posted_interrupt(vcpu, \u0026tdx-\u003evt.pi_desc, vector);\n+\t__vt_deliver_posted_interrupt(vcpu, \u0026tdx-\u003evt.pi_desc, vector);\n \n \ttrace_kvm_apicv_accept_irq(vcpu-\u003evcpu_id, delivery_mode, trig_mode, vector);\n }\n@@ -1903,7 +1903,7 @@ void tdx_deliver_interrupt(struct kvm_lapic *apic, int delivery_mode,\n static inline bool tdx_is_sept_violation_unexpected_pending(struct kvm_vcpu *vcpu)\n {\n \tu64 eeq_type = to_tdx(vcpu)-\u003eext_exit_qualification \u0026 TDX_EXT_EXIT_QUAL_TYPE_MASK;\n-\tu64 eq = vmx_get_exit_qual(vcpu);\n+\tu64 eq = vt_get_exit_qual(vcpu);\n \n \tif (eeq_type != TDX_EXT_EXIT_QUAL_TYPE_PENDING_EPT_VIOLATION)\n \t\treturn false;\n@@ -1939,7 +1939,7 @@ static int tdx_handle_ept_violation(struct kvm_vcpu *vcpu)\n \t\t/* Only private GPA triggers zero-step mitigation */\n \t\tlocal_retry = true;\n \t} else {\n-\t\texit_qual = vmx_get_exit_qual(vcpu);\n+\t\texit_qual = vt_get_exit_qual(vcpu);\n \t\t/*\n \t\t * EPT violation due to instruction fetch should never be\n \t\t * triggered from shared memory in TDX guest. If such EPT\n@@ -1987,7 +1987,7 @@ static int tdx_handle_ept_violation(struct kvm_vcpu *vcpu)\n \twhile (1) {\n \t\tstruct kvm_memory_slot *slot;\n \n-\t\tret = __vmx_handle_ept_violation(vcpu, gpa, exit_qual);\n+\t\tret = __vt_handle_ept_violation(vcpu, gpa, exit_qual);\n \n \t\tif (ret != RET_PF_RETRY || !local_retry)\n \t\t\tbreak;\n@@ -2021,7 +2021,7 @@ int tdx_complete_emulated_msr(struct kvm_vcpu *vcpu, int err)\n \t\treturn 1;\n \t}\n \n-\tif (vmx_get_exit_reason(vcpu).basic == EXIT_REASON_MSR_READ)\n+\tif (vt_get_exit_reason(vcpu).basic == EXIT_REASON_MSR_READ)\n \t\ttdvmcall_set_return_val(vcpu, kvm_read_edx_eax(vcpu));\n \n \treturn 1;\n@@ -2032,7 +2032,7 @@ int tdx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t fastpath)\n {\n \tstruct vcpu_tdx *tdx = to_tdx(vcpu);\n \tu64 vp_enter_ret = tdx-\u003evp_enter_ret;\n-\tunion vmx_exit_reason exit_reason = vmx_get_exit_reason(vcpu);\n+\tunion vmx_exit_reason exit_reason = vt_get_exit_reason(vcpu);\n \n \tif (fastpath != EXIT_FASTPATH_NONE)\n \t\treturn 1;\n@@ -2142,9 +2142,9 @@ void tdx_get_exit_info(struct kvm_vcpu *vcpu, u32 *reason,\n \n \t*reason = tdx-\u003evt.exit_reason.full;\n \tif (*reason != -1u) {\n-\t\t*info1 = vmx_get_exit_qual(vcpu);\n+\t\t*info1 = vt_get_exit_qual(vcpu);\n \t\t*info2 = tdx-\u003eext_exit_qualification;\n-\t\t*intr_info = vmx_get_intr_info(vcpu);\n+\t\t*intr_info = vt_get_intr_info(vcpu);\n \t} else {\n \t\t*info1 = 0;\n \t\t*info2 = 0;\ndiff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c\nindex 504630f0eb40f..7e35c2d03c69e 100644\n--- a/arch/x86/kvm/vmx/vmx.c\n+++ b/arch/x86/kvm/vmx/vmx.c\n@@ -1577,12 +1577,12 @@ void vmx_vcpu_load(struct kvm_vcpu *vcpu, int cpu)\n \n \tvmx_vcpu_load_vmcs(vcpu, cpu);\n \n-\tvmx_vcpu_pi_load(vcpu, cpu);\n+\tvt_vcpu_pi_load(vcpu, cpu);\n }\n \n void vmx_vcpu_put(struct kvm_vcpu *vcpu)\n {\n-\tvmx_vcpu_pi_put(vcpu);\n+\tvt_vcpu_pi_put(vcpu);\n \n \tvmx_prepare_switch_to_host(to_vmx(vcpu));\n }\n@@ -1791,7 +1791,7 @@ int vmx_check_emulate_instruction(struct kvm_vcpu *vcpu, int emul_type,\n \t * so that guest userspace can't DoS the guest simply by triggering\n \t * emulation (enclaves are CPL3 only).\n \t */\n-\tif (vmx_get_exit_reason(vcpu).enclave_mode) {\n+\tif (vt_get_exit_reason(vcpu).enclave_mode) {\n \t\tkvm_queue_exception(vcpu, UD_VECTOR);\n \t\treturn X86EMUL_PROPAGATE_FAULT;\n \t}\n@@ -1806,7 +1806,7 @@ int vmx_check_emulate_instruction(struct kvm_vcpu *vcpu, int emul_type,\n \n static int skip_emulated_instruction(struct kvm_vcpu *vcpu)\n {\n-\tunion vmx_exit_reason exit_reason = vmx_get_exit_reason(vcpu);\n+\tunion vmx_exit_reason exit_reason = vt_get_exit_reason(vcpu);\n \tunsigned long rip, orig_rip;\n \tu32 instr_len;\n \n@@ -4424,7 +4424,7 @@ static int vmx_deliver_posted_interrupt(struct kvm_vcpu *vcpu, int vector)\n \tif (!vcpu-\u003earch.apic-\u003eapicv_active)\n \t\treturn -1;\n \n-\t__vmx_deliver_posted_interrupt(vcpu, \u0026vt-\u003epi_desc, vector);\n+\t__vt_deliver_posted_interrupt(vcpu, \u0026vt-\u003epi_desc, vector);\n \treturn 0;\n }\n \n@@ -5379,15 +5379,9 @@ bool vmx_guest_inject_ac(struct kvm_vcpu *vcpu)\n \t (kvm_get_rflags(vcpu) \u0026 X86_EFLAGS_AC);\n }\n \n-static bool is_xfd_nm_fault(struct kvm_vcpu *vcpu)\n-{\n-\treturn vcpu-\u003earch.guest_fpu.fpstate-\u003exfd \u0026\u0026\n-\t !kvm_is_cr0_bit_set(vcpu, X86_CR0_TS);\n-}\n-\n static int vmx_handle_page_fault(struct kvm_vcpu *vcpu, u32 error_code)\n {\n-\tunsigned long cr2 = vmx_get_exit_qual(vcpu);\n+\tunsigned long cr2 = vt_get_exit_qual(vcpu);\n \n \tif (vcpu-\u003earch.apf.host_apf_flags)\n \t\tgoto handle_pf;\n@@ -5435,7 +5429,7 @@ static int handle_exception_nmi(struct kvm_vcpu *vcpu)\n \tu32 vect_info;\n \n \tvect_info = vmx-\u003eidt_vectoring_info;\n-\tintr_info = vmx_get_intr_info(vcpu);\n+\tintr_info = vt_get_intr_info(vcpu);\n \n \t/*\n \t * Machine checks are handled by handle_exception_irqoff(), or by\n@@ -5516,7 +5510,7 @@ static int handle_exception_nmi(struct kvm_vcpu *vcpu)\n \n \tswitch (ex_no) {\n \tcase DB_VECTOR:\n-\t\tdr6 = vmx_get_exit_qual(vcpu);\n+\t\tdr6 = vt_get_exit_qual(vcpu);\n \t\tif (!(vcpu-\u003eguest_debug \u0026\n \t\t (KVM_GUESTDBG_SINGLESTEP | KVM_GUESTDBG_USE_HW_BP))) {\n \t\t\t/*\n@@ -5592,7 +5586,7 @@ static int handle_io(struct kvm_vcpu *vcpu)\n \tint size, in, string;\n \tunsigned port;\n \n-\texit_qualification = vmx_get_exit_qual(vcpu);\n+\texit_qualification = vt_get_exit_qual(vcpu);\n \tstring = (exit_qualification \u0026 16) != 0;\n \n \t++vcpu-\u003estat.io_exits;\n@@ -5681,7 +5675,7 @@ static int handle_cr(struct kvm_vcpu *vcpu)\n \tint err;\n \tint ret;\n \n-\texit_qualification = vmx_get_exit_qual(vcpu);\n+\texit_qualification = vt_get_exit_qual(vcpu);\n \tcr = exit_qualification \u0026 15;\n \treg = (exit_qualification \u003e\u003e 8) \u0026 15;\n \tswitch ((exit_qualification \u003e\u003e 4) \u0026 3) {\n@@ -5759,7 +5753,7 @@ static int handle_dr(struct kvm_vcpu *vcpu)\n \tint dr, dr7, reg;\n \tint err = 1;\n \n-\texit_qualification = vmx_get_exit_qual(vcpu);\n+\texit_qualification = vt_get_exit_qual(vcpu);\n \tdr = exit_qualification \u0026 DEBUG_REG_ACCESS_NUM;\n \n \t/* First, if DR does not exist, trigger UD */\n@@ -5855,7 +5849,7 @@ static int handle_interrupt_window(struct kvm_vcpu *vcpu)\n \n static int handle_invlpg(struct kvm_vcpu *vcpu)\n {\n-\tunsigned long exit_qualification = vmx_get_exit_qual(vcpu);\n+\tunsigned long exit_qualification = vt_get_exit_qual(vcpu);\n \n \tkvm_mmu_invlpg(vcpu, exit_qualification);\n \treturn kvm_skip_emulated_instruction(vcpu);\n@@ -5864,7 +5858,7 @@ static int handle_invlpg(struct kvm_vcpu *vcpu)\n static int handle_apic_access(struct kvm_vcpu *vcpu)\n {\n \tif (likely(fasteoi)) {\n-\t\tunsigned long exit_qualification = vmx_get_exit_qual(vcpu);\n+\t\tunsigned long exit_qualification = vt_get_exit_qual(vcpu);\n \t\tint access_type, offset;\n \n \t\taccess_type = exit_qualification \u0026 APIC_ACCESS_TYPE;\n@@ -5885,7 +5879,7 @@ static int handle_apic_access(struct kvm_vcpu *vcpu)\n \n static int handle_apic_eoi_induced(struct kvm_vcpu *vcpu)\n {\n-\tunsigned long exit_qualification = vmx_get_exit_qual(vcpu);\n+\tunsigned long exit_qualification = vt_get_exit_qual(vcpu);\n \tint vector = exit_qualification \u0026 0xff;\n \n \t/* EOI-induced VM exit is trap-like and thus no need to adjust IP */\n@@ -5895,7 +5889,7 @@ static int handle_apic_eoi_induced(struct kvm_vcpu *vcpu)\n \n static int handle_apic_write(struct kvm_vcpu *vcpu)\n {\n-\tunsigned long exit_qualification = vmx_get_exit_qual(vcpu);\n+\tunsigned long exit_qualification = vt_get_exit_qual(vcpu);\n \n \t/*\n \t * APIC-write VM-Exit is trap-like, KVM doesn't need to advance RIP and\n@@ -5923,7 +5917,7 @@ static int handle_task_switch(struct kvm_vcpu *vcpu)\n \tidt_index = (vmx-\u003eidt_vectoring_info \u0026 VECTORING_INFO_VECTOR_MASK);\n \ttype = (vmx-\u003eidt_vectoring_info \u0026 VECTORING_INFO_TYPE_MASK);\n \n-\texit_qualification = vmx_get_exit_qual(vcpu);\n+\texit_qualification = vt_get_exit_qual(vcpu);\n \n \treason = (u32)exit_qualification \u003e\u003e 30;\n \tif (reason == TASK_SWITCH_GATE \u0026\u0026 idt_v) {\n@@ -5969,7 +5963,7 @@ static int handle_task_switch(struct kvm_vcpu *vcpu)\n \n static int handle_ept_violation(struct kvm_vcpu *vcpu)\n {\n-\tunsigned long exit_qualification = vmx_get_exit_qual(vcpu);\n+\tunsigned long exit_qualification = vt_get_exit_qual(vcpu);\n \tgpa_t gpa;\n \n \t/*\n@@ -5997,7 +5991,7 @@ static int handle_ept_violation(struct kvm_vcpu *vcpu)\n \tif (unlikely(allow_smaller_maxphyaddr \u0026\u0026 !kvm_vcpu_is_legal_gpa(vcpu, gpa)))\n \t\treturn kvm_emulate_instruction(vcpu, 0);\n \n-\treturn __vmx_handle_ept_violation(vcpu, gpa, exit_qualification);\n+\treturn __vt_handle_ept_violation(vcpu, gpa, exit_qualification);\n }\n \n static int handle_ept_misconfig(struct kvm_vcpu *vcpu)\n@@ -6160,7 +6154,7 @@ static int handle_invpcid(struct kvm_vcpu *vcpu)\n \t/* According to the Intel instruction reference, the memory operand\n \t * is read even if it isn't needed (e.g., for type==all)\n \t */\n-\tif (get_vmx_mem_address(vcpu, vmx_get_exit_qual(vcpu),\n+\tif (get_vmx_mem_address(vcpu, vt_get_exit_qual(vcpu),\n \t\t\t\tvmx_instruction_info, false,\n \t\t\t\tsizeof(operand), \u0026gva))\n \t\treturn 1;\n@@ -6174,7 +6168,7 @@ static int handle_pml_full(struct kvm_vcpu *vcpu)\n \n \ttrace_kvm_pml_full(vcpu-\u003evcpu_id);\n \n-\texit_qualification = vmx_get_exit_qual(vcpu);\n+\texit_qualification = vt_get_exit_qual(vcpu);\n \n \t/*\n \t * PML buffer FULL happened while executing iret from NMI,\n@@ -6278,7 +6272,7 @@ static int handle_bus_lock_vmexit(struct kvm_vcpu *vcpu)\n \n static int handle_notify(struct kvm_vcpu *vcpu)\n {\n-\tunsigned long exit_qual = vmx_get_exit_qual(vcpu);\n+\tunsigned long exit_qual = vt_get_exit_qual(vcpu);\n \tbool context_invalid = exit_qual \u0026 NOTIFY_VM_CONTEXT_INVALID;\n \n \t++vcpu-\u003estat.notify_window_exits;\n@@ -6309,13 +6303,13 @@ static int vmx_get_msr_imm_reg(struct kvm_vcpu *vcpu)\n \n static int handle_rdmsr_imm(struct kvm_vcpu *vcpu)\n {\n-\treturn kvm_emulate_rdmsr_imm(vcpu, vmx_get_exit_qual(vcpu),\n+\treturn kvm_emulate_rdmsr_imm(vcpu, vt_get_exit_qual(vcpu),\n \t\t\t\t vmx_get_msr_imm_reg(vcpu));\n }\n \n static int handle_wrmsr_imm(struct kvm_vcpu *vcpu)\n {\n-\treturn kvm_emulate_wrmsr_imm(vcpu, vmx_get_exit_qual(vcpu),\n+\treturn kvm_emulate_wrmsr_imm(vcpu, vt_get_exit_qual(vcpu),\n \t\t\t\t vmx_get_msr_imm_reg(vcpu));\n }\n \n@@ -6392,10 +6386,10 @@ void vmx_get_exit_info(struct kvm_vcpu *vcpu, u32 *reason,\n \tstruct vcpu_vmx *vmx = to_vmx(vcpu);\n \n \t*reason = vmx-\u003evt.exit_reason.full;\n-\t*info1 = vmx_get_exit_qual(vcpu);\n+\t*info1 = vt_get_exit_qual(vcpu);\n \tif (!(vmx-\u003evt.exit_reason.failed_vmentry)) {\n \t\t*info2 = vmx-\u003eidt_vectoring_info;\n-\t\t*intr_info = vmx_get_intr_info(vcpu);\n+\t\t*intr_info = vt_get_intr_info(vcpu);\n \t\tif (is_exception_with_error_code(*intr_info))\n \t\t\t*error_code = vmcs_read32(VM_EXIT_INTR_ERROR_CODE);\n \t\telse\n@@ -6706,7 +6700,7 @@ void dump_vmcs(struct kvm_vcpu *vcpu)\n static int __vmx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t exit_fastpath)\n {\n \tstruct vcpu_vmx *vmx = to_vmx(vcpu);\n-\tunion vmx_exit_reason exit_reason = vmx_get_exit_reason(vcpu);\n+\tunion vmx_exit_reason exit_reason = vt_get_exit_reason(vcpu);\n \tu32 vectoring_info = vmx-\u003eidt_vectoring_info;\n \tu16 exit_handler_index;\n \n@@ -6870,7 +6864,7 @@ int vmx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t exit_fastpath)\n \t * Exit to user space when bus lock detected to inform that there is\n \t * a bus lock in guest.\n \t */\n-\tif (vmx_get_exit_reason(vcpu).bus_lock_detected) {\n+\tif (vt_get_exit_reason(vcpu).bus_lock_detected) {\n \t\tif (ret \u003e 0)\n \t\t\tvcpu-\u003erun-\u003eexit_reason = KVM_EXIT_X86_BUS_LOCK;\n \n@@ -7143,74 +7137,6 @@ void vmx_load_eoi_exitmap(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap)\n \tvmcs_write64(EOI_EXIT_BITMAP3, eoi_exit_bitmap[3]);\n }\n \n-static void handle_nm_fault_irqoff(struct kvm_vcpu *vcpu)\n-{\n-\t/*\n-\t * Save xfd_err to guest_fpu before interrupt is enabled, so the\n-\t * MSR value is not clobbered by the host activity before the guest\n-\t * has chance to consume it.\n-\t *\n-\t * Update the guest's XFD_ERR if and only if XFD is enabled, as the #NM\n-\t * interception may have been caused by L1 interception. Per the SDM,\n-\t * XFD_ERR is not modified for non-XFD #NM, i.e. if CR0.TS=1.\n-\t *\n-\t * Note, XFD_ERR is updated _before_ the #NM interception check, i.e.\n-\t * unlike CR2 and DR6, the value is not a payload that is attached to\n-\t * the #NM exception.\n-\t */\n-\tif (is_xfd_nm_fault(vcpu))\n-\t\trdmsrq(MSR_IA32_XFD_ERR, vcpu-\u003earch.guest_fpu.xfd_err);\n-}\n-\n-static void handle_exception_irqoff(struct kvm_vcpu *vcpu, u32 intr_info)\n-{\n-\t/* if exit due to PF check for async PF */\n-\tif (is_page_fault(intr_info))\n-\t\tvcpu-\u003earch.apf.host_apf_flags = kvm_read_and_reset_apf_flags();\n-\t/* if exit due to NM, handle before interrupts are enabled */\n-\telse if (is_nm_fault(intr_info))\n-\t\thandle_nm_fault_irqoff(vcpu);\n-\t/* Handle machine checks before interrupts are enabled */\n-\telse if (is_machine_check(intr_info))\n-\t\tkvm_machine_check();\n-}\n-\n-static void handle_external_interrupt_irqoff(struct kvm_vcpu *vcpu,\n-\t\t\t\t\t u32 intr_info)\n-{\n-\tunsigned int vector = intr_info \u0026 INTR_INFO_VECTOR_MASK;\n-\n-\tif (KVM_BUG(!is_external_intr(intr_info), vcpu-\u003ekvm,\n-\t \"unexpected VM-Exit interrupt info: 0x%x\", intr_info))\n-\t\treturn;\n-\n-\tkvm_before_interrupt(vcpu, KVM_HANDLING_IRQ);\n-\tx86_entry_from_kvm(EVENT_TYPE_EXTINT, vector);\n-\tkvm_after_interrupt(vcpu);\n-\n-\tvcpu-\u003earch.at_instruction_boundary = true;\n-}\n-\n-void vmx_handle_exit_irqoff(struct kvm_vcpu *vcpu)\n-{\n-\tif (to_vt(vcpu)-\u003eemulation_required)\n-\t\treturn;\n-\n-\tswitch (vmx_get_exit_reason(vcpu).basic) {\n-\tcase EXIT_REASON_EXTERNAL_INTERRUPT:\n-\t\thandle_external_interrupt_irqoff(vcpu, vmx_get_intr_info(vcpu));\n-\t\tbreak;\n-\tcase EXIT_REASON_EXCEPTION_NMI:\n-\t\thandle_exception_irqoff(vcpu, vmx_get_intr_info(vcpu));\n-\t\tbreak;\n-\tcase EXIT_REASON_MCE_DURING_VMENTRY:\n-\t\tkvm_machine_check();\n-\t\tbreak;\n-\tdefault:\n-\t\tbreak;\n-\t}\n-}\n-\n /*\n * The kvm parameter can be NULL (module initialization, or invocation before\n * VM creation). Be sure to check the kvm parameter before using it.\n@@ -7250,7 +7176,7 @@ static void vmx_recover_nmi_blocking(struct vcpu_vmx *vmx)\n \t\tif (vmx-\u003eloaded_vmcs-\u003enmi_known_unmasked)\n \t\t\treturn;\n \n-\t\texit_intr_info = vmx_get_intr_info(\u0026vmx-\u003evcpu);\n+\t\texit_intr_info = vt_get_intr_info(\u0026vmx-\u003evcpu);\n \t\tunblock_nmi = (exit_intr_info \u0026 INTR_INFO_UNBLOCK_NMI) != 0;\n \t\tvector = exit_intr_info \u0026 INTR_INFO_VECTOR_MASK;\n \t\t/*\n@@ -7417,14 +7343,14 @@ static fastpath_t vmx_exit_handlers_fastpath(struct kvm_vcpu *vcpu,\n \t * the fastpath even, all other exits must use the slow path.\n \t */\n \tif (is_guest_mode(vcpu) \u0026\u0026\n-\t vmx_get_exit_reason(vcpu).basic != EXIT_REASON_PREEMPTION_TIMER)\n+\t vt_get_exit_reason(vcpu).basic != EXIT_REASON_PREEMPTION_TIMER)\n \t\treturn EXIT_FASTPATH_NONE;\n \n-\tswitch (vmx_get_exit_reason(vcpu).basic) {\n+\tswitch (vt_get_exit_reason(vcpu).basic) {\n \tcase EXIT_REASON_MSR_WRITE:\n \t\treturn handle_fastpath_wrmsr(vcpu);\n \tcase EXIT_REASON_MSR_WRITE_IMM:\n-\t\treturn handle_fastpath_wrmsr_imm(vcpu, vmx_get_exit_qual(vcpu),\n+\t\treturn handle_fastpath_wrmsr_imm(vcpu, vt_get_exit_qual(vcpu),\n \t\t\t\t\t\t vmx_get_msr_imm_reg(vcpu));\n \tcase EXIT_REASON_PREEMPTION_TIMER:\n \t\treturn handle_fastpath_preemption_timer(vcpu, force_immediate_exit);\n@@ -7437,17 +7363,6 @@ static fastpath_t vmx_exit_handlers_fastpath(struct kvm_vcpu *vcpu,\n \t}\n }\n \n-noinstr void vmx_handle_nmi(struct kvm_vcpu *vcpu)\n-{\n-\tif ((u16)vmx_get_exit_reason(vcpu).basic != EXIT_REASON_EXCEPTION_NMI ||\n-\t !is_nmi(vmx_get_intr_info(vcpu)))\n-\t\treturn;\n-\n-\tkvm_before_interrupt(vcpu, KVM_HANDLING_NMI);\n-\tx86_entry_from_kvm(EVENT_TYPE_NMI, NMI_VECTOR);\n-\tkvm_after_interrupt(vcpu);\n-}\n-\n static noinstr void vmx_vcpu_enter_exit(struct kvm_vcpu *vcpu,\n \t\t\t\t\tunsigned int flags)\n {\n@@ -7477,10 +7392,10 @@ static noinstr void vmx_vcpu_enter_exit(struct kvm_vcpu *vcpu,\n \t}\n \n \tvmx-\u003evt.exit_reason.full = vmcs_read32(VM_EXIT_REASON);\n-\tif (likely(!vmx_get_exit_reason(vcpu).failed_vmentry))\n+\tif (likely(!vt_get_exit_reason(vcpu).failed_vmentry))\n \t\tvmx-\u003eidt_vectoring_info = vmcs_read32(IDT_VECTORING_INFO_FIELD);\n \n-\tvmx_handle_nmi(vcpu);\n+\tvt_handle_nmi(vcpu);\n \n out:\n \tguest_state_exit_irqoff();\n@@ -7617,7 +7532,7 @@ fastpath_t vmx_vcpu_run(struct kvm_vcpu *vcpu, u64 run_flags)\n \t\t * checking.\n \t\t */\n \t\tif (vcpu-\u003earch.nested_run_pending \u0026\u0026\n-\t\t !vmx_get_exit_reason(vcpu).failed_vmentry)\n+\t\t !vt_get_exit_reason(vcpu).failed_vmentry)\n \t\t\t++vcpu-\u003estat.nested_run;\n \n \t\tvcpu-\u003earch.nested_run_pending = 0;\n@@ -7628,7 +7543,7 @@ fastpath_t vmx_vcpu_run(struct kvm_vcpu *vcpu, u64 run_flags)\n \n \ttrace_kvm_exit(vcpu, KVM_ISA_VMX);\n \n-\tif (unlikely(vmx_get_exit_reason(vcpu).failed_vmentry))\n+\tif (unlikely(vt_get_exit_reason(vcpu).failed_vmentry))\n \t\treturn EXIT_FASTPATH_NONE;\n \n \tvmx-\u003eloaded_vmcs-\u003elaunched = 1;\ndiff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h\nindex dc8517f15bc46..3247b55b34843 100644\n--- a/arch/x86/kvm/vmx/vmx.h\n+++ b/arch/x86/kvm/vmx/vmx.h\n@@ -304,43 +304,6 @@ struct kvm_vmx {\n \tu64 *pid_table;\n };\n \n-static __always_inline struct vcpu_vt *to_vt(struct kvm_vcpu *vcpu)\n-{\n-\treturn \u0026(container_of(vcpu, struct vcpu_vmx, vcpu)-\u003evt);\n-}\n-\n-static __always_inline struct kvm_vcpu *vt_to_vcpu(struct vcpu_vt *vt)\n-{\n-\treturn \u0026(container_of(vt, struct vcpu_vmx, vt)-\u003evcpu);\n-}\n-\n-static __always_inline union vmx_exit_reason vmx_get_exit_reason(struct kvm_vcpu *vcpu)\n-{\n-\treturn to_vt(vcpu)-\u003eexit_reason;\n-}\n-\n-static __always_inline unsigned long vmx_get_exit_qual(struct kvm_vcpu *vcpu)\n-{\n-\tstruct vcpu_vt *vt = to_vt(vcpu);\n-\n-\tif (!kvm_register_test_and_mark_available(vcpu, VCPU_REG_EXIT_INFO_1) \u0026\u0026\n-\t !WARN_ON_ONCE(is_td_vcpu(vcpu)))\n-\t\tvt-\u003eexit_qualification = vmcs_readl(EXIT_QUALIFICATION);\n-\n-\treturn vt-\u003eexit_qualification;\n-}\n-\n-static __always_inline u32 vmx_get_intr_info(struct kvm_vcpu *vcpu)\n-{\n-\tstruct vcpu_vt *vt = to_vt(vcpu);\n-\n-\tif (!kvm_register_test_and_mark_available(vcpu, VCPU_REG_EXIT_INFO_2) \u0026\u0026\n-\t !WARN_ON_ONCE(is_td_vcpu(vcpu)))\n-\t\tvt-\u003eexit_intr_info = vmcs_read32(VM_EXIT_INTR_INFO);\n-\n-\treturn vt-\u003eexit_intr_info;\n-}\n-\n void vmx_vcpu_load_vmcs(struct kvm_vcpu *vcpu, int cpu);\n int allocate_vpid(void);\n void free_vpid(int vpid);\ndiff --git a/arch/x86/kvm/vmx/x86_ops.h b/arch/x86/kvm/vmx/x86_ops.h\nindex 054fd14bb2e16..7ac02c68457f1 100644\n--- a/arch/x86/kvm/vmx/x86_ops.h\n+++ b/arch/x86/kvm/vmx/x86_ops.h\n@@ -27,7 +27,6 @@ void vmx_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event);\n void vmx_vcpu_load(struct kvm_vcpu *vcpu, int cpu);\n void vmx_vcpu_put(struct kvm_vcpu *vcpu);\n int vmx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t exit_fastpath);\n-void vmx_handle_exit_irqoff(struct kvm_vcpu *vcpu);\n int vmx_skip_emulated_instruction(struct kvm_vcpu *vcpu);\n void vmx_update_emulated_instruction(struct kvm_vcpu *vcpu);\n bool vmx_unhandleable_emulation_required(struct kvm_vcpu *vcpu);\n"
} |
| 2/1 | 2026/09/05 09:24 | agent | patch-evaluator |
0mModel:core Args: null Results: {
"EnableConfigs": [
"KVM",
"KVM_INTEL"
],
"FocusSymbols": [
"vt_handle_exit_irqoff",
"vt_handle_nmi",
"vt_vcpu_pi_load",
"vt_vcpu_pi_put",
"vt_pi_start_bypass",
"vt_pi_update_irte",
"vmx_handle_exit",
"vmx_vcpu_run",
"nested_vmx_reflect_vmexit"
],
"Reasoning": "The patch refactors KVM Intel (VMX/TDX) virtualization logic by consolidating exit status handling, exit IRQ-off processing, posted interrupt helpers, and VMCS exit qualification accessors under common vt_* abstractions. This affects core KVM VM exit handling and nested virtualization reachable on amd64.",
"WorthFuzzing": true
}Instruction: You are an expert Linux kernel maintainer and security engineer.
Your job is to review a provided patch series and evaluate whether it warrants fuzzing with syzkaller.
IMPORTANT: The changes have ALREADY been applied and committed as the HEAD commit in
your workspace. Do NOT rely on internal assumptions. You must actively use your code access
tools to inspect the actual source code, callers, and surrounding context.
================================================================================
1. CORE TRIAGE PHILOSOPHY
================================================================================
The goal of patch fuzzing is to discover crashes, regressions, exposed latent bugs,
and newly triggered assertions introduced by the patch series.
- REACHABILITY IS THE PRIMARY GATE:
Fuzzing can only discover bugs in code that can actually execute in standard virtualized
environments (GCE or QEMU, utilizing software-emulated devices like USB gadgets, netdev, tun/tap).
If the modified code is structurally unreachable (see Section 2), it MUST NOT be fuzzed,
regardless of whether it adds assertions or complex logic.
- DO NOT BLINDLY TRUST "NO FUNCTIONAL CHANGE" (NFCI) OR "REFACTORING" CLAIMS:
Patch authors routinely label changes as "cleanups", "refactorings", or state
"No functional change intended". Do NOT take these claims at face value.
Code refactorings that rearrange logic, introduce helper functions, or alter state management
in core subsystems frequently introduce subtle semantic shifts or uncover latent kernel bugs.
If reachable executable code is modified or refactored, it MUST be fuzzed.
- NEW OR MODIFIED ASSERTIONS IN REACHABLE CODE MUST BE FUZZED:
When a patch introduces or modifies runtime checks or assertions (e.g., WARN_ON*, VM_WARN_ON*,
BUG_ON*, lockdep_assert*) in reachable code paths, it enforces new or stricter invariants.
Even if the author believes the invariant always holds, fuzzing is essential to verify whether
an unusual sequence of operations can violate it.
================================================================================
2. WHEN TO RETURN WorthFuzzing=false (NEGATIVE CRITERIA)
================================================================================
Return WorthFuzzing=false ONLY IF all modified code falls strictly into one or more of these categories:
- Non-kernel and non-executable changes:
* Modifications to Documentation/, comments, or spelling fixes.
* User-space directories, self-tests, samples, or scripts (e.g., tools/, samples/, scripts/, usr/)
that do not affect the compiled kernel image (vmlinux) or kernel modules.
* Purely decorative logging (e.g., message strings in pr_err, printk, dev_info) or tracepoints
that do not alter control flow or data structures.
* Build system or Kconfig changes that do not alter compiled C logic.
- Structurally unreachable hardware:
* Vendor-specific PCIe switches, SmartNICs, or GPU drivers (e.g., mlxsw, pds_core, qed,
ionic, amdgpu) requiring physical ASIC/PCIe cards not emulated in standard QEMU.
- Unreachable execution paths:
* Driver teardown callbacks (.remove, .shutdown, pci_unregister_driver) executed only during
physical PCI hot-unplug or manual sysfs driver unbinding.
* Code paths exclusive to architectures other than the target architecture.
================================================================================
3. WHEN TO RETURN WorthFuzzing=true (POSITIVE CRITERIA)
================================================================================
Return WorthFuzzing=true whenever the patch touches reachable executable code, including:
- Core Subsystems:
* Any logic modifications in memory management (mm/), synchronization/locking (kernel/locking/),
BPF, scheduler, core networking, VFS, or syscall handling.
- Refactorings and Code Cleanups:
* Any restructuring of reachable data structures, helper abstractions, or algorithm flows.
- Runtime Assertions and Defensive Checks:
* Any introduction or alteration of assertions (WARN_ON*, VM_WARN_ON*, BUG_ON*, etc.) in reachable paths.
- Reachable Drivers and Protocols:
* Drivers accessible via virtual buses (virtio, USB gadget, loopback, netlink, binder, sockets, etc.).
================================================================================
4. EXTRACTING FocusSymbols (PREVENTING DILUTION)
================================================================================
When WorthFuzzing=true, you must extract specific kernel functions into FocusSymbols to guide the fuzzer:
- AVOID UBIQUITOUS LIFECYCLE HOT-PATHS:
Do NOT list generic, ubiquitous functions called by almost every program in the corpus
(including, but not limited to: general memory allocators and deallocators, page fault
and trap handlers, or core synchronization primitives; this is not an exhaustive list).
Listing ubiquitous functions causes the fuzzer to classify thousands of unrelated tests as "focused",
which severely dilutes fuzzing effort away from the actual changes.
- TARGET SPECIFIC FEATURE LOGIC AND ENTRYPOINTS:
List functions that specifically implement the logic being added or altered, or direct API entrypoints
for the subsystem feature under review.
- HANDLING STATIC INLINE FUNCTIONS IN HEADERS (.h):
Compiler-inlined static functions (such as static inlines in mm/*.h or include/linux/*.h) lack
distinct symbol addresses in vmlinux and cannot be targeted directly by symbol coverage filters.
If the changes are primarily in static inline helpers, identify non-static, feature-specific caller
functions in .c files that exercise them (avoiding ubiquitous lifecycle wrappers).
================================================================================
5. IDENTIFYING EnableConfigs
================================================================================
Identify any specific CONFIG_ options required to properly compile and reach the modified code:
- Inspect Kconfig files and #ifdef guards; do not make assumptions.
- Check "depends on" lines in Kconfig to include any non-standard parent subsystem configs needed.
- Strip any 'CONFIG_' prefix (e.g., return "NET_IPV4" instead of "CONFIG_NET_IPV4").
Prefer calling several tools at the same time to save round-trips.
Use set-results tool to provide results of the analysis.
It must be called exactly once before the final reply.
Ignore results of this tool.
Prompt: Target architecture: amd64
For your convenience, here is the diff of the changes:
commit 9d25f06a93aabe64fbad0ded74f73000f4a47cc3
Author: syz-cluster <triage@syzkaller.com>
Date: Sat Sep 5 09:24:22 2026 +0000
syz-cluster: applied patch under review
diff --git a/arch/x86/kvm/vmx/common.h b/arch/x86/kvm/vmx/common.h
index 08005676702c2..3e68fa12aca65 100644
--- a/arch/x86/kvm/vmx/common.h
+++ b/arch/x86/kvm/vmx/common.h
@@ -2,10 +2,12 @@
#ifndef __KVM_X86_VMX_COMMON_H
#define __KVM_X86_VMX_COMMON_H
+#include <linux/container_of.h>
#include <linux/kvm_host.h>
#include <asm/posted_intr.h>
#include "mmu.h"
+#include "vmx_ops.h"
union vmx_exit_reason {
struct {
@@ -74,14 +76,62 @@ static __always_inline bool is_td_vcpu(struct kvm_vcpu *vcpu) { return false; }
#endif
+struct vcpu_vmx_tdx {
+ struct kvm_vcpu vcpu;
+ struct vcpu_vt vt;
+};
+
+static __always_inline struct vcpu_vt *to_vt(struct kvm_vcpu *vcpu)
+{
+ return &(container_of(vcpu, struct vcpu_vmx_tdx, vcpu)->vt);
+}
+
+static __always_inline struct kvm_vcpu *vt_to_vcpu(struct vcpu_vt *vt)
+{
+ return &(container_of(vt, struct vcpu_vmx_tdx, vt)->vcpu);
+}
+
+static __always_inline union vmx_exit_reason vt_get_exit_reason(struct kvm_vcpu *vcpu)
+{
+ return to_vt(vcpu)->exit_reason;
+}
+
+static __always_inline unsigned long vt_get_exit_qual(struct kvm_vcpu *vcpu)
+{
+ struct vcpu_vt *vt = to_vt(vcpu);
+
+ if (!kvm_register_test_and_mark_available(vcpu, VCPU_REG_EXIT_INFO_1) &&
+ !WARN_ON_ONCE(is_td_vcpu(vcpu)))
+ vt->exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
+
+ return vt->exit_qualification;
+}
+
+static __always_inline u32 vt_get_intr_info(struct kvm_vcpu *vcpu)
+{
+ struct vcpu_vt *vt = to_vt(vcpu);
+
+ if (!kvm_register_test_and_mark_available(vcpu, VCPU_REG_EXIT_INFO_2) &&
+ !WARN_ON_ONCE(is_td_vcpu(vcpu)))
+ vt->exit_intr_info = vmcs_read32(VM_EXIT_INTR_INFO);
+
+ return vt->exit_intr_info;
+}
+
+static inline bool is_xfd_nm_fault(struct kvm_vcpu *vcpu)
+{
+ return vcpu->arch.guest_fpu.fpstate->xfd &&
+ !kvm_is_cr0_bit_set(vcpu, X86_CR0_TS);
+}
+
static inline bool vt_is_tdx_private_gpa(struct kvm *kvm, gpa_t gpa)
{
/* For TDX the direct mask is the shared mask. */
return !kvm_is_addr_direct(kvm, gpa);
}
-static inline int __vmx_handle_ept_violation(struct kvm_vcpu *vcpu, gpa_t gpa,
- unsigned long exit_qualification)
+static inline int __vt_handle_ept_violation(struct kvm_vcpu *vcpu, gpa_t gpa,
+ unsigned long exit_qualification)
{
u64 error_code;
@@ -164,8 +214,8 @@ static inline void kvm_vcpu_trigger_posted_interrupt(struct kvm_vcpu *vcpu,
* Post an interrupt to a vCPU's PIR and trigger the vCPU to process the
* interrupt if necessary.
*/
-static inline void __vmx_deliver_posted_interrupt(struct kvm_vcpu *vcpu,
- struct pi_desc *pi_desc, int vector)
+static inline void __vt_deliver_posted_interrupt(struct kvm_vcpu *vcpu,
+ struct pi_desc *pi_desc, int vector)
{
if (pi_test_and_set_pir(vector, pi_desc))
return;
@@ -183,6 +233,6 @@ static inline void __vmx_deliver_posted_interrupt(struct kvm_vcpu *vcpu,
kvm_vcpu_trigger_posted_interrupt(vcpu, POSTED_INTR_VECTOR);
}
-noinstr void vmx_handle_nmi(struct kvm_vcpu *vcpu);
+noinstr void vt_handle_nmi(struct kvm_vcpu *vcpu);
#endif /* __KVM_X86_VMX_COMMON_H */
diff --git a/arch/x86/kvm/vmx/main.c b/arch/x86/kvm/vmx/main.c
index 4c52ab8d07869..6e0b3959d73ab 100644
--- a/arch/x86/kvm/vmx/main.c
+++ b/arch/x86/kvm/vmx/main.c
@@ -1,4 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
+#include <linux/entry-common.h>
#include <linux/moduleparam.h>
#include "x86_ops.h"
@@ -10,8 +11,12 @@
#include "tdx.h"
#include "tdx_arch.h"
+#pragma GCC poison to_vmx
+
+static_assert(offsetof(struct vcpu_vmx_tdx, vt) == offsetof(struct vcpu_vmx, vt));
+
#ifdef CONFIG_KVM_INTEL_TDX
-static_assert(offsetof(struct vcpu_vmx, vt) == offsetof(struct vcpu_tdx, vt));
+static_assert(offsetof(struct vcpu_vmx_tdx, vt) == offsetof(struct vcpu_tdx, vt));
static void vt_disable_virtualization_cpu(void)
{
@@ -876,6 +881,85 @@ static int vt_gmem_max_mapping_level(struct kvm *kvm, kvm_pfn_t pfn,
#define vt_op_tdx_only(name) NULL
#endif /* CONFIG_KVM_INTEL_TDX */
+static void handle_nm_fault_irqoff(struct kvm_vcpu *vcpu)
+{
+ /*
+ * Save xfd_err to guest_fpu before interrupt is enabled, so the
+ * MSR value is not clobbered by the host activity before the guest
+ * has chance to consume it.
+ *
+ * Update the guest's XFD_ERR if and only if XFD is enabled, as the #NM
+ * interception may have been caused by L1 interception. Per the SDM,
+ * XFD_ERR is not modified for non-XFD #NM, i.e. if CR0.TS=1.
+ *
+ * Note, XFD_ERR is updated _before_ the #NM interception check, i.e.
+ * unlike CR2 and DR6, the value is not a payload that is attached to
+ * the #NM exception.
+ */
+ if (is_xfd_nm_fault(vcpu))
+ rdmsrq(MSR_IA32_XFD_ERR, vcpu->arch.guest_fpu.xfd_err);
+}
+
+static void handle_exception_irqoff(struct kvm_vcpu *vcpu, u32 intr_info)
+{
+ /* if exit due to PF check for async PF */
+ if (is_page_fault(intr_info))
+ vcpu->arch.apf.host_apf_flags = kvm_read_and_reset_apf_flags();
+ /* if exit due to NM, handle before interrupts are enabled */
+ else if (is_nm_fault(intr_info))
+ handle_nm_fault_irqoff(vcpu);
+ /* Handle machine checks before interrupts are enabled */
+ else if (is_machine_check(intr_info))
+ kvm_machine_check();
+}
+
+static void handle_external_interrupt_irqoff(struct kvm_vcpu *vcpu,
+ u32 intr_info)
+{
+ unsigned int vector = intr_info & INTR_INFO_VECTOR_MASK;
+
+ if (KVM_BUG(!is_external_intr(intr_info), vcpu->kvm,
+ "unexpected VM-Exit interrupt info: 0x%x", intr_info))
+ return;
+
+ kvm_before_interrupt(vcpu, KVM_HANDLING_IRQ);
+ x86_entry_from_kvm(EVENT_TYPE_EXTINT, vector);
+ kvm_after_interrupt(vcpu);
+
+ vcpu->arch.at_instruction_boundary = true;
+}
+
+static void vt_handle_exit_irqoff(struct kvm_vcpu *vcpu)
+{
+ if (to_vt(vcpu)->emulation_required)
+ return;
+
+ switch (vt_get_exit_reason(vcpu).basic) {
+ case EXIT_REASON_EXTERNAL_INTERRUPT:
+ handle_external_interrupt_irqoff(vcpu, vt_get_intr_info(vcpu));
+ break;
+ case EXIT_REASON_EXCEPTION_NMI:
+ handle_exception_irqoff(vcpu, vt_get_intr_info(vcpu));
+ break;
+ case EXIT_REASON_MCE_DURING_VMENTRY:
+ kvm_machine_check();
+ break;
+ default:
+ break;
+ }
+}
+
+noinstr void vt_handle_nmi(struct kvm_vcpu *vcpu)
+{
+ if ((u16)vt_get_exit_reason(vcpu).basic != EXIT_REASON_EXCEPTION_NMI ||
+ !is_nmi(vt_get_intr_info(vcpu)))
+ return;
+
+ kvm_before_interrupt(vcpu, KVM_HANDLING_NMI);
+ x86_entry_from_kvm(EVENT_TYPE_NMI, NMI_VECTOR);
+ kvm_after_interrupt(vcpu);
+}
+
#define VMX_REQUIRED_APICV_INHIBITS \
(BIT(APICV_INHIBIT_REASON_DISABLED) | \
BIT(APICV_INHIBIT_REASON_ABSENT) | \
@@ -1000,12 +1084,12 @@ struct kvm_x86_ops vt_x86_ops __initdata = {
.load_mmu_pgd = vt_op(load_mmu_pgd),
.check_intercept = vmx_check_intercept,
- .handle_exit_irqoff = vmx_handle_exit_irqoff,
+ .handle_exit_irqoff = vt_handle_exit_irqoff,
.update_cpu_dirty_logging = vt_op(update_cpu_dirty_logging),
- .pi_update_irte = vmx_pi_update_irte,
- .pi_start_bypass = vmx_pi_start_bypass,
+ .pi_update_irte = vt_pi_update_irte,
+ .pi_start_bypass = vt_pi_start_bypass,
#ifdef CONFIG_X86_64
.set_hv_timer = vt_op(set_hv_timer),
diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c
index 151873407abd3..47599e7312cfd 100644
--- a/arch/x86/kvm/vmx/nested.c
+++ b/arch/x86/kvm/vmx/nested.c
@@ -446,7 +446,7 @@ static void nested_ept_inject_page_fault(struct kvm_vcpu *vcpu,
* "NMI unblocking due to IRET", i.e. the bit can be propagated
* as-is from the original EXIT_QUALIFICATION.
*/
- exit_qualification = vmx_get_exit_qual(vcpu) & INTR_INFO_UNBLOCK_NMI;
+ exit_qualification = vt_get_exit_qual(vcpu) & INTR_INFO_UNBLOCK_NMI;
} else {
if (fault->error_code & PFERR_RSVD_MASK) {
vm_exit_reason = EXIT_REASON_EPT_MISCONFIG;
@@ -472,7 +472,7 @@ static void nested_ept_inject_page_fault(struct kvm_vcpu *vcpu,
* and walks the faulting GPA.
*/
if (from_hardware)
- exit_qualification |= vmx_get_exit_qual(vcpu) & mask;
+ exit_qualification |= vt_get_exit_qual(vcpu) & mask;
else
exit_qualification |= fault->exit_qualification & mask;
@@ -4747,7 +4747,7 @@ static void prepare_vmcs12(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12,
{
/* update exit information fields: */
vmcs12->vm_exit_reason = vm_exit_reason;
- if (vmx_get_exit_reason(vcpu).enclave_mode)
+ if (vt_get_exit_reason(vcpu).enclave_mode)
vmcs12->vm_exit_reason |= VMX_EXIT_REASONS_SGX_ENCLAVE_MODE;
vmcs12->exit_qualification = exit_qualification;
@@ -5373,7 +5373,7 @@ static int nested_vmx_get_vmptr(struct kvm_vcpu *vcpu, gpa_t *vmpointer,
struct x86_exception e;
int r;
- if (get_vmx_mem_address(vcpu, vmx_get_exit_qual(vcpu),
+ if (get_vmx_mem_address(vcpu, vt_get_exit_qual(vcpu),
vmcs_read32(VMX_INSTRUCTION_INFO), false,
sizeof(*vmpointer), &gva)) {
*ret = 1;
@@ -5665,7 +5665,7 @@ static int handle_vmread(struct kvm_vcpu *vcpu)
{
struct vmcs12 *vmcs12 = is_guest_mode(vcpu) ? get_shadow_vmcs12(vcpu)
: get_vmcs12(vcpu);
- unsigned long exit_qualification = vmx_get_exit_qual(vcpu);
+ unsigned long exit_qualification = vt_get_exit_qual(vcpu);
u32 instr_info = vmcs_read32(VMX_INSTRUCTION_INFO);
struct vcpu_vmx *vmx = to_vmx(vcpu);
struct x86_exception e;
@@ -5771,7 +5771,7 @@ static int handle_vmwrite(struct kvm_vcpu *vcpu)
{
struct vmcs12 *vmcs12 = is_guest_mode(vcpu) ? get_shadow_vmcs12(vcpu)
: get_vmcs12(vcpu);
- unsigned long exit_qualification = vmx_get_exit_qual(vcpu);
+ unsigned long exit_qualification = vt_get_exit_qual(vcpu);
u32 instr_info = vmcs_read32(VMX_INSTRUCTION_INFO);
struct vcpu_vmx *vmx = to_vmx(vcpu);
struct x86_exception e;
@@ -5960,7 +5960,7 @@ static int handle_vmptrld(struct kvm_vcpu *vcpu)
/* Emulate the VMPTRST instruction */
static int handle_vmptrst(struct kvm_vcpu *vcpu)
{
- unsigned long exit_qual = vmx_get_exit_qual(vcpu);
+ unsigned long exit_qual = vt_get_exit_qual(vcpu);
u32 instr_info = vmcs_read32(VMX_INSTRUCTION_INFO);
gpa_t current_vmptr = to_vmx(vcpu)->nested.current_vmptr;
struct x86_exception e;
@@ -6021,7 +6021,7 @@ static int handle_invept(struct kvm_vcpu *vcpu)
/* According to the Intel VMX instruction reference, the memory
* operand is read even if it isn't needed (e.g., for type==global)
*/
- if (get_vmx_mem_address(vcpu, vmx_get_exit_qual(vcpu),
+ if (get_vmx_mem_address(vcpu, vt_get_exit_qual(vcpu),
vmx_instruction_info, false, sizeof(operand), &gva))
return 1;
r = kvm_read_guest_virt(vcpu, gva, &operand, sizeof(operand), &e);
@@ -6104,7 +6104,7 @@ static int handle_invvpid(struct kvm_vcpu *vcpu)
/* according to the intel vmx instruction reference, the memory
* operand is read even if it isn't needed (e.g., for type==global)
*/
- if (get_vmx_mem_address(vcpu, vmx_get_exit_qual(vcpu),
+ if (get_vmx_mem_address(vcpu, vt_get_exit_qual(vcpu),
vmx_instruction_info, false, sizeof(operand), &gva))
return 1;
r = kvm_read_guest_virt(vcpu, gva, &operand, sizeof(operand), &e);
@@ -6236,8 +6236,8 @@ static int handle_vmfunc(struct kvm_vcpu *vcpu)
* EXIT_REASON_VMFUNC as the exit reason.
*/
nested_vmx_vmexit(vcpu, vmx->vt.exit_reason.full,
- vmx_get_intr_info(vcpu),
- vmx_get_exit_qual(vcpu));
+ vt_get_intr_info(vcpu),
+ vt_get_exit_qual(vcpu));
return 1;
}
@@ -6288,7 +6288,7 @@ static bool nested_vmx_exit_handled_io(struct kvm_vcpu *vcpu,
if (!nested_cpu_has(vmcs12, CPU_BASED_USE_IO_BITMAPS))
return nested_cpu_has(vmcs12, CPU_BASED_UNCOND_IO_EXITING);
- exit_qualification = vmx_get_exit_qual(vcpu);
+ exit_qualification = vt_get_exit_qual(vcpu);
port = exit_qualification >> 16;
size = (exit_qualification & 7) + 1;
@@ -6314,7 +6314,7 @@ static bool nested_vmx_exit_handled_msr(struct kvm_vcpu *vcpu,
if (exit_reason.basic == EXIT_REASON_MSR_READ_IMM ||
exit_reason.basic == EXIT_REASON_MSR_WRITE_IMM)
- msr_index = vmx_get_exit_qual(vcpu);
+ msr_index = vt_get_exit_qual(vcpu);
else
msr_index = kvm_ecx_read(vcpu);
@@ -6350,7 +6350,7 @@ static bool nested_vmx_exit_handled_msr(struct kvm_vcpu *vcpu,
static bool nested_vmx_exit_handled_cr(struct kvm_vcpu *vcpu,
struct vmcs12 *vmcs12)
{
- unsigned long exit_qualification = vmx_get_exit_qual(vcpu);
+ unsigned long exit_qualification = vt_get_exit_qual(vcpu);
int cr = exit_qualification & 15;
int reg;
unsigned long val;
@@ -6484,7 +6484,7 @@ static bool nested_vmx_l0_wants_exit(struct kvm_vcpu *vcpu,
switch ((u16)exit_reason.basic) {
case EXIT_REASON_EXCEPTION_NMI:
- intr_info = vmx_get_intr_info(vcpu);
+ intr_info = vt_get_intr_info(vcpu);
if (is_nmi(intr_info))
return true;
else if (is_page_fault(intr_info))
@@ -6567,7 +6567,7 @@ static bool nested_vmx_l1_wants_exit(struct kvm_vcpu *vcpu,
switch ((u16)exit_reason.basic) {
case EXIT_REASON_EXCEPTION_NMI:
- intr_info = vmx_get_intr_info(vcpu);
+ intr_info = vt_get_intr_info(vcpu);
if (is_nmi(intr_info))
return true;
else if (is_page_fault(intr_info))
@@ -6737,14 +6737,14 @@ bool nested_vmx_reflect_vmexit(struct kvm_vcpu *vcpu)
* need to be synthesized by querying the in-kernel LAPIC, but external
* interrupts are never reflected to L1 so it's a non-issue.
*/
- exit_intr_info = vmx_get_intr_info(vcpu);
+ exit_intr_info = vt_get_intr_info(vcpu);
if (is_exception_with_error_code(exit_intr_info)) {
struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
vmcs12->vm_exit_intr_error_code =
vmcs_read32(VM_EXIT_INTR_ERROR_CODE);
}
- exit_qual = vmx_get_exit_qual(vcpu);
+ exit_qual = vt_get_exit_qual(vcpu);
reflect_vmexit:
nested_vmx_vmexit(vcpu, exit_reason.full, exit_intr_info, exit_qual);
diff --git a/arch/x86/kvm/vmx/posted_intr.c b/arch/x86/kvm/vmx/posted_intr.c
index 4a6d9a17da238..2644add54b76b 100644
--- a/arch/x86/kvm/vmx/posted_intr.c
+++ b/arch/x86/kvm/vmx/posted_intr.c
@@ -14,6 +14,8 @@
#include "vmx.h"
#include "tdx.h"
+#pragma GCC poison to_vmx
+
/*
* Maintain a per-CPU list of vCPUs that need to be awakened by wakeup_handler()
* when a WAKEUP_VECTOR interrupted is posted. vCPUs are added to the list when
@@ -54,7 +56,7 @@ static int pi_try_set_control(struct pi_desc *pi_desc, u64 *pold, u64 new)
return 0;
}
-void vmx_vcpu_pi_load(struct kvm_vcpu *vcpu, int cpu)
+void vt_vcpu_pi_load(struct kvm_vcpu *vcpu, int cpu)
{
struct pi_desc *pi_desc = vcpu_to_pi_desc(vcpu);
struct vcpu_vt *vt = to_vt(vcpu);
@@ -144,11 +146,11 @@ void vmx_vcpu_pi_load(struct kvm_vcpu *vcpu, int cpu)
pi_set_on(pi_desc);
}
-static bool vmx_can_use_vtd_pi(struct kvm *kvm)
+static bool vt_can_use_vtd_pi(struct kvm *kvm)
{
/*
* Note, reading the number of possible bypass IRQs can race with a
- * bypass IRQ being attached to the VM. vmx_pi_start_bypass() ensures
+ * bypass IRQ being attached to the VM. vt_pi_start_bypass() ensures
* blockng vCPUs will see an elevated count or get KVM_REQ_UNBLOCK.
*/
return irqchip_in_kernel(kvm) && kvm_arch_has_irq_bypass() &&
@@ -206,7 +208,7 @@ static void pi_enable_wakeup_handler(struct kvm_vcpu *vcpu)
__apic_send_IPI_self(POSTED_INTR_WAKEUP_VECTOR);
}
-static bool vmx_needs_pi_wakeup(struct kvm_vcpu *vcpu)
+static bool vt_needs_pi_wakeup(struct kvm_vcpu *vcpu)
{
/*
* The default posted interrupt vector does nothing when
@@ -217,14 +219,14 @@ static bool vmx_needs_pi_wakeup(struct kvm_vcpu *vcpu)
* back to the pi_wakeup_handler() function.
*/
return (vmx_can_use_ipiv(vcpu) && !is_td_vcpu(vcpu)) ||
- vmx_can_use_vtd_pi(vcpu->kvm);
+ vt_can_use_vtd_pi(vcpu->kvm);
}
-void vmx_vcpu_pi_put(struct kvm_vcpu *vcpu)
+void vt_vcpu_pi_put(struct kvm_vcpu *vcpu)
{
struct pi_desc *pi_desc = vcpu_to_pi_desc(vcpu);
- if (!vmx_needs_pi_wakeup(vcpu))
+ if (!vt_needs_pi_wakeup(vcpu))
return;
/*
@@ -292,17 +294,17 @@ bool pi_has_pending_interrupt(struct kvm_vcpu *vcpu)
/*
* Kick all vCPUs when the first possible bypass IRQ is attached to a VM, as
* blocking vCPUs may scheduled out without reconfiguring PID.NV to the wakeup
- * vector, i.e. if the bypass IRQ came along after vmx_vcpu_pi_put().
+ * vector, i.e. if the bypass IRQ came along after vt_vcpu_pi_put().
*/
-void vmx_pi_start_bypass(struct kvm *kvm)
+void vt_pi_start_bypass(struct kvm *kvm)
{
- if (WARN_ON_ONCE(!vmx_can_use_vtd_pi(kvm)))
+ if (WARN_ON_ONCE(!vt_can_use_vtd_pi(kvm)))
return;
kvm_make_all_cpus_request(kvm, KVM_REQ_UNBLOCK);
}
-int vmx_pi_update_irte(struct kvm_kernel_irqfd *irqfd, struct kvm *kvm,
+int vt_pi_update_irte(struct kvm_kernel_irqfd *irqfd, struct kvm *kvm,
unsigned int host_irq, uint32_t guest_irq,
struct kvm_vcpu *vcpu, u32 vector)
{
diff --git a/arch/x86/kvm/vmx/posted_intr.h b/arch/x86/kvm/vmx/posted_intr.h
index a4af39948cf04..c5860ea828ae9 100644
--- a/arch/x86/kvm/vmx/posted_intr.h
+++ b/arch/x86/kvm/vmx/posted_intr.h
@@ -8,16 +8,16 @@
#include <asm/posted_intr.h>
-void vmx_vcpu_pi_load(struct kvm_vcpu *vcpu, int cpu);
-void vmx_vcpu_pi_put(struct kvm_vcpu *vcpu);
+void vt_vcpu_pi_load(struct kvm_vcpu *vcpu, int cpu);
+void vt_vcpu_pi_put(struct kvm_vcpu *vcpu);
void pi_wakeup_handler(void);
void __init pi_init_cpu(int cpu);
void pi_apicv_pre_state_restore(struct kvm_vcpu *vcpu);
bool pi_has_pending_interrupt(struct kvm_vcpu *vcpu);
-int vmx_pi_update_irte(struct kvm_kernel_irqfd *irqfd, struct kvm *kvm,
+int vt_pi_update_irte(struct kvm_kernel_irqfd *irqfd, struct kvm *kvm,
unsigned int host_irq, uint32_t guest_irq,
struct kvm_vcpu *vcpu, u32 vector);
-void vmx_pi_start_bypass(struct kvm *kvm);
+void vt_pi_start_bypass(struct kvm *kvm);
static inline int pi_find_highest_vector(struct pi_desc *pi_desc)
{
diff --git a/arch/x86/kvm/vmx/tdx.c b/arch/x86/kvm/vmx/tdx.c
index b272c20586a74..efbb1ac6f51ea 100644
--- a/arch/x86/kvm/vmx/tdx.c
+++ b/arch/x86/kvm/vmx/tdx.c
@@ -716,7 +716,7 @@ void tdx_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
{
struct vcpu_tdx *tdx = to_tdx(vcpu);
- vmx_vcpu_pi_load(vcpu, cpu);
+ vt_vcpu_pi_load(vcpu, cpu);
if (vcpu->cpu == cpu || !is_hkid_assigned(to_kvm_tdx(vcpu->kvm)))
return;
@@ -741,7 +741,7 @@ bool tdx_interrupt_allowed(struct kvm_vcpu *vcpu)
* interrupt is always allowed unless TDX guest calls TDVMCALL with HLT,
* which passes the interrupt blocked flag.
*/
- return vmx_get_exit_reason(vcpu).basic != EXIT_REASON_HLT ||
+ return vt_get_exit_reason(vcpu).basic != EXIT_REASON_HLT ||
!to_tdx(vcpu)->vp_enter_args.r12;
}
@@ -759,7 +759,7 @@ static bool tdx_protected_apic_has_interrupt(struct kvm_vcpu *vcpu)
* otherwise the interrupt would have been serviced at the instruction
* boundary.
*/
- if (vmx_get_exit_reason(vcpu).basic != EXIT_REASON_HLT ||
+ if (vt_get_exit_reason(vcpu).basic != EXIT_REASON_HLT ||
to_tdx(vcpu)->vp_enter_args.r12)
return false;
@@ -826,7 +826,7 @@ static void tdx_prepare_switch_to_host(struct kvm_vcpu *vcpu)
void tdx_vcpu_put(struct kvm_vcpu *vcpu)
{
- vmx_vcpu_pi_put(vcpu);
+ vt_vcpu_pi_put(vcpu);
tdx_prepare_switch_to_host(vcpu);
}
@@ -974,15 +974,15 @@ static noinstr void tdx_vcpu_enter_exit(struct kvm_vcpu *vcpu)
tdx->exit_gpa = tdx->vp_enter_args.r8;
vt->exit_intr_info = tdx->vp_enter_args.r9;
- vmx_handle_nmi(vcpu);
+ vt_handle_nmi(vcpu);
guest_state_exit_irqoff();
}
static bool tdx_failed_vmentry(struct kvm_vcpu *vcpu)
{
- return vmx_get_exit_reason(vcpu).failed_vmentry &&
- vmx_get_exit_reason(vcpu).full != -1u;
+ return vt_get_exit_reason(vcpu).failed_vmentry &&
+ vt_get_exit_reason(vcpu).full != -1u;
}
static fastpath_t tdx_exit_handlers_fastpath(struct kvm_vcpu *vcpu)
@@ -1131,7 +1131,7 @@ void tdx_inject_nmi(struct kvm_vcpu *vcpu)
static int tdx_handle_exception_nmi(struct kvm_vcpu *vcpu)
{
- u32 intr_info = vmx_get_intr_info(vcpu);
+ u32 intr_info = vt_get_intr_info(vcpu);
/*
* Machine checks are handled by handle_exception_irqoff(), or by
@@ -1895,7 +1895,7 @@ void tdx_deliver_interrupt(struct kvm_lapic *apic, int delivery_mode,
struct vcpu_tdx *tdx = to_tdx(vcpu);
/* TDX supports only posted interrupt. No lapic emulation. */
- __vmx_deliver_posted_interrupt(vcpu, &tdx->vt.pi_desc, vector);
+ __vt_deliver_posted_interrupt(vcpu, &tdx->vt.pi_desc, vector);
trace_kvm_apicv_accept_irq(vcpu->vcpu_id, delivery_mode, trig_mode, vector);
}
@@ -1903,7 +1903,7 @@ void tdx_deliver_interrupt(struct kvm_lapic *apic, int delivery_mode,
static inline bool tdx_is_sept_violation_unexpected_pending(struct kvm_vcpu *vcpu)
{
u64 eeq_type = to_tdx(vcpu)->ext_exit_qualification & TDX_EXT_EXIT_QUAL_TYPE_MASK;
- u64 eq = vmx_get_exit_qual(vcpu);
+ u64 eq = vt_get_exit_qual(vcpu);
if (eeq_type != TDX_EXT_EXIT_QUAL_TYPE_PENDING_EPT_VIOLATION)
return false;
@@ -1939,7 +1939,7 @@ static int tdx_handle_ept_violation(struct kvm_vcpu *vcpu)
/* Only private GPA triggers zero-step mitigation */
local_retry = true;
} else {
- exit_qual = vmx_get_exit_qual(vcpu);
+ exit_qual = vt_get_exit_qual(vcpu);
/*
* EPT violation due to instruction fetch should never be
* triggered from shared memory in TDX guest. If such EPT
@@ -1987,7 +1987,7 @@ static int tdx_handle_ept_violation(struct kvm_vcpu *vcpu)
while (1) {
struct kvm_memory_slot *slot;
- ret = __vmx_handle_ept_violation(vcpu, gpa, exit_qual);
+ ret = __vt_handle_ept_violation(vcpu, gpa, exit_qual);
if (ret != RET_PF_RETRY || !local_retry)
break;
@@ -2021,7 +2021,7 @@ int tdx_complete_emulated_msr(struct kvm_vcpu *vcpu, int err)
return 1;
}
- if (vmx_get_exit_reason(vcpu).basic == EXIT_REASON_MSR_READ)
+ if (vt_get_exit_reason(vcpu).basic == EXIT_REASON_MSR_READ)
tdvmcall_set_return_val(vcpu, kvm_read_edx_eax(vcpu));
return 1;
@@ -2032,7 +2032,7 @@ int tdx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t fastpath)
{
struct vcpu_tdx *tdx = to_tdx(vcpu);
u64 vp_enter_ret = tdx->vp_enter_ret;
- union vmx_exit_reason exit_reason = vmx_get_exit_reason(vcpu);
+ union vmx_exit_reason exit_reason = vt_get_exit_reason(vcpu);
if (fastpath != EXIT_FASTPATH_NONE)
return 1;
@@ -2142,9 +2142,9 @@ void tdx_get_exit_info(struct kvm_vcpu *vcpu, u32 *reason,
*reason = tdx->vt.exit_reason.full;
if (*reason != -1u) {
- *info1 = vmx_get_exit_qual(vcpu);
+ *info1 = vt_get_exit_qual(vcpu);
*info2 = tdx->ext_exit_qualification;
- *intr_info = vmx_get_intr_info(vcpu);
+ *intr_info = vt_get_intr_info(vcpu);
} else {
*info1 = 0;
*info2 = 0;
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index 504630f0eb40f..7e35c2d03c69e 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -1577,12 +1577,12 @@ void vmx_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
vmx_vcpu_load_vmcs(vcpu, cpu);
- vmx_vcpu_pi_load(vcpu, cpu);
+ vt_vcpu_pi_load(vcpu, cpu);
}
void vmx_vcpu_put(struct kvm_vcpu *vcpu)
{
- vmx_vcpu_pi_put(vcpu);
+ vt_vcpu_pi_put(vcpu);
vmx_prepare_switch_to_host(to_vmx(vcpu));
}
@@ -1791,7 +1791,7 @@ int vmx_check_emulate_instruction(struct kvm_vcpu *vcpu, int emul_type,
* so that guest userspace can't DoS the guest simply by triggering
* emulation (enclaves are CPL3 only).
*/
- if (vmx_get_exit_reason(vcpu).enclave_mode) {
+ if (vt_get_exit_reason(vcpu).enclave_mode) {
kvm_queue_exception(vcpu, UD_VECTOR);
return X86EMUL_PROPAGATE_FAULT;
}
@@ -1806,7 +1806,7 @@ int vmx_check_emulate_instruction(struct kvm_vcpu *vcpu, int emul_type,
static int skip_emulated_instruction(struct kvm_vcpu *vcpu)
{
- union vmx_exit_reason exit_reason = vmx_get_exit_reason(vcpu);
+ union vmx_exit_reason exit_reason = vt_get_exit_reason(vcpu);
unsigned long rip, orig_rip;
u32 instr_len;
@@ -4424,7 +4424,7 @@ static int vmx_deliver_posted_interrupt(struct kvm_vcpu *vcpu, int vector)
if (!vcpu->arch.apic->apicv_active)
return -1;
- __vmx_deliver_posted_interrupt(vcpu, &vt->pi_desc, vector);
+ __vt_deliver_posted_interrupt(vcpu, &vt->pi_desc, vector);
return 0;
}
@@ -5379,15 +5379,9 @@ bool vmx_guest_inject_ac(struct kvm_vcpu *vcpu)
(kvm_get_rflags(vcpu) & X86_EFLAGS_AC);
}
-static bool is_xfd_nm_fault(struct kvm_vcpu *vcpu)
-{
- return vcpu->arch.guest_fpu.fpstate->xfd &&
- !kvm_is_cr0_bit_set(vcpu, X86_CR0_TS);
-}
-
static int vmx_handle_page_fault(struct kvm_vcpu *vcpu, u32 error_code)
{
- unsigned long cr2 = vmx_get_exit_qual(vcpu);
+ unsigned long cr2 = vt_get_exit_qual(vcpu);
if (vcpu->arch.apf.host_apf_flags)
goto handle_pf;
@@ -5435,7 +5429,7 @@ static int handle_exception_nmi(struct kvm_vcpu *vcpu)
u32 vect_info;
vect_info = vmx->idt_vectoring_info;
- intr_info = vmx_get_intr_info(vcpu);
+ intr_info = vt_get_intr_info(vcpu);
/*
* Machine checks are handled by handle_exception_irqoff(), or by
@@ -5516,7 +5510,7 @@ static int handle_exception_nmi(struct kvm_vcpu *vcpu)
switch (ex_no) {
case DB_VECTOR:
- dr6 = vmx_get_exit_qual(vcpu);
+ dr6 = vt_get_exit_qual(vcpu);
if (!(vcpu->guest_debug &
(KVM_GUESTDBG_SINGLESTEP | KVM_GUESTDBG_USE_HW_BP))) {
/*
@@ -5592,7 +5586,7 @@ static int handle_io(struct kvm_vcpu *vcpu)
int size, in, string;
unsigned port;
- exit_qualification = vmx_get_exit_qual(vcpu);
+ exit_qualification = vt_get_exit_qual(vcpu);
string = (exit_qualification & 16) != 0;
++vcpu->stat.io_exits;
@@ -5681,7 +5675,7 @@ static int handle_cr(struct kvm_vcpu *vcpu)
int err;
int ret;
- exit_qualification = vmx_get_exit_qual(vcpu);
+ exit_qualification = vt_get_exit_qual(vcpu);
cr = exit_qualification & 15;
reg = (exit_qualification >> 8) & 15;
switch ((exit_qualification >> 4) & 3) {
@@ -5759,7 +5753,7 @@ static int handle_dr(struct kvm_vcpu *vcpu)
int dr, dr7, reg;
int err = 1;
- exit_qualification = vmx_get_exit_qual(vcpu);
+ exit_qualification = vt_get_exit_qual(vcpu);
dr = exit_qualification & DEBUG_REG_ACCESS_NUM;
/* First, if DR does not exist, trigger UD */
@@ -5855,7 +5849,7 @@ static int handle_interrupt_window(struct kvm_vcpu *vcpu)
static int handle_invlpg(struct kvm_vcpu *vcpu)
{
- unsigned long exit_qualification = vmx_get_exit_qual(vcpu);
+ unsigned long exit_qualification = vt_get_exit_qual(vcpu);
kvm_mmu_invlpg(vcpu, exit_qualification);
return kvm_skip_emulated_instruction(vcpu);
@@ -5864,7 +5858,7 @@ static int handle_invlpg(struct kvm_vcpu *vcpu)
static int handle_apic_access(struct kvm_vcpu *vcpu)
{
if (likely(fasteoi)) {
- unsigned long exit_qualification = vmx_get_exit_qual(vcpu);
+ unsigned long exit_qualification = vt_get_exit_qual(vcpu);
int access_type, offset;
access_type = exit_qualification & APIC_ACCESS_TYPE;
@@ -5885,7 +5879,7 @@ static int handle_apic_access(struct kvm_vcpu *vcpu)
static int handle_apic_eoi_induced(struct kvm_vcpu *vcpu)
{
- unsigned long exit_qualification = vmx_get_exit_qual(vcpu);
+ unsigned long exit_qualification = vt_get_exit_qual(vcpu);
int vector = exit_qualification & 0xff;
/* EOI-induced VM exit is trap-like and thus no need to adjust IP */
@@ -5895,7 +5889,7 @@ static int handle_apic_eoi_induced(struct kvm_vcpu *vcpu)
static int handle_apic_write(struct kvm_vcpu *vcpu)
{
- unsigned long exit_qualification = vmx_get_exit_qual(vcpu);
+ unsigned long exit_qualification = vt_get_exit_qual(vcpu);
/*
* APIC-write VM-Exit is trap-like, KVM doesn't need to advance RIP and
@@ -5923,7 +5917,7 @@ static int handle_task_switch(struct kvm_vcpu *vcpu)
idt_index = (vmx->idt_vectoring_info & VECTORING_INFO_VECTOR_MASK);
type = (vmx->idt_vectoring_info & VECTORING_INFO_TYPE_MASK);
- exit_qualification = vmx_get_exit_qual(vcpu);
+ exit_qualification = vt_get_exit_qual(vcpu);
reason = (u32)exit_qualification >> 30;
if (reason == TASK_SWITCH_GATE && idt_v) {
@@ -5969,7 +5963,7 @@ static int handle_task_switch(struct kvm_vcpu *vcpu)
static int handle_ept_violation(struct kvm_vcpu *vcpu)
{
- unsigned long exit_qualification = vmx_get_exit_qual(vcpu);
+ unsigned long exit_qualification = vt_get_exit_qual(vcpu);
gpa_t gpa;
/*
@@ -5997,7 +5991,7 @@ static int handle_ept_violation(struct kvm_vcpu *vcpu)
if (unlikely(allow_smaller_maxphyaddr && !kvm_vcpu_is_legal_gpa(vcpu, gpa)))
return kvm_emulate_instruction(vcpu, 0);
- return __vmx_handle_ept_violation(vcpu, gpa, exit_qualification);
+ return __vt_handle_ept_violation(vcpu, gpa, exit_qualification);
}
static int handle_ept_misconfig(struct kvm_vcpu *vcpu)
@@ -6160,7 +6154,7 @@ static int handle_invpcid(struct kvm_vcpu *vcpu)
/* According to the Intel instruction reference, the memory operand
* is read even if it isn't needed (e.g., for type==all)
*/
- if (get_vmx_mem_address(vcpu, vmx_get_exit_qual(vcpu),
+ if (get_vmx_mem_address(vcpu, vt_get_exit_qual(vcpu),
vmx_instruction_info, false,
sizeof(operand), &gva))
return 1;
@@ -6174,7 +6168,7 @@ static int handle_pml_full(struct kvm_vcpu *vcpu)
trace_kvm_pml_full(vcpu->vcpu_id);
- exit_qualification = vmx_get_exit_qual(vcpu);
+ exit_qualification = vt_get_exit_qual(vcpu);
/*
* PML buffer FULL happened while executing iret from NMI,
@@ -6278,7 +6272,7 @@ static int handle_bus_lock_vmexit(struct kvm_vcpu *vcpu)
static int handle_notify(struct kvm_vcpu *vcpu)
{
- unsigned long exit_qual = vmx_get_exit_qual(vcpu);
+ unsigned long exit_qual = vt_get_exit_qual(vcpu);
bool context_invalid = exit_qual & NOTIFY_VM_CONTEXT_INVALID;
++vcpu->stat.notify_window_exits;
@@ -6309,13 +6303,13 @@ static int vmx_get_msr_imm_reg(struct kvm_vcpu *vcpu)
static int handle_rdmsr_imm(struct kvm_vcpu *vcpu)
{
- return kvm_emulate_rdmsr_imm(vcpu, vmx_get_exit_qual(vcpu),
+ return kvm_emulate_rdmsr_imm(vcpu, vt_get_exit_qual(vcpu),
vmx_get_msr_imm_reg(vcpu));
}
static int handle_wrmsr_imm(struct kvm_vcpu *vcpu)
{
- return kvm_emulate_wrmsr_imm(vcpu, vmx_get_exit_qual(vcpu),
+ return kvm_emulate_wrmsr_imm(vcpu, vt_get_exit_qual(vcpu),
vmx_get_msr_imm_reg(vcpu));
}
@@ -6392,10 +6386,10 @@ void vmx_get_exit_info(struct kvm_vcpu *vcpu, u32 *reason,
struct vcpu_vmx *vmx = to_vmx(vcpu);
*reason = vmx->vt.exit_reason.full;
- *info1 = vmx_get_exit_qual(vcpu);
+ *info1 = vt_get_exit_qual(vcpu);
if (!(vmx->vt.exit_reason.failed_vmentry)) {
*info2 = vmx->idt_vectoring_info;
- *intr_info = vmx_get_intr_info(vcpu);
+ *intr_info = vt_get_intr_info(vcpu);
if (is_exception_with_error_code(*intr_info))
*error_code = vmcs_read32(VM_EXIT_INTR_ERROR_CODE);
else
@@ -6706,7 +6700,7 @@ void dump_vmcs(struct kvm_vcpu *vcpu)
static int __vmx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t exit_fastpath)
{
struct vcpu_vmx *vmx = to_vmx(vcpu);
- union vmx_exit_reason exit_reason = vmx_get_exit_reason(vcpu);
+ union vmx_exit_reason exit_reason = vt_get_exit_reason(vcpu);
u32 vectoring_info = vmx->idt_vectoring_info;
u16 exit_handler_index;
@@ -6870,7 +6864,7 @@ int vmx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t exit_fastpath)
* Exit to user space when bus lock detected to inform that there is
* a bus lock in guest.
*/
- if (vmx_get_exit_reason(vcpu).bus_lock_detected) {
+ if (vt_get_exit_reason(vcpu).bus_lock_detected) {
if (ret > 0)
vcpu->run->exit_reason = KVM_EXIT_X86_BUS_LOCK;
@@ -7143,74 +7137,6 @@ void vmx_load_eoi_exitmap(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap)
vmcs_write64(EOI_EXIT_BITMAP3, eoi_exit_bitmap[3]);
}
-static void handle_nm_fault_irqoff(struct kvm_vcpu *vcpu)
-{
- /*
- * Save xfd_err to guest_fpu before interrupt is enabled, so the
- * MSR value is not clobbered by the host activity before the guest
- * has chance to consume it.
- *
- * Update the guest's XFD_ERR if and only if XFD is enabled, as the #NM
- * interception may have been caused by L1 interception. Per the SDM,
- * XFD_ERR is not modified for non-XFD #NM, i.e. if CR0.TS=1.
- *
- * Note, XFD_ERR is updated _before_ the #NM interception check, i.e.
- * unlike CR2 and DR6, the value is not a payload that is attached to
- * the #NM exception.
- */
- if (is_xfd_nm_fault(vcpu))
- rdmsrq(MSR_IA32_XFD_ERR, vcpu->arch.guest_fpu.xfd_err);
-}
-
-static void handle_exception_irqoff(struct kvm_vcpu *vcpu, u32 intr_info)
-{
- /* if exit due to PF check for async PF */
- if (is_page_fault(intr_info))
- vcpu->arch.apf.host_apf_flags = kvm_read_and_reset_apf_flags();
- /* if exit due to NM, handle before interrupts are enabled */
- else if (is_nm_fault(intr_info))
- handle_nm_fault_irqoff(vcpu);
- /* Handle machine checks before interrupts are enabled */
- else if (is_machine_check(intr_info))
- kvm_machine_check();
-}
-
-static void handle_external_interrupt_irqoff(struct kvm_vcpu *vcpu,
- u32 intr_info)
-{
- unsigned int vector = intr_info & INTR_INFO_VECTOR_MASK;
-
- if (KVM_BUG(!is_external_intr(intr_info), vcpu->kvm,
- "unexpected VM-Exit interrupt info: 0x%x", intr_info))
- return;
-
- kvm_before_interrupt(vcpu, KVM_HANDLING_IRQ);
- x86_entry_from_kvm(EVENT_TYPE_EXTINT, vector);
- kvm_after_interrupt(vcpu);
-
- vcpu->arch.at_instruction_boundary = true;
-}
-
-void vmx_handle_exit_irqoff(struct kvm_vcpu *vcpu)
-{
- if (to_vt(vcpu)->emulation_required)
- return;
-
- switch (vmx_get_exit_reason(vcpu).basic) {
- case EXIT_REASON_EXTERNAL_INTERRUPT:
- handle_external_interrupt_irqoff(vcpu, vmx_get_intr_info(vcpu));
- break;
- case EXIT_REASON_EXCEPTION_NMI:
- handle_exception_irqoff(vcpu, vmx_get_intr_info(vcpu));
- break;
- case EXIT_REASON_MCE_DURING_VMENTRY:
- kvm_machine_check();
- break;
- default:
- break;
- }
-}
-
/*
* The kvm parameter can be NULL (module initialization, or invocation before
* VM creation). Be sure to check the kvm parameter before using it.
@@ -7250,7 +7176,7 @@ static void vmx_recover_nmi_blocking(struct vcpu_vmx *vmx)
if (vmx->loaded_vmcs->nmi_known_unmasked)
return;
- exit_intr_info = vmx_get_intr_info(&vmx->vcpu);
+ exit_intr_info = vt_get_intr_info(&vmx->vcpu);
unblock_nmi = (exit_intr_info & INTR_INFO_UNBLOCK_NMI) != 0;
vector = exit_intr_info & INTR_INFO_VECTOR_MASK;
/*
@@ -7417,14 +7343,14 @@ static fastpath_t vmx_exit_handlers_fastpath(struct kvm_vcpu *vcpu,
* the fastpath even, all other exits must use the slow path.
*/
if (is_guest_mode(vcpu) &&
- vmx_get_exit_reason(vcpu).basic != EXIT_REASON_PREEMPTION_TIMER)
+ vt_get_exit_reason(vcpu).basic != EXIT_REASON_PREEMPTION_TIMER)
return EXIT_FASTPATH_NONE;
- switch (vmx_get_exit_reason(vcpu).basic) {
+ switch (vt_get_exit_reason(vcpu).basic) {
case EXIT_REASON_MSR_WRITE:
return handle_fastpath_wrmsr(vcpu);
case EXIT_REASON_MSR_WRITE_IMM:
- return handle_fastpath_wrmsr_imm(vcpu, vmx_get_exit_qual(vcpu),
+ return handle_fastpath_wrmsr_imm(vcpu, vt_get_exit_qual(vcpu),
vmx_get_msr_imm_reg(vcpu));
case EXIT_REASON_PREEMPTION_TIMER:
return handle_fastpath_preemption_timer(vcpu, force_immediate_exit);
@@ -7437,17 +7363,6 @@ static fastpath_t vmx_exit_handlers_fastpath(struct kvm_vcpu *vcpu,
}
}
-noinstr void vmx_handle_nmi(struct kvm_vcpu *vcpu)
-{
- if ((u16)vmx_get_exit_reason(vcpu).basic != EXIT_REASON_EXCEPTION_NMI ||
- !is_nmi(vmx_get_intr_info(vcpu)))
- return;
-
- kvm_before_interrupt(vcpu, KVM_HANDLING_NMI);
- x86_entry_from_kvm(EVENT_TYPE_NMI, NMI_VECTOR);
- kvm_after_interrupt(vcpu);
-}
-
static noinstr void vmx_vcpu_enter_exit(struct kvm_vcpu *vcpu,
unsigned int flags)
{
@@ -7477,10 +7392,10 @@ static noinstr void vmx_vcpu_enter_exit(struct kvm_vcpu *vcpu,
}
vmx->vt.exit_reason.full = vmcs_read32(VM_EXIT_REASON);
- if (likely(!vmx_get_exit_reason(vcpu).failed_vmentry))
+ if (likely(!vt_get_exit_reason(vcpu).failed_vmentry))
vmx->idt_vectoring_info = vmcs_read32(IDT_VECTORING_INFO_FIELD);
- vmx_handle_nmi(vcpu);
+ vt_handle_nmi(vcpu);
out:
guest_state_exit_irqoff();
@@ -7617,7 +7532,7 @@ fastpath_t vmx_vcpu_run(struct kvm_vcpu *vcpu, u64 run_flags)
* checking.
*/
if (vcpu->arch.nested_run_pending &&
- !vmx_get_exit_reason(vcpu).failed_vmentry)
+ !vt_get_exit_reason(vcpu).failed_vmentry)
++vcpu->stat.nested_run;
vcpu->arch.nested_run_pending = 0;
@@ -7628,7 +7543,7 @@ fastpath_t vmx_vcpu_run(struct kvm_vcpu *vcpu, u64 run_flags)
trace_kvm_exit(vcpu, KVM_ISA_VMX);
- if (unlikely(vmx_get_exit_reason(vcpu).failed_vmentry))
+ if (unlikely(vt_get_exit_reason(vcpu).failed_vmentry))
return EXIT_FASTPATH_NONE;
vmx->loaded_vmcs->launched = 1;
diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h
index dc8517f15bc46..3247b55b34843 100644
--- a/arch/x86/kvm/vmx/vmx.h
+++ b/arch/x86/kvm/vmx/vmx.h
@@ -304,43 +304,6 @@ struct kvm_vmx {
u64 *pid_table;
};
-static __always_inline struct vcpu_vt *to_vt(struct kvm_vcpu *vcpu)
-{
- return &(container_of(vcpu, struct vcpu_vmx, vcpu)->vt);
-}
-
-static __always_inline struct kvm_vcpu *vt_to_vcpu(struct vcpu_vt *vt)
-{
- return &(container_of(vt, struct vcpu_vmx, vt)->vcpu);
-}
-
-static __always_inline union vmx_exit_reason vmx_get_exit_reason(struct kvm_vcpu *vcpu)
-{
- return to_vt(vcpu)->exit_reason;
-}
-
-static __always_inline unsigned long vmx_get_exit_qual(struct kvm_vcpu *vcpu)
-{
- struct vcpu_vt *vt = to_vt(vcpu);
-
- if (!kvm_register_test_and_mark_available(vcpu, VCPU_REG_EXIT_INFO_1) &&
- !WARN_ON_ONCE(is_td_vcpu(vcpu)))
- vt->exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
-
- return vt->exit_qualification;
-}
-
-static __always_inline u32 vmx_get_intr_info(struct kvm_vcpu *vcpu)
-{
- struct vcpu_vt *vt = to_vt(vcpu);
-
- if (!kvm_register_test_and_mark_available(vcpu, VCPU_REG_EXIT_INFO_2) &&
- !WARN_ON_ONCE(is_td_vcpu(vcpu)))
- vt->exit_intr_info = vmcs_read32(VM_EXIT_INTR_INFO);
-
- return vt->exit_intr_info;
-}
-
void vmx_vcpu_load_vmcs(struct kvm_vcpu *vcpu, int cpu);
int allocate_vpid(void);
void free_vpid(int vpid);
diff --git a/arch/x86/kvm/vmx/x86_ops.h b/arch/x86/kvm/vmx/x86_ops.h
index 054fd14bb2e16..7ac02c68457f1 100644
--- a/arch/x86/kvm/vmx/x86_ops.h
+++ b/arch/x86/kvm/vmx/x86_ops.h
@@ -27,7 +27,6 @@ void vmx_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event);
void vmx_vcpu_load(struct kvm_vcpu *vcpu, int cpu);
void vmx_vcpu_put(struct kvm_vcpu *vcpu);
int vmx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t exit_fastpath);
-void vmx_handle_exit_irqoff(struct kvm_vcpu *vcpu);
int vmx_skip_emulated_instruction(struct kvm_vcpu *vcpu);
void vmx_update_emulated_instruction(struct kvm_vcpu *vcpu);
bool vmx_unhandleable_emulation_required(struct kvm_vcpu *vcpu);
|
| 3/2 | 2026/09/05 09:24 | llm | patch-evaluator |
0mModel:gemini-3.7-flash Args: null Results: null Tokens: input: 19795 output: 34 thoughts: 884 Thoughts: **Analyzing this KVM Patch** Okay, let's dive into this patch. The target architecture is amd64, which is expected. The focus is clearly on the KVM Intel/VMX code, specifically the TDX (Trusted Domain Extensions) integration, given the files being touched: `common.h`, `main.c`, `nested.c`, `posted_intr.c`, `posted_intr.h`, `tdx.c`, `vmx.c`, `vmx.h`, and `x86_ops.h`. First glance, it looks like a refactoring and TDX integration effort. Let me break down what the patch is doing: 1. A new `struct vcpu_vmx_tdx` is introduced in `common.h`, and the `to_vt` and `vt_to_vcpu` macros are defined using it. This likely ties TDX-specific data or functions to the existing KVM VMX structure. Seems like a common pattern for adding a layer. 2. Key functions, `vmx_get_exit_reason`, `vmx_get_exit_qual`, and `vmx_get_intr_info` are renamed to `vt_` prefixed versions and moved to `common.h`. This is likely to establish a common API, possibly to be used between VMX and TDX code paths. 3. Similar renaming and, potentially, reorganization of several handler functions (`__vmx_handle_ept_violation`, etc.) also happens. The `vmx_` prefix is consistently changed to `vt_`, suggesting a clear transition to a more generic or TDX-specific interface. 4. More function moves! The handler functions `handle_nm_fault_irqoff`, `handle_exception_irqoff`, `handle_external_interrupt_irqoff`, `vt_handle_exit_irqoff`, and `vt_handle_nmi` are moved from `vmx.c` to `main.c`, and hook the `vt_handle_exit_irqoff` into `vt_x86_ops.handle_exit_irqoff`. This is a classic refactoring pattern and potentially isolates the TDX-specific handler's implementation. 5. Functions in `posted_intr.c` are also getting the `vt_` treatment. This suggests modifications to the posted interrupt handling, possibly to better support TDX's interrupt delivery mechanisms, if TDX even has posted interrupts. 6. The crucial step: all callers within `vmx.c`, `tdx.c`, and `nested.c` are updated to use the new `vt_*` functions. This is important to verify the changes don't break functionality. 7. Pragma GCC poison is being used to enforce an abstraction boundary. Nice! This makes the refactoring more robust and clear. 8. The static assertion `offsetof(struct vcpu_vmx_tdx, vt) == offsetof(struct vcpu_vmx, vt)` is interesting. This is a bit of a sanity check; it seems the `vt` member of the `vcpu_vmx_tdx` struct needs to be at the same offset as in the existing `vcpu_vmx` struct, likely related to how the code accesses and uses the fields. **Reachability and Fuzzing Potential** Okay, so is this code reachable and worth fuzzing on amd64? Absolutely. KVM is a *critical* piece of the virtualization infrastructure on x86/amd64 Linux and is heavily fuzzed by tools like syzkaller via `/dev/kvm`. This includes the ioctl calls like `KVM_RUN`, `KVM_CREATE_VM`, and `KVM_CREATE_VCPU`, which is nested virtualization. Intel VMX is also relevant. Given the focus on TDX, this is probably worth a fuzzing campaign to cover new code paths. I need to check the Kconfig options for KVM and KVM_INTEL. |
| 4/2 | 2026/09/05 09:24 | tool | grepper |
0mArgs:{
"Expression": "config KVM_INTEL",
"PathPrefix": "arch/x86/kvm"
}Results: {
"Output": "arch/x86/kvm/Kconfig=83=config KVM_SW_PROTECTED_VM\n--\narch/x86/kvm/Kconfig-95-\narch/x86/kvm/Kconfig:96:config KVM_INTEL\narch/x86/kvm/Kconfig-97-\ttristate \"KVM for Intel (and compatible) processors support\"\n--\narch/x86/kvm/Kconfig-106-\narch/x86/kvm/Kconfig:107:config KVM_INTEL_PROVE_VE\narch/x86/kvm/Kconfig-108- bool \"Check that guests do not receive #VE exceptions\"\n--\narch/x86/kvm/Kconfig=122=config X86_SGX_KVM\n--\narch/x86/kvm/Kconfig-133-\narch/x86/kvm/Kconfig:134:config KVM_INTEL_TDX\narch/x86/kvm/Kconfig-135-\tbool \"Intel Trust Domain Extensions (TDX) support\"\n"
} |
| 5/2 | 2026/09/05 09:24 | llm | patch-evaluator |
0mModel:gemini-3.7-flash Args: null Results: null Tokens: input: 21879 output: 38 thoughts: 29 Thoughts: Here's my take on those thoughts, tailored for an expert audience: **Examining KVM_INTEL Dependencies in Kconfig** Alright, let's dive in. My immediate thought is to zero in on the `arch/x86/kvm/Kconfig` file, specifically around the `KVM_INTEL` option. I want to quickly refresh my mental map of how this is all wired together. I'm looking for the usual suspects: any direct dependencies, of course. But I'm also interested in indirect dependencies – things that might be enabled or disabled *because* `KVM_INTEL` is selected. What other features or drivers are contingent on Intel virtualization support? This will give me a better understanding of the overall configuration impact, particularly with all the potential implications of any related changes. Basically, I am thinking through the Kconfig and its connections to the overall architecture, ready to understand the implications of any change. |
| 6/2 | 2026/09/05 09:24 | tool | read-file |
0mArgs:{
"File": "arch/x86/kvm/Kconfig",
"FirstLine": 90,
"LineCount": 45
}Results: {
"Contents": " 90:\t\t protected VMs are purely a development and testing vehicle for\n 91:\t\t KVM_CREATE_GUEST_MEMFD. Attempting to run a \"real\" VM workload as a\n 92:\t\t software-protected VM will fail miserably.\n 93:\t\n 94:\t\t If unsure, say \"N\".\n 95:\t\n 96:\tconfig KVM_INTEL\n 97:\t\ttristate \"KVM for Intel (and compatible) processors support\"\n 98:\t\tdepends on KVM \u0026\u0026 IA32_FEAT_CTL\n 99:\t\tselect X86_FRED if X86_64\n 100:\t\thelp\n 101:\t\t Provides support for KVM on processors equipped with Intel's VT\n 102:\t\t extensions, a.k.a. Virtual Machine Extensions (VMX).\n 103:\t\n 104:\t\t To compile this as a module, choose M here: the module\n 105:\t\t will be called kvm-intel.\n 106:\t\n 107:\tconfig KVM_INTEL_PROVE_VE\n 108:\t bool \"Check that guests do not receive #VE exceptions\"\n 109:\t depends on KVM_INTEL \u0026\u0026 EXPERT\n 110:\t help\n 111:\t Checks that KVM's page table management code will not incorrectly\n 112:\t let guests receive a virtualization exception. Virtualization\n 113:\t exceptions will be trapped by the hypervisor rather than injected\n 114:\t in the guest.\n 115:\t\n 116:\t Note: some CPUs appear to generate spurious EPT Violations #VEs\n 117:\t that trigger KVM's WARN, in particular with eptad=0 and/or nested\n 118:\t virtualization.\n 119:\t\n 120:\t If unsure, say N.\n 121:\t\n 122:\tconfig X86_SGX_KVM\n 123:\t\tbool \"Software Guard eXtensions (SGX) Virtualization\"\n 124:\t\tdepends on X86_SGX \u0026\u0026 KVM_INTEL\n 125:\t\thelp\n 126:\t\n 127:\t\t Enables KVM guests to create SGX enclaves.\n 128:\t\n 129:\t\t This includes support to expose \"raw\" unreclaimable enclave memory to\n 130:\t\t guests via a device node, e.g. /dev/sgx_vepc.\n 131:\t\n 132:\t\t If unsure, say N.\n 133:\t\n 134:\tconfig KVM_INTEL_TDX\n"
} |
| 7/2 | 2026/09/05 09:24 | llm | patch-evaluator |
0mModel:gemini-3.7-flash Args: null Results: null Tokens: input: 22848 output: 50 thoughts: 1303 Thoughts: **Fuzzing Target Identification: KVM Intel Virtualization** Okay, let's break this down. First, I need to confirm if the target is reachable. I see we're looking at `CONFIG_KVM` and `CONFIG_KVM_INTEL`. Good, `KVM_INTEL` is definitely reachable; I know from experience, specifically syzkaller fuzzing environments on x86_64, that it's accessible. So that's a positive starting point. Now, time for the core question: *is this worth fuzzing?* I'll apply the positive and negative criteria. The positive side is what I am really interested in. This patch touches the core subsystems (hypervisor / KVM), and what's more, it’s a code refactoring. This alone raises a flag. We're not just looking at a simple functional change or cleanup. The author’s intentions are secondary; I always fuzz *refactored* code, regardless of their claims. Changes in logic, helper function introductions, or state management, *especially* in core areas, are prime bug-hunting grounds. And, of course, the modified code is in `arch/x86/kvm/vmx/`, which is directly related to KVM Intel virtualization support. Therefore, the answer is a resounding *yes*, `WorthFuzzing = true`. Alright, with that established, let's define our focus. It's time to identify the `FocusSymbols` and `EnableConfigs`. I'll analyze the modified functions and entry points. I have a list of those from the various files. In `arch/x86/kvm/vmx/main.c`: I see `vt_handle_exit_irqoff`, `vt_handle_nmi`, `handle_nm_fault_irqoff`, `handle_exception_irqoff`, and `handle_external_interrupt_irqoff`. In `arch/x86/kvm/vmx/posted_intr.c`: I'll look at `vt_vcpu_pi_load`, `vt_vcpu_pi_put`, `vt_pi_start_bypass`, and `vt_pi_update_irte`. `arch/x86/kvm/vmx/common.h` is next: Here, `vt_get_exit_reason`, `vt_get_exit_qual`, `vt_get_intr_info`, `__vt_handle_ept_violation`, and `__vt_deliver_posted_interrupt` are potential areas of interest. `arch/x86/kvm/vmx/nested.c` is extensive: I'll include `nested_ept_inject_page_fault`, `prepare_vmcs12`, `nested_vmx_get_vmptr`, `handle_vmread`, `handle_vmwrite`, `handle_vmptrld`, `handle_vmptrst`, `handle_invept`, `handle_invvpid`, `handle_vmfunc`, `nested_vmx_exit_handled_io`, `nested_vmx_exit_handled_msr`, `nested_vmx_exit_handled_cr`, `nested_vmx_l0_wants_exit`, `nested_vmx_l1_wants_exit`, and `nested_vmx_reflect_vmexit`. Lastly, in `arch/x86/kvm/vmx/vmx.c`: I'll have to consider `vmx_handle_exit`, `__vmx_handle_exit`, `vmx_vcpu_run`, `vmx_vcpu_load`, `vmx_vcpu_put`, `handle_exception_nmi`, `handle_ept_violation`, `handle_io`, `handle_cr`, `handle_dr`, `handle_invlpg`, `handle_apic_access`, `handle_apic_eoi_induced`, `handle_apic_write`, `handle_task_switch`, `handle_invpcid`, `handle_pml_full`, `handle_notify`, `handle_rdmsr_imm`, `handle_wrmsr_imm`, `vmx_get_exit_info`, `vmx_deliver_posted_interrupt`, and `skip_emulated_instruction`. Now, I'll need to narrow these down to the non-static symbols or, those accessible outside their defined files, that are in vmlinux/kvm-intel.ko. After checking `arch/x86/kvm/vmx/main.c` and `arch/x86/kvm/vmx/posted_ |
| 8/2 | 2026/09/05 09:24 | tool | grepper |
0mArgs:{
"Expression": "(vt_vcpu_pi_|vt_handle_nmi|vt_pi_)",
"PathPrefix": "arch/x86/kvm/vmx"
}Results: {
"Output": "arch/x86/kvm/vmx/common.h=217=static inline void __vt_deliver_posted_interrupt(struct kvm_vcpu *vcpu,\n--\narch/x86/kvm/vmx/common.h-235-\narch/x86/kvm/vmx/common.h:236:noinstr void vt_handle_nmi(struct kvm_vcpu *vcpu);\narch/x86/kvm/vmx/common.h-237-\n--\narch/x86/kvm/vmx/main.c=932=static void vt_handle_exit_irqoff(struct kvm_vcpu *vcpu)\n--\narch/x86/kvm/vmx/main.c-951-\narch/x86/kvm/vmx/main.c:952:noinstr void vt_handle_nmi(struct kvm_vcpu *vcpu)\narch/x86/kvm/vmx/main.c-953-{\n--\narch/x86/kvm/vmx/main.c=972=struct kvm_x86_ops vt_x86_ops __initdata = {\n--\narch/x86/kvm/vmx/main.c-1090-\narch/x86/kvm/vmx/main.c:1091:\t.pi_update_irte = vt_pi_update_irte,\narch/x86/kvm/vmx/main.c:1092:\t.pi_start_bypass = vt_pi_start_bypass,\narch/x86/kvm/vmx/main.c-1093-\n--\narch/x86/kvm/vmx/posted_intr.c=45=static int pi_try_set_control(struct pi_desc *pi_desc, u64 *pold, u64 new)\n--\narch/x86/kvm/vmx/posted_intr.c-58-\narch/x86/kvm/vmx/posted_intr.c:59:void vt_vcpu_pi_load(struct kvm_vcpu *vcpu, int cpu)\narch/x86/kvm/vmx/posted_intr.c-60-{\n--\narch/x86/kvm/vmx/posted_intr.c=149=static bool vt_can_use_vtd_pi(struct kvm *kvm)\n--\narch/x86/kvm/vmx/posted_intr.c-152-\t * Note, reading the number of possible bypass IRQs can race with a\narch/x86/kvm/vmx/posted_intr.c:153:\t * bypass IRQ being attached to the VM. vt_pi_start_bypass() ensures\narch/x86/kvm/vmx/posted_intr.c-154-\t * blockng vCPUs will see an elevated count or get KVM_REQ_UNBLOCK.\n--\narch/x86/kvm/vmx/posted_intr.c=211=static bool vt_needs_pi_wakeup(struct kvm_vcpu *vcpu)\n--\narch/x86/kvm/vmx/posted_intr.c-224-\narch/x86/kvm/vmx/posted_intr.c:225:void vt_vcpu_pi_put(struct kvm_vcpu *vcpu)\narch/x86/kvm/vmx/posted_intr.c-226-{\n--\narch/x86/kvm/vmx/posted_intr.c=285=bool pi_has_pending_interrupt(struct kvm_vcpu *vcpu)\n--\narch/x86/kvm/vmx/posted_intr.c-296- * blocking vCPUs may scheduled out without reconfiguring PID.NV to the wakeup\narch/x86/kvm/vmx/posted_intr.c:297: * vector, i.e. if the bypass IRQ came along after vt_vcpu_pi_put().\narch/x86/kvm/vmx/posted_intr.c-298- */\narch/x86/kvm/vmx/posted_intr.c:299:void vt_pi_start_bypass(struct kvm *kvm)\narch/x86/kvm/vmx/posted_intr.c-300-{\n--\narch/x86/kvm/vmx/posted_intr.c-306-\narch/x86/kvm/vmx/posted_intr.c:307:int vt_pi_update_irte(struct kvm_kernel_irqfd *irqfd, struct kvm *kvm,\narch/x86/kvm/vmx/posted_intr.c-308-\t\t unsigned int host_irq, uint32_t guest_irq,\n--\narch/x86/kvm/vmx/posted_intr.h-10-\narch/x86/kvm/vmx/posted_intr.h:11:void vt_vcpu_pi_load(struct kvm_vcpu *vcpu, int cpu);\narch/x86/kvm/vmx/posted_intr.h:12:void vt_vcpu_pi_put(struct kvm_vcpu *vcpu);\narch/x86/kvm/vmx/posted_intr.h-13-void pi_wakeup_handler(void);\n--\narch/x86/kvm/vmx/posted_intr.h=16=bool pi_has_pending_interrupt(struct kvm_vcpu *vcpu);\narch/x86/kvm/vmx/posted_intr.h:17:int vt_pi_update_irte(struct kvm_kernel_irqfd *irqfd, struct kvm *kvm,\narch/x86/kvm/vmx/posted_intr.h-18-\t\t unsigned int host_irq, uint32_t guest_irq,\narch/x86/kvm/vmx/posted_intr.h-19-\t\t struct kvm_vcpu *vcpu, u32 vector);\narch/x86/kvm/vmx/posted_intr.h:20:void vt_pi_start_bypass(struct kvm *kvm);\narch/x86/kvm/vmx/posted_intr.h-21-\n--\narch/x86/kvm/vmx/tdx.c=715=void tdx_vcpu_load(struct kvm_vcpu *vcpu, int cpu)\n--\narch/x86/kvm/vmx/tdx.c-718-\narch/x86/kvm/vmx/tdx.c:719:\tvt_vcpu_pi_load(vcpu, cpu);\narch/x86/kvm/vmx/tdx.c-720-\tif (vcpu-\u003ecpu == cpu || !is_hkid_assigned(to_kvm_tdx(vcpu-\u003ekvm)))\n--\narch/x86/kvm/vmx/tdx.c=827=void tdx_vcpu_put(struct kvm_vcpu *vcpu)\narch/x86/kvm/vmx/tdx.c-828-{\narch/x86/kvm/vmx/tdx.c:829:\tvt_vcpu_pi_put(vcpu);\narch/x86/kvm/vmx/tdx.c-830-\ttdx_prepare_switch_to_host(vcpu);\n--\narch/x86/kvm/vmx/tdx.c=961=static noinstr void tdx_vcpu_enter_exit(struct kvm_vcpu *vcpu)\n--\narch/x86/kvm/vmx/tdx.c-976-\narch/x86/kvm/vmx/tdx.c:977:\tvt_handle_nmi(vcpu);\narch/x86/kvm/vmx/tdx.c-978-\n--\narch/x86/kvm/vmx/vmx.c=1573=void vmx_vcpu_load(struct kvm_vcpu *vcpu, int cpu)\n--\narch/x86/kvm/vmx/vmx.c-1579-\narch/x86/kvm/vmx/vmx.c:1580:\tvt_vcpu_pi_load(vcpu, cpu);\narch/x86/kvm/vmx/vmx.c-1581-}\n--\narch/x86/kvm/vmx/vmx.c=1583=void vmx_vcpu_put(struct kvm_vcpu *vcpu)\narch/x86/kvm/vmx/vmx.c-1584-{\narch/x86/kvm/vmx/vmx.c:1585:\tvt_vcpu_pi_put(vcpu);\narch/x86/kvm/vmx/vmx.c-1586-\n--\narch/x86/kvm/vmx/vmx.c=7366=static noinstr void vmx_vcpu_enter_exit(struct kvm_vcpu *vcpu,\n--\narch/x86/kvm/vmx/vmx.c-7397-\narch/x86/kvm/vmx/vmx.c:7398:\tvt_handle_nmi(vcpu);\narch/x86/kvm/vmx/vmx.c-7399-\n"
} |
| 9/2 | 2026/09/05 09:24 | llm | patch-evaluator |
0mModel:gemini-3.7-flash Args: null Results: null Tokens: input: 27651 output: 39 thoughts: 272 Thoughts: **My Analysis of KVM Configuration for Focus Symbols** Okay, let's break this down. My goal here is to understand the KVM configuration relevant to a specific set of functions, which I'll call the `FocusSymbols`. First, I'll define those symbols: `vt_handle_exit_irqoff`, `vt_handle_nmi`, `vt_vcpu_pi_load`, `vt_vcpu_pi_put`, `vt_pi_start_bypass`, `vt_pi_update_irte`, `vmx_handle_exit`, `vmx_vcpu_run`, and `nested_vmx_reflect_vmexit`. Now, I need to relate these symbols to relevant kernel configuration options. Next, I need to identify the `EnableConfigs`. I'll start by checking for the presence of `KVM` and `KVM_INTEL`. Since this environment *might* include Intel Trust Domain Extensions, or TDX, I also need to verify `KVM_INTEL_TDX`. It's important to recognize that `KVM_INTEL` is the primary configuration, and `KVM_INTEL_TDX` is contingent on it, if it is enabled. So, I will check for these options in the defined order. Now, I need to explicitly verify the dependency of `KVM_INTEL_TDX` on `KVM_INTEL`. I'll need to confirm that `KVM_INTEL_TDX` actually *requires* `KVM_INTEL` to be enabled. I'll need to locate this dependency within the Kconfig file, specifically `arch/x86/kvm/Kconfig`. I'll start by checking line 134 in the Kconfig file to see the details of the dependencies. |
| 10/2 | 2026/09/05 09:24 | tool | read-file |
0mArgs:{
"File": "arch/x86/kvm/Kconfig",
"FirstLine": 133,
"LineCount": 20
}Results: {
"Contents": " 133:\t\n 134:\tconfig KVM_INTEL_TDX\n 135:\t\tbool \"Intel Trust Domain Extensions (TDX) support\"\n 136:\t\tdefault y\n 137:\t\tdepends on INTEL_TDX_HOST\n 138:\t\tselect KVM_GENERIC_MEMORY_ATTRIBUTES\n 139:\t\tselect HAVE_KVM_ARCH_GMEM_POPULATE\n 140:\t\thelp\n 141:\t\t Provides support for launching Intel Trust Domain Extensions (TDX)\n 142:\t\t confidential VMs on Intel processors.\n 143:\t\n 144:\t\t If unsure, say N.\n 145:\t\n 146:\tconfig KVM_AMD\n 147:\t\ttristate \"KVM for AMD processors support\"\n 148:\t\tdepends on KVM \u0026\u0026 (CPU_SUP_AMD || CPU_SUP_HYGON)\n 149:\t\thelp\n 150:\t\t Provides support for KVM on AMD processors equipped with the AMD-V\n 151:\t\t (SVM) extensions.\n 152:\t\n"
} |
| 11/2 | 2026/09/05 09:24 | llm | patch-evaluator |
0mModel:gemini-3.7-flash Args: null Results: null Tokens: input: 28648 output: 199 thoughts: 236 Thoughts: **My KVM/TDX Configuration Check** Okay, so I'm looking at the core KVM Intel driver configuration, specifically `KVM_INTEL`, which, of course, relies on the broader `KVM` subsystem. And, I see that we are dealing with `INTEL_TDX_HOST` and `KVM_INTEL_TDX`, so this is definitely related to TDX. Let's quickly run a check to ensure everything is as expected. I see `WorthFuzzing` is set to true, good! And the `EnableConfigs` list is exactly what I anticipate: `"KVM"` and `"KVM_INTEL"`. Perfect. Now, let's examine the `FocusSymbols`. These seem spot-on. I'm seeing functions related to handling virtual terminal exits in a few different states: `vt_handle_exit_irqoff`, `vt_handle_nmi`, posted interrupt functions (`vt_vcpu_pi_load`, `vt_vcpu_pi_put`, `vt_pi_start_bypass`, `vt_pi_update_irte`), and a good look at `vmx_handle_exit` and `vmx_vcpu_run` as well as `nested_vmx_reflect_vmexit`. Yep, this all lines up with what I'd expect given the context – we're looking at potentially refactoring common VMX and TDX virtual terminal handling, exit handling with irqoff, posted interrupt functions, and exit reason/qualification accessors in KVM Intel. Looks like everything is exactly where it needs to be, so let's call `set-results`. Done. |
| 12/2 | 2026/09/05 09:24 | tool | set-results |
0mArgs:{
"EnableConfigs": [
"KVM",
"KVM_INTEL"
],
"FocusSymbols": [
"vt_handle_exit_irqoff",
"vt_handle_nmi",
"vt_vcpu_pi_load",
"vt_vcpu_pi_put",
"vt_pi_start_bypass",
"vt_pi_update_irte",
"vmx_handle_exit",
"vmx_vcpu_run",
"nested_vmx_reflect_vmexit"
],
"Reasoning": "The patch refactors KVM Intel (VMX/TDX) virtualization logic by consolidating exit status handling, exit IRQ-off processing, posted interrupt helpers, and VMCS exit qualification accessors under common vt_* abstractions. This affects core KVM VM exit handling and nested virtualization reachable on amd64.",
"WorthFuzzing": true
}Results: {
"EnableConfigs": [
"KVM",
"KVM_INTEL"
],
"FocusSymbols": [
"vt_handle_exit_irqoff",
"vt_handle_nmi",
"vt_vcpu_pi_load",
"vt_vcpu_pi_put",
"vt_pi_start_bypass",
"vt_pi_update_irte",
"vmx_handle_exit",
"vmx_vcpu_run",
"nested_vmx_reflect_vmexit"
],
"Reasoning": "The patch refactors KVM Intel (VMX/TDX) virtualization logic by consolidating exit status handling, exit IRQ-off processing, posted interrupt helpers, and VMCS exit qualification accessors under common vt_* abstractions. This affects core KVM VM exit handling and nested virtualization reachable on amd64.",
"WorthFuzzing": true
} |
| 13/1 | 2026/09/05 09:24 | action | If |
0mArgs:{
"WorthFuzzing": true
}Results: null |
| 14/2 | 2026/09/05 09:24 | agent | kmsan-evaluator |
0mModel:core Args: null Results: {
"KMSANReasoning": "The patch is a refactoring of KVM Intel VMX and TDX code to consolidate common virtualization infrastructure (VT) between standard VMX and TDX vCPUs:\n1. It defines a common wrapper layout `struct vcpu_vmx_tdx` with compile-time assertions (`static_assert`) ensuring offset matching of `struct vcpu_vt` across `vcpu_vmx` and `vcpu_tdx`.\n2. It moves and renames helper functions (`to_vt`, `vt_get_exit_reason`, `vt_get_exit_qual`, `vt_get_intr_info`, etc.) from `vmx.h`/`vmx.c` to `common.h`/`main.c`.\n3. It moves common exit and interrupt handling functions (`vt_handle_exit_irqoff`, `vt_handle_nmi`, `handle_external_interrupt_irqoff`, etc.) to `main.c`.\n4. It renames posted interrupt routines to use the `vt_` prefix across the codebase.\n\nNone of these changes allocate uninitialized memory, expose uninitialized fields or padding to user space, or alter buffer bounds. Any potential issues with struct layout or offsets are guarded at compile time by `static_assert` or would manifest as memory corruption/OOB access detectable by standard builds and KASAN. Therefore, a dedicated KMSAN fuzzing session is not warranted.",
"NeedsKMSAN": false
}Instruction: You are an expert Linux kernel security engineer specializing in kernel memory
error detectors (KASAN and KMSAN). Your job is to review the provided patch series and
determine if the code changes justify spawning a dedicated KMSAN (KernelMemorySanitizer)
fuzzing session in addition to standard KASAN fuzzing.
CRITICAL DISTINCTION BETWEEN KASAN AND KMSAN:
- Standard KASAN kernel builds (upstream-apparmor-kasan.config) already enable
a comprehensive suite of debugging tools and sanitizers, including KASAN
(out-of-bounds accesses, use-after-free, double free, invalid free), LOCKDEP
(locking bugs and deadlocks), UB-sanitizers, and memory corruption checks.
- KMSAN (KernelMemorySanitizer) detects reads of UNINITIALIZED memory (stack, heap,
or page allocations) and kernel-to-user memory info-leaks.
Rule: THERE IS NO SENSE IN RUNNING A KMSAN SESSION IF A BUG CAN BE CAUGHT BY KASAN,
LOCKDEP, OR OTHER STANDARD BUG DETECTORS.
A dedicated KMSAN fuzzing session incurs significant resource costs. You must ONLY
set NeedsKMSAN=true if the code changes introduce or expose UNINITIALIZED MEMORY risks
that are detected ONLY by KMSAN.
Look holistically at the patch series and surrounding code. Even if no direct
uninitialized field accesses or new buffer allocations are added in the diff itself,
a patch may alter control flow, bounds checking, or data length calculations in ways
that change how the rest of the code operates on existing buffers (e.g. allowing
uninitialized stack/heap memory to be read, copied to user space, or used in control
flow). Do not hesitate to use your code access tools to inspect the surrounding code,
called functions, and callers.
Set NeedsKMSAN=true ONLY IF the patch introduces or modifies:
1. Kernel structures sent to user space (via copy_to_user, put_user, netlink skb
attributes, ioctl output arguments, socket options, or BPF buffers) where fields
or structure padding might not be fully initialized/zeroed.
2. Conditional logic or branching that depends on potentially uninitialized variables
or struct fields.
3. Allocation or initialization of complex data structures where uninitialized fields
could be read later in reachable code paths.
4. Bounds checks, lengths, or logic in a way that allows surrounding code to access
uninitialized bytes of existing buffers.
Set NeedsKMSAN=false IF:
- The code changes primarily risk out-of-bounds access, array overflows, NULL pointer
dereferences, locking deadlocks, or use-after-free bugs (these are already caught
by KASAN, LOCKDEP, or standard bug detectors).
- All stack/heap structures touched or introduced by the patch are fully zeroed
or initialized (e.g. using = {0}, memset, kzalloc) before being read or copied.
- The patch does not introduce any risk of uninitialized memory usage or info-leaks.
Use your code access tools to inspect the surrounding code if necessary, then provide
detailed KMSANReasoning contrasting KASAN vs KMSAN applicability for this patch.
Prefer calling several tools at the same time to save round-trips.
Use set-results tool to provide results of the analysis.
It must be called exactly once before the final reply.
Ignore results of this tool.
Prompt: Target architecture: amd64
For your convenience, here is the diff of the changes:
commit 9d25f06a93aabe64fbad0ded74f73000f4a47cc3
Author: syz-cluster <triage@syzkaller.com>
Date: Sat Sep 5 09:24:22 2026 +0000
syz-cluster: applied patch under review
diff --git a/arch/x86/kvm/vmx/common.h b/arch/x86/kvm/vmx/common.h
index 08005676702c2..3e68fa12aca65 100644
--- a/arch/x86/kvm/vmx/common.h
+++ b/arch/x86/kvm/vmx/common.h
@@ -2,10 +2,12 @@
#ifndef __KVM_X86_VMX_COMMON_H
#define __KVM_X86_VMX_COMMON_H
+#include <linux/container_of.h>
#include <linux/kvm_host.h>
#include <asm/posted_intr.h>
#include "mmu.h"
+#include "vmx_ops.h"
union vmx_exit_reason {
struct {
@@ -74,14 +76,62 @@ static __always_inline bool is_td_vcpu(struct kvm_vcpu *vcpu) { return false; }
#endif
+struct vcpu_vmx_tdx {
+ struct kvm_vcpu vcpu;
+ struct vcpu_vt vt;
+};
+
+static __always_inline struct vcpu_vt *to_vt(struct kvm_vcpu *vcpu)
+{
+ return &(container_of(vcpu, struct vcpu_vmx_tdx, vcpu)->vt);
+}
+
+static __always_inline struct kvm_vcpu *vt_to_vcpu(struct vcpu_vt *vt)
+{
+ return &(container_of(vt, struct vcpu_vmx_tdx, vt)->vcpu);
+}
+
+static __always_inline union vmx_exit_reason vt_get_exit_reason(struct kvm_vcpu *vcpu)
+{
+ return to_vt(vcpu)->exit_reason;
+}
+
+static __always_inline unsigned long vt_get_exit_qual(struct kvm_vcpu *vcpu)
+{
+ struct vcpu_vt *vt = to_vt(vcpu);
+
+ if (!kvm_register_test_and_mark_available(vcpu, VCPU_REG_EXIT_INFO_1) &&
+ !WARN_ON_ONCE(is_td_vcpu(vcpu)))
+ vt->exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
+
+ return vt->exit_qualification;
+}
+
+static __always_inline u32 vt_get_intr_info(struct kvm_vcpu *vcpu)
+{
+ struct vcpu_vt *vt = to_vt(vcpu);
+
+ if (!kvm_register_test_and_mark_available(vcpu, VCPU_REG_EXIT_INFO_2) &&
+ !WARN_ON_ONCE(is_td_vcpu(vcpu)))
+ vt->exit_intr_info = vmcs_read32(VM_EXIT_INTR_INFO);
+
+ return vt->exit_intr_info;
+}
+
+static inline bool is_xfd_nm_fault(struct kvm_vcpu *vcpu)
+{
+ return vcpu->arch.guest_fpu.fpstate->xfd &&
+ !kvm_is_cr0_bit_set(vcpu, X86_CR0_TS);
+}
+
static inline bool vt_is_tdx_private_gpa(struct kvm *kvm, gpa_t gpa)
{
/* For TDX the direct mask is the shared mask. */
return !kvm_is_addr_direct(kvm, gpa);
}
-static inline int __vmx_handle_ept_violation(struct kvm_vcpu *vcpu, gpa_t gpa,
- unsigned long exit_qualification)
+static inline int __vt_handle_ept_violation(struct kvm_vcpu *vcpu, gpa_t gpa,
+ unsigned long exit_qualification)
{
u64 error_code;
@@ -164,8 +214,8 @@ static inline void kvm_vcpu_trigger_posted_interrupt(struct kvm_vcpu *vcpu,
* Post an interrupt to a vCPU's PIR and trigger the vCPU to process the
* interrupt if necessary.
*/
-static inline void __vmx_deliver_posted_interrupt(struct kvm_vcpu *vcpu,
- struct pi_desc *pi_desc, int vector)
+static inline void __vt_deliver_posted_interrupt(struct kvm_vcpu *vcpu,
+ struct pi_desc *pi_desc, int vector)
{
if (pi_test_and_set_pir(vector, pi_desc))
return;
@@ -183,6 +233,6 @@ static inline void __vmx_deliver_posted_interrupt(struct kvm_vcpu *vcpu,
kvm_vcpu_trigger_posted_interrupt(vcpu, POSTED_INTR_VECTOR);
}
-noinstr void vmx_handle_nmi(struct kvm_vcpu *vcpu);
+noinstr void vt_handle_nmi(struct kvm_vcpu *vcpu);
#endif /* __KVM_X86_VMX_COMMON_H */
diff --git a/arch/x86/kvm/vmx/main.c b/arch/x86/kvm/vmx/main.c
index 4c52ab8d07869..6e0b3959d73ab 100644
--- a/arch/x86/kvm/vmx/main.c
+++ b/arch/x86/kvm/vmx/main.c
@@ -1,4 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
+#include <linux/entry-common.h>
#include <linux/moduleparam.h>
#include "x86_ops.h"
@@ -10,8 +11,12 @@
#include "tdx.h"
#include "tdx_arch.h"
+#pragma GCC poison to_vmx
+
+static_assert(offsetof(struct vcpu_vmx_tdx, vt) == offsetof(struct vcpu_vmx, vt));
+
#ifdef CONFIG_KVM_INTEL_TDX
-static_assert(offsetof(struct vcpu_vmx, vt) == offsetof(struct vcpu_tdx, vt));
+static_assert(offsetof(struct vcpu_vmx_tdx, vt) == offsetof(struct vcpu_tdx, vt));
static void vt_disable_virtualization_cpu(void)
{
@@ -876,6 +881,85 @@ static int vt_gmem_max_mapping_level(struct kvm *kvm, kvm_pfn_t pfn,
#define vt_op_tdx_only(name) NULL
#endif /* CONFIG_KVM_INTEL_TDX */
+static void handle_nm_fault_irqoff(struct kvm_vcpu *vcpu)
+{
+ /*
+ * Save xfd_err to guest_fpu before interrupt is enabled, so the
+ * MSR value is not clobbered by the host activity before the guest
+ * has chance to consume it.
+ *
+ * Update the guest's XFD_ERR if and only if XFD is enabled, as the #NM
+ * interception may have been caused by L1 interception. Per the SDM,
+ * XFD_ERR is not modified for non-XFD #NM, i.e. if CR0.TS=1.
+ *
+ * Note, XFD_ERR is updated _before_ the #NM interception check, i.e.
+ * unlike CR2 and DR6, the value is not a payload that is attached to
+ * the #NM exception.
+ */
+ if (is_xfd_nm_fault(vcpu))
+ rdmsrq(MSR_IA32_XFD_ERR, vcpu->arch.guest_fpu.xfd_err);
+}
+
+static void handle_exception_irqoff(struct kvm_vcpu *vcpu, u32 intr_info)
+{
+ /* if exit due to PF check for async PF */
+ if (is_page_fault(intr_info))
+ vcpu->arch.apf.host_apf_flags = kvm_read_and_reset_apf_flags();
+ /* if exit due to NM, handle before interrupts are enabled */
+ else if (is_nm_fault(intr_info))
+ handle_nm_fault_irqoff(vcpu);
+ /* Handle machine checks before interrupts are enabled */
+ else if (is_machine_check(intr_info))
+ kvm_machine_check();
+}
+
+static void handle_external_interrupt_irqoff(struct kvm_vcpu *vcpu,
+ u32 intr_info)
+{
+ unsigned int vector = intr_info & INTR_INFO_VECTOR_MASK;
+
+ if (KVM_BUG(!is_external_intr(intr_info), vcpu->kvm,
+ "unexpected VM-Exit interrupt info: 0x%x", intr_info))
+ return;
+
+ kvm_before_interrupt(vcpu, KVM_HANDLING_IRQ);
+ x86_entry_from_kvm(EVENT_TYPE_EXTINT, vector);
+ kvm_after_interrupt(vcpu);
+
+ vcpu->arch.at_instruction_boundary = true;
+}
+
+static void vt_handle_exit_irqoff(struct kvm_vcpu *vcpu)
+{
+ if (to_vt(vcpu)->emulation_required)
+ return;
+
+ switch (vt_get_exit_reason(vcpu).basic) {
+ case EXIT_REASON_EXTERNAL_INTERRUPT:
+ handle_external_interrupt_irqoff(vcpu, vt_get_intr_info(vcpu));
+ break;
+ case EXIT_REASON_EXCEPTION_NMI:
+ handle_exception_irqoff(vcpu, vt_get_intr_info(vcpu));
+ break;
+ case EXIT_REASON_MCE_DURING_VMENTRY:
+ kvm_machine_check();
+ break;
+ default:
+ break;
+ }
+}
+
+noinstr void vt_handle_nmi(struct kvm_vcpu *vcpu)
+{
+ if ((u16)vt_get_exit_reason(vcpu).basic != EXIT_REASON_EXCEPTION_NMI ||
+ !is_nmi(vt_get_intr_info(vcpu)))
+ return;
+
+ kvm_before_interrupt(vcpu, KVM_HANDLING_NMI);
+ x86_entry_from_kvm(EVENT_TYPE_NMI, NMI_VECTOR);
+ kvm_after_interrupt(vcpu);
+}
+
#define VMX_REQUIRED_APICV_INHIBITS \
(BIT(APICV_INHIBIT_REASON_DISABLED) | \
BIT(APICV_INHIBIT_REASON_ABSENT) | \
@@ -1000,12 +1084,12 @@ struct kvm_x86_ops vt_x86_ops __initdata = {
.load_mmu_pgd = vt_op(load_mmu_pgd),
.check_intercept = vmx_check_intercept,
- .handle_exit_irqoff = vmx_handle_exit_irqoff,
+ .handle_exit_irqoff = vt_handle_exit_irqoff,
.update_cpu_dirty_logging = vt_op(update_cpu_dirty_logging),
- .pi_update_irte = vmx_pi_update_irte,
- .pi_start_bypass = vmx_pi_start_bypass,
+ .pi_update_irte = vt_pi_update_irte,
+ .pi_start_bypass = vt_pi_start_bypass,
#ifdef CONFIG_X86_64
.set_hv_timer = vt_op(set_hv_timer),
diff --git a/arch/x86/kvm/vmx/nested.c b/arch/x86/kvm/vmx/nested.c
index 151873407abd3..47599e7312cfd 100644
--- a/arch/x86/kvm/vmx/nested.c
+++ b/arch/x86/kvm/vmx/nested.c
@@ -446,7 +446,7 @@ static void nested_ept_inject_page_fault(struct kvm_vcpu *vcpu,
* "NMI unblocking due to IRET", i.e. the bit can be propagated
* as-is from the original EXIT_QUALIFICATION.
*/
- exit_qualification = vmx_get_exit_qual(vcpu) & INTR_INFO_UNBLOCK_NMI;
+ exit_qualification = vt_get_exit_qual(vcpu) & INTR_INFO_UNBLOCK_NMI;
} else {
if (fault->error_code & PFERR_RSVD_MASK) {
vm_exit_reason = EXIT_REASON_EPT_MISCONFIG;
@@ -472,7 +472,7 @@ static void nested_ept_inject_page_fault(struct kvm_vcpu *vcpu,
* and walks the faulting GPA.
*/
if (from_hardware)
- exit_qualification |= vmx_get_exit_qual(vcpu) & mask;
+ exit_qualification |= vt_get_exit_qual(vcpu) & mask;
else
exit_qualification |= fault->exit_qualification & mask;
@@ -4747,7 +4747,7 @@ static void prepare_vmcs12(struct kvm_vcpu *vcpu, struct vmcs12 *vmcs12,
{
/* update exit information fields: */
vmcs12->vm_exit_reason = vm_exit_reason;
- if (vmx_get_exit_reason(vcpu).enclave_mode)
+ if (vt_get_exit_reason(vcpu).enclave_mode)
vmcs12->vm_exit_reason |= VMX_EXIT_REASONS_SGX_ENCLAVE_MODE;
vmcs12->exit_qualification = exit_qualification;
@@ -5373,7 +5373,7 @@ static int nested_vmx_get_vmptr(struct kvm_vcpu *vcpu, gpa_t *vmpointer,
struct x86_exception e;
int r;
- if (get_vmx_mem_address(vcpu, vmx_get_exit_qual(vcpu),
+ if (get_vmx_mem_address(vcpu, vt_get_exit_qual(vcpu),
vmcs_read32(VMX_INSTRUCTION_INFO), false,
sizeof(*vmpointer), &gva)) {
*ret = 1;
@@ -5665,7 +5665,7 @@ static int handle_vmread(struct kvm_vcpu *vcpu)
{
struct vmcs12 *vmcs12 = is_guest_mode(vcpu) ? get_shadow_vmcs12(vcpu)
: get_vmcs12(vcpu);
- unsigned long exit_qualification = vmx_get_exit_qual(vcpu);
+ unsigned long exit_qualification = vt_get_exit_qual(vcpu);
u32 instr_info = vmcs_read32(VMX_INSTRUCTION_INFO);
struct vcpu_vmx *vmx = to_vmx(vcpu);
struct x86_exception e;
@@ -5771,7 +5771,7 @@ static int handle_vmwrite(struct kvm_vcpu *vcpu)
{
struct vmcs12 *vmcs12 = is_guest_mode(vcpu) ? get_shadow_vmcs12(vcpu)
: get_vmcs12(vcpu);
- unsigned long exit_qualification = vmx_get_exit_qual(vcpu);
+ unsigned long exit_qualification = vt_get_exit_qual(vcpu);
u32 instr_info = vmcs_read32(VMX_INSTRUCTION_INFO);
struct vcpu_vmx *vmx = to_vmx(vcpu);
struct x86_exception e;
@@ -5960,7 +5960,7 @@ static int handle_vmptrld(struct kvm_vcpu *vcpu)
/* Emulate the VMPTRST instruction */
static int handle_vmptrst(struct kvm_vcpu *vcpu)
{
- unsigned long exit_qual = vmx_get_exit_qual(vcpu);
+ unsigned long exit_qual = vt_get_exit_qual(vcpu);
u32 instr_info = vmcs_read32(VMX_INSTRUCTION_INFO);
gpa_t current_vmptr = to_vmx(vcpu)->nested.current_vmptr;
struct x86_exception e;
@@ -6021,7 +6021,7 @@ static int handle_invept(struct kvm_vcpu *vcpu)
/* According to the Intel VMX instruction reference, the memory
* operand is read even if it isn't needed (e.g., for type==global)
*/
- if (get_vmx_mem_address(vcpu, vmx_get_exit_qual(vcpu),
+ if (get_vmx_mem_address(vcpu, vt_get_exit_qual(vcpu),
vmx_instruction_info, false, sizeof(operand), &gva))
return 1;
r = kvm_read_guest_virt(vcpu, gva, &operand, sizeof(operand), &e);
@@ -6104,7 +6104,7 @@ static int handle_invvpid(struct kvm_vcpu *vcpu)
/* according to the intel vmx instruction reference, the memory
* operand is read even if it isn't needed (e.g., for type==global)
*/
- if (get_vmx_mem_address(vcpu, vmx_get_exit_qual(vcpu),
+ if (get_vmx_mem_address(vcpu, vt_get_exit_qual(vcpu),
vmx_instruction_info, false, sizeof(operand), &gva))
return 1;
r = kvm_read_guest_virt(vcpu, gva, &operand, sizeof(operand), &e);
@@ -6236,8 +6236,8 @@ static int handle_vmfunc(struct kvm_vcpu *vcpu)
* EXIT_REASON_VMFUNC as the exit reason.
*/
nested_vmx_vmexit(vcpu, vmx->vt.exit_reason.full,
- vmx_get_intr_info(vcpu),
- vmx_get_exit_qual(vcpu));
+ vt_get_intr_info(vcpu),
+ vt_get_exit_qual(vcpu));
return 1;
}
@@ -6288,7 +6288,7 @@ static bool nested_vmx_exit_handled_io(struct kvm_vcpu *vcpu,
if (!nested_cpu_has(vmcs12, CPU_BASED_USE_IO_BITMAPS))
return nested_cpu_has(vmcs12, CPU_BASED_UNCOND_IO_EXITING);
- exit_qualification = vmx_get_exit_qual(vcpu);
+ exit_qualification = vt_get_exit_qual(vcpu);
port = exit_qualification >> 16;
size = (exit_qualification & 7) + 1;
@@ -6314,7 +6314,7 @@ static bool nested_vmx_exit_handled_msr(struct kvm_vcpu *vcpu,
if (exit_reason.basic == EXIT_REASON_MSR_READ_IMM ||
exit_reason.basic == EXIT_REASON_MSR_WRITE_IMM)
- msr_index = vmx_get_exit_qual(vcpu);
+ msr_index = vt_get_exit_qual(vcpu);
else
msr_index = kvm_ecx_read(vcpu);
@@ -6350,7 +6350,7 @@ static bool nested_vmx_exit_handled_msr(struct kvm_vcpu *vcpu,
static bool nested_vmx_exit_handled_cr(struct kvm_vcpu *vcpu,
struct vmcs12 *vmcs12)
{
- unsigned long exit_qualification = vmx_get_exit_qual(vcpu);
+ unsigned long exit_qualification = vt_get_exit_qual(vcpu);
int cr = exit_qualification & 15;
int reg;
unsigned long val;
@@ -6484,7 +6484,7 @@ static bool nested_vmx_l0_wants_exit(struct kvm_vcpu *vcpu,
switch ((u16)exit_reason.basic) {
case EXIT_REASON_EXCEPTION_NMI:
- intr_info = vmx_get_intr_info(vcpu);
+ intr_info = vt_get_intr_info(vcpu);
if (is_nmi(intr_info))
return true;
else if (is_page_fault(intr_info))
@@ -6567,7 +6567,7 @@ static bool nested_vmx_l1_wants_exit(struct kvm_vcpu *vcpu,
switch ((u16)exit_reason.basic) {
case EXIT_REASON_EXCEPTION_NMI:
- intr_info = vmx_get_intr_info(vcpu);
+ intr_info = vt_get_intr_info(vcpu);
if (is_nmi(intr_info))
return true;
else if (is_page_fault(intr_info))
@@ -6737,14 +6737,14 @@ bool nested_vmx_reflect_vmexit(struct kvm_vcpu *vcpu)
* need to be synthesized by querying the in-kernel LAPIC, but external
* interrupts are never reflected to L1 so it's a non-issue.
*/
- exit_intr_info = vmx_get_intr_info(vcpu);
+ exit_intr_info = vt_get_intr_info(vcpu);
if (is_exception_with_error_code(exit_intr_info)) {
struct vmcs12 *vmcs12 = get_vmcs12(vcpu);
vmcs12->vm_exit_intr_error_code =
vmcs_read32(VM_EXIT_INTR_ERROR_CODE);
}
- exit_qual = vmx_get_exit_qual(vcpu);
+ exit_qual = vt_get_exit_qual(vcpu);
reflect_vmexit:
nested_vmx_vmexit(vcpu, exit_reason.full, exit_intr_info, exit_qual);
diff --git a/arch/x86/kvm/vmx/posted_intr.c b/arch/x86/kvm/vmx/posted_intr.c
index 4a6d9a17da238..2644add54b76b 100644
--- a/arch/x86/kvm/vmx/posted_intr.c
+++ b/arch/x86/kvm/vmx/posted_intr.c
@@ -14,6 +14,8 @@
#include "vmx.h"
#include "tdx.h"
+#pragma GCC poison to_vmx
+
/*
* Maintain a per-CPU list of vCPUs that need to be awakened by wakeup_handler()
* when a WAKEUP_VECTOR interrupted is posted. vCPUs are added to the list when
@@ -54,7 +56,7 @@ static int pi_try_set_control(struct pi_desc *pi_desc, u64 *pold, u64 new)
return 0;
}
-void vmx_vcpu_pi_load(struct kvm_vcpu *vcpu, int cpu)
+void vt_vcpu_pi_load(struct kvm_vcpu *vcpu, int cpu)
{
struct pi_desc *pi_desc = vcpu_to_pi_desc(vcpu);
struct vcpu_vt *vt = to_vt(vcpu);
@@ -144,11 +146,11 @@ void vmx_vcpu_pi_load(struct kvm_vcpu *vcpu, int cpu)
pi_set_on(pi_desc);
}
-static bool vmx_can_use_vtd_pi(struct kvm *kvm)
+static bool vt_can_use_vtd_pi(struct kvm *kvm)
{
/*
* Note, reading the number of possible bypass IRQs can race with a
- * bypass IRQ being attached to the VM. vmx_pi_start_bypass() ensures
+ * bypass IRQ being attached to the VM. vt_pi_start_bypass() ensures
* blockng vCPUs will see an elevated count or get KVM_REQ_UNBLOCK.
*/
return irqchip_in_kernel(kvm) && kvm_arch_has_irq_bypass() &&
@@ -206,7 +208,7 @@ static void pi_enable_wakeup_handler(struct kvm_vcpu *vcpu)
__apic_send_IPI_self(POSTED_INTR_WAKEUP_VECTOR);
}
-static bool vmx_needs_pi_wakeup(struct kvm_vcpu *vcpu)
+static bool vt_needs_pi_wakeup(struct kvm_vcpu *vcpu)
{
/*
* The default posted interrupt vector does nothing when
@@ -217,14 +219,14 @@ static bool vmx_needs_pi_wakeup(struct kvm_vcpu *vcpu)
* back to the pi_wakeup_handler() function.
*/
return (vmx_can_use_ipiv(vcpu) && !is_td_vcpu(vcpu)) ||
- vmx_can_use_vtd_pi(vcpu->kvm);
+ vt_can_use_vtd_pi(vcpu->kvm);
}
-void vmx_vcpu_pi_put(struct kvm_vcpu *vcpu)
+void vt_vcpu_pi_put(struct kvm_vcpu *vcpu)
{
struct pi_desc *pi_desc = vcpu_to_pi_desc(vcpu);
- if (!vmx_needs_pi_wakeup(vcpu))
+ if (!vt_needs_pi_wakeup(vcpu))
return;
/*
@@ -292,17 +294,17 @@ bool pi_has_pending_interrupt(struct kvm_vcpu *vcpu)
/*
* Kick all vCPUs when the first possible bypass IRQ is attached to a VM, as
* blocking vCPUs may scheduled out without reconfiguring PID.NV to the wakeup
- * vector, i.e. if the bypass IRQ came along after vmx_vcpu_pi_put().
+ * vector, i.e. if the bypass IRQ came along after vt_vcpu_pi_put().
*/
-void vmx_pi_start_bypass(struct kvm *kvm)
+void vt_pi_start_bypass(struct kvm *kvm)
{
- if (WARN_ON_ONCE(!vmx_can_use_vtd_pi(kvm)))
+ if (WARN_ON_ONCE(!vt_can_use_vtd_pi(kvm)))
return;
kvm_make_all_cpus_request(kvm, KVM_REQ_UNBLOCK);
}
-int vmx_pi_update_irte(struct kvm_kernel_irqfd *irqfd, struct kvm *kvm,
+int vt_pi_update_irte(struct kvm_kernel_irqfd *irqfd, struct kvm *kvm,
unsigned int host_irq, uint32_t guest_irq,
struct kvm_vcpu *vcpu, u32 vector)
{
diff --git a/arch/x86/kvm/vmx/posted_intr.h b/arch/x86/kvm/vmx/posted_intr.h
index a4af39948cf04..c5860ea828ae9 100644
--- a/arch/x86/kvm/vmx/posted_intr.h
+++ b/arch/x86/kvm/vmx/posted_intr.h
@@ -8,16 +8,16 @@
#include <asm/posted_intr.h>
-void vmx_vcpu_pi_load(struct kvm_vcpu *vcpu, int cpu);
-void vmx_vcpu_pi_put(struct kvm_vcpu *vcpu);
+void vt_vcpu_pi_load(struct kvm_vcpu *vcpu, int cpu);
+void vt_vcpu_pi_put(struct kvm_vcpu *vcpu);
void pi_wakeup_handler(void);
void __init pi_init_cpu(int cpu);
void pi_apicv_pre_state_restore(struct kvm_vcpu *vcpu);
bool pi_has_pending_interrupt(struct kvm_vcpu *vcpu);
-int vmx_pi_update_irte(struct kvm_kernel_irqfd *irqfd, struct kvm *kvm,
+int vt_pi_update_irte(struct kvm_kernel_irqfd *irqfd, struct kvm *kvm,
unsigned int host_irq, uint32_t guest_irq,
struct kvm_vcpu *vcpu, u32 vector);
-void vmx_pi_start_bypass(struct kvm *kvm);
+void vt_pi_start_bypass(struct kvm *kvm);
static inline int pi_find_highest_vector(struct pi_desc *pi_desc)
{
diff --git a/arch/x86/kvm/vmx/tdx.c b/arch/x86/kvm/vmx/tdx.c
index b272c20586a74..efbb1ac6f51ea 100644
--- a/arch/x86/kvm/vmx/tdx.c
+++ b/arch/x86/kvm/vmx/tdx.c
@@ -716,7 +716,7 @@ void tdx_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
{
struct vcpu_tdx *tdx = to_tdx(vcpu);
- vmx_vcpu_pi_load(vcpu, cpu);
+ vt_vcpu_pi_load(vcpu, cpu);
if (vcpu->cpu == cpu || !is_hkid_assigned(to_kvm_tdx(vcpu->kvm)))
return;
@@ -741,7 +741,7 @@ bool tdx_interrupt_allowed(struct kvm_vcpu *vcpu)
* interrupt is always allowed unless TDX guest calls TDVMCALL with HLT,
* which passes the interrupt blocked flag.
*/
- return vmx_get_exit_reason(vcpu).basic != EXIT_REASON_HLT ||
+ return vt_get_exit_reason(vcpu).basic != EXIT_REASON_HLT ||
!to_tdx(vcpu)->vp_enter_args.r12;
}
@@ -759,7 +759,7 @@ static bool tdx_protected_apic_has_interrupt(struct kvm_vcpu *vcpu)
* otherwise the interrupt would have been serviced at the instruction
* boundary.
*/
- if (vmx_get_exit_reason(vcpu).basic != EXIT_REASON_HLT ||
+ if (vt_get_exit_reason(vcpu).basic != EXIT_REASON_HLT ||
to_tdx(vcpu)->vp_enter_args.r12)
return false;
@@ -826,7 +826,7 @@ static void tdx_prepare_switch_to_host(struct kvm_vcpu *vcpu)
void tdx_vcpu_put(struct kvm_vcpu *vcpu)
{
- vmx_vcpu_pi_put(vcpu);
+ vt_vcpu_pi_put(vcpu);
tdx_prepare_switch_to_host(vcpu);
}
@@ -974,15 +974,15 @@ static noinstr void tdx_vcpu_enter_exit(struct kvm_vcpu *vcpu)
tdx->exit_gpa = tdx->vp_enter_args.r8;
vt->exit_intr_info = tdx->vp_enter_args.r9;
- vmx_handle_nmi(vcpu);
+ vt_handle_nmi(vcpu);
guest_state_exit_irqoff();
}
static bool tdx_failed_vmentry(struct kvm_vcpu *vcpu)
{
- return vmx_get_exit_reason(vcpu).failed_vmentry &&
- vmx_get_exit_reason(vcpu).full != -1u;
+ return vt_get_exit_reason(vcpu).failed_vmentry &&
+ vt_get_exit_reason(vcpu).full != -1u;
}
static fastpath_t tdx_exit_handlers_fastpath(struct kvm_vcpu *vcpu)
@@ -1131,7 +1131,7 @@ void tdx_inject_nmi(struct kvm_vcpu *vcpu)
static int tdx_handle_exception_nmi(struct kvm_vcpu *vcpu)
{
- u32 intr_info = vmx_get_intr_info(vcpu);
+ u32 intr_info = vt_get_intr_info(vcpu);
/*
* Machine checks are handled by handle_exception_irqoff(), or by
@@ -1895,7 +1895,7 @@ void tdx_deliver_interrupt(struct kvm_lapic *apic, int delivery_mode,
struct vcpu_tdx *tdx = to_tdx(vcpu);
/* TDX supports only posted interrupt. No lapic emulation. */
- __vmx_deliver_posted_interrupt(vcpu, &tdx->vt.pi_desc, vector);
+ __vt_deliver_posted_interrupt(vcpu, &tdx->vt.pi_desc, vector);
trace_kvm_apicv_accept_irq(vcpu->vcpu_id, delivery_mode, trig_mode, vector);
}
@@ -1903,7 +1903,7 @@ void tdx_deliver_interrupt(struct kvm_lapic *apic, int delivery_mode,
static inline bool tdx_is_sept_violation_unexpected_pending(struct kvm_vcpu *vcpu)
{
u64 eeq_type = to_tdx(vcpu)->ext_exit_qualification & TDX_EXT_EXIT_QUAL_TYPE_MASK;
- u64 eq = vmx_get_exit_qual(vcpu);
+ u64 eq = vt_get_exit_qual(vcpu);
if (eeq_type != TDX_EXT_EXIT_QUAL_TYPE_PENDING_EPT_VIOLATION)
return false;
@@ -1939,7 +1939,7 @@ static int tdx_handle_ept_violation(struct kvm_vcpu *vcpu)
/* Only private GPA triggers zero-step mitigation */
local_retry = true;
} else {
- exit_qual = vmx_get_exit_qual(vcpu);
+ exit_qual = vt_get_exit_qual(vcpu);
/*
* EPT violation due to instruction fetch should never be
* triggered from shared memory in TDX guest. If such EPT
@@ -1987,7 +1987,7 @@ static int tdx_handle_ept_violation(struct kvm_vcpu *vcpu)
while (1) {
struct kvm_memory_slot *slot;
- ret = __vmx_handle_ept_violation(vcpu, gpa, exit_qual);
+ ret = __vt_handle_ept_violation(vcpu, gpa, exit_qual);
if (ret != RET_PF_RETRY || !local_retry)
break;
@@ -2021,7 +2021,7 @@ int tdx_complete_emulated_msr(struct kvm_vcpu *vcpu, int err)
return 1;
}
- if (vmx_get_exit_reason(vcpu).basic == EXIT_REASON_MSR_READ)
+ if (vt_get_exit_reason(vcpu).basic == EXIT_REASON_MSR_READ)
tdvmcall_set_return_val(vcpu, kvm_read_edx_eax(vcpu));
return 1;
@@ -2032,7 +2032,7 @@ int tdx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t fastpath)
{
struct vcpu_tdx *tdx = to_tdx(vcpu);
u64 vp_enter_ret = tdx->vp_enter_ret;
- union vmx_exit_reason exit_reason = vmx_get_exit_reason(vcpu);
+ union vmx_exit_reason exit_reason = vt_get_exit_reason(vcpu);
if (fastpath != EXIT_FASTPATH_NONE)
return 1;
@@ -2142,9 +2142,9 @@ void tdx_get_exit_info(struct kvm_vcpu *vcpu, u32 *reason,
*reason = tdx->vt.exit_reason.full;
if (*reason != -1u) {
- *info1 = vmx_get_exit_qual(vcpu);
+ *info1 = vt_get_exit_qual(vcpu);
*info2 = tdx->ext_exit_qualification;
- *intr_info = vmx_get_intr_info(vcpu);
+ *intr_info = vt_get_intr_info(vcpu);
} else {
*info1 = 0;
*info2 = 0;
diff --git a/arch/x86/kvm/vmx/vmx.c b/arch/x86/kvm/vmx/vmx.c
index 504630f0eb40f..7e35c2d03c69e 100644
--- a/arch/x86/kvm/vmx/vmx.c
+++ b/arch/x86/kvm/vmx/vmx.c
@@ -1577,12 +1577,12 @@ void vmx_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
vmx_vcpu_load_vmcs(vcpu, cpu);
- vmx_vcpu_pi_load(vcpu, cpu);
+ vt_vcpu_pi_load(vcpu, cpu);
}
void vmx_vcpu_put(struct kvm_vcpu *vcpu)
{
- vmx_vcpu_pi_put(vcpu);
+ vt_vcpu_pi_put(vcpu);
vmx_prepare_switch_to_host(to_vmx(vcpu));
}
@@ -1791,7 +1791,7 @@ int vmx_check_emulate_instruction(struct kvm_vcpu *vcpu, int emul_type,
* so that guest userspace can't DoS the guest simply by triggering
* emulation (enclaves are CPL3 only).
*/
- if (vmx_get_exit_reason(vcpu).enclave_mode) {
+ if (vt_get_exit_reason(vcpu).enclave_mode) {
kvm_queue_exception(vcpu, UD_VECTOR);
return X86EMUL_PROPAGATE_FAULT;
}
@@ -1806,7 +1806,7 @@ int vmx_check_emulate_instruction(struct kvm_vcpu *vcpu, int emul_type,
static int skip_emulated_instruction(struct kvm_vcpu *vcpu)
{
- union vmx_exit_reason exit_reason = vmx_get_exit_reason(vcpu);
+ union vmx_exit_reason exit_reason = vt_get_exit_reason(vcpu);
unsigned long rip, orig_rip;
u32 instr_len;
@@ -4424,7 +4424,7 @@ static int vmx_deliver_posted_interrupt(struct kvm_vcpu *vcpu, int vector)
if (!vcpu->arch.apic->apicv_active)
return -1;
- __vmx_deliver_posted_interrupt(vcpu, &vt->pi_desc, vector);
+ __vt_deliver_posted_interrupt(vcpu, &vt->pi_desc, vector);
return 0;
}
@@ -5379,15 +5379,9 @@ bool vmx_guest_inject_ac(struct kvm_vcpu *vcpu)
(kvm_get_rflags(vcpu) & X86_EFLAGS_AC);
}
-static bool is_xfd_nm_fault(struct kvm_vcpu *vcpu)
-{
- return vcpu->arch.guest_fpu.fpstate->xfd &&
- !kvm_is_cr0_bit_set(vcpu, X86_CR0_TS);
-}
-
static int vmx_handle_page_fault(struct kvm_vcpu *vcpu, u32 error_code)
{
- unsigned long cr2 = vmx_get_exit_qual(vcpu);
+ unsigned long cr2 = vt_get_exit_qual(vcpu);
if (vcpu->arch.apf.host_apf_flags)
goto handle_pf;
@@ -5435,7 +5429,7 @@ static int handle_exception_nmi(struct kvm_vcpu *vcpu)
u32 vect_info;
vect_info = vmx->idt_vectoring_info;
- intr_info = vmx_get_intr_info(vcpu);
+ intr_info = vt_get_intr_info(vcpu);
/*
* Machine checks are handled by handle_exception_irqoff(), or by
@@ -5516,7 +5510,7 @@ static int handle_exception_nmi(struct kvm_vcpu *vcpu)
switch (ex_no) {
case DB_VECTOR:
- dr6 = vmx_get_exit_qual(vcpu);
+ dr6 = vt_get_exit_qual(vcpu);
if (!(vcpu->guest_debug &
(KVM_GUESTDBG_SINGLESTEP | KVM_GUESTDBG_USE_HW_BP))) {
/*
@@ -5592,7 +5586,7 @@ static int handle_io(struct kvm_vcpu *vcpu)
int size, in, string;
unsigned port;
- exit_qualification = vmx_get_exit_qual(vcpu);
+ exit_qualification = vt_get_exit_qual(vcpu);
string = (exit_qualification & 16) != 0;
++vcpu->stat.io_exits;
@@ -5681,7 +5675,7 @@ static int handle_cr(struct kvm_vcpu *vcpu)
int err;
int ret;
- exit_qualification = vmx_get_exit_qual(vcpu);
+ exit_qualification = vt_get_exit_qual(vcpu);
cr = exit_qualification & 15;
reg = (exit_qualification >> 8) & 15;
switch ((exit_qualification >> 4) & 3) {
@@ -5759,7 +5753,7 @@ static int handle_dr(struct kvm_vcpu *vcpu)
int dr, dr7, reg;
int err = 1;
- exit_qualification = vmx_get_exit_qual(vcpu);
+ exit_qualification = vt_get_exit_qual(vcpu);
dr = exit_qualification & DEBUG_REG_ACCESS_NUM;
/* First, if DR does not exist, trigger UD */
@@ -5855,7 +5849,7 @@ static int handle_interrupt_window(struct kvm_vcpu *vcpu)
static int handle_invlpg(struct kvm_vcpu *vcpu)
{
- unsigned long exit_qualification = vmx_get_exit_qual(vcpu);
+ unsigned long exit_qualification = vt_get_exit_qual(vcpu);
kvm_mmu_invlpg(vcpu, exit_qualification);
return kvm_skip_emulated_instruction(vcpu);
@@ -5864,7 +5858,7 @@ static int handle_invlpg(struct kvm_vcpu *vcpu)
static int handle_apic_access(struct kvm_vcpu *vcpu)
{
if (likely(fasteoi)) {
- unsigned long exit_qualification = vmx_get_exit_qual(vcpu);
+ unsigned long exit_qualification = vt_get_exit_qual(vcpu);
int access_type, offset;
access_type = exit_qualification & APIC_ACCESS_TYPE;
@@ -5885,7 +5879,7 @@ static int handle_apic_access(struct kvm_vcpu *vcpu)
static int handle_apic_eoi_induced(struct kvm_vcpu *vcpu)
{
- unsigned long exit_qualification = vmx_get_exit_qual(vcpu);
+ unsigned long exit_qualification = vt_get_exit_qual(vcpu);
int vector = exit_qualification & 0xff;
/* EOI-induced VM exit is trap-like and thus no need to adjust IP */
@@ -5895,7 +5889,7 @@ static int handle_apic_eoi_induced(struct kvm_vcpu *vcpu)
static int handle_apic_write(struct kvm_vcpu *vcpu)
{
- unsigned long exit_qualification = vmx_get_exit_qual(vcpu);
+ unsigned long exit_qualification = vt_get_exit_qual(vcpu);
/*
* APIC-write VM-Exit is trap-like, KVM doesn't need to advance RIP and
@@ -5923,7 +5917,7 @@ static int handle_task_switch(struct kvm_vcpu *vcpu)
idt_index = (vmx->idt_vectoring_info & VECTORING_INFO_VECTOR_MASK);
type = (vmx->idt_vectoring_info & VECTORING_INFO_TYPE_MASK);
- exit_qualification = vmx_get_exit_qual(vcpu);
+ exit_qualification = vt_get_exit_qual(vcpu);
reason = (u32)exit_qualification >> 30;
if (reason == TASK_SWITCH_GATE && idt_v) {
@@ -5969,7 +5963,7 @@ static int handle_task_switch(struct kvm_vcpu *vcpu)
static int handle_ept_violation(struct kvm_vcpu *vcpu)
{
- unsigned long exit_qualification = vmx_get_exit_qual(vcpu);
+ unsigned long exit_qualification = vt_get_exit_qual(vcpu);
gpa_t gpa;
/*
@@ -5997,7 +5991,7 @@ static int handle_ept_violation(struct kvm_vcpu *vcpu)
if (unlikely(allow_smaller_maxphyaddr && !kvm_vcpu_is_legal_gpa(vcpu, gpa)))
return kvm_emulate_instruction(vcpu, 0);
- return __vmx_handle_ept_violation(vcpu, gpa, exit_qualification);
+ return __vt_handle_ept_violation(vcpu, gpa, exit_qualification);
}
static int handle_ept_misconfig(struct kvm_vcpu *vcpu)
@@ -6160,7 +6154,7 @@ static int handle_invpcid(struct kvm_vcpu *vcpu)
/* According to the Intel instruction reference, the memory operand
* is read even if it isn't needed (e.g., for type==all)
*/
- if (get_vmx_mem_address(vcpu, vmx_get_exit_qual(vcpu),
+ if (get_vmx_mem_address(vcpu, vt_get_exit_qual(vcpu),
vmx_instruction_info, false,
sizeof(operand), &gva))
return 1;
@@ -6174,7 +6168,7 @@ static int handle_pml_full(struct kvm_vcpu *vcpu)
trace_kvm_pml_full(vcpu->vcpu_id);
- exit_qualification = vmx_get_exit_qual(vcpu);
+ exit_qualification = vt_get_exit_qual(vcpu);
/*
* PML buffer FULL happened while executing iret from NMI,
@@ -6278,7 +6272,7 @@ static int handle_bus_lock_vmexit(struct kvm_vcpu *vcpu)
static int handle_notify(struct kvm_vcpu *vcpu)
{
- unsigned long exit_qual = vmx_get_exit_qual(vcpu);
+ unsigned long exit_qual = vt_get_exit_qual(vcpu);
bool context_invalid = exit_qual & NOTIFY_VM_CONTEXT_INVALID;
++vcpu->stat.notify_window_exits;
@@ -6309,13 +6303,13 @@ static int vmx_get_msr_imm_reg(struct kvm_vcpu *vcpu)
static int handle_rdmsr_imm(struct kvm_vcpu *vcpu)
{
- return kvm_emulate_rdmsr_imm(vcpu, vmx_get_exit_qual(vcpu),
+ return kvm_emulate_rdmsr_imm(vcpu, vt_get_exit_qual(vcpu),
vmx_get_msr_imm_reg(vcpu));
}
static int handle_wrmsr_imm(struct kvm_vcpu *vcpu)
{
- return kvm_emulate_wrmsr_imm(vcpu, vmx_get_exit_qual(vcpu),
+ return kvm_emulate_wrmsr_imm(vcpu, vt_get_exit_qual(vcpu),
vmx_get_msr_imm_reg(vcpu));
}
@@ -6392,10 +6386,10 @@ void vmx_get_exit_info(struct kvm_vcpu *vcpu, u32 *reason,
struct vcpu_vmx *vmx = to_vmx(vcpu);
*reason = vmx->vt.exit_reason.full;
- *info1 = vmx_get_exit_qual(vcpu);
+ *info1 = vt_get_exit_qual(vcpu);
if (!(vmx->vt.exit_reason.failed_vmentry)) {
*info2 = vmx->idt_vectoring_info;
- *intr_info = vmx_get_intr_info(vcpu);
+ *intr_info = vt_get_intr_info(vcpu);
if (is_exception_with_error_code(*intr_info))
*error_code = vmcs_read32(VM_EXIT_INTR_ERROR_CODE);
else
@@ -6706,7 +6700,7 @@ void dump_vmcs(struct kvm_vcpu *vcpu)
static int __vmx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t exit_fastpath)
{
struct vcpu_vmx *vmx = to_vmx(vcpu);
- union vmx_exit_reason exit_reason = vmx_get_exit_reason(vcpu);
+ union vmx_exit_reason exit_reason = vt_get_exit_reason(vcpu);
u32 vectoring_info = vmx->idt_vectoring_info;
u16 exit_handler_index;
@@ -6870,7 +6864,7 @@ int vmx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t exit_fastpath)
* Exit to user space when bus lock detected to inform that there is
* a bus lock in guest.
*/
- if (vmx_get_exit_reason(vcpu).bus_lock_detected) {
+ if (vt_get_exit_reason(vcpu).bus_lock_detected) {
if (ret > 0)
vcpu->run->exit_reason = KVM_EXIT_X86_BUS_LOCK;
@@ -7143,74 +7137,6 @@ void vmx_load_eoi_exitmap(struct kvm_vcpu *vcpu, u64 *eoi_exit_bitmap)
vmcs_write64(EOI_EXIT_BITMAP3, eoi_exit_bitmap[3]);
}
-static void handle_nm_fault_irqoff(struct kvm_vcpu *vcpu)
-{
- /*
- * Save xfd_err to guest_fpu before interrupt is enabled, so the
- * MSR value is not clobbered by the host activity before the guest
- * has chance to consume it.
- *
- * Update the guest's XFD_ERR if and only if XFD is enabled, as the #NM
- * interception may have been caused by L1 interception. Per the SDM,
- * XFD_ERR is not modified for non-XFD #NM, i.e. if CR0.TS=1.
- *
- * Note, XFD_ERR is updated _before_ the #NM interception check, i.e.
- * unlike CR2 and DR6, the value is not a payload that is attached to
- * the #NM exception.
- */
- if (is_xfd_nm_fault(vcpu))
- rdmsrq(MSR_IA32_XFD_ERR, vcpu->arch.guest_fpu.xfd_err);
-}
-
-static void handle_exception_irqoff(struct kvm_vcpu *vcpu, u32 intr_info)
-{
- /* if exit due to PF check for async PF */
- if (is_page_fault(intr_info))
- vcpu->arch.apf.host_apf_flags = kvm_read_and_reset_apf_flags();
- /* if exit due to NM, handle before interrupts are enabled */
- else if (is_nm_fault(intr_info))
- handle_nm_fault_irqoff(vcpu);
- /* Handle machine checks before interrupts are enabled */
- else if (is_machine_check(intr_info))
- kvm_machine_check();
-}
-
-static void handle_external_interrupt_irqoff(struct kvm_vcpu *vcpu,
- u32 intr_info)
-{
- unsigned int vector = intr_info & INTR_INFO_VECTOR_MASK;
-
- if (KVM_BUG(!is_external_intr(intr_info), vcpu->kvm,
- "unexpected VM-Exit interrupt info: 0x%x", intr_info))
- return;
-
- kvm_before_interrupt(vcpu, KVM_HANDLING_IRQ);
- x86_entry_from_kvm(EVENT_TYPE_EXTINT, vector);
- kvm_after_interrupt(vcpu);
-
- vcpu->arch.at_instruction_boundary = true;
-}
-
-void vmx_handle_exit_irqoff(struct kvm_vcpu *vcpu)
-{
- if (to_vt(vcpu)->emulation_required)
- return;
-
- switch (vmx_get_exit_reason(vcpu).basic) {
- case EXIT_REASON_EXTERNAL_INTERRUPT:
- handle_external_interrupt_irqoff(vcpu, vmx_get_intr_info(vcpu));
- break;
- case EXIT_REASON_EXCEPTION_NMI:
- handle_exception_irqoff(vcpu, vmx_get_intr_info(vcpu));
- break;
- case EXIT_REASON_MCE_DURING_VMENTRY:
- kvm_machine_check();
- break;
- default:
- break;
- }
-}
-
/*
* The kvm parameter can be NULL (module initialization, or invocation before
* VM creation). Be sure to check the kvm parameter before using it.
@@ -7250,7 +7176,7 @@ static void vmx_recover_nmi_blocking(struct vcpu_vmx *vmx)
if (vmx->loaded_vmcs->nmi_known_unmasked)
return;
- exit_intr_info = vmx_get_intr_info(&vmx->vcpu);
+ exit_intr_info = vt_get_intr_info(&vmx->vcpu);
unblock_nmi = (exit_intr_info & INTR_INFO_UNBLOCK_NMI) != 0;
vector = exit_intr_info & INTR_INFO_VECTOR_MASK;
/*
@@ -7417,14 +7343,14 @@ static fastpath_t vmx_exit_handlers_fastpath(struct kvm_vcpu *vcpu,
* the fastpath even, all other exits must use the slow path.
*/
if (is_guest_mode(vcpu) &&
- vmx_get_exit_reason(vcpu).basic != EXIT_REASON_PREEMPTION_TIMER)
+ vt_get_exit_reason(vcpu).basic != EXIT_REASON_PREEMPTION_TIMER)
return EXIT_FASTPATH_NONE;
- switch (vmx_get_exit_reason(vcpu).basic) {
+ switch (vt_get_exit_reason(vcpu).basic) {
case EXIT_REASON_MSR_WRITE:
return handle_fastpath_wrmsr(vcpu);
case EXIT_REASON_MSR_WRITE_IMM:
- return handle_fastpath_wrmsr_imm(vcpu, vmx_get_exit_qual(vcpu),
+ return handle_fastpath_wrmsr_imm(vcpu, vt_get_exit_qual(vcpu),
vmx_get_msr_imm_reg(vcpu));
case EXIT_REASON_PREEMPTION_TIMER:
return handle_fastpath_preemption_timer(vcpu, force_immediate_exit);
@@ -7437,17 +7363,6 @@ static fastpath_t vmx_exit_handlers_fastpath(struct kvm_vcpu *vcpu,
}
}
-noinstr void vmx_handle_nmi(struct kvm_vcpu *vcpu)
-{
- if ((u16)vmx_get_exit_reason(vcpu).basic != EXIT_REASON_EXCEPTION_NMI ||
- !is_nmi(vmx_get_intr_info(vcpu)))
- return;
-
- kvm_before_interrupt(vcpu, KVM_HANDLING_NMI);
- x86_entry_from_kvm(EVENT_TYPE_NMI, NMI_VECTOR);
- kvm_after_interrupt(vcpu);
-}
-
static noinstr void vmx_vcpu_enter_exit(struct kvm_vcpu *vcpu,
unsigned int flags)
{
@@ -7477,10 +7392,10 @@ static noinstr void vmx_vcpu_enter_exit(struct kvm_vcpu *vcpu,
}
vmx->vt.exit_reason.full = vmcs_read32(VM_EXIT_REASON);
- if (likely(!vmx_get_exit_reason(vcpu).failed_vmentry))
+ if (likely(!vt_get_exit_reason(vcpu).failed_vmentry))
vmx->idt_vectoring_info = vmcs_read32(IDT_VECTORING_INFO_FIELD);
- vmx_handle_nmi(vcpu);
+ vt_handle_nmi(vcpu);
out:
guest_state_exit_irqoff();
@@ -7617,7 +7532,7 @@ fastpath_t vmx_vcpu_run(struct kvm_vcpu *vcpu, u64 run_flags)
* checking.
*/
if (vcpu->arch.nested_run_pending &&
- !vmx_get_exit_reason(vcpu).failed_vmentry)
+ !vt_get_exit_reason(vcpu).failed_vmentry)
++vcpu->stat.nested_run;
vcpu->arch.nested_run_pending = 0;
@@ -7628,7 +7543,7 @@ fastpath_t vmx_vcpu_run(struct kvm_vcpu *vcpu, u64 run_flags)
trace_kvm_exit(vcpu, KVM_ISA_VMX);
- if (unlikely(vmx_get_exit_reason(vcpu).failed_vmentry))
+ if (unlikely(vt_get_exit_reason(vcpu).failed_vmentry))
return EXIT_FASTPATH_NONE;
vmx->loaded_vmcs->launched = 1;
diff --git a/arch/x86/kvm/vmx/vmx.h b/arch/x86/kvm/vmx/vmx.h
index dc8517f15bc46..3247b55b34843 100644
--- a/arch/x86/kvm/vmx/vmx.h
+++ b/arch/x86/kvm/vmx/vmx.h
@@ -304,43 +304,6 @@ struct kvm_vmx {
u64 *pid_table;
};
-static __always_inline struct vcpu_vt *to_vt(struct kvm_vcpu *vcpu)
-{
- return &(container_of(vcpu, struct vcpu_vmx, vcpu)->vt);
-}
-
-static __always_inline struct kvm_vcpu *vt_to_vcpu(struct vcpu_vt *vt)
-{
- return &(container_of(vt, struct vcpu_vmx, vt)->vcpu);
-}
-
-static __always_inline union vmx_exit_reason vmx_get_exit_reason(struct kvm_vcpu *vcpu)
-{
- return to_vt(vcpu)->exit_reason;
-}
-
-static __always_inline unsigned long vmx_get_exit_qual(struct kvm_vcpu *vcpu)
-{
- struct vcpu_vt *vt = to_vt(vcpu);
-
- if (!kvm_register_test_and_mark_available(vcpu, VCPU_REG_EXIT_INFO_1) &&
- !WARN_ON_ONCE(is_td_vcpu(vcpu)))
- vt->exit_qualification = vmcs_readl(EXIT_QUALIFICATION);
-
- return vt->exit_qualification;
-}
-
-static __always_inline u32 vmx_get_intr_info(struct kvm_vcpu *vcpu)
-{
- struct vcpu_vt *vt = to_vt(vcpu);
-
- if (!kvm_register_test_and_mark_available(vcpu, VCPU_REG_EXIT_INFO_2) &&
- !WARN_ON_ONCE(is_td_vcpu(vcpu)))
- vt->exit_intr_info = vmcs_read32(VM_EXIT_INTR_INFO);
-
- return vt->exit_intr_info;
-}
-
void vmx_vcpu_load_vmcs(struct kvm_vcpu *vcpu, int cpu);
int allocate_vpid(void);
void free_vpid(int vpid);
diff --git a/arch/x86/kvm/vmx/x86_ops.h b/arch/x86/kvm/vmx/x86_ops.h
index 054fd14bb2e16..7ac02c68457f1 100644
--- a/arch/x86/kvm/vmx/x86_ops.h
+++ b/arch/x86/kvm/vmx/x86_ops.h
@@ -27,7 +27,6 @@ void vmx_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event);
void vmx_vcpu_load(struct kvm_vcpu *vcpu, int cpu);
void vmx_vcpu_put(struct kvm_vcpu *vcpu);
int vmx_handle_exit(struct kvm_vcpu *vcpu, fastpath_t exit_fastpath);
-void vmx_handle_exit_irqoff(struct kvm_vcpu *vcpu);
int vmx_skip_emulated_instruction(struct kvm_vcpu *vcpu);
void vmx_update_emulated_instruction(struct kvm_vcpu *vcpu);
bool vmx_unhandleable_emulation_required(struct kvm_vcpu *vcpu);
|
| 15/3 | 2026/09/05 09:24 | llm | kmsan-evaluator |
0mModel:gemini-3.7-flash Args: null Results: null Tokens: input: 19007 output: 332 thoughts: 2345 Thoughts: **KMSAN Fuzzing Session Assessment: Refactored VMX/TDX Code** Alright, let's break down this patch and determine if we need to fire up a KMSAN session. My initial thought is that this is primarily a refactoring exercise, but we need to be absolutely certain. First, I see the core of the patch involves reorganizing and renaming code related to KVM Intel's VMX and TDX implementations. The introduction of `struct vcpu_vmx_tdx` is the key – it's a unified structure that allows us to treat both VMX and TDX vCPUs similarly, specifically for accessing the `vt` member through the `to_vt()` helper. The use of `container_of` is fundamental to KVM's architecture and the purpose of this refactor is to abstract it under a common name. The patch moves and renames a series of helper functions (e.g., `vmx_get_exit_reason` to `vt_get_exit_reason`) and functions that handle interrupts and exceptions. My first impression is that there are no major functional changes, the main goals is to simplify and unify common VMX/TDX code for improved maintainability. I've carefully examined the `to_vt` function now being placed in common.h along with the moved exit and interrupt handlers. These are almost identical to their original implementations, and only the naming has been adjusted to use the unified "vt" prefix. Importantly, the `static_assert` statements confirming the offsets of the `vt` member within `vcpu_vmx_tdx`, `vcpu_vmx`, and `vcpu_tdx` structures are crucial. This guarantees the correctness of the `container_of` macro and ensures no memory corruption can occur due to struct member access through `to_vt` and `vt_to_vcpu`. It eliminates the possibility of offset mismatch bugs. Now, let's put on the KMSAN hat. We need to methodically check for any potential uninitialized memory issues. 1. **Kernel-User Interface:** Does this patch add, remove or change any kernel structures that are exposed to userspace? No, this is purely internal refactoring. 2. **Conditional Logic/Branching:** Does the patch introduce any new conditional logic where the outcome might depend on an uninitialized variable? Not that I can see. The code is carefully structured to avoid such scenarios. 3. **Data Structure Initialization:** Is there any introduction, or change to complex data structures, and if so, how are they initialized? Are any fields left uninitialized that could later be read? No. The refactoring itself doesn't alter data structures in a way that introduces this risk. 4. **Bounds/Length Checks:** Does it impact any existing checks in a way that allows access to uninitialized data? No. After this careful inspection, I'm confident that this patch doesn't introduce any new vulnerabilities related to uninitialized memory access. These kinds of bugs, with potential struct member offsets mismatches, would be caught with standard memory checkers like KASAN during routine testing. The key is in the static asserts and the rigorous code review by the community. It's essentially structural refactoring that moves code around while retaining the same functionality. My conclusion is that this patch *does not* require a dedicated KMSAN fuzzing session. The risks associated with this refactoring are minimal, primarily limited to the correctness of pointer arithmetic with offsets. These are things that would be readily picked up by existing KVM test infrastructure and memory sanitizers, so `NeedsKMSAN` = `false`. |
| 16/3 | 2026/09/05 09:25 | tool | set-results |
0mArgs:{
"KMSANReasoning": "The patch is a refactoring of KVM Intel VMX and TDX code to consolidate common virtualization infrastructure (VT) between standard VMX and TDX vCPUs:\n1. It defines a common wrapper layout `struct vcpu_vmx_tdx` with compile-time assertions (`static_assert`) ensuring offset matching of `struct vcpu_vt` across `vcpu_vmx` and `vcpu_tdx`.\n2. It moves and renames helper functions (`to_vt`, `vt_get_exit_reason`, `vt_get_exit_qual`, `vt_get_intr_info`, etc.) from `vmx.h`/`vmx.c` to `common.h`/`main.c`.\n3. It moves common exit and interrupt handling functions (`vt_handle_exit_irqoff`, `vt_handle_nmi`, `handle_external_interrupt_irqoff`, etc.) to `main.c`.\n4. It renames posted interrupt routines to use the `vt_` prefix across the codebase.\n\nNone of these changes allocate uninitialized memory, expose uninitialized fields or padding to user space, or alter buffer bounds. Any potential issues with struct layout or offsets are guarded at compile time by `static_assert` or would manifest as memory corruption/OOB access detectable by standard builds and KASAN. Therefore, a dedicated KMSAN fuzzing session is not warranted.",
"NeedsKMSAN": false
}Results: {
"KMSANReasoning": "The patch is a refactoring of KVM Intel VMX and TDX code to consolidate common virtualization infrastructure (VT) between standard VMX and TDX vCPUs:\n1. It defines a common wrapper layout `struct vcpu_vmx_tdx` with compile-time assertions (`static_assert`) ensuring offset matching of `struct vcpu_vt` across `vcpu_vmx` and `vcpu_tdx`.\n2. It moves and renames helper functions (`to_vt`, `vt_get_exit_reason`, `vt_get_exit_qual`, `vt_get_intr_info`, etc.) from `vmx.h`/`vmx.c` to `common.h`/`main.c`.\n3. It moves common exit and interrupt handling functions (`vt_handle_exit_irqoff`, `vt_handle_nmi`, `handle_external_interrupt_irqoff`, etc.) to `main.c`.\n4. It renames posted interrupt routines to use the `vt_` prefix across the codebase.\n\nNone of these changes allocate uninitialized memory, expose uninitialized fields or padding to user space, or alter buffer bounds. Any potential issues with struct layout or offsets are guarded at compile time by `static_assert` or would manifest as memory corruption/OOB access detectable by standard builds and KASAN. Therefore, a dedicated KMSAN fuzzing session is not warranted.",
"NeedsKMSAN": false
} |
| Total Calls | Total Tokens | Avg Tokens | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|
| Total Calls | Total Duration (Seconds) | Avg Duration (Seconds) |
|---|