From 410cb9211582a7893373a637be5bc00a52596efe Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Fri, 25 Sep 2015 08:59:38 -0700 Subject: [PATCH] MIPS: Initialise MAARs on secondary CPUs MAARs should be initialised on each CPU (or rather, core) in the system in order to achieve consistent behaviour & performance. Previously they have only been initialised on the boot CPU which leads to performance problems if tasks are later scheduled on a secondary CPU, particularly if those tasks make use of unaligned vector accesses where some CPUs don't handle any cases in hardware for non-speculative memory regions. Fix this by recording the MAAR configuration from the boot CPU and applying it to secondary CPUs as part of their bringup. Reported-by: Doug Gilmore Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Cc: Rusty Russell Cc: Steven J. Hill Cc: Andrew Bresticker Cc: Bjorn Helgaas Cc: David Hildenbrand Cc: linux-kernel@vger.kernel.org Cc: Aaro Koskinen Cc: James Hogan Cc: Ingo Molnar Cc: Markos Chandras Cc: Hemmo Nieminen Cc: Alex Smith Cc: Peter Zijlstra (Intel) Patchwork: https://patchwork.linux-mips.org/patch/11239/ Signed-off-by: Ralf Baechle --- arch/mips/include/asm/maar.h | 9 +++++++++ arch/mips/kernel/smp.c | 2 ++ arch/mips/mm/init.c | 28 +++++++++++++++++++++++++--- 3 files changed, 36 insertions(+), 3 deletions(-) diff --git a/arch/mips/include/asm/maar.h b/arch/mips/include/asm/maar.h index b02891f9caaf1d..21d9607c80d7de 100644 --- a/arch/mips/include/asm/maar.h +++ b/arch/mips/include/asm/maar.h @@ -65,6 +65,15 @@ static inline void write_maar_pair(unsigned idx, phys_addr_t lower, back_to_back_c0_hazard(); } +/** + * maar_init() - initialise MAARs + * + * Performs initialisation of MAARs for the current CPU, making use of the + * platforms implementation of platform_maar_init where necessary and + * duplicating the setup it provides on secondary CPUs. + */ +extern void maar_init(void); + /** * struct maar_config - MAAR configuration data * @lower: The lowest address that the MAAR pair will affect. Must be diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c index a31896c33716d4..bd4385a8e6e86f 100644 --- a/arch/mips/kernel/smp.c +++ b/arch/mips/kernel/smp.c @@ -42,6 +42,7 @@ #include #include #include +#include cpumask_t cpu_callin_map; /* Bitmask of started secondaries */ @@ -157,6 +158,7 @@ asmlinkage void start_secondary(void) mips_clockevent_init(); mp_ops->init_secondary(); cpu_report(); + maar_init(); /* * XXX parity protection should be folded in here when it's converted diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c index 023c164b9eb69f..8770e619185eb0 100644 --- a/arch/mips/mm/init.c +++ b/arch/mips/mm/init.c @@ -44,6 +44,7 @@ #include #include #include +#include /* * We have up to 8 empty zeroed pages so we can map one of the right colour @@ -288,10 +289,14 @@ unsigned __weak platform_maar_init(unsigned num_pairs) return num_configured; } -static void maar_init(void) +void maar_init(void) { unsigned num_maars, used, i; phys_addr_t lower, upper, attr; + static struct { + struct maar_config cfgs[3]; + unsigned used; + } recorded = { { { 0 } }, 0 }; if (!cpu_has_maar) return; @@ -304,8 +309,14 @@ static void maar_init(void) /* MAARs should be in pairs */ WARN_ON(num_maars % 2); - /* Configure the required MAARs */ - used = platform_maar_init(num_maars / 2); + /* Set MAARs using values we recorded already */ + if (recorded.used) { + used = maar_config(recorded.cfgs, recorded.used, num_maars / 2); + BUG_ON(used != recorded.used); + } else { + /* Configure the required MAARs */ + used = platform_maar_init(num_maars / 2); + } /* Disable any further MAARs */ for (i = (used * 2); i < num_maars; i++) { @@ -315,6 +326,9 @@ static void maar_init(void) back_to_back_c0_hazard(); } + if (recorded.used) + return; + pr_info("MAAR configuration:\n"); for (i = 0; i < num_maars; i += 2) { write_c0_maari(i); @@ -341,6 +355,14 @@ static void maar_init(void) pr_cont(" speculate"); pr_cont("\n"); + + /* Record the setup for use on secondary CPUs */ + if (used <= ARRAY_SIZE(recorded.cfgs)) { + recorded.cfgs[recorded.used].lower = lower; + recorded.cfgs[recorded.used].upper = upper; + recorded.cfgs[recorded.used].attrs = attr; + recorded.used++; + } } }