Skip to content
Permalink
Browse files
KVM: TDX: Stub in tdx.h with structs, accessors, and VMCS helpers
Stub in kvm_tdx, vcpu_tdx, their various accessors, and VMCS helpers.
The VMCS helpers, which rely on the stubs, will be used by preparatory
patches to move VMX functions for accessing VMCS state to common code.

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 5c82acd commit bf8636a6b18c9a4a17d11dd306dcc7809db9cc9c
Show file tree
Hide file tree
Showing 6 changed files with 192 additions and 1 deletion.
@@ -29,7 +29,10 @@ kvm-$(CONFIG_KVM_XEN) += xen.o
kvm-intel-y += vmx/vmx.o vmx/vmenter.o vmx/pmu_intel.o vmx/vmcs12.o \
vmx/evmcs.o vmx/nested.o vmx/posted_intr.o vmx/main.o
kvm-intel-$(CONFIG_X86_SGX_KVM) += vmx/sgx.o
kvm-intel-$(CONFIG_INTEL_TDX_HOST) += vmx/tdx_error.o
kvm-intel-$(CONFIG_INTEL_TDX_HOST) += vmx/tdx_error.o vmx/tdx.o
ifneq ($(CONFIG_INTEL_TDX_HOST),y)
kvm-intel-y += vmx/tdx_stubs.o
endif

kvm-amd-y += svm/svm.o svm/vmenter.o svm/pmu.o svm/nested.o svm/avic.o svm/sev.o

@@ -164,6 +164,9 @@ static int __init vt_init(void)
unsigned int vcpu_size = 0, vcpu_align = 0;
int r;

/* tdx_pre_kvm_init must be called before vmx_pre_kvm_init(). */
tdx_pre_kvm_init(&vcpu_size, &vcpu_align, &vt_x86_ops.vm_size);

vmx_pre_kvm_init(&vcpu_size, &vcpu_align);

r = kvm_init(&vt_init_ops, vcpu_size, vcpu_align, THIS_MODULE);
@@ -0,0 +1,21 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/cpu.h>
#include <linux/kvm_host.h>

#include "tdx_errno.h"
#include "tdx_ops.h"
#include "x86_ops.h"
#include "tdx.h"

#undef pr_fmt
#define pr_fmt(fmt) "tdx: " fmt

void __init tdx_pre_kvm_init(unsigned int *vcpu_size,
unsigned int *vcpu_align, unsigned int *vm_size)
{
*vcpu_size = sizeof(struct vcpu_tdx);
*vcpu_align = __alignof__(struct vcpu_tdx);

if (sizeof(struct kvm_tdx) > *vm_size)
*vm_size = sizeof(struct kvm_tdx);
}
@@ -0,0 +1,156 @@
/* SPDX-License-Identifier: GPL-2.0 */
#ifndef __KVM_X86_TDX_H
#define __KVM_X86_TDX_H

#include <linux/list.h>
#include <linux/kvm_host.h>

#include "tdx_errno.h"
#include "tdx_arch.h"
#include "tdx_ops.h"

#ifdef CONFIG_INTEL_TDX_HOST

struct tdx_td_page {
unsigned long va;
hpa_t pa;
bool added;
};

struct kvm_tdx {
struct kvm kvm;

struct tdx_td_page tdr;
struct tdx_td_page *tdcs;
};

struct vcpu_tdx {
struct kvm_vcpu vcpu;

struct tdx_td_page tdvpr;
struct tdx_td_page *tdvpx;
};

static inline bool is_td(struct kvm *kvm)
{
return kvm->arch.vm_type == KVM_X86_TDX_VM;
}

static inline bool is_td_vcpu(struct kvm_vcpu *vcpu)
{
return is_td(vcpu->kvm);
}

static inline bool is_debug_td(struct kvm_vcpu *vcpu)
{
return !vcpu->arch.guest_state_protected;
}

static inline struct kvm_tdx *to_kvm_tdx(struct kvm *kvm)
{
return container_of(kvm, struct kvm_tdx, kvm);
}

static inline struct vcpu_tdx *to_tdx(struct kvm_vcpu *vcpu)
{
return container_of(vcpu, struct vcpu_tdx, vcpu);
}

static __always_inline void tdvps_vmcs_check(u32 field, u8 bits)
{
BUILD_BUG_ON_MSG(__builtin_constant_p(field) && (field) & 0x1,
"Read/Write to TD VMCS *_HIGH fields not supported");

BUILD_BUG_ON(bits != 16 && bits != 32 && bits != 64);

BUILD_BUG_ON_MSG(bits != 64 && __builtin_constant_p(field) &&
(((field) & 0x6000) == 0x2000 ||
((field) & 0x6000) == 0x6000),
"Invalid TD VMCS access for 64-bit field");
BUILD_BUG_ON_MSG(bits != 32 && __builtin_constant_p(field) &&
((field) & 0x6000) == 0x4000,
"Invalid TD VMCS access for 32-bit field");
BUILD_BUG_ON_MSG(bits != 16 && __builtin_constant_p(field) &&
((field) & 0x6000) == 0x0000,
"Invalid TD VMCS access for 16-bit field");
}

static __always_inline void tdvps_state_non_arch_check(u64 field, u8 bits) {}
static __always_inline void tdvps_management_check(u64 field, u8 bits) {}

#define TDX_BUILD_TDVPS_ACCESSORS(bits, uclass, lclass) \
static __always_inline u##bits td_##lclass##_read##bits(struct vcpu_tdx *tdx, \
u32 field) \
{ \
struct tdx_ex_ret ex_ret; \
u64 err; \
\
tdvps_##lclass##_check(field, bits); \
err = tdh_vp_rd(tdx->tdvpr.pa, TDVPS_##uclass(field), &ex_ret); \
if (unlikely(err)) { \
pr_err("TDH_VP_RD["#uclass".0x%x] failed: 0x%llx\n", \
field, err); \
return 0; \
} \
return (u##bits)ex_ret.r8; \
} \
static __always_inline void td_##lclass##_write##bits(struct vcpu_tdx *tdx, \
u32 field, u##bits val) \
{ \
struct tdx_ex_ret ex_ret; \
u64 err; \
\
tdvps_##lclass##_check(field, bits); \
err = tdh_vp_wr(tdx->tdvpr.pa, TDVPS_##uclass(field), val, \
GENMASK_ULL(bits - 1, 0), &ex_ret); \
if (unlikely(err)) \
pr_err("TDH_VP_WR["#uclass".0x%x] = 0x%llx failed: 0x%llx\n", \
field, (u64)val, err); \
} \
static __always_inline void td_##lclass##_setbit##bits(struct vcpu_tdx *tdx, \
u32 field, u64 bit) \
{ \
struct tdx_ex_ret ex_ret; \
u64 err; \
\
tdvps_##lclass##_check(field, bits); \
err = tdh_vp_wr(tdx->tdvpr.pa, TDVPS_##uclass(field), bit, bit, \
&ex_ret); \
if (unlikely(err)) \
pr_err("TDH_VP_WR["#uclass".0x%x] |= 0x%llx failed: 0x%llx\n", \
field, bit, err); \
} \
static __always_inline void td_##lclass##_clearbit##bits(struct vcpu_tdx *tdx, \
u32 field, u64 bit) \
{ \
struct tdx_ex_ret ex_ret; \
u64 err; \
\
tdvps_##lclass##_check(field, bits); \
err = tdh_vp_wr(tdx->tdvpr.pa, TDVPS_##uclass(field), 0, bit, \
&ex_ret); \
if (unlikely(err)) \
pr_err("TDH_VP_WR["#uclass".0x%x] &= ~0x%llx failed: 0x%llx\n", \
field, bit, err); \
}

TDX_BUILD_TDVPS_ACCESSORS(16, VMCS, vmcs);
TDX_BUILD_TDVPS_ACCESSORS(32, VMCS, vmcs);
TDX_BUILD_TDVPS_ACCESSORS(64, VMCS, vmcs);

TDX_BUILD_TDVPS_ACCESSORS(64, STATE_NON_ARCH, state_non_arch);
TDX_BUILD_TDVPS_ACCESSORS(8, MANAGEMENT, management);

#else
struct kvm_tdx;
struct vcpu_tdx;

static inline bool is_td(struct kvm *kvm) { return false; }
static inline bool is_td_vcpu(struct kvm_vcpu *vcpu) { return false; }
static inline bool is_debug_td(struct kvm_vcpu *vcpu) { return false; }
static inline struct kvm_tdx *to_kvm_tdx(struct kvm *kvm) { return NULL; }
static inline struct vcpu_tdx *to_tdx(struct kvm_vcpu *vcpu) { return NULL; }

#endif /* CONFIG_INTEL_TDX_HOST */

#endif /* __KVM_X86_TDX_H */
@@ -0,0 +1,5 @@
// SPDX-License-Identifier: GPL-2.0
#include <linux/kvm_host.h>

void __init tdx_pre_kvm_init(unsigned int *vcpu_size,
unsigned int *vcpu_align, unsigned int *vm_size) {}
@@ -123,4 +123,7 @@ void vmx_cancel_hv_timer(struct kvm_vcpu *vcpu);
#endif
void vmx_setup_mce(struct kvm_vcpu *vcpu);

void __init tdx_pre_kvm_init(unsigned int *vcpu_size,
unsigned int *vcpu_align, unsigned int *vm_size);

#endif /* __KVM_X86_VMX_X86_OPS_H */

0 comments on commit bf8636a

Please sign in to comment.