1 /* 2 * processor control and status functions 3 * 4 * Copyright (C) 2014, Red Hat Inc, Andrew Jones <drjones@redhat.com> 5 * 6 * This work is licensed under the terms of the GNU LGPL, version 2. 7 */ 8 #include <libcflat.h> 9 #include <asm/ptrace.h> 10 #include <asm/processor.h> 11 #include <asm/thread_info.h> 12 13 static const char *vector_names[] = { 14 "el1t_sync", 15 "el1t_irq", 16 "el1t_fiq", 17 "el1t_error", 18 "el1h_sync", 19 "el1h_irq", 20 "el1h_fiq", 21 "el1h_error", 22 "el0_sync_64", 23 "el0_irq_64", 24 "el0_fiq_64", 25 "el0_error_64", 26 "el0_sync_32", 27 "el0_irq_32", 28 "el0_fiq_32", 29 "el0_error_32", 30 }; 31 32 static const char *ec_names[EC_MAX] = { 33 [ESR_EL1_EC_UNKNOWN] = "UNKNOWN", 34 [ESR_EL1_EC_WFI] = "WFI", 35 [ESR_EL1_EC_CP15_32] = "CP15_32", 36 [ESR_EL1_EC_CP15_64] = "CP15_64", 37 [ESR_EL1_EC_CP14_MR] = "CP14_MR", 38 [ESR_EL1_EC_CP14_LS] = "CP14_LS", 39 [ESR_EL1_EC_FP_ASIMD] = "FP_ASMID", 40 [ESR_EL1_EC_CP10_ID] = "CP10_ID", 41 [ESR_EL1_EC_CP14_64] = "CP14_64", 42 [ESR_EL1_EC_ILL_ISS] = "ILL_ISS", 43 [ESR_EL1_EC_SVC32] = "SVC32", 44 [ESR_EL1_EC_SVC64] = "SVC64", 45 [ESR_EL1_EC_SYS64] = "SYS64", 46 [ESR_EL1_EC_SVE] = "SVE", 47 [ESR_EL1_EC_IABT_EL0] = "IABT_EL0", 48 [ESR_EL1_EC_IABT_EL1] = "IABT_EL1", 49 [ESR_EL1_EC_PC_ALIGN] = "PC_ALIGN", 50 [ESR_EL1_EC_DABT_EL0] = "DABT_EL0", 51 [ESR_EL1_EC_DABT_EL1] = "DABT_EL1", 52 [ESR_EL1_EC_SP_ALIGN] = "SP_ALIGN", 53 [ESR_EL1_EC_FP_EXC32] = "FP_EXC32", 54 [ESR_EL1_EC_FP_EXC64] = "FP_EXC64", 55 [ESR_EL1_EC_SERROR] = "SERROR", 56 [ESR_EL1_EC_BREAKPT_EL0] = "BREAKPT_EL0", 57 [ESR_EL1_EC_BREAKPT_EL1] = "BREAKPT_EL1", 58 [ESR_EL1_EC_SOFTSTP_EL0] = "SOFTSTP_EL0", 59 [ESR_EL1_EC_SOFTSTP_EL1] = "SOFTSTP_EL1", 60 [ESR_EL1_EC_WATCHPT_EL0] = "WATCHPT_EL0", 61 [ESR_EL1_EC_WATCHPT_EL1] = "WATCHPT_EL1", 62 [ESR_EL1_EC_BKPT32] = "BKPT32", 63 [ESR_EL1_EC_BRK64] = "BRK64", 64 }; 65 66 void show_regs(struct pt_regs *regs) 67 { 68 int i; 69 70 printf("pc : [<%016lx>] lr : [<%016lx>] pstate: %08lx\n", 71 regs->pc, regs->regs[30], regs->pstate); 72 printf("sp : %016lx\n", regs->sp); 73 74 for (i = 29; i >= 0; --i) { 75 printf("x%-2d: %016lx ", i, regs->regs[i]); 76 if (i % 2 == 0) 77 printf("\n"); 78 } 79 printf("\n"); 80 } 81 82 bool get_far(unsigned int esr, unsigned long *far) 83 { 84 unsigned int ec = esr >> ESR_EL1_EC_SHIFT; 85 86 asm volatile("mrs %0, far_el1": "=r" (*far)); 87 88 switch (ec) { 89 case ESR_EL1_EC_IABT_EL0: 90 case ESR_EL1_EC_IABT_EL1: 91 case ESR_EL1_EC_PC_ALIGN: 92 case ESR_EL1_EC_DABT_EL0: 93 case ESR_EL1_EC_DABT_EL1: 94 case ESR_EL1_EC_WATCHPT_EL0: 95 case ESR_EL1_EC_WATCHPT_EL1: 96 if ((esr & 0x3f /* DFSC */) != 0x10 97 || !(esr & 0x400 /* FnV */)) 98 return true; 99 } 100 return false; 101 } 102 103 extern unsigned long _text; 104 105 static void bad_exception(enum vector v, struct pt_regs *regs, 106 unsigned int esr, bool esr_valid, bool bad_vector) 107 { 108 unsigned long far; 109 bool far_valid = get_far(esr, &far); 110 unsigned int ec = esr >> ESR_EL1_EC_SHIFT; 111 uintptr_t text = (uintptr_t)&_text; 112 113 printf("Load address: %" PRIxPTR "\n", text); 114 printf("PC: %" PRIxPTR " PC offset: %" PRIxPTR "\n", 115 (uintptr_t)regs->pc, (uintptr_t)regs->pc - text); 116 117 if (bad_vector) { 118 if (v < VECTOR_MAX) 119 printf("Unhandled vector %d (%s)\n", v, 120 vector_names[v]); 121 else 122 printf("Got bad vector=%d\n", v); 123 } else if (esr_valid) { 124 if (ec_names[ec]) 125 printf("Unhandled exception ec=%#x (%s)\n", ec, 126 ec_names[ec]); 127 else 128 printf("Got bad ec=%#x\n", ec); 129 } 130 131 printf("Vector: %d (%s)\n", v, vector_names[v]); 132 printf("ESR_EL1: %8s%08x, ec=%#x (%s)\n", "", esr, ec, ec_names[ec]); 133 printf("FAR_EL1: %016lx (%svalid)\n", far, far_valid ? "" : "not "); 134 printf("Exception frame registers:\n"); 135 show_regs(regs); 136 dump_frame_stack((void *)regs->pc, (void *)regs->regs[29]); 137 abort(); 138 } 139 140 void install_exception_handler(enum vector v, unsigned int ec, exception_fn fn) 141 { 142 struct thread_info *ti = current_thread_info(); 143 144 if (v < VECTOR_MAX && ec < EC_MAX) 145 ti->exception_handlers[v][ec] = fn; 146 } 147 148 void install_irq_handler(enum vector v, irq_handler_fn fn) 149 { 150 struct thread_info *ti = current_thread_info(); 151 152 if (v < VECTOR_MAX) 153 ti->exception_handlers[v][0] = (exception_fn)fn; 154 } 155 156 void default_vector_sync_handler(enum vector v, struct pt_regs *regs, 157 unsigned int esr) 158 { 159 struct thread_info *ti = thread_info_sp(regs->sp); 160 unsigned int ec = esr >> ESR_EL1_EC_SHIFT; 161 162 if (ti->flags & TIF_USER_MODE) { 163 if (ec < EC_MAX && ti->exception_handlers[v][ec]) { 164 ti->exception_handlers[v][ec](regs, esr); 165 return; 166 } 167 ti = current_thread_info(); 168 } 169 170 if (ec < EC_MAX && ti->exception_handlers[v][ec]) 171 ti->exception_handlers[v][ec](regs, esr); 172 else 173 bad_exception(v, regs, esr, true, false); 174 } 175 176 void default_vector_irq_handler(enum vector v, struct pt_regs *regs, 177 unsigned int esr) 178 { 179 struct thread_info *ti = thread_info_sp(regs->sp); 180 irq_handler_fn irq_handler = 181 (irq_handler_fn)ti->exception_handlers[v][0]; 182 183 if (ti->flags & TIF_USER_MODE) { 184 if (irq_handler) { 185 irq_handler(regs); 186 return; 187 } 188 ti = current_thread_info(); 189 irq_handler = (irq_handler_fn)ti->exception_handlers[v][0]; 190 } 191 192 if (irq_handler) 193 irq_handler(regs); 194 else 195 bad_exception(v, regs, esr, false, false); 196 } 197 198 void vector_handlers_default_init(vector_fn *handlers) 199 { 200 handlers[EL1H_SYNC] = default_vector_sync_handler; 201 handlers[EL1H_IRQ] = default_vector_irq_handler; 202 handlers[EL0_SYNC_64] = default_vector_sync_handler; 203 handlers[EL0_IRQ_64] = default_vector_irq_handler; 204 } 205 206 /* Needed to compile with -Wmissing-prototypes */ 207 void do_handle_exception(enum vector v, struct pt_regs *regs, unsigned int esr); 208 209 void do_handle_exception(enum vector v, struct pt_regs *regs, unsigned int esr) 210 { 211 struct thread_info *ti = thread_info_sp(regs->sp); 212 213 if (ti->flags & TIF_USER_MODE) { 214 if (v < VECTOR_MAX && ti->vector_handlers[v]) { 215 ti->vector_handlers[v](v, regs, esr); 216 return; 217 } 218 ti = current_thread_info(); 219 } 220 221 if (v < VECTOR_MAX && ti->vector_handlers[v]) 222 ti->vector_handlers[v](v, regs, esr); 223 else 224 bad_exception(v, regs, esr, true, true); 225 } 226 227 void install_vector_handler(enum vector v, vector_fn fn) 228 { 229 struct thread_info *ti = current_thread_info(); 230 231 if (v < VECTOR_MAX) 232 ti->vector_handlers[v] = fn; 233 } 234 235 static void __thread_info_init(struct thread_info *ti, unsigned int flags) 236 { 237 memset(ti, 0, sizeof(struct thread_info)); 238 ti->cpu = mpidr_to_cpu(get_mpidr()); 239 ti->flags = flags; 240 } 241 242 void thread_info_init(struct thread_info *ti, unsigned int flags) 243 { 244 __thread_info_init(ti, flags); 245 vector_handlers_default_init(ti->vector_handlers); 246 } 247 248 void start_usr(void (*func)(void *arg), void *arg, unsigned long sp_usr) 249 { 250 sp_usr &= (~15UL); /* stack ptr needs 16-byte alignment */ 251 252 __thread_info_init(thread_info_sp(sp_usr), TIF_USER_MODE); 253 thread_info_sp(sp_usr)->pgtable = current_thread_info()->pgtable; 254 255 asm volatile( 256 "mov x0, %0\n" 257 "msr sp_el0, %1\n" 258 "msr elr_el1, %2\n" 259 "mov x3, xzr\n" /* clear and "set" PSR_MODE_EL0t */ 260 "msr spsr_el1, x3\n" 261 "eret\n" 262 :: "r" (arg), "r" (sp_usr), "r" (func) : "x0", "x3"); 263 } 264 265 bool is_user(void) 266 { 267 return current_thread_info()->flags & TIF_USER_MODE; 268 } 269 270 bool __mmu_enabled(void) 271 { 272 return read_sysreg(sctlr_el1) & SCTLR_EL1_M; 273 } 274