github.com/icexin/eggos@v0.4.2-0.20220216025428-78b167e4f349/kernel/trap.go (about) 1 package kernel 2 3 import ( 4 "unsafe" 5 6 "github.com/icexin/eggos/drivers/pic" 7 "github.com/icexin/eggos/kernel/isyscall" 8 "github.com/icexin/eggos/kernel/sys" 9 "github.com/icexin/eggos/kernel/trap" 10 "github.com/icexin/eggos/log" 11 ) 12 13 var ( 14 trapnum = [...]string{ 15 "#DE(0) Divide by zero", 16 "#DB(1) Debug exception", 17 "#NMI(2) Non maskable interrupt exception", 18 "#BP(3) Breakpoint exception", 19 "#OF(4) Overflow exception", 20 "#BR(5) Bound range exception", 21 "#UD(6) Invalid opcode exception", 22 "#NM(7) Device not avaiable exception", 23 "#DF(8) Double fault exception", 24 "(9)Coprocessor segment overrun exception", 25 "#TS(10) Invalid TSS exception", 26 "#NP(11) Segment not present exception", 27 "#SS(12) Stack exception", 28 "#GP(13) General protection exception", 29 "#PF(14) Page fault exception", 30 "#MF(15) x87 floating point exception", 31 "#AC(16) Alignment check exception", 32 "#MC(17) Machine check exception", 33 "#XF(18) SIMD floating point exception", 34 "#HV(19) Hypervisor injection exception", 35 "#VC(20) VMM communication exception", 36 "#SX(21) Security Exception", 37 } 38 ) 39 40 //go:notinheap 41 type trapFrame struct { 42 AX, BX, CX, DX uintptr 43 BP, SI, DI, R8 uintptr 44 R9, R10, R11, R12 uintptr 45 R13, R14, R15 uintptr 46 47 Trapno, Err uintptr 48 49 // pushed by hardware 50 IP, CS, FLAGS, SP, SS uintptr 51 } 52 53 func (t *trapFrame) SyscallRequest() isyscall.Request { 54 return isyscall.NewRequest(uintptr(unsafe.Pointer(t))) 55 } 56 57 //go:nosplit 58 func trapret() 59 60 //go:nosplit 61 func trapPanic() { 62 tf := Mythread().tf 63 log.PrintStr("trap panic: ") 64 if tf.Trapno < uintptr(len(trapnum)) { 65 log.PrintStr(trapnum[tf.Trapno]) 66 } 67 log.PrintStr("\n") 68 throwtf(tf, "stack trace:") 69 } 70 71 //go:nosplit 72 func pageFaultPanic() { 73 panic("nil pointer or invalid memory access") 74 } 75 76 //go:nosplit 77 func ignoreHandler() { 78 } 79 80 //go:nosplit 81 func pageFaultHandler() { 82 t := Mythread() 83 checkKernelPanic(t) 84 changeReturnPC(t.tf, sys.FuncPC(pageFaultPanic)) 85 } 86 87 //go:nosplit 88 func faultHandler() { 89 trapPanic() 90 } 91 92 //go:nosplit 93 func printReg(name string, reg uintptr) { 94 log.PrintStr(name) 95 log.PrintStr("=") 96 log.PrintHex(reg) 97 log.PrintStr("\n") 98 } 99 100 //go:nosplit 101 func checkKernelPanic(t *Thread) { 102 tf := t.tf 103 if tf.CS != _KCODE_IDX<<3 { 104 return 105 } 106 printReg("tid", uintptr(t.id)) 107 printReg("no", tf.Trapno) 108 printReg("err", tf.Err) 109 printReg("cr2", sys.Cr2()) 110 printReg("ip", tf.IP) 111 printReg("sp", tf.SP) 112 printReg("ax", tf.AX) 113 printReg("bx", tf.BX) 114 printReg("cx", tf.CX) 115 printReg("dx", tf.CX) 116 printReg("cs", tf.CS) 117 throw("trap fault in kernel\n") 118 } 119 120 //go:nosplit 121 func preparePanic(tf *trapFrame) { 122 changeReturnPC(tf, sys.FuncPC(trapPanic)) 123 } 124 125 // ChangeReturnPC change the return pc of a trap 126 // must be called in trap handler 127 //go:nosplit 128 func changeReturnPC(tf *trapFrame, pc uintptr) { 129 // tf.Err, tf.IP, tf.CS, tf.FLAGS = pc, tf.CS, tf.FLAGS, tf.IP 130 sp := tf.SP 131 sp -= sys.PtrSize 132 *(*uintptr)(unsafe.Pointer(sp)) = tf.IP 133 tf.SP = sp 134 tf.IP = pc 135 } 136 137 //go:nosplit 138 func dotrap(tf *trapFrame) { 139 if sys.Flags()&_FLAGS_IF != 0 { 140 throw("IF should clear") 141 } 142 my := Mythread() 143 // ugly as it is, avoid writeBarrier 144 // my.tf = tf 145 *(*uintptr)(unsafe.Pointer(&my.tf)) = uintptr(unsafe.Pointer(tf)) 146 147 handler := trap.Handler(int(tf.Trapno)) 148 if handler == nil { 149 faultHandler() 150 return 151 } 152 // timer and syscall interrupts are processed synchronously 153 if tf.Trapno > 32 && tf.Trapno != 0x80 { 154 // pci using level trigger irq, cause dead lock on trap handler 155 // FIXME: hard code network irq line 156 if tf.Trapno == 43 { 157 pic.DisableIRQ(43 - pic.IRQ_BASE) 158 } 159 wakeIRQ(tf.Trapno) 160 return 161 } 162 handler() 163 } 164 165 //go:nosplit 166 func trapInit() { 167 trap.Register(14, pageFaultHandler) 168 trap.Register(39, ignoreHandler) 169 trap.Register(47, ignoreHandler) 170 }