Re: [PATCH v19 029/130] KVM: TDX: Add C wrapper functions for SEAMCALLs to the TDX module

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



On Thu, Mar 21, 2024 at 11:37:58AM +1300,
"Huang, Kai" <kai.huang@xxxxxxxxx> wrote:

> 
> 
> On 21/03/2024 10:36 am, Isaku Yamahata wrote:
> > On Wed, Mar 20, 2024 at 01:03:21PM +1300,
> > "Huang, Kai" <kai.huang@xxxxxxxxx> wrote:
> > 
> > > > +static inline u64 tdx_seamcall(u64 op, struct tdx_module_args *in,
> > > > +			       struct tdx_module_args *out)
> > > > +{
> > > > +	u64 ret;
> > > > +
> > > > +	if (out) {
> > > > +		*out = *in;
> > > > +		ret = seamcall_ret(op, out);
> > > > +	} else
> > > > +		ret = seamcall(op, in);
> > > 
> > > I think it's silly to have the @out argument in this way.
> > > 
> > > What is the main reason to still have it?
> > > 
> > > Yeah we used to have the @out in __seamcall() assembly function.  The
> > > assembly code checks the @out and skips copying registers to @out when it is
> > > NULL.
> > > 
> > > But it got removed when we tried to unify the assembly for TDCALL/TDVMCALL
> > > and SEAMCALL to have a *SINGLE* assembly macro.
> > > 
> > > https://lore.kernel.org/lkml/cover.1692096753.git.kai.huang@xxxxxxxxx/
> > > 
> > > To me that means we should just accept the fact we will always have a valid
> > > @out.
> > > 
> > > But there might be some case that you _obviously_ need the @out and I
> > > missed?
> > 
> > As I replied at [1], those four wrappers need to return values.
> > The first three on error, the last one on success.
> > 
> >    [1] https://lore.kernel.org/kvm/20240320202040.GH1994522@xxxxxxxxxxxxxxxxxxxxx/
> > 
> >    tdh_mem_sept_add(kvm_tdx, gpa, tdx_level, hpa, &entry, &level_state);
> >    tdh_mem_page_aug(kvm_tdx, gpa, hpa, &entry, &level_state);
> >    tdh_mem_page_remove(kvm_tdx, gpa, tdx_level, &entry, &level_state);
> >    u64 tdh_vp_rd(struct vcpu_tdx *tdx, u64 field, u64 *value)
> > 
> > We can delete out from other wrappers.
> 
> Ah, OK.  I got you don't want to invent separate wrappers for each
> seamcall() variants like:
> 
>  - tdx_seamcall(u64 fn, struct tdx_module_args *args);
>  - tdx_seamcall_ret(u64 fn, struct tdx_module_args *args);
>  - tdx_seamcall_saved_ret(u64 fn, struct tdx_module_args *args);
> 
> To be honest I found they were kinda annoying myself during the "unify
> TDCALL/SEAMCALL and TDVMCALL assembly" patchset.
> 
> But life is hard...
> 
> And given (it seems) we are going to remove kvm_spurious_fault(), I think
> the tdx_seamcall() variants are just very simple wrapper of plain seamcall()
> variants.
> 
> So how about we have some macros:
> 
> static inline bool is_seamcall_err_kernel_defined(u64 err)
> {
> 	return err & TDX_SW_ERROR;
> }
> 
> #define TDX_KVM_SEAMCALL(_kvm, _seamcall_func, _fn, _args)	\
> 	({				\
> 		u64 _ret = _seamcall_func(_fn, _args);
> 		KVM_BUG_ON(_kvm, is_seamcall_err_kernel_defined(_ret));
> 		_ret;
> 	})

As we can move out KVM_BUG_ON() to the call site, we can simply have
seamcall() or seamcall_ret().
The call site has to check error. whether it is TDX_SW_ERROR or not.
And if it hit the unexpected error, it will mark the guest bugged.


> #define tdx_kvm_seamcall(_kvm, _fn, _args)	\
> 	TDX_KVM_SEAMCALL(_kvm, seamcall, _fn, _args)
> 
> #define tdx_kvm_seamcall_ret(_kvm, _fn, _args)	\
> 	TDX_KVM_SEAMCALL(_kvm, seamcall_ret, _fn, _args)
> 
> #define tdx_kvm_seamcall_saved_ret(_kvm, _fn, _args)	\
> 	TDX_KVM_SEAMCALL(_kvm, seamcall_saved_ret, _fn, _args)
> 
> This is consistent with what we have in TDX host code, and this handles
> NO_ENTROPY error internally.
> 
> Or, maybe we can just use the seamcall_ret() for ALL SEAMCALLs, except using
> seamcall_saved_ret() for TDH.VP.ENTER.
> 
> u64 tdx_kvm_seamcall(sruct kvm*kvm, u64 fn,
> 			struct tdx_module_args *args)
> {
> 	u64 ret = seamcall_ret(fn, args);
> 
> 	KVM_BUG_ON(kvm, is_seamcall_err_kernel_defined(ret);
> 
> 	return ret;
> }
> 
> IIUC this at least should give us a single tdx_kvm_seamcall() API for
> majority (99%) code sites?

We can eleiminate tdx_kvm_seamcall() and use seamcall() or seamcall_ret()
directly.


> And obviously I'd like other people to weigh in too.
> 
> > Because only TDH.MNG.CREATE() and TDH.MNG.ADDCX() can return TDX_RND_NO_ENTROPY, > we can use __seamcall().  The TDX spec doesn't guarantee such error code
> > convention.  It's very unlikely, though.
> 
> I don't quite follow the "convention" part.  Can you elaborate?
> 
> NO_ENTROPY is already handled in seamcall() variants.  Can we just use them
> directly?

I intended for bad code generation.  If the loop on NO_ENTRY error harms the
code generation, we might be able to use __seamcall() or __seamcall_ret()
instead of seamcall(), seamcall_ret().
-- 
Isaku Yamahata <isaku.yamahata@xxxxxxxxx>




[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]

  Powered by Linux