Received: by 2002:a05:6a10:6d10:0:0:0:0 with SMTP id gq16csp24539pxb; Tue, 12 Apr 2022 15:45:30 -0700 (PDT) X-Google-Smtp-Source: ABdhPJwV94XRc8SHZ1bnYORPV8/8sPXQBsvKrUam54ZNaauKLKDxmC9xpzs3F0oswAftOvy+mnPh X-Received: by 2002:a17:902:f682:b0:154:8500:80bf with SMTP id l2-20020a170902f68200b00154850080bfmr39767859plg.112.1649803530151; Tue, 12 Apr 2022 15:45:30 -0700 (PDT) ARC-Seal: i=1; a=rsa-sha256; t=1649803530; cv=none; d=google.com; s=arc-20160816; b=ZecKou3JrC0Yxjv1anBVu8VduN4WCGvTj2QQ9nwalHQUccgVVxQ/UbLiFKrEX0ejt7 6IUiywHB2SynEYjrdqwHaobcHk4nB+Ls0hrkLJGbmFQCUcflYfnxHDm5DcVDxYDeKzph LONNsd2JRPDJZEk/RrGWFGAWTqKZFYAv6Gdl9NMoKvek72AydKRkAdCFbxMrnKE65RiF F/rTI8DPKa4wxarvUoA1NzLJEzj2XLXuTAdIJcv9jNs1DO8TLTndvcR5kHeHJYkOPdl5 mg/ykzWTqOc/hQTwRGo9YsqtCbOII1XWTbIokjVcTxgdAdKQRgfQCBJ1jzCHL4boPTu/ MHqQ== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:content-transfer-encoding:robot-unsubscribe :robot-id:message-id:mime-version:references:in-reply-to:cc:subject :to:reply-to:sender:from:dkim-signature:dkim-signature:date; bh=KJEJ0EYWeJWu3nu5hajmx4qwo3tvuJglxoa+gD2xJXg=; b=ouwL1Gfo40fSPNqgfFmJn7EAptIQH5MoAAX+H5rMni/PH3sTuFXL5Ucaz11vbfBiEp 1qdA4vdwRLSD+Gydhp8syILnl4g457ioKvBOEnMWbLttDHfwbs0RPIjWbFePt1NqNlUf XKL1/wI1QX6lMEWfcz25l2WFqF72kX3RKjEMmqraN2dUAq7Aj569MR0C8mH5GkR/aENl TWoHPjkqbcozwhom/Nq/zQzRsxIxaVeZU+Y+xvjkOhsl0g5N5kmqO9TfmOojSFD+aCFn klfkAkrb+hJJRrsQucQm7Rw9WAqmv7MzAxAO/vxLAvb9Oj0Xwqy952m91SRPlOVp+miQ 0q5g== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@linutronix.de header.s=2020 header.b=AFaY0xug; dkim=neutral (no key) header.i=@linutronix.de header.b=n4pBGpQ0; spf=softfail (google.com: domain of transitioning linux-kernel-owner@vger.kernel.org does not designate 23.128.96.19 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=linutronix.de Return-Path: Received: from lindbergh.monkeyblade.net (lindbergh.monkeyblade.net. [23.128.96.19]) by mx.google.com with ESMTPS id t186-20020a6381c3000000b003816043ee48si2502124pgd.61.2022.04.12.15.45.29 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Tue, 12 Apr 2022 15:45:30 -0700 (PDT) Received-SPF: softfail (google.com: domain of transitioning linux-kernel-owner@vger.kernel.org does not designate 23.128.96.19 as permitted sender) client-ip=23.128.96.19; Authentication-Results: mx.google.com; dkim=pass header.i=@linutronix.de header.s=2020 header.b=AFaY0xug; dkim=neutral (no key) header.i=@linutronix.de header.b=n4pBGpQ0; spf=softfail (google.com: domain of transitioning linux-kernel-owner@vger.kernel.org does not designate 23.128.96.19 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=QUARANTINE dis=NONE) header.from=linutronix.de Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by lindbergh.monkeyblade.net (Postfix) with ESMTP id 880A1DF84; Tue, 12 Apr 2022 14:26:32 -0700 (PDT) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S240293AbiDIB3v (ORCPT + 99 others); Fri, 8 Apr 2022 21:29:51 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:41274 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S239146AbiDIB3a (ORCPT ); Fri, 8 Apr 2022 21:29:30 -0400 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 03ECBDA6DF; Fri, 8 Apr 2022 18:27:23 -0700 (PDT) Date: Sat, 09 Apr 2022 01:27:21 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1649467642; h=from:from:sender:sender:reply-to:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=KJEJ0EYWeJWu3nu5hajmx4qwo3tvuJglxoa+gD2xJXg=; b=AFaY0xuglFgMb4cFRcntvFP6C6uTiC754vhxSzPMgukfWFOrriLzDcxfaMVcDIN76QMSuS h6a5mPPOA82SbxwNzA+0zybdklbPoOWp3VlE8wjpaO26vbvsg+23lRIaDakQQ4Ix8mc8t/ YiSxTprgR95fkI/vkfMj1loABLBN8hdpNtdJXDHaq96kOQprthXyHbDAyFzTiXHJRE8EK2 Fx2f2BtnJfsR+uxRX2Dogv4GIC3HhEmRRBmM/urlP7TRWMRS3ZAcZNPkA9fpUDnBzii8xs 2hCcaOMkqmaxE/f9Ce1J2fOIV9nb3wS7H95tq2Cym3tVKiLB4f7zb8BzhVktvQ== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1649467642; h=from:from:sender:sender:reply-to:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type: content-transfer-encoding:content-transfer-encoding: in-reply-to:in-reply-to:references:references; bh=KJEJ0EYWeJWu3nu5hajmx4qwo3tvuJglxoa+gD2xJXg=; b=n4pBGpQ0RFs7cJoVzR82pNTwtUD3f75ouyyRL3lvyy64e04uizPihCMTmtmw2DOK90kRg4 Q/ghEv2pm1AeTqCg== From: "tip-bot2 for Kirill A. Shutemov" Sender: tip-bot2@linutronix.de Reply-to: linux-kernel@vger.kernel.org To: linux-tip-commits@vger.kernel.org Subject: [tip: x86/tdx] x86/mm/cpa: Add support for TDX shared memory Cc: "Kirill A. Shutemov" , Dave Hansen , Thomas Gleixner , x86@kernel.org, linux-kernel@vger.kernel.org In-Reply-To: <20220405232939.73860-27-kirill.shutemov@linux.intel.com> References: <20220405232939.73860-27-kirill.shutemov@linux.intel.com> MIME-Version: 1.0 Message-ID: <164946764149.4207.1620159764822684171.tip-bot2@tip-bot2> Robot-ID: Robot-Unsubscribe: Contact to get blacklisted from these emails Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: 7bit X-Spam-Status: No, score=-2.0 required=5.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,HEADER_FROM_DIFFERENT_DOMAINS, MAILING_LIST_MULTI,RDNS_NONE,SPF_HELO_NONE,T_SCC_BODY_TEXT_LINE autolearn=no autolearn_force=no version=3.4.6 X-Spam-Checker-Version: SpamAssassin 3.4.6 (2021-04-09) on lindbergh.monkeyblade.net Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The following commit has been merged into the x86/tdx branch of tip: Commit-ID: 7dbde7631629896b478bc5b1f4c3e52e6d518d12 Gitweb: https://git.kernel.org/tip/7dbde7631629896b478bc5b1f4c3e52e6d518d12 Author: Kirill A. Shutemov AuthorDate: Wed, 06 Apr 2022 02:29:35 +03:00 Committer: Dave Hansen CommitterDate: Thu, 07 Apr 2022 08:27:53 -07:00 x86/mm/cpa: Add support for TDX shared memory Intel TDX protects guest memory from VMM access. Any memory that is required for communication with the VMM must be explicitly shared. It is a two-step process: the guest sets the shared bit in the page table entry and notifies VMM about the change. The notification happens using MapGPA hypercall. Conversion back to private memory requires clearing the shared bit, notifying VMM with MapGPA hypercall following with accepting the memory with AcceptPage hypercall. Provide a TDX version of x86_platform.guest.* callbacks. It makes __set_memory_enc_pgtable() work right in TDX guest. Signed-off-by: Kirill A. Shutemov Signed-off-by: Dave Hansen Reviewed-by: Thomas Gleixner Link: https://lkml.kernel.org/r/20220405232939.73860-27-kirill.shutemov@linux.intel.com --- arch/x86/coco/core.c | 1 +- arch/x86/coco/tdx/tdx.c | 133 +++++++++++++++++++++++++++++++++++++++- arch/x86/kernel/traps.c | 2 +- 3 files changed, 135 insertions(+), 1 deletion(-) diff --git a/arch/x86/coco/core.c b/arch/x86/coco/core.c index 70956f9..9f74125 100644 --- a/arch/x86/coco/core.c +++ b/arch/x86/coco/core.c @@ -21,6 +21,7 @@ static bool intel_cc_platform_has(enum cc_attr attr) switch (attr) { case CC_ATTR_GUEST_UNROLL_STRING_IO: case CC_ATTR_HOTPLUG_DISABLED: + case CC_ATTR_GUEST_MEM_ENCRYPT: return true; default: return false; diff --git a/arch/x86/coco/tdx/tdx.c b/arch/x86/coco/tdx/tdx.c index f50f530..03deb4d 100644 --- a/arch/x86/coco/tdx/tdx.c +++ b/arch/x86/coco/tdx/tdx.c @@ -10,10 +10,15 @@ #include #include #include +#include /* TDX module Call Leaf IDs */ #define TDX_GET_INFO 1 #define TDX_GET_VEINFO 3 +#define TDX_ACCEPT_PAGE 6 + +/* TDX hypercall Leaf IDs */ +#define TDVMCALL_MAP_GPA 0x10001 /* MMIO direction */ #define EPT_READ 0 @@ -531,6 +536,130 @@ bool tdx_handle_virt_exception(struct pt_regs *regs, struct ve_info *ve) return ret; } +static bool tdx_tlb_flush_required(bool private) +{ + /* + * TDX guest is responsible for flushing TLB on private->shared + * transition. VMM is responsible for flushing on shared->private. + * + * The VMM _can't_ flush private addresses as it can't generate PAs + * with the guest's HKID. Shared memory isn't subject to integrity + * checking, i.e. the VMM doesn't need to flush for its own protection. + * + * There's no need to flush when converting from shared to private, + * as flushing is the VMM's responsibility in this case, e.g. it must + * flush to avoid integrity failures in the face of a buggy or + * malicious guest. + */ + return !private; +} + +static bool tdx_cache_flush_required(void) +{ + /* + * AMD SME/SEV can avoid cache flushing if HW enforces cache coherence. + * TDX doesn't have such capability. + * + * Flush cache unconditionally. + */ + return true; +} + +static bool try_accept_one(phys_addr_t *start, unsigned long len, + enum pg_level pg_level) +{ + unsigned long accept_size = page_level_size(pg_level); + u64 tdcall_rcx; + u8 page_size; + + if (!IS_ALIGNED(*start, accept_size)) + return false; + + if (len < accept_size) + return false; + + /* + * Pass the page physical address to the TDX module to accept the + * pending, private page. + * + * Bits 2:0 of RCX encode page size: 0 - 4K, 1 - 2M, 2 - 1G. + */ + switch (pg_level) { + case PG_LEVEL_4K: + page_size = 0; + break; + case PG_LEVEL_2M: + page_size = 1; + break; + case PG_LEVEL_1G: + page_size = 2; + break; + default: + return false; + } + + tdcall_rcx = *start | page_size; + if (__tdx_module_call(TDX_ACCEPT_PAGE, tdcall_rcx, 0, 0, 0, NULL)) + return false; + + *start += accept_size; + return true; +} + +/* + * Inform the VMM of the guest's intent for this physical page: shared with + * the VMM or private to the guest. The VMM is expected to change its mapping + * of the page in response. + */ +static bool tdx_enc_status_changed(unsigned long vaddr, int numpages, bool enc) +{ + phys_addr_t start = __pa(vaddr); + phys_addr_t end = __pa(vaddr + numpages * PAGE_SIZE); + + if (!enc) { + /* Set the shared (decrypted) bits: */ + start |= cc_mkdec(0); + end |= cc_mkdec(0); + } + + /* + * Notify the VMM about page mapping conversion. More info about ABI + * can be found in TDX Guest-Host-Communication Interface (GHCI), + * section "TDG.VP.VMCALL" + */ + if (_tdx_hypercall(TDVMCALL_MAP_GPA, start, end - start, 0, 0)) + return false; + + /* private->shared conversion requires only MapGPA call */ + if (!enc) + return true; + + /* + * For shared->private conversion, accept the page using + * TDX_ACCEPT_PAGE TDX module call. + */ + while (start < end) { + unsigned long len = end - start; + + /* + * Try larger accepts first. It gives chance to VMM to keep + * 1G/2M SEPT entries where possible and speeds up process by + * cutting number of hypercalls (if successful). + */ + + if (try_accept_one(&start, len, PG_LEVEL_1G)) + continue; + + if (try_accept_one(&start, len, PG_LEVEL_2M)) + continue; + + if (!try_accept_one(&start, len, PG_LEVEL_4K)) + return false; + } + + return true; +} + void __init tdx_early_init(void) { u64 cc_mask; @@ -555,5 +684,9 @@ void __init tdx_early_init(void) */ physical_mask &= cc_mask - 1; + x86_platform.guest.enc_cache_flush_required = tdx_cache_flush_required; + x86_platform.guest.enc_tlb_flush_required = tdx_tlb_flush_required; + x86_platform.guest.enc_status_change_finish = tdx_enc_status_changed; + pr_info("Guest detected\n"); } diff --git a/arch/x86/kernel/traps.c b/arch/x86/kernel/traps.c index f9fb653..a4e2efd 100644 --- a/arch/x86/kernel/traps.c +++ b/arch/x86/kernel/traps.c @@ -1378,7 +1378,7 @@ static void ve_raise_fault(struct pt_regs *regs, long error_code) * * In the settings that Linux will run in, virtualization exceptions are * never generated on accesses to normal, TD-private memory that has been - * accepted. + * accepted (by BIOS or with tdx_enc_status_changed()). * * Syscall entry code has a critical window where the kernel stack is not * yet set up. Any exception in this window leads to hard to debug issues