mirror of
https://git.kernel.org/pub/scm/linux/kernel/git/next/linux-next.git
synced 2024-12-28 16:52:18 +00:00
Merge branch into tip/master: 'x86/tdx'
# New commits in x86/tdx:6f5c71cc42
("x86/virt/tdx: Require the module to assert it has the NO_RBP_MOD mitigation")fae43b24a6
("x86/virt/tdx: Switch to use auto-generated global metadata reading code")6bfb77f489
("x86/virt/tdx: Use dedicated struct members for PAMT entry sizes")04a7bc7316
("x86/virt/tdx: Use auto-generated code to read global metadata")c4e0862a62
("x86/virt/tdx: Start to track all global metadata in one structure")e8aa393b0a
("x86/virt/tdx: Rename 'struct tdx_tdmr_sysinfo' to reflect the spec better")564ea84c8c
("x86/tdx: Dump attributes and TD_CTLS on boot")cd9ce82173
("x86/tdx: Disable unnecessary virtualization exceptions") Signed-off-by: Ingo Molnar <mingo@kernel.org>
This commit is contained in:
commit
1c875bc67c
@ -1,3 +1,3 @@
|
||||
# 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
arch/x86/coco/tdx/debug.c
Normal file
69
arch/x86/coco/tdx/debug.c
Normal file
@ -0,0 +1,69 @@
|
||||
// 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");
|
||||
}
|
@ -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();
|
||||
}
|
||||
|
@ -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
|
||||
|
@ -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) { };
|
||||
|
@ -270,57 +270,15 @@ static int read_sys_metadata_field(u64 field_id, u64 *data)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int read_sys_metadata_field16(u64 field_id,
|
||||
int offset,
|
||||
struct tdx_tdmr_sysinfo *ts)
|
||||
{
|
||||
u16 *ts_member = ((void *)ts) + offset;
|
||||
u64 tmp;
|
||||
int ret;
|
||||
#include "tdx_global_metadata.c"
|
||||
|
||||
if (WARN_ON_ONCE(MD_FIELD_ID_ELE_SIZE_CODE(field_id) !=
|
||||
MD_FIELD_ID_ELE_SIZE_16BIT))
|
||||
static int check_features(struct tdx_sys_info *sysinfo)
|
||||
{
|
||||
u64 tdx_features0 = sysinfo->features.tdx_features0;
|
||||
|
||||
if (!(tdx_features0 & TDX_FEATURES0_NO_RBP_MOD)) {
|
||||
pr_err("frame pointer (RBP) clobber bug present, upgrade TDX module\n");
|
||||
return -EINVAL;
|
||||
|
||||
ret = read_sys_metadata_field(field_id, &tmp);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
*ts_member = tmp;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct field_mapping {
|
||||
u64 field_id;
|
||||
int offset;
|
||||
};
|
||||
|
||||
#define TD_SYSINFO_MAP(_field_id, _offset) \
|
||||
{ .field_id = MD_FIELD_ID_##_field_id, \
|
||||
.offset = offsetof(struct tdx_tdmr_sysinfo, _offset) }
|
||||
|
||||
/* Map TD_SYSINFO fields into 'struct tdx_tdmr_sysinfo': */
|
||||
static const struct field_mapping fields[] = {
|
||||
TD_SYSINFO_MAP(MAX_TDMRS, max_tdmrs),
|
||||
TD_SYSINFO_MAP(MAX_RESERVED_PER_TDMR, max_reserved_per_tdmr),
|
||||
TD_SYSINFO_MAP(PAMT_4K_ENTRY_SIZE, pamt_entry_size[TDX_PS_4K]),
|
||||
TD_SYSINFO_MAP(PAMT_2M_ENTRY_SIZE, pamt_entry_size[TDX_PS_2M]),
|
||||
TD_SYSINFO_MAP(PAMT_1G_ENTRY_SIZE, pamt_entry_size[TDX_PS_1G]),
|
||||
};
|
||||
|
||||
static int get_tdx_tdmr_sysinfo(struct tdx_tdmr_sysinfo *tdmr_sysinfo)
|
||||
{
|
||||
int ret;
|
||||
int i;
|
||||
|
||||
/* Populate 'tdmr_sysinfo' fields using the mapping structure above: */
|
||||
for (i = 0; i < ARRAY_SIZE(fields); i++) {
|
||||
ret = read_sys_metadata_field16(fields[i].field_id,
|
||||
fields[i].offset,
|
||||
tdmr_sysinfo);
|
||||
if (ret)
|
||||
return ret;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -342,13 +300,13 @@ static int tdmr_size_single(u16 max_reserved_per_tdmr)
|
||||
}
|
||||
|
||||
static int alloc_tdmr_list(struct tdmr_info_list *tdmr_list,
|
||||
struct tdx_tdmr_sysinfo *tdmr_sysinfo)
|
||||
struct tdx_sys_info_tdmr *sysinfo_tdmr)
|
||||
{
|
||||
size_t tdmr_sz, tdmr_array_sz;
|
||||
void *tdmr_array;
|
||||
|
||||
tdmr_sz = tdmr_size_single(tdmr_sysinfo->max_reserved_per_tdmr);
|
||||
tdmr_array_sz = tdmr_sz * tdmr_sysinfo->max_tdmrs;
|
||||
tdmr_sz = tdmr_size_single(sysinfo_tdmr->max_reserved_per_tdmr);
|
||||
tdmr_array_sz = tdmr_sz * sysinfo_tdmr->max_tdmrs;
|
||||
|
||||
/*
|
||||
* To keep things simple, allocate all TDMRs together.
|
||||
@ -367,7 +325,7 @@ static int alloc_tdmr_list(struct tdmr_info_list *tdmr_list,
|
||||
* at a given index in the TDMR list.
|
||||
*/
|
||||
tdmr_list->tdmr_sz = tdmr_sz;
|
||||
tdmr_list->max_tdmrs = tdmr_sysinfo->max_tdmrs;
|
||||
tdmr_list->max_tdmrs = sysinfo_tdmr->max_tdmrs;
|
||||
tdmr_list->nr_consumed_tdmrs = 0;
|
||||
|
||||
return 0;
|
||||
@ -921,25 +879,29 @@ static int tdmrs_populate_rsvd_areas_all(struct tdmr_info_list *tdmr_list,
|
||||
/*
|
||||
* Construct a list of TDMRs on the preallocated space in @tdmr_list
|
||||
* to cover all TDX memory regions in @tmb_list based on the TDX module
|
||||
* TDMR global information in @tdmr_sysinfo.
|
||||
* TDMR global information in @sysinfo_tdmr.
|
||||
*/
|
||||
static int construct_tdmrs(struct list_head *tmb_list,
|
||||
struct tdmr_info_list *tdmr_list,
|
||||
struct tdx_tdmr_sysinfo *tdmr_sysinfo)
|
||||
struct tdx_sys_info_tdmr *sysinfo_tdmr)
|
||||
{
|
||||
u16 pamt_entry_size[TDX_PS_NR] = {
|
||||
sysinfo_tdmr->pamt_4k_entry_size,
|
||||
sysinfo_tdmr->pamt_2m_entry_size,
|
||||
sysinfo_tdmr->pamt_1g_entry_size,
|
||||
};
|
||||
int ret;
|
||||
|
||||
ret = fill_out_tdmrs(tmb_list, tdmr_list);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = tdmrs_set_up_pamt_all(tdmr_list, tmb_list,
|
||||
tdmr_sysinfo->pamt_entry_size);
|
||||
ret = tdmrs_set_up_pamt_all(tdmr_list, tmb_list, pamt_entry_size);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
ret = tdmrs_populate_rsvd_areas_all(tdmr_list, tmb_list,
|
||||
tdmr_sysinfo->max_reserved_per_tdmr);
|
||||
sysinfo_tdmr->max_reserved_per_tdmr);
|
||||
if (ret)
|
||||
tdmrs_free_pamt_all(tdmr_list);
|
||||
|
||||
@ -1098,9 +1060,18 @@ static int init_tdmrs(struct tdmr_info_list *tdmr_list)
|
||||
|
||||
static int init_tdx_module(void)
|
||||
{
|
||||
struct tdx_tdmr_sysinfo tdmr_sysinfo;
|
||||
struct tdx_sys_info sysinfo;
|
||||
int ret;
|
||||
|
||||
ret = get_tdx_sys_info(&sysinfo);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/* Check whether the kernel can support this module */
|
||||
ret = check_features(&sysinfo);
|
||||
if (ret)
|
||||
return ret;
|
||||
|
||||
/*
|
||||
* To keep things simple, assume that all TDX-protected memory
|
||||
* will come from the page allocator. Make sure all pages in the
|
||||
@ -1117,17 +1088,13 @@ static int init_tdx_module(void)
|
||||
if (ret)
|
||||
goto out_put_tdxmem;
|
||||
|
||||
ret = get_tdx_tdmr_sysinfo(&tdmr_sysinfo);
|
||||
if (ret)
|
||||
goto err_free_tdxmem;
|
||||
|
||||
/* Allocate enough space for constructing TDMRs */
|
||||
ret = alloc_tdmr_list(&tdx_tdmr_list, &tdmr_sysinfo);
|
||||
ret = alloc_tdmr_list(&tdx_tdmr_list, &sysinfo.tdmr);
|
||||
if (ret)
|
||||
goto err_free_tdxmem;
|
||||
|
||||
/* Cover all TDX-usable memory regions in TDMRs */
|
||||
ret = construct_tdmrs(&tdx_memlist, &tdx_tdmr_list, &tdmr_sysinfo);
|
||||
ret = construct_tdmrs(&tdx_memlist, &tdx_tdmr_list, &sysinfo.tdmr);
|
||||
if (ret)
|
||||
goto err_free_tdmrs;
|
||||
|
||||
|
@ -3,6 +3,7 @@
|
||||
#define _X86_VIRT_TDX_H
|
||||
|
||||
#include <linux/bits.h>
|
||||
#include "tdx_global_metadata.h"
|
||||
|
||||
/*
|
||||
* This file contains both macros and data structures defined by the TDX
|
||||
@ -26,35 +27,6 @@
|
||||
#define PT_NDA 0x0
|
||||
#define PT_RSVD 0x1
|
||||
|
||||
/*
|
||||
* Global scope metadata field ID.
|
||||
*
|
||||
* See Table "Global Scope Metadata", TDX module 1.5 ABI spec.
|
||||
*/
|
||||
#define MD_FIELD_ID_MAX_TDMRS 0x9100000100000008ULL
|
||||
#define MD_FIELD_ID_MAX_RESERVED_PER_TDMR 0x9100000100000009ULL
|
||||
#define MD_FIELD_ID_PAMT_4K_ENTRY_SIZE 0x9100000100000010ULL
|
||||
#define MD_FIELD_ID_PAMT_2M_ENTRY_SIZE 0x9100000100000011ULL
|
||||
#define MD_FIELD_ID_PAMT_1G_ENTRY_SIZE 0x9100000100000012ULL
|
||||
|
||||
/*
|
||||
* Sub-field definition of metadata field ID.
|
||||
*
|
||||
* See Table "MD_FIELD_ID (Metadata Field Identifier / Sequence Header)
|
||||
* Definition", TDX module 1.5 ABI spec.
|
||||
*
|
||||
* - Bit 33:32: ELEMENT_SIZE_CODE -- size of a single element of metadata
|
||||
*
|
||||
* 0: 8 bits
|
||||
* 1: 16 bits
|
||||
* 2: 32 bits
|
||||
* 3: 64 bits
|
||||
*/
|
||||
#define MD_FIELD_ID_ELE_SIZE_CODE(_field_id) \
|
||||
(((_field_id) & GENMASK_ULL(33, 32)) >> 32)
|
||||
|
||||
#define MD_FIELD_ID_ELE_SIZE_16BIT 1
|
||||
|
||||
struct tdmr_reserved_area {
|
||||
u64 offset;
|
||||
u64 size;
|
||||
@ -80,6 +52,9 @@ struct tdmr_info {
|
||||
DECLARE_FLEX_ARRAY(struct tdmr_reserved_area, reserved_areas);
|
||||
} __packed __aligned(TDMR_INFO_ALIGNMENT);
|
||||
|
||||
/* Bit definitions of TDX_FEATURES0 metadata field */
|
||||
#define TDX_FEATURES0_NO_RBP_MOD BIT(18)
|
||||
|
||||
/*
|
||||
* Do not put any hardware-defined TDX structure representations below
|
||||
* this comment!
|
||||
@ -99,13 +74,6 @@ struct tdx_memblock {
|
||||
int nid;
|
||||
};
|
||||
|
||||
/* "TDMR info" part of "Global Scope Metadata" for constructing TDMRs */
|
||||
struct tdx_tdmr_sysinfo {
|
||||
u16 max_tdmrs;
|
||||
u16 max_reserved_per_tdmr;
|
||||
u16 pamt_entry_size[TDX_PS_NR];
|
||||
};
|
||||
|
||||
/* Warn if kernel has less than TDMR_NR_WARN TDMRs after allocation */
|
||||
#define TDMR_NR_WARN 4
|
||||
|
||||
|
48
arch/x86/virt/vmx/tdx/tdx_global_metadata.c
Normal file
48
arch/x86/virt/vmx/tdx/tdx_global_metadata.c
Normal file
@ -0,0 +1,48 @@
|
||||
// SPDX-License-Identifier: GPL-2.0
|
||||
/*
|
||||
* Automatically generated functions to read TDX global metadata.
|
||||
*
|
||||
* This file doesn't compile on its own as it lacks of inclusion
|
||||
* of SEAMCALL wrapper primitive which reads global metadata.
|
||||
* Include this file to other C file instead.
|
||||
*/
|
||||
|
||||
static int get_tdx_sys_info_features(struct tdx_sys_info_features *sysinfo_features)
|
||||
{
|
||||
int ret = 0;
|
||||
u64 val;
|
||||
|
||||
if (!ret && !(ret = read_sys_metadata_field(0x0A00000300000008, &val)))
|
||||
sysinfo_features->tdx_features0 = val;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int get_tdx_sys_info_tdmr(struct tdx_sys_info_tdmr *sysinfo_tdmr)
|
||||
{
|
||||
int ret = 0;
|
||||
u64 val;
|
||||
|
||||
if (!ret && !(ret = read_sys_metadata_field(0x9100000100000008, &val)))
|
||||
sysinfo_tdmr->max_tdmrs = val;
|
||||
if (!ret && !(ret = read_sys_metadata_field(0x9100000100000009, &val)))
|
||||
sysinfo_tdmr->max_reserved_per_tdmr = val;
|
||||
if (!ret && !(ret = read_sys_metadata_field(0x9100000100000010, &val)))
|
||||
sysinfo_tdmr->pamt_4k_entry_size = val;
|
||||
if (!ret && !(ret = read_sys_metadata_field(0x9100000100000011, &val)))
|
||||
sysinfo_tdmr->pamt_2m_entry_size = val;
|
||||
if (!ret && !(ret = read_sys_metadata_field(0x9100000100000012, &val)))
|
||||
sysinfo_tdmr->pamt_1g_entry_size = val;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static int get_tdx_sys_info(struct tdx_sys_info *sysinfo)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
ret = ret ?: get_tdx_sys_info_features(&sysinfo->features);
|
||||
ret = ret ?: get_tdx_sys_info_tdmr(&sysinfo->tdmr);
|
||||
|
||||
return ret;
|
||||
}
|
25
arch/x86/virt/vmx/tdx/tdx_global_metadata.h
Normal file
25
arch/x86/virt/vmx/tdx/tdx_global_metadata.h
Normal file
@ -0,0 +1,25 @@
|
||||
/* SPDX-License-Identifier: GPL-2.0 */
|
||||
/* Automatically generated TDX global metadata structures. */
|
||||
#ifndef _X86_VIRT_TDX_AUTO_GENERATED_TDX_GLOBAL_METADATA_H
|
||||
#define _X86_VIRT_TDX_AUTO_GENERATED_TDX_GLOBAL_METADATA_H
|
||||
|
||||
#include <linux/types.h>
|
||||
|
||||
struct tdx_sys_info_features {
|
||||
u64 tdx_features0;
|
||||
};
|
||||
|
||||
struct tdx_sys_info_tdmr {
|
||||
u16 max_tdmrs;
|
||||
u16 max_reserved_per_tdmr;
|
||||
u16 pamt_4k_entry_size;
|
||||
u16 pamt_2m_entry_size;
|
||||
u16 pamt_1g_entry_size;
|
||||
};
|
||||
|
||||
struct tdx_sys_info {
|
||||
struct tdx_sys_info_features features;
|
||||
struct tdx_sys_info_tdmr tdmr;
|
||||
};
|
||||
|
||||
#endif
|
Loading…
Reference in New Issue
Block a user