2022-05-31 18:04:11 +08:00
|
|
|
/* SPDX-License-Identifier: GPL-2.0 */
|
|
|
|
/*
|
|
|
|
* Copyright (C) 2020-2022 Loongson Technology Corporation Limited
|
|
|
|
*/
|
|
|
|
#ifndef __ASM_PERCPU_H
|
|
|
|
#define __ASM_PERCPU_H
|
|
|
|
|
2022-05-31 18:04:12 +08:00
|
|
|
#include <asm/cmpxchg.h>
|
LoongArch: Fix the !CONFIG_SMP build
1, We assume arch/loongarch/include/asm/smp.h be included in include/
linux/smp.h is valid and the reverse inclusion isn't. So remove the
<linux/smp.h> in arch/loongarch/include/asm/smp.h.
2, arch/loongarch/include/asm/smp.h is only needed when CONFIG_SMP,
and setup.c include it only because it need plat_smp_setup(). So,
reorganize setup.c & smp.h, and then remove <asm/smp.h> in setup.c.
3, Fix cacheinfo.c and percpu.h build error by adding the missing header
files when !CONFIG_SMP.
4, Fix acpi.c build error by adding CONFIG_SMP guards.
5, Move irq_stat definition from smp.c to irq.c and fix its declaration.
6, Select CONFIG_SMP for CONFIG_NUMA, similar as other architectures do.
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
2022-06-05 16:19:53 +08:00
|
|
|
#include <asm/loongarch.h>
|
2022-05-31 18:04:12 +08:00
|
|
|
|
2022-10-12 16:36:08 +08:00
|
|
|
/*
|
|
|
|
* The "address" (in fact, offset from $r21) of a per-CPU variable is close to
|
|
|
|
* the loading address of main kernel image, but far from where the modules are
|
|
|
|
* loaded. Tell the compiler this fact when using explicit relocs.
|
|
|
|
*/
|
|
|
|
#if defined(MODULE) && defined(CONFIG_AS_HAS_EXPLICIT_RELOCS)
|
LoongArch: Tweak CFLAGS for Clang compatibility
Now the arch code is mostly ready for LLVM/Clang consumption, it is time
to re-organize the CFLAGS a little to actually enable the LLVM build.
Namely, all -G0 switches from CFLAGS are removed, and -mexplicit-relocs
and -mdirect-extern-access are now wrapped with cc-option (with the
related asm/percpu.h definition guarded against toolchain combos that
are known to not work).
A build with !RELOCATABLE && !MODULE is confirmed working within a QEMU
environment; support for the two features are currently blocked on
LLVM/Clang, and will come later.
Why -G0 can be removed:
In GCC, -G stands for "small data threshold", that instructs the
compiler to put data smaller than the specified threshold in a dedicated
"small data" section (called .sdata on LoongArch and several other
arches).
However, benefiting from this would require ABI cooperation, which is
not the case for LoongArch; and current GCC behave the same whether -G0
(equal to disabling this optimization) is given or not. So, remove -G0
from CFLAGS altogether for one less thing to care about. This also
benefits LLVM/Clang compatibility where the -G switch is not supported.
Why -mexplicit-relocs can now be conditionally applied without
regressions:
Originally -mexplicit-relocs is unconditionally added to CFLAGS in case
of CONFIG_AS_HAS_EXPLICIT_RELOCS, because not having it (i.e. old GCC +
new binutils) would not work: modules will have R_LARCH_ABS_* relocs
inside, but given the rarity of such toolchain combo in the wild, it may
not be worthwhile to support it, so support for such relocs in modules
were not added back when explicit relocs support was upstreamed, and
-mexplicit-relocs is unconditionally added to fail the build early.
Now that Clang compatibility is desired, given Clang is behaving like
-mexplicit-relocs from day one but without support for the CLI flag, we
must ensure the flag is not passed in case of Clang. However, explicit
compiler flavor checks can be more brittle than feature detection: in
this case what actually matters is support for __attribute__((model))
when building modules. Given neither older GCC nor current Clang support
this attribute, probing for the attribute support and #error'ing out
would allow proper UX without checking for Clang, and also automatically
work when Clang support for the attribute is to be added in the future.
Why -mdirect-extern-access is now conditionally applied:
This is actually a nice-to-have optimization that can reduce GOT
accesses, but not having it is harmless either. Because Clang does not
support the option currently, but might do so in the future, conditional
application via cc-option ensures compatibility with both current and
future Clang versions.
Suggested-by: Xi Ruoyao <xry111@xry111.site> # cc-option changes
Signed-off-by: WANG Xuerui <git@xen0n.name>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
2023-06-29 20:58:43 +08:00
|
|
|
# if __has_attribute(model)
|
|
|
|
# define PER_CPU_ATTRIBUTES __attribute__((model("extreme")))
|
|
|
|
# else
|
|
|
|
# error compiler support for the model attribute is necessary when a recent assembler is used
|
|
|
|
# endif
|
2022-10-12 16:36:08 +08:00
|
|
|
#endif
|
|
|
|
|
2022-05-31 18:04:11 +08:00
|
|
|
/* Use r21 for fast access */
|
|
|
|
register unsigned long __my_cpu_offset __asm__("$r21");
|
|
|
|
|
|
|
|
static inline void set_my_cpu_offset(unsigned long off)
|
|
|
|
{
|
|
|
|
__my_cpu_offset = off;
|
|
|
|
csr_write64(off, PERCPU_BASE_KS);
|
|
|
|
}
|
2024-03-19 15:50:34 +08:00
|
|
|
|
|
|
|
#define __my_cpu_offset \
|
|
|
|
({ \
|
|
|
|
__asm__ __volatile__("":"+r"(__my_cpu_offset)); \
|
|
|
|
__my_cpu_offset; \
|
|
|
|
})
|
2022-05-31 18:04:11 +08:00
|
|
|
|
2022-05-31 18:04:12 +08:00
|
|
|
#define PERCPU_OP(op, asm_op, c_op) \
|
LoongArch: Mark __percpu functions as always inline
A recent change to the optimization pipeline in LLVM reveals some
fragility around the inlining of LoongArch's __percpu functions, which
manifests as a BUILD_BUG() failure:
In file included from kernel/sched/build_policy.c:17:
In file included from include/linux/sched/cputime.h:5:
In file included from include/linux/sched/signal.h:5:
In file included from include/linux/rculist.h:11:
In file included from include/linux/rcupdate.h:26:
In file included from include/linux/irqflags.h:18:
arch/loongarch/include/asm/percpu.h:97:3: error: call to '__compiletime_assert_51' declared with 'error' attribute: BUILD_BUG failed
97 | BUILD_BUG();
| ^
include/linux/build_bug.h:59:21: note: expanded from macro 'BUILD_BUG'
59 | #define BUILD_BUG() BUILD_BUG_ON_MSG(1, "BUILD_BUG failed")
| ^
include/linux/build_bug.h:39:37: note: expanded from macro 'BUILD_BUG_ON_MSG'
39 | #define BUILD_BUG_ON_MSG(cond, msg) compiletime_assert(!(cond), msg)
| ^
include/linux/compiler_types.h:425:2: note: expanded from macro 'compiletime_assert'
425 | _compiletime_assert(condition, msg, __compiletime_assert_, __COUNTER__)
| ^
include/linux/compiler_types.h:413:2: note: expanded from macro '_compiletime_assert'
413 | __compiletime_assert(condition, msg, prefix, suffix)
| ^
include/linux/compiler_types.h:406:4: note: expanded from macro '__compiletime_assert'
406 | prefix ## suffix(); \
| ^
<scratch space>:86:1: note: expanded from here
86 | __compiletime_assert_51
| ^
1 error generated.
If these functions are not inlined (which the compiler is free to do
even with functions marked with the standard 'inline' keyword), the
BUILD_BUG() in the default case cannot be eliminated since the compiler
cannot prove it is never used, resulting in a build failure due to the
error attribute.
Mark these functions as __always_inline to guarantee inlining so that
the BUILD_BUG() only triggers when the default case genuinely cannot be
eliminated due to an unexpected size.
Cc: <stable@vger.kernel.org>
Closes: https://github.com/ClangBuiltLinux/linux/issues/1955
Fixes: 46859ac8af52 ("LoongArch: Add multi-processor (SMP) support")
Link: https://github.com/llvm/llvm-project/commit/1a2e77cf9e11dbf56b5720c607313a566eebb16e
Suggested-by: Nick Desaulniers <ndesaulniers@google.com>
Signed-off-by: Nathan Chancellor <nathan@kernel.org>
Signed-off-by: Huacai Chen <chenhuacai@loongson.cn>
2023-11-08 14:12:15 +08:00
|
|
|
static __always_inline unsigned long __percpu_##op(void *ptr, \
|
2022-05-31 18:04:12 +08:00
|
|
|
unsigned long val, int size) \
|
|
|
|
{ \
|
|
|
|
unsigned long ret; \
|
|
|
|
\
|
|
|
|
switch (size) { \
|
|
|
|
case 4: \
|
|
|
|
__asm__ __volatile__( \
|
2023-11-21 15:03:25 +08:00
|
|
|
"am"#asm_op".w" " %[ret], %[val], %[ptr] \n" \
|
2022-05-31 18:04:12 +08:00
|
|
|
: [ret] "=&r" (ret), [ptr] "+ZB"(*(u32 *)ptr) \
|
|
|
|
: [val] "r" (val)); \
|
|
|
|
break; \
|
|
|
|
case 8: \
|
|
|
|
__asm__ __volatile__( \
|
2023-11-21 15:03:25 +08:00
|
|
|
"am"#asm_op".d" " %[ret], %[val], %[ptr] \n" \
|
2022-05-31 18:04:12 +08:00
|
|
|
: [ret] "=&r" (ret), [ptr] "+ZB"(*(u64 *)ptr) \
|
|
|
|
: [val] "r" (val)); \
|
|
|
|
break; \
|
|
|
|
default: \
|
|
|
|
ret = 0; \
|
|
|
|
BUILD_BUG(); \
|
|
|
|
} \
|
|
|
|
\
|
|
|
|
return ret c_op val; \
|
|
|
|
}
|
|
|
|
|
|
|
|
PERCPU_OP(add, add, +)
|
|
|
|
PERCPU_OP(and, and, &)
|
|
|
|
PERCPU_OP(or, or, |)
|
|
|
|
#undef PERCPU_OP
|
|
|
|
|
2023-11-21 15:03:25 +08:00
|
|
|
static __always_inline unsigned long __percpu_xchg(void *ptr, unsigned long val, int size)
|
2022-05-31 18:04:12 +08:00
|
|
|
{
|
|
|
|
switch (size) {
|
2022-08-25 19:34:59 +08:00
|
|
|
case 1:
|
|
|
|
case 2:
|
|
|
|
return __xchg_small((volatile void *)ptr, val, size);
|
|
|
|
|
2022-05-31 18:04:12 +08:00
|
|
|
case 4:
|
|
|
|
return __xchg_asm("amswap.w", (volatile u32 *)ptr, (u32)val);
|
|
|
|
|
|
|
|
case 8:
|
|
|
|
return __xchg_asm("amswap.d", (volatile u64 *)ptr, (u64)val);
|
|
|
|
|
|
|
|
default:
|
|
|
|
BUILD_BUG();
|
|
|
|
}
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
}
|
|
|
|
|
2024-09-24 15:32:20 +08:00
|
|
|
#define __pcpu_op_1(op) op ".b "
|
|
|
|
#define __pcpu_op_2(op) op ".h "
|
|
|
|
#define __pcpu_op_4(op) op ".w "
|
|
|
|
#define __pcpu_op_8(op) op ".d "
|
|
|
|
|
|
|
|
#define _percpu_read(size, _pcp) \
|
|
|
|
({ \
|
|
|
|
typeof(_pcp) __pcp_ret; \
|
|
|
|
\
|
|
|
|
__asm__ __volatile__( \
|
|
|
|
__pcpu_op_##size("ldx") "%[ret], $r21, %[ptr] \n" \
|
|
|
|
: [ret] "=&r"(__pcp_ret) \
|
|
|
|
: [ptr] "r"(&(_pcp)) \
|
|
|
|
: "memory"); \
|
|
|
|
\
|
|
|
|
__pcp_ret; \
|
|
|
|
})
|
|
|
|
|
|
|
|
#define _percpu_write(size, _pcp, _val) \
|
|
|
|
do { \
|
|
|
|
__asm__ __volatile__( \
|
|
|
|
__pcpu_op_##size("stx") "%[val], $r21, %[ptr] \n" \
|
|
|
|
: \
|
|
|
|
: [val] "r"(_val), [ptr] "r"(&(_pcp)) \
|
|
|
|
: "memory"); \
|
|
|
|
} while (0)
|
|
|
|
|
2022-05-31 18:04:12 +08:00
|
|
|
/* this_cpu_cmpxchg */
|
|
|
|
#define _protect_cmpxchg_local(pcp, o, n) \
|
|
|
|
({ \
|
|
|
|
typeof(*raw_cpu_ptr(&(pcp))) __ret; \
|
|
|
|
preempt_disable_notrace(); \
|
|
|
|
__ret = cmpxchg_local(raw_cpu_ptr(&(pcp)), o, n); \
|
|
|
|
preempt_enable_notrace(); \
|
|
|
|
__ret; \
|
|
|
|
})
|
|
|
|
|
|
|
|
#define _pcp_protect(operation, pcp, val) \
|
|
|
|
({ \
|
|
|
|
typeof(pcp) __retval; \
|
|
|
|
preempt_disable_notrace(); \
|
|
|
|
__retval = (typeof(pcp))operation(raw_cpu_ptr(&(pcp)), \
|
|
|
|
(val), sizeof(pcp)); \
|
|
|
|
preempt_enable_notrace(); \
|
|
|
|
__retval; \
|
|
|
|
})
|
|
|
|
|
|
|
|
#define _percpu_add(pcp, val) \
|
|
|
|
_pcp_protect(__percpu_add, pcp, val)
|
|
|
|
|
|
|
|
#define _percpu_add_return(pcp, val) _percpu_add(pcp, val)
|
|
|
|
|
|
|
|
#define _percpu_and(pcp, val) \
|
|
|
|
_pcp_protect(__percpu_and, pcp, val)
|
|
|
|
|
|
|
|
#define _percpu_or(pcp, val) \
|
|
|
|
_pcp_protect(__percpu_or, pcp, val)
|
|
|
|
|
|
|
|
#define _percpu_xchg(pcp, val) ((typeof(pcp)) \
|
|
|
|
_pcp_protect(__percpu_xchg, pcp, (unsigned long)(val)))
|
|
|
|
|
|
|
|
#define this_cpu_add_4(pcp, val) _percpu_add(pcp, val)
|
|
|
|
#define this_cpu_add_8(pcp, val) _percpu_add(pcp, val)
|
|
|
|
|
|
|
|
#define this_cpu_add_return_4(pcp, val) _percpu_add_return(pcp, val)
|
|
|
|
#define this_cpu_add_return_8(pcp, val) _percpu_add_return(pcp, val)
|
|
|
|
|
|
|
|
#define this_cpu_and_4(pcp, val) _percpu_and(pcp, val)
|
|
|
|
#define this_cpu_and_8(pcp, val) _percpu_and(pcp, val)
|
|
|
|
|
|
|
|
#define this_cpu_or_4(pcp, val) _percpu_or(pcp, val)
|
|
|
|
#define this_cpu_or_8(pcp, val) _percpu_or(pcp, val)
|
|
|
|
|
2024-09-24 15:32:20 +08:00
|
|
|
#define this_cpu_read_1(pcp) _percpu_read(1, pcp)
|
|
|
|
#define this_cpu_read_2(pcp) _percpu_read(2, pcp)
|
|
|
|
#define this_cpu_read_4(pcp) _percpu_read(4, pcp)
|
|
|
|
#define this_cpu_read_8(pcp) _percpu_read(8, pcp)
|
2022-05-31 18:04:12 +08:00
|
|
|
|
2024-09-24 15:32:20 +08:00
|
|
|
#define this_cpu_write_1(pcp, val) _percpu_write(1, pcp, val)
|
|
|
|
#define this_cpu_write_2(pcp, val) _percpu_write(2, pcp, val)
|
|
|
|
#define this_cpu_write_4(pcp, val) _percpu_write(4, pcp, val)
|
|
|
|
#define this_cpu_write_8(pcp, val) _percpu_write(8, pcp, val)
|
2022-05-31 18:04:12 +08:00
|
|
|
|
2022-08-25 19:34:59 +08:00
|
|
|
#define this_cpu_xchg_1(pcp, val) _percpu_xchg(pcp, val)
|
|
|
|
#define this_cpu_xchg_2(pcp, val) _percpu_xchg(pcp, val)
|
2022-05-31 18:04:12 +08:00
|
|
|
#define this_cpu_xchg_4(pcp, val) _percpu_xchg(pcp, val)
|
|
|
|
#define this_cpu_xchg_8(pcp, val) _percpu_xchg(pcp, val)
|
|
|
|
|
2022-08-25 19:34:59 +08:00
|
|
|
#define this_cpu_cmpxchg_1(ptr, o, n) _protect_cmpxchg_local(ptr, o, n)
|
|
|
|
#define this_cpu_cmpxchg_2(ptr, o, n) _protect_cmpxchg_local(ptr, o, n)
|
2022-05-31 18:04:12 +08:00
|
|
|
#define this_cpu_cmpxchg_4(ptr, o, n) _protect_cmpxchg_local(ptr, o, n)
|
|
|
|
#define this_cpu_cmpxchg_8(ptr, o, n) _protect_cmpxchg_local(ptr, o, n)
|
|
|
|
|
2022-05-31 18:04:11 +08:00
|
|
|
#include <asm-generic/percpu.h>
|
|
|
|
|
|
|
|
#endif /* __ASM_PERCPU_H */
|