github.com/f-secure-foundry/tamago@v0.0.0-20220307101044-d73fcdd7f11b/arm/exception.go (about) 1 // ARM processor support 2 // https://github.com/f-secure-foundry/tamago 3 // 4 // Copyright (c) F-Secure Corporation 5 // https://foundry.f-secure.com 6 // 7 // Use of this source code is governed by the license 8 // that can be found in the LICENSE file. 9 10 package arm 11 12 import ( 13 "runtime" 14 "unsafe" 15 16 "github.com/f-secure-foundry/tamago/internal/reg" 17 ) 18 19 // ARM exception vector offsets 20 // (Table 11-1, ARM® Cortex™ -A Series Programmer’s Guide). 21 const ( 22 RESET = 0x00 23 UNDEFINED = 0x04 24 SUPERVISOR = 0x08 25 PREFETCH_ABORT = 0x0c 26 DATA_ABORT = 0x10 27 IRQ = 0x18 28 FIQ = 0x1c 29 ) 30 31 const ( 32 vecTableJump uint32 = 0xe59ff018 // ldr pc, [pc, #24] 33 34 vecTableOffset = 0 35 vecTableSize = 0x4000 // 16 kB 36 37 excStackOffset = 0x8000 // 32 kB 38 excStackSize = 0x4000 // 16 kB 39 ) 40 41 // defined in exception.s 42 func set_exc_stack(addr uint32) 43 func set_vbar(addr uint32) 44 func set_mvbar(addr uint32) 45 func resetHandler() 46 func undefinedHandler() 47 func supervisorHandler() 48 func prefetchAbortHandler() 49 func dataAbortHandler() 50 func irqHandler() 51 func fiqHandler() 52 func nullHandler() 53 54 type ExceptionHandler func() 55 56 func vector(fn ExceptionHandler) uint32 { 57 return **((**uint32)(unsafe.Pointer(&fn))) 58 } 59 60 type VectorTable struct { 61 Reset ExceptionHandler 62 Undefined ExceptionHandler 63 Supervisor ExceptionHandler 64 PrefetchAbort ExceptionHandler 65 DataAbort ExceptionHandler 66 IRQ ExceptionHandler 67 FIQ ExceptionHandler 68 } 69 70 // DefaultExceptionHandler handles an exception by printing its vector and 71 // processor mode before panicking. 72 func DefaultExceptionHandler(off int) { 73 print("exception: vector ", off, " mode ", int(read_cpsr()&0x1f), "\n") 74 panic("unhandled exception") 75 } 76 77 // SystemExceptionHandler allows to override the default exception handler 78 // executed at any exception by the table returned by SystemVectorTable(), 79 // which is used by default when initializing the CPU instance (e.g. 80 // CPU.Init()). 81 var SystemExceptionHandler = DefaultExceptionHandler 82 83 func systemException(off int) { 84 SystemExceptionHandler(off) 85 } 86 87 // SystemVectorTable returns a vector table that, for all exceptions, switches 88 // to system mode and calls the SystemExceptionHandler on the Go runtime stack 89 // within goroutine g0. 90 func SystemVectorTable() VectorTable { 91 return VectorTable{ 92 Reset: resetHandler, 93 Undefined: undefinedHandler, 94 Supervisor: supervisorHandler, 95 PrefetchAbort: prefetchAbortHandler, 96 DataAbort: dataAbortHandler, 97 IRQ: irqHandler, 98 FIQ: fiqHandler, 99 } 100 } 101 102 // VectorName returns the exception vector offset name. 103 func VectorName(off int) string { 104 switch off { 105 case RESET: 106 return "RESET" 107 case UNDEFINED: 108 return "UNDEFINED" 109 case SUPERVISOR: 110 return "SUPERVISOR" 111 case PREFETCH_ABORT: 112 return "PREFETCH_ABORT" 113 case DATA_ABORT: 114 return "DATA_ABORT" 115 case IRQ: 116 return "IRQ" 117 case FIQ: 118 return "FIQ" 119 } 120 121 return "Unknown" 122 } 123 124 // SetVectorTable updates the CPU exception handling vector table with the 125 // addresses of the functions defined in the passed structure. 126 func SetVectorTable(t VectorTable) { 127 ramStart, _ := runtime.MemRegion() 128 vecTable := ramStart + vecTableOffset + 8*4 129 130 // set handler pointers 131 // Table 11-1 ARM® Cortex™ -A Series Programmer’s Guide 132 133 reg.Write(vecTable+RESET, vector(t.Reset)) 134 reg.Write(vecTable+UNDEFINED, vector(t.Undefined)) 135 reg.Write(vecTable+SUPERVISOR, vector(t.Supervisor)) 136 reg.Write(vecTable+PREFETCH_ABORT, vector(t.PrefetchAbort)) 137 reg.Write(vecTable+DATA_ABORT, vector(t.DataAbort)) 138 reg.Write(vecTable+IRQ, vector(t.IRQ)) 139 reg.Write(vecTable+FIQ, vector(t.FIQ)) 140 } 141 142 //go:nosplit 143 func (cpu *CPU) initVectorTable() { 144 ramStart, _ := runtime.MemRegion() 145 vecTableStart := ramStart + vecTableOffset 146 147 // initialize jump table 148 // Table 11-1 ARM® Cortex™ -A Series Programmer’s Guide 149 for i := uint32(0); i < 8; i++ { 150 reg.Write(vecTableStart+4*i, vecTableJump) 151 } 152 153 // set exception handlers 154 SetVectorTable(SystemVectorTable()) 155 156 // set vector base address register 157 set_vbar(vecTableStart) 158 159 if cpu.Secure() { 160 // set monitor vector base address register 161 set_mvbar(vecTableStart) 162 } 163 164 // Set the stack pointer for exception modes to provide a stack when 165 // summoned by exception vectors. 166 excStackStart := ramStart + excStackOffset 167 set_exc_stack(excStackStart + excStackSize) 168 }