1 | // SPDX-License-Identifier: GPL-3.0-or-later |
2 | |
3 | #include "mos/assert.h" |
4 | |
5 | #include <mos/interrupt/ipi.h> |
6 | #include <mos/platform/platform.h> |
7 | #include <mos/syslog/printk.h> |
8 | #include <mos/types.h> |
9 | |
10 | #if MOS_CONFIG(MOS_SMP) |
11 | #include "mos/tasks/schedule.h" |
12 | |
13 | static void ipi_handler_halt(ipi_type_t type) |
14 | { |
15 | MOS_UNUSED(type); |
16 | pr_info("halt IPI received" ); |
17 | platform_halt_cpu(); |
18 | } |
19 | |
20 | static void ipi_handler_invalidate_tlb(ipi_type_t type) |
21 | { |
22 | MOS_UNUSED(type); |
23 | pr_dinfo2(ipi, "Received invalidate TLB IPI" ); |
24 | platform_invalidate_tlb(vaddr: 0); |
25 | } |
26 | |
27 | static void ipi_handler_reschedule(ipi_type_t type) |
28 | { |
29 | MOS_UNUSED(type); |
30 | pr_dinfo2(ipi, "Received reschedule IPI" ); |
31 | spinlock_acquire(¤t_thread->state_lock); |
32 | reschedule(); |
33 | } |
34 | |
35 | #define IPI_ENTRY(_type, _handler) [_type] = { .handle = _handler, .nr = PER_CPU_VAR_INIT } |
36 | |
37 | static struct |
38 | { |
39 | void (*handle)(ipi_type_t type); |
40 | PER_CPU_DECLARE(size_t, nr); |
41 | } ipi_handlers[IPI_TYPE_MAX] = { |
42 | IPI_ENTRY(IPI_TYPE_HALT, ipi_handler_halt), |
43 | IPI_ENTRY(IPI_TYPE_INVALIDATE_TLB, ipi_handler_invalidate_tlb), |
44 | IPI_ENTRY(IPI_TYPE_RESCHEDULE, ipi_handler_reschedule), |
45 | }; |
46 | |
47 | void ipi_send(u8 target, ipi_type_t type) |
48 | { |
49 | pr_dinfo2(ipi, "Sending IPI to %d of type %d" , target, type); |
50 | platform_ipi_send(target_cpu: target, type); |
51 | } |
52 | |
53 | void ipi_send_all(ipi_type_t type) |
54 | { |
55 | pr_dinfo2(ipi, "Sending IPI to all of type %d" , type); |
56 | platform_ipi_send(TARGET_CPU_ALL, type); |
57 | } |
58 | |
59 | void ipi_do_handle(ipi_type_t type) |
60 | { |
61 | pr_dinfo2(ipi, "Handling IPI of type %d" , type); |
62 | |
63 | if (type >= IPI_TYPE_MAX) |
64 | { |
65 | mos_warn("IPI type %d is out of range" , type); |
66 | return; |
67 | } |
68 | |
69 | if (ipi_handlers[type].handle == NULL) |
70 | { |
71 | mos_warn("No handler for IPI type %d" , type); |
72 | return; |
73 | } |
74 | |
75 | (*per_cpu(ipi_handlers[type].nr))++; |
76 | ipi_handlers[type].handle(type); |
77 | } |
78 | #else |
79 | // clang-format off |
80 | #define STUB_FUNCTION(func, ...) void func(__VA_ARGS__){} |
81 | #define STUB_FUNCTION_UNREACHABLE(func, ...) void func(__VA_ARGS__){ MOS_UNREACHABLE(); } |
82 | // clang-format on |
83 | |
84 | STUB_FUNCTION(ipi_send, u8 __maybe_unused target, ipi_type_t __maybe_unused type) |
85 | STUB_FUNCTION(ipi_send_all, ipi_type_t __maybe_unused type) |
86 | STUB_FUNCTION(ipi_init, ) |
87 | STUB_FUNCTION_UNREACHABLE(ipi_do_handle, ipi_type_t __maybe_unused type) |
88 | #endif |
89 | |