Received: by 2002:a05:6a10:206:0:0:0:0 with SMTP id 6csp1707297pxj; Wed, 19 May 2021 12:00:33 -0700 (PDT) X-Google-Smtp-Source: ABdhPJxM74mVZsqgACHJb9KowziH8WKyguo0OwMT9qrz30fTO90ZvfvMCZl9sfZnowLd+rJmegkg X-Received: by 2002:a05:6638:a48:: with SMTP id 8mr618168jap.38.1621450833098; Wed, 19 May 2021 12:00:33 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1621450833; cv=none; d=google.com; s=arc-20160816; b=JqkMUBH4ItMZvdB6MPpXvDOFDufXXRF7PvMrd/BqSCkL+ATdqmzruBwECJw4Lrz+M4 4UzaEWv1UQmpvKpFVeAHJddo3xpcxOxOKJwL4Ym7XncoJTxa51YfnJkXTxKGvCH10OGS c7Jadr4OSK9DMrehR+7+NoJ+IP4qSCZJl6Y3fTHXbdjQChdQvR9cMfbtKdSXPCUXWboP Q81sgdmLCQlshO4jZUaxzYjdyB5mHF4/QRNwT58gI/cnUyDJm1RBpRjhWKrbRubLTr39 CnGVXdImrQaEScRGZ2/aKTD5LJr/Jme2SlL4LhtPtPmgC9YSiAEE6jNviLGvCjdS2hQo anNw== 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=6H3XfbN5S7OuP93M+am0vijRxzVMgvHpTXNobuH4mV4=; b=vVlTed1thm2vL3rSsj9kk8uNcWojF7DflA3DYXLoi9KteFgY4Ysl8Y4/j0MxVLfmwl 2adzy56cqc3akGjHMwIQOg3u+r3i0mSX1TKo3lGcC1EU3iZx7BswL03QBqOlYeEAmu7C GoYeiskD0a3XeMK/80kLzve1QvHdHsfUXaBukkHv2PnSASulR+ztg8Er3tPme8HJogSx jR3Q8Pxg315rF4opSFCkxedv5iK2SiIeXcR0gZOs4VH1Waq+uhJRvNOMZOYiu3ZehOBh 5qhuynECoj4ccHjkUi1HIr7q+E5drc3aS6Xqf/QQWniL4XFQBN/dEvha5YS/109mI5nD Yx+Q== 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 j24si34854jad.22.2021.05.19.12.00.20; Wed, 19 May 2021 12:00:33 -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 S231659AbhESBSf (ORCPT + 99 others); Tue, 18 May 2021 21:18:35 -0400 Received: from mga02.intel.com ([134.134.136.20]:39944 "EHLO mga02.intel.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S231641AbhESBSe (ORCPT ); Tue, 18 May 2021 21:18:34 -0400 IronPort-SDR: dRq0thjR8KcOYsQVTcpsuwnxPpqDz/nElU1Ml4+sokv+gIFCIDF3WiruoqSzGFx0oytBHRz0qk btGgQClowHug== X-IronPort-AV: E=McAfee;i="6200,9189,9988"; a="187991924" X-IronPort-AV: E=Sophos;i="5.82,310,1613462400"; d="scan'208";a="187991924" Received: from fmsmga005.fm.intel.com ([10.253.24.32]) by orsmga101.jf.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 18 May 2021 18:17:15 -0700 IronPort-SDR: P0vs2i19sy0wZ8XWfMyfK9Ebf04a71jJgifSdC6aS756Bx/IztdKS+gcMnjkexOgoKYWwuZ2v+ wU9NPutejlaQ== X-IronPort-AV: E=Sophos;i="5.82,310,1613462400"; d="scan'208";a="630728043" Received: from kmylavar-mobl.amr.corp.intel.com (HELO skuppusw-desk1.amr.corp.intel.com) ([10.212.100.98]) by fmsmga005-auth.fm.intel.com with ESMTP/TLS/ECDHE-RSA-AES256-GCM-SHA384; 18 May 2021 18:17:14 -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, Kuppuswamy Sathyanarayanan Subject: [RFC v2-fix-v3 1/1] x86/tdx: Wire up KVM hypercalls Date: Tue, 18 May 2021 18:17:12 -0700 Message-Id: <20210519011712.1334416-1-sathyanarayanan.kuppuswamy@linux.intel.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <97588756-5c12-2913-05a7-938eb7a510c8@intel.com> References: <97588756-5c12-2913-05a7-938eb7a510c8@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-specific TDVMCALLs instead of VMCALL. This enables TDX guests to run with KVM acting as the hypervisor. TDX guests running under other hypervisors will continue to use those hypervisors' hypercalls. Since KVM driver can be built as a kernel module, export tdx_kvm_hypercall*() to make the symbols visible to kvm.ko. [Isaku Yamahata: proposed KVM VENDOR string] Signed-off-by: Kirill A. Shutemov Reviewed-by: Andi Kleen Reviewed-by: Dave Hansen Signed-off-by: Kuppuswamy Sathyanarayanan --- arch/x86/Kconfig | 5 +++ arch/x86/include/asm/kvm_para.h | 21 ++++++++++ arch/x86/include/asm/tdx.h | 68 +++++++++++++++++++++++++++++++++ arch/x86/kernel/tdcall.S | 26 +++++++++++++ 4 files changed, 120 insertions(+) diff --git a/arch/x86/Kconfig b/arch/x86/Kconfig index 9e0e0ff76bab..15e66a99dd41 100644 --- a/arch/x86/Kconfig +++ b/arch/x86/Kconfig @@ -886,6 +886,11 @@ 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. +# This option enables KVM specific hypercalls in TDX guest. +config INTEL_TDX_GUEST_KVM + def_bool y + depends on KVM_GUEST && INTEL_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..3d8d977e52f0 100644 --- a/arch/x86/include/asm/tdx.h +++ b/arch/x86/include/asm/tdx.h @@ -73,4 +73,72 @@ 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); + +/* Used by kvm_hypercall0() to trigger hypercall in TDX guest */ +static inline long tdx_kvm_hypercall0(unsigned int nr) +{ + return __tdx_hypercall_vendor_kvm(nr, 0, 0, 0, 0, NULL); +} + +/* Used by kvm_hypercall1() to trigger hypercall in TDX guest */ +static inline long tdx_kvm_hypercall1(unsigned int nr, unsigned long p1) +{ + return __tdx_hypercall_vendor_kvm(nr, p1, 0, 0, 0, NULL); +} + +/* Used by kvm_hypercall2() to trigger hypercall in TDX guest */ +static inline long tdx_kvm_hypercall2(unsigned int nr, unsigned long p1, + unsigned long p2) +{ + return __tdx_hypercall_vendor_kvm(nr, p1, p2, 0, 0, NULL); +} + +/* Used by kvm_hypercall3() to trigger hypercall in TDX guest */ +static inline long tdx_kvm_hypercall3(unsigned int nr, unsigned long p1, + unsigned long p2, unsigned long p3) +{ + return __tdx_hypercall_vendor_kvm(nr, p1, p2, p3, 0, NULL); +} + +/* Used by kvm_hypercall4() to trigger hypercall in TDX guest */ +static inline long tdx_kvm_hypercall4(unsigned int nr, unsigned long p1, + unsigned long p2, unsigned long p3, + unsigned long p4) +{ + return __tdx_hypercall_vendor_kvm(nr, p1, p2, p3, p4, NULL); +} +#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/tdcall.S b/arch/x86/kernel/tdcall.S index 2dfecdae38bb..27355fb80aeb 100644 --- a/arch/x86/kernel/tdcall.S +++ b/arch/x86/kernel/tdcall.S @@ -3,6 +3,7 @@ #include #include #include +#include #include #include @@ -25,6 +26,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 @@ -212,3 +215,26 @@ SYM_FUNC_START(__tdx_hypercall) FRAME_END 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) + FRAME_BEGIN + /* + * 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 + FRAME_END + retq +SYM_FUNC_END(__tdx_hypercall_vendor_kvm) + +EXPORT_SYMBOL(__tdx_hypercall_vendor_kvm); +#endif /* CONFIG_INTEL_TDX_GUEST_KVM */ -- 2.25.1