SimpleKernel 1.17.0
Loading...
Searching...
No Matches
local_apic.cpp
Go to the documentation of this file.
1
5#include <etl/io_port.h>
6
7#include "apic.h"
8#include "kernel_log.hpp"
9
11 // 检查 APIC 是否全局启用
12 if (!cpu_io::msr::apic::IsGloballyEnabled()) {
13 cpu_io::msr::apic::EnableGlobally();
14 }
15
16 // 首先尝试启用 x2APIC 模式
17 if (EnableX2Apic()) {
18 is_x2apic_mode_ = true;
19 } else {
20 if (!EnableXApic()) {
21 klog::Err("Failed to enable APIC in any mode");
22 return std::unexpected(Error(ErrorCode::kApicInitFailed));
23 }
24 is_x2apic_mode_ = false;
25 }
26
27 // 启用 Local APIC(通过设置 SIVR)
28 uint32_t sivr;
29 if (is_x2apic_mode_) {
30 sivr = cpu_io::msr::apic::ReadSivr();
31 } else {
32 etl::io_port_ro<uint32_t> sivr_reg{
33 reinterpret_cast<void*>(apic_base_ + kXApicSivrOffset)};
34 sivr = sivr_reg.read();
35 }
36
37 // 设置 APIC Software Enable 位
38 sivr |= kApicSoftwareEnableBit;
39 // 设置虚假中断向量为 0xFF
40 sivr |= kSpuriousVector;
41
42 if (is_x2apic_mode_) {
43 cpu_io::msr::apic::WriteSivr(sivr);
44 } else {
45 etl::io_port_wo<uint32_t> sivr_reg{
46 reinterpret_cast<void*>(apic_base_ + kXApicSivrOffset)};
47 sivr_reg.write(sivr);
48 }
49
50 // 清除任务优先级
51 SetTaskPriority(0);
52
53 // 禁用所有 LVT 条目(设置 mask 位)
54 if (is_x2apic_mode_) {
55 cpu_io::msr::apic::WriteLvtTimer(kLvtMaskBit);
56 cpu_io::msr::apic::WriteLvtLint0(kLvtMaskBit);
57 cpu_io::msr::apic::WriteLvtLint1(kLvtMaskBit);
58 cpu_io::msr::apic::WriteLvtError(kLvtMaskBit);
59 } else {
60 // xAPIC 模式下通过内存映射写入
61 etl::io_port_wo<uint32_t> lvt_timer{
62 reinterpret_cast<void*>(apic_base_ + kXApicLvtTimerOffset)};
63 lvt_timer.write(kLvtMaskBit);
64 etl::io_port_wo<uint32_t> lvt_lint0{
65 reinterpret_cast<void*>(apic_base_ + kXApicLvtLint0Offset)};
66 lvt_lint0.write(kLvtMaskBit);
67 etl::io_port_wo<uint32_t> lvt_lint1{
68 reinterpret_cast<void*>(apic_base_ + kXApicLvtLint1Offset)};
69 lvt_lint1.write(kLvtMaskBit);
70 etl::io_port_wo<uint32_t> lvt_error{
71 reinterpret_cast<void*>(apic_base_ + kXApicLvtErrorOffset)};
72 lvt_error.write(kLvtMaskBit);
73 }
74 return {};
75}
76
77auto LocalApic::GetApicVersion() const -> uint32_t {
78 if (is_x2apic_mode_) {
79 return cpu_io::msr::apic::ReadVersion();
80 } else {
81 // 版本寄存器在偏移 0x30 处
82 etl::io_port_ro<uint32_t> ver_reg{
83 reinterpret_cast<void*>(apic_base_ + kXApicVersionOffset)};
84 return ver_reg.read();
85 }
86}
87
88auto LocalApic::SendEoi() const -> void {
89 if (is_x2apic_mode_) {
90 cpu_io::msr::apic::WriteEoi(0);
91 } else {
92 // 写入 EOI 寄存器(偏移 0xB0)
93 etl::io_port_wo<uint32_t> eoi_reg{
94 reinterpret_cast<void*>(apic_base_ + kXApicEoiOffset)};
95 eoi_reg.write(0);
96 }
97}
98
99auto LocalApic::SendIpi(uint32_t destination_apic_id, uint8_t vector) const
100 -> Expected<void> {
101 if (is_x2apic_mode_) {
102 auto icr = static_cast<uint64_t>(vector);
103 icr |= static_cast<uint64_t>(destination_apic_id) << 32;
104
105 cpu_io::msr::apic::WriteIcr(icr);
106
107 while ((cpu_io::msr::apic::ReadIcr() & kIcrDeliveryStatusBit) != 0) {
108 ;
109 }
110 } else {
111 // ICR 分为两个 32 位寄存器:ICR_LOW (0x300) 和 ICR_HIGH (0x310)
112
113 // 设置目标 APIC ID(ICR_HIGH 的位 24-31)
114 auto icr_high = (destination_apic_id & kApicIdMask) << kIcrDestShift;
115 etl::io_port_wo<uint32_t> icr_high_reg{
116 reinterpret_cast<void*>(apic_base_ + kXApicIcrHighOffset)};
117 icr_high_reg.write(icr_high);
118
119 // 设置向量和传递模式(ICR_LOW)
120 auto icr_low = static_cast<uint32_t>(vector);
121 etl::io_port_wo<uint32_t> icr_low_wo{
122 reinterpret_cast<void*>(apic_base_ + kXApicIcrLowOffset)};
123 icr_low_wo.write(icr_low);
124
125 {
126 etl::io_port_ro<uint32_t> icr_low_ro{
127 reinterpret_cast<void*>(apic_base_ + kXApicIcrLowOffset)};
128 while ((icr_low_ro.read() & kIcrDeliveryStatusBit) != 0) {
129 ;
130 }
131 }
132 }
133 return {};
134}
135
136auto LocalApic::BroadcastIpi(uint8_t vector) const -> Expected<void> {
137 if (is_x2apic_mode_) {
138 auto icr = static_cast<uint64_t>(vector);
139 // 目标简写:除自己外的所有 CPU
140 icr |= 0x80000;
141
142 cpu_io::msr::apic::WriteIcr(icr);
143
144 while ((cpu_io::msr::apic::ReadIcr() & kIcrDeliveryStatusBit) != 0) {
145 ;
146 }
147 } else {
148 // 广播到除自己外的所有 CPU(目标简写模式)
149 // ICR_HIGH 设为 0(不使用具体目标 ID)
150 etl::io_port_wo<uint32_t> icr_high_reg{
151 reinterpret_cast<void*>(apic_base_ + kXApicIcrHighOffset)};
152 icr_high_reg.write(0);
153
154 // ICR_LOW:向量 + 目标简写模式(位 18-19 = 11)
155 auto icr_low = static_cast<uint32_t>(vector) | kIcrBroadcastMode;
156 etl::io_port_wo<uint32_t> icr_low_wo{
157 reinterpret_cast<void*>(apic_base_ + kXApicIcrLowOffset)};
158 icr_low_wo.write(icr_low);
159
160 {
161 etl::io_port_ro<uint32_t> icr_low_ro{
162 reinterpret_cast<void*>(apic_base_ + kXApicIcrLowOffset)};
163 while ((icr_low_ro.read() & kIcrDeliveryStatusBit) != 0) {
164 ;
165 }
166 }
167 }
168 return {};
169}
170
171auto LocalApic::SetTaskPriority(uint8_t priority) const -> void {
172 if (is_x2apic_mode_) {
173 cpu_io::msr::apic::WriteTpr(static_cast<uint32_t>(priority));
174 } else {
175 etl::io_port_wo<uint32_t> tpr_reg{
176 reinterpret_cast<void*>(apic_base_ + kXApicTprOffset)};
177 tpr_reg.write(static_cast<uint32_t>(priority));
178 }
179}
180
181auto LocalApic::GetTaskPriority() const -> uint8_t {
182 if (is_x2apic_mode_) {
183 return static_cast<uint8_t>(cpu_io::msr::apic::ReadTpr() & kApicIdMask);
184 } else {
185 etl::io_port_ro<uint32_t> tpr_reg{
186 reinterpret_cast<void*>(apic_base_ + kXApicTprOffset)};
187 auto tpr = tpr_reg.read();
188 return static_cast<uint8_t>(tpr & kApicIdMask);
189 }
190}
191
192auto LocalApic::EnableTimer(uint32_t initial_count, uint32_t divide_value,
193 uint8_t vector, bool periodic) const -> void {
194 if (is_x2apic_mode_) {
195 cpu_io::msr::apic::WriteTimerDivide(divide_value);
196
197 auto lvt_timer = static_cast<uint32_t>(vector);
198 if (periodic) {
199 lvt_timer |= kLvtPeriodicMode;
200 }
201
202 cpu_io::msr::apic::WriteLvtTimer(lvt_timer);
203 cpu_io::msr::apic::WriteTimerInitCount(initial_count);
204 } else {
205 // 设置分频器(偏移 0x3E0)
206 etl::io_port_wo<uint32_t> divide_reg{
207 reinterpret_cast<void*>(apic_base_ + kXApicTimerDivideOffset)};
208 divide_reg.write(divide_value);
209
210 // 设置 LVT 定时器寄存器(偏移 0x320)
211 auto lvt_timer = static_cast<uint32_t>(vector);
212 if (periodic) {
213 lvt_timer |= kLvtPeriodicMode;
214 }
215
216 etl::io_port_wo<uint32_t> lvt_timer_reg{
217 reinterpret_cast<void*>(apic_base_ + kXApicLvtTimerOffset)};
218 lvt_timer_reg.write(lvt_timer);
219
220 // 设置初始计数值(偏移 0x380)
221 etl::io_port_wo<uint32_t> init_count_reg{
222 reinterpret_cast<void*>(apic_base_ + kXApicTimerInitCountOffset)};
223 init_count_reg.write(initial_count);
224 }
225}
226
227auto LocalApic::DisableTimer() const -> void {
228 if (is_x2apic_mode_) {
229 auto lvt_timer = cpu_io::msr::apic::ReadLvtTimer();
230 lvt_timer |= kLvtMaskBit;
231 cpu_io::msr::apic::WriteLvtTimer(lvt_timer);
232 cpu_io::msr::apic::WriteTimerInitCount(0);
233 } else {
234 etl::io_port_rw<uint32_t> lvt_timer_reg{
235 reinterpret_cast<void*>(apic_base_ + kXApicLvtTimerOffset)};
236 auto lvt_timer = lvt_timer_reg.read();
237 lvt_timer |= kLvtMaskBit;
238 lvt_timer_reg.write(lvt_timer);
239 etl::io_port_wo<uint32_t> init_count_reg{
240 reinterpret_cast<void*>(apic_base_ + kXApicTimerInitCountOffset)};
241 init_count_reg.write(0);
242 }
243}
244
245auto LocalApic::GetTimerCurrentCount() const -> uint32_t {
246 if (is_x2apic_mode_) {
247 return cpu_io::msr::apic::ReadTimerCurrCount();
248 } else {
249 // 当前计数寄存器在偏移 0x390 处
250 etl::io_port_ro<uint32_t> curr_count_reg{
251 reinterpret_cast<void*>(apic_base_ + kXApicTimerCurrCountOffset)};
252 return curr_count_reg.read();
253 }
254}
255
256auto LocalApic::SetupPeriodicTimer(uint32_t frequency_hz, uint8_t vector) const
257 -> void {
258 // 使用 APIC 定时器的典型配置
259 // 假设 APIC 时钟频率为 100MHz(实际应从 CPU 频率计算)
260
261 // 计算初始计数值
262 auto initial_count = kDefaultApicClockHz / frequency_hz;
263
264 // 选择合适的分频值以获得更好的精度
265 auto divide_value = kTimerDivideBy1;
266 if (initial_count > 0xFFFFFFFF) {
267 // 如果计数值太大,使用分频
268 divide_value = kTimerDivideBy16;
269 initial_count = (kDefaultApicClockHz / 16) / frequency_hz;
270 }
271
272 EnableTimer(initial_count, divide_value, vector, true);
273}
274
275auto LocalApic::SetupOneShotTimer(uint32_t microseconds, uint8_t vector) const
276 -> void {
277 // 假设 APIC 时钟频率为 100MHz
278
279 // 计算初始计数值(微秒转换为时钟周期)
280 auto initial_count =
281 (kDefaultApicClockHz / kMicrosecondsPerSecond) * microseconds;
282
283 // 选择合适的分频值
284 auto divide_value = kTimerDivideBy1;
285 if (initial_count > 0xFFFFFFFF) {
286 divide_value = kTimerDivideBy16;
287 initial_count =
288 ((kDefaultApicClockHz / 16) / kMicrosecondsPerSecond) * microseconds;
289 }
290
291 EnableTimer(initial_count, divide_value, vector, false);
292}
293
294auto LocalApic::SendInitIpi(uint32_t destination_apic_id) const -> void {
295 if (is_x2apic_mode_) {
296 auto icr = kInitIpiMode;
297 icr |= static_cast<uint64_t>(destination_apic_id) << 32;
298
299 cpu_io::msr::apic::WriteIcr(icr);
300
301 while ((cpu_io::msr::apic::ReadIcr() & kIcrDeliveryStatusBit) != 0) {
302 ;
303 }
304 } else {
305 // 设置目标 APIC ID(ICR_HIGH)
306 auto icr_high = (destination_apic_id & kApicIdMask) << kIcrDestShift;
307 etl::io_port_wo<uint32_t> icr_high_reg{
308 reinterpret_cast<void*>(apic_base_ + kXApicIcrHighOffset)};
309 icr_high_reg.write(icr_high);
310
311 // 发送 INIT IPI(ICR_LOW)
312 auto icr_low = kInitIpiMode;
313 etl::io_port_wo<uint32_t> icr_low_wo{
314 reinterpret_cast<void*>(apic_base_ + kXApicIcrLowOffset)};
315 icr_low_wo.write(icr_low);
316
317 {
318 etl::io_port_ro<uint32_t> icr_low_ro{
319 reinterpret_cast<void*>(apic_base_ + kXApicIcrLowOffset)};
320 while ((icr_low_ro.read() & kIcrDeliveryStatusBit) != 0) {
321 ;
322 }
323 }
324 }
325
326 klog::Info("INIT IPI sent to APIC ID {:#x}", destination_apic_id);
327}
328
329auto LocalApic::SendStartupIpi(uint32_t destination_apic_id,
330 uint8_t start_page) const -> void {
331 if (is_x2apic_mode_) {
332 // SIPI with start page (delivery mode = 110b)
333 auto icr = kSipiMode | start_page;
334 icr |= static_cast<uint64_t>(destination_apic_id) << 32;
335
336 cpu_io::msr::apic::WriteIcr(icr);
337
338 while ((cpu_io::msr::apic::ReadIcr() & kIcrDeliveryStatusBit) != 0) {
339 ;
340 }
341 } else {
342 // 设置目标 APIC ID(ICR_HIGH)
343 uint32_t icr_high = (destination_apic_id & kApicIdMask) << kIcrDestShift;
344 etl::io_port_wo<uint32_t> icr_high_reg{
345 reinterpret_cast<void*>(apic_base_ + kXApicIcrHighOffset)};
346 icr_high_reg.write(icr_high);
347
348 // 发送 SIPI(ICR_LOW)
349 uint32_t icr_low = kSipiMode | start_page;
350 etl::io_port_wo<uint32_t> icr_low_wo{
351 reinterpret_cast<void*>(apic_base_ + kXApicIcrLowOffset)};
352 icr_low_wo.write(icr_low);
353
354 {
355 etl::io_port_ro<uint32_t> icr_low_ro{
356 reinterpret_cast<void*>(apic_base_ + kXApicIcrLowOffset)};
357 while ((icr_low_ro.read() & kIcrDeliveryStatusBit) != 0) {
358 ;
359 }
360 }
361 }
362}
363
364auto LocalApic::ConfigureLvtEntries() const -> void {
365 if (is_x2apic_mode_) {
366 // 配置 LINT0 (通常连接到 8259 PIC 的 INTR)
367 cpu_io::msr::apic::WriteLvtLint0(kExtIntMode);
368
369 // 配置 LINT1 (通常连接到 NMI)
370 cpu_io::msr::apic::WriteLvtLint1(kNmiMode);
371
372 // 配置错误中断
373 cpu_io::msr::apic::WriteLvtError(kErrorVector);
374 } else {
375 // 配置 LINT0 (偏移 0x350)
376 etl::io_port_wo<uint32_t> lint0_reg{
377 reinterpret_cast<void*>(apic_base_ + kXApicLvtLint0Offset)};
378 lint0_reg.write(kExtIntMode);
379
380 // 配置 LINT1 (偏移 0x360)
381 etl::io_port_wo<uint32_t> lint1_reg{
382 reinterpret_cast<void*>(apic_base_ + kXApicLvtLint1Offset)};
383 lint1_reg.write(kNmiMode);
384
385 // 配置错误中断 (偏移 0x370)
386 etl::io_port_wo<uint32_t> error_reg{
387 reinterpret_cast<void*>(apic_base_ + kXApicLvtErrorOffset)};
388 error_reg.write(kErrorVector);
389 }
390}
391
392auto LocalApic::ReadErrorStatus() const -> uint32_t {
393 if (is_x2apic_mode_) {
394 // x2APIC 模式下没有直接的 ESR 访问方式
395 // 这里返回 0 表示没有错误
396 return 0;
397 } else {
398 // 取 ESR (Error Status Register, 偏移 0x280)
399 // 读取 ESR 之前需要先写入 0
400 etl::io_port_rw<uint32_t> esr_reg{
401 reinterpret_cast<void*>(apic_base_ + kXApicEsrOffset)};
402 esr_reg.write(0);
403 return esr_reg.read();
404 }
405}
406
407auto LocalApic::PrintInfo() const -> void {
408 klog::Info("APIC Version: {:#x}", GetApicVersion());
409 klog::Info("Mode: {}", is_x2apic_mode_ ? "x2APIC" : "xAPIC");
410 klog::Info("x2APIC Enabled: {}", IsX2ApicEnabled() ? "Yes" : "No");
411 klog::Info("Task Priority: {:#x}", GetTaskPriority());
412 klog::Info("Timer Current Count: {}", GetTimerCurrentCount());
413
414 // 读取各种寄存器状态
415 if (is_x2apic_mode_) {
416 uint32_t sivr = cpu_io::msr::apic::ReadSivr();
417 klog::Info("SIVR: {:#x} (APIC {})", sivr,
418 (sivr & kApicSoftwareEnableBit) ? "Enabled" : "Disabled");
419
420 uint32_t lvt_timer = cpu_io::msr::apic::ReadLvtTimer();
421 klog::Info("LVT Timer: {:#x}", lvt_timer);
422
423 uint32_t lvt_lint0 = cpu_io::msr::apic::ReadLvtLint0();
424 klog::Info("LVT LINT0: {:#x}", lvt_lint0);
425
426 uint32_t lvt_lint1 = cpu_io::msr::apic::ReadLvtLint1();
427 klog::Info("LVT LINT1: {:#x}", lvt_lint1);
428
429 uint32_t lvt_error = cpu_io::msr::apic::ReadLvtError();
430 klog::Info("LVT Error: {:#x}", lvt_error);
431 } else {
432 etl::io_port_ro<uint32_t> sivr_reg{
433 reinterpret_cast<void*>(apic_base_ + kXApicSivrOffset)};
434 uint32_t sivr = sivr_reg.read();
435 klog::Info("SIVR: {:#x} (APIC {})", sivr,
436 (sivr & kApicSoftwareEnableBit) ? "Enabled" : "Disabled");
437
438 etl::io_port_ro<uint32_t> lvt_timer_reg{
439 reinterpret_cast<void*>(apic_base_ + kXApicLvtTimerOffset)};
440 uint32_t lvt_timer = lvt_timer_reg.read();
441 klog::Info("LVT Timer: {:#x}", lvt_timer);
442
443 etl::io_port_ro<uint32_t> lvt_lint0_reg{
444 reinterpret_cast<void*>(apic_base_ + kXApicLvtLint0Offset)};
445 uint32_t lvt_lint0 = lvt_lint0_reg.read();
446 klog::Info("LVT LINT0: {:#x}", lvt_lint0);
447
448 etl::io_port_ro<uint32_t> lvt_lint1_reg{
449 reinterpret_cast<void*>(apic_base_ + kXApicLvtLint1Offset)};
450 uint32_t lvt_lint1 = lvt_lint1_reg.read();
451 klog::Info("LVT LINT1: {:#x}", lvt_lint1);
452
453 etl::io_port_ro<uint32_t> lvt_error_reg{
454 reinterpret_cast<void*>(apic_base_ + kXApicLvtErrorOffset)};
455 uint32_t lvt_error = lvt_error_reg.read();
456 klog::Info("LVT Error: {:#x}", lvt_error);
457
458 klog::Info("APIC Base Address: {:#x}", apic_base_);
459 }
460}
461
462auto LocalApic::CheckX2ApicSupport() const -> bool {
463 return cpu_io::cpuid::HasX2Apic();
464}
465
466auto LocalApic::EnableXApic() const -> bool {
467 // 设置 IA32_APIC_BASE.Global_Enable (位11) = 1
468 cpu_io::msr::apic::EnableGlobally();
469 // 清除 IA32_APIC_BASE.x2APIC_Enable (位10) = 0
470 cpu_io::msr::apic::DisableX2Apic();
471 return IsXApicEnabled();
472}
473
474auto LocalApic::DisableXApic() const -> bool {
475 // 清除 IA32_APIC_BASE.Global_Enable (位11) = 0
476 cpu_io::msr::apic::DisableGlobally();
477 return !IsXApicEnabled();
478}
479
480auto LocalApic::IsXApicEnabled() const -> bool {
481 // Global_Enable = 1 && x2APIC_Enable = 0
482 return cpu_io::msr::apic::IsGloballyEnabled() &&
483 !cpu_io::msr::apic::IsX2ApicEnabled();
484}
485
486auto LocalApic::EnableX2Apic() const -> bool {
487 // 检查 CPU 是否支持 x2APIC
488 if (!CheckX2ApicSupport()) {
489 return false;
490 }
491
492 // 设置 IA32_APIC_BASE.x2APIC_Enable (位10) = 1
493 // 同时确保 IA32_APIC_BASE.Global_Enable (位11) = 1
494 cpu_io::msr::apic::EnableX2Apic();
495
496 // 验证 x2APIC 是否成功启用
497 return IsX2ApicEnabled();
498}
499
500auto LocalApic::DisableX2Apic() const -> bool {
501 // 清除 IA32_APIC_BASE.x2APIC_Enable (位10) = 0
502 cpu_io::msr::apic::DisableX2Apic();
503 return !IsX2ApicEnabled();
504}
505
506auto LocalApic::IsX2ApicEnabled() const -> bool {
507 return cpu_io::msr::apic::IsX2ApicEnabled();
508}
509
510auto LocalApic::WakeupAp(uint32_t destination_apic_id,
511 uint8_t start_vector) const -> void {
512 // 发送 INIT IPI
513 SendInitIpi(destination_apic_id);
514
515 // 等待 10ms (INIT IPI 后的标准等待时间)
516 auto delay = 10 * kCalibrationDelayLoop;
517 while (delay--) {
518 __asm__ volatile("nop");
519 }
520
521 // 发送第一个 SIPI
522 SendStartupIpi(destination_apic_id, start_vector);
523
524 // 等待 200μs (SIPI 后的标准等待时间)
525 delay = 200 * (kCalibrationDelayLoop / 1000);
526 while (delay--) {
527 __asm__ volatile("nop");
528 }
529
530 // 发送第二个 SIPI (为了可靠性)
531 SendStartupIpi(destination_apic_id, start_vector);
532
533 // 等待 200μs
534 delay = 200 * (kCalibrationDelayLoop / 1000);
535 while (delay--) {
536 __asm__ volatile("nop");
537 }
538}
auto IsXApicEnabled() const -> bool
检查传统 xAPIC 是否启用
static constexpr uint32_t kXApicLvtLint0Offset
LVT LINT0 寄存器偏移
Definition local_apic.h:172
auto SetupOneShotTimer(uint32_t microseconds, uint8_t vector) const -> void
设置单次定时器
auto EnableXApic() const -> bool
启用传统 xAPIC 模式
static constexpr uint32_t kXApicEoiOffset
EOI 寄存器偏移
Definition local_apic.h:160
uint64_t apic_base_
APIC 基地址(仅用于 xAPIC 模式)
Definition local_apic.h:253
static constexpr uint32_t kXApicTimerCurrCountOffset
定时器当前计数寄存器偏移
Definition local_apic.h:180
static constexpr uint32_t kApicSoftwareEnableBit
APIC 软件启用位
Definition local_apic.h:192
static constexpr uint32_t kXApicVersionOffset
版本寄存器偏移
Definition local_apic.h:156
static constexpr uint32_t kXApicSivrOffset
虚假中断向量寄存器偏移
Definition local_apic.h:162
static constexpr uint32_t kXApicEsrOffset
错误状态寄存器偏移
Definition local_apic.h:164
auto DisableTimer() const -> void
禁用 Local APIC 定时器
static constexpr uint32_t kXApicLvtLint1Offset
LVT LINT1 寄存器偏移
Definition local_apic.h:174
auto DisableXApic() const -> bool
禁用传统 xAPIC 模式
auto GetApicVersion() const -> uint32_t
获取 APIC 版本信息
bool is_x2apic_mode_
当前 APIC 模式(true = x2APIC, false = xAPIC)
Definition local_apic.h:250
auto SendEoi() const -> void
发送中断结束信号 (EOI)
static constexpr uint32_t kExtIntMode
ExtINT 传递模式
Definition local_apic.h:210
auto DisableX2Apic() const -> bool
禁用 x2APIC 模式
static constexpr uint32_t kXApicTprOffset
任务优先级寄存器偏移
Definition local_apic.h:158
auto ReadErrorStatus() const -> uint32_t
读取错误状态
static constexpr uint32_t kApicIdMask
xAPIC ID 掩码
Definition local_apic.h:190
auto SendStartupIpi(uint32_t destination_apic_id, uint8_t start_page) const -> void
发送 SIPI (Startup IPI)
static constexpr uint32_t kNmiMode
NMI 传递模式
Definition local_apic.h:212
auto GetTaskPriority() const -> uint8_t
获取任务优先级
auto SetupPeriodicTimer(uint32_t frequency_hz, uint8_t vector) const -> void
设置周期性定时器
static constexpr uint32_t kLvtMaskBit
LVT 掩码位
Definition local_apic.h:196
auto EnableTimer(uint32_t initial_count, uint32_t divide_value, uint8_t vector, bool periodic=true) const -> void
启用 Local APIC 定时器
auto BroadcastIpi(uint8_t vector) const -> Expected< void >
广播 IPI 到所有其他 CPU
auto GetTimerCurrentCount() const -> uint32_t
获取定时器当前计数值
auto SendIpi(uint32_t destination_apic_id, uint8_t vector) const -> Expected< void >
发送处理器间中断 (IPI)
auto ConfigureLvtEntries() const -> void
配置 Local Vector Table 条目
static constexpr uint32_t kXApicTimerInitCountOffset
定时器初始计数寄存器偏移
Definition local_apic.h:178
static constexpr uint32_t kXApicLvtErrorOffset
LVT 错误寄存器偏移
Definition local_apic.h:176
auto IsX2ApicEnabled() const -> bool
检查 x2APIC 是否启用
auto PrintInfo() const -> void
打印 Local APIC 信息(调试用)
auto CheckX2ApicSupport() const -> bool
检查 CPU 是否支持 x2APIC
auto EnableX2Apic() const -> bool
启用 x2APIC 模式
static constexpr uint8_t kErrorVector
错误中断向量
Definition local_apic.h:214
auto Init() -> Expected< void >
初始化 Local APIC
static constexpr uint32_t kXApicLvtTimerOffset
LVT 定时器寄存器偏移
Definition local_apic.h:170
auto SendInitIpi(uint32_t destination_apic_id) const -> void
发送 INIT IPI
auto WakeupAp(uint32_t destination_apic_id, uint8_t start_vector) const -> void
唤醒应用处理器 (AP)
auto SetTaskPriority(uint8_t priority) const -> void
设置任务优先级
std::expected< T, Error > Expected
std::expected 别名模板
Definition expected.hpp:365
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