Commit 0d20742b authored by Paolo Bonzini's avatar Paolo Bonzini
Browse files

Merge branch 'kvm-tdx-initialization' into HEAD

This series kicks off the actual interaction of KVM with the TDX module.
This series encompasses the basic setup for using the TDX module from KVM,
and the creation of TD VMs and vCPUs.

The TDX Module is a software component that runs in a special CPU mode
called SEAM (Secure Arbitration Mode). Loading it is mostly handled
outside of KVM by the core kernel. Once it’s loaded  KVM can interact with
the TDX Module via a new instruction called SEAMCALL to virtualize a TD
guests. This instruction can be used to make various types of seamcalls,
with names organized into a hierarchy. The format is TDH.[AREA].[ACTION],
where “TDH” stands for “Trust Domain Host”, and differentiates from
another set of calls that can be done by the guest “TDG”. The KVM relevant
areas of SEAMCALLs are:
   SYS    – TDX module management, static metadata reading.
   MNG    – TD management. VM scoped things that operate on a TDX module
            controlled structure called the TDCS.
   VP     – vCPU management. vCPU scoped things that operate on TDX module
            controlled structures called the TDVPS.
   PHYMEM - Operations related to physical memory management (page
            reclaiming, cache operations, etc).

This series introduces some TDX specific KVM APIs and stops short of
fully “finalizing” the creation of a TD VM. The part of initializing
a guest where initial private memory is loaded is left to a separate
MMU related series.
parents 74c1807f 7c035bea
Loading
Loading
Loading
Loading
+3 −1
Original line number Diff line number Diff line
@@ -21,6 +21,7 @@ KVM_X86_OP(has_emulated_msr)
KVM_X86_OP(vcpu_after_set_cpuid)
KVM_X86_OP(vm_init)
KVM_X86_OP_OPTIONAL(vm_destroy)
KVM_X86_OP_OPTIONAL(vm_pre_destroy)
KVM_X86_OP_OPTIONAL_RET0(vcpu_precreate)
KVM_X86_OP(vcpu_create)
KVM_X86_OP(vcpu_free)
@@ -125,7 +126,8 @@ KVM_X86_OP(leave_smm)
KVM_X86_OP(enable_smi_window)
#endif
KVM_X86_OP_OPTIONAL(dev_get_attr)
KVM_X86_OP_OPTIONAL(mem_enc_ioctl)
KVM_X86_OP(mem_enc_ioctl)
KVM_X86_OP_OPTIONAL(vcpu_mem_enc_ioctl)
KVM_X86_OP_OPTIONAL(mem_enc_register_region)
KVM_X86_OP_OPTIONAL(mem_enc_unregister_region)
KVM_X86_OP_OPTIONAL(vm_copy_enc_context_from)
+2 −0
Original line number Diff line number Diff line
@@ -1665,6 +1665,7 @@ struct kvm_x86_ops {
	unsigned int vm_size;
	int (*vm_init)(struct kvm *kvm);
	void (*vm_destroy)(struct kvm *kvm);
	void (*vm_pre_destroy)(struct kvm *kvm);

	/* Create, but do not attach this VCPU */
	int (*vcpu_precreate)(struct kvm *kvm);
@@ -1848,6 +1849,7 @@ struct kvm_x86_ops {

	int (*dev_get_attr)(u32 group, u64 attr, u64 *val);
	int (*mem_enc_ioctl)(struct kvm *kvm, void __user *argp);
	int (*vcpu_mem_enc_ioctl)(struct kvm_vcpu *vcpu, void __user *argp);
	int (*mem_enc_register_region)(struct kvm *kvm, struct kvm_enc_region *argp);
	int (*mem_enc_unregister_region)(struct kvm *kvm, struct kvm_enc_region *argp);
	int (*vm_copy_enc_context_from)(struct kvm *kvm, unsigned int source_fd);
+6 −1
Original line number Diff line number Diff line
@@ -71,7 +71,12 @@
#define TDVMCALL_GET_QUOTE		0x10002
#define TDVMCALL_REPORT_FATAL_ERROR	0x10003

#define TDVMCALL_STATUS_RETRY		1
/*
 * TDG.VP.VMCALL Status Codes (returned in R10)
 */
#define TDVMCALL_STATUS_SUCCESS		0x0000000000000000ULL
#define TDVMCALL_STATUS_RETRY		0x0000000000000001ULL
#define TDVMCALL_STATUS_INVALID_OPERAND	0x8000000000000000ULL

/*
 * Bitmasks of exposed registers (with VMM).
+60 −0
Original line number Diff line number Diff line
@@ -5,6 +5,7 @@

#include <linux/init.h>
#include <linux/bits.h>
#include <linux/mmzone.h>

#include <asm/errno.h>
#include <asm/ptrace.h>
@@ -33,6 +34,8 @@
#ifndef __ASSEMBLY__

#include <uapi/asm/mce.h>
#include <asm/tdx_global_metadata.h>
#include <linux/pgtable.h>

/*
 * Used by the #VE exception handler to gather the #VE exception
@@ -119,11 +122,68 @@ static inline u64 sc_retry(sc_func_t func, u64 fn,
int tdx_cpu_enable(void);
int tdx_enable(void);
const char *tdx_dump_mce_info(struct mce *m);
const struct tdx_sys_info *tdx_get_sysinfo(void);

int tdx_guest_keyid_alloc(void);
u32 tdx_get_nr_guest_keyids(void);
void tdx_guest_keyid_free(unsigned int keyid);

struct tdx_td {
	/* TD root structure: */
	struct page *tdr_page;

	int tdcs_nr_pages;
	/* TD control structure: */
	struct page **tdcs_pages;

	/* Size of `tdcx_pages` in struct tdx_vp */
	int tdcx_nr_pages;
};

struct tdx_vp {
	/* TDVP root page */
	struct page *tdvpr_page;

	/* TD vCPU control structure: */
	struct page **tdcx_pages;
};


static inline u64 mk_keyed_paddr(u16 hkid, struct page *page)
{
	u64 ret;

	ret = page_to_phys(page);
	/* KeyID bits are just above the physical address bits: */
	ret |= (u64)hkid << boot_cpu_data.x86_phys_bits;

	return ret;

}

u64 tdh_mng_addcx(struct tdx_td *td, struct page *tdcs_page);
u64 tdh_vp_addcx(struct tdx_vp *vp, struct page *tdcx_page);
u64 tdh_mng_key_config(struct tdx_td *td);
u64 tdh_mng_create(struct tdx_td *td, u16 hkid);
u64 tdh_vp_create(struct tdx_td *td, struct tdx_vp *vp);
u64 tdh_mng_rd(struct tdx_td *td, u64 field, u64 *data);
u64 tdh_vp_flush(struct tdx_vp *vp);
u64 tdh_mng_vpflushdone(struct tdx_td *td);
u64 tdh_mng_key_freeid(struct tdx_td *td);
u64 tdh_mng_init(struct tdx_td *td, u64 td_params, u64 *extended_err);
u64 tdh_vp_init(struct tdx_vp *vp, u64 initial_rcx, u32 x2apicid);
u64 tdh_vp_rd(struct tdx_vp *vp, u64 field, u64 *data);
u64 tdh_vp_wr(struct tdx_vp *vp, u64 field, u64 data, u64 mask);
u64 tdh_phymem_page_reclaim(struct page *page, u64 *tdx_pt, u64 *tdx_owner, u64 *tdx_size);
u64 tdh_phymem_cache_wb(bool resume);
u64 tdh_phymem_page_wbinvd_tdr(struct tdx_td *td);
#else
static inline void tdx_init(void) { }
static inline int tdx_cpu_enable(void) { return -ENODEV; }
static inline int tdx_enable(void)  { return -ENODEV; }
static inline u32 tdx_get_nr_guest_keyids(void) { return 0; }
static inline const char *tdx_dump_mce_info(struct mce *m) { return NULL; }
static inline const struct tdx_sys_info *tdx_get_sysinfo(void) { return NULL; }
#endif	/* CONFIG_INTEL_TDX_HOST */

#endif /* !__ASSEMBLY__ */
+19 −0
Original line number Diff line number Diff line
@@ -17,9 +17,28 @@ struct tdx_sys_info_tdmr {
	u16 pamt_1g_entry_size;
};

struct tdx_sys_info_td_ctrl {
	u16 tdr_base_size;
	u16 tdcs_base_size;
	u16 tdvps_base_size;
};

struct tdx_sys_info_td_conf {
	u64 attributes_fixed0;
	u64 attributes_fixed1;
	u64 xfam_fixed0;
	u64 xfam_fixed1;
	u16 num_cpuid_config;
	u16 max_vcpus_per_td;
	u64 cpuid_config_leaves[128];
	u64 cpuid_config_values[128][2];
};

struct tdx_sys_info {
	struct tdx_sys_info_features features;
	struct tdx_sys_info_tdmr tdmr;
	struct tdx_sys_info_td_ctrl td_ctrl;
	struct tdx_sys_info_td_conf td_conf;
};

#endif
Loading