tianole/docs/agents/tasks/01-early-debug.md

4.0 KiB
Raw Blame History

01 早期调试输出

目标

建立 firmware 之外的稳定日志能力,作为后续 CPU、内存、调度和驱动开发的基础。

前置条件

  • bootloader 已能进入 kernel。
  • kernel 已在 ExitBootServices 后运行。
  • 当前已有 QEMU debug port 输出。

建议边界

  • arch/x86/COM1、I/O port、架构相关 early log backend。
  • kernel/:通用 early log 前端和 panic/oops 入口。
  • scripts/QEMU 串口参数和日志验证。

实现内容

  • 初始化 COM1。
  • 增加串口输出 backend。
  • 保留 QEMU debug port backend。
  • 统一 early_log_puts() 一类前端接口。
  • 增加最小 panic()panic 后停止 CPU。
  • 为后续 printk、oops、内核符号和 crash dump 预留接口边界。

1. Early console backend

  • 建立通用 early log 前端,后端可以是 QEMU debug port、COM1、framebuffer console 或后续平台 console。
  • x86 I/O port 访问集中在 arch 层,通用日志代码不能直接写端口。
  • early 阶段不能依赖动态内存、锁、线程或 VFS。
  • 后续切到正式 console 后early backend 仍可作为 panic fallback。

2. Panic 与 halt 路径

  • panic() 必须能在 allocator、scheduler、interrupt 都不可靠时输出最小信息。
  • panic 路径要尽量避免递归 panic至少保证第二次进入时直接 halt。
  • arch 层提供 arch_halt_forever(),通用 panic 不直接写 hlt 循环细节。
  • 后续 oops 和 panic 要区分:可恢复异常进入 oops不可恢复错误进入 panic。

3. Log buffer 与正式 printk 预留

  • early log 前端后续应能迁移到 ring buffer而不是让所有代码直接写串口。
  • 预留 log level、CPU id、timestamp、caller/source 信息。
  • 预留多 consumerserial、debug port、framebuffer console、内存 buffer。
  • 预留 crash dump 或重启后读取日志的路径。

Linux 参考原则

  • 参考 Linux printk/console 分层调用方写通用日志接口console driver 负责具体输出设备。
  • 参考 Linux early console 思路:早期输出简单可靠,正式 console 接管后仍保留诊断价值。
  • 参考 Linux panic/oops 分离panic 是不可恢复停机oops 是异常诊断和策略入口。
  • 参考 Linux ring buffer 思路:日志先进入内核缓冲,再由不同 console 消费,避免业务代码绑定输出硬件。

非玩具化约束

  • 日志前端不能直接绑定 COM1。
  • COM1 端口号要集中定义,不能散落在业务代码。
  • panic 路径不能依赖动态内存。
  • 输出接口要允许后续接 framebuffer console。
  • 日志接口不能要求 scheduler、heap 或 interrupt 已经初始化。
  • panic/oops 策略不能写进异常入口汇编。
  • 正式 printk 出现后early log 调用方不能被迫大规模改名或换接口。
  • 任何新增 backend 都不能影响其他 backend 的可用性。

验收方式

  • QEMU 日志中能看到 bootloader 和 kernel 输出。
  • 串口或 debug log 中能看到 boot services exited
  • 人为触发 panic 时能看到 panic 信息并停止。
  • 禁用某一个输出 backend 时,其他 backend 仍可输出关键日志。
  • panic 路径在 heap 未初始化前也能输出。
  • scripts/check.sh 至少验证 debug log 和 serial log 两条路径。

当前状态

基础完成:

  • kernel early log 已拆成通用前端和 x86 backend。
  • x86 backend 已同时写 QEMU debug port 和 COM1。
  • panic() 已接入 early log 和 arch_halt_forever()
  • scripts/check.sh 已验证 build/debug.logbuild/serial.log 中的关键启动行。

后续扩展:

  • printk/log level/ring buffer。
  • oops 格式。
  • 异常栈输出。
  • 内核符号化输出。
  • framebuffer console。
  • crash dump。
  • early log 到 printk 的接管流程。
  • panic 后保留最后日志的内存 buffer。
  • 多 CPU 后的日志串行化规则。

验收依据:

  • 正常启动日志能进入 QEMU debug log。
  • kernel 日志能进入 COM1 serial log。
  • panic() 已被 02-cpu-interrupts.md 的 invalid opcode 测试覆盖。