@@ -129,6 +129,23 @@ static void vt_vcpu_load(struct kvm_vcpu *vcpu, int cpu)
vmx_vcpu_load(vcpu, cpu);
}
+static int vt_vcpu_pre_run(struct kvm_vcpu *vcpu)
+{
+ if (is_td_vcpu(vcpu))
+ /* Unconditionally continue to vcpu_run(). */
+ return 1;
+
+ return vmx_vcpu_pre_run(vcpu);
+}
+
+static fastpath_t vt_vcpu_run(struct kvm_vcpu *vcpu, bool force_immediate_exit)
+{
+ if (is_td_vcpu(vcpu))
+ return tdx_vcpu_run(vcpu, force_immediate_exit);
+
+ return vmx_vcpu_run(vcpu, force_immediate_exit);
+}
+
static void vt_flush_tlb_all(struct kvm_vcpu *vcpu)
{
if (is_td_vcpu(vcpu)) {
@@ -267,8 +284,8 @@ struct kvm_x86_ops vt_x86_ops __initdata = {
.flush_tlb_gva = vt_flush_tlb_gva,
.flush_tlb_guest = vt_flush_tlb_guest,
- .vcpu_pre_run = vmx_vcpu_pre_run,
- .vcpu_run = vmx_vcpu_run,
+ .vcpu_pre_run = vt_vcpu_pre_run,
+ .vcpu_run = vt_vcpu_run,
.handle_exit = vmx_handle_exit,
.skip_emulated_instruction = vmx_skip_emulated_instruction,
.update_emulated_instruction = vmx_update_emulated_instruction,
@@ -10,6 +10,9 @@
#include "mmu/spte.h"
#include "common.h"
+#include <trace/events/kvm.h>
+#include "trace.h"
+
#undef pr_fmt
#define pr_fmt(fmt) KBUILD_MODNAME ": " fmt
@@ -662,6 +665,79 @@ void tdx_vcpu_free(struct kvm_vcpu *vcpu)
}
+static void tdx_vcpu_enter_exit(struct kvm_vcpu *vcpu)
+{
+ struct vcpu_tdx *tdx = to_tdx(vcpu);
+ struct tdx_module_args args;
+
+ guest_state_enter_irqoff();
+
+ /*
+ * TODO: optimization:
+ * - Eliminate copy between args and vcpu->arch.regs.
+ * - copyin/copyout registers only if (tdx->tdvmvall.regs_mask != 0)
+ * which means TDG.VP.VMCALL.
+ */
+ args = (struct tdx_module_args) {
+ .rcx = tdx->tdvpr_pa,
+#define REG(reg, REG) .reg = vcpu->arch.regs[VCPU_REGS_ ## REG]
+ REG(rdx, RDX),
+ REG(r8, R8),
+ REG(r9, R9),
+ REG(r10, R10),
+ REG(r11, R11),
+ REG(r12, R12),
+ REG(r13, R13),
+ REG(r14, R14),
+ REG(r15, R15),
+ REG(rbx, RBX),
+ REG(rdi, RDI),
+ REG(rsi, RSI),
+#undef REG
+ };
+
+ tdx->vp_enter_ret = tdh_vp_enter(tdx->tdvpr_pa, &args);
+
+#define REG(reg, REG) vcpu->arch.regs[VCPU_REGS_ ## REG] = args.reg
+ REG(rcx, RCX);
+ REG(rdx, RDX);
+ REG(r8, R8);
+ REG(r9, R9);
+ REG(r10, R10);
+ REG(r11, R11);
+ REG(r12, R12);
+ REG(r13, R13);
+ REG(r14, R14);
+ REG(r15, R15);
+ REG(rbx, RBX);
+ REG(rdi, RDI);
+ REG(rsi, RSI);
+#undef REG
+
+ guest_state_exit_irqoff();
+}
+
+fastpath_t tdx_vcpu_run(struct kvm_vcpu *vcpu, bool force_immediate_exit)
+{
+ struct vcpu_tdx *tdx = to_tdx(vcpu);
+
+ /* TDX exit handle takes care of this error case. */
+ if (unlikely(tdx->state != VCPU_TD_STATE_INITIALIZED)) {
+ /* Set to avoid collision with EXIT_REASON_EXCEPTION_NMI. */
+ tdx->vp_enter_ret = TDX_SW_ERROR;
+ return EXIT_FASTPATH_NONE;
+ }
+
+ trace_kvm_entry(vcpu, force_immediate_exit);
+
+ tdx_vcpu_enter_exit(vcpu);
+
+ vcpu->arch.regs_avail &= ~VMX_REGS_LAZY_LOAD_SET;
+ trace_kvm_exit(vcpu, KVM_ISA_VMX);
+
+ return EXIT_FASTPATH_NONE;
+}
+
void tdx_load_mmu_pgd(struct kvm_vcpu *vcpu, hpa_t root_hpa, int pgd_level)
{
u64 shared_bit = (pgd_level == 5) ? TDX_SHARED_BIT_PWL_5 :
@@ -51,6 +51,8 @@ struct vcpu_tdx {
struct list_head cpu_list;
+ u64 vp_enter_ret;
+
enum vcpu_tdx_state state;
};
@@ -129,6 +129,7 @@ int tdx_vm_ioctl(struct kvm *kvm, void __user *argp);
int tdx_vcpu_create(struct kvm_vcpu *vcpu);
void tdx_vcpu_free(struct kvm_vcpu *vcpu);
void tdx_vcpu_load(struct kvm_vcpu *vcpu, int cpu);
+fastpath_t tdx_vcpu_run(struct kvm_vcpu *vcpu, bool force_immediate_exit);
int tdx_vcpu_ioctl(struct kvm_vcpu *vcpu, void __user *argp);
@@ -156,6 +157,10 @@ static inline int tdx_vm_ioctl(struct kvm *kvm, void __user *argp) { return -EOP
static inline int tdx_vcpu_create(struct kvm_vcpu *vcpu) { return -EOPNOTSUPP; }
static inline void tdx_vcpu_free(struct kvm_vcpu *vcpu) {}
static inline void tdx_vcpu_load(struct kvm_vcpu *vcpu, int cpu) {}
+static inline fastpath_t tdx_vcpu_run(struct kvm_vcpu *vcpu, bool force_immediate_exit)
+{
+ return EXIT_FASTPATH_NONE;
+}
static inline int tdx_vcpu_ioctl(struct kvm_vcpu *vcpu, void __user *argp) { return -EOPNOTSUPP; }