Received: by 2002:a25:31c3:0:0:0:0:0 with SMTP id x186csp2929055ybx; Fri, 8 Nov 2019 11:24:01 -0800 (PST) X-Google-Smtp-Source: APXvYqwcHaeZsGAXkPh6oOLaksobJ35stjfcQOG0K3Q2jE8bC+04CkRPaAQWYbCze1U4KZ2TzqTj X-Received: by 2002:a17:906:af5a:: with SMTP id ly26mr8952103ejb.252.1573241041761; Fri, 08 Nov 2019 11:24:01 -0800 (PST) ARC-Seal: i=1; a=rsa-sha256; t=1573241041; cv=none; d=google.com; s=arc-20160816; b=JgixxQsbNPh7dhmdEEsJ3QMW0siCw2LcWznouWsnDkP9+vs9PQ5nm9CKUz2Kan1jOG uQAlycjPWHbLzIDmSpJrbU+aYry7usf35IHyLQdm7nWgQNLZ/jsVZYJdWc+Kpfl4Z1Vb MUsAZ2USED3vUPyzrju81sUA+F87De/AEihGXa5k9mGIBKJqdkfKMvj1TwawCHuxXevs eo21W9iBkKx3vWHb9+hJE0JdSI+arvJZAO3TvlNsu4hypoOQbLaswqhNyTpzHd0CJ2s5 97TuUJOfYc0muV//4noImPGn4LqnVu+NME1Q2QcrwxZaIcfb0dheaBbi4cy9Sh12Yp2B 29Tw== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=arc-20160816; h=list-id:precedence:sender:content-transfer-encoding:mime-version :user-agent:references:in-reply-to:message-id:date:subject:cc:to :from:dkim-signature; bh=KkMiEgbfF1a/W77nGCfm16j9akLn55KZ4X0mZ+uDfsA=; b=L9jpxS7amp4owmDJ+efkxZkfp49aI+pLHoWsCXWKpV4F8IaBIhc0LF0GaM3vYMxIJR 7gzg52AzBT7s5ftL1KxNWE+Hs7fcmzyTaloyhABpVvDu3tf7Dl7afNVupvvx6MalXFZ+ xQXm7gPAWwLtzljEbmweikZLKVV066how/SlzStLvcJFjHYaOIyEXw5zwbGWsRN2zC28 Jpps1TPHoaKe0tHd9SvEQNqEpssVIfiWTi1MzW85cXQ6TBvdm3yPbNc0HQTNNwgnSXQC h1Ydh1nEB9jsN+13ubmpyeN5Y4fVUmBfcPScs5rP3fFZGDERsmbK55Tho+55odj9I2gb gHwQ== ARC-Authentication-Results: i=1; mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b="qC/w+z1W"; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id p20si3875700eju.109.2019.11.08.11.23.37; Fri, 08 Nov 2019 11:24:01 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@kernel.org header.s=default header.b="qC/w+z1W"; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S2391110AbfKHTXC (ORCPT + 99 others); Fri, 8 Nov 2019 14:23:02 -0500 Received: from mail.kernel.org ([198.145.29.99]:52494 "EHLO mail.kernel.org" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1731608AbfKHSzO (ORCPT ); Fri, 8 Nov 2019 13:55:14 -0500 Received: from localhost (83-86-89-107.cable.dynamic.v4.ziggo.nl [83.86.89.107]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPSA id B3ADF21D82; Fri, 8 Nov 2019 18:55:12 +0000 (UTC) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/simple; d=kernel.org; s=default; t=1573239313; bh=awx7wz/KoRhgKQtKCnfVr0cgeX8koSNPdNZI/Y+qaBk=; h=From:To:Cc:Subject:Date:In-Reply-To:References:From; b=qC/w+z1WNNHZ+Uh4HQYLq+11yGzsxHMS3cddg1yObvciXHZAPYpgbR2xFlrqonzVR 4akPCxKbT0HOJ61NQC4CCu8Pq/uwgwYHUAs/yKlO2Sc7HAgOzvsJnEZ379ivYpgwzO Vkb4+dzprC45TuSrcnHwD0e3TtH8srNeUBAet9Pk= From: Greg Kroah-Hartman To: linux-kernel@vger.kernel.org, stable@vger.kernel.org Cc: Greg Kroah-Hartman , "linus.walleij@linaro.org, rmk+kernel@armlinux.org.uk, Ard Biesheuvel" , Julien Thierry , Russell King , "David A. Long" , Sasha Levin , Ard Biesheuvel Subject: [PATCH 4.4 71/75] ARM: spectre-v2: per-CPU vtables to work around big.Little systems Date: Fri, 8 Nov 2019 19:50:28 +0100 Message-Id: <20191108174811.499447790@linuxfoundation.org> X-Mailer: git-send-email 2.24.0 In-Reply-To: <20191108174708.135680837@linuxfoundation.org> References: <20191108174708.135680837@linuxfoundation.org> User-Agent: quilt/0.66 MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org From: Russell King Commit 383fb3ee8024d596f488d2dbaf45e572897acbdb upstream. In big.Little systems, some CPUs require the Spectre workarounds in paths such as the context switch, but other CPUs do not. In order to handle these differences, we need per-CPU vtables. We are unable to use the kernel's per-CPU variables to support this as per-CPU is not initialised at times when we need access to the vtables, so we have to use an array indexed by logical CPU number. We use an array-of-pointers to avoid having function pointers in the kernel's read/write .data section. Note: Added include of linux/slab.h in arch/arm/smp.c. Reviewed-by: Julien Thierry Signed-off-by: Russell King Signed-off-by: David A. Long Reviewed-by: Julien Thierry Signed-off-by: Sasha Levin Signed-off-by: Ard Biesheuvel Signed-off-by: Greg Kroah-Hartman --- arch/arm/include/asm/proc-fns.h | 23 +++++++++++++++++++++++ arch/arm/kernel/setup.c | 5 +++++ arch/arm/kernel/smp.c | 32 ++++++++++++++++++++++++++++++++ arch/arm/mm/proc-v7-bugs.c | 17 ++--------------- 4 files changed, 62 insertions(+), 15 deletions(-) --- a/arch/arm/include/asm/proc-fns.h +++ b/arch/arm/include/asm/proc-fns.h @@ -104,12 +104,35 @@ extern void cpu_do_resume(void *); #else extern struct processor processor; +#if defined(CONFIG_BIG_LITTLE) && defined(CONFIG_HARDEN_BRANCH_PREDICTOR) +#include +/* + * This can't be a per-cpu variable because we need to access it before + * per-cpu has been initialised. We have a couple of functions that are + * called in a pre-emptible context, and so can't use smp_processor_id() + * there, hence PROC_TABLE(). We insist in init_proc_vtable() that the + * function pointers for these are identical across all CPUs. + */ +extern struct processor *cpu_vtable[]; +#define PROC_VTABLE(f) cpu_vtable[smp_processor_id()]->f +#define PROC_TABLE(f) cpu_vtable[0]->f +static inline void init_proc_vtable(const struct processor *p) +{ + unsigned int cpu = smp_processor_id(); + *cpu_vtable[cpu] = *p; + WARN_ON_ONCE(cpu_vtable[cpu]->dcache_clean_area != + cpu_vtable[0]->dcache_clean_area); + WARN_ON_ONCE(cpu_vtable[cpu]->set_pte_ext != + cpu_vtable[0]->set_pte_ext); +} +#else #define PROC_VTABLE(f) processor.f #define PROC_TABLE(f) processor.f static inline void init_proc_vtable(const struct processor *p) { processor = *p; } +#endif #define cpu_proc_init PROC_VTABLE(_proc_init) #define cpu_check_bugs PROC_VTABLE(check_bugs) --- a/arch/arm/kernel/setup.c +++ b/arch/arm/kernel/setup.c @@ -113,6 +113,11 @@ EXPORT_SYMBOL(elf_hwcap2); #ifdef MULTI_CPU struct processor processor __read_mostly; +#if defined(CONFIG_BIG_LITTLE) && defined(CONFIG_HARDEN_BRANCH_PREDICTOR) +struct processor *cpu_vtable[NR_CPUS] = { + [0] = &processor, +}; +#endif #endif #ifdef MULTI_TLB struct cpu_tlb_fns cpu_tlb __read_mostly; --- a/arch/arm/kernel/smp.c +++ b/arch/arm/kernel/smp.c @@ -27,6 +27,7 @@ #include #include #include +#include #include #include @@ -40,6 +41,7 @@ #include #include #include +#include #include #include #include @@ -96,6 +98,30 @@ static unsigned long get_arch_pgd(pgd_t #endif } +#if defined(CONFIG_BIG_LITTLE) && defined(CONFIG_HARDEN_BRANCH_PREDICTOR) +static int secondary_biglittle_prepare(unsigned int cpu) +{ + if (!cpu_vtable[cpu]) + cpu_vtable[cpu] = kzalloc(sizeof(*cpu_vtable[cpu]), GFP_KERNEL); + + return cpu_vtable[cpu] ? 0 : -ENOMEM; +} + +static void secondary_biglittle_init(void) +{ + init_proc_vtable(lookup_processor(read_cpuid_id())->proc); +} +#else +static int secondary_biglittle_prepare(unsigned int cpu) +{ + return 0; +} + +static void secondary_biglittle_init(void) +{ +} +#endif + int __cpu_up(unsigned int cpu, struct task_struct *idle) { int ret; @@ -103,6 +129,10 @@ int __cpu_up(unsigned int cpu, struct ta if (!smp_ops.smp_boot_secondary) return -ENOSYS; + ret = secondary_biglittle_prepare(cpu); + if (ret) + return ret; + /* * We need to tell the secondary core where to find * its stack and the page tables. @@ -354,6 +384,8 @@ asmlinkage void secondary_start_kernel(v struct mm_struct *mm = &init_mm; unsigned int cpu; + secondary_biglittle_init(); + /* * The identity mapping is uncached (strongly ordered), so * switch away from it before attempting any exclusive accesses. --- a/arch/arm/mm/proc-v7-bugs.c +++ b/arch/arm/mm/proc-v7-bugs.c @@ -52,8 +52,6 @@ static void cpu_v7_spectre_init(void) case ARM_CPU_PART_CORTEX_A17: case ARM_CPU_PART_CORTEX_A73: case ARM_CPU_PART_CORTEX_A75: - if (processor.switch_mm != cpu_v7_bpiall_switch_mm) - goto bl_error; per_cpu(harden_branch_predictor_fn, cpu) = harden_branch_predictor_bpiall; spectre_v2_method = "BPIALL"; @@ -61,8 +59,6 @@ static void cpu_v7_spectre_init(void) case ARM_CPU_PART_CORTEX_A15: case ARM_CPU_PART_BRAHMA_B15: - if (processor.switch_mm != cpu_v7_iciallu_switch_mm) - goto bl_error; per_cpu(harden_branch_predictor_fn, cpu) = harden_branch_predictor_iciallu; spectre_v2_method = "ICIALLU"; @@ -88,11 +84,9 @@ static void cpu_v7_spectre_init(void) ARM_SMCCC_ARCH_WORKAROUND_1, &res); if ((int)res.a0 != 0) break; - if (processor.switch_mm != cpu_v7_hvc_switch_mm && cpu) - goto bl_error; per_cpu(harden_branch_predictor_fn, cpu) = call_hvc_arch_workaround_1; - processor.switch_mm = cpu_v7_hvc_switch_mm; + cpu_do_switch_mm = cpu_v7_hvc_switch_mm; spectre_v2_method = "hypervisor"; break; @@ -101,11 +95,9 @@ static void cpu_v7_spectre_init(void) ARM_SMCCC_ARCH_WORKAROUND_1, &res); if ((int)res.a0 != 0) break; - if (processor.switch_mm != cpu_v7_smc_switch_mm && cpu) - goto bl_error; per_cpu(harden_branch_predictor_fn, cpu) = call_smc_arch_workaround_1; - processor.switch_mm = cpu_v7_smc_switch_mm; + cpu_do_switch_mm = cpu_v7_smc_switch_mm; spectre_v2_method = "firmware"; break; @@ -119,11 +111,6 @@ static void cpu_v7_spectre_init(void) if (spectre_v2_method) pr_info("CPU%u: Spectre v2: using %s workaround\n", smp_processor_id(), spectre_v2_method); - return; - -bl_error: - pr_err("CPU%u: Spectre v2: incorrect context switching function, system vulnerable\n", - cpu); } #else static void cpu_v7_spectre_init(void)