Skip to content

Commit e8b5060

Browse files
committed
Merge tag 'mips_fixes_5.0_3' of git://git.kernel.org/pub/scm/linux/kernel/git/mips/linux
Pull MIPS fixes from Paul Burton: "A batch of MIPS fixes for 5.0, nothing too scary. - A workaround for a Loongson 3 CPU bug is the biggest change, but still fairly straightforward. It adds extra memory barriers (sync instructions) around atomics to avoid a CPU bug that can break atomicity. - Loongson64 also sees a fix for powering off some systems which would incorrectly reboot rather than waiting for the power down sequence to complete. - We have DT fixes for the Ingenic JZ4740 SoC & the JZ4780-based Ci20 board, and a DT warning fix for the Nexsys4/MIPSfpga board. - The Cavium Octeon platform sees a further fix to the behaviour of the pcie_disable command line argument that was introduced in v3.3. - The VDSO, introduced in v4.4, sees build fixes for configurations of GCC that were built using the --with-fp-32= flag to specify a default 32-bit floating point ABI. - get_frame_info() sees a fix for configurations with CONFIG_KALLSYMS=n, for which it previously always returned an error. - If the MIPS Coherence Manager (CM) reports an error then we'll now clear that error correctly so that the GCR_ERROR_CAUSE register will be updated with information about any future errors" * tag 'mips_fixes_5.0_3' of git://git.kernel.org/pub/scm/linux/kernel/git/mips/linux: mips: cm: reprime error cause mips: loongson64: remove unreachable(), fix loongson_poweroff(). MIPS: Remove function size check in get_frame_info() MIPS: Use lower case for addresses in nexys4ddr.dts MIPS: Loongson: Introduce and use loongson_llsc_mb() MIPS: VDSO: Include $(ccflags-vdso) in o32,n32 .lds builds MIPS: VDSO: Use same -m%-float cflag as the kernel proper MIPS: OCTEON: don't set octeon_dma_bar_type if PCI is disabled DTS: CI20: Fix bugs in ci20's device tree. MIPS: DTS: jz4740: Correct interrupt number of DMA core
2 parents e5a8a11 + 05dc600 commit e8b5060

File tree

16 files changed

+127
-22
lines changed

16 files changed

+127
-22
lines changed

arch/mips/Kconfig

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1403,6 +1403,21 @@ config LOONGSON3_ENHANCEMENT
14031403
please say 'N' here. If you want a high-performance kernel to run on
14041404
new Loongson 3 machines only, please say 'Y' here.
14051405

1406+
config CPU_LOONGSON3_WORKAROUNDS
1407+
bool "Old Loongson 3 LLSC Workarounds"
1408+
default y if SMP
1409+
depends on CPU_LOONGSON3
1410+
help
1411+
Loongson 3 processors have the llsc issues which require workarounds.
1412+
Without workarounds the system may hang unexpectedly.
1413+
1414+
Newer Loongson 3 will fix these issues and no workarounds are needed.
1415+
The workarounds have no significant side effect on them but may
1416+
decrease the performance of the system so this option should be
1417+
disabled unless the kernel is intended to be run on old systems.
1418+
1419+
If unsure, please say Y.
1420+
14061421
config CPU_LOONGSON2E
14071422
bool "Loongson 2E"
14081423
depends on SYS_HAS_CPU_LOONGSON2E

arch/mips/boot/dts/ingenic/ci20.dts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -76,7 +76,7 @@
7676
status = "okay";
7777

7878
pinctrl-names = "default";
79-
pinctrl-0 = <&pins_uart2>;
79+
pinctrl-0 = <&pins_uart3>;
8080
};
8181

8282
&uart4 {
@@ -196,9 +196,9 @@
196196
bias-disable;
197197
};
198198

199-
pins_uart2: uart2 {
200-
function = "uart2";
201-
groups = "uart2-data", "uart2-hwflow";
199+
pins_uart3: uart3 {
200+
function = "uart3";
201+
groups = "uart3-data", "uart3-hwflow";
202202
bias-disable;
203203
};
204204

arch/mips/boot/dts/ingenic/jz4740.dtsi

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -161,7 +161,7 @@
161161
#dma-cells = <2>;
162162

163163
interrupt-parent = <&intc>;
164-
interrupts = <29>;
164+
interrupts = <20>;
165165

166166
clocks = <&cgu JZ4740_CLK_DMA>;
167167

arch/mips/boot/dts/xilfpga/nexys4ddr.dts

Lines changed: 4 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -90,11 +90,11 @@
9090
interrupts = <0>;
9191
};
9292

93-
axi_i2c: i2c@10A00000 {
93+
axi_i2c: i2c@10a00000 {
9494
compatible = "xlnx,xps-iic-2.00.a";
9595
interrupt-parent = <&axi_intc>;
9696
interrupts = <4>;
97-
reg = < 0x10A00000 0x10000 >;
97+
reg = < 0x10a00000 0x10000 >;
9898
clocks = <&ext>;
9999
xlnx,clk-freq = <0x5f5e100>;
100100
xlnx,family = "Artix7";
@@ -106,9 +106,9 @@
106106
#address-cells = <1>;
107107
#size-cells = <0>;
108108

109-
ad7420@4B {
109+
ad7420@4b {
110110
compatible = "adi,adt7420";
111-
reg = <0x4B>;
111+
reg = <0x4b>;
112112
};
113113
} ;
114114
};

arch/mips/include/asm/atomic.h

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -58,6 +58,7 @@ static __inline__ void atomic_##op(int i, atomic_t * v) \
5858
if (kernel_uses_llsc) { \
5959
int temp; \
6060
\
61+
loongson_llsc_mb(); \
6162
__asm__ __volatile__( \
6263
" .set push \n" \
6364
" .set "MIPS_ISA_LEVEL" \n" \
@@ -85,6 +86,7 @@ static __inline__ int atomic_##op##_return_relaxed(int i, atomic_t * v) \
8586
if (kernel_uses_llsc) { \
8687
int temp; \
8788
\
89+
loongson_llsc_mb(); \
8890
__asm__ __volatile__( \
8991
" .set push \n" \
9092
" .set "MIPS_ISA_LEVEL" \n" \
@@ -118,6 +120,7 @@ static __inline__ int atomic_fetch_##op##_relaxed(int i, atomic_t * v) \
118120
if (kernel_uses_llsc) { \
119121
int temp; \
120122
\
123+
loongson_llsc_mb(); \
121124
__asm__ __volatile__( \
122125
" .set push \n" \
123126
" .set "MIPS_ISA_LEVEL" \n" \
@@ -256,6 +259,7 @@ static __inline__ void atomic64_##op(long i, atomic64_t * v) \
256259
if (kernel_uses_llsc) { \
257260
long temp; \
258261
\
262+
loongson_llsc_mb(); \
259263
__asm__ __volatile__( \
260264
" .set push \n" \
261265
" .set "MIPS_ISA_LEVEL" \n" \
@@ -283,6 +287,7 @@ static __inline__ long atomic64_##op##_return_relaxed(long i, atomic64_t * v) \
283287
if (kernel_uses_llsc) { \
284288
long temp; \
285289
\
290+
loongson_llsc_mb(); \
286291
__asm__ __volatile__( \
287292
" .set push \n" \
288293
" .set "MIPS_ISA_LEVEL" \n" \
@@ -316,6 +321,7 @@ static __inline__ long atomic64_fetch_##op##_relaxed(long i, atomic64_t * v) \
316321
if (kernel_uses_llsc) { \
317322
long temp; \
318323
\
324+
loongson_llsc_mb(); \
319325
__asm__ __volatile__( \
320326
" .set push \n" \
321327
" .set "MIPS_ISA_LEVEL" \n" \

arch/mips/include/asm/barrier.h

Lines changed: 36 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -222,6 +222,42 @@
222222
#define __smp_mb__before_atomic() __smp_mb__before_llsc()
223223
#define __smp_mb__after_atomic() smp_llsc_mb()
224224

225+
/*
226+
* Some Loongson 3 CPUs have a bug wherein execution of a memory access (load,
227+
* store or pref) in between an ll & sc can cause the sc instruction to
228+
* erroneously succeed, breaking atomicity. Whilst it's unusual to write code
229+
* containing such sequences, this bug bites harder than we might otherwise
230+
* expect due to reordering & speculation:
231+
*
232+
* 1) A memory access appearing prior to the ll in program order may actually
233+
* be executed after the ll - this is the reordering case.
234+
*
235+
* In order to avoid this we need to place a memory barrier (ie. a sync
236+
* instruction) prior to every ll instruction, in between it & any earlier
237+
* memory access instructions. Many of these cases are already covered by
238+
* smp_mb__before_llsc() but for the remaining cases, typically ones in
239+
* which multiple CPUs may operate on a memory location but ordering is not
240+
* usually guaranteed, we use loongson_llsc_mb() below.
241+
*
242+
* This reordering case is fixed by 3A R2 CPUs, ie. 3A2000 models and later.
243+
*
244+
* 2) If a conditional branch exists between an ll & sc with a target outside
245+
* of the ll-sc loop, for example an exit upon value mismatch in cmpxchg()
246+
* or similar, then misprediction of the branch may allow speculative
247+
* execution of memory accesses from outside of the ll-sc loop.
248+
*
249+
* In order to avoid this we need a memory barrier (ie. a sync instruction)
250+
* at each affected branch target, for which we also use loongson_llsc_mb()
251+
* defined below.
252+
*
253+
* This case affects all current Loongson 3 CPUs.
254+
*/
255+
#ifdef CONFIG_CPU_LOONGSON3_WORKAROUNDS /* Loongson-3's LLSC workaround */
256+
#define loongson_llsc_mb() __asm__ __volatile__(__WEAK_LLSC_MB : : :"memory")
257+
#else
258+
#define loongson_llsc_mb() do { } while (0)
259+
#endif
260+
225261
#include <asm-generic/barrier.h>
226262

227263
#endif /* __ASM_BARRIER_H */

arch/mips/include/asm/bitops.h

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -69,6 +69,7 @@ static inline void set_bit(unsigned long nr, volatile unsigned long *addr)
6969
: "ir" (1UL << bit), GCC_OFF_SMALL_ASM() (*m));
7070
#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
7171
} else if (kernel_uses_llsc && __builtin_constant_p(bit)) {
72+
loongson_llsc_mb();
7273
do {
7374
__asm__ __volatile__(
7475
" " __LL "%0, %1 # set_bit \n"
@@ -79,6 +80,7 @@ static inline void set_bit(unsigned long nr, volatile unsigned long *addr)
7980
} while (unlikely(!temp));
8081
#endif /* CONFIG_CPU_MIPSR2 || CONFIG_CPU_MIPSR6 */
8182
} else if (kernel_uses_llsc) {
83+
loongson_llsc_mb();
8284
do {
8385
__asm__ __volatile__(
8486
" .set push \n"
@@ -123,6 +125,7 @@ static inline void clear_bit(unsigned long nr, volatile unsigned long *addr)
123125
: "ir" (~(1UL << bit)));
124126
#if defined(CONFIG_CPU_MIPSR2) || defined(CONFIG_CPU_MIPSR6)
125127
} else if (kernel_uses_llsc && __builtin_constant_p(bit)) {
128+
loongson_llsc_mb();
126129
do {
127130
__asm__ __volatile__(
128131
" " __LL "%0, %1 # clear_bit \n"
@@ -133,6 +136,7 @@ static inline void clear_bit(unsigned long nr, volatile unsigned long *addr)
133136
} while (unlikely(!temp));
134137
#endif /* CONFIG_CPU_MIPSR2 || CONFIG_CPU_MIPSR6 */
135138
} else if (kernel_uses_llsc) {
139+
loongson_llsc_mb();
136140
do {
137141
__asm__ __volatile__(
138142
" .set push \n"
@@ -193,6 +197,7 @@ static inline void change_bit(unsigned long nr, volatile unsigned long *addr)
193197
unsigned long *m = ((unsigned long *) addr) + (nr >> SZLONG_LOG);
194198
unsigned long temp;
195199

200+
loongson_llsc_mb();
196201
do {
197202
__asm__ __volatile__(
198203
" .set push \n"

arch/mips/include/asm/futex.h

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -50,6 +50,7 @@
5050
"i" (-EFAULT) \
5151
: "memory"); \
5252
} else if (cpu_has_llsc) { \
53+
loongson_llsc_mb(); \
5354
__asm__ __volatile__( \
5455
" .set push \n" \
5556
" .set noat \n" \
@@ -163,6 +164,7 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
163164
"i" (-EFAULT)
164165
: "memory");
165166
} else if (cpu_has_llsc) {
167+
loongson_llsc_mb();
166168
__asm__ __volatile__(
167169
"# futex_atomic_cmpxchg_inatomic \n"
168170
" .set push \n"
@@ -192,6 +194,7 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr,
192194
: GCC_OFF_SMALL_ASM() (*uaddr), "Jr" (oldval), "Jr" (newval),
193195
"i" (-EFAULT)
194196
: "memory");
197+
loongson_llsc_mb();
195198
} else
196199
return -ENOSYS;
197200

arch/mips/include/asm/pgtable.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -228,6 +228,7 @@ static inline void set_pte(pte_t *ptep, pte_t pteval)
228228
: [buddy] "+m" (buddy->pte), [tmp] "=&r" (tmp)
229229
: [global] "r" (page_global));
230230
} else if (kernel_uses_llsc) {
231+
loongson_llsc_mb();
231232
__asm__ __volatile__ (
232233
" .set push \n"
233234
" .set "MIPS_ISA_ARCH_LEVEL" \n"
@@ -242,6 +243,7 @@ static inline void set_pte(pte_t *ptep, pte_t pteval)
242243
" .set pop \n"
243244
: [buddy] "+m" (buddy->pte), [tmp] "=&r" (tmp)
244245
: [global] "r" (page_global));
246+
loongson_llsc_mb();
245247
}
246248
#else /* !CONFIG_SMP */
247249
if (pte_none(*buddy))

arch/mips/kernel/mips-cm.c

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -457,5 +457,5 @@ void mips_cm_error_report(void)
457457
}
458458

459459
/* reprime cause register */
460-
write_gcr_error_cause(0);
460+
write_gcr_error_cause(cm_error);
461461
}

arch/mips/kernel/process.c

Lines changed: 3 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -371,7 +371,7 @@ static inline int is_sp_move_ins(union mips_instruction *ip, int *frame_size)
371371
static int get_frame_info(struct mips_frame_info *info)
372372
{
373373
bool is_mmips = IS_ENABLED(CONFIG_CPU_MICROMIPS);
374-
union mips_instruction insn, *ip, *ip_end;
374+
union mips_instruction insn, *ip;
375375
const unsigned int max_insns = 128;
376376
unsigned int last_insn_size = 0;
377377
unsigned int i;
@@ -384,10 +384,9 @@ static int get_frame_info(struct mips_frame_info *info)
384384
if (!ip)
385385
goto err;
386386

387-
ip_end = (void *)ip + info->func_size;
388-
389-
for (i = 0; i < max_insns && ip < ip_end; i++) {
387+
for (i = 0; i < max_insns; i++) {
390388
ip = (void *)ip + last_insn_size;
389+
391390
if (is_mmips && mm_insn_16bit(ip->halfword[0])) {
392391
insn.word = ip->halfword[0] << 16;
393392
last_insn_size = 2;

arch/mips/loongson64/Platform

Lines changed: 23 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,29 @@ ifdef CONFIG_CPU_LOONGSON2F_WORKAROUNDS
2323
endif
2424

2525
cflags-$(CONFIG_CPU_LOONGSON3) += -Wa,--trap
26+
27+
#
28+
# Some versions of binutils, not currently mainline as of 2019/02/04, support
29+
# an -mfix-loongson3-llsc flag which emits a sync prior to each ll instruction
30+
# to work around a CPU bug (see loongson_llsc_mb() in asm/barrier.h for a
31+
# description).
32+
#
33+
# We disable this in order to prevent the assembler meddling with the
34+
# instruction that labels refer to, ie. if we label an ll instruction:
35+
#
36+
# 1: ll v0, 0(a0)
37+
#
38+
# ...then with the assembler fix applied the label may actually point at a sync
39+
# instruction inserted by the assembler, and if we were using the label in an
40+
# exception table the table would no longer contain the address of the ll
41+
# instruction.
42+
#
43+
# Avoid this by explicitly disabling that assembler behaviour. If upstream
44+
# binutils does not merge support for the flag then we can revisit & remove
45+
# this later - for now it ensures vendor toolchains don't cause problems.
46+
#
47+
cflags-$(CONFIG_CPU_LOONGSON3) += $(call as-option,-Wa$(comma)-mno-fix-loongson3-llsc,)
48+
2649
#
2750
# binutils from v2.25 on and gcc starting from v4.9.0 treat -march=loongson3a
2851
# as MIPS64 R2; older versions as just R1. This leaves the possibility open

arch/mips/loongson64/common/reset.c

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -59,7 +59,12 @@ static void loongson_poweroff(void)
5959
{
6060
#ifndef CONFIG_LEFI_FIRMWARE_INTERFACE
6161
mach_prepare_shutdown();
62-
unreachable();
62+
63+
/*
64+
* It needs a wait loop here, but mips/kernel/reset.c already calls
65+
* a generic delay loop, machine_hang(), so simply return.
66+
*/
67+
return;
6368
#else
6469
void (*fw_poweroff)(void) = (void *)loongson_sysconf.poweroff_addr;
6570

arch/mips/mm/tlbex.c

Lines changed: 10 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -932,6 +932,8 @@ build_get_pgd_vmalloc64(u32 **p, struct uasm_label **l, struct uasm_reloc **r,
932932
* to mimic that here by taking a load/istream page
933933
* fault.
934934
*/
935+
if (IS_ENABLED(CONFIG_CPU_LOONGSON3_WORKAROUNDS))
936+
uasm_i_sync(p, 0);
935937
UASM_i_LA(p, ptr, (unsigned long)tlb_do_page_fault_0);
936938
uasm_i_jr(p, ptr);
937939

@@ -1646,6 +1648,8 @@ static void
16461648
iPTE_LW(u32 **p, unsigned int pte, unsigned int ptr)
16471649
{
16481650
#ifdef CONFIG_SMP
1651+
if (IS_ENABLED(CONFIG_CPU_LOONGSON3_WORKAROUNDS))
1652+
uasm_i_sync(p, 0);
16491653
# ifdef CONFIG_PHYS_ADDR_T_64BIT
16501654
if (cpu_has_64bits)
16511655
uasm_i_lld(p, pte, 0, ptr);
@@ -2259,6 +2263,8 @@ static void build_r4000_tlb_load_handler(void)
22592263
#endif
22602264

22612265
uasm_l_nopage_tlbl(&l, p);
2266+
if (IS_ENABLED(CONFIG_CPU_LOONGSON3_WORKAROUNDS))
2267+
uasm_i_sync(&p, 0);
22622268
build_restore_work_registers(&p);
22632269
#ifdef CONFIG_CPU_MICROMIPS
22642270
if ((unsigned long)tlb_do_page_fault_0 & 1) {
@@ -2313,6 +2319,8 @@ static void build_r4000_tlb_store_handler(void)
23132319
#endif
23142320

23152321
uasm_l_nopage_tlbs(&l, p);
2322+
if (IS_ENABLED(CONFIG_CPU_LOONGSON3_WORKAROUNDS))
2323+
uasm_i_sync(&p, 0);
23162324
build_restore_work_registers(&p);
23172325
#ifdef CONFIG_CPU_MICROMIPS
23182326
if ((unsigned long)tlb_do_page_fault_1 & 1) {
@@ -2368,6 +2376,8 @@ static void build_r4000_tlb_modify_handler(void)
23682376
#endif
23692377

23702378
uasm_l_nopage_tlbm(&l, p);
2379+
if (IS_ENABLED(CONFIG_CPU_LOONGSON3_WORKAROUNDS))
2380+
uasm_i_sync(&p, 0);
23712381
build_restore_work_registers(&p);
23722382
#ifdef CONFIG_CPU_MICROMIPS
23732383
if ((unsigned long)tlb_do_page_fault_1 & 1) {

arch/mips/pci/pci-octeon.c

Lines changed: 5 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -568,6 +568,11 @@ static int __init octeon_pci_setup(void)
568568
if (octeon_has_feature(OCTEON_FEATURE_PCIE))
569569
return 0;
570570

571+
if (!octeon_is_pci_host()) {
572+
pr_notice("Not in host mode, PCI Controller not initialized\n");
573+
return 0;
574+
}
575+
571576
/* Point pcibios_map_irq() to the PCI version of it */
572577
octeon_pcibios_map_irq = octeon_pci_pcibios_map_irq;
573578

@@ -579,11 +584,6 @@ static int __init octeon_pci_setup(void)
579584
else
580585
octeon_dma_bar_type = OCTEON_DMA_BAR_TYPE_BIG;
581586

582-
if (!octeon_is_pci_host()) {
583-
pr_notice("Not in host mode, PCI Controller not initialized\n");
584-
return 0;
585-
}
586-
587587
/* PCI I/O and PCI MEM values */
588588
set_io_port_base(OCTEON_PCI_IOSPACE_BASE);
589589
ioport_resource.start = 0;

0 commit comments

Comments
 (0)