import platform.pch.pic as pic import platform.pch.timer as timer import sched.sched as sched import drivers.serial.uart.serial as serial import viperlib import asm import t, c CODE_SEG: t.CDefine | t.CUInt16T = 0x08 @c.Attribute(t.attr.packed) class idt_entry: base_low: t.CUInt16T selector: t.CUInt16T ist_attr: t.CUInt8T type_attr: t.CUInt8T base_middle: t.CUInt16T base_high: t.CUInt32T reserved1: t.CUInt32T idt: t.CArray[idt_entry, 256] = [] irq_handler_t: t.CTypedef | t.Callable[[], t.CInt] def isr0() -> t.CExtern | t.CVoid | t.State: pass def isr1() -> t.CExtern | t.CVoid | t.State: pass def isr2() -> t.CExtern | t.CVoid | t.State: pass def isr3() -> t.CExtern | t.CVoid | t.State: pass def isr4() -> t.CExtern | t.CVoid | t.State: pass def isr5() -> t.CExtern | t.CVoid | t.State: pass def isr6() -> t.CExtern | t.CVoid | t.State: pass def isr7() -> t.CExtern | t.CVoid | t.State: pass def isr8() -> t.CExtern | t.CVoid | t.State: pass def isr9() -> t.CExtern | t.CVoid | t.State: pass def isr10() -> t.CExtern | t.CVoid | t.State: pass def isr11() -> t.CExtern | t.CVoid | t.State: pass def isr12() -> t.CExtern | t.CVoid | t.State: pass def isr13() -> t.CExtern | t.CVoid | t.State: pass def isr14() -> t.CExtern | t.CVoid | t.State: pass def isr15() -> t.CExtern | t.CVoid | t.State: pass def isr16() -> t.CExtern | t.CVoid | t.State: pass def isr17() -> t.CExtern | t.CVoid | t.State: pass def isr18() -> t.CExtern | t.CVoid | t.State: pass def isr19() -> t.CExtern | t.CVoid | t.State: pass def isr20() -> t.CExtern | t.CVoid | t.State: pass def isr21() -> t.CExtern | t.CVoid | t.State: pass def isr22() -> t.CExtern | t.CVoid | t.State: pass def isr23() -> t.CExtern | t.CVoid | t.State: pass def isr24() -> t.CExtern | t.CVoid | t.State: pass def isr25() -> t.CExtern | t.CVoid | t.State: pass def isr26() -> t.CExtern | t.CVoid | t.State: pass def isr27() -> t.CExtern | t.CVoid | t.State: pass def isr28() -> t.CExtern | t.CVoid | t.State: pass def isr29() -> t.CExtern | t.CVoid | t.State: pass def isr30() -> t.CExtern | t.CVoid | t.State: pass def isr31() -> t.CExtern | t.CVoid | t.State: pass def isr32() -> t.CExtern | t.CVoid | t.State: pass def isr33() -> t.CExtern | t.CVoid | t.State: pass def isr34() -> t.CExtern | t.CVoid | t.State: pass def isr35() -> t.CExtern | t.CVoid | t.State: pass def isr36() -> t.CExtern | t.CVoid | t.State: pass def isr37() -> t.CExtern | t.CVoid | t.State: pass def isr38() -> t.CExtern | t.CVoid | t.State: pass def isr39() -> t.CExtern | t.CVoid | t.State: pass def isr40() -> t.CExtern | t.CVoid | t.State: pass def isr41() -> t.CExtern | t.CVoid | t.State: pass def isr42() -> t.CExtern | t.CVoid | t.State: pass def isr43() -> t.CExtern | t.CVoid | t.State: pass def isr44() -> t.CExtern | t.CVoid | t.State: pass def isr45() -> t.CExtern | t.CVoid | t.State: pass def isr46() -> t.CExtern | t.CVoid | t.State: pass def isr47() -> t.CExtern | t.CVoid | t.State: pass def isr80() -> t.CExtern | t.CVoid | t.State: pass def isr_default() -> t.CExtern | t.CVoid | t.State: pass def setGate(num: int, base: t.CUInt64T, sel: t.CUInt16T, flags: t.CUInt8T): global idt idt[num].base_low = (base & 0xFFFF) idt[num].base_middle = (base >> 16) & 0xFFFF idt[num].base_high = (base >> 32) & 0xFFFFFFFF idt[num].selector = sel idt[num].ist_attr = 0 idt[num].type_attr = flags idt[num].reserved1 = 0 def isrCommonhandler(interrupt: t.CInt): c.Asm(f"""mov dx, 0x3F8 mov al, 91 out dx, al mov ecx, {c.AsmInp(interrupt, t.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=[t.ASM_DESCR.CLOBBER_RAX, t.ASM_DESCR.CLOBBER_RCX, t.ASM_DESCR.CLOBBER_RDX]) # Print CR2 for page faults (ISR 14) if interrupt == 14: cr2: t.CUInt64T = 0 c.Asm(f"""mov {c.AsmOut(cr2, t.ASM_DESCR.OUTPUT_REG)}, cr2""", op=[t.ASM_DESCR.CLOBBER_RAX]) fault_rip: t.CUInt64T = 0 fault_err: t.CUInt64T = 0 c.Asm(f"""mov {c.AsmOut(fault_rip, t.ASM_DESCR.OUTPUT_REG)}, [_fault_rip] mov {c.AsmOut(fault_err, t.ASM_DESCR.OUTPUT_REG)}, [_fault_err]""", op=[t.ASM_DESCR.CLOBBER_RAX]) buf: t.CArray[t.CChar, 80] viperlib.snprintf(c.Addr(buf), 80, "[PF] cr2=0x%lx rip=0x%lx err=0x%lx\n", cr2, fault_rip, fault_err) serial.puts(buf) elif interrupt == 13: gp_rip: t.CUInt64T = 0 gp_err: t.CUInt64T = 0 c.Asm(f"""mov {c.AsmOut(gp_rip, t.ASM_DESCR.OUTPUT_REG)}, [_fault_rip] mov {c.AsmOut(gp_err, t.ASM_DESCR.OUTPUT_REG)}, [_fault_err]""", op=[t.ASM_DESCR.CLOBBER_RAX]) gp_buf: t.CArray[t.CChar, 80] viperlib.snprintf(c.Addr(gp_buf), 80, "[GP] rip=0x%lx err=0x%lx\n", gp_rip, gp_err) serial.puts(gp_buf) s: sched.Scheduler | t.CPtr = sched._sched_ptr # 如果调度器未初始化,直接进入安全停机状态 if s == 0: serial.puts(" KERNEL PANIC (sched not init)\n") while True: asm.sti() asm.hlt() tid: t.CInt = s.current_tid if tid == 0: serial.puts(" KERNEL PANIC\n") while True: asm.sti() asm.hlt() buf2: t.CArray[t.CChar, 64] viperlib.snprintf(c.Addr(buf2), 64, " exc in tid=%d, terminating\n", tid) serial.puts(buf2) 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. c.Asm(f"""mov ecx, 0xC0000101 rdmsr shl rdx, 32 or rax, rdx test rax, rax jz 1f swapgs 1:""", op=[t.ASM_DESCR.CLOBBER_RAX, t.ASM_DESCR.CLOBBER_RCX, t.ASM_DESCR.CLOBBER_RDX]) sched.Scheduler._yield() while True: asm.sti() asm.hlt() def isr0_handler() -> t.CExport | t.CVoid: isrCommonhandler(0) def isr1_handler() -> t.CExport | t.CVoid: isrCommonhandler(1) def isr2_handler() -> t.CExport | t.CVoid: isrCommonhandler(2) def isr3_handler() -> t.CExport | t.CVoid: isrCommonhandler(3) def isr4_handler() -> t.CExport | t.CVoid: isrCommonhandler(4) def isr5_handler() -> t.CExport | t.CVoid: isrCommonhandler(5) def isr6_handler() -> t.CExport | t.CVoid: isrCommonhandler(6) def isr7_handler() -> t.CExport | t.CVoid: isrCommonhandler(7) def isr8_handler() -> t.CExport | t.CVoid: isrCommonhandler(8) def isr9_handler() -> t.CExport | t.CVoid: isrCommonhandler(9) def isr10_handler() -> t.CExport | t.CVoid: isrCommonhandler(10) def isr11_handler() -> t.CExport | t.CVoid: isrCommonhandler(11) def isr12_handler() -> t.CExport | t.CVoid: isrCommonhandler(12) def isr13_handler() -> t.CExport | t.CVoid: isrCommonhandler(13) def isr14_handler() -> t.CExport | t.CVoid: isrCommonhandler(14) def isr15_handler() -> t.CExport | t.CVoid: isrCommonhandler(15) def isr16_handler() -> t.CExport | t.CVoid: isrCommonhandler(16) def isr17_handler() -> t.CExport | t.CVoid: isrCommonhandler(17) def isr18_handler() -> t.CExport | t.CVoid: isrCommonhandler(18) def isr19_handler() -> t.CExport | t.CVoid: isrCommonhandler(19) def isr20_handler() -> t.CExport | t.CVoid: isrCommonhandler(20) def isr21_handler() -> t.CExport | t.CVoid: isrCommonhandler(21) def isr22_handler() -> t.CExport | t.CVoid: isrCommonhandler(22) def isr23_handler() -> t.CExport | t.CVoid: isrCommonhandler(23) def isr24_handler() -> t.CExport | t.CVoid: isrCommonhandler(24) def isr25_handler() -> t.CExport | t.CVoid: isrCommonhandler(25) def isr26_handler() -> t.CExport | t.CVoid: isrCommonhandler(26) def isr27_handler() -> t.CExport | t.CVoid: isrCommonhandler(27) def isr28_handler() -> t.CExport | t.CVoid: isrCommonhandler(28) def isr29_handler() -> t.CExport | t.CVoid: isrCommonhandler(29) def isr30_handler() -> t.CExport | t.CVoid: isrCommonhandler(30) def isr31_handler() -> t.CExport | t.CVoid: isrCommonhandler(31) def isr32_handler() -> t.CExport | t.CVoid: timer.timer_handler() def isr33_handler() -> t.CExport | t.CVoid: handler: irq_handler_t = irqGetHandler(1) if handler: c.Asm(f"""call {c.AsmInp(handler, t.ASM_DESCR.REG_ANY)}""", op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RAX, t.ASM_DESCR.CLOBBER_RCX, t.ASM_DESCR.CLOBBER_RDX, t.ASM_DESCR.CLOBBER_R8, t.ASM_DESCR.CLOBBER_R9, t.ASM_DESCR.CLOBBER_R10, t.ASM_DESCR.CLOBBER_R11]) pic.eoi(1) def isr34_handler() -> t.CExport | t.CVoid: handler2: irq_handler_t = irqGetHandler(2) if handler2: c.Asm(f"""call {c.AsmInp(handler2, t.ASM_DESCR.REG_ANY)}""", op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RAX, t.ASM_DESCR.CLOBBER_RCX, t.ASM_DESCR.CLOBBER_RDX, t.ASM_DESCR.CLOBBER_R8, t.ASM_DESCR.CLOBBER_R9, t.ASM_DESCR.CLOBBER_R10, t.ASM_DESCR.CLOBBER_R11]) pic.eoi(2) def isr35_handler() -> t.CExport | t.CVoid: handler3: irq_handler_t = irqGetHandler(3) if handler3: c.Asm(f"""call {c.AsmInp(handler3, t.ASM_DESCR.REG_ANY)}""", op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RAX, t.ASM_DESCR.CLOBBER_RCX, t.ASM_DESCR.CLOBBER_RDX, t.ASM_DESCR.CLOBBER_R8, t.ASM_DESCR.CLOBBER_R9, t.ASM_DESCR.CLOBBER_R10, t.ASM_DESCR.CLOBBER_R11]) pic.eoi(3) def isr36_handler() -> t.CExport | t.CVoid: handler4: irq_handler_t = irqGetHandler(4) if handler4: c.Asm(f"""call {c.AsmInp(handler4, t.ASM_DESCR.REG_ANY)}""", op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RAX, t.ASM_DESCR.CLOBBER_RCX, t.ASM_DESCR.CLOBBER_RDX, t.ASM_DESCR.CLOBBER_R8, t.ASM_DESCR.CLOBBER_R9, t.ASM_DESCR.CLOBBER_R10, t.ASM_DESCR.CLOBBER_R11]) pic.eoi(4) def isr37_handler() -> t.CExport | t.CVoid: handler5: irq_handler_t = irqGetHandler(5) if handler5: c.Asm(f"""call {c.AsmInp(handler5, t.ASM_DESCR.REG_ANY)}""", op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RAX, t.ASM_DESCR.CLOBBER_RCX, t.ASM_DESCR.CLOBBER_RDX, t.ASM_DESCR.CLOBBER_R8, t.ASM_DESCR.CLOBBER_R9, t.ASM_DESCR.CLOBBER_R10, t.ASM_DESCR.CLOBBER_R11]) pic.eoi(5) def isr38_handler() -> t.CExport | t.CVoid: handler6: irq_handler_t = irqGetHandler(6) if handler6: c.Asm(f"""call {c.AsmInp(handler6, t.ASM_DESCR.REG_ANY)}""", op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RAX, t.ASM_DESCR.CLOBBER_RCX, t.ASM_DESCR.CLOBBER_RDX, t.ASM_DESCR.CLOBBER_R8, t.ASM_DESCR.CLOBBER_R9, t.ASM_DESCR.CLOBBER_R10, t.ASM_DESCR.CLOBBER_R11]) pic.eoi(6) def isr39_handler() -> t.CExport | t.CVoid: if pic.isSpurious(7): return handler7: irq_handler_t = irqGetHandler(7) if handler7: c.Asm(f"""call {c.AsmInp(handler7, t.ASM_DESCR.REG_ANY)}""", op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RAX, t.ASM_DESCR.CLOBBER_RCX, t.ASM_DESCR.CLOBBER_RDX, t.ASM_DESCR.CLOBBER_R8, t.ASM_DESCR.CLOBBER_R9, t.ASM_DESCR.CLOBBER_R10, t.ASM_DESCR.CLOBBER_R11]) pic.eoi(7) def isr40_handler() -> t.CExport | t.CVoid: handler8: irq_handler_t = irqGetHandler(8) if handler8: c.Asm(f"""call {c.AsmInp(handler8, t.ASM_DESCR.REG_ANY)}""", op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RAX, t.ASM_DESCR.CLOBBER_RCX, t.ASM_DESCR.CLOBBER_RDX, t.ASM_DESCR.CLOBBER_R8, t.ASM_DESCR.CLOBBER_R9, t.ASM_DESCR.CLOBBER_R10, t.ASM_DESCR.CLOBBER_R11]) pic.eoi(8) def isr41_handler() -> t.CExport | t.CVoid: handler9: irq_handler_t = irqGetHandler(9) if handler9: c.Asm(f"""call {c.AsmInp(handler9, t.ASM_DESCR.REG_ANY)}""", op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RAX, t.ASM_DESCR.CLOBBER_RCX, t.ASM_DESCR.CLOBBER_RDX, t.ASM_DESCR.CLOBBER_R8, t.ASM_DESCR.CLOBBER_R9, t.ASM_DESCR.CLOBBER_R10, t.ASM_DESCR.CLOBBER_R11]) pic.eoi(9) def isr42_handler() -> t.CExport | t.CVoid: handler10: irq_handler_t = irqGetHandler(10) if handler10: c.Asm(f"""call {c.AsmInp(handler10, t.ASM_DESCR.REG_ANY)}""", op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RAX, t.ASM_DESCR.CLOBBER_RCX, t.ASM_DESCR.CLOBBER_RDX, t.ASM_DESCR.CLOBBER_R8, t.ASM_DESCR.CLOBBER_R9, t.ASM_DESCR.CLOBBER_R10, t.ASM_DESCR.CLOBBER_R11]) pic.eoi(10) def isr43_handler() -> t.CExport | t.CVoid: handler11: irq_handler_t = irqGetHandler(11) if handler11: c.Asm(f"""call {c.AsmInp(handler11, t.ASM_DESCR.REG_ANY)}""", op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RAX, t.ASM_DESCR.CLOBBER_RCX, t.ASM_DESCR.CLOBBER_RDX, t.ASM_DESCR.CLOBBER_R8, t.ASM_DESCR.CLOBBER_R9, t.ASM_DESCR.CLOBBER_R10, t.ASM_DESCR.CLOBBER_R11]) pic.eoi(11) def isr44_handler() -> t.CExport | t.CVoid: handler: irq_handler_t = irqGetHandler(12) if handler: c.Asm(f"""call {c.AsmInp(handler, t.ASM_DESCR.REG_ANY)}""", op=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RAX, t.ASM_DESCR.CLOBBER_RCX, t.ASM_DESCR.CLOBBER_RDX, t.ASM_DESCR.CLOBBER_R8, t.ASM_DESCR.CLOBBER_R9, t.ASM_DESCR.CLOBBER_R10, t.ASM_DESCR.CLOBBER_R11]) pic.eoi(12) def isr45_handler() -> t.CExport | t.CVoid: pic.eoi(13) def isr46_handler() -> t.CExport | t.CVoid: pic.eoi(14) def isr47_handler() -> t.CExport | t.CVoid: if pic.isSpurious(15): return pic.eoi(15) def init_exceptions(): setGate(0, t.CUInt64T(isr0), CODE_SEG, 0x8E) setGate(1, t.CUInt64T(isr1), CODE_SEG, 0x8E) setGate(2, t.CUInt64T(isr2), CODE_SEG, 0x8E) setGate(3, t.CUInt64T(isr3), CODE_SEG, 0x8E) setGate(4, t.CUInt64T(isr4), CODE_SEG, 0x8E) setGate(5, t.CUInt64T(isr5), CODE_SEG, 0x8E) setGate(6, t.CUInt64T(isr6), CODE_SEG, 0x8E) setGate(7, t.CUInt64T(isr7), CODE_SEG, 0x8E) setGate(8, t.CUInt64T(isr8), CODE_SEG, 0x8E) setGate(9, t.CUInt64T(isr9), CODE_SEG, 0x8E) setGate(10, t.CUInt64T(isr10), CODE_SEG, 0x8E) setGate(11, t.CUInt64T(isr11), CODE_SEG, 0x8E) setGate(12, t.CUInt64T(isr12), CODE_SEG, 0x8E) setGate(13, t.CUInt64T(isr13), CODE_SEG, 0x8E) setGate(14, t.CUInt64T(isr14), CODE_SEG, 0x8E) setGate(15, t.CUInt64T(isr15), CODE_SEG, 0x8E) setGate(16, t.CUInt64T(isr16), CODE_SEG, 0x8E) setGate(17, t.CUInt64T(isr17), CODE_SEG, 0x8E) setGate(18, t.CUInt64T(isr18), CODE_SEG, 0x8E) setGate(19, t.CUInt64T(isr19), CODE_SEG, 0x8E) setGate(20, t.CUInt64T(isr20), CODE_SEG, 0x8E) setGate(21, t.CUInt64T(isr21), CODE_SEG, 0x8E) setGate(22, t.CUInt64T(isr22), CODE_SEG, 0x8E) setGate(23, t.CUInt64T(isr23), CODE_SEG, 0x8E) setGate(24, t.CUInt64T(isr24), CODE_SEG, 0x8E) setGate(25, t.CUInt64T(isr25), CODE_SEG, 0x8E) setGate(26, t.CUInt64T(isr26), CODE_SEG, 0x8E) setGate(27, t.CUInt64T(isr27), CODE_SEG, 0x8E) setGate(28, t.CUInt64T(isr28), CODE_SEG, 0x8E) setGate(29, t.CUInt64T(isr29), CODE_SEG, 0x8E) setGate(30, t.CUInt64T(isr30), CODE_SEG, 0x8E) setGate(31, t.CUInt64T(isr31), CODE_SEG, 0x8E) def init_irqs(): setGate(32, t.CUInt64T(isr32), CODE_SEG, 0x8E) setGate(33, t.CUInt64T(isr33), CODE_SEG, 0x8E) setGate(34, t.CUInt64T(isr34), CODE_SEG, 0x8E) setGate(35, t.CUInt64T(isr35), CODE_SEG, 0x8E) setGate(36, t.CUInt64T(isr36), CODE_SEG, 0x8E) setGate(37, t.CUInt64T(isr37), CODE_SEG, 0x8E) setGate(38, t.CUInt64T(isr38), CODE_SEG, 0x8E) setGate(39, t.CUInt64T(isr39), CODE_SEG, 0x8E) setGate(40, t.CUInt64T(isr40), CODE_SEG, 0x8E) setGate(41, t.CUInt64T(isr41), CODE_SEG, 0x8E) setGate(42, t.CUInt64T(isr42), CODE_SEG, 0x8E) setGate(43, t.CUInt64T(isr43), CODE_SEG, 0x8E) setGate(44, t.CUInt64T(isr44), CODE_SEG, 0x8E) setGate(45, t.CUInt64T(isr45), CODE_SEG, 0x8E) setGate(46, t.CUInt64T(isr46), CODE_SEG, 0x8E) setGate(47, t.CUInt64T(isr47), CODE_SEG, 0x8E) irq_handlers: t.CStatic | t.CArray[irq_handler_t, 16] = [None] def irqInstallHandler(irq: t.CInt, handler: irq_handler_t, name: str) -> t.CInt: global irq_handlers if irq < 0 or irq > 15: return -1 irq_handlers[irq] = handler return 0 def irqGetHandler(irq: t.CInt) -> 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, t.CUInt64T(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, t.CUInt64T(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 c.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=[t.ASM_DESCR.CLOBBER_MEMORY, t.ASM_DESCR.CLOBBER_RAX])