From: Adrian Hunter <adrian.hunter@intel.com>
To: Kai Huang <kai.huang@intel.com>,
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, chao.gao@intel.com,
binbin.wu@linux.intel.com
Subject: Re: [PATCH v3 2/8] x86/virt/tdx: Remove 'struct field_mapping' and implement TD_SYSINFO_MAP() macro
Date: Thu, 29 Aug 2024 10:20:11 +0300 [thread overview]
Message-ID: <5235e05e-1d73-4f70-9b5d-b8648b1f4524@intel.com> (raw)
In-Reply-To: <9eb6b2e3577be66ea2f711e37141ca021bf0159b.1724741926.git.kai.huang@intel.com>
On 27/08/24 10:14, Kai Huang wrote:
Subject could be "Simplify the reading of Global Metadata Fields"
> TL;DR: Remove the 'struct field_mapping' structure and use another way
> to implement the TD_SYSINFO_MAP() macro to improve the current metadata
> reading code, e.g., switching to use build-time check for metadata field
> size over the existing runtime check.
Perhaps:
Remove 'struct field_mapping' and let read_sys_metadata_field16() accept
the member variable address, simplifying the code in preparation for adding
support for more metadata structures and field sizes.
>
> The TDX module provides a set of "global metadata fields". They report
Global Metadata Fields
> things like TDX module version, supported features, and fields related
> to create/run TDX guests and so on.
>
> For now the kernel only reads "TD Memory Region" (TDMR) related global
> metadata fields, and all of those fields are organized in one structure.
The patch is self-evidently simpler (21 insertions(+), 36 deletions(-))
so there doesn't seem to be any need for further elaboration. Perhaps
just round it off and stop there.
... and all of those fields are organized in one structure,
but that will change in the near future.
>
> The kernel currently uses 'struct field_mapping' to facilitate reading
> multiple metadata fields into one structure. The 'struct field_mapping'
> records the mapping between the field ID and the offset of the structure
> to fill out. The kernel initializes an array of 'struct field_mapping'
> for each structure member (using the TD_SYSINFO_MAP() macro) and then
> reads all metadata fields in a loop using that array.
>
> Currently the kernel only reads TDMR related metadata fields into one
> structure, and the function to read one metadata field takes the pointer
> of that structure and the offset:
>
> static int read_sys_metadata_field16(u64 field_id,
> int offset,
> struct tdx_sys_info_tdmr *ts)
> {...}
>
> Future changes will need to read more metadata fields into different
> structures. To support this the above function will need to be changed
> to take 'void *':
>
> static int read_sys_metadata_field16(u64 field_id,
> int offset,
> void *stbuf)
> {...}
>
> This approach loses type-safety, as Dan suggested. A better way is to
> make it be ..
>
> static int read_sys_metadata_field16(u64 field_id, u16 *val) {...}
>
> .. and let the caller calculate the buffer in a type-safe way [1].
>
> Also, the using of the 'struct field_mapping' loses the ability to be
> able to do build-time check about the metadata field size (encoded in
> the field ID) due to the field ID is "indirectly" initialized to the
> 'struct field_mapping' and passed to the function to read. Thus the
> current code uses runtime check instead.
>
> Dan suggested to remove the 'struct field_mapping', unroll the loop,
> skip the array, and call the read_sys_metadata_field16() directly with
> build-time check [1][2]. And to improve the readability, reimplement
> the TD_SYSINFO_MAP() [3].
>
> The new TD_SYSINFO_MAP() isn't perfect. It requires the function that
> uses it to define a local variable @ret to carry the error code and set
> the initial value to 0. It also hard-codes the variable name of the
> structure pointer used in the function. But overall the pros of this
> approach beat the cons.
>
> Link: https://lore.kernel.org/kvm/a107b067-861d-43f4-86b5-29271cb93dad@intel.com/T/#m7cfb3c146214d94b24e978eeb8708d92c0b14ac6 [1]
> Link: https://lore.kernel.org/kvm/a107b067-861d-43f4-86b5-29271cb93dad@intel.com/T/#mbe65f0903ff7835bc418a907f0d02d7a9e0b78be [2]
> Link: https://lore.kernel.org/kvm/a107b067-861d-43f4-86b5-29271cb93dad@intel.com/T/#m80cde5e6504b3af74d933ea0cbfc3ca9d24697d3 [3]
Probably just one link would suffice, say the permalink to Dan's
comment:
https://lore.kernel.org/kvm/66b16121c48f4_4fc729424@dwillia2-xfh.jf.intel.com.notmuch/
> Suggested-by: Dan Williams <dan.j.williams@intel.com>
> Signed-off-by: Kai Huang <kai.huang@intel.com>
> ---
>
> v2 -> v3:
> - Remove 'struct field_mapping' and reimplement TD_SYSINFO_MAP().
>
> ---
> arch/x86/virt/vmx/tdx/tdx.c | 57 ++++++++++++++-----------------------
> 1 file changed, 21 insertions(+), 36 deletions(-)
>
> diff --git a/arch/x86/virt/vmx/tdx/tdx.c b/arch/x86/virt/vmx/tdx/tdx.c
> index e979bf442929..7e75c1b10838 100644
> --- a/arch/x86/virt/vmx/tdx/tdx.c
> +++ b/arch/x86/virt/vmx/tdx/tdx.c
> @@ -270,60 +270,45 @@ 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_sys_info_tdmr *ts)
> +static int read_sys_metadata_field16(u64 field_id, u16 *val)
> {
> - u16 *ts_member = ((void *)ts) + offset;
> u64 tmp;
> int ret;
>
> - if (WARN_ON_ONCE(MD_FIELD_ID_ELE_SIZE_CODE(field_id) !=
> - MD_FIELD_ID_ELE_SIZE_16BIT))
> - return -EINVAL;
> + BUILD_BUG_ON(MD_FIELD_ID_ELE_SIZE_CODE(field_id) !=
> + MD_FIELD_ID_ELE_SIZE_16BIT);
This gets removed next patch, so why do it
>
> ret = read_sys_metadata_field(field_id, &tmp);
> if (ret)
> return ret;
>
> - *ts_member = tmp;
> + *val = 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_sys_info_tdmr, _offset) }
> -
> -/* Map TD_SYSINFO fields into 'struct tdx_sys_info_tdmr': */
> -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]),
> -};
> +/*
> + * Assumes locally defined @ret and @sysinfo_tdmr to convey the error
> + * code and the 'struct tdx_sys_info_tdmr' instance to fill out.
> + */
> +#define TD_SYSINFO_MAP(_field_id, _member) \
"MAP" made sense when it was in a struct whereas
now it is reading.
> + ({ \
> + if (!ret) \
> + ret = read_sys_metadata_field16(MD_FIELD_ID_##_field_id, \
> + &sysinfo_tdmr->_member); \
> + })
>
> static int get_tdx_sys_info_tdmr(struct tdx_sys_info_tdmr *sysinfo_tdmr)
> {
> - int ret;
> - int i;
> + int ret = 0;
>
> - /* Populate 'sysinfo_tdmr' 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,
> - sysinfo_tdmr);
> - if (ret)
> - return ret;
> - }
> + 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]);
Another possibility is to put the macro at the invocation site:
#define READ_SYS_INFO(_field_id, _member) \
ret = ret ?: read_sys_metadata_field16(MD_FIELD_ID_##_field_id, \
&sysinfo_tdmr->_member)
READ_SYS_INFO(MAX_TDMRS, max_tdmrs);
READ_SYS_INFO(MAX_RESERVED_PER_TDMR, max_reserved_per_tdmr);
READ_SYS_INFO(PAMT_4K_ENTRY_SIZE, pamt_entry_size[TDX_PS_4K]);
READ_SYS_INFO(PAMT_2M_ENTRY_SIZE, pamt_entry_size[TDX_PS_2M]);
READ_SYS_INFO(PAMT_1G_ENTRY_SIZE, pamt_entry_size[TDX_PS_1G]);
#undef READ_SYS_INFO
And so on in later patches:
#define READ_SYS_INFO(_field_id, _member) \
ret = ret ?: read_sys_metadata_field(MD_FIELD_ID_##_field_id, \
&sysinfo_version->_member)
READ_SYS_INFO(MAJOR_VERSION, major);
READ_SYS_INFO(MINOR_VERSION, minor);
READ_SYS_INFO(UPDATE_VERSION, update);
READ_SYS_INFO(INTERNAL_VERSION, internal);
READ_SYS_INFO(BUILD_NUM, build_num);
READ_SYS_INFO(BUILD_DATE, build_date);
#undef READ_SYS_INFO
>
> - return 0;
> + return ret;
> }
>
> /* Calculate the actual TDMR size */
next prev parent reply other threads:[~2024-08-29 7:20 UTC|newest]
Thread overview: 42+ messages / expand[flat|nested] mbox.gz Atom feed top
2024-08-27 7:14 [PATCH v3 0/8] TDX host: metadata reading tweaks, bug fix and info dump Kai Huang
2024-08-27 7:14 ` [PATCH v3 1/8] x86/virt/tdx: Rename 'struct tdx_tdmr_sysinfo' to reflect the spec better Kai Huang
2024-08-27 13:10 ` Adrian Hunter
2024-08-27 22:20 ` Huang, Kai
2024-09-24 11:39 ` Huang, Kai
2024-08-30 22:05 ` Dan Williams
2024-08-27 7:14 ` [PATCH v3 2/8] x86/virt/tdx: Remove 'struct field_mapping' and implement TD_SYSINFO_MAP() macro Kai Huang
2024-08-29 7:20 ` Adrian Hunter [this message]
2024-08-30 10:52 ` Huang, Kai
2024-09-06 21:30 ` Dan Williams
2024-09-09 9:59 ` Huang, Kai
2024-09-06 20:21 ` Dan Williams
2024-09-09 9:59 ` Huang, Kai
2024-08-27 7:14 ` [PATCH v3 3/8] x86/virt/tdx: Prepare to support reading other global metadata fields Kai Huang
2024-08-30 6:43 ` Adrian Hunter
2024-08-30 11:02 ` Huang, Kai
2024-08-30 9:05 ` Nikolay Borisov
2024-08-30 11:09 ` Huang, Kai
2024-09-06 21:34 ` Dan Williams
2024-09-09 12:28 ` Huang, Kai
2024-08-27 7:14 ` [PATCH v3 4/8] x86/virt/tdx: Refine a comment to reflect the latest TDX spec Kai Huang
2024-08-30 6:45 ` Adrian Hunter
2024-08-30 9:14 ` Nikolay Borisov
2024-08-27 7:14 ` [PATCH v3 5/8] x86/virt/tdx: Start to track all global metadata in one structure Kai Huang
2024-08-30 7:02 ` Adrian Hunter
2024-08-30 11:10 ` Huang, Kai
2024-08-30 11:01 ` Nikolay Borisov
2024-08-30 11:57 ` Huang, Kai
2024-08-27 7:14 ` [PATCH v3 6/8] x86/virt/tdx: Print TDX module basic information Kai Huang
2024-09-06 22:46 ` Dan Williams
2024-09-09 10:18 ` Huang, Kai
2024-08-27 7:14 ` [PATCH v3 7/8] x86/virt/tdx: Reduce TDMR's reserved areas by using CMRs to find memory holes Kai Huang
2024-08-30 10:50 ` Adrian Hunter
2024-08-30 11:52 ` Huang, Kai
2024-08-30 12:02 ` Adrian Hunter
2024-08-30 12:27 ` Nikolay Borisov
2024-09-06 23:31 ` Dan Williams
2024-09-09 10:30 ` Huang, Kai
2024-08-27 7:14 ` [PATCH v3 8/8] x86/virt/tdx: Don't initialize module that doesn't support NO_RBP_MOD feature Kai Huang
2024-08-30 11:01 ` Adrian Hunter
2024-09-06 23:36 ` Dan Williams
2024-09-09 10:21 ` 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=5235e05e-1d73-4f70-9b5d-b8648b1f4524@intel.com \
--to=adrian.hunter@intel.com \
--cc=binbin.wu@linux.intel.com \
--cc=bp@alien8.de \
--cc=chao.gao@intel.com \
--cc=dan.j.williams@intel.com \
--cc=dave.hansen@intel.com \
--cc=hpa@zytor.com \
--cc=isaku.yamahata@intel.com \
--cc=kai.huang@intel.com \
--cc=kirill.shutemov@linux.intel.com \
--cc=kvm@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@redhat.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
all inboxes | Powered by JetHome®