From nobody Sat Jun 20 01:55:04 2026 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from vger.kernel.org (vger.kernel.org [23.128.96.18]) by smtp.lore.kernel.org (Postfix) with ESMTP id 0CCBAC433EF for ; Thu, 24 Mar 2022 11:55:48 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1349913AbiCXL5R (ORCPT ); Thu, 24 Mar 2022 07:57:17 -0400 Received: from lindbergh.monkeyblade.net ([23.128.96.19]:54430 "EHLO lindbergh.monkeyblade.net" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1346172AbiCXL5P (ORCPT ); Thu, 24 Mar 2022 07:57:15 -0400 Received: from galois.linutronix.de (Galois.linutronix.de [193.142.43.55]) by lindbergh.monkeyblade.net (Postfix) with ESMTPS id 9603249CBC; Thu, 24 Mar 2022 04:55:43 -0700 (PDT) Date: Thu, 24 Mar 2022 11:55:39 -0000 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020; t=1648122940; 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=NFzSfnJQPfWQ61qS3sd7xjhFHPK4LiPf59g3D1N0RyE=; b=oWbKqTznDCC6qPoLjcbRt92+W1NUmxPE0HCjoR4Eat4zgmnBdKeYHloROOnpJsb6sFFlyb 87Q1WxAtqNaDtEg9E8L+g6iFaErh+2WMqSrmQlMxS+4BHJWtjh11fst2lzYgG6aJomVg21 khJqh0myTTdqlHnASOXPqabmWb3mvLHElIydceWhTYDDQPnNYsIouBV+uf2XEggNO/QeCZ JXamixt1JT6YW7xNMniIVqazCZ11IJdl7+dZJBukQ2kRsJxNPKCh3UGwdHwDs1+pZDAK7P sn8+Ah4FbAJczU1/b30BZ4Kw1p3mp2wkrJDMrILcrHkwAg7DEFwkjZ3xtbBHsg== DKIM-Signature: v=1; a=ed25519-sha256; c=relaxed/relaxed; d=linutronix.de; s=2020e; t=1648122940; 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=NFzSfnJQPfWQ61qS3sd7xjhFHPK4LiPf59g3D1N0RyE=; b=fji+B/LfOkl0RWiaWzjwAIjejXLfzR69s/TxiSu418Ends/ULRe1k80+6+UGXBttoZlOe+ mw3oXZnxnsKB95CA== From: "tip-bot2 for Joerg Roedel" Sender: tip-bot2@linutronix.de Reply-to: linux-kernel@vger.kernel.org To: linux-tip-commits@vger.kernel.org Subject: [tip: x86/urgent] x86/sev: Unroll string mmio with CC_ATTR_GUEST_UNROLL_STRING_IO Cc: Joerg Roedel , Borislav Petkov , Tom Lendacky , x86@kernel.org, linux-kernel@vger.kernel.org In-Reply-To: <20220321093351.23976-1-joro@8bytes.org> References: <20220321093351.23976-1-joro@8bytes.org> MIME-Version: 1.0 Message-ID: <164812293945.389.13575455229967480197.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: quoted-printable Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The following commit has been merged into the x86/urgent branch of tip: Commit-ID: fb96320e194066cd9a177989920e8854fa6c1537 Gitweb: https://git.kernel.org/tip/fb96320e194066cd9a177989920e8854f= a6c1537 Author: Joerg Roedel AuthorDate: Mon, 21 Mar 2022 10:33:51 +01:00 Committer: Borislav Petkov CommitterDate: Thu, 24 Mar 2022 12:24:04 +01:00 x86/sev: Unroll string mmio with CC_ATTR_GUEST_UNROLL_STRING_IO The io-specific memcpy/memset functions use string mmio accesses to do their work. Under SEV, the hypervisor can't emulate these instructions because they read/write directly from/to encrypted memory. KVM will inject a page fault exception into the guest when it is asked to emulate string mmio instructions for an SEV guest: BUG: unable to handle page fault for address: ffffc90000065068 #PF: supervisor read access in kernel mode #PF: error_code(0x0000) - not-present page PGD 8000100000067 P4D 8000100000067 PUD 80001000fb067 PMD 80001000fc067 P= TE 80000000fed40173 Oops: 0000 [#1] PREEMPT SMP NOPTI CPU: 0 PID: 1 Comm: swapper/0 Not tainted 5.17.0-rc7 #3 As string mmio for an SEV guest can not be supported by the hypervisor, unroll the instructions for CC_ATTR_GUEST_UNROLL_STRING_IO enabled kernels. This issue appears when kernels are launched in recent libvirt-managed SEV virtual machines, because virt-install started to add a tpm-crb device to the guest by default and proactively because, raisins: https://github.com/virt-manager/virt-manager/commit/eb58c09f488b0633ed1ee= a012cd311e48864401e and as that commit says, the default adding of a TPM can be disabled with "virt-install ... --tpm none". The kernel driver for tpm-crb uses memcpy_to/from_io() functions to access MMIO memory, resulting in a page-fault injected by KVM and crashing the kernel at boot. [ bp: Massage and extend commit message. ] Fixes: d8aa7eea78a1 ('x86/mm: Add Secure Encrypted Virtualization (SEV) sup= port') Signed-off-by: Joerg Roedel Signed-off-by: Borislav Petkov Reviewed-by: Tom Lendacky Link: https://lore.kernel.org/r/20220321093351.23976-1-joro@8bytes.org --- arch/x86/lib/iomem.c | 65 +++++++++++++++++++++++++++++++++++++------ 1 file changed, 57 insertions(+), 8 deletions(-) diff --git a/arch/x86/lib/iomem.c b/arch/x86/lib/iomem.c index df50451..6954193 100644 --- a/arch/x86/lib/iomem.c +++ b/arch/x86/lib/iomem.c @@ -22,7 +22,7 @@ static __always_inline void rep_movs(void *to, const void= *from, size_t n) : "memory"); } =20 -void memcpy_fromio(void *to, const volatile void __iomem *from, size_t n) +static void string_memcpy_fromio(void *to, const volatile void __iomem *fr= om, size_t n) { if (unlikely(!n)) return; @@ -38,9 +38,8 @@ void memcpy_fromio(void *to, const volatile void __iomem = *from, size_t n) } rep_movs(to, (const void *)from, n); } -EXPORT_SYMBOL(memcpy_fromio); =20 -void memcpy_toio(volatile void __iomem *to, const void *from, size_t n) +static void string_memcpy_toio(volatile void __iomem *to, const void *from= , size_t n) { if (unlikely(!n)) return; @@ -56,14 +55,64 @@ void memcpy_toio(volatile void __iomem *to, const void = *from, size_t n) } rep_movs((void *)to, (const void *) from, n); } + +static void unrolled_memcpy_fromio(void *to, const volatile void __iomem *= from, size_t n) +{ + const volatile char __iomem *in =3D from; + char *out =3D to; + int i; + + for (i =3D 0; i < n; ++i) + out[i] =3D in[i]; +} + +static void unrolled_memcpy_toio(volatile void __iomem *to, const void *fr= om, size_t n) +{ + volatile char __iomem *out =3D to; + const char *in =3D from; + int i; + + for (i =3D 0; i < n; ++i) + out[i] =3D in[i]; +} + +static void unrolled_memset_io(volatile void __iomem *a, int b, size_t c) +{ + volatile char __iomem *mem =3D a; + int i; + + for (i =3D 0; i < c; ++i) + mem[i] =3D b; +} + +void memcpy_fromio(void *to, const volatile void __iomem *from, size_t n) +{ + if (cc_platform_has(CC_ATTR_GUEST_UNROLL_STRING_IO)) + unrolled_memcpy_fromio(to, from, n); + else + string_memcpy_fromio(to, from, n); +} +EXPORT_SYMBOL(memcpy_fromio); + +void memcpy_toio(volatile void __iomem *to, const void *from, size_t n) +{ + if (cc_platform_has(CC_ATTR_GUEST_UNROLL_STRING_IO)) + unrolled_memcpy_toio(to, from, n); + else + string_memcpy_toio(to, from, n); +} EXPORT_SYMBOL(memcpy_toio); =20 void memset_io(volatile void __iomem *a, int b, size_t c) { - /* - * TODO: memset can mangle the IO patterns quite a bit. - * perhaps it would be better to use a dumb one: - */ - memset((void *)a, b, c); + if (cc_platform_has(CC_ATTR_GUEST_UNROLL_STRING_IO)) { + unrolled_memset_io(a, b, c); + } else { + /* + * TODO: memset can mangle the IO patterns quite a bit. + * perhaps it would be better to use a dumb one: + */ + memset((void *)a, b, c); + } } EXPORT_SYMBOL(memset_io);