[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20220120021545.7786-3-kirill.shutemov@linux.intel.com>
Date: Thu, 20 Jan 2022 05:15:44 +0300
From: "Kirill A. Shutemov" <kirill@...temov.name>
To: bp@...en8.de
Cc: aarcange@...hat.com, ak@...ux.intel.com, dan.j.williams@...el.com,
dave.hansen@...el.com, david@...hat.com, hpa@...or.com,
jgross@...e.com, jmattson@...gle.com, joro@...tes.org,
jpoimboe@...hat.com, kirill.shutemov@...ux.intel.com,
kirill@...temov.name, knsathya@...nel.org,
linux-kernel@...r.kernel.org, luto@...nel.org, mingo@...hat.com,
pbonzini@...hat.com, peterz@...radead.org,
sathyanarayanan.kuppuswamy@...ux.intel.com, sdeep@...are.com,
seanjc@...gle.com, tglx@...utronix.de, tony.luck@...el.com,
vkuznets@...hat.com, wanpengli@...cent.com, x86@...nel.org
Subject: [PATCH 3/3] x86/boot/compressed: Support TDX guest port I/O at decompression time
Port I/O instructions trigger #VE in the TDX environment. In response to
the exception, kernel emulates these instructions using hypercalls.
But during early boot, on the decompression stage, it is cumbersome to
deal with #VE. It is cleaner to go to hypercalls directly, bypassing #VE
handling.
Hook up TDX-specific port I/O helpers if booting in TDX environment.
Signed-off-by: Kirill A. Shutemov <kirill.shutemov@...ux.intel.com>
---
arch/x86/boot/compressed/Makefile | 2 +-
arch/x86/boot/compressed/tdcall.S | 3 ++
arch/x86/boot/compressed/tdx.c | 62 +++++++++++++++++++++++++++++++
3 files changed, 66 insertions(+), 1 deletion(-)
create mode 100644 arch/x86/boot/compressed/tdcall.S
diff --git a/arch/x86/boot/compressed/Makefile b/arch/x86/boot/compressed/Makefile
index 22a2a6cc2ab4..3215442d8d2d 100644
--- a/arch/x86/boot/compressed/Makefile
+++ b/arch/x86/boot/compressed/Makefile
@@ -98,7 +98,7 @@ ifdef CONFIG_X86_64
endif
vmlinux-objs-$(CONFIG_ACPI) += $(obj)/acpi.o
-vmlinux-objs-$(CONFIG_INTEL_TDX_GUEST) += $(obj)/tdx.o
+vmlinux-objs-$(CONFIG_INTEL_TDX_GUEST) += $(obj)/tdx.o $(obj)/tdcall.o
vmlinux-objs-$(CONFIG_EFI_MIXED) += $(obj)/efi_thunk_$(BITS).o
efi-obj-$(CONFIG_EFI_STUB) = $(objtree)/drivers/firmware/efi/libstub/lib.a
diff --git a/arch/x86/boot/compressed/tdcall.S b/arch/x86/boot/compressed/tdcall.S
new file mode 100644
index 000000000000..aafadc136c88
--- /dev/null
+++ b/arch/x86/boot/compressed/tdcall.S
@@ -0,0 +1,3 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+
+#include "../../kernel/tdcall.S"
diff --git a/arch/x86/boot/compressed/tdx.c b/arch/x86/boot/compressed/tdx.c
index ae8c57ea00d8..265359131b92 100644
--- a/arch/x86/boot/compressed/tdx.c
+++ b/arch/x86/boot/compressed/tdx.c
@@ -5,6 +5,11 @@
#include "../cpuflags.h"
#include "../string.h"
+#include "../io.h"
+
+#include <vdso/limits.h>
+#include <uapi/asm/vmx.h>
+#include <asm/tdx.h>
#define TDX_CPUID_LEAF_ID 0x21
#define TDX_IDENT "IntelTDX "
@@ -16,6 +21,54 @@ bool early_is_tdx_guest(void)
return tdx_guest_detected;
}
+static inline unsigned int tdx_io_in(int size, int port)
+{
+ struct tdx_hypercall_output out;
+
+ __tdx_hypercall(TDX_HYPERCALL_STANDARD, EXIT_REASON_IO_INSTRUCTION,
+ size, 0, port, 0, &out);
+
+ return out.r10 ? UINT_MAX : out.r11;
+}
+
+static inline void tdx_io_out(int size, int port, u64 value)
+{
+ struct tdx_hypercall_output out;
+
+ __tdx_hypercall(TDX_HYPERCALL_STANDARD, EXIT_REASON_IO_INSTRUCTION,
+ size, 1, port, value, &out);
+}
+
+static inline unsigned char tdx_inb(int port)
+{
+ return tdx_io_in(1, port);
+}
+
+static inline unsigned short tdx_inw(int port)
+{
+ return tdx_io_in(2, port);
+}
+
+static inline unsigned int tdx_inl(int port)
+{
+ return tdx_io_in(4, port);
+}
+
+static inline void tdx_outb(unsigned char value, int port)
+{
+ tdx_io_out(1, port, value);
+}
+
+static inline void tdx_outw(unsigned short value, int port)
+{
+ tdx_io_out(2, port, value);
+}
+
+static inline void tdx_outl(unsigned int value, int port)
+{
+ tdx_io_out(4, port, value);
+}
+
void early_tdx_detect(void)
{
u32 eax, sig[3];
@@ -27,4 +80,13 @@ void early_tdx_detect(void)
/* Cache TDX guest feature status */
tdx_guest_detected = true;
+
+ pio_ops = (struct port_io_ops) {
+ .inb = tdx_inb,
+ .inw = tdx_inw,
+ .inl = tdx_inl,
+ .outb = tdx_outb,
+ .outw = tdx_outw,
+ .outl = tdx_outl,
+ };
}
--
2.34.1
Powered by blists - more mailing lists