Skip to content

Commit

Permalink
KVM: TDX: Do TDX specific vcpu initialization
Browse files Browse the repository at this point in the history
One 64bit value is passed to vcpu as an initial parameter in guest vcpu RCX
initial value.

KVM_MEMORY_ENCRYPT_OP KVM API was introduced for VM-scoped operations of
protected guest VM.  It has sub-commands under the API.  Repurpose
KVM_MEMORY_ENCRYPT_OP to pass vcpu parameter.  Which requires vCPU-scoped
operations in addition to the existing VM-scoped operations.

Add callback for kvm vCPU-scoped operations of KVM_MEMORY_ENCRYPT_OP and
add a new subcommand, KVM_TDX_INIT_VCPU, to pass a parameter for TDX vcpu.

Signed-off-by: Sean Christopherson <sean.j.christopherson@intel.com>
Signed-off-by: Isaku Yamahata <isaku.yamahata@intel.com>
  • Loading branch information
Sean Christopherson authored and yamahata committed Dec 15, 2021
1 parent bd5ba6a commit 2a1d7e9
Show file tree
Hide file tree
Showing 9 changed files with 68 additions and 0 deletions.
1 change: 1 addition & 0 deletions arch/x86/include/asm/kvm_host.h
Expand Up @@ -1483,6 +1483,7 @@ struct kvm_x86_ops {

int (*mem_enc_op_dev)(void __user *argp);
int (*mem_enc_op)(struct kvm *kvm, void __user *argp);
int (*mem_enc_op_vcpu)(struct kvm_vcpu *vcpu, void __user *argp);
int (*mem_enc_reg_region)(struct kvm *kvm, struct kvm_enc_region *argp);
int (*mem_enc_unreg_region)(struct kvm *kvm, struct kvm_enc_region *argp);
int (*vm_copy_enc_context_from)(struct kvm *kvm, unsigned int source_fd);
Expand Down
1 change: 1 addition & 0 deletions arch/x86/include/uapi/asm/kvm.h
Expand Up @@ -515,6 +515,7 @@ struct kvm_pmu_event_filter {
enum kvm_tdx_cmd_id {
KVM_TDX_CAPABILITIES = 0,
KVM_TDX_INIT_VM,
KVM_TDX_INIT_VCPU,

KVM_TDX_CMD_NR_MAX,
};
Expand Down
9 changes: 9 additions & 0 deletions arch/x86/kvm/vmx/main.c
Expand Up @@ -117,6 +117,14 @@ static int vt_mem_enc_op(struct kvm *kvm, void __user *argp)
return tdx_vm_ioctl(kvm, argp);
}

static int vt_mem_enc_op_vcpu(struct kvm_vcpu *vcpu, void __user *argp)
{
if (!is_td_vcpu(vcpu))
return -EINVAL;

return tdx_vcpu_ioctl(vcpu, argp);
}

struct kvm_x86_ops vt_x86_ops __initdata = {
.name = "kvm_intel",

Expand Down Expand Up @@ -259,6 +267,7 @@ struct kvm_x86_ops vt_x86_ops __initdata = {

.mem_enc_op_dev = vt_mem_enc_op_dev,
.mem_enc_op = vt_mem_enc_op,
.mem_enc_op_vcpu = vt_mem_enc_op_vcpu,
};

static struct kvm_x86_init_ops vt_init_ops __initdata = {
Expand Down
44 changes: 44 additions & 0 deletions arch/x86/kvm/vmx/tdx.c
Expand Up @@ -106,6 +106,11 @@ static inline bool is_hkid_assigned(struct kvm_tdx *kvm_tdx)
return kvm_tdx->hkid >= 0;
}

static inline bool is_td_finalized(struct kvm_tdx *kvm_tdx)
{
return kvm_tdx->finalized;
}

void tdx_hardware_enable(void)
{
}
Expand Down Expand Up @@ -794,6 +799,45 @@ int tdx_vm_ioctl(struct kvm *kvm, void __user *argp)
return r;
}

int tdx_vcpu_ioctl(struct kvm_vcpu *vcpu, void __user *argp)
{
struct kvm_tdx *kvm_tdx = to_kvm_tdx(vcpu->kvm);
struct vcpu_tdx *tdx = to_tdx(vcpu);
struct kvm_tdx_cmd cmd;
u64 err;

if (tdx->initialized)
return -EINVAL;

if (!is_td_initialized(vcpu->kvm) || is_td_finalized(kvm_tdx))
return -EINVAL;

if (copy_from_user(&cmd, argp, sizeof(cmd)))
return -EFAULT;

if (cmd.metadata || cmd.id != KVM_TDX_INIT_VCPU)
return -EINVAL;

err = tdh_vp_init(tdx->tdvpr.pa, cmd.data);
if (WARN_ON_ONCE(err)) {
pr_tdx_error(TDH_VP_INIT, err, NULL);
return -EIO;
}

tdx->initialized = true;

td_vmcs_write16(tdx, POSTED_INTR_NV, POSTED_INTR_VECTOR);
td_vmcs_write64(tdx, POSTED_INTR_DESC_ADDR, __pa(&tdx->pi_desc));
td_vmcs_setbit32(tdx, PIN_BASED_VM_EXEC_CONTROL, PIN_BASED_POSTED_INTR);

if (vcpu->kvm->arch.bus_lock_detection_enabled)
td_vmcs_setbit32(tdx,
SECONDARY_VM_EXEC_CONTROL,
SECONDARY_EXEC_BUS_LOCK_DETECTION);

return 0;
}

int __init tdx_hardware_setup(struct kvm_x86_ops *x86_ops)
{
int i, max_pkgs;
Expand Down
4 changes: 4 additions & 0 deletions arch/x86/kvm/vmx/tdx.h
Expand Up @@ -31,6 +31,8 @@ struct kvm_tdx {
int cpuid_nent;
struct kvm_cpuid_entry2 cpuid_entries[KVM_MAX_CPUID_ENTRIES];

bool finalized;

u64 tsc_offset;
};

Expand All @@ -42,6 +44,8 @@ struct vcpu_tdx {

/* Posted interrupt descriptor */
struct pi_desc pi_desc;

bool initialized;
};

#define TDX_MAX_NR_CPUID_CONFIGS \
Expand Down
1 change: 1 addition & 0 deletions arch/x86/kvm/vmx/tdx_stubs.c
Expand Up @@ -13,3 +13,4 @@ void tdx_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event) {}

int tdx_dev_ioctl(void __user *argp) { return -EOPNOTSUPP; }
int tdx_vm_ioctl(struct kvm *kvm, void __user *argp) { return -EOPNOTSUPP; }
int tdx_vcpu_ioctl(struct kvm_vcpu *vcpu, void __user *argp) { return -ENOPNOTSUPP; }
1 change: 1 addition & 0 deletions arch/x86/kvm/vmx/x86_ops.h
Expand Up @@ -138,5 +138,6 @@ void tdx_vcpu_reset(struct kvm_vcpu *vcpu, bool init_event);

int tdx_dev_ioctl(void __user *argp);
int tdx_vm_ioctl(struct kvm *kvm, void __user *argp);
int tdx_vcpu_ioctl(struct kvm_vcpu *vcpu, void __user *argp);

#endif /* __KVM_X86_VMX_X86_OPS_H */
6 changes: 6 additions & 0 deletions arch/x86/kvm/x86.c
Expand Up @@ -5524,6 +5524,12 @@ long kvm_arch_vcpu_ioctl(struct file *filp,
case KVM_SET_DEVICE_ATTR:
r = kvm_vcpu_ioctl_device_attr(vcpu, ioctl, argp);
break;
case KVM_MEMORY_ENCRYPT_OP:
r = -EINVAL;
if (!kvm_x86_ops.mem_enc_op_vcpu)
goto out;
r = kvm_x86_ops.mem_enc_op_vcpu(vcpu, argp);
break;
default:
r = -EINVAL;
}
Expand Down
1 change: 1 addition & 0 deletions tools/arch/x86/include/uapi/asm/kvm.h
Expand Up @@ -515,6 +515,7 @@ struct kvm_pmu_event_filter {
enum kvm_tdx_cmd_id {
KVM_TDX_CAPABILITIES = 0,
KVM_TDX_INIT_VM,
KVM_TDX_INIT_VCPU,

KVM_TDX_CMD_NR_MAX,
};
Expand Down

0 comments on commit 2a1d7e9

Please sign in to comment.