Skip to content

Commit 46859ac

Browse files
committed
LoongArch: Add multi-processor (SMP) support
LoongArch-based procesors have 4, 8 or 16 cores per package. This patch adds multi-processor (SMP) support for LoongArch. Reviewed-by: WANG Xuerui <[email protected]> Reviewed-by: Jiaxun Yang <[email protected]> Signed-off-by: Huacai Chen <[email protected]>
1 parent c6b99be commit 46859ac

27 files changed

+1550
-10
lines changed

arch/loongarch/Kconfig

Lines changed: 39 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,6 +64,7 @@ config LOONGARCH
6464
select GENERIC_LIB_UCMPDI2
6565
select GENERIC_PCI_IOMAP
6666
select GENERIC_SCHED_CLOCK
67+
select GENERIC_SMP_IDLE_THREAD
6768
select GENERIC_TIME_VSYSCALL
6869
select GPIOLIB
6970
select HAVE_ARCH_AUDITSYSCALL
@@ -92,7 +93,7 @@ config LOONGARCH
9293
select HAVE_RSEQ
9394
select HAVE_SYSCALL_TRACEPOINTS
9495
select HAVE_TIF_NOHZ
95-
select HAVE_VIRT_CPU_ACCOUNTING_GEN
96+
select HAVE_VIRT_CPU_ACCOUNTING_GEN if !SMP
9697
select IRQ_FORCED_THREADING
9798
select IRQ_LOONGARCH_CPU
9899
select MODULES_USE_ELF_RELA if MODULES
@@ -297,6 +298,43 @@ config EFI
297298
This enables the kernel to use EFI runtime services that are
298299
available (such as the EFI variable services).
299300

301+
config SMP
302+
bool "Multi-Processing support"
303+
help
304+
This enables support for systems with more than one CPU. If you have
305+
a system with only one CPU, say N. If you have a system with more
306+
than one CPU, say Y.
307+
308+
If you say N here, the kernel will run on uni- and multiprocessor
309+
machines, but will use only one CPU of a multiprocessor machine. If
310+
you say Y here, the kernel will run on many, but not all,
311+
uniprocessor machines. On a uniprocessor machine, the kernel
312+
will run faster if you say N here.
313+
314+
See also the SMP-HOWTO available at <http://www.tldp.org/docs.html#howto>.
315+
316+
If you don't know what to do here, say N.
317+
318+
config HOTPLUG_CPU
319+
bool "Support for hot-pluggable CPUs"
320+
depends on SMP
321+
select GENERIC_IRQ_MIGRATION
322+
help
323+
Say Y here to allow turning CPUs off and on. CPUs can be
324+
controlled through /sys/devices/system/cpu.
325+
(Note: power management support will enable this option
326+
automatically on SMP systems. )
327+
Say N if you want to disable CPU hotplug.
328+
329+
config NR_CPUS
330+
int "Maximum number of CPUs (2-256)"
331+
range 2 256
332+
depends on SMP
333+
default "64"
334+
help
335+
This allows you to specify the maximum number of CPUs which this
336+
kernel will support.
337+
300338
config FORCE_MAX_ZONEORDER
301339
int "Maximum zone order"
302340
range 14 64 if PAGE_SIZE_64KB

arch/loongarch/include/asm/atomic.h

Lines changed: 4 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -162,6 +162,7 @@ static inline int arch_atomic_sub_if_positive(int i, atomic_t *v)
162162
" sc.w %1, %2 \n"
163163
" beq $zero, %1, 1b \n"
164164
"2: \n"
165+
__WEAK_LLSC_MB
165166
: "=&r" (result), "=&r" (temp),
166167
"+" GCC_OFF_SMALL_ASM() (v->counter)
167168
: "I" (-i));
@@ -174,6 +175,7 @@ static inline int arch_atomic_sub_if_positive(int i, atomic_t *v)
174175
" sc.w %1, %2 \n"
175176
" beq $zero, %1, 1b \n"
176177
"2: \n"
178+
__WEAK_LLSC_MB
177179
: "=&r" (result), "=&r" (temp),
178180
"+" GCC_OFF_SMALL_ASM() (v->counter)
179181
: "r" (i));
@@ -323,6 +325,7 @@ static inline long arch_atomic64_sub_if_positive(long i, atomic64_t *v)
323325
" sc.d %1, %2 \n"
324326
" beq %1, $zero, 1b \n"
325327
"2: \n"
328+
__WEAK_LLSC_MB
326329
: "=&r" (result), "=&r" (temp),
327330
"+" GCC_OFF_SMALL_ASM() (v->counter)
328331
: "I" (-i));
@@ -335,6 +338,7 @@ static inline long arch_atomic64_sub_if_positive(long i, atomic64_t *v)
335338
" sc.d %1, %2 \n"
336339
" beq %1, $zero, 1b \n"
337340
"2: \n"
341+
__WEAK_LLSC_MB
338342
: "=&r" (result), "=&r" (temp),
339343
"+" GCC_OFF_SMALL_ASM() (v->counter)
340344
: "r" (i));

arch/loongarch/include/asm/barrier.h

Lines changed: 108 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,19 @@
1818
#define mb() fast_mb()
1919
#define iob() fast_iob()
2020

21+
#define __smp_mb() __asm__ __volatile__("dbar 0" : : : "memory")
22+
#define __smp_rmb() __asm__ __volatile__("dbar 0" : : : "memory")
23+
#define __smp_wmb() __asm__ __volatile__("dbar 0" : : : "memory")
24+
25+
#ifdef CONFIG_SMP
26+
#define __WEAK_LLSC_MB " dbar 0 \n"
27+
#else
28+
#define __WEAK_LLSC_MB " \n"
29+
#endif
30+
31+
#define __smp_mb__before_atomic() barrier()
32+
#define __smp_mb__after_atomic() barrier()
33+
2134
/**
2235
* array_index_mask_nospec() - generate a ~0 mask when index < size, 0 otherwise
2336
* @index: array element index
@@ -46,6 +59,101 @@ static inline unsigned long array_index_mask_nospec(unsigned long index,
4659
return mask;
4760
}
4861

62+
#define __smp_load_acquire(p) \
63+
({ \
64+
union { typeof(*p) __val; char __c[1]; } __u; \
65+
unsigned long __tmp = 0; \
66+
compiletime_assert_atomic_type(*p); \
67+
switch (sizeof(*p)) { \
68+
case 1: \
69+
*(__u8 *)__u.__c = *(volatile __u8 *)p; \
70+
__smp_mb(); \
71+
break; \
72+
case 2: \
73+
*(__u16 *)__u.__c = *(volatile __u16 *)p; \
74+
__smp_mb(); \
75+
break; \
76+
case 4: \
77+
__asm__ __volatile__( \
78+
"amor_db.w %[val], %[tmp], %[mem] \n" \
79+
: [val] "=&r" (*(__u32 *)__u.__c) \
80+
: [mem] "ZB" (*(u32 *) p), [tmp] "r" (__tmp) \
81+
: "memory"); \
82+
break; \
83+
case 8: \
84+
__asm__ __volatile__( \
85+
"amor_db.d %[val], %[tmp], %[mem] \n" \
86+
: [val] "=&r" (*(__u64 *)__u.__c) \
87+
: [mem] "ZB" (*(u64 *) p), [tmp] "r" (__tmp) \
88+
: "memory"); \
89+
break; \
90+
} \
91+
(typeof(*p))__u.__val; \
92+
})
93+
94+
#define __smp_store_release(p, v) \
95+
do { \
96+
union { typeof(*p) __val; char __c[1]; } __u = \
97+
{ .__val = (__force typeof(*p)) (v) }; \
98+
unsigned long __tmp; \
99+
compiletime_assert_atomic_type(*p); \
100+
switch (sizeof(*p)) { \
101+
case 1: \
102+
__smp_mb(); \
103+
*(volatile __u8 *)p = *(__u8 *)__u.__c; \
104+
break; \
105+
case 2: \
106+
__smp_mb(); \
107+
*(volatile __u16 *)p = *(__u16 *)__u.__c; \
108+
break; \
109+
case 4: \
110+
__asm__ __volatile__( \
111+
"amswap_db.w %[tmp], %[val], %[mem] \n" \
112+
: [mem] "+ZB" (*(u32 *)p), [tmp] "=&r" (__tmp) \
113+
: [val] "r" (*(__u32 *)__u.__c) \
114+
: ); \
115+
break; \
116+
case 8: \
117+
__asm__ __volatile__( \
118+
"amswap_db.d %[tmp], %[val], %[mem] \n" \
119+
: [mem] "+ZB" (*(u64 *)p), [tmp] "=&r" (__tmp) \
120+
: [val] "r" (*(__u64 *)__u.__c) \
121+
: ); \
122+
break; \
123+
} \
124+
} while (0)
125+
126+
#define __smp_store_mb(p, v) \
127+
do { \
128+
union { typeof(p) __val; char __c[1]; } __u = \
129+
{ .__val = (__force typeof(p)) (v) }; \
130+
unsigned long __tmp; \
131+
switch (sizeof(p)) { \
132+
case 1: \
133+
*(volatile __u8 *)&p = *(__u8 *)__u.__c; \
134+
__smp_mb(); \
135+
break; \
136+
case 2: \
137+
*(volatile __u16 *)&p = *(__u16 *)__u.__c; \
138+
__smp_mb(); \
139+
break; \
140+
case 4: \
141+
__asm__ __volatile__( \
142+
"amswap_db.w %[tmp], %[val], %[mem] \n" \
143+
: [mem] "+ZB" (*(u32 *)&p), [tmp] "=&r" (__tmp) \
144+
: [val] "r" (*(__u32 *)__u.__c) \
145+
: ); \
146+
break; \
147+
case 8: \
148+
__asm__ __volatile__( \
149+
"amswap_db.d %[tmp], %[val], %[mem] \n" \
150+
: [mem] "+ZB" (*(u64 *)&p), [tmp] "=&r" (__tmp) \
151+
: [val] "r" (*(__u64 *)__u.__c) \
152+
: ); \
153+
break; \
154+
} \
155+
} while (0)
156+
49157
#include <asm-generic/barrier.h>
50158

51159
#endif /* __ASM_BARRIER_H */

arch/loongarch/include/asm/cmpxchg.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -59,6 +59,7 @@ static inline unsigned long __xchg(volatile void *ptr, unsigned long x,
5959
" " st " $t0, %1 \n" \
6060
" beq $zero, $t0, 1b \n" \
6161
"2: \n" \
62+
__WEAK_LLSC_MB \
6263
: "=&r" (__ret), "=ZB"(*m) \
6364
: "ZB"(*m), "Jr" (old), "Jr" (new) \
6465
: "t0", "memory"); \

arch/loongarch/include/asm/futex.h

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -86,6 +86,7 @@ futex_atomic_cmpxchg_inatomic(u32 *uval, u32 __user *uaddr, u32 oldval, u32 newv
8686
"2: sc.w $t0, %2 \n"
8787
" beq $zero, $t0, 1b \n"
8888
"3: \n"
89+
__WEAK_LLSC_MB
8990
" .section .fixup,\"ax\" \n"
9091
"4: li.d %0, %6 \n"
9192
" b 3b \n"

arch/loongarch/include/asm/hardirq.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -21,4 +21,6 @@ typedef struct {
2121

2222
DECLARE_PER_CPU_ALIGNED(irq_cpustat_t, irq_stat);
2323

24+
#define __ARCH_IRQ_STAT
25+
2426
#endif /* _ASM_HARDIRQ_H */

arch/loongarch/include/asm/irq.h

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -125,6 +125,8 @@ extern struct irq_domain *pch_lpc_domain;
125125
extern struct irq_domain *pch_msi_domain[MAX_IO_PICS];
126126
extern struct irq_domain *pch_pic_domain[MAX_IO_PICS];
127127

128+
extern irqreturn_t loongson3_ipi_interrupt(int irq, void *dev);
129+
128130
#include <asm-generic/irq.h>
129131

130132
#endif /* _ASM_IRQ_H */

0 commit comments

Comments
 (0)