From patchwork Wed May 29 11:55:48 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marc Gonzalez X-Patchwork-Id: 10966875 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 74DA276 for ; Wed, 29 May 2019 11:55:55 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 609BB2883F for ; Wed, 29 May 2019 11:55:55 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 51EDD2892B; Wed, 29 May 2019 11:55:55 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-5.2 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,FREEMAIL_FROM,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED autolearn=unavailable version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [198.137.202.133]) (using TLSv1.2 with cipher AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id 01EC22883F for ; Wed, 29 May 2019 11:55:55 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=lists.infradead.org; s=bombadil.20170209; h=Sender: Content-Transfer-Encoding:Content-Type:Cc:List-Subscribe:List-Help:List-Post: List-Archive:List-Unsubscribe:List-Id:MIME-Version:Date:Message-ID:Subject: From:To:Reply-To:Content-ID:Content-Description:Resent-Date:Resent-From: Resent-Sender:Resent-To:Resent-Cc:Resent-Message-ID:In-Reply-To:References: List-Owner; bh=UhNjYEwiX8qVQvWpoMd/YDNtyndQVKk3jz+gdYSaT60=; b=kBVDAMHxhDyQIq eTlUtrpcFRWx8kcjhPzFdaPBbLu0iZMJ4qCJGeUk0GNI77XVt6r4bBzgCYdiHwm2sEO5Hul0mTPWM E2cN6j/knfS0+Qwc7cOc9GmYAy8GFK55qpIbvaDjdaJMt7VlYcKboVuGXpAm4sGg/CZ4jDrzB3CaA VNSo1mVZkHCSmiAXZ/fTHTQ9p9IDOQ2OK+ShFvCKRwWzm6UO2ccwzJ8HoH514zWAk0bcnDqbgPyUi uJ1Y/GEb5TlJ1NSklpK3aqY/wv3/C/EnIcxd9SqDOqOlxcu1DRgAw2/Uird44cRhHRarkNg0sTgwy U2DKVgW751OwkHv/P0kg==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1hVxBR-0001sD-Ss; Wed, 29 May 2019 11:55:53 +0000 Received: from ns.iliad.fr ([212.27.33.1]) by bombadil.infradead.org with esmtps (Exim 4.90_1 #2 (Red Hat Linux)) id 1hVxBO-0001rn-4P for linux-arm-kernel@lists.infradead.org; Wed, 29 May 2019 11:55:51 +0000 Received: from ns.iliad.fr (localhost [127.0.0.1]) by ns.iliad.fr (Postfix) with ESMTP id C0B5D209AE; Wed, 29 May 2019 13:55:48 +0200 (CEST) Received: from [192.168.108.49] (freebox.vlq16.iliad.fr [213.36.7.13]) by ns.iliad.fr (Postfix) with ESMTP id A6481207DC; Wed, 29 May 2019 13:55:48 +0200 (CEST) To: Robin Murphy , Will Deacon , Joerg Roedel From: Marc Gonzalez Subject: [PATCH v2] iommu/arm-smmu: Avoid constant zero in TLBI writes Message-ID: Date: Wed, 29 May 2019 13:55:48 +0200 User-Agent: Mozilla/5.0 (X11; Linux x86_64; rv:60.0) Gecko/20100101 Thunderbird/60.6.1 MIME-Version: 1.0 Content-Language: en-US X-Virus-Scanned: ClamAV using ClamSMTP ; ns.iliad.fr ; Wed May 29 13:55:48 2019 +0200 (CEST) X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20190529_045550_316872_3B6C5728 X-CRM114-Status: GOOD ( 14.96 ) X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Jeffrey Hugo , MSM , Bjorn Andersson , iommu , Andy Gross , AngeloGioacchino Del Regno , Linux ARM Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Virus-Scanned: ClamAV using ClamSMTP From: Robin Murphy Apparently, some Qualcomm arm64 platforms which appear to expose their SMMU global register space are still, in fact, using a hypervisor to mediate it by trapping and emulating register accesses. Sadly, some deployed versions of said trapping code have bugs wherein they go horribly wrong for stores using r31 (i.e. XZR/WZR) as the source register. While this can be mitigated for GCC today by tweaking the constraints for the implementation of writel_relaxed(), to avoid any potential arms race with future compilers more aggressively optimising register allocation, the simple way is to just remove all the problematic constant zeros. For the write-only TLB operations, the actual value is irrelevant anyway and any old nearby variable will provide a suitable GPR to encode. The one point at which we really do need a zero to clear a context bank happens before any of the TLB maintenance where crashes have been reported, so is apparently not a problem... :/ Reported-by: AngeloGioacchino Del Regno Reviewed-by: Marc Gonzalez Reviewed-by: Bjorn Andersson Tested-by: AngeloGioacchino Del Regno Tested-by: Marc Gonzalez Tested-by: Bjorn Andersson Signed-off-by: Robin Murphy --- Changes from v1: - Tweak commit message (remove "compilers", s/hangs/crashes) - Add a comment before writel_relaxed --- drivers/iommu/arm-smmu.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/iommu/arm-smmu.c b/drivers/iommu/arm-smmu.c index 5e54cc0a28b3..3f352268fa8b 100644 --- a/drivers/iommu/arm-smmu.c +++ b/drivers/iommu/arm-smmu.c @@ -423,7 +423,8 @@ static void __arm_smmu_tlb_sync(struct arm_smmu_device *smmu, { unsigned int spin_cnt, delay; - writel_relaxed(0, sync); + /* Write "garbage" (rather than 0) to work around a qcom bug */ + writel_relaxed((unsigned long)sync, sync); for (delay = 1; delay < TLB_LOOP_TIMEOUT; delay *= 2) { for (spin_cnt = TLB_SPIN_COUNT; spin_cnt > 0; spin_cnt--) { if (!(readl_relaxed(status) & sTLBGSTATUS_GSACTIVE)) @@ -1763,8 +1764,9 @@ static void arm_smmu_device_reset(struct arm_smmu_device *smmu) } /* Invalidate the TLB, just in case */ - writel_relaxed(0, gr0_base + ARM_SMMU_GR0_TLBIALLH); - writel_relaxed(0, gr0_base + ARM_SMMU_GR0_TLBIALLNSNH); + /* Write "garbage" (rather than 0) to work around a qcom bug */ + writel_relaxed(reg, gr0_base + ARM_SMMU_GR0_TLBIALLH); + writel_relaxed(reg, gr0_base + ARM_SMMU_GR0_TLBIALLNSNH); reg = readl_relaxed(ARM_SMMU_GR0_NS(smmu) + ARM_SMMU_GR0_sCR0);