From: Kiryl Shutsemau <kas@kernel.org>
To: "Verma, Vishal L" <vishal.l.verma@intel.com>
Cc: "rdunlap@infradead.org" <rdunlap@infradead.org>,
"corbet@lwn.net" <corbet@lwn.net>,
"Edgecombe, Rick P" <rick.p.edgecombe@intel.com>,
"dave.hansen@linux.intel.com" <dave.hansen@linux.intel.com>,
"x86@kernel.org" <x86@kernel.org>,
"linux-kernel@vger.kernel.org" <linux-kernel@vger.kernel.org>,
"linux-doc@vger.kernel.org" <linux-doc@vger.kernel.org>,
"skhan@linuxfoundation.org" <skhan@linuxfoundation.org>,
"linux-coco@lists.linux.dev" <linux-coco@lists.linux.dev>,
"kvm@vger.kernel.org" <kvm@vger.kernel.org>
Subject: Re: [PATCH v3 2/2] x86/early_printk: Add earlyprintk=tdx to drive the UART with TDVMCALLs
Date: Fri, 2 Oct 2026 15:59:16 +0100 [thread overview]
Message-ID: <ar_GLgzxdWUdXn0Z@thinkstation> (raw)
In-Reply-To: <c41ffc542bd677b71bcecbe4e2c2e2a3b605ffcf.camel@intel.com>
On Mon, Sep 28, 2026 at 11:07:52PM +0000, Verma, Vishal L wrote:
> On Fri, 2026-09-25 at 12:30 +0100, Kiryl Shutsemau wrote:
>
> >
> > All these #ifdefs in early_printk.c can go. X86_FEATURE_TDX_GUEST is a
> > disabled feature without CONFIG_INTEL_TDX_GUEST, so
> > cpu_feature_enabled() folds to zero and the compiler drops the
> > static_call_update() calls and the wrappers with them.
> >
> > Add stubs for tdx_inb() and tdx_outb() to the #else branch in
> > <asm/tdx.h> and make the "tdx" case unconditional.
>
> Tried this - it causes an objtool error:
>
> CC arch/x86/kernel/early_printk.o
> arch/x86/kernel/early_printk.o: error: objtool: bad .discard.annotate_insn entry: 4 of type 1
> make: *** [Makefile:248: __sub-make] Error 2
>
> It can be fixed by adding a __used annotation to the wrappers, but is that
> ok?
>
ANNOTATE_NOENDBR_SYM() is a top-level asm() that references the symbol.
Once the compiler drops the wrapper, the annotation points at an
undefined symbol and objtool flags it.
__used makes it go away by keeping the dead wrappers in every non-TDX
kernel, which is the opposite of what dropping the #ifdefs was for.
Drop the wrappers instead.
Let tdx.c provide the accessors with the serial_in/serial_out signature,
__noendbr and annotated there, and declare them outside the #ifdef. No
stubs are needed: the only reference is under cpu_feature_enabled(),
which folds to zero without CONFIG_INTEL_TDX_GUEST.
Builds with TDX on and off.
diff --git a/arch/x86/coco/tdx/tdx.c b/arch/x86/coco/tdx/tdx.c
index d8887a2a524b..c5e16ea3844d 100644
--- a/arch/x86/coco/tdx/tdx.c
+++ b/arch/x86/coco/tdx/tdx.c
@@ -194,23 +194,19 @@ u64 tdx_hcall_get_quote(u8 *buf, size_t size)
}
EXPORT_SYMBOL_GPL(tdx_hcall_get_quote);
-/**
- * tdx_inb() - Read a byte from an I/O port without a #VE
- * @port: I/O port to read from
- *
- * Ask the VMM to perform the read with TDG.VP.VMCALL<Instruction.IO>, rather
- * than executing an IN instruction and having the resulting #VE emulate it.
- *
- * Return: the byte read, or 0xFF if the hypercall failed.
+/*
+ * early_printk accessors for a TDX guest. Ask the VMM to do the port I/O with
+ * TDG.VP.VMCALL<Instruction.IO> instead of executing IN/OUT and having the
+ * resulting #VE emulate it.
*/
-u8 tdx_inb(u16 port)
+__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,
.r13 = TDVMCALL_PORT_READ,
- .r14 = port,
+ .r14 = addr + offset,
};
if (__tdx_hypercall(&args))
@@ -218,20 +214,14 @@ u8 tdx_inb(u16 port)
return args.r11;
}
+ANNOTATE_NOENDBR_SYM(tdx_serial_in);
-/**
- * tdx_outb() - Write a byte to an I/O port without a #VE
- * @value: byte to write
- * @port: I/O port to write to
- *
- * Ask the VMM to perform the write with TDG.VP.VMCALL<Instruction.IO>, rather
- * than executing an OUT instruction and having the resulting #VE emulate it.
- */
-void tdx_outb(u8 value, u16 port)
+__noendbr void tdx_serial_out(unsigned long addr, int offset, int value)
{
_tdx_hypercall(hcall_func(EXIT_REASON_IO_INSTRUCTION), 1,
- TDVMCALL_PORT_WRITE, port, value);
+ TDVMCALL_PORT_WRITE, addr + offset, value);
}
+ANNOTATE_NOENDBR_SYM(tdx_serial_out);
static void __noreturn tdx_panic(const char *msg)
{
diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h
index 325dd7c5929f..0bbabcf0791e 100644
--- a/arch/x86/include/asm/tdx.h
+++ b/arch/x86/include/asm/tdx.h
@@ -83,9 +83,6 @@ int tdx_mcall_extend_rtmr(u8 index, u8 *data);
u64 tdx_hcall_get_quote(u8 *buf, size_t size);
-u8 tdx_inb(u16 port);
-void tdx_outb(u8 value, u16 port);
-
void __init tdx_dump_attributes(u64 td_attr);
void __init tdx_dump_td_ctls(u64 td_ctls);
@@ -98,6 +95,10 @@ static inline bool tdx_early_handle_ve(struct pt_regs *regs) { return false; }
#endif /* CONFIG_INTEL_TDX_GUEST */
+/* Only referenced when X86_FEATURE_TDX_GUEST is enabled, no stubs needed */
+unsigned int tdx_serial_in(unsigned long addr, int offset);
+void tdx_serial_out(unsigned long addr, int offset, int value);
+
#if defined(CONFIG_KVM_GUEST) && defined(CONFIG_INTEL_TDX_GUEST)
long tdx_kvm_hypercall(unsigned int nr, unsigned long p1, unsigned long p2,
unsigned long p3, unsigned long p4);
diff --git a/arch/x86/kernel/early_printk.c b/arch/x86/kernel/early_printk.c
index 194737a3e9a0..04dadcd73b85 100644
--- a/arch/x86/kernel/early_printk.c
+++ b/arch/x86/kernel/early_printk.c
@@ -112,23 +112,6 @@ 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)
-{
- return tdx_inb(addr + offset);
-}
-ANNOTATE_NOENDBR_SYM(tdx_serial_in);
-
-static __noendbr void tdx_serial_out(unsigned long addr, int offset, int value)
-{
- tdx_outb(value, addr + offset);
-}
-ANNOTATE_NOENDBR_SYM(tdx_serial_out);
-#endif /* CONFIG_INTEL_TDX_GUEST */
-
static int early_serial_putc(unsigned char ch)
{
unsigned timeout = 0xffff;
@@ -214,7 +197,6 @@ static __init void early_serial_init(char *s)
early_serial_hw_init(divisor);
}
-#ifdef CONFIG_INTEL_TDX_GUEST
/*
* Use early_serial_base (COM1) and same default baud rate as
* "earlyprintk=serial"
@@ -228,7 +210,6 @@ static __init void early_serial_tdx_init(void)
early_serial_hw_init(115200 / DEFAULT_BAUD);
}
-#endif /* CONFIG_INTEL_TDX_GUEST */
static __noendbr void mem32_serial_out(unsigned long addr, int offset, int value)
{
@@ -448,13 +429,11 @@ static int __init setup_early_printk(char *buf)
early_serial_init(buf + 4);
early_console_register(&early_serial_console, keep);
}
-#ifdef CONFIG_INTEL_TDX_GUEST
if (!strncmp(buf, "tdx", 3)) {
early_serial_tdx_init();
early_console_register(&early_serial_console, keep);
break;
}
-#endif
#ifdef CONFIG_PCI
if (!strncmp(buf, "pciserial", 9)) {
buf += 9; /* Keep from match the above "pciserial" */
--
Kiryl Shutsemau / Kirill A. Shutemov
next prev parent reply other threads:[~2026-10-02 14:59 UTC|newest]
Thread overview: 8+ messages / expand[flat|nested] mbox.gz Atom feed top
2026-09-22 20:20 [PATCH v3 0/2] x86/tdx: Use TDVMCALLs directly for earlyprintk Vishal Verma
2026-09-22 20:20 ` [PATCH v3 1/2] x86/tdx: Move port I/O definitions to a shared header Vishal Verma
2026-09-22 20:20 ` [PATCH v3 2/2] x86/early_printk: Add earlyprintk=tdx to drive the UART with TDVMCALLs Vishal Verma
2026-09-25 11:30 ` Kiryl Shutsemau
2026-09-28 23:07 ` Verma, Vishal L
2026-10-02 14:59 ` Kiryl Shutsemau [this message]
2026-10-02 19:31 ` Verma, Vishal L
2026-10-03 23:34 ` Kiryl Shutsemau
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=ar_GLgzxdWUdXn0Z@thinkstation \
--to=kas@kernel.org \
--cc=corbet@lwn.net \
--cc=dave.hansen@linux.intel.com \
--cc=kvm@vger.kernel.org \
--cc=linux-coco@lists.linux.dev \
--cc=linux-doc@vger.kernel.org \
--cc=linux-kernel@vger.kernel.org \
--cc=rdunlap@infradead.org \
--cc=rick.p.edgecombe@intel.com \
--cc=skhan@linuxfoundation.org \
--cc=vishal.l.verma@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 an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.