// SPDX-License-Identifier: GPL-2.0
#include <linux/moduleparam.h>
#include "x86_ops.h"
#include "vmx.h"
#include "mmu.h"
#include "nested.h"
#include "pmu.h"
#include "posted_intr.h"
#include "tdx.h"
#include "tdx_arch.h"
#ifdef CONFIG_KVM_INTEL_TDX
static_assert(offsetof(struct vcpu_vmx, vt) == offsetof(struct vcpu_tdx, vt));
static void vt_disable_virtualization_cpu(void)
{
/* Note, TDX *and* VMX need to be disabled if TDX is enabled. */
if (enable_tdx)
tdx_disable_virtualization_cpu();
vmx_disable_virtualization_cpu();
}
static __init int vt_hardware_setup(void)
{
int ret;
ret = vmx_hardware_setup();
if (ret)
return ret;
return enable_tdx ? tdx_hardware_setup() : 0;
}
static void vt_hardware_unsetup(void)
{
if (enable_tdx)
tdx_hardware_unsetup();
vmx_hardware_unsetup();
}
static int vt_vm_init(struct kvm *kvm)
{
if (is_td(kvm))
return tdx_vm_init(kvm);
return vmx_vm_init(kvm);
}
static void vt_vm_pre_destroy(struct kvm *kvm)
{
if (is_td(kvm))
return tdx_mmu_release_hkid(kvm);
}
static void vt_vm_destroy(struct kvm *kvm)
{
if (is_td(kvm))
return tdx_vm_destroy(kvm);
vmx_vm_destroy(kvm);
}
static int vt_vcpu_precreate(struct kvm *kvm)
{
if (is_td(kvm))
return 0;
return vmx_vcpu_precreate(kvm);
}
static int vt_vcpu_create(struct kvm_vcpu *vcpu)
{
if (is_td_vcpu(vcpu))
return tdx_vcpu_create(vcpu);
return vmx_vcpu_create(vcpu);
}
static void vt_vcpu_free(struct kvm_vcpu *vcpu)
{
if (is_td_vcpu(vcpu)) {
tdx_vcpu_free(vcpu);
return;
}
vmx_vcpu_free(vcpu);
}
static void vt_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event)
{
if (is_td_vcpu(vcpu)) {
tdx_vcpu_reset(vcpu, init_event);
return;
}
vmx_vcpu_reset(vcpu, init_event);
}
static void vt_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
{
if (is_td_vcpu(vcpu)) {
tdx_vcpu_load(vcpu, cpu);
return;
}
vmx_vcpu_load(vcpu, cpu);
}
static void vt_update_cpu_dirty_logging(struct kvm_vcpu *vcpu)
{
/*
* Basic TDX does not support feature PML. KVM does not enable PML in
* TD's VMCS, nor does it allocate or flush PML buffer for TDX.
*/
if (WARN_ON_ONCE(is_td_vcpu(vcpu)))
return;
vmx_update_cpu_dirty_logging(vcpu);
}
static void vt_prepare_switch_to_guest(struct kvm_vcpu *vcpu)
{
if (is_td_vcpu(vcpu)) {
tdx_prepare_switch_to_guest(vcpu);
return;
}
vmx_prepare_switch_to_guest(vcpu);
}
static void vt_vcpu_put(struct kvm_vcpu *vcpu)
{
if (is_td_vcpu(vcpu)) {
tdx_vcpu_put(vcpu);
return;
}
vmx_vcpu_put(vcpu);
}
static int vt_vcpu_pre_run(struct kvm_vcpu *vcpu)
{
if (is_td_vcpu(vcpu))
return tdx_vcpu_pre_run(vcpu);
return vmx_vcpu_pre_run(vcpu);
}
static fastpath_t vt_vcpu_run(struct kvm_vcpu *vcpu, u64 run_flags)
{
if (is_td_vcpu(vcpu))
return tdx_vcpu_run(vcpu, run_flags);
return vmx_vcpu_run(vcpu, run_flags);
}
static int vt_handle_exit(struct kvm_vcpu *vcpu,
enum exit_fastpath_completion fastpath)
{
if (is_td_vcpu(vcpu))
return tdx_handle_exit(vcpu, fastpath);
return vmx_handle_exit(vcpu,