From nobody Sun Nov 24 01:21:46 2024 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 2F7D9191F6D; Thu, 7 Nov 2024 18:46:06 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=193.142.43.55 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731005170; cv=none; b=IgMBdS7Xtrwx8AzNXGJGZYZHQVWOOxQX9Cj+xJKOvORcvzZ2DAeKbKOtJ+Tdq9j13DQgSMRRfIjMusaFK8vNBq4Gzn8rovGdG2J/KoZVsWDKtmr5LqJm9AEZka7OvNFeslv2FMme3WQzsRtiiXpvLcediV+if7PEfzZd7h7QtJY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1731005170; c=relaxed/simple; bh=ofSAmJQwCydNAZN7mO+fNLcogzsUM7l+FGxGfq+144o=; h=Date:From:To:Subject:Cc:MIME-Version:Message-ID:Content-Type; b=WadrrkUl9bNKdhC8VGIbdgtdW3PdrA3lIIK52SYnmgAQxPaedyuiVETLSVT5eoDnSykUhR1j8djOKXYqp1wD2oZk0qHoOkC/+EQaIln8VHzuY+rR4m75GuG5EOXdrFY2u1+60lHJkGJaVpkHN/gMjMgTR2twvEw1HTufr/Xk6Ik= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de; spf=pass smtp.mailfrom=linutronix.de; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=aGlF3M38; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b=mgBHq9ry; arc=none smtp.client-ip=193.142.43.55 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=linutronix.de Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=linutronix.de Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="aGlF3M38"; dkim=permerror (0-bit key) header.d=linutronix.de header.i=@linutronix.de header.b="mgBHq9ry" Date: Thu, 07 Nov 2024 18:46:04 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1731005165; 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; bh=iuc0vAKZGK9wXLFM9HHpftiuLd+2rzLzKZHIzVdtWGM=; b=aGlF3M387eS1QlDs2GKc9P8t0hekyqjBNLb61x1brsKsz/tKmzo96adISckcq+frEz9o9n 6NJ++rboPfoYudAJbZZoD76E8QWO2T2pALjAH4KMJUpPiHYswUpLCXFK9kb1P8BhAvNzHR K9iHR/EP/8m5bmpWD2PlDNLdJzQ8cbF1W5nxV4w0jISHUp2JNdtVSXeBr67Ley6106gj5k nKrrtH81MxHZyw4tcieyZ1/scJGPgZxkLjoTQ72w7bOGlMj5qY6VoRi9+WzB/ql+1x6V1X 1Dz8NCwZPUSVK72y1DUjXC9hPRavcnBE3fgKbTaem/Sx6/TPLwUbMj/Zci3h2Q== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1731005165; 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; bh=iuc0vAKZGK9wXLFM9HHpftiuLd+2rzLzKZHIzVdtWGM=; b=mgBHq9ry1BtUnEW4GHin/eX1QOgEWQVOhiWPlX/OTPfFOyyt79gU6DxYQ1ES4VgCidsLeY gId6VPVdAg7pg2DA== 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/tdx: Dynamically disable SEPT violations from causing #VEs Cc: "Kirill A. Shutemov" , Dave Hansen , Kai Huang , x86@kernel.org, linux-kernel@vger.kernel.org Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Message-ID: <173100516422.32228.17502510135596361843.tip-bot2@tip-bot2> Robot-ID: Robot-Unsubscribe: Contact to get blacklisted from these emails Precedence: bulk Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable The following commit has been merged into the x86/tdx branch of tip: Commit-ID: f65aa0ad79fca4ace921da0701644f020129043d Gitweb: https://git.kernel.org/tip/f65aa0ad79fca4ace921da0701644f020= 129043d Author: Kirill A. Shutemov AuthorDate: Mon, 04 Nov 2024 12:38:02 +02:00 Committer: Dave Hansen CommitterDate: Thu, 07 Nov 2024 10:27:38 -08:00 x86/tdx: Dynamically disable SEPT violations from causing #VEs Memory access #VEs are hard for Linux to handle in contexts like the entry code or NMIs. But other OSes need them for functionality. There's a static (pre-guest-boot) way for a VMM to choose one or the other. But VMMs don't always know which OS they are booting, so they choose to deliver those #VEs so the "other" OSes will work. That, unfortunately has left us in the lurch and exposed to these hard-to-handle #VEs. The TDX module has introduced a new feature. Even if the static configuration is set to "send nasty #VEs", the kernel can dynamically request that they be disabled. Once they are disabled, access to private memory that is not in the Mapped state in the Secure-EPT (SEPT) will result in an exit to the VMM rather than injecting a #VE. Check if the feature is available and disable SEPT #VE if possible. If the TD is allowed to disable/enable SEPT #VEs, the ATTR_SEPT_VE_DISABLE attribute is no longer reliable. It reflects the initial state of the control for the TD, but it will not be updated if someone (e.g. bootloader) changes it before the kernel starts. Kernel must check TDCS_TD_CTLS bit to determine if SEPT #VEs are enabled or disabled. [ dhansen: remove 'return' at end of function ] Fixes: 373e715e31bf ("x86/tdx: Panic on bad configs that #VE on "private" m= emory access") Signed-off-by: Kirill A. Shutemov Signed-off-by: Dave Hansen Acked-by: Kai Huang Link: https://lore.kernel.org/all/20241104103803.195705-4-kirill.shutemov%4= 0linux.intel.com --- arch/x86/coco/tdx/tdx.c | 74 +++++++++++++++++++++++------- arch/x86/include/asm/shared/tdx.h | 10 +++- 2 files changed, 67 insertions(+), 17 deletions(-) diff --git a/arch/x86/coco/tdx/tdx.c b/arch/x86/coco/tdx/tdx.c index 28b321a..2f85ed0 100644 --- a/arch/x86/coco/tdx/tdx.c +++ b/arch/x86/coco/tdx/tdx.c @@ -79,7 +79,7 @@ static inline void tdcall(u64 fn, struct tdx_module_args = *args) } =20 /* Read TD-scoped metadata */ -static inline u64 __maybe_unused tdg_vm_rd(u64 field, u64 *value) +static inline u64 tdg_vm_rd(u64 field, u64 *value) { struct tdx_module_args args =3D { .rdx =3D field, @@ -194,6 +194,60 @@ static void __noreturn tdx_panic(const char *msg) __tdx_hypercall(&args); } =20 +/* + * The kernel cannot handle #VEs when accessing normal kernel memory. Ensu= re + * that no #VE will be delivered for accesses to TD-private memory. + * + * TDX 1.0 does not allow the guest to disable SEPT #VE on its own. The VMM + * controls if the guest will receive such #VE with TD attribute + * ATTR_SEPT_VE_DISABLE. + * + * Newer TDX modules allow the guest to control if it wants to receive SEPT + * violation #VEs. + * + * Check if the feature is available and disable SEPT #VE if possible. + * + * If the TD is allowed to disable/enable SEPT #VEs, the ATTR_SEPT_VE_DISA= BLE + * attribute is no longer reliable. It reflects the initial state of the + * control for the TD, but it will not be updated if someone (e.g. bootloa= der) + * changes it before the kernel starts. Kernel must check TDCS_TD_CTLS bit= to + * determine if SEPT #VEs are enabled or disabled. + */ +static void disable_sept_ve(u64 td_attr) +{ + const char *msg =3D "TD misconfiguration: SEPT #VE has to be disabled"; + bool debug =3D td_attr & ATTR_DEBUG; + u64 config, controls; + + /* Is this TD allowed to disable SEPT #VE */ + tdg_vm_rd(TDCS_CONFIG_FLAGS, &config); + if (!(config & TDCS_CONFIG_FLEXIBLE_PENDING_VE)) { + /* No SEPT #VE controls for the guest: check the attribute */ + if (td_attr & ATTR_SEPT_VE_DISABLE) + return; + + /* Relax SEPT_VE_DISABLE check for debug TD for backtraces */ + if (debug) + pr_warn("%s\n", msg); + else + tdx_panic(msg); + return; + } + + /* Check if SEPT #VE has been disabled before us */ + tdg_vm_rd(TDCS_TD_CTLS, &controls); + if (controls & TD_CTLS_PENDING_VE_DISABLE) + return; + + /* Keep #VEs enabled for splats in debugging environments */ + if (debug) + return; + + /* Disable SEPT #VEs */ + tdg_vm_wr(TDCS_TD_CTLS, TD_CTLS_PENDING_VE_DISABLE, + TD_CTLS_PENDING_VE_DISABLE); +} + static void tdx_setup(u64 *cc_mask) { struct tdx_module_args args =3D {}; @@ -219,24 +273,12 @@ static void tdx_setup(u64 *cc_mask) gpa_width =3D args.rcx & GENMASK(5, 0); *cc_mask =3D BIT_ULL(gpa_width - 1); =20 + td_attr =3D args.rdx; + /* Kernel does not use NOTIFY_ENABLES and does not need random #VEs */ tdg_vm_wr(TDCS_NOTIFY_ENABLES, 0, -1ULL); =20 - /* - * The kernel can not handle #VE's when accessing normal kernel - * memory. Ensure that no #VE will be delivered for accesses to - * TD-private memory. Only VMM-shared memory (MMIO) will #VE. - */ - td_attr =3D args.rdx; - if (!(td_attr & ATTR_SEPT_VE_DISABLE)) { - const char *msg =3D "TD misconfiguration: SEPT_VE_DISABLE attribute must= be set."; - - /* Relax SEPT_VE_DISABLE check for debug TD. */ - if (td_attr & ATTR_DEBUG) - pr_warn("%s\n", msg); - else - tdx_panic(msg); - } + disable_sept_ve(td_attr); } =20 /* diff --git a/arch/x86/include/asm/shared/tdx.h b/arch/x86/include/asm/share= d/tdx.h index 7e12cfa..fecb2a6 100644 --- a/arch/x86/include/asm/shared/tdx.h +++ b/arch/x86/include/asm/shared/tdx.h @@ -19,9 +19,17 @@ #define TDG_VM_RD 7 #define TDG_VM_WR 8 =20 -/* TDCS fields. To be used by TDG.VM.WR and TDG.VM.RD module calls */ +/* TDX TD-Scope Metadata. To be used by TDG.VM.WR and TDG.VM.RD */ +#define TDCS_CONFIG_FLAGS 0x1110000300000016 +#define TDCS_TD_CTLS 0x1110000300000017 #define TDCS_NOTIFY_ENABLES 0x9100000000000010 =20 +/* TDCS_CONFIG_FLAGS bits */ +#define TDCS_CONFIG_FLEXIBLE_PENDING_VE BIT_ULL(1) + +/* TDCS_TD_CTLS bits */ +#define TD_CTLS_PENDING_VE_DISABLE BIT_ULL(0) + /* TDX hypercall Leaf IDs */ #define TDVMCALL_MAP_GPA 0x10001 #define TDVMCALL_GET_QUOTE 0x10002