fix(apic): early_init 改用 IA32_APIC_BASE EN 位判断,避免 cpuid 误判跳过 init

lint0 读回 0x0(QEMU 复位默认 0x10000)说明此前读的是 RAM,_lapic_base 为 0,
init() 很可能未执行。msr_read 已在前置流程验证可用,改按 MSR bit11 判断更可靠。
main.vp 增补综合诊断:打印 base/version/svr/lint0 重写读回/特性位,一次性区分
init 未执行、MMIO 映射失效、写不粘三种假设。
This commit is contained in:
TermiNexus committed 2026-08-26 18:39:07 +08:00
1 parent 9ff53aa1fa
commit ee329c313f
2 files changed
+21 -9

No files matched your search

+8 -2
View File
@@ -237,8 +237,11 @@ def start_aps():
def early_init():
global _cpu_count, _bsp_lapic_id
features: t.CUInt32T = cpu.detect_features_static()
if features & cpu.CPU_FEATURE_APIC:
# 直接以 IA32_APIC_BASE 的 EN 位(bit 11)判断 APIC 是否可用:
# QEMU/OVMF 必启用,且 msr_read 路径已在前置流程验证可用;
# 比依赖 cpuid 特性位更可靠(避免 cpuid 包装被误判时静默跳过 init)。
msr_val: t.CUInt64T = cpu.msr_read(IA32_APIC_BASE)
if msr_val & APIC_BASE_MSR_ENABLE:
init()
_cpu_count = detect_cpu_count()
else:
@@ -247,5 +250,8 @@ def early_init():
def get_cpu_count() -> t.CUInt32T:
return _cpu_count
def get_base() -> t.CUInt64T:
return _lapic_base
def get_lapic_id() -> t.CUInt32T:
return get_id()
+13 -7
View File
@@ -78,13 +78,19 @@ class ViperKernel:
apic.early_init()
serial.puts("[main] apic init done\n")
# [DBG] 读回 LAPIC LINT0 与 APIC BASE MSR,验证 EXTINT 配置(用后移除)
_lint0: t.CUInt32T = apic.read(0x350)
_apic_msr: t.CUInt64T = cpu.msr_read(apic.IA32_APIC_BASE)
_abuf: t.CArray[t.CChar, 96]
viperlib.snprintf(c.Addr(_abuf), 96, "[APIC] lint0=0x%x apic_base_msr=0x%lx\n",
_lint0, _apic_msr)
serial.puts(c.Addr(_abuf))
# [DBG] 综合诊断:判定 LAPIC MMIO 是否真正可访问/可写(用后移除)
_dbg_base: t.CUInt64T = apic.get_base()
_dbg_ver: t.CUInt32T = apic.read(0x030) # LAPIC_VERSION:真 LAPIC 应为 0x50014
_dbg_svr: t.CUInt32T = apic.read(0x0F0) # LAPIC_SVR:init 已写 0x1FF
apic.write(0x350, 0x700) # 再次写 LINT0,验证写粘性
_dbg_lint0: t.CUInt32T = apic.read(0x350)
_dbg_feat: t.CUInt32T = cpu.detect_features_static()
_dbg_buf: t.CArray[t.CChar, 160]
viperlib.snprintf(c.Addr(_dbg_buf), 160,
"[DBG] base=0x%lx ver=0x%x svr=0x%x lint0=0x%x feat=0x%x apic=%d\n",
_dbg_base, _dbg_ver, _dbg_svr, _dbg_lint0, _dbg_feat,
1 if (_dbg_feat & cpu.CPU_FEATURE_APIC) else 0)
serial.puts(c.Addr(_dbg_buf))
asm.sti()
serial.puts("[main] sti done\n")