Skip to content

Commit 5f18c64

Browse files
committed
KVM: VMX: Move out vmx_x86_ops to 'main.c' to dispatch VMX and TDX
KVM accesses Virtual Machine Control Structure (VMCS) with VMX instructions to operate on VM. TDX doesn't allow VMM to operate VMCS directly. Instead, TDX has its own data structures, and TDX SEAMCALL APIs for VMM to indirectly operate those data structures. This means we must have a TDX version of kvm_x86_ops. The existing global struct kvm_x86_ops already defines an interface which can be adapted to TDX, but kvm_x86_ops is a system-wide, not per-VM structure. To allow VMX to coexist with TDs, the kvm_x86_ops callbacks will have wrappers "if (tdx) tdx_op() else vmx_op()" to pick VMX or TDX at run time. To split the runtime switch, the VMX implementation, and the TDX implementation, add main.c, and move out the vmx_x86_ops hooks in preparation for adding TDX. Use 'vt' for the naming scheme as a nod to VT-x and as a concatenation of VmxTdx. The eventually converted code will look like this: vmx.c: vmx_op() { ... } VMX initialization tdx.c: tdx_op() { ... } TDX initialization x86_ops.h: vmx_op(); tdx_op(); main.c: static vt_op() { if (tdx) tdx_op() else vmx_op() } static struct kvm_x86_ops vt_x86_ops = { .op = vt_op, initialization functions call both VMX and TDX initialization Opportunistically, fix the name inconsistency from vmx_create_vcpu() and vmx_free_vcpu() to vmx_vcpu_create() and vmx_vcpu_free(). Co-developed-by: Xiaoyao Li <[email protected]> Signed-off-by: Xiaoyao Li <[email protected]> Signed-off-by: Sean Christopherson <[email protected]> Signed-off-by: Isaku Yamahata <[email protected]> Reviewed-by: Binbin Wu <[email protected]> Reviewed-by: Xiaoyao Li <[email protected]> Reviewed-by: Yuan Yao <[email protected]> Message-Id: <e603c317587f933a9d1bee8728c84e4935849c16.1705965634.git.isaku.yamahata@intel.com> Signed-off-by: Paolo Bonzini <[email protected]>
1 parent e913ef1 commit 5f18c64

File tree

4 files changed

+391
-270
lines changed

4 files changed

+391
-270
lines changed

arch/x86/kvm/Makefile

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -21,7 +21,7 @@ kvm-$(CONFIG_KVM_XEN) += xen.o
2121
kvm-$(CONFIG_KVM_SMM) += smm.o
2222

2323
kvm-intel-y += vmx/vmx.o vmx/vmenter.o vmx/pmu_intel.o vmx/vmcs12.o \
24-
vmx/nested.o vmx/posted_intr.o
24+
vmx/nested.o vmx/posted_intr.o vmx/main.o
2525

2626
kvm-intel-$(CONFIG_X86_SGX_KVM) += vmx/sgx.o
2727
kvm-intel-$(CONFIG_KVM_HYPERV) += vmx/hyperv.o vmx/hyperv_evmcs.o

arch/x86/kvm/vmx/main.c

Lines changed: 166 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,166 @@
1+
// SPDX-License-Identifier: GPL-2.0
2+
#include <linux/moduleparam.h>
3+
4+
#include "x86_ops.h"
5+
#include "vmx.h"
6+
#include "nested.h"
7+
#include "pmu.h"
8+
9+
#define VMX_REQUIRED_APICV_INHIBITS \
10+
(BIT(APICV_INHIBIT_REASON_DISABLE)| \
11+
BIT(APICV_INHIBIT_REASON_ABSENT) | \
12+
BIT(APICV_INHIBIT_REASON_HYPERV) | \
13+
BIT(APICV_INHIBIT_REASON_BLOCKIRQ) | \
14+
BIT(APICV_INHIBIT_REASON_PHYSICAL_ID_ALIASED) | \
15+
BIT(APICV_INHIBIT_REASON_APIC_ID_MODIFIED) | \
16+
BIT(APICV_INHIBIT_REASON_APIC_BASE_MODIFIED))
17+
18+
struct kvm_x86_ops vt_x86_ops __initdata = {
19+
.name = KBUILD_MODNAME,
20+
21+
.check_processor_compatibility = vmx_check_processor_compat,
22+
23+
.hardware_unsetup = vmx_hardware_unsetup,
24+
25+
.hardware_enable = vmx_hardware_enable,
26+
.hardware_disable = vmx_hardware_disable,
27+
.has_emulated_msr = vmx_has_emulated_msr,
28+
29+
.vm_size = sizeof(struct kvm_vmx),
30+
.vm_init = vmx_vm_init,
31+
.vm_destroy = vmx_vm_destroy,
32+
33+
.vcpu_precreate = vmx_vcpu_precreate,
34+
.vcpu_create = vmx_vcpu_create,
35+
.vcpu_free = vmx_vcpu_free,
36+
.vcpu_reset = vmx_vcpu_reset,
37+
38+
.prepare_switch_to_guest = vmx_prepare_switch_to_guest,
39+
.vcpu_load = vmx_vcpu_load,
40+
.vcpu_put = vmx_vcpu_put,
41+
42+
.update_exception_bitmap = vmx_update_exception_bitmap,
43+
.get_msr_feature = vmx_get_msr_feature,
44+
.get_msr = vmx_get_msr,
45+
.set_msr = vmx_set_msr,
46+
.get_segment_base = vmx_get_segment_base,
47+
.get_segment = vmx_get_segment,
48+
.set_segment = vmx_set_segment,
49+
.get_cpl = vmx_get_cpl,
50+
.get_cs_db_l_bits = vmx_get_cs_db_l_bits,
51+
.is_valid_cr0 = vmx_is_valid_cr0,
52+
.set_cr0 = vmx_set_cr0,
53+
.is_valid_cr4 = vmx_is_valid_cr4,
54+
.set_cr4 = vmx_set_cr4,
55+
.set_efer = vmx_set_efer,
56+
.get_idt = vmx_get_idt,
57+
.set_idt = vmx_set_idt,
58+
.get_gdt = vmx_get_gdt,
59+
.set_gdt = vmx_set_gdt,
60+
.set_dr7 = vmx_set_dr7,
61+
.sync_dirty_debug_regs = vmx_sync_dirty_debug_regs,
62+
.cache_reg = vmx_cache_reg,
63+
.get_rflags = vmx_get_rflags,
64+
.set_rflags = vmx_set_rflags,
65+
.get_if_flag = vmx_get_if_flag,
66+
67+
.flush_tlb_all = vmx_flush_tlb_all,
68+
.flush_tlb_current = vmx_flush_tlb_current,
69+
.flush_tlb_gva = vmx_flush_tlb_gva,
70+
.flush_tlb_guest = vmx_flush_tlb_guest,
71+
72+
.vcpu_pre_run = vmx_vcpu_pre_run,
73+
.vcpu_run = vmx_vcpu_run,
74+
.handle_exit = vmx_handle_exit,
75+
.skip_emulated_instruction = vmx_skip_emulated_instruction,
76+
.update_emulated_instruction = vmx_update_emulated_instruction,
77+
.set_interrupt_shadow = vmx_set_interrupt_shadow,
78+
.get_interrupt_shadow = vmx_get_interrupt_shadow,
79+
.patch_hypercall = vmx_patch_hypercall,
80+
.inject_irq = vmx_inject_irq,
81+
.inject_nmi = vmx_inject_nmi,
82+
.inject_exception = vmx_inject_exception,
83+
.cancel_injection = vmx_cancel_injection,
84+
.interrupt_allowed = vmx_interrupt_allowed,
85+
.nmi_allowed = vmx_nmi_allowed,
86+
.get_nmi_mask = vmx_get_nmi_mask,
87+
.set_nmi_mask = vmx_set_nmi_mask,
88+
.enable_nmi_window = vmx_enable_nmi_window,
89+
.enable_irq_window = vmx_enable_irq_window,
90+
.update_cr8_intercept = vmx_update_cr8_intercept,
91+
.set_virtual_apic_mode = vmx_set_virtual_apic_mode,
92+
.set_apic_access_page_addr = vmx_set_apic_access_page_addr,
93+
.refresh_apicv_exec_ctrl = vmx_refresh_apicv_exec_ctrl,
94+
.load_eoi_exitmap = vmx_load_eoi_exitmap,
95+
.apicv_pre_state_restore = vmx_apicv_pre_state_restore,
96+
.required_apicv_inhibits = VMX_REQUIRED_APICV_INHIBITS,
97+
.hwapic_irr_update = vmx_hwapic_irr_update,
98+
.hwapic_isr_update = vmx_hwapic_isr_update,
99+
.guest_apic_has_interrupt = vmx_guest_apic_has_interrupt,
100+
.sync_pir_to_irr = vmx_sync_pir_to_irr,
101+
.deliver_interrupt = vmx_deliver_interrupt,
102+
.dy_apicv_has_pending_interrupt = pi_has_pending_interrupt,
103+
104+
.set_tss_addr = vmx_set_tss_addr,
105+
.set_identity_map_addr = vmx_set_identity_map_addr,
106+
.get_mt_mask = vmx_get_mt_mask,
107+
108+
.get_exit_info = vmx_get_exit_info,
109+
110+
.vcpu_after_set_cpuid = vmx_vcpu_after_set_cpuid,
111+
112+
.has_wbinvd_exit = cpu_has_vmx_wbinvd_exit,
113+
114+
.get_l2_tsc_offset = vmx_get_l2_tsc_offset,
115+
.get_l2_tsc_multiplier = vmx_get_l2_tsc_multiplier,
116+
.write_tsc_offset = vmx_write_tsc_offset,
117+
.write_tsc_multiplier = vmx_write_tsc_multiplier,
118+
119+
.load_mmu_pgd = vmx_load_mmu_pgd,
120+
121+
.check_intercept = vmx_check_intercept,
122+
.handle_exit_irqoff = vmx_handle_exit_irqoff,
123+
124+
.sched_in = vmx_sched_in,
125+
126+
.cpu_dirty_log_size = PML_ENTITY_NUM,
127+
.update_cpu_dirty_logging = vmx_update_cpu_dirty_logging,
128+
129+
.nested_ops = &vmx_nested_ops,
130+
131+
.pi_update_irte = vmx_pi_update_irte,
132+
.pi_start_assignment = vmx_pi_start_assignment,
133+
134+
#ifdef CONFIG_X86_64
135+
.set_hv_timer = vmx_set_hv_timer,
136+
.cancel_hv_timer = vmx_cancel_hv_timer,
137+
#endif
138+
139+
.setup_mce = vmx_setup_mce,
140+
141+
#ifdef CONFIG_KVM_SMM
142+
.smi_allowed = vmx_smi_allowed,
143+
.enter_smm = vmx_enter_smm,
144+
.leave_smm = vmx_leave_smm,
145+
.enable_smi_window = vmx_enable_smi_window,
146+
#endif
147+
148+
.check_emulate_instruction = vmx_check_emulate_instruction,
149+
.apic_init_signal_blocked = vmx_apic_init_signal_blocked,
150+
.migrate_timers = vmx_migrate_timers,
151+
152+
.msr_filter_changed = vmx_msr_filter_changed,
153+
.complete_emulated_msr = kvm_complete_insn_gp,
154+
155+
.vcpu_deliver_sipi_vector = kvm_vcpu_deliver_sipi_vector,
156+
157+
.get_untagged_addr = vmx_get_untagged_addr,
158+
};
159+
160+
struct kvm_x86_init_ops vt_init_ops __initdata = {
161+
.hardware_setup = vmx_hardware_setup,
162+
.handle_intel_pt_intr = NULL,
163+
164+
.runtime_ops = &vt_x86_ops,
165+
.pmu_ops = &intel_pmu_ops,
166+
};

0 commit comments

Comments
 (0)