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 "kernel.h"
8#include "kernel_fdt.hpp"
9#include "kernel_log.hpp"
10#include "virtual_memory.hpp"
11
12namespace {
19auto DefaultInterruptHandler(uint64_t cause, cpu_io::TrapContext* context)
20 -> uint64_t {
21 klog::Info("Default Interrupt handler {:#X}, {:#x}", cause,
22 reinterpret_cast<uintptr_t>(context));
23 return 0;
24}
25} // namespace
26
28 auto [dist_base_addr, dist_size, redist_base_addr, redist_size] =
29 KernelFdtSingleton::instance().GetGIC().value();
30 VirtualMemorySingleton::instance()
31 .MapMMIO(dist_base_addr, dist_size)
32 .or_else([](Error err) -> Expected<void*> {
33 klog::Err("Failed to map GIC distributor MMIO: {}", err.message());
34 while (true) {
36 }
37 return std::unexpected(err);
38 });
39 VirtualMemorySingleton::instance()
40 .MapMMIO(redist_base_addr, redist_size)
41 .or_else([](Error err) -> Expected<void*> {
42 klog::Err("Failed to map GIC redistributor MMIO: {}", err.message());
43 while (true) {
45 }
46 return std::unexpected(err);
47 });
48
49 gic_ = std::move(Gic(dist_base_addr, redist_base_addr));
50
51 // 注册默认中断处理函数
52 for (auto& i : interrupt_handlers_) {
53 i = InterruptDelegate::create<DefaultInterruptHandler>();
54 }
55
56 // 设置 SGI 0 用于 IPI
57 auto cpuid = cpu_io::GetCurrentCoreId();
58 gic_.Sgi(0, cpuid);
59
60 klog::Info("Interrupt init.");
61}
62
63auto Interrupt::Do(uint64_t cause, cpu_io::TrapContext* context) -> void {
64 interrupt_handlers_[cause](cause, context);
65 cpu_io::ICC_EOIR1_EL1::Write(cause);
66}
67
69 -> void {
70 if (func) {
71 interrupt_handlers_[cause] = func;
72 }
73}
74
75auto Interrupt::SendIpi(uint64_t target_cpu_mask) -> Expected<void> {
77 static constexpr uint64_t kIPISGI = 0;
78
79 uint64_t sgi_value = 0;
80
81 // 设置 INTID 为 0 (SGI 0)
82 sgi_value |= (kIPISGI & 0xF) << 24;
83
84 // 设置 TargetList (Aff0 级别,低 16 位)
85 sgi_value |= (target_cpu_mask & 0xFFFF);
86
87 // 写入 ICC_SGI1R_EL1 寄存器发送 SGI
88 cpu_io::ICC_SGI1R_EL1::Write(sgi_value);
89
90 return {};
91}
92
95 static constexpr uint64_t kIPISGI = 0;
96
97 // 构造 ICC_SGI1R_EL1 寄存器的值
98 uint64_t sgi_value = 0;
99
100 // 设置 INTID 为 0 (SGI 0)
101 sgi_value |= (kIPISGI & 0xF) << 24;
102
103 // 设置 IRM (Interrupt Routing Mode) 为 1,表示广播到所有 PE
104 sgi_value |= (1ULL << 40);
105
106 // 写入 ICC_SGI1R_EL1 寄存器发送 SGI
107 cpu_io::ICC_SGI1R_EL1::Write(sgi_value);
108
109 return {};
110}
111
112auto Interrupt::RegisterExternalInterrupt(uint32_t irq, uint32_t cpu_id,
113 uint32_t priority,
114 InterruptDelegate handler)
115 -> Expected<void> {
116 // irq 为 GIC INTID(已含 kSpiBase 偏移)
117 if (irq >= kMaxInterrupt) {
118 return std::unexpected(Error(ErrorCode::kIrqChipInvalidIrq));
119 }
120
121 // 先注册处理函数
122 RegisterInterruptFunc(irq, handler);
123
124 // 再在 GIC 上为指定核心配置并启用 SPI
125 gic_.Spi(irq, cpu_id);
126
127 klog::Info("RegisterExternalInterrupt: INTID {}, cpu {}, priority {}", irq,
128 cpu_id, priority);
129 return {};
130}
InterruptBase::InterruptDelegate InterruptDelegate
GIC 中断控制器驱动
Definition gic.h:17
auto Sgi(uint32_t intid, uint32_t cpuid) const -> void
配置软件生成中断 (SGI)
Definition gic.cpp:39
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
注册外部中断
Gic gic_
GIC 中断控制器实例
Definition interrupt.h:113
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 BroadcastIpi() -> Expected< void > override
广播 IPI 到所有 CPU
Definition interrupt.cpp:93
std::array< InterruptDelegate, kMaxInterrupt > interrupt_handlers_
中断处理函数数组
Definition interrupt.h:110
@ 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
constexpr auto message() const -> const char *
Definition expected.hpp:358