SimpleKernel 1.17.0
Loading...
Searching...
No Matches
apic.cpp
Go to the documentation of this file.
1
5#include "apic.h"
6
7#include <cpu_io.h>
8
9#include <cassert>
10#include <cstring>
11
12#include "kernel_log.hpp"
13
14Apic::Apic(size_t cpu_count) : cpu_count_(cpu_count) {
15 // 禁用传统的 8259A PIC 以避免与 APIC 冲突
16 cpu_io::Pic::Disable();
17}
18
20 return local_apic_.Init()
21 .and_then([]() -> Expected<void> {
23 "Local APIC initialized successfully for CPU with APIC ID {:#x}",
25 return {};
26 })
27 .or_else([](Error err) -> Expected<void> {
28 klog::Err("Failed to initialize Local APIC for current CPU: {}",
29 err.message());
30 return std::unexpected(err);
31 });
32}
33
34auto Apic::SetIrqRedirection(uint8_t irq, uint8_t vector,
35 uint32_t destination_apic_id, bool mask)
37 // 检查 IRQ 是否在有效范围内
38 if (irq >= io_apic_.GetMaxRedirectionEntries()) {
39 klog::Err("IRQ {} exceeds IO APIC range (max: {})", irq,
40 io_apic_.GetMaxRedirectionEntries() - 1);
41 return std::unexpected(Error(ErrorCode::kApicInvalidIrq));
42 }
43
44 // 设置重定向
45 io_apic_.SetIrqRedirection(irq, vector, destination_apic_id, mask);
46 return {};
47}
48
49auto Apic::MaskIrq(uint8_t irq) -> Expected<void> {
50 // 检查 IRQ 是否在有效范围内
51 if (irq >= io_apic_.GetMaxRedirectionEntries()) {
52 klog::Err("IRQ {} exceeds IO APIC range (max: {})", irq,
53 io_apic_.GetMaxRedirectionEntries() - 1);
54 return std::unexpected(Error(ErrorCode::kApicInvalidIrq));
55 }
56
57 io_apic_.MaskIrq(irq);
58 return {};
59}
60
61auto Apic::UnmaskIrq(uint8_t irq) -> Expected<void> {
62 // 检查 IRQ 是否在有效范围内
63 if (irq >= io_apic_.GetMaxRedirectionEntries()) {
64 klog::Err("IRQ {} exceeds IO APIC range (max: {})", irq,
65 io_apic_.GetMaxRedirectionEntries() - 1);
66 return std::unexpected(Error(ErrorCode::kApicInvalidIrq));
67 }
68
69 io_apic_.UnmaskIrq(irq);
70 return {};
71}
72
73auto Apic::SendIpi(uint32_t target_apic_id, uint8_t vector) const
75 return local_apic_.SendIpi(target_apic_id, vector);
76}
77
78auto Apic::BroadcastIpi(uint8_t vector) const -> Expected<void> {
79 return local_apic_.BroadcastIpi(vector);
80}
81
82auto Apic::StartupAp(uint32_t apic_id, uint64_t ap_code_addr,
83 size_t ap_code_size, uint64_t target_addr) const
85 assert(ap_code_addr != 0 && "AP code address must not be null");
86 assert(ap_code_size != 0 && "AP code size must not be zero");
87 assert((target_addr & 0xFFF) == 0 && "Target address must be 4KB aligned");
88 assert(target_addr < 0x100000 &&
89 "Target address exceeds real mode limit (1MB)");
90
91 std::memcpy(reinterpret_cast<void*>(target_addr),
92 reinterpret_cast<void*>(ap_code_addr), ap_code_size);
93
94 // 验证复制是否成功
95 if (std::memcmp(reinterpret_cast<const void*>(target_addr),
96 reinterpret_cast<const void*>(ap_code_addr),
97 ap_code_size) != 0) {
98 klog::Err("AP code copy verification failed");
99 return std::unexpected(Error(ErrorCode::kApicCodeCopyFailed));
100 }
101
102 // 计算启动向量 (物理地址 / 4096)
103 auto start_vector = static_cast<uint8_t>(target_addr >> 12);
104 // 使用 Local APIC 发送 INIT-SIPI-SIPI 序列
105 local_apic_.WakeupAp(apic_id, start_vector);
106
107 return {};
108}
109
110auto Apic::StartupAllAps(uint64_t ap_code_addr, size_t ap_code_size,
111 uint64_t target_addr) const -> void {
112 assert(ap_code_addr != 0 && "AP code address must not be null");
113 assert(ap_code_size != 0 && "AP code size must not be zero");
114 assert((target_addr & 0xFFF) == 0 && "Target address must be 4KB aligned");
115 assert(target_addr < 0x100000 &&
116 "Target address exceeds real mode limit (1MB)");
117
118 // 启动 APIC ID 0 到 cpu_count_-1 的所有处理器
119 // 跳过当前的 BSP (Bootstrap Processor)
120 for (size_t apic_id = 0; apic_id < cpu_count_; apic_id++) {
121 // 跳过当前 BSP
122 if (static_cast<uint32_t>(apic_id) == cpu_io::GetCurrentCoreId()) {
123 continue;
124 }
125 StartupAp(static_cast<uint32_t>(apic_id), ap_code_addr, ap_code_size,
126 target_addr)
127 .or_else([apic_id](Error err) -> Expected<void> {
128 klog::Err("Failed to start AP with APIC ID {:#x}: {}", apic_id,
129 err.message());
130 return std::unexpected(err);
131 });
132 }
133}
134
135auto Apic::SendEoi() const -> void { local_apic_.SendEoi(); }
136
137auto Apic::SetupPeriodicTimer(uint32_t frequency_hz, uint8_t vector) const
138 -> void {
139 local_apic_.SetupPeriodicTimer(frequency_hz, vector);
140}
141
142auto Apic::PrintInfo() const -> void {
145}
auto InitCurrentCpuLocalApic() -> Expected< void >
初始化当前 CPU 的 Local APIC
Definition apic.cpp:19
auto BroadcastIpi(uint8_t vector) const -> Expected< void >
广播 IPI 到所有其他 CPU
Definition apic.cpp:78
auto PrintInfo() const -> void
打印所有 APIC 信息(调试用)
Definition apic.cpp:142
auto SendIpi(uint32_t target_apic_id, uint8_t vector) const -> Expected< void >
发送 IPI 到指定 CPU
Definition apic.cpp:73
auto SetupPeriodicTimer(uint32_t frequency_hz, uint8_t vector) const -> void
设置 Local APIC 定时器
Definition apic.cpp:137
auto SendEoi() const -> void
发送 EOI 信号给当前 CPU 的 Local APIC
Definition apic.cpp:135
IoApic io_apic_
只支持一个 IO APIC
Definition apic.h:130
auto SetIrqRedirection(uint8_t irq, uint8_t vector, uint32_t destination_apic_id, bool mask=false) -> Expected< void >
设置 IRQ 重定向
Definition apic.cpp:34
auto StartupAllAps(uint64_t ap_code_addr, size_t ap_code_size, uint64_t target_addr) const -> void
唤醒所有应用处理器 (AP)
Definition apic.cpp:110
auto StartupAp(uint32_t apic_id, uint64_t ap_code_addr, size_t ap_code_size, uint64_t target_addr) const -> Expected< void >
启动 AP (Application Processor)
Definition apic.cpp:82
auto UnmaskIrq(uint8_t irq) -> Expected< void >
取消屏蔽 IRQ
Definition apic.cpp:61
Apic()=default
auto MaskIrq(uint8_t irq) -> Expected< void >
屏蔽 IRQ
Definition apic.cpp:49
LocalApic local_apic_
Local APIC 操作接口(静态实例,用于当前 CPU)
Definition apic.h:127
auto PrintInfo() const -> void
打印 IO APIC 信息(调试用)
Definition io_apic.cpp:88
auto SendEoi() const -> void
发送中断结束信号 (EOI)
auto PrintInfo() const -> void
打印 Local APIC 信息(调试用)
@ kApicCodeCopyFailed
std::expected< T, Error > Expected
std::expected 别名模板
Definition expected.hpp:365
auto GetCurrentCoreId() -> size_t
Definition cpu_io.h:26
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