Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

MIPS: Malta: Fix crash in SMP kernel on non-CMP systems.

Since 6be63bbbdab66b9185dc6f67c8b1bacb6f37f946 (lmo) rsp.
af3a1f6f4813907e143f87030cde67a9971db533 (kernel.org) the Malta code does
no longer probe for presence of GCMP if CMP is not configured. This means
that the variable gcmp_present well be left at its default value of -1
which normally is meant to indicate that GCMP has not yet been mmapped.
This non-zero value is now interpreted as GCMP being present resulting
in a write attempt to a GCMP register resulting in a crash.

Reported and a build fix on top of my fix by Rob Landley <rob@landley.net>.

Reported-by: Rob Landley <rob@landley.net>
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Patchwork: https://patchwork.linux-mips.org/patch/2413/

+56 -24
+38 -3
arch/mips/include/asm/smp-ops.h
··· 56 56 57 57 #endif /* !CONFIG_SMP */ 58 58 59 - extern struct plat_smp_ops up_smp_ops; 60 - extern struct plat_smp_ops cmp_smp_ops; 61 - extern struct plat_smp_ops vsmp_smp_ops; 59 + static inline int register_up_smp_ops(void) 60 + { 61 + #ifdef CONFIG_SMP_UP 62 + extern struct plat_smp_ops up_smp_ops; 63 + 64 + register_smp_ops(&up_smp_ops); 65 + 66 + return 0; 67 + #else 68 + return -ENODEV; 69 + #endif 70 + } 71 + 72 + static inline int register_cmp_smp_ops(void) 73 + { 74 + #ifdef CONFIG_MIPS_CMP 75 + extern struct plat_smp_ops cmp_smp_ops; 76 + 77 + register_smp_ops(&cmp_smp_ops); 78 + 79 + return 0; 80 + #else 81 + return -ENODEV; 82 + #endif 83 + } 84 + 85 + static inline int register_vsmp_smp_ops(void) 86 + { 87 + #ifdef CONFIG_MIPS_MT_SMP 88 + extern struct plat_smp_ops vsmp_smp_ops; 89 + 90 + register_smp_ops(&vsmp_smp_ops); 91 + 92 + return 0; 93 + #else 94 + return -ENODEV; 95 + #endif 96 + } 62 97 63 98 #endif /* __ASM_SMP_OPS_H */
+8 -9
arch/mips/mipssim/sim_setup.c
··· 59 59 60 60 prom_meminit(); 61 61 62 - #ifdef CONFIG_MIPS_MT_SMP 63 - if (cpu_has_mipsmt) 64 - register_smp_ops(&vsmp_smp_ops); 65 - else 66 - register_smp_ops(&up_smp_ops); 67 - #endif 62 + if (cpu_has_mipsmt) { 63 + if (!register_vsmp_smp_ops()) 64 + return; 65 + 68 66 #ifdef CONFIG_MIPS_MT_SMTC 69 - if (cpu_has_mipsmt) 70 67 register_smp_ops(&ssmtc_smp_ops); 71 - else 72 - register_smp_ops(&up_smp_ops); 68 + return; 73 69 #endif 70 + } 71 + 72 + register_up_smp_ops(); 74 73 } 75 74 76 75 static void __init serial_init(void)
+7 -7
arch/mips/mti-malta/malta-init.c
··· 28 28 #include <asm/io.h> 29 29 #include <asm/system.h> 30 30 #include <asm/cacheflush.h> 31 + #include <asm/smp-ops.h> 31 32 #include <asm/traps.h> 32 33 33 34 #include <asm/gcmpregs.h> ··· 359 358 #ifdef CONFIG_SERIAL_8250_CONSOLE 360 359 console_config(); 361 360 #endif 362 - #ifdef CONFIG_MIPS_CMP 363 361 /* Early detection of CMP support */ 364 362 if (gcmp_probe(GCMP_BASE_ADDR, GCMP_ADDRSPACE_SZ)) 365 - register_smp_ops(&cmp_smp_ops); 366 - else 367 - #endif 368 - #ifdef CONFIG_MIPS_MT_SMP 369 - register_smp_ops(&vsmp_smp_ops); 370 - #endif 363 + if (!register_cmp_smp_ops()) 364 + return; 365 + 366 + if (!register_vsmp_smp_ops()) 367 + return; 368 + 371 369 #ifdef CONFIG_MIPS_MT_SMTC 372 370 register_smp_ops(&msmtc_smp_ops); 373 371 #endif
+3 -5
arch/mips/pmc-sierra/msp71xx/msp_setup.c
··· 228 228 */ 229 229 msp_serial_setup(); 230 230 231 - #ifdef CONFIG_MIPS_MT_SMP 232 - register_smp_ops(&vsmp_smp_ops); 233 - #endif 234 - 231 + if (register_vsmp_smp_ops()) { 235 232 #ifdef CONFIG_MIPS_MT_SMTC 236 - register_smp_ops(&msp_smtc_smp_ops); 233 + register_smp_ops(&msp_smtc_smp_ops); 237 234 #endif 235 + } 238 236 239 237 #ifdef CONFIG_PMCTWILED 240 238 /*