Commit 113691ce authored by Linus Torvalds's avatar Linus Torvalds
Browse files

Merge tag 'x86_tdx_for_6.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip

Pull x86 TDX updates from Dave Hansen:
 "Intel Trust Domain updates.

  The existing TDX code needs a _bit_ of metadata from the TDX module.
  But KVM is going to need a bunch more very shortly. Rework the
  interface with the TDX module to be more consistent and handle the new
  higher volume.

  The TDX module has added a few new features. The first is a promise
  not to clobber RBP under any circumstances. Basically the kernel now
  will refuse to use any modules that don't have this promise. Second,
  enable the new "REDUCE_VE" feature. This ensures that the TDX module
  will not send some silly virtualization exceptions that the guest had
  no good way to handle anyway.

   - Centralize global metadata infrastructure

   - Use new TDX module features for exception suppression and RBP
     clobbering"

* tag 'x86_tdx_for_6.14-rc1' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip:
  x86/virt/tdx: Require the module to assert it has the NO_RBP_MOD mitigation
  x86/virt/tdx: Switch to use auto-generated global metadata reading code
  x86/virt/tdx: Use dedicated struct members for PAMT entry sizes
  x86/virt/tdx: Use auto-generated code to read global metadata
  x86/virt/tdx: Start to track all global metadata in one structure
  x86/virt/tdx: Rename 'struct tdx_tdmr_sysinfo' to reflect the spec better
  x86/tdx: Dump attributes and TD_CTLS on boot
  x86/tdx: Disable unnecessary virtualization exceptions
parents 5b7f7234 6f5c71cc
Loading
Loading
Loading
Loading
+1 −1
Original line number Diff line number Diff line
# SPDX-License-Identifier: GPL-2.0

obj-y += tdx.o tdx-shared.o tdcall.o
obj-y += debug.o tdcall.o tdx.o tdx-shared.o
+69 −0
Original line number Diff line number Diff line
// SPDX-License-Identifier: GPL-2.0

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

#include <linux/array_size.h>
#include <linux/printk.h>
#include <asm/tdx.h>

#define DEF_TDX_ATTR_NAME(_name) [TDX_ATTR_##_name##_BIT] = __stringify(_name)

static __initdata const char *tdx_attributes[] = {
	DEF_TDX_ATTR_NAME(DEBUG),
	DEF_TDX_ATTR_NAME(HGS_PLUS_PROF),
	DEF_TDX_ATTR_NAME(PERF_PROF),
	DEF_TDX_ATTR_NAME(PMT_PROF),
	DEF_TDX_ATTR_NAME(ICSSD),
	DEF_TDX_ATTR_NAME(LASS),
	DEF_TDX_ATTR_NAME(SEPT_VE_DISABLE),
	DEF_TDX_ATTR_NAME(MIGRTABLE),
	DEF_TDX_ATTR_NAME(PKS),
	DEF_TDX_ATTR_NAME(KL),
	DEF_TDX_ATTR_NAME(TPA),
	DEF_TDX_ATTR_NAME(PERFMON),
};

#define DEF_TD_CTLS_NAME(_name) [TD_CTLS_##_name##_BIT] = __stringify(_name)

static __initdata const char *tdcs_td_ctls[] = {
	DEF_TD_CTLS_NAME(PENDING_VE_DISABLE),
	DEF_TD_CTLS_NAME(ENUM_TOPOLOGY),
	DEF_TD_CTLS_NAME(VIRT_CPUID2),
	DEF_TD_CTLS_NAME(REDUCE_VE),
	DEF_TD_CTLS_NAME(LOCK),
};

void __init tdx_dump_attributes(u64 td_attr)
{
	pr_info("Attributes:");

	for (int i = 0; i < ARRAY_SIZE(tdx_attributes); i++) {
		if (!tdx_attributes[i])
			continue;
		if (td_attr & BIT(i))
			pr_cont(" %s", tdx_attributes[i]);
		td_attr &= ~BIT(i);
	}

	if (td_attr)
		pr_cont(" unknown:%#llx", td_attr);
	pr_cont("\n");

}

void __init tdx_dump_td_ctls(u64 td_ctls)
{
	pr_info("TD_CTLS:");

	for (int i = 0; i < ARRAY_SIZE(tdcs_td_ctls); i++) {
		if (!tdcs_td_ctls[i])
			continue;
		if (td_ctls & BIT(i))
			pr_cont(" %s", tdcs_td_ctls[i]);
		td_ctls &= ~BIT(i);
	}
	if (td_ctls)
		pr_cont(" unknown:%#llx", td_ctls);
	pr_cont("\n");
}
+35 −9
Original line number Diff line number Diff line
@@ -32,9 +32,6 @@
#define VE_GET_PORT_NUM(e)	((e) >> 16)
#define VE_IS_IO_STRING(e)	((e) & BIT(4))

#define ATTR_DEBUG		BIT(0)
#define ATTR_SEPT_VE_DISABLE	BIT(28)

/* TDX Module call error codes */
#define TDCALL_RETURN_CODE(a)	((a) >> 32)
#define TDCALL_INVALID_OPERAND	0xc0000100
@@ -200,14 +197,14 @@ static void __noreturn tdx_panic(const char *msg)
 *
 * TDX 1.0 does not allow the guest to disable SEPT #VE on its own. The VMM
 * controls if the guest will receive such #VE with TD attribute
 * ATTR_SEPT_VE_DISABLE.
 * TDX_ATTR_SEPT_VE_DISABLE.
 *
 * Newer TDX modules allow the guest to control if it wants to receive SEPT
 * violation #VEs.
 *
 * Check if the feature is available and disable SEPT #VE if possible.
 *
 * If the TD is allowed to disable/enable SEPT #VEs, the ATTR_SEPT_VE_DISABLE
 * If the TD is allowed to disable/enable SEPT #VEs, the TDX_ATTR_SEPT_VE_DISABLE
 * attribute is no longer reliable. It reflects the initial state of the
 * control for the TD, but it will not be updated if someone (e.g. bootloader)
 * changes it before the kernel starts. Kernel must check TDCS_TD_CTLS bit to
@@ -216,14 +213,14 @@ static void __noreturn tdx_panic(const char *msg)
static void disable_sept_ve(u64 td_attr)
{
	const char *msg = "TD misconfiguration: SEPT #VE has to be disabled";
	bool debug = td_attr & ATTR_DEBUG;
	bool debug = td_attr & TDX_ATTR_DEBUG;
	u64 config, controls;

	/* Is this TD allowed to disable SEPT #VE */
	tdg_vm_rd(TDCS_CONFIG_FLAGS, &config);
	if (!(config & TDCS_CONFIG_FLEXIBLE_PENDING_VE)) {
		/* No SEPT #VE controls for the guest: check the attribute */
		if (td_attr & ATTR_SEPT_VE_DISABLE)
		if (td_attr & TDX_ATTR_SEPT_VE_DISABLE)
			return;

		/* Relax SEPT_VE_DISABLE check for debug TD for backtraces */
@@ -274,6 +271,20 @@ static void enable_cpu_topology_enumeration(void)
	tdg_vm_wr(TDCS_TD_CTLS, TD_CTLS_ENUM_TOPOLOGY, TD_CTLS_ENUM_TOPOLOGY);
}

static void reduce_unnecessary_ve(void)
{
	u64 err = tdg_vm_wr(TDCS_TD_CTLS, TD_CTLS_REDUCE_VE, TD_CTLS_REDUCE_VE);

	if (err == TDX_SUCCESS)
		return;

	/*
	 * Enabling REDUCE_VE includes ENUM_TOPOLOGY. Only try to
	 * enable ENUM_TOPOLOGY if REDUCE_VE was not successful.
	 */
	enable_cpu_topology_enumeration();
}

static void tdx_setup(u64 *cc_mask)
{
	struct tdx_module_args args = {};
@@ -305,7 +316,8 @@ static void tdx_setup(u64 *cc_mask)
	tdg_vm_wr(TDCS_NOTIFY_ENABLES, 0, -1ULL);

	disable_sept_ve(td_attr);
	enable_cpu_topology_enumeration();

	reduce_unnecessary_ve();
}

/*
@@ -1025,6 +1037,20 @@ static void tdx_kexec_finish(void)
	}
}

static __init void tdx_announce(void)
{
	struct tdx_module_args args = {};
	u64 controls;

	pr_info("Guest detected\n");

	tdcall(TDG_VP_INFO, &args);
	tdx_dump_attributes(args.rdx);

	tdg_vm_rd(TDCS_TD_CTLS, &controls);
	tdx_dump_td_ctls(controls);
}

void __init tdx_early_init(void)
{
	u64 cc_mask;
@@ -1094,5 +1120,5 @@ void __init tdx_early_init(void)
	 */
	x86_cpuinit.parallel_bringup = false;

	pr_info("Guest detected\n");
	tdx_announce();
}
+36 −2
Original line number Diff line number Diff line
@@ -19,6 +19,32 @@
#define TDG_VM_RD			7
#define TDG_VM_WR			8

/* TDX attributes */
#define TDX_ATTR_DEBUG_BIT		0
#define TDX_ATTR_DEBUG			BIT_ULL(TDX_ATTR_DEBUG_BIT)
#define TDX_ATTR_HGS_PLUS_PROF_BIT	4
#define TDX_ATTR_HGS_PLUS_PROF		BIT_ULL(TDX_ATTR_HGS_PLUS_PROF_BIT)
#define TDX_ATTR_PERF_PROF_BIT		5
#define TDX_ATTR_PERF_PROF		BIT_ULL(TDX_ATTR_PERF_PROF_BIT)
#define TDX_ATTR_PMT_PROF_BIT		6
#define TDX_ATTR_PMT_PROF		BIT_ULL(TDX_ATTR_PMT_PROF_BIT)
#define TDX_ATTR_ICSSD_BIT		16
#define TDX_ATTR_ICSSD			BIT_ULL(TDX_ATTR_ICSSD_BIT)
#define TDX_ATTR_LASS_BIT		27
#define TDX_ATTR_LASS			BIT_ULL(TDX_ATTR_LASS_BIT)
#define TDX_ATTR_SEPT_VE_DISABLE_BIT	28
#define TDX_ATTR_SEPT_VE_DISABLE	BIT_ULL(TDX_ATTR_SEPT_VE_DISABLE_BIT)
#define TDX_ATTR_MIGRTABLE_BIT		29
#define TDX_ATTR_MIGRTABLE		BIT_ULL(TDX_ATTR_MIGRTABLE_BIT)
#define TDX_ATTR_PKS_BIT		30
#define TDX_ATTR_PKS			BIT_ULL(TDX_ATTR_PKS_BIT)
#define TDX_ATTR_KL_BIT			31
#define TDX_ATTR_KL			BIT_ULL(TDX_ATTR_KL_BIT)
#define TDX_ATTR_TPA_BIT		62
#define TDX_ATTR_TPA			BIT_ULL(TDX_ATTR_TPA_BIT)
#define TDX_ATTR_PERFMON_BIT		63
#define TDX_ATTR_PERFMON		BIT_ULL(TDX_ATTR_PERFMON_BIT)

/* TDX TD-Scope Metadata. To be used by TDG.VM.WR and TDG.VM.RD */
#define TDCS_CONFIG_FLAGS		0x1110000300000016
#define TDCS_TD_CTLS			0x1110000300000017
@@ -29,8 +55,16 @@
#define TDCS_CONFIG_FLEXIBLE_PENDING_VE	BIT_ULL(1)

/* TDCS_TD_CTLS bits */
#define TD_CTLS_PENDING_VE_DISABLE	BIT_ULL(0)
#define TD_CTLS_ENUM_TOPOLOGY		BIT_ULL(1)
#define TD_CTLS_PENDING_VE_DISABLE_BIT	0
#define TD_CTLS_PENDING_VE_DISABLE	BIT_ULL(TD_CTLS_PENDING_VE_DISABLE_BIT)
#define TD_CTLS_ENUM_TOPOLOGY_BIT	1
#define TD_CTLS_ENUM_TOPOLOGY		BIT_ULL(TD_CTLS_ENUM_TOPOLOGY_BIT)
#define TD_CTLS_VIRT_CPUID2_BIT		2
#define TD_CTLS_VIRT_CPUID2		BIT_ULL(TD_CTLS_VIRT_CPUID2_BIT)
#define TD_CTLS_REDUCE_VE_BIT		3
#define TD_CTLS_REDUCE_VE		BIT_ULL(TD_CTLS_REDUCE_VE_BIT)
#define TD_CTLS_LOCK_BIT		63
#define TD_CTLS_LOCK			BIT_ULL(TD_CTLS_LOCK_BIT)

/* TDX hypercall Leaf IDs */
#define TDVMCALL_MAP_GPA		0x10001
+3 −0
Original line number Diff line number Diff line
@@ -66,6 +66,9 @@ int tdx_mcall_get_report0(u8 *reportdata, u8 *tdreport);

u64 tdx_hcall_get_quote(u8 *buf, size_t size);

void __init tdx_dump_attributes(u64 td_attr);
void __init tdx_dump_td_ctls(u64 td_ctls);

#else

static inline void tdx_early_init(void) { };
Loading