From patchwork Mon Jan 14 10:35:27 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Marc Zyngier X-Patchwork-Id: 10762059 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 D3F3613BF for ; Mon, 14 Jan 2019 10:36:05 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id C57A028B44 for ; Mon, 14 Jan 2019 10:36:05 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id B93A828B4F; Mon, 14 Jan 2019 10:36:05 +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,MAILING_LIST_MULTI,RCVD_IN_DNSWL_MED autolearn=ham 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 2D92A28B44 for ; Mon, 14 Jan 2019 10:36:05 +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:References:In-Reply-To: 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: List-Owner; bh=+gM+1hp5dNsIEIKLYm48GvkLo2bBlJyGiOElmU7qmUs=; b=eyG8ypbCvF7l/1 0DZ887uA8Q4WBU88TrLseiEc3ZrSx2vlT07gXl8mNaUZANzjb4YtwkRAlIGCMEB92dLGkOQ5JUEaH KO+HTJ/pH8BrnPIyjFPTrVpUtJlsoPAHIjwDGhjCu2MReNN+ypzpb69eve6Zr18co3Swq8PCheLNh 03DnwnK7u8sTQH1lk0genxCKhsLAbLY5d0luMI6WYFIpC35aIIYZYQA6AYNtu86+wOqGIqliGXacT 4Kf5LWqmmM9dcOKK0tFNXdDKluE1p6+ocLTbKTFTG+rgtAUCkWblm/+fIOOVVbm4401R209meLjK3 +QxWNd5Fd67MAdsM7o+Q==; 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 1gizb7-0001K1-DT; Mon, 14 Jan 2019 10:36:01 +0000 Received: from foss.arm.com ([217.140.101.70]) by bombadil.infradead.org with esmtp (Exim 4.90_1 #2 (Red Hat Linux)) id 1gizam-000106-EC for linux-arm-kernel@lists.infradead.org; Mon, 14 Jan 2019 10:35:42 +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 EFAA915AB; Mon, 14 Jan 2019 02:35:39 -0800 (PST) Received: from filthy-habits.cambridge.arm.com (filthy-habits.cambridge.arm.com [10.1.196.62]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id E065E3F5BD; Mon, 14 Jan 2019 02:35:38 -0800 (PST) From: Marc Zyngier To: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org Subject: [PATCH v2 1/2] arm64: Advertise mitigation of Spectre-v2, or lack thereof Date: Mon, 14 Jan 2019 10:35:27 +0000 Message-Id: <20190114103528.52931-2-marc.zyngier@arm.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20190114103528.52931-1-marc.zyngier@arm.com> References: <20190114103528.52931-1-marc.zyngier@arm.com> MIME-Version: 1.0 X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20190114_023540_756182_BD8C18AA X-CRM114-Status: GOOD ( 19.13 ) 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: Catalin Marinas , Will Deacon , Jeremy Linton 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 We currently have a list of CPUs affected by Spectre-v2, for which we check that the firmware implements ARCH_WORKAROUND_1. It turns out that not all firmwares do implement the required mitigation, and that we fail to let the user know about it. Instead, let's slightly revamp our checks, and rely on a whitelist of cores that are known to be non-vulnerable, and let the user know the status of the mitigation in the kernel log. Signed-off-by: Marc Zyngier --- arch/arm64/kernel/cpu_errata.c | 111 +++++++++++++++------------------ 1 file changed, 52 insertions(+), 59 deletions(-) diff --git a/arch/arm64/kernel/cpu_errata.c b/arch/arm64/kernel/cpu_errata.c index c8ff96158b94..145f8b5d093d 100644 --- a/arch/arm64/kernel/cpu_errata.c +++ b/arch/arm64/kernel/cpu_errata.c @@ -138,9 +138,9 @@ static void __copy_hyp_vect_bpi(int slot, const char *hyp_vecs_start, __flush_icache_range((uintptr_t)dst, (uintptr_t)dst + SZ_2K); } -static void __install_bp_hardening_cb(bp_hardening_cb_t fn, - const char *hyp_vecs_start, - const char *hyp_vecs_end) +static void install_bp_hardening_cb(bp_hardening_cb_t fn, + const char *hyp_vecs_start, + const char *hyp_vecs_end) { static DEFINE_RAW_SPINLOCK(bp_lock); int cpu, slot = -1; @@ -176,31 +176,14 @@ static void __install_bp_hardening_cb(bp_hardening_cb_t fn, #define __smccc_workaround_1_smc_start NULL #define __smccc_workaround_1_smc_end NULL -static void __install_bp_hardening_cb(bp_hardening_cb_t fn, - const char *hyp_vecs_start, - const char *hyp_vecs_end) +static void install_bp_hardening_cb(bp_hardening_cb_t fn, + const char *hyp_vecs_start, + const char *hyp_vecs_end) { __this_cpu_write(bp_hardening_data.fn, fn); } #endif /* CONFIG_KVM_INDIRECT_VECTORS */ -static void install_bp_hardening_cb(const struct arm64_cpu_capabilities *entry, - bp_hardening_cb_t fn, - const char *hyp_vecs_start, - const char *hyp_vecs_end) -{ - u64 pfr0; - - if (!entry->matches(entry, SCOPE_LOCAL_CPU)) - return; - - pfr0 = read_cpuid(ID_AA64PFR0_EL1); - if (cpuid_feature_extract_unsigned_field(pfr0, ID_AA64PFR0_CSV2_SHIFT)) - return; - - __install_bp_hardening_cb(fn, hyp_vecs_start, hyp_vecs_end); -} - #include #include #include @@ -227,20 +210,21 @@ static void qcom_link_stack_sanitization(void) : "=&r" (tmp)); } -static void -enable_smccc_arch_workaround_1(const struct arm64_cpu_capabilities *entry) +/* + * -1: No workaround + * 0: No workaround required + * 1: Workaround installed + */ +static int detect_harden_bp_fw(void) { bp_hardening_cb_t cb; void *smccc_start, *smccc_end; struct arm_smccc_res res; u32 midr = read_cpuid_id(); - if (!entry->matches(entry, SCOPE_LOCAL_CPU)) - return; - if (psci_ops.smccc_version == SMCCC_VERSION_1_0) { __hardenbp_enab = false; - return; + return -1; } switch (psci_ops.conduit) { @@ -249,7 +233,7 @@ enable_smccc_arch_workaround_1(const struct arm64_cpu_capabilities *entry) ARM_SMCCC_ARCH_WORKAROUND_1, &res); if ((int)res.a0 < 0) { __hardenbp_enab = false; - return; + return -1; } cb = call_hvc_arch_workaround_1; /* This is a guest, no need to patch KVM vectors */ @@ -262,7 +246,7 @@ enable_smccc_arch_workaround_1(const struct arm64_cpu_capabilities *entry) ARM_SMCCC_ARCH_WORKAROUND_1, &res); if ((int)res.a0 < 0) { __hardenbp_enab = false; - return; + return -1; } cb = call_smc_arch_workaround_1; smccc_start = __smccc_workaround_1_smc_start; @@ -271,16 +255,22 @@ enable_smccc_arch_workaround_1(const struct arm64_cpu_capabilities *entry) default: __hardenbp_enab = false; - return; + return -1; } if (((midr & MIDR_CPU_MODEL_MASK) == MIDR_QCOM_FALKOR) || ((midr & MIDR_CPU_MODEL_MASK) == MIDR_QCOM_FALKOR_V1)) cb = qcom_link_stack_sanitization; - install_bp_hardening_cb(entry, cb, smccc_start, smccc_end); + install_bp_hardening_cb(cb, smccc_start, smccc_end); - return; + return 1; +} +#else +static int detect_harden_bp_fw(void) +{ + /* Sorry, can't do a thing */ + return -1; } #endif /* CONFIG_HARDEN_BRANCH_PREDICTOR */ @@ -544,7 +534,15 @@ cpu_enable_cache_maint_trap(const struct arm64_cpu_capabilities *__unused) #if defined(CONFIG_HARDEN_BRANCH_PREDICTOR) || \ defined(CONFIG_GENERIC_CPU_VULNERABILITIES) - +/* + * List of CPUs that do not need any Spectre-v2 mitigation at all. + */ +static const struct midr_range spectre_v2_safe_list[] = { + MIDR_ALL_VERSIONS(MIDR_CORTEX_A35), + MIDR_ALL_VERSIONS(MIDR_CORTEX_A53), + MIDR_ALL_VERSIONS(MIDR_CORTEX_A55), + { /* sentinel */ } +}; static bool __spectrev2_safe = true; @@ -555,37 +553,34 @@ static bool __spectrev2_safe = true; static bool __maybe_unused check_branch_predictor(const struct arm64_cpu_capabilities *entry, int scope) { - bool is_vul; + int need_wa; WARN_ON(scope != SCOPE_LOCAL_CPU || preemptible()); - is_vul = is_midr_in_range_list(read_cpuid_id(), entry->midr_range_list); + /* If the CPU has CSV2 set, we're safe */ + if (cpuid_feature_extract_unsigned_field(read_cpuid(ID_AA64PFR0_EL1), + ID_AA64PFR0_CSV2_SHIFT)) + return false; - if (is_vul) - __spectrev2_safe = false; + /* Alternatively, we have a list of unaffected CPUs */ + if (is_midr_in_range_list(read_cpuid_id(), spectre_v2_safe_list)) + return false; + + /* Fallback to firmware detection */ + need_wa = detect_harden_bp_fw(); + if (!need_wa) + return false; + + __spectrev2_safe = false; + + if (need_wa < 0) + pr_warn_once("ARM_SMCCC_ARCH_WORKAROUND_1 missing from firmware\n"); arm64_requested_vuln_attrs |= VULN_SPECTREV2; - return is_vul; + return (need_wa > 0); } -/* - * List of CPUs where we need to issue a psci call to - * harden the branch predictor. - */ -static const struct midr_range arm64_bp_harden_smccc_cpus[] = { - MIDR_ALL_VERSIONS(MIDR_CORTEX_A57), - MIDR_ALL_VERSIONS(MIDR_CORTEX_A72), - MIDR_ALL_VERSIONS(MIDR_CORTEX_A73), - MIDR_ALL_VERSIONS(MIDR_CORTEX_A75), - MIDR_ALL_VERSIONS(MIDR_BRCM_VULCAN), - MIDR_ALL_VERSIONS(MIDR_CAVIUM_THUNDERX2), - MIDR_ALL_VERSIONS(MIDR_QCOM_FALKOR_V1), - MIDR_ALL_VERSIONS(MIDR_QCOM_FALKOR), - MIDR_ALL_VERSIONS(MIDR_NVIDIA_DENVER), - {}, -}; - #endif #ifdef CONFIG_HARDEN_EL2_VECTORS @@ -764,10 +759,8 @@ const struct arm64_cpu_capabilities arm64_errata[] = { #ifdef CONFIG_HARDEN_BRANCH_PREDICTOR { .capability = ARM64_HARDEN_BRANCH_PREDICTOR, - .cpu_enable = enable_smccc_arch_workaround_1, .type = ARM64_CPUCAP_LOCAL_CPU_ERRATUM, .matches = check_branch_predictor, - .midr_range_list = arm64_bp_harden_smccc_cpus, }, #endif #ifdef CONFIG_HARDEN_EL2_VECTORS