SimpleKernel 1.17.0
Loading...
Searching...
No Matches
io_apic.cpp
Go to the documentation of this file.
1
5#include "io_apic.h"
6
7#include <etl/io_port.h>
8
9#include "kernel_log.hpp"
10
12 // 禁用所有重定向条目(设置为屏蔽状态)
13 for (uint32_t i = 0; i < GetMaxRedirectionEntries(); i++) {
14 auto entry = ReadRedirectionEntry(i);
15 entry |= kMaskBit;
16 WriteRedirectionEntry(i, entry);
17 }
18
19 klog::Info("IO APIC initialization completed");
20}
21
22auto IoApic::SetIrqRedirection(uint8_t irq, uint8_t vector,
23 uint32_t destination_apic_id, bool mask) const
24 -> void {
25 // 检查 IRQ 是否在有效范围内
26 auto max_entries = GetMaxRedirectionEntries();
27 if (irq >= max_entries) {
28 klog::Err("IRQ {} exceeds maximum entries {}", irq, max_entries);
29 return;
30 }
31
32 // 构造重定向表项
33 uint64_t entry = 0;
34
35 // 设置中断向量 (位 0-7)
36 entry |= vector & kVectorMask;
37 // 设置屏蔽位 (位 16)
38 if (mask) {
39 entry |= kMaskBit;
40 }
41
42 // 设置目标 APIC ID (位 56-63)
43 entry |= (static_cast<uint64_t>(destination_apic_id & kDestApicIdMask)
44 << kDestApicIdShift);
45
46 WriteRedirectionEntry(irq, entry);
47}
48
49auto IoApic::MaskIrq(uint8_t irq) const -> void {
50 auto max_entries = GetMaxRedirectionEntries();
51 if (irq >= max_entries) {
52 klog::Err("IRQ {} exceeds maximum entries {}", irq, max_entries);
53 return;
54 }
55
56 auto entry = ReadRedirectionEntry(irq);
57 entry |= kMaskBit;
58 WriteRedirectionEntry(irq, entry);
59}
60
61auto IoApic::UnmaskIrq(uint8_t irq) const -> void {
62 auto max_entries = GetMaxRedirectionEntries();
63 if (irq >= max_entries) {
64 klog::Err("IRQ {} exceeds maximum entries {}", irq, max_entries);
65 return;
66 }
67
68 auto entry = ReadRedirectionEntry(irq);
69 entry &= ~kMaskBit;
70 WriteRedirectionEntry(irq, entry);
71}
72
73auto IoApic::GetId() const -> uint32_t {
74 // ID 位于位 24-27
75 return (Read(kRegId) >> 24) & 0x0F;
76}
77
78auto IoApic::GetVersion() const -> uint32_t {
79 // 版本位于位 0-7
80 return Read(kRegVer) & 0xFF;
81}
82
83auto IoApic::GetMaxRedirectionEntries() const -> uint32_t {
84 // MRE 位于位 16-23,实际数量需要 +1
85 return ((Read(kRegVer) >> 16) & 0xFF) + 1;
86}
87
88auto IoApic::PrintInfo() const -> void {
89 klog::Info("IO APIC Information");
90 klog::Info("Base Address: {:#x}", base_address_);
91 klog::Info("ID: {:#x}", GetId());
92 klog::Info("Version: {:#x}", GetVersion());
93 klog::Info("Max Redirection Entries: {}", GetMaxRedirectionEntries());
94}
95
96auto IoApic::Read(uint32_t reg) const -> uint32_t {
97 etl::io_port_wo<uint32_t> sel{
98 reinterpret_cast<void*>(base_address_ + kRegSel)};
99 sel.write(reg);
100 etl::io_port_ro<uint32_t> win{
101 reinterpret_cast<void*>(base_address_ + kRegWin)};
102 return win.read();
103}
104
105auto IoApic::Write(uint32_t reg, uint32_t value) const -> void {
106 etl::io_port_wo<uint32_t> sel{
107 reinterpret_cast<void*>(base_address_ + kRegSel)};
108 sel.write(reg);
109 etl::io_port_wo<uint32_t> win{
110 reinterpret_cast<void*>(base_address_ + kRegWin)};
111 win.write(value);
112}
113
114auto IoApic::ReadRedirectionEntry(uint8_t irq) const -> uint64_t {
115 auto low_reg = kRedTblBase + (irq * 2);
116 auto high_reg = low_reg + 1;
117
118 auto low = Read(low_reg);
119 auto high = Read(high_reg);
120
121 return (static_cast<uint64_t>(high) << 32) | low;
122}
123
124auto IoApic::WriteRedirectionEntry(uint8_t irq, uint64_t value) const -> void {
125 auto low_reg = kRedTblBase + (irq * 2);
126 auto high_reg = low_reg + 1;
127
128 auto low = static_cast<uint32_t>(value & 0xFFFFFFFF);
129 auto high = static_cast<uint32_t>((value >> 32) & 0xFFFFFFFF);
130
131 Write(low_reg, low);
132 Write(high_reg, high);
133}
uint64_t base_address_
IO APIC 基地址
Definition io_apic.h:142
static constexpr uint32_t kRegVer
IO APIC 版本寄存器索引
Definition io_apic.h:88
auto Read(uint32_t reg) const -> uint32_t
读取 IO APIC 寄存器
Definition io_apic.cpp:96
auto UnmaskIrq(uint8_t irq) const -> void
取消屏蔽 IRQ
Definition io_apic.cpp:61
auto GetId() const -> uint32_t
获取 IO APIC ID
Definition io_apic.cpp:73
auto GetMaxRedirectionEntries() const -> uint32_t
获取 IO APIC 最大重定向条目数
Definition io_apic.cpp:83
auto GetVersion() const -> uint32_t
获取 IO APIC 版本
Definition io_apic.cpp:78
auto SetIrqRedirection(uint8_t irq, uint8_t vector, uint32_t destination_apic_id, bool mask=false) const -> void
设置 IO APIC 重定向表项
Definition io_apic.cpp:22
IoApic()
Definition io_apic.cpp:11
auto Write(uint32_t reg, uint32_t value) const -> void
写入 IO APIC 寄存器
Definition io_apic.cpp:105
static constexpr uint32_t kRegId
Definition io_apic.h:86
auto PrintInfo() const -> void
打印 IO APIC 信息(调试用)
Definition io_apic.cpp:88
auto WriteRedirectionEntry(uint8_t irq, uint64_t value) const -> void
写入 IO APIC 重定向表项
Definition io_apic.cpp:124
static constexpr uint64_t kMaskBit
屏蔽位 (位 16)
Definition io_apic.h:112
auto ReadRedirectionEntry(uint8_t irq) const -> uint64_t
读取 IO APIC 重定向表项
Definition io_apic.cpp:114
auto MaskIrq(uint8_t irq) const -> void
屏蔽 IRQ
Definition io_apic.cpp:49
auto Err(etl::format_string< Args... > fmt, Args &&... args) -> void
以 ERROR 级别记录日志
auto Info(etl::format_string< Args... > fmt, Args &&... args) -> void
以 INFO 级别记录日志