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
9#include "arch.h"
10#include "kernel.h"
11#include "kernel_log.hpp"
12#include "kstd_cstdio"
13
14namespace {
21template <uint8_t no>
22__attribute__((target("general-regs-only"))) __attribute__((interrupt)) auto
23TarpEntry(cpu_io::TrapContext* interrupt_context) -> void {
24 InterruptSingleton::instance().Do(no, interrupt_context);
25}
26
27auto DefaultInterruptHandler(uint64_t cause, cpu_io::TrapContext* context)
28 -> uint64_t {
29 klog::Info("Default Interrupt handler [{}] {:#X}, {:#x}",
30 cpu_io::IdtrInfo::kInterruptNames[cause], cause,
31 reinterpret_cast<uintptr_t>(context));
32 while (true) {
33 ;
34 }
35}
36} // namespace
37
39 // 注册默认中断处理函数
40 for (auto& i : interrupt_handlers_) {
41 i = InterruptDelegate::create<DefaultInterruptHandler>();
42 }
43
44 klog::Info("Interrupt init.");
45}
46
47auto Interrupt::Do(uint64_t cause, cpu_io::TrapContext* context) -> void {
48 if (cause < cpu_io::IdtrInfo::kInterruptMaxCount) {
49 interrupt_handlers_[cause](cause, context);
50 }
51}
52
54 -> void {
55 if (cause < cpu_io::IdtrInfo::kInterruptMaxCount) {
56 interrupt_handlers_[cause] = func;
57 klog::Debug("RegisterInterruptFunc [{}] {:#X}",
58 cpu_io::IdtrInfo::kInterruptNames[cause], cause);
59 }
60}
61
62auto Interrupt::SetUpIdtr() -> void { SetUpIdtr<0>(); }
63
64template <uint8_t no>
65auto Interrupt::SetUpIdtr() -> void {
66 if constexpr (no < cpu_io::IdtrInfo::kInterruptMaxCount - 1) {
67 idts_[no] = cpu_io::IdtrInfo::Idt(
68 reinterpret_cast<uint64_t>(TarpEntry<no>), 8, 0x0,
69 cpu_io::IdtrInfo::Idt::Type::k64BitInterruptGate,
70 cpu_io::IdtrInfo::Idt::DPL::kRing0, cpu_io::IdtrInfo::Idt::P::kPresent);
71 SetUpIdtr<no + 1>();
72 } else {
73 // 写入 idtr
74 static auto idtr = cpu_io::IdtrInfo::Idtr{
75 .limit = sizeof(cpu_io::IdtrInfo::Idt) *
76 cpu_io::IdtrInfo::kInterruptMaxCount -
77 1,
78 .base = idts_.data(),
79 };
80 cpu_io::Idtr::Write(idtr);
81
82 // 输出 idtr 信息
83 for (size_t i = 0;
84 i < (cpu_io::Idtr::Read().limit + 1) / sizeof(cpu_io::IdtrInfo::Idtr);
85 i++) {
86 klog::Debug("idtr[{}] {:#x}", i,
87 reinterpret_cast<uintptr_t>(cpu_io::Idtr::Read().base + i));
88 }
89 }
90}
91
92auto Interrupt::SendIpi(uint64_t target_cpu_mask) -> Expected<void> {
94 return std::unexpected(Error(ErrorCode::kIpiSendFailed));
95}
96
99 return std::unexpected(Error(ErrorCode::kIpiSendFailed));
100}
101
102auto Interrupt::RegisterExternalInterrupt(uint32_t irq, uint32_t cpu_id,
103 uint32_t priority,
104 InterruptDelegate handler)
105 -> Expected<void> {
106 // 计算 IDT 向量号:kExternalVectorBase + irq
107 auto vector = static_cast<uint64_t>(kExternalVectorBase + irq);
108 if (vector >= cpu_io::IdtrInfo::kInterruptMaxCount) {
109 return std::unexpected(Error(ErrorCode::kApicInvalidIrq));
110 }
111
112 // 先注册处理函数
113 RegisterInterruptFunc(vector, handler);
114
115 // 再在 IO APIC 上启用 IRQ 重定向到指定核心
116 // 注: x86 APIC 优先级由向量号隐含决定,priority 参数不直接使用
117 auto result = apic_.SetIrqRedirection(
118 static_cast<uint8_t>(irq), static_cast<uint8_t>(vector), cpu_id, false);
119 if (!result.has_value()) {
120 return std::unexpected(result.error());
121 }
122
123 klog::Info("RegisterExternalInterrupt: IRQ {} -> vector {:#X}, cpu {}", irq,
124 vector, cpu_id);
125 return {};
126}
127
128auto Interrupt::InitApic(size_t cpu_count) -> void { apic_ = Apic(cpu_count); }
InterruptBase::InterruptDelegate InterruptDelegate
APIC 管理类,管理整个系统的 Local APIC 和 IO APIC.
Definition apic.h:22
auto SendIpi(uint64_t target_cpu_mask) -> Expected< void > override
发送 IPI 到指定 CPU
Definition interrupt.cpp:75
auto SetUpIdtr() -> void
初始化 idtr
Definition interrupt.cpp:62
auto InitApic(size_t cpu_count) -> void
初始化 APIC
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 BroadcastIpi() -> Expected< void > override
广播 IPI 到所有 CPU
Definition interrupt.cpp:93
std::array< InterruptDelegate, kMaxInterrupt > interrupt_handlers_
中断处理函数数组
Definition interrupt.h:110
std::expected< T, Error > Expected
std::expected 别名模板
Definition expected.hpp:365
auto Info(etl::format_string< Args... > fmt, Args &&... args) -> void
以 INFO 级别记录日志
auto Debug(etl::format_string< Args... > fmt, Args &&... args) -> void
以 DEBUG 级别记录日志(SIMPLEKERNEL_MIN_LOG_LEVEL > 0 时编译期消除)
struct per_cpu::PerCpu __attribute__((aligned(SIMPLEKERNEL_PER_CPU_ALIGN_SIZE)))
错误类型,用于 std::expected
Definition expected.hpp:343