From patchwork Thu Feb 23 16:03:17 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Mark Rutland X-Patchwork-Id: 9588481 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id AF5356051E for ; Thu, 23 Feb 2017 16:05:16 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A04C22891F for ; Thu, 23 Feb 2017 16:05:16 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 92D4928922; Thu, 23 Feb 2017 16:05:16 +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=-1.9 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID autolearn=ham version=3.3.1 Received: from bombadil.infradead.org (bombadil.infradead.org [65.50.211.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 2EF062891F for ; Thu, 23 Feb 2017 16:05:16 +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:MIME-Version:Cc:List-Subscribe: List-Help:List-Post:List-Archive:List-Unsubscribe:List-Id:Message-Id:Date: Subject:To:From: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=uQsAockgMTPePnYEWqRmkQHCORm0fFHkqW2+1ulxqU0=; b=lgK Ejiz0Jnu14nGbYnTCrEjZNLeAzkl98BNJa+P+2GN1yHGPYCuS0kOzCrcP7tN1urwn+LC4YM6MH6Pi Gxh9l66xIl/qCqMtyfq8jTsdJeUvxD97DZzwpV5lbCEOo/TBDgnLEp6tTkwIQodH9DKQpi7uN/DjY piQosG1M+xY0E3hB0iJJZdO+Saqt8R6azYI4dZUJNVe1N6ejzFFvYVGOssqI4rBOEfNxdyTc1oxGE VkQTXUfGfYYNG5A9RgfHLhB8BU6IKdgkb4y4iLFhsBAGKrhRupFW1rwJU8B0kMHs6/yAPDz3fwNeS tnKjImBly773RGBOu721CJRV19du+2Q==; Received: from localhost ([127.0.0.1] helo=bombadil.infradead.org) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1cgvtB-0005aA-Dw; Thu, 23 Feb 2017 16:05:05 +0000 Received: from foss.arm.com ([217.140.101.70]) by bombadil.infradead.org with esmtp (Exim 4.87 #1 (Red Hat Linux)) id 1cgvrv-0005J8-0z for linux-arm-kernel@lists.infradead.org; Thu, 23 Feb 2017 16:03:49 +0000 Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.72.51.249]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id B0203687; Thu, 23 Feb 2017 08:03:26 -0800 (PST) Received: from leverpostej.cambridge.arm.com (usa-sjc-imap-foss1.foss.arm.com [10.72.51.249]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPA id ECF263F483; Thu, 23 Feb 2017 08:03:25 -0800 (PST) From: Mark Rutland To: linux-arm-kernel@lists.infradead.org Subject: [PATCH] arm64/cpufeature: check correct field width when updating sys_val Date: Thu, 23 Feb 2017 16:03:17 +0000 Message-Id: <1487865797-25418-1-git-send-email-mark.rutland@arm.com> X-Mailer: git-send-email 1.9.1 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20170223_080347_141344_68485E7B X-CRM114-Status: UNSURE ( 9.87 ) X-CRM114-Notice: Please train this message. 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: Mark Rutland , Catalin Marinas , Will Deacon MIME-Version: 1.0 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 When we're updating a register's sys_val, we use arm64_ftr_value() to find the new field value. We use cpuid_feature_extract_field() to find the new value, but this implicitly assumes a 4-bit field, so we may extract more bits than we mean to for fields like CTR_EL0.L1ip. This affects update_cpu_ftr_reg(), where we may extract erroneous values for ftr_cur and ftr_new. Depending on the additional bits extracted in either case, we may erroneously detect that the value is mismatched, and we'll try to compute a new safe value. Dependent on these extra bits and feature type, arm64_ftr_safe_value() may pessimistically select the always-safe value, or may erroneously choose either the extracted cur or new value as the safe option. The extra bits will subsequently be masked out in arm64_ftr_set_value(), so we may choose a higher value, yet write back a lower one. Fix this by passing the width down explicitly in arm64_ftr_value(), so we always extract the correct amount. Signed-off-by: Mark Rutland Reviewed-by: Suzuki K Poulose Cc: Catalin Marinas Cc: Will Deacon --- arch/arm64/include/asm/cpufeature.h | 14 ++++++++++---- 1 file changed, 10 insertions(+), 4 deletions(-) Strictly speaking, this fixes: 3c739b5710843621 ("arm64: Keep track of CPU feature registers") ... but this doesn't (yet) have any functional impact. Luckily the L1ip detection reads from cpuinfo_arm64 directly, and is not affected by this error. Mark. diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h index 4ce82ed..05310ad 100644 --- a/arch/arm64/include/asm/cpufeature.h +++ b/arch/arm64/include/asm/cpufeature.h @@ -184,16 +184,22 @@ static inline u64 arm64_ftr_reg_user_value(const struct arm64_ftr_reg *reg) } static inline int __attribute_const__ -cpuid_feature_extract_field(u64 features, int field, bool sign) +cpuid_feature_extract_field_width(u64 features, int field, int width, bool sign) { return (sign) ? - cpuid_feature_extract_signed_field(features, field) : - cpuid_feature_extract_unsigned_field(features, field); + cpuid_feature_extract_signed_field_width(features, field, width) : + cpuid_feature_extract_unsigned_field_width(features, field, width); +} + +static inline int __attribute_const__ +cpuid_feature_extract_field(u64 features, int field, bool sign) +{ + return cpuid_feature_extract_field_width(features, field, 4, sign); } static inline s64 arm64_ftr_value(const struct arm64_ftr_bits *ftrp, u64 val) { - return (s64)cpuid_feature_extract_field(val, ftrp->shift, ftrp->sign); + return (s64)cpuid_feature_extract_field_width(val, ftrp->shift, ftrp->width, ftrp->sign); } static inline bool id_aa64mmfr0_mixed_endian_el0(u64 mmfr0)