diff options
author | Paul Burton <paul.burton@imgtec.com> | 2015-09-25 11:59:38 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2015-09-27 08:15:26 -0400 |
commit | e060f6ed281669b6d2f22d8dafd664b532386918 (patch) | |
tree | fa74247359834941661b76a318ca6ad790b01041 | |
parent | 651ca7f4dab77f07fdac9cfb68bcab6bd2b7f827 (diff) |
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 <doug.gilmore@imgtec.com>
Signed-off-by: Paul Burton <paul.burton@imgtec.com>
Cc: linux-mips@linux-mips.org
Cc: Rusty Russell <rusty@rustcorp.com.au>
Cc: Steven J. Hill <Steven.Hill@imgtec.com>
Cc: Andrew Bresticker <abrestic@chromium.org>
Cc: Bjorn Helgaas <bhelgaas@google.com>
Cc: David Hildenbrand <dahi@linux.vnet.ibm.com>
Cc: linux-kernel@vger.kernel.org
Cc: Aaro Koskinen <aaro.koskinen@iki.fi>
Cc: James Hogan <james.hogan@imgtec.com>
Cc: Ingo Molnar <mingo@kernel.org>
Cc: Markos Chandras <markos.chandras@imgtec.com>
Cc: Hemmo Nieminen <hemmo.nieminen@iki.fi>
Cc: Alex Smith <alex.smith@imgtec.com>
Cc: Peter Zijlstra (Intel) <peterz@infradead.org>
Patchwork: https://patchwork.linux-mips.org/patch/11239/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
-rw-r--r-- | arch/mips/include/asm/maar.h | 9 | ||||
-rw-r--r-- | arch/mips/kernel/smp.c | 2 | ||||
-rw-r--r-- | 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 b02891f9caaf..21d9607c80d7 100644 --- a/arch/mips/include/asm/maar.h +++ b/arch/mips/include/asm/maar.h | |||
@@ -66,6 +66,15 @@ static inline void write_maar_pair(unsigned idx, phys_addr_t lower, | |||
66 | } | 66 | } |
67 | 67 | ||
68 | /** | 68 | /** |
69 | * maar_init() - initialise MAARs | ||
70 | * | ||
71 | * Performs initialisation of MAARs for the current CPU, making use of the | ||
72 | * platforms implementation of platform_maar_init where necessary and | ||
73 | * duplicating the setup it provides on secondary CPUs. | ||
74 | */ | ||
75 | extern void maar_init(void); | ||
76 | |||
77 | /** | ||
69 | * struct maar_config - MAAR configuration data | 78 | * struct maar_config - MAAR configuration data |
70 | * @lower: The lowest address that the MAAR pair will affect. Must be | 79 | * @lower: The lowest address that the MAAR pair will affect. Must be |
71 | * aligned to a 2^16 byte boundary. | 80 | * aligned to a 2^16 byte boundary. |
diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c index a31896c33716..bd4385a8e6e8 100644 --- a/arch/mips/kernel/smp.c +++ b/arch/mips/kernel/smp.c | |||
@@ -42,6 +42,7 @@ | |||
42 | #include <asm/mmu_context.h> | 42 | #include <asm/mmu_context.h> |
43 | #include <asm/time.h> | 43 | #include <asm/time.h> |
44 | #include <asm/setup.h> | 44 | #include <asm/setup.h> |
45 | #include <asm/maar.h> | ||
45 | 46 | ||
46 | cpumask_t cpu_callin_map; /* Bitmask of started secondaries */ | 47 | cpumask_t cpu_callin_map; /* Bitmask of started secondaries */ |
47 | 48 | ||
@@ -157,6 +158,7 @@ asmlinkage void start_secondary(void) | |||
157 | mips_clockevent_init(); | 158 | mips_clockevent_init(); |
158 | mp_ops->init_secondary(); | 159 | mp_ops->init_secondary(); |
159 | cpu_report(); | 160 | cpu_report(); |
161 | maar_init(); | ||
160 | 162 | ||
161 | /* | 163 | /* |
162 | * XXX parity protection should be folded in here when it's converted | 164 | * 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 023c164b9eb6..8770e619185e 100644 --- a/arch/mips/mm/init.c +++ b/arch/mips/mm/init.c | |||
@@ -44,6 +44,7 @@ | |||
44 | #include <asm/pgalloc.h> | 44 | #include <asm/pgalloc.h> |
45 | #include <asm/tlb.h> | 45 | #include <asm/tlb.h> |
46 | #include <asm/fixmap.h> | 46 | #include <asm/fixmap.h> |
47 | #include <asm/maar.h> | ||
47 | 48 | ||
48 | /* | 49 | /* |
49 | * We have up to 8 empty zeroed pages so we can map one of the right colour | 50 | * 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) | |||
288 | return num_configured; | 289 | return num_configured; |
289 | } | 290 | } |
290 | 291 | ||
291 | static void maar_init(void) | 292 | void maar_init(void) |
292 | { | 293 | { |
293 | unsigned num_maars, used, i; | 294 | unsigned num_maars, used, i; |
294 | phys_addr_t lower, upper, attr; | 295 | phys_addr_t lower, upper, attr; |
296 | static struct { | ||
297 | struct maar_config cfgs[3]; | ||
298 | unsigned used; | ||
299 | } recorded = { { { 0 } }, 0 }; | ||
295 | 300 | ||
296 | if (!cpu_has_maar) | 301 | if (!cpu_has_maar) |
297 | return; | 302 | return; |
@@ -304,8 +309,14 @@ static void maar_init(void) | |||
304 | /* MAARs should be in pairs */ | 309 | /* MAARs should be in pairs */ |
305 | WARN_ON(num_maars % 2); | 310 | WARN_ON(num_maars % 2); |
306 | 311 | ||
307 | /* Configure the required MAARs */ | 312 | /* Set MAARs using values we recorded already */ |
308 | used = platform_maar_init(num_maars / 2); | 313 | if (recorded.used) { |
314 | used = maar_config(recorded.cfgs, recorded.used, num_maars / 2); | ||
315 | BUG_ON(used != recorded.used); | ||
316 | } else { | ||
317 | /* Configure the required MAARs */ | ||
318 | used = platform_maar_init(num_maars / 2); | ||
319 | } | ||
309 | 320 | ||
310 | /* Disable any further MAARs */ | 321 | /* Disable any further MAARs */ |
311 | for (i = (used * 2); i < num_maars; i++) { | 322 | for (i = (used * 2); i < num_maars; i++) { |
@@ -315,6 +326,9 @@ static void maar_init(void) | |||
315 | back_to_back_c0_hazard(); | 326 | back_to_back_c0_hazard(); |
316 | } | 327 | } |
317 | 328 | ||
329 | if (recorded.used) | ||
330 | return; | ||
331 | |||
318 | pr_info("MAAR configuration:\n"); | 332 | pr_info("MAAR configuration:\n"); |
319 | for (i = 0; i < num_maars; i += 2) { | 333 | for (i = 0; i < num_maars; i += 2) { |
320 | write_c0_maari(i); | 334 | write_c0_maari(i); |
@@ -341,6 +355,14 @@ static void maar_init(void) | |||
341 | pr_cont(" speculate"); | 355 | pr_cont(" speculate"); |
342 | 356 | ||
343 | pr_cont("\n"); | 357 | pr_cont("\n"); |
358 | |||
359 | /* Record the setup for use on secondary CPUs */ | ||
360 | if (used <= ARRAY_SIZE(recorded.cfgs)) { | ||
361 | recorded.cfgs[recorded.used].lower = lower; | ||
362 | recorded.cfgs[recorded.used].upper = upper; | ||
363 | recorded.cfgs[recorded.used].attrs = attr; | ||
364 | recorded.used++; | ||
365 | } | ||
344 | } | 366 | } |
345 | } | 367 | } |
346 | 368 | ||