From: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
To: Thomas Gleixner <tglx@linutronix.de>,
Ingo Molnar <mingo@redhat.com>, Borislav Petkov <bp@alien8.de>,
x86@kernel.org, "H . Peter Anvin" <hpa@zytor.com>
Cc: Dave Hansen <dave.hansen@intel.com>,
Tony Luck <tony.luck@intel.com>,
Dan Williams <dan.j.williams@intel.com>,
Andi Kleen <ak@linux.intel.com>,
Kirill Shutemov <kirill.shutemov@linux.intel.com>,
Sean Christopherson <seanjc@google.com>,
Kuppuswamy Sathyanarayanan <knsathya@kernel.org>,
linux-kernel@vger.kernel.org
Subject: [PATCH v6 04/10] x86/tdx: Handle early IO operations
Date: Wed, 22 Sep 2021 15:52:33 -0700 [thread overview]
Message-ID: <20210922225239.3501262-5-sathyanarayanan.kuppuswamy@linux.intel.com> (raw)
In-Reply-To: <20210922225239.3501262-1-sathyanarayanan.kuppuswamy@linux.intel.com>
From: Andi Kleen <ak@linux.intel.com>
Add an early #VE handler to convert early port IOs into TDCALLs.
TDX cannot do port IO directly. The TDX module triggers a #VE exception
to let the guest kernel to emulate port I/O, by converting them into
TDCALLs to call the host.
To support port IO in early boot code, add a minimal support in early
exception handlers. This is similar to what AMD SEV does. This is
mainly to support early_printk's serial driver, as well as potentially
the VGA driver (although it is expected not to be used).
The early handler only does IO calls and nothing else, and anything
that goes wrong results in a normal early exception panic.
It cannot share the code paths with the normal #VE handler because it
needs to avoid using trace calls or printk.
This early handler allows us to use the normal in*/out* macros without
patching them for every driver. Since, there is no expectation that
early port IO is performance critical, the #VE emulation cost is worth
the simplicity benefit of not patching out port IO usage in early code.
There are also no concerns with nesting, since there should be no NMIs
this early.
Signed-off-by: Andi Kleen <ak@linux.intel.com>
Reviewed-by: Dan Williams <dan.j.williams@intel.com>
Reviewed-by: Andi Kleen <ak@linux.intel.com>
Signed-off-by: Kuppuswamy Sathyanarayanan <sathyanarayanan.kuppuswamy@linux.intel.com>
---
Changes since v5:
* None
Changes since v4:
* Changed order of variable declaration in tdx_early_io()
Changes since v3:
* None
Changes since v2:
* None
Changes since v1:
* Renamed tdx_early_io() to tdg_early_io().
arch/x86/include/asm/tdx.h | 4 +++
arch/x86/kernel/head64.c | 3 ++
arch/x86/kernel/tdx.c | 60 ++++++++++++++++++++++++++++++++++++++
3 files changed, 67 insertions(+)
diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h
index b35ebb3c54f0..eedacf8ede3d 100644
--- a/arch/x86/include/asm/tdx.h
+++ b/arch/x86/include/asm/tdx.h
@@ -73,6 +73,8 @@ unsigned long tdx_get_ve_info(struct ve_info *ve);
int tdx_handle_virtualization_exception(struct pt_regs *regs,
struct ve_info *ve);
+bool tdx_early_handle_ve(struct pt_regs *regs);
+
/*
* To support I/O port access in decompressor or early kernel init
* code, since #VE exception handler cannot be used, use paravirt
@@ -135,6 +137,8 @@ do { \
static inline void tdx_early_init(void) { };
+static inline bool tdx_early_handle_ve(struct pt_regs *regs) { return false; }
+
#endif /* CONFIG_INTEL_TDX_GUEST */
#if defined(CONFIG_KVM_GUEST) && defined(CONFIG_INTEL_TDX_GUEST)
diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
index 10c2568d7c42..f1e09ecbc1b5 100644
--- a/arch/x86/kernel/head64.c
+++ b/arch/x86/kernel/head64.c
@@ -410,6 +410,9 @@ void __init do_early_exception(struct pt_regs *regs, int trapnr)
trapnr == X86_TRAP_VC && handle_vc_boot_ghcb(regs))
return;
+ if (trapnr == X86_TRAP_VE && tdx_early_handle_ve(regs))
+ return;
+
early_fixup_exception(regs, trapnr);
}
diff --git a/arch/x86/kernel/tdx.c b/arch/x86/kernel/tdx.c
index 45dbd8863ec0..b3515f789f64 100644
--- a/arch/x86/kernel/tdx.c
+++ b/arch/x86/kernel/tdx.c
@@ -10,6 +10,11 @@
/* TDX Module call Leaf IDs */
#define TDGETVEINFO 3
+#define VE_IS_IO_OUT(exit_qual) (((exit_qual) & 8) ? 0 : 1)
+#define VE_GET_IO_SIZE(exit_qual) (((exit_qual) & 7) + 1)
+#define VE_GET_PORT_NUM(exit_qual) ((exit_qual) >> 16)
+#define VE_IS_IO_STRING(exit_qual) ((exit_qual) & 16 ? 1 : 0)
+
/*
* Wrapper for standard use of __tdx_hypercall with BUG_ON() check
* for TDCALL error.
@@ -233,6 +238,61 @@ int tdx_handle_virtualization_exception(struct pt_regs *regs,
return ret;
}
+/*
+ * Handle early IO, mainly for early printks serial output.
+ * This avoids anything that doesn't work early on, like tracing
+ * or printks, by calling the low level functions directly. Any
+ * problems are handled by falling back to a standard early exception.
+ *
+ * Assumes the IO instruction was using ax, which is enforced
+ * by the standard io.h macros.
+ */
+static __init bool tdx_early_io(struct pt_regs *regs, u32 exit_qual)
+{
+ struct tdx_hypercall_output outh;
+ int out, size, port, ret;
+ bool string;
+ u64 mask;
+
+ string = VE_IS_IO_STRING(exit_qual);
+
+ /* I/O strings ops are unrolled at build time. */
+ if (string)
+ return 0;
+
+ out = VE_IS_IO_OUT(exit_qual);
+ size = VE_GET_IO_SIZE(exit_qual);
+ port = VE_GET_PORT_NUM(exit_qual);
+ mask = GENMASK(8 * size, 0);
+
+ ret = _tdx_hypercall(EXIT_REASON_IO_INSTRUCTION, size, out, port,
+ regs->ax, &outh);
+ if (!out && !ret) {
+ regs->ax &= ~mask;
+ regs->ax |= outh.r11 & mask;
+ }
+
+ return !ret;
+}
+
+/*
+ * Early #VE exception handler. Just used to handle port IOs
+ * for early_printk. If anything goes wrong handle it like
+ * a normal early exception.
+ */
+__init bool tdx_early_handle_ve(struct pt_regs *regs)
+{
+ struct ve_info ve;
+
+ if (tdx_get_ve_info(&ve))
+ return false;
+
+ if (ve.exit_reason == EXIT_REASON_IO_INSTRUCTION)
+ return tdx_early_io(regs, ve.exit_qual);
+
+ return false;
+}
+
void __init tdx_early_init(void)
{
if (!cpuid_has_tdx_guest())
--
2.25.1
next prev parent reply other threads:[~2021-09-22 22:55 UTC|newest]
Thread overview: 15+ messages / expand[flat|nested] mbox.gz Atom feed top
2021-09-22 22:52 [PATCH v6 00/10] Add TDX Guest Support (#VE handler support) Kuppuswamy Sathyanarayanan
2021-09-22 22:52 ` [PATCH v6 01/10] x86/io: Allow to override inX() and outX() implementation Kuppuswamy Sathyanarayanan
2021-09-22 22:52 ` [PATCH v6 02/10] x86/tdx: Add early_is_tdx_guest() interface Kuppuswamy Sathyanarayanan
2021-09-22 22:52 ` [PATCH v6 03/10] x86/tdx: Handle port I/O in decompression code Kuppuswamy Sathyanarayanan
2021-09-22 22:52 ` Kuppuswamy Sathyanarayanan [this message]
2021-09-22 22:52 ` [PATCH v6 05/10] x86/tdx: Handle port I/O Kuppuswamy Sathyanarayanan
2021-09-23 16:32 ` Tom Lendacky
2021-09-23 17:24 ` Kuppuswamy, Sathyanarayanan
2021-09-23 17:59 ` Tom Lendacky
2021-10-15 0:45 ` Sean Christopherson
2021-09-22 22:52 ` [PATCH v6 06/10] x86/insn-eval: Introduce insn_get_modrm_reg_ptr() Kuppuswamy Sathyanarayanan
2021-09-22 22:52 ` [PATCH v6 07/10] x86/insn-eval: Introduce insn_decode_mmio() Kuppuswamy Sathyanarayanan
2021-09-22 22:52 ` [PATCH v6 08/10] x86/sev-es: Use insn_decode_mmio() for MMIO implementation Kuppuswamy Sathyanarayanan
2021-09-22 22:52 ` [PATCH v6 09/10] x86/tdx: Handle in-kernel MMIO Kuppuswamy Sathyanarayanan
2021-09-22 22:52 ` [PATCH v6 10/10] x86/tdx: Handle MWAIT and MONITOR Kuppuswamy Sathyanarayanan
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=20210922225239.3501262-5-sathyanarayanan.kuppuswamy@linux.intel.com \
--to=sathyanarayanan.kuppuswamy@linux.intel.com \
--cc=ak@linux.intel.com \
--cc=bp@alien8.de \
--cc=dan.j.williams@intel.com \
--cc=dave.hansen@intel.com \
--cc=hpa@zytor.com \
--cc=kirill.shutemov@linux.intel.com \
--cc=knsathya@kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=mingo@redhat.com \
--cc=seanjc@google.com \
--cc=tglx@linutronix.de \
--cc=tony.luck@intel.com \
--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
all inboxes | Powered by JetHome®