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])