Linux Confidential Computing Development
 help / color / mirror / Atom feed
* [PATCH 0/2] x86/tdx: Use TDVMCALLs directly for earlyprintk
@ 2026-09-10 22:34 Vishal Verma
  2026-09-10 22:34 ` [PATCH 1/2] x86/tdx: Move port I/O definitions to a shared header Vishal Verma
                   ` (2 more replies)
  0 siblings, 3 replies; 8+ messages in thread
From: Vishal Verma @ 2026-09-10 22:34 UTC (permalink / raw)
  To: x86, Dave Hansen, Kiryl Shutsemau, Rick Edgecombe
  Cc: linux-kernel, linux-coco, kvm, Vishal Verma

Background
==========

TDX guests have early_printk support, but it is through a roundabout way
using a #VE exception as a functional mechanism, which is fragile. The
exception handler has to use TDG.VP.VEINFO.GET to find out what faulted,
and then issue the TDVMCALL. This can be simplified into a TDVMCALL from
the guest that does the I/O directly.

Patch details
=============

Patch 1 is a prep patch that moves the port I/O direction constants to
arch/x86/include/asm/shared/tdx.h.

Patch 2: early_printk.c already reaches the UART through static calls,
so a TDX guest can simply substitute accessors that issue
TDG.VP.VMCALL<Instruction.IO> directly.

Testing
=======

Measured using a TD guest by counting handle_io() calls and snapshotting
the counter at the last earlyprintk write.

  COM1 #VE count: 63160 (before patch) -> 21 (with patch)

Additionally, ran the usual suite of CI testing, which covers KVM self
tests, KVM unit tests, and Avocado KVM tests without any regressions.

This is based on v7.3-rc2.

Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
---
Vishal Verma (2):
      x86/tdx: Move port I/O definitions to a shared header
      x86/early_printk: Avoid #VE emulation for TDX guest serial output

 arch/x86/include/asm/shared/tdx.h |  4 ++++
 arch/x86/boot/compressed/tdx.c    |  4 ++--
 arch/x86/coco/tdx/tdx.c           |  8 ++-----
 arch/x86/kernel/early_printk.c    | 48 +++++++++++++++++++++++++++++++++++++++
 4 files changed, 56 insertions(+), 8 deletions(-)
---
base-commit: df2908090cda368b01ff43709f51890076c56157
change-id: 20260903-b4-tdx_earlyprintk_tdcalls-40d1b21a8ba2

Best regards,
--  
Vishal Verma <vishal.l.verma@intel.com>


^ permalink raw reply	[flat|nested] 8+ messages in thread

* [PATCH 1/2] x86/tdx: Move port I/O definitions to a shared header
  2026-09-10 22:34 [PATCH 0/2] x86/tdx: Use TDVMCALLs directly for earlyprintk Vishal Verma
@ 2026-09-10 22:34 ` Vishal Verma
  2026-09-11 10:40   ` Kiryl Shutsemau
  2026-09-10 22:34 ` [PATCH 2/2] x86/early_printk: Avoid #VE emulation for TDX guest serial output Vishal Verma
  2026-09-11  1:17 ` [PATCH 0/2] x86/tdx: Use TDVMCALLs directly for earlyprintk Edgecombe, Rick P
  2 siblings, 1 reply; 8+ messages in thread
From: Vishal Verma @ 2026-09-10 22:34 UTC (permalink / raw)
  To: x86, Dave Hansen, Kiryl Shutsemau, Rick Edgecombe
  Cc: linux-kernel, linux-coco, kvm, Vishal Verma

In preparation for switching early_printk to use direct TDVMCALLs for
I/O, factor out the PORT_READ and PORT_WRITE definitions from
arch/x86/coco/tdx/tdx.c into arch/x86/include/asm/shared/tdx.h, and
namespace them with 'TDVMCALL_'.

The decompressor also used 0/1 literals in its tdx_io_{in,out} helpers -
switch those to use the new definitions.

Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
Cc: Rick Edgecombe <rick.p.edgecombe@intel.com>
---
 arch/x86/include/asm/shared/tdx.h | 4 ++++
 arch/x86/boot/compressed/tdx.c    | 4 ++--
 arch/x86/coco/tdx/tdx.c           | 8 ++------
 3 files changed, 8 insertions(+), 8 deletions(-)

diff --git a/arch/x86/include/asm/shared/tdx.h b/arch/x86/include/asm/shared/tdx.h
index f20e91d7ac35..25429d515cc5 100644
--- a/arch/x86/include/asm/shared/tdx.h
+++ b/arch/x86/include/asm/shared/tdx.h
@@ -84,6 +84,10 @@
 #define TDVMCALL_STATUS_ALIGN_ERROR	0x8000000000000002ULL
 #define TDVMCALL_STATUS_SUBFUNC_UNSUPPORTED	0x8000000000000003ULL
 
+/* TDG.VP.VMCALL<Instruction.IO> direction, passed in R13 */
+#define TDVMCALL_PORT_READ		0
+#define TDVMCALL_PORT_WRITE		1
+
 /*
  * Bitmasks of exposed registers (with VMM).
  */
diff --git a/arch/x86/boot/compressed/tdx.c b/arch/x86/boot/compressed/tdx.c
index 8451d6a1030c..ed278bac3c93 100644
--- a/arch/x86/boot/compressed/tdx.c
+++ b/arch/x86/boot/compressed/tdx.c
@@ -22,7 +22,7 @@ static inline unsigned int tdx_io_in(int size, u16 port)
 		.r10 = TDX_HYPERCALL_STANDARD,
 		.r11 = hcall_func(EXIT_REASON_IO_INSTRUCTION),
 		.r12 = size,
-		.r13 = 0,
+		.r13 = TDVMCALL_PORT_READ,
 		.r14 = port,
 	};
 
@@ -38,7 +38,7 @@ static inline void tdx_io_out(int size, u16 port, u32 value)
 		.r10 = TDX_HYPERCALL_STANDARD,
 		.r11 = hcall_func(EXIT_REASON_IO_INSTRUCTION),
 		.r12 = size,
-		.r13 = 1,
+		.r13 = TDVMCALL_PORT_WRITE,
 		.r14 = port,
 		.r15 = value,
 	};
diff --git a/arch/x86/coco/tdx/tdx.c b/arch/x86/coco/tdx/tdx.c
index f904a636d449..7d1a93ee2534 100644
--- a/arch/x86/coco/tdx/tdx.c
+++ b/arch/x86/coco/tdx/tdx.c
@@ -24,10 +24,6 @@
 #define EPT_READ	0
 #define EPT_WRITE	1
 
-/* Port I/O direction */
-#define PORT_READ	0
-#define PORT_WRITE	1
-
 /* See Exit Qualification for I/O Instructions in VMX documentation */
 #define VE_IS_IO_IN(e)		((e) & BIT(3))
 #define VE_GET_IO_SIZE(e)	(((e) & GENMASK(2, 0)) + 1)
@@ -691,7 +687,7 @@ static bool handle_in(struct pt_regs *regs, int size, int port)
 		.r10 = TDX_HYPERCALL_STANDARD,
 		.r11 = hcall_func(EXIT_REASON_IO_INSTRUCTION),
 		.r12 = size,
-		.r13 = PORT_READ,
+		.r13 = TDVMCALL_PORT_READ,
 		.r14 = port,
 	};
 	bool success;
@@ -720,7 +716,7 @@ static bool handle_out(struct pt_regs *regs, int size, int port)
 	 * "TDG.VP.VMCALL<Instruction.IO>".
 	 */
 	return !_tdx_hypercall(hcall_func(EXIT_REASON_IO_INSTRUCTION), size,
-			       PORT_WRITE, port, regs->ax & mask);
+			       TDVMCALL_PORT_WRITE, port, regs->ax & mask);
 }
 
 /*

-- 
2.55.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* [PATCH 2/2] x86/early_printk: Avoid #VE emulation for TDX guest serial output
  2026-09-10 22:34 [PATCH 0/2] x86/tdx: Use TDVMCALLs directly for earlyprintk Vishal Verma
  2026-09-10 22:34 ` [PATCH 1/2] x86/tdx: Move port I/O definitions to a shared header Vishal Verma
@ 2026-09-10 22:34 ` Vishal Verma
       [not found]   ` <20260910224829.C1F191F000FF@smtp.kernel.org>
                     ` (2 more replies)
  2026-09-11  1:17 ` [PATCH 0/2] x86/tdx: Use TDVMCALLs directly for earlyprintk Edgecombe, Rick P
  2 siblings, 3 replies; 8+ messages in thread
From: Vishal Verma @ 2026-09-10 22:34 UTC (permalink / raw)
  To: x86, Dave Hansen, Kiryl Shutsemau, Rick Edgecombe
  Cc: linux-kernel, linux-coco, kvm, Vishal Verma

A TDX guest cannot execute port I/O instructions directly, but
earlyprintk's serial console still issues plain inb()/outb() and lets
each one fault into the #VE handler to be emulated as a TDVMCALL.

While that works, it is a roundabout way to get a character out.
early_serial_putc() polls the LSR, and then writes a byte, but since the
TDX guest can't directly do port I/O, a #VE exception is raised. The #VE
handler must call TDG.VP.VEINFO.GET to find out what faulted, and then
it can issue the TDVMCALL that does the actual work.

This makes #VE a functional mechanism for doing I/O, which is not
desirable, is unnecessarily complicated and fragile, and results in
twice the number of calls into the TDX module.

Instead, issue the TDVMCALL directly. In early_printk.c, port access is
routed through static calls so the MMIO console can substitute its own
accessors. Add a TDX pair and swap them in the same way.

Note that the output does not appear any earlier - "earlyprintk=" is an
early_param(), so the console is still registered from
parse_early_param(). This only changes how the bytes leave the guest
once it is up.

LLMs were used under supervision to create this patch, to help
understand the scope and mechanisms, create testing instrumentation
(throwaway) to count #VEs before/after the change, and to drive lab
machines to do this testing.

Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
---
 arch/x86/kernel/early_printk.c | 48 ++++++++++++++++++++++++++++++++++++++++++
 1 file changed, 48 insertions(+)

diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c
index cba75306e5b6..4a70799cd80a 100644
--- a/arch/x86/kernel/early_printk.c
+++ b/arch/x86/kernel/early_printk.c
@@ -21,6 +21,8 @@
 #include <linux/usb/xhci-dbgp.h>
 #include <asm/pci_x86.h>
 #include <linux/static_call.h>
+#include <asm/shared/tdx.h>
+#include <asm/vmx.h>
 
 /* Simple VGA output */
 #define VGABASE		(__ISA_IO_base + 0xb8000)
@@ -111,6 +113,48 @@ ANNOTATE_NOENDBR_SYM(io_serial_out);
 DEFINE_STATIC_CALL(serial_in, io_serial_in);
 DEFINE_STATIC_CALL(serial_out, io_serial_out);
 
+#ifdef CONFIG_INTEL_TDX_GUEST
+/*
+ * A TDX guest cannot execute port I/O instructions, so ask the VMM to do it.
+ */
+static __noendbr unsigned int tdx_serial_in(unsigned long addr, int offset)
+{
+	struct tdx_module_args args = {
+		.r10 = TDX_HYPERCALL_STANDARD,
+		.r11 = hcall_func(EXIT_REASON_IO_INSTRUCTION),
+		.r12 = 1,			/* One byte */
+		.r13 = TDVMCALL_PORT_READ,
+		.r14 = addr + offset,
+	};
+
+	if (__tdx_hypercall(&args))
+		return UINT_MAX;
+
+	return args.r11;
+}
+ANNOTATE_NOENDBR_SYM(tdx_serial_in);
+
+static __noendbr void tdx_serial_out(unsigned long addr, int offset, int value)
+{
+	/* One byte */
+	_tdx_hypercall(hcall_func(EXIT_REASON_IO_INSTRUCTION), 1,
+		       TDVMCALL_PORT_WRITE, addr + offset, value);
+}
+ANNOTATE_NOENDBR_SYM(tdx_serial_out);
+
+/* Substitute the hypercall accessors, but only in an actual TDX guest */
+static __init void early_serial_tdx_init(void)
+{
+	if (!cpu_feature_enabled(X86_FEATURE_TDX_GUEST))
+		return;
+
+	static_call_update(serial_in, tdx_serial_in);
+	static_call_update(serial_out, tdx_serial_out);
+}
+#else
+static inline void early_serial_tdx_init(void) { }
+#endif /* CONFIG_INTEL_TDX_GUEST */
+
 static int early_serial_putc(unsigned char ch)
 {
 	unsigned timeout = 0xffff;
@@ -160,6 +204,9 @@ static __init void early_serial_init(char *s)
 	unsigned long baud = DEFAULT_BAUD;
 	char *e;
 
+	/* Must be before early_serial_hw_init(), which does port I/O */
+	early_serial_tdx_init();
+
 	if (*s == ',')
 		++s;
 
@@ -323,6 +370,7 @@ static __init void early_pci_serial_init(char *s)
 	 */
 	if ((bar0 & PCI_BASE_ADDRESS_SPACE) == PCI_BASE_ADDRESS_SPACE_IO) {
 		/* it is IO mapped */
+		early_serial_tdx_init();
 		early_serial_base = bar0 & PCI_BASE_ADDRESS_IO_MASK;
 		write_pci_config(bus, slot, func, PCI_COMMAND,
 				 cmdreg|PCI_COMMAND_IO);

-- 
2.55.0


^ permalink raw reply related	[flat|nested] 8+ messages in thread

* Re: [PATCH 2/2] x86/early_printk: Avoid #VE emulation for TDX guest serial output
       [not found]   ` <20260910224829.C1F191F000FF@smtp.kernel.org>
@ 2026-09-10 23:44     ` Verma, Vishal L
  0 siblings, 0 replies; 8+ messages in thread
From: Verma, Vishal L @ 2026-09-10 23:44 UTC (permalink / raw)
  To: sashiko-reviews@lists.linux.dev
  Cc: ak@linux.intel.com, dave.hansen@linux.intel.com, x86@kernel.org,
	kas@kernel.org, linux-kernel@vger.kernel.org, Verma, Vishal L,
	kvm@vger.kernel.org, linux-coco@lists.linux.dev

On Thu, 2026-09-10 at 22:48 +0000, sashiko-bot@kernel.org wrote:
> 
> > +/* Substitute the hypercall accessors, but only in an actual TDX guest */
> > +static __init void early_serial_tdx_init(void)
> > +{
> > +	if (!cpu_feature_enabled(X86_FEATURE_TDX_GUEST))
> > +		return;
> > +
> > +	static_call_update(serial_in, tdx_serial_in);
> > +	static_call_update(serial_out, tdx_serial_out);
> 
> [Severity: Medium]
> Will calling static_call_update() here trigger a WARN_ON_ONCE during early boot?
> 
> Booting a TDX guest with earlyprintk invokes parse_early_param(), which ends
> up calling early_serial_tdx_init() before the static call infrastructure is
> fully set up. Because static_call_init() is an early_initcall that runs much
> later in the boot sequence, static_call_initialized is still 0 at this point.
> 
> This unconditionally triggers the WARN_ON_ONCE(!static_call_initialized)
> safety check in __static_call_update(), which dumps a stack trace to the
> boot log and will crash the boot process if panic_on_warn is set.
> 
> Should this use the x86-specific static_call_update_early() macro instead,
> which checks the initialization state and safely patches the trampoline
> directly during early boot?
> 
> 
This Sashiko report is a false positive - for x86's setup_arch(),
static_call_init() happens before parse_early_param().

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 0/2] x86/tdx: Use TDVMCALLs directly for earlyprintk
  2026-09-10 22:34 [PATCH 0/2] x86/tdx: Use TDVMCALLs directly for earlyprintk Vishal Verma
  2026-09-10 22:34 ` [PATCH 1/2] x86/tdx: Move port I/O definitions to a shared header Vishal Verma
  2026-09-10 22:34 ` [PATCH 2/2] x86/early_printk: Avoid #VE emulation for TDX guest serial output Vishal Verma
@ 2026-09-11  1:17 ` Edgecombe, Rick P
  2 siblings, 0 replies; 8+ messages in thread
From: Edgecombe, Rick P @ 2026-09-11  1:17 UTC (permalink / raw)
  To: Verma, Vishal L, kas@kernel.org, x86@kernel.org,
	dave.hansen@linux.intel.com
  Cc: kvm@vger.kernel.org, linux-coco@lists.linux.dev,
	linux-kernel@vger.kernel.org

On Thu, 2026-09-10 at 16:34 -0600, Vishal Verma wrote:
> Background
> ==========
> 
> TDX guests have early_printk support, but it is through a roundabout way
> using a #VE exception as a functional mechanism, which is fragile. The
> exception handler has to use TDG.VP.VEINFO.GET to find out what faulted,
> and then issue the TDVMCALL. This can be simplified into a TDVMCALL from
> the guest that does the I/O directly.

How many other port io #VE users are there? How far is this on the way to
removing them all? Is early printk an especially fragile #VE port io user?

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 1/2] x86/tdx: Move port I/O definitions to a shared header
  2026-09-10 22:34 ` [PATCH 1/2] x86/tdx: Move port I/O definitions to a shared header Vishal Verma
@ 2026-09-11 10:40   ` Kiryl Shutsemau
  0 siblings, 0 replies; 8+ messages in thread
From: Kiryl Shutsemau @ 2026-09-11 10:40 UTC (permalink / raw)
  To: Vishal Verma
  Cc: x86, Dave Hansen, Rick Edgecombe, linux-kernel, linux-coco, kvm

On Thu, Sep 10, 2026 at 04:34:08PM -0600, Vishal Verma wrote:
> In preparation for switching early_printk to use direct TDVMCALLs for
> I/O, factor out the PORT_READ and PORT_WRITE definitions from
> arch/x86/coco/tdx/tdx.c into arch/x86/include/asm/shared/tdx.h, and
> namespace them with 'TDVMCALL_'.
> 
> The decompressor also used 0/1 literals in its tdx_io_{in,out} helpers -
> switch those to use the new definitions.
> 
> Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
> Cc: Rick Edgecombe <rick.p.edgecombe@intel.com>

Nice cleanup!

Reviewed-by: Kiryl Shutsemau (Meta) <kas@kernel.org>

-- 
  Kiryl Shutsemau / Kirill A. Shutemov

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 2/2] x86/early_printk: Avoid #VE emulation for TDX guest serial output
  2026-09-10 22:34 ` [PATCH 2/2] x86/early_printk: Avoid #VE emulation for TDX guest serial output Vishal Verma
       [not found]   ` <20260910224829.C1F191F000FF@smtp.kernel.org>
@ 2026-09-11 10:49   ` Kiryl Shutsemau
  2026-09-11 20:25   ` Dave Hansen
  2 siblings, 0 replies; 8+ messages in thread
From: Kiryl Shutsemau @ 2026-09-11 10:49 UTC (permalink / raw)
  To: Vishal Verma
  Cc: x86, Dave Hansen, Rick Edgecombe, linux-kernel, linux-coco, kvm

On Thu, Sep 10, 2026 at 04:34:09PM -0600, Vishal Verma wrote:
> A TDX guest cannot execute port I/O instructions directly, but
> earlyprintk's serial console still issues plain inb()/outb() and lets
> each one fault into the #VE handler to be emulated as a TDVMCALL.
> 
> While that works, it is a roundabout way to get a character out.
> early_serial_putc() polls the LSR, and then writes a byte, but since the
> TDX guest can't directly do port I/O, a #VE exception is raised. The #VE
> handler must call TDG.VP.VEINFO.GET to find out what faulted, and then
> it can issue the TDVMCALL that does the actual work.
> 
> This makes #VE a functional mechanism for doing I/O, which is not
> desirable, is unnecessarily complicated and fragile, and results in
> twice the number of calls into the TDX module.
> 
> Instead, issue the TDVMCALL directly. In early_printk.c, port access is
> routed through static calls so the MMIO console can substitute its own
> accessors. Add a TDX pair and swap them in the same way.
> 
> Note that the output does not appear any earlier - "earlyprintk=" is an
> early_param(), so the console is still registered from
> parse_early_param(). This only changes how the bytes leave the guest
> once it is up.
> 
> LLMs were used under supervision to create this patch, to help
> understand the scope and mechanisms, create testing instrumentation
> (throwaway) to count #VEs before/after the change, and to drive lab
> machines to do this testing.
> 
> Signed-off-by: Vishal Verma <vishal.l.verma@intel.com>
> ---
>  arch/x86/kernel/early_printk.c | 48 ++++++++++++++++++++++++++++++++++++++++++
>  1 file changed, 48 insertions(+)
> 
> diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c
> index cba75306e5b6..4a70799cd80a 100644
> --- a/arch/x86/kernel/early_printk.c
> +++ b/arch/x86/kernel/early_printk.c
> @@ -21,6 +21,8 @@
>  #include <linux/usb/xhci-dbgp.h>
>  #include <asm/pci_x86.h>
>  #include <linux/static_call.h>
> +#include <asm/shared/tdx.h>
> +#include <asm/vmx.h>
>  
>  /* Simple VGA output */
>  #define VGABASE		(__ISA_IO_base + 0xb8000)
> @@ -111,6 +113,48 @@ ANNOTATE_NOENDBR_SYM(io_serial_out);
>  DEFINE_STATIC_CALL(serial_in, io_serial_in);
>  DEFINE_STATIC_CALL(serial_out, io_serial_out);
>  
> +#ifdef CONFIG_INTEL_TDX_GUEST
> +/*
> + * A TDX guest cannot execute port I/O instructions, so ask the VMM to do it.
> + */
> +static __noendbr unsigned int tdx_serial_in(unsigned long addr, int offset)
> +{
> +	struct tdx_module_args args = {
> +		.r10 = TDX_HYPERCALL_STANDARD,
> +		.r11 = hcall_func(EXIT_REASON_IO_INSTRUCTION),
> +		.r12 = 1,			/* One byte */
> +		.r13 = TDVMCALL_PORT_READ,
> +		.r14 = addr + offset,
> +	};
> +
> +	if (__tdx_hypercall(&args))
> +		return UINT_MAX;
> +
> +	return args.r11;
> +}
> +ANNOTATE_NOENDBR_SYM(tdx_serial_in);
> +
> +static __noendbr void tdx_serial_out(unsigned long addr, int offset, int value)
> +{
> +	/* One byte */
> +	_tdx_hypercall(hcall_func(EXIT_REASON_IO_INSTRUCTION), 1,
> +		       TDVMCALL_PORT_WRITE, addr + offset, value);
> +}
> +ANNOTATE_NOENDBR_SYM(tdx_serial_out);
> +
> +/* Substitute the hypercall accessors, but only in an actual TDX guest */
> +static __init void early_serial_tdx_init(void)
> +{
> +	if (!cpu_feature_enabled(X86_FEATURE_TDX_GUEST))
> +		return;
> +
> +	static_call_update(serial_in, tdx_serial_in);
> +	static_call_update(serial_out, tdx_serial_out);
> +}
> +#else
> +static inline void early_serial_tdx_init(void) { }
> +#endif /* CONFIG_INTEL_TDX_GUEST */
> +

I don't particularly like this being in early_printk.c

Maybe coco/tdx/tdx.c should provide tdx_inb() and tdx_outb() helpers
that we just hook up here?



-- 
  Kiryl Shutsemau / Kirill A. Shutemov

^ permalink raw reply	[flat|nested] 8+ messages in thread

* Re: [PATCH 2/2] x86/early_printk: Avoid #VE emulation for TDX guest serial output
  2026-09-10 22:34 ` [PATCH 2/2] x86/early_printk: Avoid #VE emulation for TDX guest serial output Vishal Verma
       [not found]   ` <20260910224829.C1F191F000FF@smtp.kernel.org>
  2026-09-11 10:49   ` Kiryl Shutsemau
@ 2026-09-11 20:25   ` Dave Hansen
  2 siblings, 0 replies; 8+ messages in thread
From: Dave Hansen @ 2026-09-11 20:25 UTC (permalink / raw)
  To: Vishal Verma, x86, Dave Hansen, Kiryl Shutsemau, Rick Edgecombe
  Cc: linux-kernel, linux-coco, kvm

On 9/10/26 15:34, Vishal Verma wrote:
> +/* Substitute the hypercall accessors, but only in an actual TDX guest */
> +static __init void early_serial_tdx_init(void)
> +{
> +	if (!cpu_feature_enabled(X86_FEATURE_TDX_GUEST))
> +		return;
> +
> +	static_call_update(serial_in, tdx_serial_in);
> +	static_call_update(serial_out, tdx_serial_out);
> +}
> +#else
> +static inline void early_serial_tdx_init(void) { }
> +#endif /* CONFIG_INTEL_TDX_GUEST */
> +
>  static int early_serial_putc(unsigned char ch)
>  {
>  	unsigned timeout = 0xffff;
> @@ -160,6 +204,9 @@ static __init void early_serial_init(char *s)
>  	unsigned long baud = DEFAULT_BAUD;
>  	char *e;
>  
> +	/* Must be before early_serial_hw_init(), which does port I/O */
> +	early_serial_tdx_init();

I really don't like the idea of putting any code in here. How about just
adding a case to setup_early_printk(). Perhaps:

#ifdef CONFIG_TDX_GUEST
	if (!strncmp(buf, "tdx", 3)) {
		early_serial_tdx_init();
		early_serial_init(buf + 3);
		early_console_register(&early_serial_console, keep);
	}
#endif

Then folks can just use earlyprintk=tdx.

^ permalink raw reply	[flat|nested] 8+ messages in thread

end of thread, other threads:[~2026-09-11 20:25 UTC | newest]

Thread overview: 8+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-10 22:34 [PATCH 0/2] x86/tdx: Use TDVMCALLs directly for earlyprintk Vishal Verma
2026-09-10 22:34 ` [PATCH 1/2] x86/tdx: Move port I/O definitions to a shared header Vishal Verma
2026-09-11 10:40   ` Kiryl Shutsemau
2026-09-10 22:34 ` [PATCH 2/2] x86/early_printk: Avoid #VE emulation for TDX guest serial output Vishal Verma
     [not found]   ` <20260910224829.C1F191F000FF@smtp.kernel.org>
2026-09-10 23:44     ` Verma, Vishal L
2026-09-11 10:49   ` Kiryl Shutsemau
2026-09-11 20:25   ` Dave Hansen
2026-09-11  1:17 ` [PATCH 0/2] x86/tdx: Use TDVMCALLs directly for earlyprintk Edgecombe, Rick P

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox