609 lines
25 KiB
Plaintext
609 lines
25 KiB
Plaintext
import platform.pch.pic as pic
|
||
import platform.pch.timer as timer
|
||
import sched.sched as sched
|
||
import sched.process as proc
|
||
import drivers.serial.uart.serial as serial
|
||
import drivers.core.cpu.apic as apic
|
||
import viperlib
|
||
import asm
|
||
|
||
|
||
define CODE_SEG: uint16 = 0x08
|
||
|
||
@__attribute__(packed)
|
||
class idt_entry:
|
||
base_low: uint16
|
||
selector: uint16
|
||
ist_attr: uint8
|
||
type_attr: uint8
|
||
base_middle: uint16
|
||
base_high: uint32
|
||
reserved1: uint32
|
||
|
||
export idt: [256]idt_entry = []
|
||
typedef irq_handler_t = callable[[], int]
|
||
|
||
|
||
def _SafeStackWord(addr: uint64) -> uint64:
|
||
"""异常处理专用安全解引用:仅当 addr 落在**内核**区间(0x1000..0x80000000)才读。
|
||
|
||
异常处理里绝不允许再触发一次 #PF:一旦读到用户地址(典型是 iret 帧里压入的
|
||
user_rsp=0x7fffffe00000),就会在 #PF 处理中再次 #PF → 无限重入 → 内核栈耗尽
|
||
→ 三重故障(QEMU 窗口直接消失,且**看不到真正的首故障**)。
|
||
"""
|
||
if addr < 0x1000 or addr >= 0x80000000: return 0
|
||
v: uint64 = 0
|
||
__asm__(f"""mov rax, {asminp(addr, ASM_DESCR.REG_ANY)}
|
||
mov {asmout(v, ASM_DESCR.OUTPUT_REG)}, [rax]""",
|
||
op=[ASM_DESCR.CLOBBER_RAX])
|
||
return v
|
||
|
||
extern def isr0()
|
||
extern def isr1()
|
||
extern def isr2()
|
||
extern def isr3()
|
||
extern def isr4()
|
||
extern def isr5()
|
||
extern def isr6()
|
||
extern def isr7()
|
||
extern def isr8()
|
||
extern def isr9()
|
||
extern def isr10()
|
||
extern def isr11()
|
||
extern def isr12()
|
||
extern def isr13()
|
||
extern def isr14()
|
||
extern def isr15()
|
||
extern def isr16()
|
||
extern def isr17()
|
||
extern def isr18()
|
||
extern def isr19()
|
||
extern def isr20()
|
||
extern def isr21()
|
||
extern def isr22()
|
||
extern def isr23()
|
||
extern def isr24()
|
||
extern def isr25()
|
||
extern def isr26()
|
||
extern def isr27()
|
||
extern def isr28()
|
||
extern def isr29()
|
||
extern def isr30()
|
||
extern def isr31()
|
||
extern def isr32()
|
||
extern def isr33()
|
||
extern def isr34()
|
||
extern def isr35()
|
||
extern def isr36()
|
||
extern def isr37()
|
||
extern def isr38()
|
||
extern def isr39()
|
||
extern def isr40()
|
||
extern def isr41()
|
||
extern def isr42()
|
||
extern def isr43()
|
||
extern def isr44()
|
||
extern def isr45()
|
||
extern def isr46()
|
||
extern def isr47()
|
||
|
||
extern def isr80()
|
||
extern def isr_default()
|
||
|
||
def setGate(num: int, base: uint64, sel: uint16, flags: uint8):
|
||
global idt
|
||
idt[num].base_low = uint16(base & 0xFFFF)
|
||
idt[num].base_middle = uint16((base >> 16) & 0xFFFF)
|
||
idt[num].base_high = uint32((base >> 32) & 0xFFFFFFFF)
|
||
idt[num].selector = uint16(sel)
|
||
idt[num].ist_attr = 0
|
||
idt[num].type_attr = uint8(flags)
|
||
idt[num].reserved1 = 0
|
||
|
||
def isrCommonhandler(interrupt: int):
|
||
__asm__(f"""mov dx, 0x3F8
|
||
mov al, 91
|
||
out dx, al
|
||
mov ecx, {asminp(interrupt, ASM_DESCR.REG_ANY)}
|
||
mov rax, rcx
|
||
shr rax, 4
|
||
and al, 15
|
||
add al, 48
|
||
cmp al, 57
|
||
jle 1f
|
||
add al, 7
|
||
1:
|
||
out dx, al
|
||
mov rax, rcx
|
||
and al, 15
|
||
add al, 48
|
||
cmp al, 57
|
||
jle 2f
|
||
add al, 7
|
||
2:
|
||
out dx, al
|
||
mov al, 93
|
||
out dx, al""",
|
||
op=[ASM_DESCR.CLOBBER_RAX, ASM_DESCR.CLOBBER_RCX, ASM_DESCR.CLOBBER_RDX])
|
||
# Print CR2 for page faults (ISR 14)
|
||
if interrupt == 14:
|
||
cr2: uint64 = 0
|
||
__asm__(f"""mov {asmout(cr2, ASM_DESCR.OUTPUT_REG)}, cr2""",
|
||
op=[ASM_DESCR.CLOBBER_RAX])
|
||
fault_rip: uint64 = 0
|
||
fault_err: uint64 = 0
|
||
fault_rsp: uint64 = 0
|
||
__asm__(f"""mov {asmout(fault_rip, ASM_DESCR.OUTPUT_REG)}, [_fault_rip]
|
||
mov {asmout(fault_err, ASM_DESCR.OUTPUT_REG)}, [_fault_err]
|
||
mov {asmout(fault_rsp, ASM_DESCR.OUTPUT_REG)}, [_fault_rsp]""",
|
||
op=[ASM_DESCR.CLOBBER_RAX])
|
||
buf: [100]char
|
||
viperlib.snprintf(&buf, 100, "[PF] cr2=0x%lx rip=0x%lx err=0x%lx rsp=0x%lx\n", cr2, fault_rip, fault_err, fault_rsp)
|
||
serial.puts(buf)
|
||
# [CR3] 当前 pml4:定位栈区/对象写缺页是否因 pml4 被 switch_pid 切走
|
||
# (内核 pml4=0xf801000,用户 pml4=0x9781xxx —— 若显示用户 pml4 而 rsp
|
||
# 在 bootloader 栈区 0x60000-0x80000,则是进程切换后未切回内核页表)。
|
||
cur_cr3: uint64 = 0
|
||
__asm__(f"mov {asmout(cur_cr3, ASM_DESCR.OUTPUT_REG)}, cr3",
|
||
op=[ASM_DESCR.CLOBBER_RAX])
|
||
cr3_buf: [80]char
|
||
viperlib.snprintf(&cr3_buf, 80, "[CR3] pml4=0x%lx\n", cur_cr3)
|
||
serial.puts(cr3_buf)
|
||
# [临时] syscall 用户 rsp 对照:入口值 vs 返回时待恢复值。
|
||
# 两者不同 ⇒ 内核在 syscall 期间覆盖了 gs:[0x0];两者相同且都异常 ⇒ app 自己弄坏了 rsp。
|
||
sc_ent: uint64 = 0
|
||
sc_ret: uint64 = 0
|
||
__asm__(f"""mov rax, [_sc_ent_rsp]
|
||
mov {asmout(sc_ent, ASM_DESCR.OUTPUT_REG)}, rax
|
||
mov rax, [_sc_ret_rsp]
|
||
mov {asmout(sc_ret, ASM_DESCR.OUTPUT_REG)}, rax""",
|
||
op=[ASM_DESCR.CLOBBER_RAX])
|
||
sc_buf: [160]char
|
||
viperlib.snprintf(&sc_buf, 160, "[SYSCALL-RSP] entry=0x%lx ret=0x%lx\n", sc_ent, sc_ret)
|
||
serial.puts(sc_buf)
|
||
# [RAX] 崩溃时 rax(isr.s 保存):定位 cr2 与 rax 关系(rax-偏移=cr2)
|
||
f_rax: uint64 = 0
|
||
__asm__(f"""mov {asmout(f_rax, ASM_DESCR.OUTPUT_REG)}, [_fault_rax]""",
|
||
op=[ASM_DESCR.CLOBBER_RAX])
|
||
rax_buf: [80]char
|
||
viperlib.snprintf(&rax_buf, 80, "[RAX] rax=0x%lx\n", f_rax)
|
||
serial.puts(rax_buf)
|
||
# [STK] rbp 链回溯(定位栈损坏源)。**每一跳都必须先校验再解引用**(_SafeStackWord):
|
||
# 旧实现是 `mov rax,[rax]; mov rax,[rax+8]` 的裸链式解引用,一旦链上出现用户地址
|
||
# (实测就是 iret 帧里压入的 user_rsp=0x7fffffe00000)就会在 #PF 处理中再触发 #PF
|
||
# → 无限重入、rsp 每次下移 ~0x2A0 → 内核栈耗尽 → 三重故障,且真正的首故障被淹没。
|
||
# 用户态 rbp(>=0x80000000)直接不回溯。
|
||
fr0: uint64 = 0
|
||
__asm__(f"""mov rax, [_fault_rbp]
|
||
mov {asmout(fr0, ASM_DESCR.OUTPUT_REG)}, rax""",
|
||
op=[ASM_DESCR.CLOBBER_RAX])
|
||
stk_buf: [160]char
|
||
if fr0 < 0x1000 or fr0 >= 0x80000000:
|
||
viperlib.snprintf(&stk_buf, 160, "[STK] rbp=0x%lx out of kernel range, chain skipped\n", fr0)
|
||
serial.puts(stk_buf)
|
||
else:
|
||
fr1: uint64 = _SafeStackWord(fr0 + 8)
|
||
rbp1: uint64 = _SafeStackWord(fr0)
|
||
fr2: uint64 = _SafeStackWord(rbp1 + 8)
|
||
rbp2: uint64 = _SafeStackWord(rbp1)
|
||
fr3: uint64 = _SafeStackWord(rbp2 + 8)
|
||
rbp3: uint64 = _SafeStackWord(rbp2)
|
||
fr4: uint64 = _SafeStackWord(rbp3 + 8)
|
||
viperlib.snprintf(&stk_buf, 160, "[STK] rbp=0x%lx ret: 0x%lx 0x%lx 0x%lx 0x%lx\n",
|
||
fr0, fr1, fr2, fr3, fr4)
|
||
serial.puts(stk_buf)
|
||
elif interrupt == 13:
|
||
gp_rip: uint64 = 0
|
||
gp_err: uint64 = 0
|
||
gp_rsp: uint64 = 0
|
||
gp_cr4: uint64 = 0
|
||
gp_cr0: uint64 = 0
|
||
__asm__(f"""mov {asmout(gp_rip, ASM_DESCR.OUTPUT_REG)}, [_fault_rip]
|
||
mov {asmout(gp_err, ASM_DESCR.OUTPUT_REG)}, [_fault_err]
|
||
mov {asmout(gp_rsp, ASM_DESCR.OUTPUT_REG)}, [_fault_rsp]
|
||
mov rax, cr4
|
||
mov {asmout(gp_cr4, ASM_DESCR.OUTPUT_REG)}, rax
|
||
mov rax, cr0
|
||
mov {asmout(gp_cr0, ASM_DESCR.OUTPUT_REG)}, rax""",
|
||
op=[ASM_DESCR.CLOBBER_RAX])
|
||
gp_buf: [140]char
|
||
viperlib.snprintf(&gp_buf, 140, "[GP] rip=0x%lx err=0x%lx rsp=0x%lx cr4=0x%lx cr0=0x%lx\n",
|
||
gp_rip, gp_err, gp_rsp, gp_cr4, gp_cr0)
|
||
serial.puts(gp_buf)
|
||
# [GP-RAX]:崩溃时的 rax(isr.s 保存的 _fault_rax)。
|
||
# #GP(err=0) 最常见于"写/读非规范地址"(如 mm 空闲链 next/prev 被写坏后
|
||
# `mov [rax+0x10], rcx`):rax 就是那个坏基址,+0x10 即触发的那次访存地址。
|
||
# 现场缺这一条,只剩"[STK] rbp=0x0"无从定位,故按 #PF 分支的口径补齐。
|
||
g_frax: uint64 = 0
|
||
__asm__(f"""mov rax, [_fault_rax]
|
||
mov {asmout(g_frax, ASM_DESCR.OUTPUT_REG)}, rax""",
|
||
op=[ASM_DESCR.CLOBBER_RAX])
|
||
gp_reg_buf: [140]char
|
||
viperlib.snprintf(&gp_reg_buf, 140, "[GP-RAX] rax=0x%lx (rax+0x10=0x%lx)\n",
|
||
g_frax, g_frax + 16)
|
||
serial.puts(gp_reg_buf)
|
||
# [STK] rbp 链回溯(与 #PF 分支同款安全口径:每跳先校验再解引用,见 _SafeStackWord)
|
||
gfr0: uint64 = 0
|
||
__asm__(f"""mov rax, [_fault_rbp]
|
||
mov {asmout(gfr0, ASM_DESCR.OUTPUT_REG)}, rax""",
|
||
op=[ASM_DESCR.CLOBBER_RAX])
|
||
gp_stk_buf: [160]char
|
||
if gfr0 < 0x1000 or gfr0 >= 0x80000000:
|
||
viperlib.snprintf(&gp_stk_buf, 160, "[STK] rbp=0x%lx out of kernel range, chain skipped\n", gfr0)
|
||
serial.puts(gp_stk_buf)
|
||
else:
|
||
gfr1: uint64 = _SafeStackWord(gfr0 + 8)
|
||
grbp1: uint64 = _SafeStackWord(gfr0)
|
||
gfr2: uint64 = _SafeStackWord(grbp1 + 8)
|
||
grbp2: uint64 = _SafeStackWord(grbp1)
|
||
gfr3: uint64 = _SafeStackWord(grbp2 + 8)
|
||
grbp3: uint64 = _SafeStackWord(grbp2)
|
||
gfr4: uint64 = _SafeStackWord(grbp3 + 8)
|
||
viperlib.snprintf(&gp_stk_buf, 160, "[STK] rbp=0x%lx ret: 0x%lx 0x%lx 0x%lx 0x%lx\n",
|
||
gfr0, gfr1, gfr2, gfr3, gfr4)
|
||
serial.puts(gp_stk_buf)
|
||
else:
|
||
# 其他异常(#UD 等):打印 rip/rsp 定位执行位置(isr.s 已保存 _fault_rip)
|
||
ex_rip: uint64 = 0
|
||
ex_rsp: uint64 = 0
|
||
__asm__(f"""mov {asmout(ex_rip, ASM_DESCR.OUTPUT_REG)}, [_fault_rip]
|
||
mov {asmout(ex_rsp, ASM_DESCR.OUTPUT_REG)}, [_fault_rsp]""",
|
||
op=[ASM_DESCR.CLOBBER_RAX])
|
||
ex_buf: [100]char
|
||
viperlib.snprintf(&ex_buf, 100, "[EX] int=%d rip=0x%lx rsp=0x%lx\n", interrupt, ex_rip, ex_rsp)
|
||
serial.puts(ex_buf)
|
||
# [RAX] 崩溃时 rax(isr.s 保存)
|
||
f_rax: uint64 = 0
|
||
__asm__(f"""mov {asmout(f_rax, ASM_DESCR.OUTPUT_REG)}, [_fault_rax]""",
|
||
op=[ASM_DESCR.CLOBBER_RAX])
|
||
rax_buf: [80]char
|
||
viperlib.snprintf(&rax_buf, 80, "[RAX] rax=0x%lx\n", f_rax)
|
||
serial.puts(rax_buf)
|
||
# [STK] rbp 链回溯(与 #PF 分支同款安全口径:每跳先校验再解引用,见 _SafeStackWord)
|
||
fr0: uint64 = 0
|
||
__asm__(f"""mov rax, [_fault_rbp]
|
||
mov {asmout(fr0, ASM_DESCR.OUTPUT_REG)}, rax""",
|
||
op=[ASM_DESCR.CLOBBER_RAX])
|
||
stk_buf: [160]char
|
||
if fr0 < 0x1000 or fr0 >= 0x80000000:
|
||
viperlib.snprintf(&stk_buf, 160, "[STK] rbp=0x%lx out of kernel range, chain skipped\n", fr0)
|
||
serial.puts(stk_buf)
|
||
else:
|
||
fr1: uint64 = _SafeStackWord(fr0 + 8)
|
||
rbp1: uint64 = _SafeStackWord(fr0)
|
||
fr2: uint64 = _SafeStackWord(rbp1 + 8)
|
||
rbp2: uint64 = _SafeStackWord(rbp1)
|
||
fr3: uint64 = _SafeStackWord(rbp2 + 8)
|
||
rbp3: uint64 = _SafeStackWord(rbp2)
|
||
fr4: uint64 = _SafeStackWord(rbp3 + 8)
|
||
viperlib.snprintf(&stk_buf, 160, "[STK] rbp=0x%lx ret: 0x%lx 0x%lx 0x%lx 0x%lx\n",
|
||
fr0, fr1, fr2, fr3, fr4)
|
||
serial.puts(stk_buf)
|
||
s: sched.Scheduler* = sched._sched_ptr
|
||
# 如果调度器未初始化,直接进入安全停机状态
|
||
if s == 0:
|
||
serial.puts(" KERNEL PANIC (sched not init)\n")
|
||
while True:
|
||
asm.sti()
|
||
asm.hlt()
|
||
pass
|
||
tid: int = s.current_tid
|
||
if tid == 0:
|
||
serial.puts(" KERNEL PANIC\n")
|
||
while True:
|
||
asm.sti()
|
||
asm.hlt()
|
||
pass
|
||
# s.threads 为 [16 x Thread](sched.MAX_THREADS),越界写会破坏调度器状态
|
||
if tid < 0 or tid >= 16:
|
||
serial.puts(" KERNEL PANIC (bad tid)\n")
|
||
while True:
|
||
asm.sti()
|
||
asm.hlt()
|
||
pass
|
||
buf2: [64]char
|
||
viperlib.snprintf(&buf2, 64, " exc in tid=%d, terminating\n", tid)
|
||
serial.puts(buf2)
|
||
# 用户线程被异常终止时回收其用户栈等资源(主线程/内核线程没有对应槽位,自动跳过)。
|
||
proc.free_user_thread(proc.find_user_slot_by_tid(tid))
|
||
s.threads[tid].state = 3
|
||
# Restore GS to kernel-normal state before _yield().
|
||
# ISR entry does swapgs for user-mode exceptions (GS_BASE=&_per_cpu).
|
||
# Since _yield() switches to another thread and never returns via ISR exit,
|
||
# the swapgs at ISR exit is never executed. We must swap back here.
|
||
# Check IA32_GS_BASE (MSR 0xC0000101): if non-zero, swapgs was done at entry.
|
||
__asm__(f"""mov ecx, 0xC0000101
|
||
rdmsr
|
||
shl rdx, 32
|
||
or rax, rdx
|
||
test rax, rax
|
||
jz 1f
|
||
swapgs
|
||
1:""",
|
||
op=[ASM_DESCR.CLOBBER_RAX, ASM_DESCR.CLOBBER_RCX, ASM_DESCR.CLOBBER_RDX])
|
||
# 【修复】本路径是从**异常上下文**进来(用户态异常时 CPU 已把 IF 清 0),而且这里
|
||
# **永不 iretq 返回**(直接 _yield 换线程)⇒ 若不在这里开中断,被切到的线程就会带着
|
||
# "中断关着"继续跑 ⇒ 定时器再也进不来 ⇒ 整机卡死;后续再出异常就是三重故障。
|
||
# (定时器抢占路径没这个问题:它靠 iretq 从原帧恢复 RFLAGS。)
|
||
asm.sti()
|
||
sched.Scheduler._yield()
|
||
while True:
|
||
asm.sti()
|
||
asm.hlt()
|
||
|
||
export def isr0_handler(): isrCommonhandler(0)
|
||
export def isr1_handler(): isrCommonhandler(1)
|
||
export def isr2_handler(): isrCommonhandler(2)
|
||
export def isr3_handler(): isrCommonhandler(3)
|
||
export def isr4_handler(): isrCommonhandler(4)
|
||
export def isr5_handler(): isrCommonhandler(5)
|
||
export def isr6_handler(): isrCommonhandler(6)
|
||
export def isr7_handler(): isrCommonhandler(7)
|
||
export def isr8_handler(): isrCommonhandler(8)
|
||
export def isr9_handler(): isrCommonhandler(9)
|
||
export def isr10_handler(): isrCommonhandler(10)
|
||
export def isr11_handler(): isrCommonhandler(11)
|
||
export def isr12_handler(): isrCommonhandler(12)
|
||
export def isr13_handler(): isrCommonhandler(13)
|
||
export def isr14_handler(): isrCommonhandler(14)
|
||
export def isr15_handler(): isrCommonhandler(15)
|
||
export def isr16_handler(): isrCommonhandler(16)
|
||
export def isr17_handler(): isrCommonhandler(17)
|
||
export def isr18_handler(): isrCommonhandler(18)
|
||
export def isr19_handler(): isrCommonhandler(19)
|
||
export def isr20_handler(): isrCommonhandler(20)
|
||
export def isr21_handler(): isrCommonhandler(21)
|
||
export def isr22_handler(): isrCommonhandler(22)
|
||
export def isr23_handler(): isrCommonhandler(23)
|
||
export def isr24_handler(): isrCommonhandler(24)
|
||
export def isr25_handler(): isrCommonhandler(25)
|
||
export def isr26_handler(): isrCommonhandler(26)
|
||
export def isr27_handler(): isrCommonhandler(27)
|
||
export def isr28_handler(): isrCommonhandler(28)
|
||
export def isr29_handler(): isrCommonhandler(29)
|
||
export def isr30_handler(): isrCommonhandler(30)
|
||
export def isr31_handler(): isrCommonhandler(31)
|
||
export def isr32_handler(): timer.timer_handler()
|
||
|
||
export def isr33_handler():
|
||
handler: irq_handler_t = irqGetHandler(1)
|
||
if handler:
|
||
__asm__(f"""call {asminp(handler, ASM_DESCR.REG_ANY)}""",
|
||
op=[ASM_DESCR.CLOBBER_MEMORY, ASM_DESCR.CLOBBER_RAX,
|
||
ASM_DESCR.CLOBBER_RCX, ASM_DESCR.CLOBBER_RDX,
|
||
ASM_DESCR.CLOBBER_RSI, ASM_DESCR.CLOBBER_RDI,
|
||
ASM_DESCR.CLOBBER_R8, ASM_DESCR.CLOBBER_R9,
|
||
ASM_DESCR.CLOBBER_R10, ASM_DESCR.CLOBBER_R11])
|
||
pic.eoi(1)
|
||
apic.eoi()
|
||
|
||
export def isr34_handler():
|
||
handler2: irq_handler_t = irqGetHandler(2)
|
||
if handler2:
|
||
__asm__(f"""call {asminp(handler2, ASM_DESCR.REG_ANY)}""",
|
||
op=[ASM_DESCR.CLOBBER_MEMORY, ASM_DESCR.CLOBBER_RAX,
|
||
ASM_DESCR.CLOBBER_RCX, ASM_DESCR.CLOBBER_RDX,
|
||
ASM_DESCR.CLOBBER_RSI, ASM_DESCR.CLOBBER_RDI,
|
||
ASM_DESCR.CLOBBER_R8, ASM_DESCR.CLOBBER_R9,
|
||
ASM_DESCR.CLOBBER_R10, ASM_DESCR.CLOBBER_R11])
|
||
pic.eoi(2)
|
||
apic.eoi()
|
||
|
||
export def isr35_handler():
|
||
handler3: irq_handler_t = irqGetHandler(3)
|
||
if handler3:
|
||
__asm__(f"""call {asminp(handler3, ASM_DESCR.REG_ANY)}""",
|
||
op=[ASM_DESCR.CLOBBER_MEMORY, ASM_DESCR.CLOBBER_RAX,
|
||
ASM_DESCR.CLOBBER_RCX, ASM_DESCR.CLOBBER_RDX,
|
||
ASM_DESCR.CLOBBER_RSI, ASM_DESCR.CLOBBER_RDI,
|
||
ASM_DESCR.CLOBBER_R8, ASM_DESCR.CLOBBER_R9,
|
||
ASM_DESCR.CLOBBER_R10, ASM_DESCR.CLOBBER_R11])
|
||
pic.eoi(3)
|
||
apic.eoi()
|
||
|
||
export def isr36_handler():
|
||
handler4: irq_handler_t = irqGetHandler(4)
|
||
if handler4:
|
||
__asm__(f"""call {asminp(handler4, ASM_DESCR.REG_ANY)}""",
|
||
op=[ASM_DESCR.CLOBBER_MEMORY, ASM_DESCR.CLOBBER_RAX,
|
||
ASM_DESCR.CLOBBER_RCX, ASM_DESCR.CLOBBER_RDX,
|
||
ASM_DESCR.CLOBBER_RSI, ASM_DESCR.CLOBBER_RDI,
|
||
ASM_DESCR.CLOBBER_R8, ASM_DESCR.CLOBBER_R9,
|
||
ASM_DESCR.CLOBBER_R10, ASM_DESCR.CLOBBER_R11])
|
||
pic.eoi(4)
|
||
apic.eoi()
|
||
|
||
export def isr37_handler():
|
||
handler5: irq_handler_t = irqGetHandler(5)
|
||
if handler5:
|
||
__asm__(f"""call {asminp(handler5, ASM_DESCR.REG_ANY)}""",
|
||
op=[ASM_DESCR.CLOBBER_MEMORY, ASM_DESCR.CLOBBER_RAX,
|
||
ASM_DESCR.CLOBBER_RCX, ASM_DESCR.CLOBBER_RDX,
|
||
ASM_DESCR.CLOBBER_RSI, ASM_DESCR.CLOBBER_RDI,
|
||
ASM_DESCR.CLOBBER_R8, ASM_DESCR.CLOBBER_R9,
|
||
ASM_DESCR.CLOBBER_R10, ASM_DESCR.CLOBBER_R11])
|
||
pic.eoi(5)
|
||
apic.eoi()
|
||
|
||
export def isr38_handler():
|
||
handler6: irq_handler_t = irqGetHandler(6)
|
||
if handler6:
|
||
__asm__(f"""call {asminp(handler6, ASM_DESCR.REG_ANY)}""",
|
||
op=[ASM_DESCR.CLOBBER_MEMORY, ASM_DESCR.CLOBBER_RAX,
|
||
ASM_DESCR.CLOBBER_RCX, ASM_DESCR.CLOBBER_RDX,
|
||
ASM_DESCR.CLOBBER_RSI, ASM_DESCR.CLOBBER_RDI,
|
||
ASM_DESCR.CLOBBER_R8, ASM_DESCR.CLOBBER_R9,
|
||
ASM_DESCR.CLOBBER_R10, ASM_DESCR.CLOBBER_R11])
|
||
pic.eoi(6)
|
||
apic.eoi()
|
||
|
||
export def isr39_handler():
|
||
if pic.isSpurious(7):
|
||
return
|
||
handler7: irq_handler_t = irqGetHandler(7)
|
||
if handler7:
|
||
__asm__(f"""call {asminp(handler7, ASM_DESCR.REG_ANY)}""",
|
||
op=[ASM_DESCR.CLOBBER_MEMORY, ASM_DESCR.CLOBBER_RAX,
|
||
ASM_DESCR.CLOBBER_RCX, ASM_DESCR.CLOBBER_RDX,
|
||
ASM_DESCR.CLOBBER_RSI, ASM_DESCR.CLOBBER_RDI,
|
||
ASM_DESCR.CLOBBER_R8, ASM_DESCR.CLOBBER_R9,
|
||
ASM_DESCR.CLOBBER_R10, ASM_DESCR.CLOBBER_R11])
|
||
pic.eoi(7)
|
||
apic.eoi()
|
||
|
||
export def isr40_handler():
|
||
handler8: irq_handler_t = irqGetHandler(8)
|
||
if handler8:
|
||
__asm__(f"""call {asminp(handler8, ASM_DESCR.REG_ANY)}""",
|
||
op=[ASM_DESCR.CLOBBER_MEMORY, ASM_DESCR.CLOBBER_RAX,
|
||
ASM_DESCR.CLOBBER_RCX, ASM_DESCR.CLOBBER_RDX,
|
||
ASM_DESCR.CLOBBER_RSI, ASM_DESCR.CLOBBER_RDI,
|
||
ASM_DESCR.CLOBBER_R8, ASM_DESCR.CLOBBER_R9,
|
||
ASM_DESCR.CLOBBER_R10, ASM_DESCR.CLOBBER_R11])
|
||
pic.eoi(8)
|
||
apic.eoi()
|
||
|
||
export def isr41_handler():
|
||
handler9: irq_handler_t = irqGetHandler(9)
|
||
if handler9:
|
||
__asm__(f"""call {asminp(handler9, ASM_DESCR.REG_ANY)}""",
|
||
op=[ASM_DESCR.CLOBBER_MEMORY, ASM_DESCR.CLOBBER_RAX,
|
||
ASM_DESCR.CLOBBER_RCX, ASM_DESCR.CLOBBER_RDX,
|
||
ASM_DESCR.CLOBBER_RSI, ASM_DESCR.CLOBBER_RDI,
|
||
ASM_DESCR.CLOBBER_R8, ASM_DESCR.CLOBBER_R9,
|
||
ASM_DESCR.CLOBBER_R10, ASM_DESCR.CLOBBER_R11])
|
||
pic.eoi(9)
|
||
apic.eoi()
|
||
|
||
export def isr42_handler():
|
||
handler10: irq_handler_t = irqGetHandler(10)
|
||
if handler10:
|
||
__asm__(f"""call {asminp(handler10, ASM_DESCR.REG_ANY)}""",
|
||
op=[ASM_DESCR.CLOBBER_MEMORY, ASM_DESCR.CLOBBER_RAX,
|
||
ASM_DESCR.CLOBBER_RCX, ASM_DESCR.CLOBBER_RDX,
|
||
ASM_DESCR.CLOBBER_RSI, ASM_DESCR.CLOBBER_RDI,
|
||
ASM_DESCR.CLOBBER_R8, ASM_DESCR.CLOBBER_R9,
|
||
ASM_DESCR.CLOBBER_R10, ASM_DESCR.CLOBBER_R11])
|
||
pic.eoi(10)
|
||
apic.eoi()
|
||
|
||
export def isr43_handler():
|
||
handler11: irq_handler_t = irqGetHandler(11)
|
||
if handler11:
|
||
__asm__(f"""call {asminp(handler11, ASM_DESCR.REG_ANY)}""",
|
||
op=[ASM_DESCR.CLOBBER_MEMORY, ASM_DESCR.CLOBBER_RAX,
|
||
ASM_DESCR.CLOBBER_RCX, ASM_DESCR.CLOBBER_RDX,
|
||
ASM_DESCR.CLOBBER_RSI, ASM_DESCR.CLOBBER_RDI,
|
||
ASM_DESCR.CLOBBER_R8, ASM_DESCR.CLOBBER_R9,
|
||
ASM_DESCR.CLOBBER_R10, ASM_DESCR.CLOBBER_R11])
|
||
pic.eoi(11)
|
||
apic.eoi()
|
||
|
||
export def isr44_handler():
|
||
handler: irq_handler_t = irqGetHandler(12)
|
||
if handler:
|
||
__asm__(f"""call {asminp(handler, ASM_DESCR.REG_ANY)}""",
|
||
op=[ASM_DESCR.CLOBBER_MEMORY, ASM_DESCR.CLOBBER_RAX,
|
||
ASM_DESCR.CLOBBER_RCX, ASM_DESCR.CLOBBER_RDX,
|
||
ASM_DESCR.CLOBBER_RSI, ASM_DESCR.CLOBBER_RDI,
|
||
ASM_DESCR.CLOBBER_R8, ASM_DESCR.CLOBBER_R9,
|
||
ASM_DESCR.CLOBBER_R10, ASM_DESCR.CLOBBER_R11])
|
||
pic.eoi(12)
|
||
apic.eoi()
|
||
|
||
export def isr45_handler():
|
||
pic.eoi(13)
|
||
apic.eoi()
|
||
|
||
export def isr46_handler():
|
||
pic.eoi(14)
|
||
apic.eoi()
|
||
|
||
export def isr47_handler():
|
||
if pic.isSpurious(15):
|
||
return
|
||
pic.eoi(15)
|
||
apic.eoi()
|
||
|
||
def init_exceptions():
|
||
setGate(0, uint64(isr0), CODE_SEG, 0x8E)
|
||
setGate(1, uint64(isr1), CODE_SEG, 0x8E)
|
||
setGate(2, uint64(isr2), CODE_SEG, 0x8E)
|
||
setGate(3, uint64(isr3), CODE_SEG, 0x8E)
|
||
setGate(4, uint64(isr4), CODE_SEG, 0x8E)
|
||
setGate(5, uint64(isr5), CODE_SEG, 0x8E)
|
||
setGate(6, uint64(isr6), CODE_SEG, 0x8E)
|
||
setGate(7, uint64(isr7), CODE_SEG, 0x8E)
|
||
setGate(8, uint64(isr8), CODE_SEG, 0x8E)
|
||
setGate(9, uint64(isr9), CODE_SEG, 0x8E)
|
||
setGate(10, uint64(isr10), CODE_SEG, 0x8E)
|
||
setGate(11, uint64(isr11), CODE_SEG, 0x8E)
|
||
setGate(12, uint64(isr12), CODE_SEG, 0x8E)
|
||
setGate(13, uint64(isr13), CODE_SEG, 0x8E)
|
||
setGate(14, uint64(isr14), CODE_SEG, 0x8E)
|
||
setGate(15, uint64(isr15), CODE_SEG, 0x8E)
|
||
setGate(16, uint64(isr16), CODE_SEG, 0x8E)
|
||
setGate(17, uint64(isr17), CODE_SEG, 0x8E)
|
||
setGate(18, uint64(isr18), CODE_SEG, 0x8E)
|
||
setGate(19, uint64(isr19), CODE_SEG, 0x8E)
|
||
setGate(20, uint64(isr20), CODE_SEG, 0x8E)
|
||
setGate(21, uint64(isr21), CODE_SEG, 0x8E)
|
||
setGate(22, uint64(isr22), CODE_SEG, 0x8E)
|
||
setGate(23, uint64(isr23), CODE_SEG, 0x8E)
|
||
setGate(24, uint64(isr24), CODE_SEG, 0x8E)
|
||
setGate(25, uint64(isr25), CODE_SEG, 0x8E)
|
||
setGate(26, uint64(isr26), CODE_SEG, 0x8E)
|
||
setGate(27, uint64(isr27), CODE_SEG, 0x8E)
|
||
setGate(28, uint64(isr28), CODE_SEG, 0x8E)
|
||
setGate(29, uint64(isr29), CODE_SEG, 0x8E)
|
||
setGate(30, uint64(isr30), CODE_SEG, 0x8E)
|
||
setGate(31, uint64(isr31), CODE_SEG, 0x8E)
|
||
|
||
def init_irqs():
|
||
setGate(32, uint64(isr32), CODE_SEG, 0x8E)
|
||
setGate(33, uint64(isr33), CODE_SEG, 0x8E)
|
||
setGate(34, uint64(isr34), CODE_SEG, 0x8E)
|
||
setGate(35, uint64(isr35), CODE_SEG, 0x8E)
|
||
setGate(36, uint64(isr36), CODE_SEG, 0x8E)
|
||
setGate(37, uint64(isr37), CODE_SEG, 0x8E)
|
||
setGate(38, uint64(isr38), CODE_SEG, 0x8E)
|
||
setGate(39, uint64(isr39), CODE_SEG, 0x8E)
|
||
setGate(40, uint64(isr40), CODE_SEG, 0x8E)
|
||
setGate(41, uint64(isr41), CODE_SEG, 0x8E)
|
||
setGate(42, uint64(isr42), CODE_SEG, 0x8E)
|
||
setGate(43, uint64(isr43), CODE_SEG, 0x8E)
|
||
setGate(44, uint64(isr44), CODE_SEG, 0x8E)
|
||
setGate(45, uint64(isr45), CODE_SEG, 0x8E)
|
||
setGate(46, uint64(isr46), CODE_SEG, 0x8E)
|
||
setGate(47, uint64(isr47), CODE_SEG, 0x8E)
|
||
|
||
irq_handlers: static [16]irq_handler_t = [None]
|
||
|
||
def irqInstallHandler(irq: int, handler: irq_handler_t, name: str) -> int:
|
||
global irq_handlers
|
||
if irq < 0 or irq > 15: return -1
|
||
irq_handlers[irq] = handler
|
||
return 0
|
||
|
||
def irqGetHandler(irq: int) -> irq_handler_t:
|
||
if irq < 0 or irq > 15: return None
|
||
return irq_handlers[irq]
|
||
|
||
def init():
|
||
global idt
|
||
for i in range(256):
|
||
setGate(i, uint64(isr_default), CODE_SEG, 0x8E)
|
||
pic.init()
|
||
init_exceptions()
|
||
init_irqs()
|
||
# Register ISR 0x80 for int 0x80 syscall interface (user-mode ELF apps)
|
||
setGate(0x80, uint64(isr80), CODE_SEG, 0xEE) # DPL=3 allows Ring 3 to call int 0x80
|
||
# Build idt_ptr on stack and load directly in one asm block
|
||
__asm__("""lea rax, [rip + idt]
|
||
sub rsp, 16
|
||
mov word ptr [rsp], 0x0fff
|
||
mov qword ptr [rsp+2], rax
|
||
lidt [rsp]
|
||
add rsp, 16""",
|
||
op=[ASM_DESCR.CLOBBER_MEMORY, ASM_DESCR.CLOBBER_RAX])
|