Files
ViperOS/VKernel/Kernel/intr/idt.vp
T

609 lines
25 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 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])