Received: by 2002:a05:6a11:4021:0:0:0:0 with SMTP id ky33csp59662pxb; Wed, 22 Sep 2021 15:57:11 -0700 (PDT) X-Google-Smtp-Source: ABdhPJyzrq0NhZ4NEdw6BjFILpt3xNJrqrtNuMtCPC326U8A5cbo2ItM/80OyCB3i1eSHf8TFfMG X-Received: by 2002:a50:f145:: with SMTP id z5mr2087474edl.4.1632351431556; Wed, 22 Sep 2021 15:57:11 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1632351431; cv=none; d=google.com; s=arc-20160816; b=1DVYmoOSvZi/w14VHI/B7lf7NOkMKeesSxoovJlNpZg0TX/zsf+qAqffz1vyETdhUD 1WS5dkR7FrzD4v0IEd7K6TeFlLC9fTYZtepqzH00Er/9Q/UHky7MLiws+bd1CJ0TdHLf olDuC6+r4OhMAIk/2d0KgvWUc1BXfLUDnnOJ2aYBTK820nWuEUiu7UfeVvH0Rq2ZIiH3 S9FwV2AJz4Rd6mV5A7GusMCXiYeOQ96Crst6I2JTVNTZJeddsRPVEQDTWJMXnF9E2K83 N3ofHwINk9w9oZpoOvWNzBmPgehMjM0eLcX0SS9davndlF55Ki4LnFk9sxVaf7XB4S/s ULYQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:mime-version :references:in-reply-to:message-id:date:subject:cc:to:from; bh=KmgO3MvmjkYga7m6eDumYtiQLQMEdc4YkjHrp3/TKIw=; b=veRukv5FP4tw6UUdgU7SjEoid3bJsmxZO8Hoa2kVbFxf/taKNZat69ywl6lp0885vR KMmbEsPkMM1NN5BHzRU5DSA+dmvaKYf0zg6RAfmEuPgSS64Fz/vmf4ZINVTGXSeJEL1g QWNWPiVGqeXz4qy6lFDeUWTaA8QaPfGc0krE2FCgZZmbatU9r3aYO3sAXlHj9noMUA3I kwQUIq423755M8HXwTLIlqeMicft8XWCUYr+l8lxrSapnFcoYwR6yb+ZFDHlWZDAaWVU WQG8UAOGEz5g6ySywALeUXHfESwgtWt7V2nvlUz7RfGC5lVYLsj3xTpDI18T6pX7vLjy 1cbg== ARC-Authentication-Results: i=1; mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Return-Path: Received: from vger.kernel.org (vger.kernel.org. [23.128.96.18]) by mx.google.com with ESMTP id j30si4254995ejj.467.2021.09.22.15.56.47; Wed, 22 Sep 2021 15:57:11 -0700 (PDT) Received-SPF: pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) client-ip=23.128.96.18; Authentication-Results: mx.google.com; spf=pass (google.com: domain of linux-kernel-owner@vger.kernel.org designates 23.128.96.18 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=intel.com Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S238368AbhIVW4m (ORCPT + 99 others); Wed, 22 Sep 2021 18:56:42 -0400 Received: from mga04.intel.com ([192.55.52.120]:62858 "EHLO mga04.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S238357AbhIVW4T (ORCPT ); Wed, 22 Sep 2021 18:56:19 -0400 X-IronPort-AV: E=McAfee;i="6200,9189,10115"; a="221832433" X-IronPort-AV: E=Sophos;i="5.85,315,1624345200"; d="scan'208";a="221832433" Received: from orsmga005.jf.intel.com ([10.7.209.41]) by fmsmga104.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Sep 2021 15:54:49 -0700 X-IronPort-AV: E=Sophos;i="5.85,315,1624345200"; d="scan'208";a="653457340" Received: from mnamagi-mobl1.gar.corp.intel.com (HELO skuppusw-desk1.amr.corp.intel.com) ([10.254.34.84]) by orsmga005-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 22 Sep 2021 15:54:48 -0700 From: Kuppuswamy Sathyanarayanan To: Thomas Gleixner , Ingo Molnar , Borislav Petkov , x86@kernel.org, "H . Peter Anvin" Cc: Dave Hansen , Tony Luck , Dan Williams , Andi Kleen , Kirill Shutemov , Sean Christopherson , Kuppuswamy Sathyanarayanan , linux-kernel@vger.kernel.org Subject: [PATCH v6 03/10] x86/tdx: Handle port I/O in decompression code Date: Wed, 22 Sep 2021 15:52:32 -0700 Message-Id: <20210922225239.3501262-4-sathyanarayanan.kuppuswamy@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20210922225239.3501262-1-sathyanarayanan.kuppuswamy@linux.intel.com> References: <20210922225239.3501262-1-sathyanarayanan.kuppuswamy@linux.intel.com> MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Add support to replace IN/OUT instructions in decompression code with TDX IO hypercalls. 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 TDX hypercalls to call the host. But for the really early code in the decompressor, #VE cannot be used because the IDT needed for handling the exception is not set-up, and some other infrastructure needed by the handler is missing. So to support port IO in decompressor code, directly replace IN/OUT instructions with TDX IO hypercalls. This can be easily achieved by modifying __in/__out macros. Also, since TDX IO hypercall requires an IO size parameter, modify __in/__out macros to accept size as input parameter. Reviewed-by: Andi Kleen Reviewed-by: Dan Williams Signed-off-by: Kuppuswamy Sathyanarayanan --- Changes since v5: * None Changes since v4: * Replaced in/out with IN/OUT. * Fixed typo in commit log and comments. * Renamed tdg_* prefix with tdx_* Changes since v3: * None Changes since v2: * None Changes since v1: * Modified tdg_{in/out} to adapt to API changes of __tdx_hypercall(). * Removed !CONFIG_INTEL_TDX_GUEST comment in #if else case. arch/x86/boot/compressed/Makefile | 1 + arch/x86/boot/compressed/tdcall.S | 3 ++ arch/x86/include/asm/io.h | 9 ++--- arch/x86/include/asm/tdx.h | 60 +++++++++++++++++++++++++++++++ 4 files changed, 69 insertions(+), 4 deletions(-) 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..1bfe30ebadbe 100644 --- a/arch/x86/boot/compressed/Makefile +++ b/arch/x86/boot/compressed/Makefile @@ -99,6 +99,7 @@ endif vmlinux-objs-$(CONFIG_ACPI) += $(obj)/acpi.o vmlinux-objs-$(CONFIG_INTEL_TDX_GUEST) += $(obj)/tdx.o +vmlinux-objs-$(CONFIG_INTEL_TDX_GUEST) += $(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/include/asm/io.h b/arch/x86/include/asm/io.h index 3647a96238a9..fa6aa43e5dc3 100644 --- a/arch/x86/include/asm/io.h +++ b/arch/x86/include/asm/io.h @@ -41,6 +41,7 @@ #include #include #include +#include #include #include @@ -272,25 +273,25 @@ static inline bool sev_key_active(void) { return false; } #endif /* CONFIG_AMD_MEM_ENCRYPT */ #ifndef __out -#define __out(bwl, bw) \ +#define __out(bwl, bw, sz) \ asm volatile("out" #bwl " %" #bw "0, %w1" : : "a"(value), "Nd"(port)) #endif #ifndef __in -#define __in(bwl, bw) \ +#define __in(bwl, bw, sz) \ asm volatile("in" #bwl " %w1, %" #bw "0" : "=a"(value) : "Nd"(port)) #endif #define BUILDIO(bwl, bw, type) \ static inline void out##bwl(unsigned type value, int port) \ { \ - __out(bwl, bw); \ + __out(bwl, bw, sizeof(type)); \ } \ \ static inline unsigned type in##bwl(int port) \ { \ unsigned type value; \ - __in(bwl, bw); \ + __in(bwl, bw, sizeof(type)); \ return value; \ } \ \ diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h index d47fec42df11..b35ebb3c54f0 100644 --- a/arch/x86/include/asm/tdx.h +++ b/arch/x86/include/asm/tdx.h @@ -5,6 +5,8 @@ #include #include +#include +#include #define TDX_CPUID_LEAF_ID 0x21 #define TDX_HYPERCALL_STANDARD 0 @@ -71,6 +73,64 @@ unsigned long tdx_get_ve_info(struct ve_info *ve); int tdx_handle_virtualization_exception(struct pt_regs *regs, struct ve_info *ve); +/* + * To support I/O port access in decompressor or early kernel init + * code, since #VE exception handler cannot be used, use paravirt + * model to implement __in/__out macros which will in turn be used + * by in{b,w,l}()/out{b,w,l} I/O helper macros used in kernel. Details + * about __in/__out macro usage can be found in arch/x86/include/asm/io.h + */ +#ifdef BOOT_COMPRESSED_MISC_H + +bool early_is_tdx_guest(void); + +/* + * Helper function used for making hypercall for "in" + * instruction. It will be called from __in IO macro + * If IO is failed, it will return all 1s. + */ +static inline unsigned int tdx_io_in(int size, int port) +{ + struct tdx_hypercall_output out = {0}; + + __tdx_hypercall(TDX_HYPERCALL_STANDARD, EXIT_REASON_IO_INSTRUCTION, + size, 0, port, 0, &out); + + return out.r10 ? UINT_MAX : out.r11; +} + +/* + * Helper function used for making hypercall for "out" + * instruction. It will be called from __out IO macro + */ +static inline void tdx_io_out(int size, int port, u64 value) +{ + struct tdx_hypercall_output out = {0}; + + __tdx_hypercall(TDX_HYPERCALL_STANDARD, EXIT_REASON_IO_INSTRUCTION, + size, 1, port, value, &out); +} + +#define __out(bwl, bw, sz) \ +do { \ + if (early_is_tdx_guest()) { \ + tdx_io_out(sz, port, value); \ + } else { \ + asm volatile("out" #bwl " %" #bw "0, %w1" : : \ + "a"(value), "Nd"(port)); \ + } \ +} while (0) +#define __in(bwl, bw, sz) \ +do { \ + if (early_is_tdx_guest()) { \ + value = tdx_io_in(sz, port); \ + } else { \ + asm volatile("in" #bwl " %w1, %" #bw "0" : \ + "=a"(value) : "Nd"(port)); \ + } \ +} while (0) +#endif + #else static inline void tdx_early_init(void) { }; -- 2.25.1