Files
ViperOS/VKernel/Kernel/drivers/core/cpu/cpu.vp
T
TermiNexus dcb7c5c2c0 chore(ViperOS): 落库内核侧进行中的改动(26 文件,+1573/-1805)
内容由用户产出,本次仅代为提交、未做任何语义修改;含 static 修饰符前置迁移等(新增 static 前缀 16 行)。提交消息为中性描述——如需更精确的说明请 amend。
2026-09-28 15:24:52 +08:00

376 lines
14 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 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), 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(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])