SimpleKernel 1.17.0
Loading...
Searching...
No Matches
interrupt.cpp
Go to the documentation of this file.
1
5#include "interrupt.h"
6
7#include <cpu_io.h>
8#include <opensbi_interface.h>
9
10#include <cassert>
11
12#include "basic_info.hpp"
13#include "kernel.h"
14#include "kstd_cstdio"
15
16namespace {
17auto DefaultInterruptHandler(uint64_t cause, cpu_io::TrapContext* context)
18 -> uint64_t {
19 klog::Info("Default Interrupt handler [{}] {:#X}, {:#x}",
20 cpu_io::ScauseInfo::kInterruptNames[cause], cause,
21 reinterpret_cast<uintptr_t>(context));
22 return 0;
23}
24
25auto DefaultExceptionHandler(uint64_t cause, cpu_io::TrapContext* context)
26 -> uint64_t {
27 klog::Err("Default Exception handler [{}] {:#X}, {:#x}",
28 cpu_io::ScauseInfo::kExceptionNames[cause], cause,
29 reinterpret_cast<uintptr_t>(context));
30 while (true) {
32 }
33}
34} // namespace
35
37 // 注册默认中断处理函数
38 for (auto& i : interrupt_handlers_) {
39 i = InterruptDelegate::create<DefaultInterruptHandler>();
40 }
41 // 注册默认异常处理函数
42 for (auto& i : exception_handlers_) {
43 i = InterruptDelegate::create<DefaultExceptionHandler>();
44 }
45 klog::Info("Interrupt init.");
46}
47
48auto Interrupt::Do(uint64_t cause, cpu_io::TrapContext* context) -> void {
49 auto interrupt = cpu_io::Scause::Interrupt::Get(cause);
50 auto exception_code = cpu_io::Scause::ExceptionCode::Get(cause);
51
52 if (interrupt) {
53 // 中断
54 if (exception_code < cpu_io::ScauseInfo::kInterruptMaxCount) {
55 interrupt_handlers_[exception_code](exception_code, context);
56 }
57 } else {
58 // 异常
59 if (exception_code < cpu_io::ScauseInfo::kExceptionMaxCount) {
60 exception_handlers_[exception_code](exception_code, context);
61 }
62 }
63}
64
66 -> void {
67 auto interrupt = cpu_io::Scause::Interrupt::Get(cause);
68 auto exception_code = cpu_io::Scause::ExceptionCode::Get(cause);
69
70 if (interrupt) {
71 assert(exception_code < cpu_io::ScauseInfo::kInterruptMaxCount &&
72 "Interrupt code out of range");
73
74 interrupt_handlers_[exception_code] = func;
75 klog::Info("RegisterInterruptFunc [{}] {:#X}",
76 cpu_io::ScauseInfo::kInterruptNames[exception_code], cause);
77 } else {
78 assert(exception_code < cpu_io::ScauseInfo::kExceptionMaxCount &&
79 "Exception code out of range");
80
81 exception_handlers_[exception_code] = func;
82 klog::Info("RegisterInterruptFunc [{}] {:#X}",
83 cpu_io::ScauseInfo::kExceptionNames[exception_code], cause);
84 }
85}
86
87auto Interrupt::SendIpi(uint64_t target_cpu_mask) -> Expected<void> {
88 if (target_cpu_mask > (1UL << SIMPLEKERNEL_MAX_CORE_COUNT) - 1) {
89 return std::unexpected(Error(ErrorCode::kIpiTargetOutOfRange));
90 }
91
92 auto ret = sbi_send_ipi(target_cpu_mask, 0);
93 if (ret.error != SBI_SUCCESS) {
94 return std::unexpected(Error(ErrorCode::kIpiSendFailed));
95 }
96 return {};
97}
98
100 // 如果没有其他核心,直接返回成功
101 if (BasicInfoSingleton::instance().core_count == 1) {
102 return {};
103 }
104
105 uint64_t mask = 0;
106 auto current = cpu_io::GetCurrentCoreId();
107 for (size_t i = 0; i < BasicInfoSingleton::instance().core_count; ++i) {
108 if (i != current) {
109 mask |= (1UL << i);
110 }
111 }
112
113 return SendIpi(mask);
114}
115
116auto Interrupt::RegisterExternalInterrupt(uint32_t irq, uint32_t cpu_id,
117 uint32_t priority,
118 InterruptDelegate handler)
119 -> Expected<void> {
120 if (irq >= Plic::kInterruptMaxCount) {
121 return std::unexpected(Error(ErrorCode::kIrqChipInvalidIrq));
122 }
123
124 // 先注册处理函数
125 plic_.RegisterInterruptFunc(static_cast<uint8_t>(irq), handler);
126
127 // 再在 PLIC 上为指定核心启用该中断
128 plic_.Set(cpu_id, irq, priority, true);
129
130 klog::Info("RegisterExternalInterrupt: IRQ {}, cpu {}, priority {}", irq,
131 cpu_id, priority);
132 return {};
133}
134
135auto Interrupt::InitPlic(uint64_t dev_addr, size_t ndev, size_t context_count)
136 -> void {
137 plic_ = Plic(dev_addr, ndev, context_count);
138}
InterruptBase::InterruptDelegate InterruptDelegate
auto SendIpi(uint64_t target_cpu_mask) -> Expected< void > override
发送 IPI 到指定 CPU
Definition interrupt.cpp:75
auto RegisterExternalInterrupt(uint32_t irq, uint32_t cpu_id, uint32_t priority, InterruptDelegate handler) -> Expected< void > override
注册外部中断
auto Do(uint64_t cause, cpu_io::TrapContext *context) -> void override
执行中断处理
Definition interrupt.cpp:63
auto RegisterInterruptFunc(uint64_t cause, InterruptDelegate func) -> void override
注册中断处理函数
Definition interrupt.cpp:68
auto InitPlic(uint64_t dev_addr, size_t ndev, size_t context_count) -> void
初始化 PLIC
auto BroadcastIpi() -> Expected< void > override
广播 IPI 到所有 CPU
Definition interrupt.cpp:93
std::array< InterruptDelegate, cpu_io::ScauseInfo::kExceptionMaxCount > exception_handlers_
异常处理函数数组
Definition interrupt.h:97
std::array< InterruptDelegate, kMaxInterrupt > interrupt_handlers_
中断处理函数数组
Definition interrupt.h:110
Plic 驱动
Definition plic.h:20
static constexpr size_t kInterruptMaxCount
最大外部中断数量
Definition plic.h:25
@ kIpiTargetOutOfRange
@ kIrqChipInvalidIrq
std::expected< T, Error > Expected
std::expected 别名模板
Definition expected.hpp:365
auto GetCurrentCoreId() -> size_t
Definition cpu_io.h:26
void Pause()
Definition cpu_io.h:20
auto Err(etl::format_string< Args... > fmt, Args &&... args) -> void
以 ERROR 级别记录日志
auto Info(etl::format_string< Args... > fmt, Args &&... args) -> void
以 INFO 级别记录日志
错误类型,用于 std::expected
Definition expected.hpp:343