SimpleKernel 1.17.0
Loading...
Searching...
No Matches
Interrupt Class Referencefinal

AArch64 中断控制器实现 More...

#include <interrupt.h>

Inheritance diagram for Interrupt:
Inheritance graph
Collaboration diagram for Interrupt:
Collaboration graph

Public Member Functions

auto Do (uint64_t cause, cpu_io::TrapContext *context) -> void override
 执行中断处理
 
auto RegisterInterruptFunc (uint64_t cause, InterruptDelegate func) -> void override
 注册中断处理函数
 
auto SendIpi (uint64_t target_cpu_mask) -> Expected< void > override
 发送 IPI 到指定 CPU
 
auto BroadcastIpi () -> Expected< void > override
 广播 IPI 到所有 CPU
 
auto RegisterExternalInterrupt (uint32_t irq, uint32_t cpu_id, uint32_t priority, InterruptDelegate handler) -> Expected< void > override
 注册外部中断
 
__always_inline auto SetUp () const -> void
 设置 GIC
 
__always_inline auto Spi (uint32_t intid, uint32_t cpuid) const -> void
 设置 SPI 中断
 
__always_inline auto Ppi (uint32_t intid, uint32_t cpuid) const -> void
 设置 PPI 中断
 
__always_inline auto Sgi (uint32_t intid, uint32_t cpuid) const -> void
 设置 SGI 中断
 
auto Do (uint64_t cause, cpu_io::TrapContext *context) -> void override
 执行中断处理
 
auto RegisterInterruptFunc (uint64_t cause, InterruptDelegate func) -> void override
 注册中断处理函数
 
auto SendIpi (uint64_t target_cpu_mask) -> Expected< void > override
 发送 IPI 到指定核心
 
auto BroadcastIpi () -> Expected< void > override
 广播 IPI 到所有其他核心
 
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
 执行中断处理
 
auto RegisterInterruptFunc (uint64_t cause, InterruptDelegate func) -> void override
 注册中断处理函数
 
auto SendIpi (uint64_t target_cpu_mask) -> Expected< void > override
 发送 IPI 到指定核心
 
auto BroadcastIpi () -> Expected< void > override
 广播 IPI 到所有其他核心
 
auto RegisterExternalInterrupt (uint32_t irq, uint32_t cpu_id, uint32_t priority, InterruptDelegate handler) -> Expected< void > override
 注册外部中断处理函数
 
auto InitApic (size_t cpu_count) -> void
 初始化 APIC
 
auto SetUpIdtr () -> void
 初始化 idtr
 
构造/析构函数
 Interrupt ()
 
 Interrupt (const Interrupt &)=delete
 
 Interrupt (Interrupt &&)=delete
 
auto operator= (const Interrupt &) -> Interrupt &=delete
 
auto operator= (Interrupt &&) -> Interrupt &=delete
 
 ~Interrupt ()=default
 
 Interrupt ()
 
 Interrupt (const Interrupt &)=delete
 
 Interrupt (Interrupt &&)=delete
 
auto operator= (const Interrupt &) -> Interrupt &=delete
 
auto operator= (Interrupt &&) -> Interrupt &=delete
 
 ~Interrupt ()=default
 
 Interrupt ()
 
 Interrupt (const Interrupt &)=delete
 
 Interrupt (Interrupt &&)=delete
 
auto operator= (const Interrupt &) -> Interrupt &=delete
 
auto operator= (Interrupt &&) -> Interrupt &=delete
 
 ~Interrupt () override=default
 
PLIC 访问接口
__always_inline auto plic () -> Plic &
 获取 PLIC 引用
 
__always_inline auto plic () const -> const Plic &
 获取 PLIC 的只读引用
 
auto InitPlic (uint64_t dev_addr, size_t ndev, size_t context_count) -> void
 初始化 PLIC
 
APIC 访问接口
__always_inline auto apic () -> Apic &
 
__always_inline auto apic () const -> const Apic &
 
- Public Member Functions inherited from InterruptBase
 InterruptBase ()=default
 
 InterruptBase (const InterruptBase &)=delete
 
 InterruptBase (InterruptBase &&)=delete
 
auto operator= (const InterruptBase &) -> InterruptBase &=delete
 
auto operator= (InterruptBase &&) -> InterruptBase &=delete
 
virtual ~InterruptBase ()=default
 

Static Public Attributes

static constexpr size_t kMaxInterrupt = 128
 最大中断号
 
static constexpr uint8_t kExternalVectorBase = 0x20
 外部中断向量基址(IO APIC IRQ 到 IDT 向量的映射)
 

Private Member Functions

template<uint8_t no = 0>
auto SetUpIdtr () -> void
 初始化 idtr
 

Private Attributes

std::array< InterruptDelegate, kMaxInterruptinterrupt_handlers_ {}
 中断处理函数数组
 
Gic gic_ {}
 GIC 中断控制器实例
 
std::array< InterruptDelegate, cpu_io::ScauseInfo::kInterruptMaxCount > interrupt_handlers_ {}
 中断处理函数数组
 
std::array< InterruptDelegate, cpu_io::ScauseInfo::kExceptionMaxCount > exception_handlers_ {}
 异常处理函数数组
 
Plic plic_ {}
 
std::array< InterruptDelegate, cpu_io::IdtrInfo::kInterruptMaxCount > interrupt_handlers_ {}
 中断处理函数数组
 
std::array< cpu_io::IdtrInfo::Idt, cpu_io::IdtrInfo::kInterruptMaxCount > idts_ {}
 
Apic apic_ {}
 APIC 中断控制器实例
 

Additional Inherited Members

- Public Types inherited from InterruptBase
using InterruptDelegate = etl::delegate< uint64_t(uint64_t, cpu_io::TrapContext *)>
 类型安全的中断处理委托
 

Detailed Description

AArch64 中断控制器实现

Definition at line 19 of file interrupt.h.

Constructor & Destructor Documentation

◆ Interrupt() [1/9]

Interrupt::Interrupt ( )

Definition at line 27 of file interrupt.cpp.

27 {
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()
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
50
51 // 注册默认中断处理函数
52 for (auto& i : interrupt_handlers_) {
53 i = InterruptDelegate::create<DefaultInterruptHandler>();
54 }
55
56 // 设置 SGI 0 用于 IPI
58 gic_.Sgi(0, cpuid);
59
60 klog::Info("Interrupt init.");
61}
GIC 中断控制器驱动
Definition gic.h:17
auto Sgi(uint32_t intid, uint32_t cpuid) const -> void
配置软件生成中断 (SGI)
Definition gic.cpp:39
auto SetUpIdtr() -> void
初始化 idtr
Definition interrupt.cpp:62
Gic gic_
GIC 中断控制器实例
Definition interrupt.h:113
std::array< InterruptDelegate, kMaxInterrupt > interrupt_handlers_
中断处理函数数组
Definition interrupt.h:110
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
Here is the call graph for this function:

◆ Interrupt() [2/9]

Interrupt::Interrupt ( const Interrupt )
delete

◆ Interrupt() [3/9]

Interrupt::Interrupt ( Interrupt &&  )
delete

◆ ~Interrupt() [1/3]

Interrupt::~Interrupt ( )
default

◆ Interrupt() [4/9]

Interrupt::Interrupt ( )

◆ Interrupt() [5/9]

Interrupt::Interrupt ( const Interrupt )
delete

◆ Interrupt() [6/9]

Interrupt::Interrupt ( Interrupt &&  )
delete

◆ ~Interrupt() [2/3]

Interrupt::~Interrupt ( )
default

◆ Interrupt() [7/9]

Interrupt::Interrupt ( )

◆ Interrupt() [8/9]

Interrupt::Interrupt ( const Interrupt )
delete

◆ Interrupt() [9/9]

Interrupt::Interrupt ( Interrupt &&  )
delete

◆ ~Interrupt() [3/3]

Interrupt::~Interrupt ( )
overridedefault

Member Function Documentation

◆ apic() [1/2]

__always_inline auto Interrupt::apic ( ) -> Apic&
inline

Definition at line 39 of file interrupt.h.

39{ return apic_; }
Apic apic_
APIC 中断控制器实例
Definition interrupt.h:76

◆ apic() [2/2]

__always_inline auto Interrupt::apic ( ) const -> const Apic&
inline

Definition at line 40 of file interrupt.h.

40 {
41 return apic_;
42 }

◆ BroadcastIpi() [1/3]

auto Interrupt::BroadcastIpi ( ) -> Expected<void>
overridevirtual

广播 IPI 到所有 CPU

Returns
Expected<void> 成功或失败
Todo:
默认使用 SGI 0 作为 IPI 中断

Implements InterruptBase.

Definition at line 93 of file interrupt.cpp.

93 {
95 static constexpr uint64_t kIPISGI = 0;
96
97 // 构造 ICC_SGI1R_EL1 寄存器的值
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}

◆ BroadcastIpi() [2/3]

auto Interrupt::BroadcastIpi ( ) -> Expected< void >
overridevirtual

广播 IPI 到所有其他核心

Returns
Expected<void> 成功时返回 void,失败时返回错误

Implements InterruptBase.

◆ BroadcastIpi() [3/3]

auto Interrupt::BroadcastIpi ( ) -> Expected< void >
overridevirtual

广播 IPI 到所有其他核心

Returns
Expected<void> 成功时返回 void,失败时返回错误

Implements InterruptBase.

◆ Do() [1/3]

auto Interrupt::Do ( uint64_t  cause,
cpu_io::TrapContext context 
) -> void
overridevirtual

执行中断处理

Parameters
cause中断号
context中断上下文

Implements InterruptBase.

Definition at line 63 of file interrupt.cpp.

63 {
65 cpu_io::ICC_EOIR1_EL1::Write(cause);
66}

◆ Do() [2/3]

auto Interrupt::Do ( uint64_t  cause,
cpu_io::TrapContext context 
) -> void
overridevirtual

执行中断处理

Parameters
cause中断原因值(scause 寄存器内容)
context中断上下文

Implements InterruptBase.

◆ Do() [3/3]

auto Interrupt::Do ( uint64_t  ,
cpu_io::TrapContext  
) -> void
overridevirtual

执行中断处理

Parameters
不同平台有不同含义

Implements InterruptBase.

◆ InitApic()

auto Interrupt::InitApic ( size_t  cpu_count) -> void

初始化 APIC

Parameters
cpu_countCPU 核心数

Definition at line 128 of file interrupt.cpp.

128{ apic_ = Apic(cpu_count); }
APIC 管理类,管理整个系统的 Local APIC 和 IO APIC.
Definition apic.h:22

◆ InitPlic()

auto Interrupt::InitPlic ( uint64_t  dev_addr,
size_t  ndev,
size_t  context_count 
) -> void

初始化 PLIC

Parameters
dev_addrPLIC 设备地址
ndev支持的中断源数量
context_count上下文数量

Definition at line 135 of file interrupt.cpp.

136 {
138}
Plic plic_
Definition interrupt.h:98
Plic 驱动
Definition plic.h:20

◆ operator=() [1/6]

◆ operator=() [2/6]

◆ operator=() [3/6]

◆ operator=() [4/6]

◆ operator=() [5/6]

◆ operator=() [6/6]

◆ plic() [1/2]

__always_inline auto Interrupt::plic ( ) -> Plic&
inline

获取 PLIC 引用

Returns
Plic& PLIC 实例引用

Definition at line 63 of file interrupt.h.

63{ return plic_; }

◆ plic() [2/2]

__always_inline auto Interrupt::plic ( ) const -> const Plic&
inline

获取 PLIC 的只读引用

Returns
const Plic& PLIC 实例常量引用

Definition at line 68 of file interrupt.h.

68 {
69 return plic_;
70 }

◆ Ppi()

__always_inline auto Interrupt::Ppi ( uint32_t  intid,
uint32_t  cpuid 
) const -> void
inline

设置 PPI 中断

Parameters
intid中断号
cpuidCPU 编号

Definition at line 85 of file interrupt.h.

85 {
87 }
auto Ppi(uint32_t intid, uint32_t cpuid) const -> void
配置私有外设中断 (PPI)
Definition gic.cpp:35
Here is the call graph for this function:

◆ RegisterExternalInterrupt() [1/3]

auto Interrupt::RegisterExternalInterrupt ( uint32_t  irq,
uint32_t  cpu_id,
uint32_t  priority,
InterruptDelegate  handler 
) -> Expected<void>
overridevirtual

注册外部中断

Parameters
irqGIC INTID(已含 kSpiBase 偏移)
cpu_idCPU 编号
priority中断优先级
handler中断处理委托
Returns
Expected<void> 成功或失败

Implements InterruptBase.

Definition at line 112 of file interrupt.cpp.

115 {
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}
auto Spi(uint32_t intid, uint32_t cpuid) const -> void
配置共享外设中断 (SPI)
Definition gic.cpp:31
static constexpr size_t kMaxInterrupt
最大中断号
Definition interrupt.h:22
auto RegisterInterruptFunc(uint64_t cause, InterruptDelegate func) -> void override
注册中断处理函数
Definition interrupt.cpp:68
@ kIrqChipInvalidIrq
Here is the call graph for this function:

◆ RegisterExternalInterrupt() [2/3]

auto Interrupt::RegisterExternalInterrupt ( uint32_t  irq,
uint32_t  cpu_id,
uint32_t  priority,
InterruptDelegate  handler 
) -> Expected< void >
overridevirtual

注册外部中断处理函数

Parameters
irq外部中断号(PLIC source_id)
cpu_id目标 CPU 核心 ID
priority中断优先级
handler中断处理委托
Returns
Expected<void> 成功时返回 void,失败时返回错误

Implements InterruptBase.

◆ RegisterExternalInterrupt() [3/3]

auto Interrupt::RegisterExternalInterrupt ( uint32_t  irq,
uint32_t  cpu_id,
uint32_t  priority,
InterruptDelegate  handler 
) -> Expected< void >
overridevirtual

注册外部中断处理函数

Parameters
irq外部中断号(平台相关: PLIC source_id / GIC INTID / APIC IRQ)
cpu_id目标 CPU 核心 ID,中断将路由到该核心
priority中断优先级
handler中断处理函数
Returns
Expected<void> 成功时返回 void,失败时返回错误

Implements InterruptBase.

◆ RegisterInterruptFunc() [1/3]

auto Interrupt::RegisterInterruptFunc ( uint64_t  cause,
InterruptDelegate  func 
) -> void
overridevirtual

注册中断处理函数

Parameters
cause中断号
func中断处理委托

Implements InterruptBase.

Definition at line 68 of file interrupt.cpp.

69 {
70 if (func) {
72 }
73}

◆ RegisterInterruptFunc() [2/3]

auto Interrupt::RegisterInterruptFunc ( uint64_t  cause,
InterruptDelegate  func 
) -> void
overridevirtual

注册中断处理函数

Parameters
cause中断原因值(scause 格式)
func中断处理委托

Implements InterruptBase.

◆ RegisterInterruptFunc() [3/3]

auto Interrupt::RegisterInterruptFunc ( uint64_t  cause,
InterruptDelegate  func 
) -> void
overridevirtual

注册中断处理函数

Parameters
cause中断号,不同平台有不同含义
func处理函数

Implements InterruptBase.

◆ SendIpi() [1/3]

auto Interrupt::SendIpi ( uint64_t  target_cpu_mask) -> Expected<void>
overridevirtual

发送 IPI 到指定 CPU

Parameters
target_cpu_mask目标 CPU 位掩码
Returns
Expected<void> 成功或失败
Todo:
默认使用 SGI 0 作为 IPI 中断

Implements InterruptBase.

Definition at line 75 of file interrupt.cpp.

75 {
77 static constexpr uint64_t kIPISGI = 0;
78
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}

◆ SendIpi() [2/3]

auto Interrupt::SendIpi ( uint64_t  target_cpu_mask) -> Expected< void >
overridevirtual

发送 IPI 到指定核心

Parameters
target_cpu_mask目标核心的位掩码
Returns
Expected<void> 成功时返回 void,失败时返回错误

Implements InterruptBase.

◆ SendIpi() [3/3]

auto Interrupt::SendIpi ( uint64_t  target_cpu_mask) -> Expected< void >
overridevirtual

发送 IPI 到指定核心

Parameters
target_cpu_mask目标核心的位掩码
Returns
Expected<void> 成功时返回 void,失败时返回错误

Implements InterruptBase.

◆ SetUp()

__always_inline auto Interrupt::SetUp ( ) const -> void
inline

设置 GIC

Definition at line 69 of file interrupt.h.

69{ gic_.SetUp(); }
auto SetUp() const -> void
初始化当前 CPU 的 GIC 配置
Definition gic.cpp:23
Here is the call graph for this function:

◆ SetUpIdtr() [1/2]

auto Interrupt::SetUpIdtr ( ) -> void

初始化 idtr

Definition at line 62 of file interrupt.cpp.

62{ SetUpIdtr<0>(); }

◆ SetUpIdtr() [2/2]

template<uint8_t no>
auto Interrupt::SetUpIdtr ( ) -> void
private

初始化 idtr

Note
注意模板展开时的栈溢出

Definition at line 65 of file interrupt.cpp.

65 {
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);
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}
std::array< cpu_io::IdtrInfo::Idt, cpu_io::IdtrInfo::kInterruptMaxCount > idts_
Definition interrupt.h:73
auto Debug(etl::format_string< Args... > fmt, Args &&... args) -> void
以 DEBUG 级别记录日志(SIMPLEKERNEL_MIN_LOG_LEVEL > 0 时编译期消除)
Here is the call graph for this function:

◆ Sgi()

__always_inline auto Interrupt::Sgi ( uint32_t  intid,
uint32_t  cpuid 
) const -> void
inline

设置 SGI 中断

Parameters
intid中断号
cpuidCPU 编号

Definition at line 94 of file interrupt.h.

94 {
96 }
Here is the call graph for this function:

◆ Spi()

__always_inline auto Interrupt::Spi ( uint32_t  intid,
uint32_t  cpuid 
) const -> void
inline

设置 SPI 中断

Parameters
intid中断号
cpuidCPU 编号

Definition at line 76 of file interrupt.h.

76 {
78 }
Here is the call graph for this function:

Member Data Documentation

◆ apic_

Apic Interrupt::apic_ {}
private

APIC 中断控制器实例

Definition at line 76 of file interrupt.h.

76{};

◆ exception_handlers_

std::array<InterruptDelegate, cpu_io::ScauseInfo::kExceptionMaxCount> Interrupt::exception_handlers_ {}
private

异常处理函数数组

Definition at line 97 of file interrupt.h.

97{};

◆ gic_

Gic Interrupt::gic_ {}
private

GIC 中断控制器实例

Definition at line 113 of file interrupt.h.

113{};

◆ idts_

std::array<cpu_io::IdtrInfo::Idt, cpu_io::IdtrInfo::kInterruptMaxCount> Interrupt::idts_ {}
private

Definition at line 73 of file interrupt.h.

73{};

◆ interrupt_handlers_ [1/3]

std::array<InterruptDelegate, kMaxInterrupt> Interrupt::interrupt_handlers_ {}
private

中断处理函数数组

Definition at line 110 of file interrupt.h.

110{};

◆ interrupt_handlers_ [2/3]

std::array<InterruptDelegate, cpu_io::ScauseInfo::kInterruptMaxCount> Interrupt::interrupt_handlers_ {}
private

中断处理函数数组

Definition at line 94 of file interrupt.h.

94{};

◆ interrupt_handlers_ [3/3]

std::array<InterruptDelegate, cpu_io::IdtrInfo::kInterruptMaxCount> Interrupt::interrupt_handlers_ {}
private

中断处理函数数组

Definition at line 70 of file interrupt.h.

70{};

◆ kExternalVectorBase

constexpr uint8_t Interrupt::kExternalVectorBase = 0x20
staticconstexpr

外部中断向量基址(IO APIC IRQ 到 IDT 向量的映射)

Definition at line 20 of file interrupt.h.

◆ kMaxInterrupt

constexpr size_t Interrupt::kMaxInterrupt = 128
staticconstexpr

最大中断号

Definition at line 22 of file interrupt.h.

◆ plic_

Plic Interrupt::plic_ {}
private

Definition at line 98 of file interrupt.h.

98{};

The documentation for this class was generated from the following files: