From ee329c313fdd5f28c2ff4ad59c9a2b70011d32a1 Mon Sep 17 00:00:00 2001 From: TermiNexus Date: Wed, 26 Aug 2026 18:39:07 +0800 Subject: [PATCH] =?UTF-8?q?fix(apic):=20early=5Finit=20=E6=94=B9=E7=94=A8?= =?UTF-8?q?=20IA32=5FAPIC=5FBASE=20EN=20=E4=BD=8D=E5=88=A4=E6=96=AD?= =?UTF-8?q?=EF=BC=8C=E9=81=BF=E5=85=8D=20cpuid=20=E8=AF=AF=E5=88=A4?= =?UTF-8?q?=E8=B7=B3=E8=BF=87=20init?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit lint0 读回 0x0(QEMU 复位默认 0x10000)说明此前读的是 RAM,_lapic_base 为 0, init() 很可能未执行。msr_read 已在前置流程验证可用,改按 MSR bit11 判断更可靠。 main.vp 增补综合诊断:打印 base/version/svr/lint0 重写读回/特性位,一次性区分 init 未执行、MMIO 映射失效、写不粘三种假设。 --- VKernel/Kernel/drivers/core/cpu/apic.vp | 10 ++++++++-- VKernel/Kernel/main.vp | 20 +++++++++++++------- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/VKernel/Kernel/drivers/core/cpu/apic.vp b/VKernel/Kernel/drivers/core/cpu/apic.vp index be57b2a..3e872b5 100644 --- a/VKernel/Kernel/drivers/core/cpu/apic.vp +++ b/VKernel/Kernel/drivers/core/cpu/apic.vp @@ -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() diff --git a/VKernel/Kernel/main.vp b/VKernel/Kernel/main.vp index 42681d7..55da781 100644 --- a/VKernel/Kernel/main.vp +++ b/VKernel/Kernel/main.vp @@ -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")