arch/x86/virt/vmx/tdx/tdx.c

Source file repositories/reference/linux-study-clean/arch/x86/virt/vmx/tdx/tdx.c

File Facts

System
Linux kernel
Corpus path
arch/x86/virt/vmx/tdx/tdx.c
Extension
.c
Size
50207 bytes
Lines
2035
Domain
Architecture Layer
Bucket
arch/x86
Inferred role
Architecture Layer: exported/initcall integration point
Status
integration implementation candidate

Why This File Exists

CPU and platform-specific kernel glue: boot entry, traps, syscall entry, interrupts, page tables, context switch, and low-level barriers.

Dependency Surface

Detected Declarations

Annotated Snippet

subsys_initcall(tdx_enable);

int tdx_module_shutdown(void)
{
	struct tdx_sys_info_handoff handoff = {};
	struct tdx_module_args args = {};
	int ret;
	int cpu;

	ret = get_tdx_sys_info_handoff(&handoff);
	/*
	 * Handoff information is required for proper
	 * shutdown. Refuse to shut down without it.
	 */
	if (ret)
		return ret;

	/*
	 * Use the module's handoff version as it is the highest the
	 * module can produce and most likely supported by newer modules.
	 */
	args.rcx = handoff.module_hv;

	ret = seamcall_prerr(TDH_SYS_SHUTDOWN, &args);
	if (ret)
		return ret;

	/*
	 * Clear global and per-CPU initialization flags so the new module
	 * can be fully re-initialized after a successful update.
	 *
	 * No locks needed as no concurrent accesses can occur here.
	 */
	memset(&tdx_module_state, 0, sizeof(tdx_module_state));
	for_each_possible_cpu(cpu)
		per_cpu(tdx_lp_initialized, cpu) = false;

	return 0;
}

int tdx_module_run_update(void)
{
	struct tdx_module_args args = {};
	int ret;

	ret = seamcall_prerr(TDH_SYS_UPDATE, &args);
	if (ret)
		return ret;

	ret = get_tdx_sys_info_version(&tdx_sysinfo.version);
	/*
	 * Only fails if there is something unexpected
	 * and severely wrong with the module.
	 */
	WARN_ON_ONCE(ret);

	tdx_module_state.initialized = true;
	return 0;
}

static bool is_pamt_page(unsigned long phys)
{
	struct tdmr_info_list *tdmr_list = &tdx_tdmr_list;
	int i;

	/* Ensure that all remote 'tdmr_list' writes are visible: */
	smp_rmb();

	/*
	 * The TDX module is no longer returning TDX_SYS_NOT_READY and
	 * is initialized.  The 'tdmr_list' was initialized long ago
	 * and is now read-only.
	 */
	for (i = 0; i < tdmr_list->nr_consumed_tdmrs; i++) {
		unsigned long base, size;

		tdmr_get_pamt(tdmr_entry(tdmr_list, i), &base, &size);

		if (phys >= base && phys < (base + size))
			return true;
	}

	return false;
}

/*
 * Return whether the memory page at the given physical address is TDX
 * private memory or not.
 *
 * This can be imprecise for two known reasons:

Annotation

Implementation Notes