tianole/docs/agents/tasks/01-early-debug.md
Microindole 11a1a8234b
Some checks failed
check / build-and-boot (push) Has been cancelled
kernel: add framebuffer early console and tighten wait queues
2026-05-13 11:42:24 +08:00

103 lines
4.1 KiB
Markdown
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# 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。
- x86 backend 已可在 UEFI GOP framebuffer 上显示 early logQEMU 图形窗口可直接观察启动日志。
- `panic()` 已接入 early log 和 `arch_halt_forever()`
- `scripts/check.sh` 已验证 `build/debug.log``build/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 测试覆盖。