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
13static 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
20static 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
27static void ipi_handler_reschedule(ipi_type_t type)
28{
29 MOS_UNUSED(type);
30 pr_dinfo2(ipi, "Received reschedule IPI");
31 spinlock_acquire(&current_thread->state_lock);
32 reschedule();
33}
34
35#define IPI_ENTRY(_type, _handler) [_type] = { .handle = _handler, .nr = PER_CPU_VAR_INIT }
36
37static 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
47void 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
53void 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
59void 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
84STUB_FUNCTION(ipi_send, u8 __maybe_unused target, ipi_type_t __maybe_unused type)
85STUB_FUNCTION(ipi_send_all, ipi_type_t __maybe_unused type)
86STUB_FUNCTION(ipi_init, )
87STUB_FUNCTION_UNREACHABLE(ipi_do_handle, ipi_type_t __maybe_unused type)
88#endif
89