On Monday, May 29, 2023 12:19 PM, isaku.yamahata@xxxxxxxxx wrote: > From: Isaku Yamahata <isaku.yamahata@xxxxxxxxx> > > A VMM interacts with the TDX module using a new instruction (SEAMCALL). > For instance, a TDX VMM does not have full access to the VM control > structure corresponding to VMX VMCS. Instead, a VMM induces the TDX > module to act on behalf via SEAMCALLs. > > Export __seamcall and define C wrapper functions for SEAMCALLs for > readability. > > Some SEAMCALL APIs donate host pages to TDX module or guest TD, and the > donated pages are encrypted. Such SEAMCALLs flush cache lines (typically by > movdir64b instruction), but some don't. Those that don't clear cache lines > require the VMM to flush the cache lines to avoid cache line alias. > > Signed-off-by: Sean Christopherson <sean.j.christopherson@xxxxxxxxx> > Signed-off-by: Isaku Yamahata <isaku.yamahata@xxxxxxxxx> > --- > arch/x86/include/asm/tdx.h | 4 + > arch/x86/kvm/vmx/tdx_ops.h | 202 > +++++++++++++++++++++++++++++++ > arch/x86/virt/vmx/tdx/seamcall.S | 2 + > arch/x86/virt/vmx/tdx/tdx.h | 3 - > 4 files changed, 208 insertions(+), 3 deletions(-) create mode 100644 > arch/x86/kvm/vmx/tdx_ops.h > > diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h index > 112a5b9bd5cd..6c01ab572c1f 100644 > --- a/arch/x86/include/asm/tdx.h > +++ b/arch/x86/include/asm/tdx.h > @@ -104,10 +104,14 @@ static inline long tdx_kvm_hypercall(unsigned int > nr, unsigned long p1, bool platform_tdx_enabled(void); int > tdx_cpu_enable(void); int tdx_enable(void); > +u64 __seamcall(u64 op, u64 rcx, u64 rdx, u64 r8, u64 r9, > + struct tdx_module_output *out); > #else /* !CONFIG_INTEL_TDX_HOST */ > static inline bool platform_tdx_enabled(void) { return false; } static inline int > tdx_cpu_enable(void) { return -EINVAL; } static inline int tdx_enable(void) > { return -EINVAL; } > +static inline u64 __seamcall(u64 op, u64 rcx, u64 rdx, u64 r8, u64 r9, > + struct tdx_module_output *out) { return > TDX_SEAMCALL_UD; }; > #endif /* CONFIG_INTEL_TDX_HOST */ > > #endif /* !__ASSEMBLY__ */ > diff --git a/arch/x86/kvm/vmx/tdx_ops.h b/arch/x86/kvm/vmx/tdx_ops.h > new file mode 100644 index 000000000000..893cc6c25f3b > --- /dev/null > +++ b/arch/x86/kvm/vmx/tdx_ops.h > @@ -0,0 +1,202 @@ > +/* SPDX-License-Identifier: GPL-2.0 */ > +/* constants/data definitions for TDX SEAMCALLs */ > + > +#ifndef __KVM_X86_TDX_OPS_H > +#define __KVM_X86_TDX_OPS_H > + > +#include <linux/compiler.h> > + > +#include <asm/cacheflush.h> > +#include <asm/asm.h> > +#include <asm/kvm_host.h> > + > +#include "tdx_errno.h" > +#include "tdx_arch.h" > +#include "x86.h" > + > +static inline u64 kvm_seamcall(u64 op, u64 rcx, u64 rdx, u64 r8, u64 r9, > + struct tdx_module_output *out) { > + u64 ret; > + > + ret = __seamcall(op, rcx, rdx, r8, r9, out); > + if (unlikely(ret == TDX_SEAMCALL_UD)) { > + /* > + * TDX requires VMXON or #UD. In the case of reboot or > kexec, > + * VMX is made off (VMXOFF) by kvm reboot notifier, > + * kvm_reboot(), while TDs are still running. The callers > check > + * the returned error and complain. Suppress it by returning 0. > + */ Curious how do the callers check the returned error when " Suppress it by returning 0" here. > + kvm_spurious_fault(); > + return 0; > + } > + return ret; > +}