根因:bootloader 只按 kernel 文件大小 AllocatePages(.bss 不占文件),于是 .bss 尾部(ticks/_perf_* 等全局量)与主线程栈区(0x60000~0x80000)在 memmap 里仍是 EfiConventionalMemory,被内核 mm 的堆 arena 当作空闲内存占用 → 内核全局量被写坏、 堆元数据被反向破坏,最终桌面线程栈上的 va_list 被改坏,vsnprintf 读 %d 变参时 #GP(rip=0x130d45, err=0x0)。 - linker.ld: .bss 末尾加 LONG(0) 强制 PROGBITS,使 kernel.bin 的 FileSize 涵盖 .bss,bootloader 的 PagesNeeded 得以预留整块内核镜像(含 .bss) - mm.init: 新增 KernelAddr/KernelEnd,挑 arena 时把与内核镜像 [kernel_PhysAddr, __bss_end) 重叠的 region 起点抬到镜像末端(不整段丢弃) - main.vp: 取 __bss_end 并传入 mm.init - boot.c: ExitBootServices 前用 AllocatePages(AllocateAddress, EfiLoaderData) 占位内核栈区 0x60000~0x80000,使其在 memmap 中标记已用 另含在途整理:多处补显式收窄转换(uint8()/uint16() 等)、kbd_svc 构造改为 kbd_svc.__init__() 等。
27 lines
669 B
Plaintext
27 lines
669 B
Plaintext
import asm
|
|
|
|
|
|
define PIT_CHANNEL0 = 0x40
|
|
define PIT_CHANNEL1 = 0x41
|
|
define PIT_CHANNEL2 = 0x42
|
|
define PIT_COMMAND = 0x43
|
|
|
|
def pit_init(frequency: int):
|
|
# 参数验证:确保频率为正数
|
|
if frequency <= 0: return
|
|
|
|
# 计算除数,使用16位无符号整数
|
|
divisor: uint32 = 1193180 / frequency
|
|
|
|
# 发送命令字:通道0,先低后高,模式3(方波),二进制计数
|
|
asm.outb(PIT_COMMAND, 0x36)
|
|
asm.io_wait()
|
|
|
|
# 写入低字节
|
|
asm.outb(PIT_CHANNEL0, uint8(divisor & 0xFF))
|
|
asm.io_wait()
|
|
|
|
# 写入高字节
|
|
asm.outb(PIT_CHANNEL0, uint8((divisor >> 8) & 0xFF))
|
|
asm.io_wait()
|