2022-01-24 19:24:22

by Kirill A. Shutemov

[permalink] [raw]
Subject: [PATCHv2 14/29] x86/tdx: Early boot handling of port I/O

From: Andi Kleen <[email protected]>

TDX guests cannot do port I/O directly. The TDX module triggers a #VE
exception to let the guest kernel emulate port I/O, by converting them
into TDCALLs to call the host.

But before IDT handlers are set up, port I/O cannot be emulated using
normal kernel #VE handlers. To support the #VE-based emulation during
this boot window, add a minimal early #VE handler support in early
exception handlers. This is similar to what AMD SEV does. This is
mainly to support earlyprintk's serial driver, as well as potentially
the VGA driver (although it is expected not to be used).

The early handler only supports I/O-related #VE exceptions. Unhandled or
failed exceptions will be handled via early_fixup_exceptions() (like
normal exception failures).

This early handler enables the use of normal in*/out* macros without
patching them for every driver. Since there is no expectation that
early port I/O is performance-critical, the #VE emulation cost is worth
the simplicity benefit of not patching the port I/O usage in early
code. There are also no concerns with nesting, since there should be
no NMIs or interrupts this early.

Signed-off-by: Andi Kleen <[email protected]>
Reviewed-by: Dan Williams <[email protected]>
Signed-off-by: Kuppuswamy Sathyanarayanan <[email protected]>
Signed-off-by: Kirill A. Shutemov <[email protected]>
---
arch/x86/include/asm/tdx.h | 4 ++++
arch/x86/kernel/head64.c | 3 +++
arch/x86/kernel/tdx.c | 17 +++++++++++++++++
3 files changed, 24 insertions(+)

diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h
index 27eb4ab2fdd2..8013686192fd 100644
--- a/arch/x86/include/asm/tdx.h
+++ b/arch/x86/include/asm/tdx.h
@@ -53,12 +53,16 @@ bool tdx_handle_virt_exception(struct pt_regs *regs, struct ve_info *ve);

void tdx_safe_halt(void);

+bool tdx_early_handle_ve(struct pt_regs *regs);
+
#else

static inline void tdx_early_init(void) { };
static inline bool is_tdx_guest(void) { return false; }
static inline void tdx_safe_halt(void) { };

+static inline bool tdx_early_handle_ve(struct pt_regs *regs) { return false; }
+
#endif /* CONFIG_INTEL_TDX_GUEST */

#endif /* _ASM_X86_TDX_H */
diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
index 1cb6346ec3d1..76d298ddfe75 100644
--- a/arch/x86/kernel/head64.c
+++ b/arch/x86/kernel/head64.c
@@ -417,6 +417,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 e73af22a4c11..ebb29dfb3ad4 100644
--- a/arch/x86/kernel/tdx.c
+++ b/arch/x86/kernel/tdx.c
@@ -302,6 +302,23 @@ static bool tdx_handle_io(struct pt_regs *regs, u32 exit_qual)
return !ret;
}

+/*
+ * Early #VE exception handler. Only handles a subset of port I/O.
+ * Intended only for earlyprintk. If failed, return false.
+ */
+__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 false;
+
+ return tdx_handle_io(regs, ve.exit_qual);
+}
+
bool tdx_get_ve_info(struct ve_info *ve)
{
struct tdx_module_output out;
--
2.34.1


2022-02-03 00:14:28

by Thomas Gleixner

[permalink] [raw]
Subject: Re: [PATCHv2 14/29] x86/tdx: Early boot handling of port I/O

On Mon, Jan 24 2022 at 18:02, Kirill A. Shutemov wrote:
> This early handler enables the use of normal in*/out* macros without
> patching them for every driver. Since there is no expectation that
> early port I/O is performance-critical, the #VE emulation cost is worth
> the simplicity benefit of not patching the port I/O usage in early
> code. There are also no concerns with nesting, since there should be
> no NMIs or interrupts this early.
>
> Signed-off-by: Andi Kleen <[email protected]>
> Reviewed-by: Dan Williams <[email protected]>
> Signed-off-by: Kuppuswamy Sathyanarayanan <[email protected]>
> Signed-off-by: Kirill A. Shutemov <[email protected]>

Reviewed-by: Thomas Gleixner <[email protected]>

2022-02-03 06:16:45

by Borislav Petkov

[permalink] [raw]
Subject: Re: [PATCHv2 14/29] x86/tdx: Early boot handling of port I/O

On Mon, Jan 24, 2022 at 06:02:00PM +0300, Kirill A. Shutemov wrote:
> Subject: Re: [PATCHv2 14/29] x86/tdx: Early boot handling of port I/O

The condensed patch description in the subject line should start with a
uppercase letter and should be written in imperative tone:

... Handle early boot port I/O

or so.

> From: Andi Kleen <[email protected]>
>
> TDX guests cannot do port I/O directly. The TDX module triggers a #VE
> exception to let the guest kernel emulate port I/O, by converting them

s/,//

> into TDCALLs to call the host.
>
> But before IDT handlers are set up, port I/O cannot be emulated using
> normal kernel #VE handlers. To support the #VE-based emulation during
> this boot window, add a minimal early #VE handler support in early
> exception handlers. This is similar to what AMD SEV does. This is
> mainly to support earlyprintk's serial driver, as well as potentially
> the VGA driver (although it is expected not to be used).

expectations, shmexpectations...

...

> diff --git a/arch/x86/kernel/head64.c b/arch/x86/kernel/head64.c
> index 1cb6346ec3d1..76d298ddfe75 100644
> --- a/arch/x86/kernel/head64.c
> +++ b/arch/x86/kernel/head64.c
> @@ -417,6 +417,9 @@ void __init do_early_exception(struct pt_regs *regs, int trapnr)
> trapnr == X86_TRAP_VC && handle_vc_boot_ghcb(regs))
> return;
>


if (IS_ENABLED(CONFIG_INTEL_TDX_GUEST)) &&

> + if (trapnr == X86_TRAP_VE && tdx_early_handle_ve(regs))
> + return;
> +
> early_fixup_exception(regs, trapnr);

--
Regards/Gruss,
Boris.

https://people.kernel.org/tglx/notes-about-netiquette