Lisa Wang <[email protected]> writes: > From: Erdem Aktas <[email protected]> > > Implement the tdx_mmio_write() to allow TDX VMs to request MMIO > emulation. > > Follow the Intel Guest-Hypervisor Communication Interface (GHCI) spec > to the minimum extent that a spec-abiding TDX module will pass the > request to KVM. Skip implementing the #VE handler as described in the > GHCI spec to reduce selftests dependency. > > To perform emulated I/O, VMs use the TDG.VP.VMCALL instruction to > request MMIO. > > Signed-off-by: Erdem Aktas <[email protected]> > Co-developed-by: Sagi Shahar <[email protected]> > Signed-off-by: Sagi Shahar <[email protected]> > Co-developed-by: Lisa Wang <[email protected]> > Signed-off-by: Lisa Wang <[email protected]> > --- > tools/testing/selftests/kvm/Makefile.kvm | 1 + > tools/testing/selftests/kvm/include/x86/tdx/tdx.h | 17 +++++++++++ > tools/testing/selftests/kvm/lib/x86/tdx/tdx.S | 37 > +++++++++++++++++++++++ > 3 files changed, 55 insertions(+) > > diff --git a/tools/testing/selftests/kvm/Makefile.kvm > b/tools/testing/selftests/kvm/Makefile.kvm > index 645d9aac61db..28b33ed8c2e6 100644 > --- a/tools/testing/selftests/kvm/Makefile.kvm > +++ b/tools/testing/selftests/kvm/Makefile.kvm > @@ -33,6 +33,7 @@ LIBKVM_x86 += lib/x86/tdx/tdx_util.c > LIBKVM_x86 += lib/x86/ucall.c > LIBKVM_x86 += lib/x86/vmx.c > LIBKVM_x86 += lib/x86/tdx/td_boot.S > +LIBKVM_x86 += lib/x86/tdx/tdx.S > > LIBKVM_arm64 += lib/arm64/gic.c > LIBKVM_arm64 += lib/arm64/gic_v3.c > diff --git a/tools/testing/selftests/kvm/include/x86/tdx/tdx.h > b/tools/testing/selftests/kvm/include/x86/tdx/tdx.h > new file mode 100644 > index 000000000000..6355a30bb47f > --- /dev/null > +++ b/tools/testing/selftests/kvm/include/x86/tdx/tdx.h > @@ -0,0 +1,17 @@ > +/* SPDX-License-Identifier: GPL-2.0-only */ > +#ifndef SELFTEST_KVM_TDX_TDX_H > +#define SELFTEST_KVM_TDX_TDX_H > + > +#include <linux/types.h> > + > +#define TDG_VP_VMCALL_VE_REQUEST_MMIO 48 > +#define TDVMCALL_MMIO_WRITE 1 > + > +u64 __tdcall(u64 leaf, u64 r12, u64 r13, u64 r14, u64 r15); > + > +static inline u64 tdx_mmio_write(u64 address, u32 size, u64 data_in) > +{ > + return __tdcall(TDG_VP_VMCALL_VE_REQUEST_MMIO, size, > + TDVMCALL_MMIO_WRITE, address, data_in); > +} > +#endif /* SELFTEST_KVM_TDX_TDX_H */ > diff --git a/tools/testing/selftests/kvm/lib/x86/tdx/tdx.S > b/tools/testing/selftests/kvm/lib/x86/tdx/tdx.S > new file mode 100644 > index 000000000000..dff48a3624a1 > --- /dev/null > +++ b/tools/testing/selftests/kvm/lib/x86/tdx/tdx.S > @@ -0,0 +1,37 @@ > +/* SPDX-License-Identifier: GPL-2.0-only */ > + > +.globl __tdcall > +/* > + * u64 __tdcall(u64 leaf, u64 r12, u64 r13, u64 r14, u64 r15) > + */ > +__tdcall: > + push %r12 > + push %r13 > + push %r14 > + push %r15 > + > + /* Map C ABI fast arguments to TDX GHCI payload registers */ > + /* RDI=leaf, RSI=r12, RDX=r13, RCX=r14, R8=r15 */ > + > + mov %rdi, %r11 > + mov %rsi, %r12 > + mov %rdx, %r13 > + mov %rcx, %r14 > + mov %r8, %r15 > + > + /* TDCALL boilerplate */ > + mov $0, %rax > + mov $0xFC00, %rcx /* Expose R10-R15 */ > + mov $0, %r10 > + > + /* tdcall instruction */ > + .byte 0x66, 0x0f, 0x01, 0xcc > + > + /* Extract status */ > + mov %r10, %rax > + > + pop %r15 > + pop %r14 > + pop %r13 > + pop %r12 > + ret > > -- > 2.55.0.229.g6434b31f56-goog
We've been discussing internally if there's a nicer way to write this and let it scale to other tdcall wrappers in future tests, especially when we run out of registers for passing parameters (input and output) for other tdcalls. Looks like the only way to prevent the compiler from messing up register state before the tdcall instruction is to be completely explicit about it, and to use assembly in a .S file. I miss how readable it was in v13 [1]. Sean's comments at [1] are also echoed in [2]. [1] https://lore.kernel.org/all/[email protected]/ [2] https://lore.kernel.org/all/[email protected]/ We can figure out how best to extend this when the other tests are worked on. Reviewed-by: Ackerley Tng <[email protected]>

