public inbox for kvm@vger.kernel.org
 help / color / mirror / Atom feed
From: "Huang, Kai" <kai.huang@intel.com>
To: "Hansen, Dave" <dave.hansen@intel.com>,
	"seanjc@google.com" <seanjc@google.com>,
	"bp@alien8.de" <bp@alien8.de>,
	"peterz@infradead.org" <peterz@infradead.org>,
	"hpa@zytor.com" <hpa@zytor.com>,
	"mingo@redhat.com" <mingo@redhat.com>,
	"kirill.shutemov@linux.intel.com"
	<kirill.shutemov@linux.intel.com>,
	"tglx@linutronix.de" <tglx@linutronix.de>,
	"pbonzini@redhat.com" <pbonzini@redhat.com>,
	"Hunter, Adrian" <adrian.hunter@intel.com>,
	"Williams, Dan J" <dan.j.williams@intel.com>
Cc: "Gao, Chao" <chao.gao@intel.com>,
	"kvm@vger.kernel.org" <kvm@vger.kernel.org>,
	"binbin.wu@linux.intel.com" <binbin.wu@linux.intel.com>,
	"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
	"Edgecombe, Rick P" <rick.p.edgecombe@intel.com>,
	"x86@kernel.org" <x86@kernel.org>,
	"Yamahata, Isaku" <isaku.yamahata@intel.com>
Subject: Re: [PATCH v3 2/8] x86/virt/tdx: Remove 'struct field_mapping' and implement TD_SYSINFO_MAP() macro
Date: Fri, 30 Aug 2024 10:52:29 +0000	[thread overview]
Message-ID: <b78ff897309014ea151f6eec68beff9b88f00e15.camel@intel.com> (raw)
In-Reply-To: <5235e05e-1d73-4f70-9b5d-b8648b1f4524@intel.com>

On Thu, 2024-08-29 at 10:20 +0300, Adrian Hunter wrote:
> On 27/08/24 10:14, Kai Huang wrote:
> 
> Subject could be "Simplify the reading of Global Metadata Fields"

OK.

> 
> > 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.

Fine to me.  I would like also to mention there are improvements in the new
code (as suggested by Dan), so I will say:

"..., simplifying and improving the code in preparation ...".

> 
> > 
> > The TDX module provides a set of "global metadata fields".  They report
> 
> Global Metadata Fields

OK. 

> 
> > 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.

I think the code change here is not only to reduce the LoC (i.e., simplify the
code), but also improve the code, so I would like to keep the things mentioned
by Dan in the changelog.

> 
> > 
> > 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/

[1] and [2] are actually replies to different patches, so I would like to keep
them.  [1] and [3] are replies to the same patch, so I could remove [3], but I
think keeping all of them is also fine since it's more easy to find the exact
comment that I want to address.

> 
> > 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

This patch I didn't add the build-time check in the (new) TD_SYSINFO_MAP(), so
I changed the runtime check to build-time check here since we can actually do
it here.  I think even for this middle state patch we should do the build-time
check.  I can move it to the (new) TD_SYSINFO_MAP() though if that's better.

> 
> >  
> >  	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
> 

This is fine to me.  But AFAICT Kirill doesn't like the "#undef" part.

Kirill, do you have comments?

Otherwise I will go with what Adrian suggested.

  reply	other threads:[~2024-08-30 10:52 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
2024-08-30 10:52     ` Huang, Kai [this message]
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=b78ff897309014ea151f6eec68beff9b88f00e15.camel@intel.com \
    --to=kai.huang@intel.com \
    --cc=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=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