mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
* [PATCH v4 00/10] TDX: Stop auto-generating the global metadata code
@ 2026-10-12  9:47 Chao Gao
  2026-10-12  9:47 ` [PATCH v4 01/10] x86/virt/tdx: Add a helper to read a table of metadata fields Chao Gao
                   ` (9 more replies)
  0 siblings, 10 replies; 11+ messages in thread
From: Chao Gao @ 2026-10-12  9:47 UTC (permalink / raw)
  To: x86, linux-coco, kvm, linux-kernel
  Cc: yilun.xu, chao.gao, binbin.wu, tony.lindgren, rick.p.edgecombe,
	nik.borisov, Kiryl Shutsemau, Dave Hansen, Thomas Gleixner,
	Ingo Molnar, Borislav Petkov, H. Peter Anvin

This series cleans up the TDX global metadata code. It has two goals:

1. Replace the generated code with a table-driven metadata reader.

2. Make the existing code easier to read and maintain, and simplify
   adding new metadata fields.

Most of the feedback on v3 was about style and small nits, and eight of
the ten patches now have Reviewed-by tags. Patches 7 and 10 still need
review.

Dave, if there are no further comments, please consider merging this
series.

This series conflicts with the TDX Module Extensions series, which adds
new metadata fields. If needed, I am happy to provide a patch that
resolves the conflicts.

Changes since v3:
=================

The per-class macros are gone. Dave and Nikolay found them to be an
unnecessary layer, so every table entry now uses FIELD_MAP() directly.

Spelling out the full structure type in each entry would make most
entries 80-100 columns wide, and two would go over 100. As Yilun
suggested, FIELD_MAP() now takes only the part of the structure name
after tdx_sys_info_ and builds the full name from it, which keeps the
entries readable.

All entries now fit in 80 columns, with two of them wrapped onto a
second line.

Other changes:
  - Patch 7: Read the two cpuid_config_values[] entries with two
    explicit calls instead of an inner loop [Nikolay]
  - Patch 9: Reword the justification for printing the module version
    only after a successful read [Rick]
  - Patch 10: Encode the member size and compare it with the size bits
    in the field ID, instead of decoding the field ID with shifts and
    masks [Rick]
  - Collect Reviewed-by tags from Rick and Nikolay
  - v3: https://lore.kernel.org/kvm/20260930053901.22528-1-chao.gao@intel.com/

Problem & Solution
==================

The TDX module reports its capabilities and limits through a set of global
metadata fields, each read using a 64-bit field ID via TDH.SYS.RD. The
fields are grouped into classes, and the kernel mirrors each class it
needs in a sub-structure of struct tdx_sys_info.

Both those structures and the code that fills them were generated by an
out-of-tree script from a JSON file.

The script was not the first approach.  Kai's first attempt paired each
field ID with its destination C member in a table and walked the table in a
loop to read every field.  Two pieces of feedback on it drove everything
that followed [1]:

  1. Compile-time type checking. Metadata fields have different sizes (u16
     and u64), so a common helper takes a void * and a size instead of
     a typed destination.

  2. The check that a field ID's encoded size matches its destination
     member ran at runtime, although both sizes are known at build time.

The discussion did not converge after several rounds of review. Dave noted
that, despite the void *, the size check provides the safety that matters:
it catches mismatched field and member widths [2]. That left one problem:
moving the size check from runtime to build time.

Before that was settled, the direction shifted to generating the code with a
script. At the time, the TDX ABI definitions were published as JSON, so
checking a field ID required consulting a machine-readable file by hand.
The script parsed the JSON and generated both the structures and their
readers [3]. Generation also made the size/type check unnecessary. The
field IDs and destination members came from the same input, so a mismatch
could only result from a bug in the script, which is less likely than a
mistake in hand-written code.

Dave concluded that the JSON experiment had failed [4] for two reasons:

  1. The JSON file is not stable. The CPUID config arrays here were once
     sized for a maximum of 32 entries, which has since increased to 128 [5].

  2. The JSON file is not authoritative enough to write code from by itself.

TDX ABI definitions are now available in human-readable PDF specifications
[6]. So, stop relying on the out-of-tree script and maintain the code by
hand.

Yilun later proposed a single table whose entries carry the offset and size
of each mapped member in struct tdx_sys_info [7]. That design does not
cover the new handoff metadata because it is not cached in
struct tdx_sys_info.

This series gives every class its own table: each entry pairs a field ID
with the member that holds it, and a loop walks the table. This also covers
handoff metadata, which is read into a local structure rather than into
struct tdx_sys_info.

The common reader still takes a void *, but each mapping verifies at build
time that the destination member size matches the size encoded in the field
ID. A field/member width mismatch therefore fails the build.

AI usage
========

I used LLM tools to review the patches and refine the wording of the cover
letter and changelogs from my drafts. I reviewed all suggestions and adopted
those I agreed with. For example, AI review suggested the
read_sys_metadata_table() macro, which avoids repeating the table name when
passing both the table and its size.


Testing
=======
Built each patch individually and successfully launched TDs.


Chao Gao (10):
  x86/virt/tdx: Add a helper to read a table of metadata fields
  x86/virt/tdx: Convert the version metadata reader
  x86/virt/tdx: Convert the features metadata reader
  x86/virt/tdx: Convert the tdmr metadata reader
  x86/virt/tdx: Convert the td_ctrl metadata reader
  x86/virt/tdx: Convert the handoff metadata reader
  x86/virt/tdx: Convert the td_conf metadata reader
  x86/virt/tdx: Remove tdx_global_metadata.c
  x86/virt/tdx: Use early returns in get_tdx_sys_info()
  x86/virt/tdx: Verify structure member sizes against metadata field IDs

 arch/x86/virt/vmx/tdx/tdx.c                 | 190 +++++++++++++++++++-
 arch/x86/virt/vmx/tdx/tdx.h                 |  52 ++++++
 arch/x86/virt/vmx/tdx/tdx_global_metadata.c | 154 ----------------
 3 files changed, 239 insertions(+), 157 deletions(-)
 delete mode 100644 arch/x86/virt/vmx/tdx/tdx_global_metadata.c


base-commit: 5b8212d45d99b77c84e3ad305a295e9e65d5ef20
-- 
2.52.0


^ permalink raw reply	[flat|nested] 11+ messages in thread

end of thread, other threads:[~2026-10-12  9:50 UTC | newest]

Thread overview: 11+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2026-10-12  9:47 [PATCH v4 00/10] TDX: Stop auto-generating the global metadata code Chao Gao
2026-10-12  9:47 ` [PATCH v4 01/10] x86/virt/tdx: Add a helper to read a table of metadata fields Chao Gao
2026-10-12  9:47 ` [PATCH v4 02/10] x86/virt/tdx: Convert the version metadata reader Chao Gao
2026-10-12  9:47 ` [PATCH v4 03/10] x86/virt/tdx: Convert the features " Chao Gao
2026-10-12  9:47 ` [PATCH v4 04/10] x86/virt/tdx: Convert the tdmr " Chao Gao
2026-10-12  9:47 ` [PATCH v4 05/10] x86/virt/tdx: Convert the td_ctrl " Chao Gao
2026-10-12  9:47 ` [PATCH v4 06/10] x86/virt/tdx: Convert the handoff " Chao Gao
2026-10-12  9:47 ` [PATCH v4 07/10] x86/virt/tdx: Convert the td_conf " Chao Gao
2026-10-12  9:47 ` [PATCH v4 08/10] x86/virt/tdx: Remove tdx_global_metadata.c Chao Gao
2026-10-12  9:47 ` [PATCH v4 09/10] x86/virt/tdx: Use early returns in get_tdx_sys_info() Chao Gao
2026-10-12  9:47 ` [PATCH v4 10/10] x86/virt/tdx: Verify structure member sizes against metadata field IDs Chao Gao

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®