[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20210318213053.203403-1-sathyanarayanan.kuppuswamy@linux.intel.com>
Date: Thu, 18 Mar 2021 14:30:53 -0700
From: Kuppuswamy Sathyanarayanan
<sathyanarayanan.kuppuswamy@...ux.intel.com>
To: Peter Zijlstra <peterz@...radead.org>,
Andy Lutomirski <luto@...nel.org>,
Dave Hansen <dave.hansen@...el.com>
Cc: Andi Kleen <ak@...ux.intel.com>,
Kirill Shutemov <kirill.shutemov@...ux.intel.com>,
Kuppuswamy Sathyanarayanan <knsathya@...nel.org>,
Dan Williams <dan.j.williams@...el.com>,
Raj Ashok <ashok.raj@...el.com>,
Sean Christopherson <seanjc@...gle.com>,
linux-kernel@...r.kernel.org,
Kuppuswamy Sathyanarayanan
<sathyanarayanan.kuppuswamy@...ux.intel.com>
Subject: [PATCH v1 1/1] x86/tdx: Add tdcall() and tdvmcall() helper functions
Implement common helper functions to communicate with
the TDX Module and VMM (using TDCALL instruction).
tdvmcall() function can be used to request services
from VMM.
tdcall() function can be used to communicate with the
TDX Module.
Using common helper functions makes the code more readable
and less error prone compared to distributed and use case
specific inline assembly code. Only downside in using this
approach is, it adds a few extra instructions for every
TDCALL use case when compared to distributed checks. Although
it's a bit less efficient, it's worth it to make the code more
readable.
Signed-off-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@...ux.intel.com>
---
Hi All,
As you have suggested, I have created common helper functions
for all tdcall() and tdvmcall() use cases. It uses inline
assembly and passes GPRs R8-15 and r[a-c]x registers to TDX
Module/VMM. Please take a look at it and let me know your
comments. If you agree with the design, I can re-submit the
patchset with changes related to using these new APIs. Please
let me know.
arch/x86/include/asm/tdx.h | 27 ++++++++++++++++++++
arch/x86/kernel/tdx.c | 52 ++++++++++++++++++++++++++++++++++++++
2 files changed, 79 insertions(+)
diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h
index 0b9d571b1f95..311252a90cfb 100644
--- a/arch/x86/include/asm/tdx.h
+++ b/arch/x86/include/asm/tdx.h
@@ -3,8 +3,27 @@
#ifndef _ASM_X86_TDX_H
#define _ASM_X86_TDX_H
+#include <linux/types.h>
+
#define TDX_CPUID_LEAF_ID 0x21
+#define TDVMCALL 0
+
+/* TDVMCALL R10 Input */
+#define TDVMCALL_STANDARD 0
+
+/*
+ * TDCALL instruction is newly added in TDX architecture,
+ * used by TD for requesting the host VMM to provide
+ * (untrusted) services. Supported in Binutils >= 2.36
+ */
+#define TDCALL ".byte 0x66,0x0f,0x01,0xcc"
+
+struct tdcall_regs {
+ u64 rax, rcx, rdx;
+ u64 r8, r9, r10, r11, r12, r13, r14, r15;
+};
+
#ifdef CONFIG_INTEL_TDX_GUEST
/* Common API to check TDX support in decompression and common kernel code. */
@@ -12,6 +31,10 @@ bool is_tdx_guest(void);
void __init tdx_early_init(void);
+void tdcall(u64 leafid, struct tdcall_regs *regs);
+
+void tdvmcall(u64 subid, struct tdcall_regs *regs);
+
#else // !CONFIG_INTEL_TDX_GUEST
static inline bool is_tdx_guest(void)
@@ -21,6 +44,10 @@ static inline bool is_tdx_guest(void)
static inline void tdx_early_init(void) { };
+static inline void tdcall(u64 leafid, struct tdcall_regs *regs) { };
+
+static inline void tdvmcall(u64 subid, struct tdcall_regs *regs) { };
+
#endif /* CONFIG_INTEL_TDX_GUEST */
#endif /* _ASM_X86_TDX_H */
diff --git a/arch/x86/kernel/tdx.c b/arch/x86/kernel/tdx.c
index e44e55d1e519..7ae1d25e272b 100644
--- a/arch/x86/kernel/tdx.c
+++ b/arch/x86/kernel/tdx.c
@@ -4,6 +4,58 @@
#include <asm/tdx.h>
#include <asm/cpufeature.h>
+void tdcall(u64 leafid, struct tdcall_regs *regs)
+{
+ asm volatile(
+ /* RAX = leafid (TDCALL LEAF ID) */
+ " movq %0, %%rax;"
+ /* Move regs->r[*] data to regs r[a-c]x, r8-r5 */
+ " movq 8(%1), %%rcx;"
+ " movq 16(%1), %%rdx;"
+ " movq 24(%1), %%r8;"
+ " movq 32(%1), %%r9;"
+ " movq 40(%1), %%r10;"
+ " movq 48(%1), %%r11;"
+ " movq 56(%1), %%r12;"
+ " movq 64(%1), %%r13;"
+ " movq 72(%1), %%r14;"
+ " movq 80(%1), %%r15;"
+ TDCALL ";"
+ /* Save TDCALL success/failure to regs->rax */
+ " movq %%rax, (%1);"
+ /* Save rcx and rdx contents to regs->r[c-d]x */
+ " movq %%rcx, 8(%1);"
+ " movq %%rdx, 16(%1);"
+ /* Move content of registers R8-R15 regs->r[8-15] */
+ " movq %%r8, 24(%1);"
+ " movq %%r9, 32(%1);"
+ " movq %%r10, 40(%1);"
+ " movq %%r11, 48(%1);"
+ " movq %%r12, 56(%1);"
+ " movq %%r13, 64(%1);"
+ " movq %%r14, 72(%1);"
+ " movq %%r15, 80(%1);"
+
+ :
+ : "r" (leafid), "r" (regs)
+ : "memory", "rax", "rbx", "rcx", "rdx", "r8",
+ "r9", "r10", "r11", "r12", "r13", "r14", "r15"
+ );
+
+}
+
+void tdvmcall(u64 subid, struct tdcall_regs *regs)
+{
+ /* Expose GPRs R8-R15 to VMM */
+ regs->rcx = 0xff00;
+ /* R10 = 0 (standard TDVMCALL) */
+ regs->r10 = TDVMCALL_STANDARD;
+ /* Save subid to r11 register */
+ regs->r11 = subid;
+
+ tdcall(TDVMCALL, regs);
+}
+
static inline bool cpuid_has_tdx_guest(void)
{
u32 eax, signature[3];
--
2.25.1
Powered by blists - more mailing lists