16 cpu_io::Pic::Disable();
20 return local_apic_.Init()
23 "Local APIC initialized successfully for CPU with APIC ID {:#x}",
28 klog::Err(
"Failed to initialize Local APIC for current CPU: {}",
30 return std::unexpected(err);
35 uint32_t destination_apic_id,
bool mask)
38 if (irq >= io_apic_.GetMaxRedirectionEntries()) {
39 klog::Err(
"IRQ {} exceeds IO APIC range (max: {})", irq,
40 io_apic_.GetMaxRedirectionEntries() - 1);
45 io_apic_.SetIrqRedirection(irq, vector, destination_apic_id, mask);
51 if (irq >= io_apic_.GetMaxRedirectionEntries()) {
52 klog::Err(
"IRQ {} exceeds IO APIC range (max: {})", irq,
53 io_apic_.GetMaxRedirectionEntries() - 1);
57 io_apic_.MaskIrq(irq);
63 if (irq >= io_apic_.GetMaxRedirectionEntries()) {
64 klog::Err(
"IRQ {} exceeds IO APIC range (max: {})", irq,
65 io_apic_.GetMaxRedirectionEntries() - 1);
69 io_apic_.UnmaskIrq(irq);
75 return local_apic_.SendIpi(target_apic_id, vector);
79 return local_apic_.BroadcastIpi(vector);
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)");
91 std::memcpy(
reinterpret_cast<void*
>(target_addr),
92 reinterpret_cast<void*
>(ap_code_addr), ap_code_size);
95 if (std::memcmp(
reinterpret_cast<const void*
>(target_addr),
96 reinterpret_cast<const void*
>(ap_code_addr),
98 klog::Err(
"AP code copy verification failed");
103 auto start_vector =
static_cast<uint8_t
>(target_addr >> 12);
105 local_apic_.WakeupAp(apic_id, start_vector);
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)");
120 for (
size_t apic_id = 0; apic_id < cpu_count_; apic_id++) {
125 StartupAp(
static_cast<uint32_t
>(apic_id), ap_code_addr, ap_code_size,
128 klog::Err(
"Failed to start AP with APIC ID {:#x}: {}", apic_id,
130 return std::unexpected(err);
139 local_apic_.SetupPeriodicTimer(frequency_hz, vector);
auto InitCurrentCpuLocalApic() -> Expected< void >
初始化当前 CPU 的 Local APIC
auto BroadcastIpi(uint8_t vector) const -> Expected< void >
广播 IPI 到所有其他 CPU
auto PrintInfo() const -> void
打印所有 APIC 信息(调试用)
auto SendIpi(uint32_t target_apic_id, uint8_t vector) const -> Expected< void >
发送 IPI 到指定 CPU
auto SetupPeriodicTimer(uint32_t frequency_hz, uint8_t vector) const -> void
设置 Local APIC 定时器
auto SendEoi() const -> void
发送 EOI 信号给当前 CPU 的 Local APIC
IoApic io_apic_
只支持一个 IO APIC
auto SetIrqRedirection(uint8_t irq, uint8_t vector, uint32_t destination_apic_id, bool mask=false) -> Expected< void >
设置 IRQ 重定向
auto StartupAllAps(uint64_t ap_code_addr, size_t ap_code_size, uint64_t target_addr) const -> void
唤醒所有应用处理器 (AP)
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)
auto UnmaskIrq(uint8_t irq) -> Expected< void >
取消屏蔽 IRQ
auto MaskIrq(uint8_t irq) -> Expected< void >
屏蔽 IRQ
LocalApic local_apic_
Local APIC 操作接口(静态实例,用于当前 CPU)
auto PrintInfo() const -> void
打印 IO APIC 信息(调试用)
auto SendEoi() const -> void
发送中断结束信号 (EOI)
auto PrintInfo() const -> void
打印 Local APIC 信息(调试用)
std::expected< T, Error > Expected
std::expected 别名模板
auto GetCurrentCoreId() -> size_t
auto Err(etl::format_string< Args... > fmt, Args &&... args) -> void
以 ERROR 级别记录日志
auto Info(etl::format_string< Args... > fmt, Args &&... args) -> void
以 INFO 级别记录日志
constexpr auto message() const -> const char *