From fc2ca674470bbfe11d72a20a3f19fd3dc43bfca0 Mon Sep 17 00:00:00 2001 From: Guenter Roeck Date: Sun, 30 Aug 2015 21:19:58 -0700 Subject: MIPS: Fix console output for Fulong2e system Commit 3adeb2566b9b ("MIPS: Loongson: Improve LEFI firmware interface") made the number of UARTs dynamic if LEFI_FIRMWARE_INTERFACE is configured. Unfortunately, it did not initialize the number of UARTs if LEFI_FIRMWARE_INTERFACE is not configured. As a result, the Fulong2e system has no console. Fixes: 3adeb2566b9b ("MIPS: Loongson: Improve LEFI firmware interface") Acked-by: Huacai Chen Signed-off-by: Guenter Roeck Tested-by: Markos Chandras Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/11076/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/loongson64/common/env.c b/arch/mips/loongson64/common/env.c index f6c44dd..d6d07ad 100644 --- a/arch/mips/loongson64/common/env.c +++ b/arch/mips/loongson64/common/env.c @@ -64,6 +64,9 @@ void __init prom_init_env(void) } if (memsize == 0) memsize = 256; + + loongson_sysconf.nr_uarts = 1; + pr_info("memsize=%u, highmemsize=%u\n", memsize, highmemsize); #else struct boot_params *boot_p; -- cgit v0.10.2 From 88d3426942d748b90b051b7ef2d5d765f5f3054c Mon Sep 17 00:00:00 2001 From: Alexander Sverdlin Date: Thu, 3 Sep 2015 08:36:35 +0200 Subject: MIPS: bootmem: Fix mapstart calculation for contiguous maps Commit a6335fa1 fixed the case with gap between initrd and next usable PFN zone, but broken the case when initrd is combined with usable memory into one region (in add_memory_region()). Restore the fixup initially brought in by f9a7febd. ---- error message ---- Unpacking initramfs... Initramfs unpacking failed: junk in compressed archive BUG: Bad page state in process swapper pfn:00261 page:81004c20 count:0 mapcount:-127 mapping: (null) index:0x2 flags: 0x0() page dumped because: nonzero mapcount CPU: 0 PID: 1 Comm: swapper Not tainted 4.2.0+ #1782 ----------------------- Signed-off-by: Alexander Sverdlin Reported-by: Tony Wu Tested-by: Tony Wu Cc: David Daney Cc: Zubair Lutfullah Kakakhel Cc: Huacai Chen Cc: Joe Perches Cc: Steven J. Hill Cc: Aaro Koskinen Cc: stable@vger.kernel.org Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/11086/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/kernel/setup.c b/arch/mips/kernel/setup.c index 35b8316..4795151 100644 --- a/arch/mips/kernel/setup.c +++ b/arch/mips/kernel/setup.c @@ -338,7 +338,7 @@ static void __init bootmem_init(void) if (end <= reserved_end) continue; #ifdef CONFIG_BLK_DEV_INITRD - /* mapstart should be after initrd_end */ + /* Skip zones before initrd and initrd itself */ if (initrd_end && end <= (unsigned long)PFN_UP(__pa(initrd_end))) continue; #endif @@ -371,6 +371,14 @@ static void __init bootmem_init(void) max_low_pfn = PFN_DOWN(HIGHMEM_START); } +#ifdef CONFIG_BLK_DEV_INITRD + /* + * mapstart should be after initrd_end + */ + if (initrd_end) + mapstart = max(mapstart, (unsigned long)PFN_UP(__pa(initrd_end))); +#endif + /* * Initialize the boot-time allocator with low memory only. */ -- cgit v0.10.2 From faa9724a674e5e52316bb0d173aed16bd17d536c Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sat, 5 Sep 2015 18:46:56 +0200 Subject: MIPS: BPF: Avoid unreachable code on little endian On little endian, avoid generating the big endian version of the code by using #else in addition to #ifdef #endif. Also fix one alignment issue wrt delay slot. Signed-off-by: Aurelien Jarno Reviewed-by: Markos Chandras Cc: stable@vger.kernel.org # v4.2+ Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/11097/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/net/bpf_jit_asm.S b/arch/mips/net/bpf_jit_asm.S index e927260..4f54cb1 100644 --- a/arch/mips/net/bpf_jit_asm.S +++ b/arch/mips/net/bpf_jit_asm.S @@ -151,9 +151,10 @@ NESTED(bpf_slow_path_word, (6 * SZREG), $r_sp) wsbh t0, $r_s0 jr $r_ra rotr $r_A, t0, 16 -#endif +#else jr $r_ra - move $r_A, $r_s0 + move $r_A, $r_s0 +#endif END(bpf_slow_path_word) @@ -162,9 +163,10 @@ NESTED(bpf_slow_path_half, (6 * SZREG), $r_sp) #ifdef CONFIG_CPU_LITTLE_ENDIAN jr $r_ra wsbh $r_A, $r_s0 -#endif +#else jr $r_ra move $r_A, $r_s0 +#endif END(bpf_slow_path_half) -- cgit v0.10.2 From b259e51f2e29390518021f9b8df55a3de42f371b Mon Sep 17 00:00:00 2001 From: Aurelien Jarno Date: Sat, 5 Sep 2015 18:46:57 +0200 Subject: MIPS: BPF: Fix build on pre-R2 little endian CPUs The rotr, seh and wsbh instructions have been introduced with the R2 ISA. Thus the current BPF code fails to build on pre-R2 little endian CPUs: CC arch/mips/net/bpf_jit.o AS arch/mips/net/bpf_jit_asm.o /home/aurel32/linux-4.2/arch/mips/net/bpf_jit_asm.S: Assembler messages: /home/aurel32/linux-4.2/arch/mips/net/bpf_jit_asm.S:67: Error: opcode not supported on this processor: mips32 (mips32) `wsbh $8,$19' /home/aurel32/linux-4.2/arch/mips/net/bpf_jit_asm.S:68: Error: opcode not supported on this processor: mips32 (mips32) `rotr $19,$8,16' /home/aurel32/linux-4.2/arch/mips/net/bpf_jit_asm.S:83: Error: opcode not supported on this processor: mips32 (mips32) `wsbh $8,$19' /home/aurel32/linux-4.2/arch/mips/net/bpf_jit_asm.S:84: Error: opcode not supported on this processor: mips32 (mips32) `seh $19,$8' /home/aurel32/linux-4.2/arch/mips/net/bpf_jit_asm.S:151: Error: opcode not supported on this processor: mips32 (mips32) `wsbh $8,$12' /home/aurel32/linux-4.2/arch/mips/net/bpf_jit_asm.S:153: Error: opcode not supported on this processor: mips32 (mips32) `rotr $19,$8,16' /home/aurel32/linux-4.2/arch/mips/net/bpf_jit_asm.S:164: Error: opcode not supported on this processor: mips32 (mips32) `wsbh $19,$12' /home/aurel32/linux-4.2/scripts/Makefile.build:294: recipe for target 'arch/mips/net/bpf_jit_asm.o' failed Fix that by providing equivalent code for these CPUs. Signed-off-by: Aurelien Jarno Reviewed-by: Markos Chandras Cc: stable@vger.kernel.org # v4.2+ Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/11098/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/net/bpf_jit_asm.S b/arch/mips/net/bpf_jit_asm.S index 4f54cb1..dabf417 100644 --- a/arch/mips/net/bpf_jit_asm.S +++ b/arch/mips/net/bpf_jit_asm.S @@ -64,8 +64,20 @@ sk_load_word_positive: PTR_ADDU t1, $r_skb_data, offset lw $r_A, 0(t1) #ifdef CONFIG_CPU_LITTLE_ENDIAN +# if defined(__mips_isa_rev) && (__mips_isa_rev >= 2) wsbh t0, $r_A rotr $r_A, t0, 16 +# else + sll t0, $r_A, 24 + srl t1, $r_A, 24 + srl t2, $r_A, 8 + or t0, t0, t1 + andi t2, t2, 0xff00 + andi t1, $r_A, 0xff00 + or t0, t0, t2 + sll t1, t1, 8 + or $r_A, t0, t1 +# endif #endif jr $r_ra move $r_ret, zero @@ -80,8 +92,16 @@ sk_load_half_positive: PTR_ADDU t1, $r_skb_data, offset lh $r_A, 0(t1) #ifdef CONFIG_CPU_LITTLE_ENDIAN +# if defined(__mips_isa_rev) && (__mips_isa_rev >= 2) wsbh t0, $r_A seh $r_A, t0 +# else + sll t0, $r_A, 24 + andi t1, $r_A, 0xff00 + sra t0, t0, 16 + srl t1, t1, 8 + or $r_A, t0, t1 +# endif #endif jr $r_ra move $r_ret, zero @@ -148,9 +168,22 @@ sk_load_byte_positive: NESTED(bpf_slow_path_word, (6 * SZREG), $r_sp) bpf_slow_path_common(4) #ifdef CONFIG_CPU_LITTLE_ENDIAN +# if defined(__mips_isa_rev) && (__mips_isa_rev >= 2) wsbh t0, $r_s0 jr $r_ra rotr $r_A, t0, 16 +# else + sll t0, $r_s0, 24 + srl t1, $r_s0, 24 + srl t2, $r_s0, 8 + or t0, t0, t1 + andi t2, t2, 0xff00 + andi t1, $r_s0, 0xff00 + or t0, t0, t2 + sll t1, t1, 8 + jr $r_ra + or $r_A, t0, t1 +# endif #else jr $r_ra move $r_A, $r_s0 @@ -161,8 +194,17 @@ NESTED(bpf_slow_path_word, (6 * SZREG), $r_sp) NESTED(bpf_slow_path_half, (6 * SZREG), $r_sp) bpf_slow_path_common(2) #ifdef CONFIG_CPU_LITTLE_ENDIAN +# if defined(__mips_isa_rev) && (__mips_isa_rev >= 2) jr $r_ra wsbh $r_A, $r_s0 +# else + sll t0, $r_s0, 8 + andi t1, $r_s0, 0xff00 + andi t0, t0, 0xff00 + srl t1, t1, 8 + jr $r_ra + or $r_A, t0, t1 +# endif #else jr $r_ra move $r_A, $r_s0 -- cgit v0.10.2 From 84dedd71cf3bc61cc65ca43a48f7252344a1bb68 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Sat, 19 Sep 2015 06:26:19 +0200 Subject: MIPS: ATH79: Set missing irq ack handler for ar7100-misc-intc irq chip The irq ack handler was forgotten while introducing OF support. Only ar71xx and ar933x based devices require it. Signed-off-by: Alexander Couzens Acked-by: Alban Bedel Acked-by: Thomas Gleixner Cc: linux-mips@linux-mips.org Cc: Rob Herring Cc: Pawel Moll Cc: Mark Rutland Cc: Ian Campbell Cc: Kumar Gala Cc: devicetree@vger.kernel.org Cc: Jason Cooper Cc: Marc Zyngier Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/11163/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/ath79/irq.c b/arch/mips/ath79/irq.c index 15ecb48..bf1651c 100644 --- a/arch/mips/ath79/irq.c +++ b/arch/mips/ath79/irq.c @@ -293,8 +293,16 @@ static int __init ath79_misc_intc_of_init( return 0; } -IRQCHIP_DECLARE(ath79_misc_intc, "qca,ar7100-misc-intc", - ath79_misc_intc_of_init); + +static int __init ar7100_misc_intc_of_init( + struct device_node *node, struct device_node *parent) +{ + ath79_misc_irq_chip.irq_mask_ack = ar71xx_misc_irq_mask; + return ath79_misc_intc_of_init(node, parent); +} + +IRQCHIP_DECLARE(ar7100_misc_intc, "qca,ar7100-misc-intc", + ar7100_misc_intc_of_init); static int __init ar79_cpu_intc_of_init( struct device_node *node, struct device_node *parent) -- cgit v0.10.2 From 19446da415e0f01d56364b700fe984cda78bca50 Mon Sep 17 00:00:00 2001 From: Alexander Couzens Date: Sat, 19 Sep 2015 06:26:20 +0200 Subject: MIPS: ATH79: Add irq chip ar7240-misc-intc The ar7240 misc irq chip use ack handler instead of ack_mask handler. All new ath79 chips use the ar7240 misc irq chip Signed-off-by: Alexander Couzens Acked-by: Alban Bedel Acked-by: Thomas Gleixner Cc: linux-mips@linux-mips.org Cc: Rob Herring Cc: Pawel Moll Cc: Mark Rutland Cc: Ian Campbell Cc: Kumar Gala Cc: devicetree@vger.kernel.org Cc: Jason Cooper Cc: Marc Zyngier Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/11164/ Signed-off-by: Ralf Baechle diff --git a/Documentation/devicetree/bindings/interrupt-controller/qca,ath79-misc-intc.txt b/Documentation/devicetree/bindings/interrupt-controller/qca,ath79-misc-intc.txt index 391717a..ec96b1f 100644 --- a/Documentation/devicetree/bindings/interrupt-controller/qca,ath79-misc-intc.txt +++ b/Documentation/devicetree/bindings/interrupt-controller/qca,ath79-misc-intc.txt @@ -4,8 +4,8 @@ The MISC interrupt controller is a secondary controller for lower priority interrupt. Required Properties: -- compatible: has to be "qca,-cpu-intc", "qca,ar7100-misc-intc" - as fallback +- compatible: has to be "qca,-cpu-intc", "qca,ar7100-misc-intc" or + "qca,-cpu-intc", "qca,ar7240-misc-intc" - reg: Base address and size of the controllers memory area - interrupt-parent: phandle of the parent interrupt controller. - interrupts: Interrupt specifier for the controllers interrupt. @@ -13,6 +13,9 @@ Required Properties: - #interrupt-cells : Specifies the number of cells needed to encode interrupt source, should be 1 +Compatible fallback depends on the SoC. Use ar7100 for ar71xx and ar913x, +use ar7240 for all other SoCs. + Please refer to interrupts.txt in this directory for details of the common Interrupt Controllers bindings used by client devices. @@ -28,3 +31,16 @@ Example: interrupt-controller; #interrupt-cells = <1>; }; + +Another example: + + interrupt-controller@18060010 { + compatible = "qca,ar9331-misc-intc", qca,ar7240-misc-intc"; + reg = <0x18060010 0x4>; + + interrupt-parent = <&cpuintc>; + interrupts = <6>; + + interrupt-controller; + #interrupt-cells = <1>; + }; diff --git a/arch/mips/ath79/irq.c b/arch/mips/ath79/irq.c index bf1651c..eeb3953 100644 --- a/arch/mips/ath79/irq.c +++ b/arch/mips/ath79/irq.c @@ -304,6 +304,16 @@ static int __init ar7100_misc_intc_of_init( IRQCHIP_DECLARE(ar7100_misc_intc, "qca,ar7100-misc-intc", ar7100_misc_intc_of_init); +static int __init ar7240_misc_intc_of_init( + struct device_node *node, struct device_node *parent) +{ + ath79_misc_irq_chip.irq_ack = ar724x_misc_irq_ack; + return ath79_misc_intc_of_init(node, parent); +} + +IRQCHIP_DECLARE(ar7240_misc_intc, "qca,ar7240-misc-intc", + ar7240_misc_intc_of_init); + static int __init ar79_cpu_intc_of_init( struct device_node *node, struct device_node *parent) { -- cgit v0.10.2 From 2f6f31363cb7890784458d7805140687b4de5b59 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Thu, 17 Sep 2015 17:49:20 +0100 Subject: MIPS: cpu-features: Add cpu_has_ftlb Add cpu_has_ftlb, which specifies that an FTLB is present in addition to the VTLB, probed based on whether Config.MT == 4 (rather than 1 for standard JTLB). This is necessary since MIPS release 6 removes Config4.MMUExtDef, so the presence of the FTLB fields in Config4 must be determined from Config.MT instead. Signed-off-by: James Hogan Cc: Markos Chandras Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/11159/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/cpu-features.h b/arch/mips/include/asm/cpu-features.h index 9801ac9..fe67f12 100644 --- a/arch/mips/include/asm/cpu-features.h +++ b/arch/mips/include/asm/cpu-features.h @@ -20,6 +20,9 @@ #ifndef cpu_has_tlb #define cpu_has_tlb (cpu_data[0].options & MIPS_CPU_TLB) #endif +#ifndef cpu_has_ftlb +#define cpu_has_ftlb (cpu_data[0].options & MIPS_CPU_FTLB) +#endif #ifndef cpu_has_tlbinv #define cpu_has_tlbinv (cpu_data[0].options & MIPS_CPU_TLBINV) #endif diff --git a/arch/mips/include/asm/cpu.h b/arch/mips/include/asm/cpu.h index cd89e98..82ad15f 100644 --- a/arch/mips/include/asm/cpu.h +++ b/arch/mips/include/asm/cpu.h @@ -385,6 +385,7 @@ enum cpu_type_enum { #define MIPS_CPU_CDMM 0x4000000000ull /* CPU has Common Device Memory Map */ #define MIPS_CPU_BP_GHIST 0x8000000000ull /* R12K+ Branch Prediction Global History */ #define MIPS_CPU_SP 0x10000000000ull /* Small (1KB) page support */ +#define MIPS_CPU_FTLB 0x20000000000ull /* CPU has Fixed-page-size TLB */ /* * CPU ASE encodings diff --git a/arch/mips/include/asm/mipsregs.h b/arch/mips/include/asm/mipsregs.h index d3cd8ea..c64781c 100644 --- a/arch/mips/include/asm/mipsregs.h +++ b/arch/mips/include/asm/mipsregs.h @@ -487,6 +487,8 @@ /* Bits specific to the MIPS32/64 PRA. */ #define MIPS_CONF_MT (_ULCAST_(7) << 7) +#define MIPS_CONF_MT_TLB (_ULCAST_(1) << 7) +#define MIPS_CONF_MT_FTLB (_ULCAST_(4) << 7) #define MIPS_CONF_AR (_ULCAST_(7) << 10) #define MIPS_CONF_AT (_ULCAST_(3) << 13) #define MIPS_CONF_M (_ULCAST_(1) << 31) diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 571a8e6..397551c 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -410,16 +410,18 @@ static int set_ftlb_enable(struct cpuinfo_mips *c, int enable) static inline unsigned int decode_config0(struct cpuinfo_mips *c) { unsigned int config0; - int isa; + int isa, mt; config0 = read_c0_config(); /* * Look for Standard TLB or Dual VTLB and FTLB */ - if ((((config0 & MIPS_CONF_MT) >> 7) == 1) || - (((config0 & MIPS_CONF_MT) >> 7) == 4)) + mt = config0 & MIPS_CONF_MT; + if (mt == MIPS_CONF_MT_TLB) c->options |= MIPS_CPU_TLB; + else if (mt == MIPS_CONF_MT_FTLB) + c->options |= MIPS_CPU_TLB | MIPS_CPU_FTLB; isa = (config0 & MIPS_CONF_AT) >> 13; switch (isa) { -- cgit v0.10.2 From 43d104db596977a8fddc1e71245859a7fe85a658 Mon Sep 17 00:00:00 2001 From: James Hogan Date: Thu, 17 Sep 2015 17:49:21 +0100 Subject: MIPS: Fix FTLB detection for R6 R6 removed the Config4.MMUExtDef field, with the low 16 bits only allowed to contain FTLB fields, and commit e87569cd6c57 ("MIPS: cpu-probe: Fix VTLB/FTLB configuration for R6") updated the probing of this field to assume an FTLB is always present for R6. However the FTLB may still be absent. The presence of those fields is actually specified by the MMU type in the Config.MT field, so use that (the new cpu_has_ftlb) to determine whether the FTLB is actually present. Fixes: e87569cd6c57 ("MIPS: cpu-probe: Fix VTLB/FTLB configuration for R6") Signed-off-by: James Hogan Cc: Ralf Baechle Cc: Markos Chandras Cc: linux-mips@linux-mips.org Patchwork: https://patchwork.linux-mips.org/patch/11160/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/kernel/cpu-probe.c b/arch/mips/kernel/cpu-probe.c index 397551c..09a51d0 100644 --- a/arch/mips/kernel/cpu-probe.c +++ b/arch/mips/kernel/cpu-probe.c @@ -561,15 +561,18 @@ static inline unsigned int decode_config4(struct cpuinfo_mips *c) if (cpu_has_tlb) { if (((config4 & MIPS_CONF4_IE) >> 29) == 2) c->options |= MIPS_CPU_TLBINV; + /* - * This is a bit ugly. R6 has dropped that field from - * config4 and the only valid configuration is VTLB+FTLB so - * set a good value for mmuextdef for that case. + * R6 has dropped the MMUExtDef field from config4. + * On R6 the fields always describe the FTLB, and only if it is + * present according to Config.MT. */ - if (cpu_has_mips_r6) + if (!cpu_has_mips_r6) + mmuextdef = config4 & MIPS_CONF4_MMUEXTDEF; + else if (cpu_has_ftlb) mmuextdef = MIPS_CONF4_MMUEXTDEF_VTLBSIZEEXT; else - mmuextdef = config4 & MIPS_CONF4_MMUEXTDEF; + mmuextdef = 0; switch (mmuextdef) { case MIPS_CONF4_MMUEXTDEF_MMUSIZEEXT: -- cgit v0.10.2 From 7573b94e08aeb5b814e2f277210bdcdf21a83869 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 22 Sep 2015 11:29:09 -0700 Subject: MIPS: CM: Provide a function to map from CPU to VP ID. The VP ID of a given CPU may not match up with the CPU number used by Linux. For example, if the width of the VP part of the VP ID is wider than log2(number of VPs per core) and the system has multiple cores then this will be the case. Alternatively, if a pre-r6 system implements the MT ASE with multiple VPEs per core and Linux is built without support for the MT ASE then the numbers won't match up either. Provide a function to convert from CPU number to VP ID. Signed-off-by: Paul Burton Acked-by: Thomas Gleixner Cc: linux-mips@linux-mips.org Cc: linux-kernel@vger.kernel.org Cc: James Hogan Cc: Markos Chandras Patchwork: https://patchwork.linux-mips.org/patch/11211/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/include/asm/mips-cm.h b/arch/mips/include/asm/mips-cm.h index d75b75e..1f1927a 100644 --- a/arch/mips/include/asm/mips-cm.h +++ b/arch/mips/include/asm/mips-cm.h @@ -194,6 +194,7 @@ BUILD_CM_RW(reg3_mask, MIPS_CM_GCB_OFS + 0xc8) BUILD_CM_R_(gic_status, MIPS_CM_GCB_OFS + 0xd0) BUILD_CM_R_(cpc_status, MIPS_CM_GCB_OFS + 0xf0) BUILD_CM_RW(l2_config, MIPS_CM_GCB_OFS + 0x130) +BUILD_CM_RW(sys_config2, MIPS_CM_GCB_OFS + 0x150) /* Core Local & Core Other register accessor functions */ BUILD_CM_Cx_RW(reset_release, 0x00) @@ -316,6 +317,10 @@ BUILD_CM_Cx_R_(tcid_8_priority, 0x80) #define CM_GCR_L2_CONFIG_ASSOC_SHF 0 #define CM_GCR_L2_CONFIG_ASSOC_MSK (_ULCAST_(0xff) << 0) +/* GCR_SYS_CONFIG2 register fields */ +#define CM_GCR_SYS_CONFIG2_MAXVPW_SHF 0 +#define CM_GCR_SYS_CONFIG2_MAXVPW_MSK (_ULCAST_(0xf) << 0) + /* GCR_Cx_COHERENCE register fields */ #define CM_GCR_Cx_COHERENCE_COHDOMAINEN_SHF 0 #define CM_GCR_Cx_COHERENCE_COHDOMAINEN_MSK (_ULCAST_(0xff) << 0) @@ -405,4 +410,38 @@ static inline int mips_cm_revision(void) return read_gcr_rev(); } +/** + * mips_cm_max_vp_width() - return the width in bits of VP indices + * + * Return: the width, in bits, of VP indices in fields that combine core & VP + * indices. + */ +static inline unsigned int mips_cm_max_vp_width(void) +{ + extern int smp_num_siblings; + + if (mips_cm_revision() >= CM_REV_CM3) + return read_gcr_sys_config2() & CM_GCR_SYS_CONFIG2_MAXVPW_MSK; + + return smp_num_siblings; +} + +/** + * mips_cm_vp_id() - calculate the hardware VP ID for a CPU + * @cpu: the CPU whose VP ID to calculate + * + * Hardware such as the GIC uses identifiers for VPs which may not match the + * CPU numbers used by Linux. This function calculates the hardware VP + * identifier corresponding to a given CPU. + * + * Return: the VP ID for the CPU. + */ +static inline unsigned int mips_cm_vp_id(unsigned int cpu) +{ + unsigned int core = cpu_data[cpu].core; + unsigned int vp = cpu_vpe_id(&cpu_data[cpu]); + + return (core * mips_cm_max_vp_width()) + vp; +} + #endif /* __MIPS_ASM_MIPS_CM_H__ */ -- cgit v0.10.2 From ab41f6c8620a6e65df4ee19d284c97efdd3d9b63 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 22 Sep 2015 11:29:10 -0700 Subject: irqchip: mips-gic: Convert CPU numbers to VP IDs. Make use of the mips_cm_vp_id function to convert from Linux CPU numbers to the VP IDs used by hardware, which are not identical in all systems. Without doing so we map interrupts to incorrect VP(E)s. Signed-off-by: Paul Burton Acked-by: Thomas Gleixner Cc: linux-mips@linux-mips.org Cc: Paul Burton Cc: Marc Zyngier Cc: Jason Cooper Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/11212/ Signed-off-by: Ralf Baechle diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c index af2f16b..842a53d 100644 --- a/drivers/irqchip/irq-mips-gic.c +++ b/drivers/irqchip/irq-mips-gic.c @@ -426,7 +426,7 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *cpumask, spin_lock_irqsave(&gic_lock, flags); /* Re-route this IRQ */ - gic_map_to_vpe(irq, cpumask_first(&tmp)); + gic_map_to_vpe(irq, mips_cm_vp_id(cpumask_first(&tmp))); /* Update the pcpu_masks */ for (i = 0; i < NR_CPUS; i++) @@ -599,7 +599,7 @@ static __init void gic_ipi_init_one(unsigned int intr, int cpu, GIC_SHARED_TO_HWIRQ(intr)); int i; - gic_map_to_vpe(intr, cpu); + gic_map_to_vpe(intr, mips_cm_vp_id(cpu)); for (i = 0; i < NR_CPUS; i++) clear_bit(intr, pcpu_masks[i].pcpu_mask); set_bit(intr, pcpu_masks[cpu].pcpu_mask); -- cgit v0.10.2 From d77d5ac9c9b5abf45aeb6e12930fab832e5c81d1 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Tue, 22 Sep 2015 11:29:11 -0700 Subject: irqchip: mips-gic: Fix pending & mask reads for MIPS64 with 32b GIC. gic_handle_shared_int reads the GIC interrupt pending & mask registers directly into a bitmap, which is defined as an array of unsigned longs. The GIC pending registers may be 32 bits wide if the CM is older than CM3, regardless of the bit width of the CPU, but for MIPS64 kernels the unsigned longs in the bitmap will be 64 bits wide. In this case we need to perform 2 x 32 bit reads per 64 bit unsigned long in order to avoid missing interrupts. Signed-off-by: Paul Burton Acked-by: Thomas Gleixner Cc: linux-mips@linux-mips.org Cc: Marc Zyngier Cc: Jason Cooper Cc: linux-kernel@vger.kernel.org Patchwork: https://patchwork.linux-mips.org/patch/11213/ Signed-off-by: Ralf Baechle diff --git a/drivers/irqchip/irq-mips-gic.c b/drivers/irqchip/irq-mips-gic.c index 842a53d..aeaa061 100644 --- a/drivers/irqchip/irq-mips-gic.c +++ b/drivers/irqchip/irq-mips-gic.c @@ -320,6 +320,14 @@ static void gic_handle_shared_int(bool chained) intrmask[i] = gic_read(intrmask_reg); pending_reg += gic_reg_step; intrmask_reg += gic_reg_step; + + if (!config_enabled(CONFIG_64BIT) || mips_cm_is64) + continue; + + pending[i] |= (u64)gic_read(pending_reg) << 32; + intrmask[i] |= (u64)gic_read(intrmask_reg) << 32; + pending_reg += gic_reg_step; + intrmask_reg += gic_reg_step; } bitmap_and(pending, pending, intrmask, gic_shared_intrs); -- cgit v0.10.2 From def3ab5d0a0fe53026c2495b054dcc46cf923dac Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Fri, 25 Sep 2015 08:59:36 -0700 Subject: MIPS: mm: compile maar_init unconditionally maar_init was previously only compiled when CONFIG_NEED_MULTIPLE_NODES was not set, which has been fine since it is only called from the standard implementation of mem_init which has the same condition. In preparation for calling it from the SMP startup code on secondary CPUs, move maar_init outside of the #ifndef such that it is always compiled. Signed-off-by: Paul Burton Cc: Markos Chandras Cc: linux-mips@linux-mips.org Cc: Steven J. Hill Cc: David Hildenbrand Cc: linux-kernel@vger.kernel.org Cc: Ingo Molnar Patchwork: https://patchwork.linux-mips.org/patch/11237/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c index 66d0f49..074ac54 100644 --- a/arch/mips/mm/init.c +++ b/arch/mips/mm/init.c @@ -252,6 +252,69 @@ void __init fixrange_init(unsigned long start, unsigned long end, #endif } +unsigned __weak platform_maar_init(unsigned num_pairs) +{ + struct maar_config cfg[BOOT_MEM_MAP_MAX]; + unsigned i, num_configured, num_cfg = 0; + phys_addr_t skip; + + for (i = 0; i < boot_mem_map.nr_map; i++) { + switch (boot_mem_map.map[i].type) { + case BOOT_MEM_RAM: + case BOOT_MEM_INIT_RAM: + break; + default: + continue; + } + + skip = 0x10000 - (boot_mem_map.map[i].addr & 0xffff); + + cfg[num_cfg].lower = boot_mem_map.map[i].addr; + cfg[num_cfg].lower += skip; + + cfg[num_cfg].upper = cfg[num_cfg].lower; + cfg[num_cfg].upper += boot_mem_map.map[i].size - 1; + cfg[num_cfg].upper -= skip; + + cfg[num_cfg].attrs = MIPS_MAAR_S; + num_cfg++; + } + + num_configured = maar_config(cfg, num_cfg, num_pairs); + if (num_configured < num_cfg) + pr_warn("Not enough MAAR pairs (%u) for all bootmem regions (%u)\n", + num_pairs, num_cfg); + + return num_configured; +} + +static void maar_init(void) +{ + unsigned num_maars, used, i; + + if (!cpu_has_maar) + return; + + /* Detect the number of MAARs */ + write_c0_maari(~0); + back_to_back_c0_hazard(); + num_maars = read_c0_maari() + 1; + + /* MAARs should be in pairs */ + WARN_ON(num_maars % 2); + + /* Configure the required MAARs */ + used = platform_maar_init(num_maars / 2); + + /* Disable any further MAARs */ + for (i = (used * 2); i < num_maars; i++) { + write_c0_maari(i); + back_to_back_c0_hazard(); + write_c0_maar(0); + back_to_back_c0_hazard(); + } +} + #ifndef CONFIG_NEED_MULTIPLE_NODES int page_is_ram(unsigned long pagenr) { @@ -334,69 +397,6 @@ static inline void mem_init_free_highmem(void) #endif } -unsigned __weak platform_maar_init(unsigned num_pairs) -{ - struct maar_config cfg[BOOT_MEM_MAP_MAX]; - unsigned i, num_configured, num_cfg = 0; - phys_addr_t skip; - - for (i = 0; i < boot_mem_map.nr_map; i++) { - switch (boot_mem_map.map[i].type) { - case BOOT_MEM_RAM: - case BOOT_MEM_INIT_RAM: - break; - default: - continue; - } - - skip = 0x10000 - (boot_mem_map.map[i].addr & 0xffff); - - cfg[num_cfg].lower = boot_mem_map.map[i].addr; - cfg[num_cfg].lower += skip; - - cfg[num_cfg].upper = cfg[num_cfg].lower; - cfg[num_cfg].upper += boot_mem_map.map[i].size - 1; - cfg[num_cfg].upper -= skip; - - cfg[num_cfg].attrs = MIPS_MAAR_S; - num_cfg++; - } - - num_configured = maar_config(cfg, num_cfg, num_pairs); - if (num_configured < num_cfg) - pr_warn("Not enough MAAR pairs (%u) for all bootmem regions (%u)\n", - num_pairs, num_cfg); - - return num_configured; -} - -static void maar_init(void) -{ - unsigned num_maars, used, i; - - if (!cpu_has_maar) - return; - - /* Detect the number of MAARs */ - write_c0_maari(~0); - back_to_back_c0_hazard(); - num_maars = read_c0_maari() + 1; - - /* MAARs should be in pairs */ - WARN_ON(num_maars % 2); - - /* Configure the required MAARs */ - used = platform_maar_init(num_maars / 2); - - /* Disable any further MAARs */ - for (i = (used * 2); i < num_maars; i++) { - write_c0_maari(i); - back_to_back_c0_hazard(); - write_c0_maar(0); - back_to_back_c0_hazard(); - } -} - void __init mem_init(void) { #ifdef CONFIG_HIGHMEM -- cgit v0.10.2 From 651ca7f4dab77f07fdac9cfb68bcab6bd2b7f827 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Fri, 25 Sep 2015 08:59:37 -0700 Subject: MIPS: print MAAR configuration during boot Verifying that the MAAR configuration is as expected is useful when debugging the performance of a system. Print out the memory regions configured via MAAR along with their attributes. Signed-off-by: Paul Burton Cc: linux-mips@linux-mips.org Cc: Steven J. Hill Cc: David Hildenbrand Cc: linux-kernel@vger.kernel.org Cc: Peter Zijlstra (Intel) Patchwork: https://patchwork.linux-mips.org/patch/11238/ Signed-off-by: Ralf Baechle diff --git a/arch/mips/mm/init.c b/arch/mips/mm/init.c index 074ac54..023c164 100644 --- a/arch/mips/mm/init.c +++ b/arch/mips/mm/init.c @@ -291,6 +291,7 @@ unsigned __weak platform_maar_init(unsigned num_pairs) static void maar_init(void) { unsigned num_maars, used, i; + phys_addr_t lower, upper, attr; if (!cpu_has_maar) return; @@ -313,6 +314,34 @@ static void maar_init(void) write_c0_maar(0); back_to_back_c0_hazard(); } + + pr_info("MAAR configuration:\n"); + for (i = 0; i < num_maars; i += 2) { + write_c0_maari(i); + back_to_back_c0_hazard(); + upper = read_c0_maar(); + + write_c0_maari(i + 1); + back_to_back_c0_hazard(); + lower = read_c0_maar(); + + attr = lower & upper; + lower = (lower & MIPS_MAAR_ADDR) << 4; + upper = ((upper & MIPS_MAAR_ADDR) << 4) | 0xffff; + + pr_info(" [%d]: ", i / 2); + if (!(attr & MIPS_MAAR_V)) { + pr_cont("disabled\n"); + continue; + } + + pr_cont("%pa-%pa", &lower, &upper); + + if (attr & MIPS_MAAR_S) + pr_cont(" speculate"); + + pr_cont("\n"); + } } #ifndef CONFIG_NEED_MULTIPLE_NODES -- cgit v0.10.2 From e060f6ed281669b6d2f22d8dafd664b532386918 Mon Sep 17 00:00:00 2001 From: Paul Burton Date: Fri, 25 Sep 2015 08:59:38 -0700 Subject: 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 diff --git a/arch/mips/include/asm/maar.h b/arch/mips/include/asm/maar.h index b02891f..21d9607 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, } /** + * 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 * aligned to a 2^16 byte boundary. diff --git a/arch/mips/kernel/smp.c b/arch/mips/kernel/smp.c index a31896c..bd4385a 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 023c164..8770e61 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++; + } } } -- cgit v0.10.2