Files
ViperOS/VKernel/Kernel/platform/pch/pic.vp
T
TermiNexus 0919a058a8 fix(vkernel): 预留内核 .bss 与栈区,修堆 arena 覆盖未预留内核内存
根因: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__() 等。
2026-10-14 12:54:43 +08:00

120 lines
3.6 KiB
Plaintext
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.
import asm
# PIC端口定义
define PIC1_COMMAND = 0x20
define PIC1_DATA = 0x21
define PIC2_COMMAND = 0xA0
define PIC2_DATA = 0xA1
# ICW1 - 初始化命令字1
define ICW1_ICW4 = 0x01 # 需要ICW4
define ICW1_SINGLE = 0x02 # 单级模式
define ICW1_INTERVAL4 = 0x04 # 间隔4字节
define ICW1_LEVEL = 0x08 # 电平触发模式
define ICW1_INIT = 0x10 # 初始化
# ICW4 - 初始化命令字4
define ICW4_8086 = 0x01 # 8086/88模式
define ICW4_AUTO = 0x02 # 自动EOI
define ICW4_BUF_SLAVE = 0x08 # 缓冲模式(从片)
define ICW4_BUF_MASTER = 0x0C # 缓冲模式(主片)
define ICW4_SFNM = 0x10 # 特殊全嵌套模式
# OCW2 - 操作命令字2
define OCW2_EOI = 0x20 # 结束中断
# OCW3 - 操作命令字3
define OCW3_READ_ISR = 0x0B # 读取中断服务寄存器(ISR)
# 初始化PIC
def init():
# 发送ICW1:开始初始化,需要ICW4
asm.outb(PIC1_COMMAND, ICW1_INIT | ICW1_ICW4)
asm.io_wait()
asm.outb(PIC2_COMMAND, ICW1_INIT | ICW1_ICW4)
asm.io_wait()
# 发送ICW2:中断向量偏移
asm.outb(PIC1_DATA, 0x20) # IRQ0-7映射到0x20-0x27
asm.io_wait()
asm.outb(PIC2_DATA, 0x28) # IRQ8-15映射到0x28-0x2F
asm.io_wait()
# 发送ICW3:级联信息
asm.outb(PIC1_DATA, 0x04) # 主PIC的IRQ2连接从PIC
asm.io_wait()
asm.outb(PIC2_DATA, 0x02) # 从PIC连接到主PIC的IRQ2
asm.io_wait()
# 发送ICW4:8086模式
asm.outb(PIC1_DATA, ICW4_8086)
asm.io_wait()
asm.outb(PIC2_DATA, ICW4_8086)
asm.io_wait()
# 设置初始屏蔽字:只启用IRQ0(定时器)、IRQ1(键盘)、IRQ2(级联)
# 主PIC: 屏蔽所有除了IRQ0, IRQ1, IRQ2 (0xF8 = 11111000)
# 从PIC: 屏蔽所有 (0xFF = 11111111),鼠标中断由驱动程序自己启用
asm.outb(PIC1_DATA, 0xF8) # 启用IRQ0, IRQ1, IRQ2
asm.io_wait()
asm.outb(PIC2_DATA, 0xFF) # 屏蔽所有从PIC中断
asm.io_wait()
# 发送EOI信号
def eoi(irq: uint8):
if irq >= 8: asm.outb(PIC2_COMMAND, OCW2_EOI)
asm.outb(PIC1_COMMAND, OCW2_EOI)
# 检查是否是虚假中断(spurious interrupt)
# 返回 1 表示是虚假中断,0 表示是真实中断
def isSpurious(irq: int) -> int:
# 边界检查
if irq < 0 or irq > 15: return 0
isr: uint8
if irq < 8:
# 发送OCW3,读取ISR(Interrupt Service Register)
asm.outb(PIC1_COMMAND, OCW3_READ_ISR)
asm.io_wait()
isr = asm.inb(PIC1_COMMAND)
# 如果ISR中对应位为0,说明是虚假中断
return not (isr & (1 << irq))
else:
# 发送OCW3,读取从PIC的ISR
asm.outb(PIC2_COMMAND, OCW3_READ_ISR)
asm.io_wait()
isr = asm.inb(PIC2_COMMAND)
# 如果ISR中对应位为0,说明是虚假中断
return not (isr & (1 << (irq - 8)))
# 设置IRQ屏蔽
def setMask(irq: uint8):
# 边界检查
if irq > 15: return
port: uint16
value: uint8
if irq < 8:
port = PIC1_DATA
else:
port = PIC2_DATA
irq -= 8
value = uint8(asm.inb(port) | (1 << irq))
asm.outb(port, value)
asm.io_wait() # 确保命令生效
# 清除IRQ屏蔽
def clearMask(irq: uint8):
# 边界检查
if irq > 15: return
port: uint16
value: uint8
if irq < 8:
port = PIC1_DATA
else:
port = PIC2_DATA
irq -= 8
value = uint8(asm.inb(port) & ~(1 << irq))
asm.outb(port, value)
asm.io_wait() # 确保命令生效