Received: by 2002:a05:6a10:d5a5:0:0:0:0 with SMTP id gn37csp4936678pxb; Tue, 5 Oct 2021 13:43:07 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxEj6X6aOmtKYDcv6gvzhRovZRwQxmjH+X1IZ0p9fKCSunrEkT3YsHT4oLxndUFe1rL3RdH X-Received: by 2002:a17:90b:1e4f:: with SMTP id pi15mr6238843pjb.231.1633466587379; Tue, 05 Oct 2021 13:43:07 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1633466587; cv=none; d=google.com; s=arc-20160816; b=VwBm1mQR/8h44JzFdlYxgqwu+u9rT5BwajyfXxCVCOnj4/4uqewGoUD2+Mbir9Xk2q LTtAeeZcxGTwlmh10j2j+fnaCRsAUJvpZTavMpABqXRpA5SlnHzWd+xEqFy8A9e+Frpo JKgjDV7I/KS1otisLeTrSXG3rbUIRJfFdJyVuFjmK2BeziIG6MBe42RgDR5aGu3kPIiW LIRG/D00TOh/VJ9nQrh8yftKmJmZZeDy+G5FxCZisJx/vn0kEaxhpbKqgA/sEDnOYMGt D1QI9ZXZOCutfBesRch5PdCR17PbD1qjOp3I38OnXltr3vd3oyQQkKlzkRjoYQYIZyyk ir8w== 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=DeA/dWMQFQW+S2rQ5sqCiJL0pALMRcBYUBM7a11oylM=; b=WhRlWU4qzdm8rrfTnGOwme+KbpSG/TOuUeEqeal06muQE5+HoSWqjpQp4K6fFebU07 oMvayg0kuz+dSOe4aaMp59sVVx7MC0/xct4c4D47JnszCeVreWzFOvHaDplXrNXMWHCq xpFf9ooFCTVRkIKzJLuNFhsxVk4EkRkW2gXCUukTHV1o6h8WcoVCAgUTKaLC0dRXHDgA wPJOS7+tYt0EmZf3h98PcpSfC50o3gkHusFJ7Yq+iXF4B0ZWibDtigbPcy4isJz2tuk4 HT47UmweJcWgEM7Jp1wQ7wEZdk9ZJLkZmJ9wXI2Mh37YNCvzEZLGKPdOVpNZy/mW2Xgr rrsA== 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 z130si1717490pgz.341.2021.10.05.13.42.54; Tue, 05 Oct 2021 13:43:07 -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 S236200AbhJEUn5 (ORCPT + 99 others); Tue, 5 Oct 2021 16:43:57 -0400 Received: from mga07.intel.com ([134.134.136.100]:11157 "EHLO mga07.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S229920AbhJEUnu (ORCPT ); Tue, 5 Oct 2021 16:43:50 -0400 X-IronPort-AV: E=McAfee;i="6200,9189,10128"; a="289354596" X-IronPort-AV: E=Sophos;i="5.85,349,1624345200"; d="scan'208";a="289354596" Received: from fmsmga008.fm.intel.com ([10.253.24.58]) by orsmga105.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Oct 2021 13:41:59 -0700 X-IronPort-AV: E=Sophos;i="5.85,349,1624345200"; d="scan'208";a="523979490" Received: from alyee-mobl.amr.corp.intel.com (HELO skuppusw-desk1.amr.corp.intel.com) ([10.254.5.222]) by fmsmga008-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 05 Oct 2021 13:41:58 -0700 From: Kuppuswamy Sathyanarayanan To: Thomas Gleixner , Ingo Molnar , Borislav Petkov , x86@kernel.org, Paolo Bonzini , David Hildenbrand , Andrea Arcangeli , Josh Poimboeuf , "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 v7 03/10] x86/tdx: Handle port I/O in decompression code Date: Tue, 5 Oct 2021 13:41:29 -0700 Message-Id: <20211005204136.1812078-4-sathyanarayanan.kuppuswamy@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20211005204136.1812078-1-sathyanarayanan.kuppuswamy@linux.intel.com> References: <20211005204136.1812078-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 v6: * None 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 ebb97e082376..02f6036ef85f 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 @@ -72,6 +74,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 #define is_tdx_guest 0ULL -- 2.25.1