Skip to content
Navigation Menu
Toggle navigation
Sign in
In this repository
All GitHub Enterprise
↵
Jump to
↵
No suggested jump to results
In this repository
All GitHub Enterprise
↵
Jump to
↵
In this organization
All GitHub Enterprise
↵
Jump to
↵
In this repository
All GitHub Enterprise
↵
Jump to
↵
Sign in
Reseting focus
You signed in with another tab or window.
Reload
to refresh your session.
You signed out in another tab or window.
Reload
to refresh your session.
You switched accounts on another tab or window.
Reload
to refresh your session.
Dismiss alert
{{ message }}
mariux64
/
linux
Public
Notifications
You must be signed in to change notification settings
Fork
0
Star
0
Code
Issues
2
Pull requests
0
Actions
Projects
0
Wiki
Security
Insights
Additional navigation options
Code
Issues
Pull requests
Actions
Projects
Wiki
Security
Insights
Files
4c8c3c7
Documentation
LICENSES
arch
alpha
arc
arm
arm64
csky
abiv1
abiv2
boot
configs
include
kernel
probes
vdso
Makefile
asm-offsets.c
atomic.S
cpu-probe.c
entry.S
ftrace.c
head.S
io.c
irq.c
jump_label.c
module.c
perf_callchain.c
perf_event.c
perf_regs.c
power.c
process.c
ptrace.c
setup.c
signal.c
smp.c
stacktrace.c
syscall.c
syscall_table.c
time.c
traps.c
vdso.c
vmlinux.lds.S
lib
mm
Kbuild
Kconfig
Kconfig.debug
Kconfig.platforms
Makefile
hexagon
ia64
loongarch
m68k
microblaze
mips
nios2
openrisc
parisc
powerpc
riscv
s390
sh
sparc
um
x86
xtensa
.gitignore
Kconfig
block
certs
crypto
drivers
fs
include
init
io_uring
ipc
kernel
lib
mm
net
rust
samples
scripts
security
sound
tools
usr
virt
.clang-format
.cocciconfig
.get_maintainer.ignore
.gitattributes
.gitignore
.mailmap
.rustfmt.toml
COPYING
CREDITS
Kbuild
Kconfig
MAINTAINERS
Makefile
README
Breadcrumbs
linux
/
arch
/
csky
/
kernel
/
smp.c
Blame
Blame
Latest commit
Valentin Schneider
and
Peter Zijlstra
treewide: Trace IPIs sent via smp_send_reschedule()
Mar 24, 2023
4c8c3c7
·
Mar 24, 2023
History
History
321 lines (252 loc) · 6.04 KB
Breadcrumbs
linux
/
arch
/
csky
/
kernel
/
smp.c
Top
File metadata and controls
Code
Blame
321 lines (252 loc) · 6.04 KB
Raw
// SPDX-License-Identifier: GPL-2.0 #include <linux/module.h> #include <linux/init.h> #include <linux/kernel.h> #include <linux/mm.h> #include <linux/sched.h> #include <linux/kernel_stat.h> #include <linux/notifier.h> #include <linux/cpu.h> #include <linux/percpu.h> #include <linux/delay.h> #include <linux/err.h> #include <linux/irq.h> #include <linux/irq_work.h> #include <linux/irqdomain.h> #include <linux/of.h> #include <linux/seq_file.h> #include <linux/sched/task_stack.h> #include <linux/sched/mm.h> #include <linux/sched/hotplug.h> #include <asm/irq.h> #include <asm/traps.h> #include <asm/sections.h> #include <asm/mmu_context.h> #ifdef CONFIG_CPU_HAS_FPU #include <abi/fpu.h> #endif enum ipi_message_type { IPI_EMPTY, IPI_RESCHEDULE, IPI_CALL_FUNC, IPI_IRQ_WORK, IPI_MAX }; struct ipi_data_struct { unsigned long bits ____cacheline_aligned; unsigned long stats[IPI_MAX] ____cacheline_aligned; }; static DEFINE_PER_CPU(struct ipi_data_struct, ipi_data); static irqreturn_t handle_ipi(int irq, void *dev) { unsigned long *stats = this_cpu_ptr(&ipi_data)->stats; while (true) { unsigned long ops; ops = xchg(&this_cpu_ptr(&ipi_data)->bits, 0); if (ops == 0) return IRQ_HANDLED; if (ops & (1 << IPI_RESCHEDULE)) { stats[IPI_RESCHEDULE]++; scheduler_ipi(); } if (ops & (1 << IPI_CALL_FUNC)) { stats[IPI_CALL_FUNC]++; generic_smp_call_function_interrupt(); } if (ops & (1 << IPI_IRQ_WORK)) { stats[IPI_IRQ_WORK]++; irq_work_run(); } BUG_ON((ops >> IPI_MAX) != 0); } return IRQ_HANDLED; } static void (*send_arch_ipi)(const struct cpumask *mask); static int ipi_irq; void __init set_send_ipi(void (*func)(const struct cpumask *mask), int irq) { if (send_arch_ipi) return; send_arch_ipi = func; ipi_irq = irq; } static void send_ipi_message(const struct cpumask *to_whom, enum ipi_message_type operation) { int i; for_each_cpu(i, to_whom) set_bit(operation, &per_cpu_ptr(&ipi_data, i)->bits); smp_mb(); send_arch_ipi(to_whom); } static const char * const ipi_names[] = { [IPI_EMPTY] = "Empty interrupts", [IPI_RESCHEDULE] = "Rescheduling interrupts", [IPI_CALL_FUNC] = "Function call interrupts", [IPI_IRQ_WORK] = "Irq work interrupts", }; int arch_show_interrupts(struct seq_file *p, int prec) { unsigned int cpu, i; for (i = 0; i < IPI_MAX; i++) { seq_printf(p, "%*s%u:%s", prec - 1, "IPI", i, prec >= 4 ? " " : ""); for_each_online_cpu(cpu) seq_printf(p, "%10lu ", per_cpu_ptr(&ipi_data, cpu)->stats[i]); seq_printf(p, " %s\n", ipi_names[i]); } return 0; } void arch_send_call_function_ipi_mask(struct cpumask *mask) { send_ipi_message(mask, IPI_CALL_FUNC); } void arch_send_call_function_single_ipi(int cpu) { send_ipi_message(cpumask_of(cpu), IPI_CALL_FUNC); } static void ipi_stop(void *unused) { while (1); } void smp_send_stop(void) { on_each_cpu(ipi_stop, NULL, 1); } void arch_smp_send_reschedule(int cpu) { send_ipi_message(cpumask_of(cpu), IPI_RESCHEDULE); } #ifdef CONFIG_IRQ_WORK void arch_irq_work_raise(void) { send_ipi_message(cpumask_of(smp_processor_id()), IPI_IRQ_WORK); } #endif void __init smp_prepare_boot_cpu(void) { } void __init smp_prepare_cpus(unsigned int max_cpus) { } static int ipi_dummy_dev; void __init setup_smp_ipi(void) { int rc; if (ipi_irq == 0) return; rc = request_percpu_irq(ipi_irq, handle_ipi, "IPI Interrupt", &ipi_dummy_dev); if (rc) panic("%s IRQ request failed\n", __func__); enable_percpu_irq(ipi_irq, 0); } void __init setup_smp(void) { struct device_node *node = NULL; unsigned int cpu; for_each_of_cpu_node(node) { if (!of_device_is_available(node)) continue; cpu = of_get_cpu_hwid(node, 0); if (cpu >= NR_CPUS) continue; set_cpu_possible(cpu, true); set_cpu_present(cpu, true); } } extern void _start_smp_secondary(void); volatile unsigned int secondary_hint; volatile unsigned int secondary_hint2; volatile unsigned int secondary_ccr; volatile unsigned int secondary_stack; volatile unsigned int secondary_msa1; volatile unsigned int secondary_pgd; int __cpu_up(unsigned int cpu, struct task_struct *tidle) { unsigned long mask = 1 << cpu; secondary_stack = (unsigned int) task_stack_page(tidle) + THREAD_SIZE - 8; secondary_hint = mfcr("cr31"); secondary_hint2 = mfcr("cr<21, 1>"); secondary_ccr = mfcr("cr18"); secondary_msa1 = read_mmu_msa1(); secondary_pgd = mfcr("cr<29, 15>"); /* * Because other CPUs are in reset status, we must flush data * from cache to out and secondary CPUs use them in * csky_start_secondary(void) */ mtcr("cr17", 0x22); if (mask & mfcr("cr<29, 0>")) { send_arch_ipi(cpumask_of(cpu)); } else { /* Enable cpu in SMP reset ctrl reg */ mask |= mfcr("cr<29, 0>"); mtcr("cr<29, 0>", mask); } /* Wait for the cpu online */ while (!cpu_online(cpu)); secondary_stack = 0; return 0; } void __init smp_cpus_done(unsigned int max_cpus) { } void csky_start_secondary(void) { struct mm_struct *mm = &init_mm; unsigned int cpu = smp_processor_id(); mtcr("cr31", secondary_hint); mtcr("cr<21, 1>", secondary_hint2); mtcr("cr18", secondary_ccr); mtcr("vbr", vec_base); flush_tlb_all(); write_mmu_pagemask(0); #ifdef CONFIG_CPU_HAS_FPU init_fpu(); #endif enable_percpu_irq(ipi_irq, 0); mmget(mm); mmgrab(mm); current->active_mm = mm; cpumask_set_cpu(cpu, mm_cpumask(mm)); notify_cpu_starting(cpu); set_cpu_online(cpu, true); pr_info("CPU%u Online: %s...\n", cpu, __func__); local_irq_enable(); cpu_startup_entry(CPUHP_AP_ONLINE_IDLE); } #ifdef CONFIG_HOTPLUG_CPU int __cpu_disable(void) { unsigned int cpu = smp_processor_id(); set_cpu_online(cpu, false); irq_migrate_all_off_this_cpu(); clear_tasks_mm_cpumask(cpu); return 0; } void __cpu_die(unsigned int cpu) { if (!cpu_wait_death(cpu, 5)) { pr_crit("CPU%u: shutdown failed\n", cpu); return; } pr_notice("CPU%u: shutdown\n", cpu); } void arch_cpu_idle_dead(void) { idle_task_exit(); cpu_report_death(); while (!secondary_stack) arch_cpu_idle(); raw_local_irq_disable(); asm volatile( "mov sp, %0\n" "mov r8, %0\n" "jmpi csky_start_secondary" : : "r" (secondary_stack)); } #endif
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
You can’t perform that action at this time.