Received: by 2002:a05:6a10:206:0:0:0:0 with SMTP id 6csp1278919pxj; Wed, 19 May 2021 02:21:05 -0700 (PDT) X-Google-Smtp-Source: ABdhPJwremfJszW8OjjfHip8vC5yFDtL+brUXHxl41W1S6YxIt5RHrBm2SvHZpn8yl3AXx+DeWQt X-Received: by 2002:a5d:9343:: with SMTP id i3mr9223028ioo.77.1621416065236; Wed, 19 May 2021 02:21:05 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1621416065; cv=none; d=google.com; s=arc-20160816; b=fxWSyibKmmPWMui7rG3kl8Oi54/R5G5zKN3e9DJnSZRfk3AKHcdSqFNlNGzWpA0T4V HsyodL/T/wN5v8Z+Ln9kcRhfkIVeC9jiOyTjP/Wn5JnQ+DV1/t/lIIrz165HjSow+48c nWstZ7/QXQIpdA2URBBbZ6sbftMLZ1a0trwLBQMVr2hx+3OPu+2yI9/swfHX/0qsE4Ca E/kqFrPxDcI4h1TPT4YuZ/zcQI8pEiN9n4bbktFkvCMJ8/TUjO71utrT49Kb6qoTaUBJ mgmMQ1KNBkedDS4AaQDMs+YDGh3jEXs7zR14gtqH4CB/6lM0kdQsnn9WfuLxcHJsPxnW P0Ew== 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 :ironport-sdr:ironport-sdr; bh=MDI+wOa0n9PBHQeqWS8lC8jdnV/Bw+M69zsU8nNN538=; b=h1ArPBHsuA3y88lH7J3f8HTjPTcUU8iUrBz+dKf7RSjCdMFryg7A0UmnLBQly39JD5 nEZwU2G3MN+Y9gyk9DA1jUhTBLGRlM1+XEdg7ics7fmfz7d2OOVTPd0fjIEtDsascTcW 0oHJkV9wlbXZ0Vr/hA9SGjtSdBo1dMpYjiZlPzjdJ7/MtjUzfA9OQfBQTZEEkSDGHJD2 ujG8asyErq75RazfdP98GiX2c7tg5sDMDmTO6VRXTZSrpGVvP/vJfuoFfjdxZMGpYYCj LDE3LDVG+nlPKC1/hmGdBWbg+bHkn0+bepZLJ+AiSgxZ2IaSimcxqQvlOyQ8jMg9zCsX yaiw== 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 j188si27737589jac.58.2021.05.19.02.20.53; Wed, 19 May 2021 02:21:05 -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 S239537AbhERARk (ORCPT + 99 others); Mon, 17 May 2021 20:17:40 -0400 Received: from mga07.intel.com ([134.134.136.100]:15626 "EHLO mga07.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239680AbhERARk (ORCPT ); Mon, 17 May 2021 20:17:40 -0400 IronPort-SDR: fovHzXRuSn1JSS3xjM0vJz3QSTKTW4B7+ryiigY/eYe+acvau1dwWHNjisc+3e7+5rD0RN5zSG uAl2ewOwRuuw== X-IronPort-AV: E=McAfee;i="6200,9189,9987"; a="264507062" X-IronPort-AV: E=Sophos;i="5.82,307,1613462400"; d="scan'208";a="264507062" Received: from orsmga008.jf.intel.com ([10.7.209.65]) by orsmga105.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 May 2021 17:16:21 -0700 IronPort-SDR: zdoLRS9HnSUEbMndQrgJj5wq1bH/qcvWvg1mQB4PioV5T5k150OGeKCCiNLZT43Y3lYr7ImPD5 mzaVLWjL0doA== X-IronPort-AV: E=Sophos;i="5.82,307,1613462400"; d="scan'208";a="439170849" Received: from sdayal-mobl.amr.corp.intel.com (HELO skuppusw-desk1.amr.corp.intel.com) ([10.213.167.196]) by orsmga008-auth.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 17 May 2021 17:16:20 -0700 From: Kuppuswamy Sathyanarayanan To: Peter Zijlstra , Andy Lutomirski , Dave Hansen Cc: Tony Luck , Andi Kleen , Kirill Shutemov , Kuppuswamy Sathyanarayanan , Dan Williams , Raj Ashok , Sean Christopherson , linux-kernel@vger.kernel.org, Isaku Yamahata , Kuppuswamy Sathyanarayanan Subject: [RFC v2-fix 1/1] x86/tdx: Wire up KVM hypercalls Date: Mon, 17 May 2021 17:15:51 -0700 Message-Id: <20210518001551.258126-1-sathyanarayanan.kuppuswamy@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <2a4e9702-5407-aa95-be9b-864775bbaabd@intel.com> References: <2a4e9702-5407-aa95-be9b-864775bbaabd@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 From: "Kirill A. Shutemov" KVM hypercalls use the "vmcall" or "vmmcall" instructions. Although the ABI is similar, those instructions no longer function for TDX guests. Make vendor specififc TDVMCALLs instead of VMCALL. [Isaku: proposed KVM VENDOR string] Signed-off-by: Kirill A. Shutemov Signed-off-by: Isaku Yamahata Reviewed-by: Andi Kleen Signed-off-by: Kuppuswamy Sathyanarayanan --- Changes since RFC v2: * Introduced INTEL_TDX_GUEST_KVM config for TDX+KVM related changes. * Removed "C" include file. * Fixed commit log as per Dave's comments. arch/x86/Kconfig | 6 +++++ arch/x86/include/asm/kvm_para.h | 21 +++++++++++++++ arch/x86/include/asm/tdx.h | 41 ++++++++++++++++++++++++++++ arch/x86/kernel/Makefile | 1 + arch/x86/kernel/tdcall.S | 20 ++++++++++++++ arch/x86/kernel/tdx-kvm.c | 48 +++++++++++++++++++++++++++++++++ 6 files changed, 137 insertions(+) create mode 100644 arch/x86/kernel/tdx-kvm.c diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 9e0e0ff76bab..768df1b98487 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -886,6 +886,12 @@ config INTEL_TDX_GUEST run in a CPU mode that protects the confidentiality of TD memory contents and the TD’s CPU state from other software, including VMM. +config INTEL_TDX_GUEST_KVM + def_bool y + depends on KVM_GUEST && INTEL_TDX_GUEST + help + This option enables KVM specific hypercalls in TDX guest. + endif #HYPERVISOR_GUEST source "arch/x86/Kconfig.cpu" diff --git a/arch/x86/include/asm/kvm_para.h b/arch/x86/include/asm/kvm_para.h index 338119852512..2fa85481520b 100644 --- a/arch/x86/include/asm/kvm_para.h +++ b/arch/x86/include/asm/kvm_para.h @@ -6,6 +6,7 @@ #include #include #include +#include extern void kvmclock_init(void); @@ -34,6 +35,10 @@ static inline bool kvm_check_and_clear_guest_paused(void) static inline long kvm_hypercall0(unsigned int nr) { long ret; + + if (is_tdx_guest()) + return tdx_kvm_hypercall0(nr); + asm volatile(KVM_HYPERCALL : "=a"(ret) : "a"(nr) @@ -44,6 +49,10 @@ static inline long kvm_hypercall0(unsigned int nr) static inline long kvm_hypercall1(unsigned int nr, unsigned long p1) { long ret; + + if (is_tdx_guest()) + return tdx_kvm_hypercall1(nr, p1); + asm volatile(KVM_HYPERCALL : "=a"(ret) : "a"(nr), "b"(p1) @@ -55,6 +64,10 @@ static inline long kvm_hypercall2(unsigned int nr, unsigned long p1, unsigned long p2) { long ret; + + if (is_tdx_guest()) + return tdx_kvm_hypercall2(nr, p1, p2); + asm volatile(KVM_HYPERCALL : "=a"(ret) : "a"(nr), "b"(p1), "c"(p2) @@ -66,6 +79,10 @@ static inline long kvm_hypercall3(unsigned int nr, unsigned long p1, unsigned long p2, unsigned long p3) { long ret; + + if (is_tdx_guest()) + return tdx_kvm_hypercall3(nr, p1, p2, p3); + asm volatile(KVM_HYPERCALL : "=a"(ret) : "a"(nr), "b"(p1), "c"(p2), "d"(p3) @@ -78,6 +95,10 @@ static inline long kvm_hypercall4(unsigned int nr, unsigned long p1, unsigned long p4) { long ret; + + if (is_tdx_guest()) + return tdx_kvm_hypercall4(nr, p1, p2, p3, p4); + asm volatile(KVM_HYPERCALL : "=a"(ret) : "a"(nr), "b"(p1), "c"(p2), "d"(p3), "S"(p4) diff --git a/arch/x86/include/asm/tdx.h b/arch/x86/include/asm/tdx.h index 8ab4067afefc..eb758b506dba 100644 --- a/arch/x86/include/asm/tdx.h +++ b/arch/x86/include/asm/tdx.h @@ -73,4 +73,45 @@ static inline void tdx_early_init(void) { }; #endif /* CONFIG_INTEL_TDX_GUEST */ +#ifdef CONFIG_INTEL_TDX_GUEST_KVM +u64 __tdx_hypercall_vendor_kvm(u64 fn, u64 r12, u64 r13, u64 r14, + u64 r15, struct tdx_hypercall_output *out); +long tdx_kvm_hypercall0(unsigned int nr); +long tdx_kvm_hypercall1(unsigned int nr, unsigned long p1); +long tdx_kvm_hypercall2(unsigned int nr, unsigned long p1, unsigned long p2); +long tdx_kvm_hypercall3(unsigned int nr, unsigned long p1, unsigned long p2, + unsigned long p3); +long tdx_kvm_hypercall4(unsigned int nr, unsigned long p1, unsigned long p2, + unsigned long p3, unsigned long p4); +#else +static inline long tdx_kvm_hypercall0(unsigned int nr) +{ + return -ENODEV; +} + +static inline long tdx_kvm_hypercall1(unsigned int nr, unsigned long p1) +{ + return -ENODEV; +} + +static inline long tdx_kvm_hypercall2(unsigned int nr, unsigned long p1, + unsigned long p2) +{ + return -ENODEV; +} + +static inline long tdx_kvm_hypercall3(unsigned int nr, unsigned long p1, + unsigned long p2, unsigned long p3) +{ + return -ENODEV; +} + +static inline long tdx_kvm_hypercall4(unsigned int nr, unsigned long p1, + unsigned long p2, unsigned long p3, + unsigned long p4) +{ + return -ENODEV; +} +#endif /* CONFIG_INTEL_TDX_GUEST_KVM */ + #endif /* _ASM_X86_TDX_H */ diff --git a/arch/x86/kernel/Makefile b/arch/x86/kernel/Makefile index 7966c10ea8d1..a90fec004844 100644 --- a/arch/x86/kernel/Makefile +++ b/arch/x86/kernel/Makefile @@ -128,6 +128,7 @@ obj-$(CONFIG_X86_PMEM_LEGACY_DEVICE) += pmem.o obj-$(CONFIG_JAILHOUSE_GUEST) += jailhouse.o obj-$(CONFIG_INTEL_TDX_GUEST) += tdcall.o tdx.o +obj-$(CONFIG_INTEL_TDX_GUEST_KVM) += tdx-kvm.o obj-$(CONFIG_EISA) += eisa.o obj-$(CONFIG_PCSPKR_PLATFORM) += pcspeaker.o diff --git a/arch/x86/kernel/tdcall.S b/arch/x86/kernel/tdcall.S index a484c4aef6e6..3c57a1d67b79 100644 --- a/arch/x86/kernel/tdcall.S +++ b/arch/x86/kernel/tdcall.S @@ -25,6 +25,8 @@ TDG_R12 | TDG_R13 | \ TDG_R14 | TDG_R15 ) +#define TDVMCALL_VENDOR_KVM 0x4d564b2e584454 /* "TDX.KVM" */ + /* * TDX guests use the TDCALL instruction to make requests to the * TDX module and hypercalls to the VMM. It is supported in @@ -213,3 +215,21 @@ SYM_FUNC_START(__tdx_hypercall) call do_tdx_hypercall retq SYM_FUNC_END(__tdx_hypercall) + +#ifdef CONFIG_INTEL_TDX_GUEST_KVM +/* + * Helper function for KVM vendor TDVMCALLs. This assembly wrapper + * lets us reuse do_tdvmcall() for KVM-specific hypercalls ( + * TDVMCALL_VENDOR_KVM). + */ +SYM_FUNC_START(__tdx_hypercall_vendor_kvm) + /* + * R10 is not part of the function call ABI, but it is a part + * of the TDVMCALL ABI. So set it before making call to the + * do_tdx_hypercall(). + */ + movq $TDVMCALL_VENDOR_KVM, %r10 + call do_tdx_hypercall + retq +SYM_FUNC_END(__tdx_hypercall_vendor_kvm) +#endif /* CONFIG_INTEL_TDX_GUEST_KVM */ diff --git a/arch/x86/kernel/tdx-kvm.c b/arch/x86/kernel/tdx-kvm.c new file mode 100644 index 000000000000..b21453a81e38 --- /dev/null +++ b/arch/x86/kernel/tdx-kvm.c @@ -0,0 +1,48 @@ +// SPDX-License-Identifier: GPL-2.0 +/* Copyright (C) 2020 Intel Corporation */ + +#include + +static long tdx_kvm_hypercall(unsigned int fn, unsigned long r12, + unsigned long r13, unsigned long r14, + unsigned long r15) +{ + return __tdx_hypercall_vendor_kvm(fn, r12, r13, r14, r15, NULL); +} + +/* Used by kvm_hypercall0() to trigger hypercall in TDX guest */ +long tdx_kvm_hypercall0(unsigned int nr) +{ + return tdx_kvm_hypercall(nr, 0, 0, 0, 0); +} +EXPORT_SYMBOL_GPL(tdx_kvm_hypercall0); + +/* Used by kvm_hypercall1() to trigger hypercall in TDX guest */ +long tdx_kvm_hypercall1(unsigned int nr, unsigned long p1) +{ + return tdx_kvm_hypercall(nr, p1, 0, 0, 0); +} +EXPORT_SYMBOL_GPL(tdx_kvm_hypercall1); + +/* Used by kvm_hypercall2() to trigger hypercall in TDX guest */ +long tdx_kvm_hypercall2(unsigned int nr, unsigned long p1, unsigned long p2) +{ + return tdx_kvm_hypercall(nr, p1, p2, 0, 0); +} +EXPORT_SYMBOL_GPL(tdx_kvm_hypercall2); + +/* Used by kvm_hypercall3() to trigger hypercall in TDX guest */ +long tdx_kvm_hypercall3(unsigned int nr, unsigned long p1, unsigned long p2, + unsigned long p3) +{ + return tdx_kvm_hypercall(nr, p1, p2, p3, 0); +} +EXPORT_SYMBOL_GPL(tdx_kvm_hypercall3); + +/* Used by kvm_hypercall4() to trigger hypercall in TDX guest */ +long tdx_kvm_hypercall4(unsigned int nr, unsigned long p1, unsigned long p2, + unsigned long p3, unsigned long p4) +{ + return tdx_kvm_hypercall(nr, p1, p2, p3, p4); +} +EXPORT_SYMBOL_GPL(tdx_kvm_hypercall4); -- 2.25.1