@@ -287,6 +287,7 @@ static int __read_sys_metadata_field##_size(u64 field_id, u##_size *val) \
build_sysmd_read(16)
build_sysmd_read(32)
+build_sysmd_read(64)
#define read_sys_metadata_field(_field_id, _val, _size) \
({ \
@@ -296,6 +297,21 @@ build_sysmd_read(32)
__read_sys_metadata_field##_size(_field_id, _val); \
})
+static int get_tdx_sys_info_features(struct tdx_sys_info_features *sysinfo_features)
+{
+ int ret = 0;
+
+#define READ_SYS_INFO(_field_id, _member) \
+ ret = ret ?: read_sys_metadata_field(MD_FIELD_ID_##_field_id, \
+ &sysinfo_features->_member, 64)
+
+ READ_SYS_INFO(TDX_FEATURES0, tdx_features0);
+
+#undef READ_SYS_INFO
+
+ return ret;
+}
+
static int get_tdx_sys_info_version(struct tdx_sys_info_version *sysinfo_version)
{
int ret = 0;
@@ -339,6 +355,10 @@ static int get_tdx_sys_info(struct tdx_sys_info *sysinfo)
{
int ret;
+ ret = get_tdx_sys_info_features(&sysinfo->features);
+ if (ret)
+ return ret;
+
ret = get_tdx_sys_info_version(&sysinfo->version);
if (ret)
return ret;
@@ -368,6 +388,18 @@ static void print_basic_sys_info(struct tdx_sys_info *sysinfo)
print_sys_info_version(&sysinfo->version);
}
+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;
+ }
+
+ return 0;
+}
+
/* Calculate the actual TDMR size */
static int tdmr_size_single(u16 max_reserved_per_tdmr)
{
@@ -1149,6 +1181,11 @@ static int init_tdx_module(void)
print_basic_sys_info(&sysinfo);
+ /* 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
@@ -31,6 +31,7 @@
*
* See the "global_metadata.json" in the "TDX 1.5 ABI definitions".
*/
+#define MD_FIELD_ID_TDX_FEATURES0 0x0A00000300000008ULL
#define MD_FIELD_ID_BUILD_DATE 0x8800000200000001ULL
#define MD_FIELD_ID_BUILD_NUM 0x8800000100000002ULL
#define MD_FIELD_ID_MINOR_VERSION 0x0800000100000003ULL
@@ -61,6 +62,7 @@
#define MD_FIELD_ID_ELE_SIZE_16BIT 1
#define MD_FIELD_ID_ELE_SIZE_32BIT 2
+#define MD_FIELD_ID_ELE_SIZE_64BIT 3
struct tdmr_reserved_area {
u64 offset;
@@ -105,6 +107,20 @@ struct tdmr_info {
* those used by the kernel are.
*/
+/*
+ * Class "TDX Module Info".
+ *
+ * This class also contains other fields like SYS_ATTRIBUTES and the
+ * NUM_TDX_FEATURES. For now only TDX_FEATURES0 is needed, but still
+ * keep the structure to follow the spec (and for future extension).
+ */
+struct tdx_sys_info_features {
+ u64 tdx_features0;
+};
+
+/* Bit definitions of TDX_FEATURES0 metadata field */
+#define TDX_FEATURES0_NO_RBP_MOD _BITULL(18)
+
/* Class "TDX Module Version" */
struct tdx_sys_info_version {
u16 major;
@@ -123,6 +139,7 @@ struct tdx_sys_info_tdmr {
};
struct tdx_sys_info {
+ struct tdx_sys_info_features features;
struct tdx_sys_info_version version;
struct tdx_sys_info_tdmr tdmr;
};