public inbox for kvm@vger.kernel.org
 help / color / mirror / Atom feed
From: Kai Huang <kai.huang@intel.com>
To: dave.hansen@intel.com, kirill.shutemov@linux.intel.com,
	tglx@linutronix.de, bp@alien8.de, peterz@infradead.org,
	mingo@redhat.com, hpa@zytor.com, dan.j.williams@intel.com,
	seanjc@google.com, pbonzini@redhat.com
Cc: x86@kernel.org, linux-kernel@vger.kernel.org,
	kvm@vger.kernel.org, rick.p.edgecombe@intel.com,
	isaku.yamahata@intel.com, adrian.hunter@intel.com,
	nik.borisov@suse.com, kai.huang@intel.com
Subject: [PATCH 9/8] x86/virt/tdx: Add the global metadata code generation script
Date: Thu, 31 Oct 2024 23:44:33 +1300	[thread overview]
Message-ID: <20241031104433.855336-1-kai.huang@intel.com> (raw)
In-Reply-To: <cover.1730118186.git.kai.huang@intel.com>

From: Paolo Bonzini <pbonzini@redhat.com>

Currently, the global metadata reading code is auto-generated by a
script [1].  Future work to support KVM TDX will need to read more
fields thus will need to regenerate the metadata reading code.

Add the script to the kernel tree to keep it under track [2].

Note the script has some minor updates (to make it more readable)
comparing to [1] but they don't change the generated code.  Also change
the name to tdx_global_metadata.py to make it more specific.

Link: https://lore.kernel.org/0853b155ec9aac09c594caa60914ed6ea4dc0a71.camel@intel.com/ [1]
Link: https://lore.kernel.org/CABgObfZWjGc0FT2My_oEd6V8ZxYHD-RejndbU_FipuADgJkFbw@mail.gmail.com/ [2]
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Co-developed-by: Kai Huang <kai.huang@intel.com>
Signed-off-by: Kai Huang <kai.huang@intel.com>
---
 MAINTAINERS                    |   1 +
 scripts/tdx_global_metadata.py | 187 +++++++++++++++++++++++++++++++++
 2 files changed, 188 insertions(+)
 create mode 100644 scripts/tdx_global_metadata.py

diff --git a/MAINTAINERS b/MAINTAINERS
index cf02cbf4bef1..fc983bc02109 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -24987,6 +24987,7 @@ T:	git git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip.git x86/core
 F:	Documentation/arch/x86/
 F:	Documentation/devicetree/bindings/x86/
 F:	arch/x86/
+F:	scripts/tdx_global_metadata.py
 F:	tools/testing/selftests/x86
 
 X86 CPUID DATABASE
diff --git a/scripts/tdx_global_metadata.py b/scripts/tdx_global_metadata.py
new file mode 100644
index 000000000000..7f5cc13b1d78
--- /dev/null
+++ b/scripts/tdx_global_metadata.py
@@ -0,0 +1,187 @@
+#! /usr/bin/env python3
+# SPDX-License-Identifier: GPL-2.0
+import json
+import sys
+
+# Note: this script does not run as part of the build process.
+# It is used to generate structs from the TDX global_metadata.json
+# file, and functions to fill in said structs.  Rerun it if
+# you need more fields.
+
+TDX_STRUCTS = {
+    "version": [
+        "BUILD_DATE",
+        "BUILD_NUM",
+        "MINOR_VERSION",
+        "MAJOR_VERSION",
+        "UPDATE_VERSION",
+        "INTERNAL_VERSION",
+    ],
+    "features": [
+        "TDX_FEATURES0"
+    ],
+    "tdmr": [
+        "MAX_TDMRS",
+        "MAX_RESERVED_PER_TDMR",
+        "PAMT_4K_ENTRY_SIZE",
+        "PAMT_2M_ENTRY_SIZE",
+        "PAMT_1G_ENTRY_SIZE",
+    ],
+    "cmr": [
+        "NUM_CMRS", "CMR_BASE", "CMR_SIZE"
+    ],
+}
+
+STRUCT_PREFIX = "tdx_sys_info"
+FUNC_PREFIX = "get_tdx_sys_info"
+STRVAR_PREFIX = "sysinfo"
+
+def print_class_struct_field(field_name, element_bytes, num_fields, num_elements, file):
+    element_type = "u%s" % (element_bytes * 8)
+    element_array = ""
+    if num_fields > 1:
+        element_array += "[%d]" % (num_fields)
+    if num_elements > 1:
+        element_array += "[%d]" % (num_elements)
+    print("\t%s %s%s;" % (element_type, field_name, element_array), file=file)
+
+def print_class_struct(class_name, fields, file):
+    struct_name = "%s_%s" % (STRUCT_PREFIX, class_name)
+    print("struct %s {" % (struct_name), file=file)
+    for f in fields:
+        print_class_struct_field(
+            f["Field Name"].lower(),
+            int(f["Element Size (Bytes)"]),
+            int(f["Num Fields"]),
+            int(f["Num Elements"]),
+            file=file)
+    print("};", file=file)
+
+def print_read_field(field_id, struct_var, struct_member, indent, file):
+    print(
+        "%sif (!ret && !(ret = read_sys_metadata_field(%s, &val)))\n%s\t%s->%s = val;"
+        % (indent, field_id, indent, struct_var, struct_member),
+        file=file,
+    )
+
+def print_class_function(class_name, fields, file):
+    func_name = "%s_%s" % (FUNC_PREFIX, class_name)
+    struct_name = "%s_%s" % (STRUCT_PREFIX, class_name)
+    struct_var = "%s_%s" % (STRVAR_PREFIX, class_name)
+
+    print("static int %s(struct %s *%s)" % (func_name, struct_name, struct_var), file=file)
+    print("{", file=file)
+    print("\tint ret = 0;", file=file)
+    print("\tu64 val;", file=file)
+
+    has_i = 0
+    has_j = 0
+    for f in fields:
+        num_fields = int(f["Num Fields"])
+        num_elements = int(f["Num Elements"])
+        if num_fields > 1:
+            has_i = 1
+        if num_elements > 1:
+            has_j = 1
+
+    if has_i == 1 and has_j == 1:
+        print("\tint i, j;", file=file)
+    elif has_i == 1:
+        print("\tint i;", file=file)
+
+    print(file=file)
+    for f in fields:
+        fname = f["Field Name"]
+        field_id = f["Base FIELD_ID (Hex)"]
+        num_fields = int(f["Num Fields"])
+        num_elements = int(f["Num Elements"])
+        struct_member = fname.lower()
+        indent = "\t"
+        if num_fields > 1:
+            if fname == "CMR_BASE" or fname == "CMR_SIZE":
+                limit = "%s_%s->num_cmrs" %(STRVAR_PREFIX, "cmr")
+            elif fname == "CPUID_CONFIG_LEAVES" or fname == "CPUID_CONFIG_VALUES":
+                limit = "%s_%s->num_cpuid_config" %(STRVAR_PREFIX, "td_conf")
+            else:
+                limit = "%d" %(num_fields)
+            print("%sfor (i = 0; i < %s; i++)" % (indent, limit), file=file)
+            indent += "\t"
+            field_id += " + i"
+            struct_member += "[i]"
+        if num_elements > 1:
+            print("%sfor (j = 0; j < %d; j++)" % (indent, num_elements), file=file)
+            indent += "\t"
+            field_id += " * 2 + j"
+            struct_member += "[j]"
+
+        print_read_field(
+            field_id,
+            struct_var,
+            struct_member,
+            indent,
+            file=file,
+        )
+
+    print(file=file)
+    print("\treturn ret;", file=file)
+    print("}", file=file)
+
+def print_main_struct(file):
+    print("struct tdx_sys_info {", file=file)
+    for class_name, field_names in TDX_STRUCTS.items():
+        struct_name = "%s_%s" % (STRUCT_PREFIX, class_name)
+        struct_var = class_name
+        print("\tstruct %s %s;" % (struct_name, struct_var), file=file)
+    print("};", file=file)
+
+def print_main_function(file):
+    print("static int get_tdx_sys_info(struct tdx_sys_info *sysinfo)", file=file)
+    print("{", file=file)
+    print("\tint ret = 0;", file=file)
+    print(file=file)
+    for class_name, field_names in TDX_STRUCTS.items():
+        func_name = "%s_%s" % (FUNC_PREFIX, class_name)
+        struct_var = class_name
+        print("\tret = ret ?: %s(&sysinfo->%s);" % (func_name, struct_var), file=file)
+    print(file=file)
+    print("\treturn ret;", file=file)
+    print("}", file=file)
+
+jsonfile = sys.argv[1]
+hfile = sys.argv[2]
+cfile = sys.argv[3]
+hfileifdef = hfile.replace(".", "_")
+
+with open(jsonfile, "r") as f:
+    json_in = json.load(f)
+    fields = {x["Field Name"]: x for x in json_in["Fields"]}
+
+with open(hfile, "w") as f:
+    print("/* SPDX-License-Identifier: GPL-2.0 */", file=f)
+    print("/* Automatically generated TDX global metadata structures. */", file=f)
+    print("#ifndef _X86_VIRT_TDX_AUTO_GENERATED_" + hfileifdef.upper(), file=f)
+    print("#define _X86_VIRT_TDX_AUTO_GENERATED_" + hfileifdef.upper(), file=f)
+    print(file=f)
+    print("#include <linux/types.h>", file=f)
+    print(file=f)
+    for class_name, field_names in TDX_STRUCTS.items():
+        print_class_struct(class_name, [fields[x] for x in field_names], file=f)
+        print(file=f)
+    print_main_struct(file=f)
+    print(file=f)
+    print("#endif", file=f)
+
+with open(cfile, "w") as f:
+    print("// SPDX-License-Identifier: GPL-2.0", file=f)
+    print("/*", file=f)
+    print(" * Automatically generated functions to read TDX global metadata.", file=f)
+    print(" *", file=f)
+    print(" * This file doesn't compile on its own as it lacks of inclusion", file=f)
+    print(" * of SEAMCALL wrapper primitive which reads global metadata.", file=f)
+    print(" * Include this file to other C file instead.", file=f)
+    print(" */", file=f)
+    for class_name, field_names in TDX_STRUCTS.items():
+        print(file=f)
+        print_class_function(class_name, [fields[x] for x in field_names], file=f)
+    print(file=f)
+    print_main_function(file=f)
-- 
2.46.2


  parent reply	other threads:[~2024-10-31 10:45 UTC|newest]

Thread overview: 34+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2024-10-28 12:41 [PATCH v6 00/10] TDX host: metadata reading tweaks, bug fix and info dump Kai Huang
2024-10-28 12:41 ` [PATCH v6 01/10] x86/virt/tdx: Rename 'struct tdx_tdmr_sysinfo' to reflect the spec better Kai Huang
2024-10-28 12:41 ` [PATCH v6 02/10] x86/virt/tdx: Start to track all global metadata in one structure Kai Huang
2024-10-28 21:37   ` Dan Williams
2024-10-28 12:41 ` [PATCH v6 03/10] x86/virt/tdx: Use auto-generated code to read global metadata Kai Huang
2024-10-28 21:46   ` Dan Williams
2024-10-28 22:47     ` Huang, Kai
2024-10-28 12:41 ` [PATCH v6 04/10] x86/virt/tdx: Use dedicated struct members for PAMT entry sizes Kai Huang
2024-10-28 13:29   ` Nikolay Borisov
2024-10-28 21:51   ` Dan Williams
2024-10-28 12:41 ` [PATCH v6 05/10] x86/virt/tdx: Add missing header file inclusion to local tdx.h Kai Huang
2024-10-28 13:35   ` Nikolay Borisov
2024-10-28 21:55   ` Dan Williams
2024-10-28 12:41 ` [PATCH v6 06/10] x86/virt/tdx: Switch to use auto-generated global metadata reading code Kai Huang
2024-10-28 14:55   ` Nikolay Borisov
2024-10-28 22:08   ` Dan Williams
2024-10-28 12:41 ` [PATCH v6 07/10] x86/virt/tdx: Trim away tail null CMRs Kai Huang
2024-10-28 22:12   ` Dan Williams
2024-10-28 12:41 ` [PATCH v6 08/10] x86/virt/tdx: Reduce TDMR's reserved areas by using CMRs to find memory holes Kai Huang
2024-10-28 22:26   ` Dan Williams
2024-10-28 23:22     ` Huang, Kai
2024-10-28 12:41 ` [PATCH v6 09/10] x86/virt/tdx: Require the module to assert it has the NO_RBP_MOD mitigation Kai Huang
2024-10-28 12:41 ` [PATCH v6 10/10] x86/virt/tdx: Print TDX module version Kai Huang
2024-10-28 22:36   ` Dan Williams
2024-10-28 22:59     ` Huang, Kai
2024-10-28 17:59 ` [PATCH v6 00/10] TDX host: metadata reading tweaks, bug fix and info dump Paolo Bonzini
2024-10-28 21:50   ` Huang, Kai
2024-10-28 18:35 ` Paolo Bonzini
2024-10-28 21:39   ` Huang, Kai
2024-10-29  0:23     ` Huang, Kai
2024-10-30 14:48       ` Paolo Bonzini
2024-10-30 20:40         ` Huang, Kai
2024-10-31 10:44 ` Kai Huang [this message]
2024-11-06 11:00 ` Huang, Kai

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20241031104433.855336-1-kai.huang@intel.com \
    --to=kai.huang@intel.com \
    --cc=adrian.hunter@intel.com \
    --cc=bp@alien8.de \
    --cc=dan.j.williams@intel.com \
    --cc=dave.hansen@intel.com \
    --cc=hpa@zytor.com \
    --cc=isaku.yamahata@intel.com \
    --cc=kirill.shutemov@linux.intel.com \
    --cc=kvm@vger.kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=mingo@redhat.com \
    --cc=nik.borisov@suse.com \
    --cc=pbonzini@redhat.com \
    --cc=peterz@infradead.org \
    --cc=rick.p.edgecombe@intel.com \
    --cc=seanjc@google.com \
    --cc=tglx@linutronix.de \
    --cc=x86@kernel.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox