根因: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__() 等。
376 lines
14 KiB
Plaintext
376 lines
14 KiB
Plaintext
import intr.gdt as gdt
|
||
import string
|
||
import asm
|
||
|
||
define IA32_KERNEL_GS_BASE = 0xC0000102
|
||
define KERN_STACK_SIZE = 8192
|
||
|
||
|
||
define CPU_FEATURE_FPU = (1 << 0)
|
||
define CPU_FEATURE_PSE = (1 << 1)
|
||
define CPU_FEATURE_MSR = (1 << 2)
|
||
define CPU_FEATURE_PAE = (1 << 3)
|
||
define CPU_FEATURE_MCE = (1 << 4)
|
||
define CPU_FEATURE_CX8 = (1 << 5)
|
||
define CPU_FEATURE_APIC = (1 << 6)
|
||
define CPU_FEATURE_SEP = (1 << 7)
|
||
define CPU_FEATURE_MTRR = (1 << 8)
|
||
define CPU_FEATURE_PGE = (1 << 9)
|
||
define CPU_FEATURE_MCA = (1 << 10)
|
||
define CPU_FEATURE_CMOV = (1 << 11)
|
||
define CPU_FEATURE_PAT = (1 << 12)
|
||
define CPU_FEATURE_PSE36 = (1 << 13)
|
||
define CPU_FEATURE_PSN = (1 << 14)
|
||
define CPU_FEATURE_CLFSH = (1 << 15)
|
||
define CPU_FEATURE_DS = (1 << 16)
|
||
define CPU_FEATURE_ACPI = (1 << 17)
|
||
define CPU_FEATURE_MMX = (1 << 18)
|
||
define CPU_FEATURE_FXSR = (1 << 19)
|
||
define CPU_FEATURE_SSE = (1 << 20)
|
||
define CPU_FEATURE_SSE2 = (1 << 21)
|
||
define CPU_FEATURE_SS = (1 << 22)
|
||
define CPU_FEATURE_HTT = (1 << 23)
|
||
define CPU_FEATURE_TM = (1 << 24)
|
||
define CPU_FEATURE_PBE = (1 << 25)
|
||
|
||
class cpu_info:
|
||
vendor_id: [13]char
|
||
brand_string: [48]char
|
||
features: uint32
|
||
family: uint32
|
||
model: uint32
|
||
stepping: uint32
|
||
cpu_type: uint32
|
||
ext_model: uint32
|
||
ext_family: uint32
|
||
cpu_freq: uint64
|
||
|
||
@__attribute__(packed)
|
||
class _tss:
|
||
# x86_64 TSS 布局:偏移 0 为 4 字节保留字段(对齐 gdt.vp:32 的
|
||
# "reserved0(4) rsp0(8) ..." 与 tss_buf: t.CArray[uint8, 104])。
|
||
# 此前写作 uint64 使 RSP0 落在偏移 8、结构体 108B —— 与硬件 104B 布局
|
||
# 及 gdt 的 tss_buf(104B) 不一致(N6)。
|
||
reserved0: uint32
|
||
rsp0: uint64
|
||
rsp1: uint64
|
||
rsp2: uint64
|
||
reserved1: uint64
|
||
ist1: uint64
|
||
ist2: uint64
|
||
ist3: uint64
|
||
ist4: uint64
|
||
ist5: uint64
|
||
ist6: uint64
|
||
ist7: uint64
|
||
reserved2: uint64
|
||
reserved3: uint16
|
||
io_map_base: uint16
|
||
|
||
class cpuid_result:
|
||
eax: uint32
|
||
ebx: uint32
|
||
ecx: uint32
|
||
edx: uint32
|
||
|
||
@__attribute__(packed)
|
||
def _rdmsr_naked():
|
||
__asm__(f"""rdmsr
|
||
shl rdx, 32
|
||
or rax, rdx
|
||
ret""",
|
||
op=[ASM_DESCR.CLOBBER_RDX])
|
||
|
||
@__attribute__(packed)
|
||
def _wrmsr_naked():
|
||
# msr_write sets ecx=msr, r8=value. wrmsr needs ECX=msr, EDX:EAX=value.
|
||
# Old code did `mov rax,rcx` (rax=msr) which wrote (value>>32):msr to MSR,
|
||
# corrupting IA32_KERNEL_GS_BASE -> swapgs -> #GP on gs:[0]. Fixed below.
|
||
__asm__(f"""mov rax, r8
|
||
mov rdx, r8
|
||
shr rdx, 32
|
||
wrmsr
|
||
ret""",
|
||
op=[ASM_DESCR.CLOBBER_RAX, ASM_DESCR.CLOBBER_RDX])
|
||
|
||
def msr_read(msr: uint32) -> uint64:
|
||
result: uint64 = 0
|
||
func: callable = _rdmsr_naked
|
||
__asm__(f"""mov ecx, {asminp(msr, ASM_DESCR.REG_ANY)}
|
||
call {asminp(func, ASM_DESCR.REG_ANY)}
|
||
mov {asmout(result, ASM_DESCR.OUTPUT_REG)}, rax""",
|
||
op=[ASM_DESCR.CLOBBER_RAX, ASM_DESCR.CLOBBER_RCX, ASM_DESCR.CLOBBER_RDX])
|
||
return result
|
||
|
||
def msr_write(msr: uint32, value: uint64):
|
||
func: callable = _wrmsr_naked
|
||
__asm__(f"""mov ecx, {asminp(msr, ASM_DESCR.REG_ANY)}
|
||
mov r8, {asminp(value, ASM_DESCR.REG_ANY)}
|
||
call {asminp(func, ASM_DESCR.REG_ANY)}""",
|
||
op=[ASM_DESCR.CLOBBER_RAX, ASM_DESCR.CLOBBER_RCX, ASM_DESCR.CLOBBER_RDX, ASM_DESCR.CLOBBER_R8])
|
||
|
||
@__attribute__(packed)
|
||
def _cpuid_naked():
|
||
__asm__(f"""push rbx
|
||
mov eax, ecx
|
||
cpuid
|
||
mov dword ptr [rdx], eax
|
||
mov dword ptr [rdx + 4], ebx
|
||
mov dword ptr [rdx + 8], ecx
|
||
mov dword ptr [rdx + 12], edx
|
||
pop rbx
|
||
ret""",
|
||
op=[ASM_DESCR.CLOBBER_RAX, ASM_DESCR.CLOBBER_RCX,
|
||
ASM_DESCR.CLOBBER_RDX])
|
||
|
||
@__attribute__(packed)
|
||
def _cpuid_sub_naked():
|
||
__asm__(f"""push rbx
|
||
mov eax, ecx
|
||
mov ecx, r8d
|
||
cpuid
|
||
mov dword ptr [rdx], eax
|
||
mov dword ptr [rdx + 4], ebx
|
||
mov dword ptr [rdx + 8], ecx
|
||
mov dword ptr [rdx + 12], edx
|
||
pop rbx
|
||
ret""",
|
||
op=[ASM_DESCR.CLOBBER_RAX, ASM_DESCR.CLOBBER_RCX,
|
||
ASM_DESCR.CLOBBER_RDX])
|
||
|
||
@__attribute__(noinline)
|
||
def cpuid(leaf: uint32, out: cpuid_result*):
|
||
func: callable = _cpuid_naked
|
||
__asm__(f"""mov ecx, {asminp(leaf, ASM_DESCR.REG_ANY)}
|
||
mov rdx, {asminp(out, ASM_DESCR.REG_ANY)}
|
||
call {asminp(func, ASM_DESCR.REG_ANY)}""",
|
||
op=[ASM_DESCR.CLOBBER_RAX, ASM_DESCR.CLOBBER_RCX,
|
||
ASM_DESCR.CLOBBER_RDX, ASM_DESCR.CLOBBER_R8,
|
||
ASM_DESCR.CLOBBER_R9, ASM_DESCR.CLOBBER_R10,
|
||
ASM_DESCR.CLOBBER_R11])
|
||
|
||
@__attribute__(noinline)
|
||
def cpuid_sub(leaf: uint32, sub: uint32, out: cpuid_result*):
|
||
func: callable = _cpuid_sub_naked
|
||
__asm__(f"""mov ecx, {asminp(leaf, ASM_DESCR.REG_ANY)}
|
||
mov r8d, {asminp(sub, ASM_DESCR.REG_ANY)}
|
||
mov rdx, {asminp(out, ASM_DESCR.REG_ANY)}
|
||
call {asminp(func, ASM_DESCR.REG_ANY)}""",
|
||
op=[ASM_DESCR.CLOBBER_RAX, ASM_DESCR.CLOBBER_RCX,
|
||
ASM_DESCR.CLOBBER_RDX, ASM_DESCR.CLOBBER_R8,
|
||
ASM_DESCR.CLOBBER_R9, ASM_DESCR.CLOBBER_R10,
|
||
ASM_DESCR.CLOBBER_R11])
|
||
|
||
@__attribute__(noinline)
|
||
def detect_features_static() -> uint32:
|
||
features: uint32 = 0
|
||
res: cpuid_result
|
||
cpuid(1, &res)
|
||
if res.edx & (1 << 0): features |= CPU_FEATURE_FPU
|
||
if res.edx & (1 << 3): features |= CPU_FEATURE_PSE
|
||
if res.edx & (1 << 5): features |= CPU_FEATURE_MSR
|
||
if res.edx & (1 << 6): features |= CPU_FEATURE_PAE
|
||
if res.edx & (1 << 7): features |= CPU_FEATURE_MCE
|
||
if res.edx & (1 << 8): features |= CPU_FEATURE_CX8
|
||
if res.edx & (1 << 9): features |= CPU_FEATURE_APIC
|
||
if res.edx & (1 << 11): features |= CPU_FEATURE_SEP
|
||
if res.edx & (1 << 12): features |= CPU_FEATURE_MTRR
|
||
if res.edx & (1 << 13): features |= CPU_FEATURE_PGE
|
||
if res.edx & (1 << 14): features |= CPU_FEATURE_MCA
|
||
if res.edx & (1 << 15): features |= CPU_FEATURE_CMOV
|
||
if res.edx & (1 << 16): features |= CPU_FEATURE_PAT
|
||
if res.edx & (1 << 17): features |= CPU_FEATURE_PSE36
|
||
if res.edx & (1 << 18): features |= CPU_FEATURE_PSN
|
||
if res.edx & (1 << 19): features |= CPU_FEATURE_CLFSH
|
||
if res.edx & (1 << 21): features |= CPU_FEATURE_DS
|
||
if res.edx & (1 << 22): features |= CPU_FEATURE_ACPI
|
||
if res.edx & (1 << 23): features |= CPU_FEATURE_MMX
|
||
if res.edx & (1 << 24): features |= CPU_FEATURE_FXSR
|
||
if res.edx & (1 << 25): features |= CPU_FEATURE_SSE
|
||
if res.edx & (1 << 26): features |= CPU_FEATURE_SSE2
|
||
if res.edx & (1 << 27): features |= CPU_FEATURE_SS
|
||
if res.edx & (1 << 28): features |= CPU_FEATURE_HTT
|
||
if res.edx & (1 << 29): features |= CPU_FEATURE_TM
|
||
if res.edx & (1 << 30): features |= CPU_FEATURE_PBE
|
||
return features
|
||
|
||
@__attribute__(packed)
|
||
class per_cpu_data:
|
||
user_rsp: uint64
|
||
kernel_rsp0: uint64
|
||
current_pid: int
|
||
_pad0: uint32
|
||
_pad1: uint64
|
||
|
||
_per_cpu: per_cpu_data
|
||
|
||
class _CPUObject:
|
||
tss: _tss
|
||
features: uint32
|
||
def __init__(self):
|
||
self.__init_tss__()
|
||
|
||
def __init_tss__(self):
|
||
global _per_cpu
|
||
string.memset(&self.tss, 0, self.tss.__sizeof__())
|
||
self.tss.io_map_base = self.tss.__sizeof__()
|
||
string.memset(&_per_cpu, 0, per_cpu_data.__sizeof__())
|
||
gdt.setTSS64(5, uint64(&self.tss), int(self.tss.__sizeof__() - 1))
|
||
gdt.flush()
|
||
# IA32_KERNEL_GS_BASE holds the per_cpu address for swapgs.
|
||
# When entering from Ring 3, swapgs swaps IA32_GS_BASE (0) with
|
||
# IA32_KERNEL_GS_BASE (_per_cpu), making gs: accessible in kernel.
|
||
# When returning to Ring 3, swapgs swaps back, restoring GS base to 0.
|
||
msr_write(IA32_KERNEL_GS_BASE, uint64(&_per_cpu))
|
||
|
||
def getInfo(self, info: cpu_info*):
|
||
if not info: return
|
||
res: cpuid_result
|
||
cpuid(0, &res)
|
||
uint32*(info.vendor_id)[0] = res.ebx
|
||
uint32*(info.vendor_id)[1] = res.edx
|
||
uint32*(info.vendor_id)[2] = res.ecx
|
||
info.vendor_id[12] = '\0'
|
||
info.features = self.detectFeatures()
|
||
cpuid(1, &res)
|
||
info.stepping = (res.eax >> 0) & 0x0F
|
||
info.model = (res.eax >> 4) & 0x0F
|
||
info.family = (res.eax >> 8) & 0x0F
|
||
info.cpu_type = (res.eax >> 12) & 0x03
|
||
info.ext_model = (res.eax >> 16) & 0x0F
|
||
info.ext_family = (res.eax >> 20) & 0xFF
|
||
# CPUID 品牌串:0x80000002..0x80000004 共 3 个叶 × 16 字节 = 48,
|
||
# 与 brand_string[48] 等长(此前 range(4) 会写 64 字节 → 越界 16 字节)。
|
||
# 逐 u32 按字节地址显式写入,避免 uint32|t.CPtr 被降级为 i8* 后
|
||
# 下标按字节偏移且被截断为 i8(只写低字节、偏移不乘 4)。
|
||
brand_addr: uint64 = uint64(uint32*(info.brand_string))
|
||
for i in range(3):
|
||
cpuid(int(0x80000002 + i), &res)
|
||
off_b: uint64 = uint64(i) * 16
|
||
*(uint32*(brand_addr + off_b + 0)) = res.eax
|
||
*(uint32*(brand_addr + off_b + 4)) = res.ebx
|
||
*(uint32*(brand_addr + off_b + 8)) = res.ecx
|
||
*(uint32*(brand_addr + off_b + 12)) = res.edx
|
||
info.brand_string[47] = '\0'
|
||
info.cpu_freq = 2000000000
|
||
|
||
def detectFeatures(self) -> uint32:
|
||
features: int32 = 0
|
||
res: cpuid_result
|
||
cpuid(1, &res)
|
||
if res.edx & (1 << 0): features |= CPU_FEATURE_FPU
|
||
if res.edx & (1 << 3): features |= CPU_FEATURE_PSE
|
||
if res.edx & (1 << 5): features |= CPU_FEATURE_MSR
|
||
if res.edx & (1 << 6): features |= CPU_FEATURE_PAE
|
||
if res.edx & (1 << 7): features |= CPU_FEATURE_MCE
|
||
if res.edx & (1 << 8): features |= CPU_FEATURE_CX8
|
||
if res.edx & (1 << 9): features |= CPU_FEATURE_APIC
|
||
if res.edx & (1 << 11): features |= CPU_FEATURE_SEP
|
||
if res.edx & (1 << 12): features |= CPU_FEATURE_MTRR
|
||
if res.edx & (1 << 13): features |= CPU_FEATURE_PGE
|
||
if res.edx & (1 << 14): features |= CPU_FEATURE_MCA
|
||
if res.edx & (1 << 15): features |= CPU_FEATURE_CMOV
|
||
if res.edx & (1 << 16): features |= CPU_FEATURE_PAT
|
||
if res.edx & (1 << 17): features |= CPU_FEATURE_PSE36
|
||
if res.edx & (1 << 18): features |= CPU_FEATURE_PSN
|
||
if res.edx & (1 << 19): features |= CPU_FEATURE_CLFSH
|
||
if res.edx & (1 << 21): features |= CPU_FEATURE_DS
|
||
if res.edx & (1 << 22): features |= CPU_FEATURE_ACPI
|
||
if res.edx & (1 << 23): features |= CPU_FEATURE_MMX
|
||
if res.edx & (1 << 24): features |= CPU_FEATURE_FXSR
|
||
if res.edx & (1 << 25): features |= CPU_FEATURE_SSE
|
||
if res.edx & (1 << 26): features |= CPU_FEATURE_SSE2
|
||
if res.edx & (1 << 27): features |= CPU_FEATURE_SS
|
||
if res.edx & (1 << 28): features |= CPU_FEATURE_HTT
|
||
if res.edx & (1 << 29): features |= CPU_FEATURE_TM
|
||
if res.edx & (1 << 30): features |= CPU_FEATURE_PBE
|
||
return features
|
||
|
||
def enableInterrupts(self):
|
||
__asm__("sti", [ASM_DESCR.CLOBBER_MEMORY])
|
||
|
||
def disableInterrupts(self):
|
||
__asm__("cli", [ASM_DESCR.CLOBBER_MEMORY])
|
||
|
||
def enableNmis(self):
|
||
current: uint8 = asm.inb(0x70)
|
||
asm.outb(0x70, current & 0x7F)
|
||
|
||
def disableNmis(self):
|
||
current: uint8 = asm.inb(0x70)
|
||
asm.outb(0x70, current | 0x80)
|
||
|
||
def readCR0(self) -> uint64:
|
||
cr0: uint64
|
||
__asm__(f"""mov rax, cr0
|
||
mov {asmout(cr0, ASM_DESCR.OUTPUT_REG)}, rax""",
|
||
[ASM_DESCR.CLOBBER_RAX])
|
||
return cr0
|
||
|
||
def writeCR0(self, value: uint64):
|
||
__asm__(f"""mov rax, {asminp(value, ASM_DESCR.REG_ANY)}
|
||
mov cr0, rax""",
|
||
[ASM_DESCR.CLOBBER_RAX])
|
||
|
||
def readCR3(self) -> uint64:
|
||
cr3: uint64
|
||
__asm__(f"""mov rax, cr3
|
||
mov {asmout(cr3, ASM_DESCR.OUTPUT_REG)}, rax""",
|
||
[ASM_DESCR.CLOBBER_RAX])
|
||
return cr3
|
||
|
||
def writeCR3(self, value: uint64):
|
||
__asm__(f"""mov rax, {asminp(value, ASM_DESCR.REG_ANY)}
|
||
mov cr3, rax""",
|
||
[ASM_DESCR.CLOBBER_RAX])
|
||
|
||
def readCR4(self) -> uint64:
|
||
cr4: uint64
|
||
__asm__(f"""mov rax, cr4
|
||
mov {asmout(cr4, ASM_DESCR.OUTPUT_REG)}, rax""",
|
||
[ASM_DESCR.CLOBBER_RAX])
|
||
return cr4
|
||
|
||
def writeCR4(self, value: uint64):
|
||
__asm__(f"""mov rax, {asminp(value, ASM_DESCR.REG_ANY)}
|
||
mov cr4, rax""",
|
||
[ASM_DESCR.CLOBBER_RAX])
|
||
|
||
def readMSR(self, msr: uint32) -> uint64:
|
||
return msr_read(msr)
|
||
|
||
def writeMSR(self, msr: uint32, value: uint64):
|
||
msr_write(msr, value)
|
||
|
||
def setTSSRSP0(self, rsp0: uint64):
|
||
global _per_cpu
|
||
self.tss.rsp0 = rsp0
|
||
_per_cpu.kernel_rsp0 = rsp0
|
||
|
||
def set_kernel_rsp0(rsp0: uint64):
|
||
global _per_cpu
|
||
_per_cpu.kernel_rsp0 = rsp0
|
||
|
||
# 启用 SSE/FPU:CR4.OSFXSR(bit9)|OSXMMEXCPT(bit10) 置位、CR0 清 EM(bit2) 置 MP(bit1)。
|
||
# OVMF/UEFI 启动后 CR4.OSFXSR 未置位,任何 movaps 都 #GP(err=0)——变参函数
|
||
# 传 float/double 时保存 xmm 寄存器触发(serial.printf / snprintf("%.2f") 崩溃根因)。
|
||
def enable_sse():
|
||
cr0_v: uint64 = 0
|
||
__asm__(f"""mov rax, cr0
|
||
mov {asmout(cr0_v, ASM_DESCR.OUTPUT_REG)}, rax""",
|
||
op=[ASM_DESCR.CLOBBER_RAX])
|
||
cr0_v = cr0_v & ~uint64(4) # 清 EM(禁止 FPU 仿真)
|
||
cr0_v = cr0_v | uint64(2) # 置 MP(监控协处理器)
|
||
__asm__(f"""mov rax, {asminp(cr0_v, ASM_DESCR.REG_ANY)}
|
||
mov cr0, rax""",
|
||
op=[ASM_DESCR.CLOBBER_RAX])
|
||
cr4_v: uint64 = 0
|
||
__asm__(f"""mov rax, cr4
|
||
mov {asmout(cr4_v, ASM_DESCR.OUTPUT_REG)}, rax""",
|
||
op=[ASM_DESCR.CLOBBER_RAX])
|
||
cr4_v = cr4_v | uint64(0x600) # OSFXSR | OSXMMEXCPT
|
||
__asm__(f"""mov rax, {asminp(cr4_v, ASM_DESCR.REG_ANY)}
|
||
mov cr4, rax""",
|
||
op=[ASM_DESCR.CLOBBER_RAX])
|
||
__asm__("fninit", op=[ASM_DESCR.CLOBBER_MEMORY])
|