1 /* $OpenBSD: trap.c,v 1.50 2024/11/10 06:51:59 jsg Exp $ */ 2 /*- 3 * Copyright (c) 2014 Andrew Turner 4 * All rights reserved. 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 */ 27 28 #include <sys/param.h> 29 #include <sys/systm.h> 30 #include <sys/kernel.h> 31 #include <sys/lock.h> 32 #include <sys/mutex.h> 33 #include <sys/proc.h> 34 #include <sys/ptrace.h> 35 #include <sys/syscall.h> 36 #include <sys/signalvar.h> 37 #include <sys/user.h> 38 39 #include <uvm/uvm_extern.h> 40 41 #include <machine/cpu.h> 42 #include <machine/fpu.h> 43 #include <machine/frame.h> 44 #include <machine/pcb.h> 45 #include <machine/vmparam.h> 46 47 #ifdef DDB 48 #include <ddb/db_output.h> 49 #endif 50 51 /* Called from exception.S */ 52 void do_el1h_sync(struct trapframe *); 53 void do_el0_sync(struct trapframe *); 54 void do_el0_error(struct trapframe *); 55 56 void dumpregs(struct trapframe*); 57 58 /* Check whether we're executing an unprivileged load/store instruction. */ 59 static inline int 60 is_unpriv_ldst(uint64_t elr) 61 { 62 uint32_t insn = *(uint32_t *)elr; 63 return ((insn & 0x3f200c00) == 0x38000800); 64 } 65 66 static inline int 67 accesstype(uint64_t esr, int exe) 68 { 69 if (exe) 70 return PROT_EXEC; 71 return (!(esr & ISS_DATA_CM) && (esr & ISS_DATA_WnR)) ? 72 PROT_WRITE : PROT_READ; 73 } 74 75 static void 76 udata_abort(struct trapframe *frame, uint64_t esr, uint64_t far, int exe) 77 { 78 struct vm_map *map; 79 struct proc *p; 80 struct pcb *pcb; 81 vm_prot_t access_type = accesstype(esr, exe); 82 vaddr_t va; 83 union sigval sv; 84 int error = 0, sig, code; 85 86 pcb = curcpu()->ci_curpcb; 87 p = curcpu()->ci_curproc; 88 89 va = trunc_page(far); 90 if (va >= VM_MAXUSER_ADDRESS) 91 curcpu()->ci_flush_bp(); 92 93 switch (esr & ISS_DATA_DFSC_MASK) { 94 case ISS_DATA_DFSC_ALIGN: 95 sv.sival_ptr = (void *)far; 96 trapsignal(p, SIGBUS, esr, BUS_ADRALN, sv); 97 return; 98 default: 99 break; 100 } 101 102 map = &p->p_vmspace->vm_map; 103 104 if (!uvm_map_inentry(p, &p->p_spinentry, PROC_STACK(p), 105 "[%s]%d/%d sp=%lx inside %lx-%lx: not MAP_STACK\n", 106 uvm_map_inentry_sp, p->p_vmspace->vm_map.sserial)) 107 return; 108 109 /* Handle referenced/modified emulation */ 110 if (pmap_fault_fixup(map->pmap, va, access_type)) 111 return; 112 113 error = uvm_fault(map, va, 0, access_type); 114 115 if (error == 0) { 116 uvm_grow(p, va); 117 return; 118 } 119 120 if (error == ENOMEM) { 121 sig = SIGKILL; 122 code = 0; 123 } else if (error == EIO) { 124 sig = SIGBUS; 125 code = BUS_OBJERR; 126 } else if (error == EACCES) { 127 sig = SIGSEGV; 128 code = SEGV_ACCERR; 129 } else { 130 sig = SIGSEGV; 131 code = SEGV_MAPERR; 132 } 133 sv.sival_ptr = (void *)far; 134 trapsignal(p, sig, esr, code, sv); 135 } 136 137 static void 138 kdata_abort(struct trapframe *frame, uint64_t esr, uint64_t far, int exe) 139 { 140 struct vm_map *map; 141 struct proc *p; 142 struct pcb *pcb; 143 vm_prot_t access_type = accesstype(esr, exe); 144 vaddr_t va; 145 int error = 0; 146 147 pcb = curcpu()->ci_curpcb; 148 p = curcpu()->ci_curproc; 149 150 va = trunc_page(far); 151 152 /* The top bit tells us which range to use */ 153 if ((far >> 63) == 1) 154 map = kernel_map; 155 else { 156 /* 157 * Only allow user-space access using 158 * unprivileged load/store instructions. 159 */ 160 if (is_unpriv_ldst(frame->tf_elr)) 161 map = &p->p_vmspace->vm_map; 162 else if (pcb->pcb_onfault != NULL) 163 map = kernel_map; 164 else { 165 panic("attempt to access user address" 166 " 0x%llx from EL1", far); 167 } 168 } 169 170 /* Handle referenced/modified emulation */ 171 if (!pmap_fault_fixup(map->pmap, va, access_type)) { 172 error = uvm_fault(map, va, 0, access_type); 173 174 if (error == 0 && map != kernel_map) 175 uvm_grow(p, va); 176 } 177 178 if (error != 0) { 179 if (curcpu()->ci_idepth == 0 && 180 pcb->pcb_onfault != NULL) { 181 frame->tf_elr = (register_t)pcb->pcb_onfault; 182 return; 183 } 184 panic("uvm_fault failed: %lx esr %llx far %llx", 185 frame->tf_elr, esr, far); 186 } 187 } 188 189 static int 190 emulate_msr(struct trapframe *frame, uint64_t esr) 191 { 192 u_int rt = ISS_MSR_Rt(esr); 193 uint64_t val; 194 195 /* Only emulate reads. */ 196 if ((esr & ISS_MSR_DIR) == 0) 197 return 0; 198 199 /* Only emulate non-debug System register access. */ 200 if (ISS_MSR_OP0(esr) != 3 || ISS_MSR_OP1(esr) != 0 || 201 ISS_MSR_CRn(esr) != 0) 202 return 0; 203 204 switch (ISS_MSR_CRm(esr)) { 205 case 0: 206 switch (ISS_MSR_OP2(esr)) { 207 case 0: /* MIDR_EL1 */ 208 val = READ_SPECIALREG(midr_el1); 209 break; 210 case 5: /* MPIDR_EL1 */ 211 /* 212 * Don't reveal the topology to userland. But 213 * return a valid value; Bit 31 is RES1. 214 */ 215 val = 0x80000000; 216 break; 217 case 6: /* REVIDR_EL1 */ 218 val = 0; 219 break; 220 default: 221 return 0; 222 } 223 break; 224 case 4: 225 switch (ISS_MSR_OP2(esr)) { 226 case 0: /* ID_AA64PFR0_EL1 */ 227 val = cpu_id_aa64pfr0; 228 break; 229 case 1: /* ID_AA64PFR1_EL1 */ 230 val = cpu_id_aa64pfr1; 231 break; 232 case 2: /* ID_AA64PFR2_EL1 */ 233 case 4: /* ID_AA64ZFR0_EL1 */ 234 case 5: /* ID_AA64SMFR0_EL1 */ 235 val = 0; 236 break; 237 default: 238 return 0; 239 } 240 break; 241 case 6: 242 switch (ISS_MSR_OP2(esr)) { 243 case 0: /* ID_AA64ISAR0_EL1 */ 244 val = cpu_id_aa64isar0; 245 break; 246 case 1: /* ID_AA64ISAR1_EL1 */ 247 val = cpu_id_aa64isar1; 248 break; 249 case 2: /* ID_AA64ISAR2_EL2 */ 250 val = cpu_id_aa64isar2; 251 break; 252 default: 253 return 0; 254 } 255 break; 256 case 7: 257 switch (ISS_MSR_OP2(esr)) { 258 case 0: /* ID_AA64MMFR0_EL1 */ 259 case 1: /* ID_AA64MMFR1_EL1 */ 260 case 2: /* ID_AA64MMFR2_EL1 */ 261 case 3: /* ID_AA64MMFR3_EL1 */ 262 case 4: /* ID_AA64MMFR4_EL1 */ 263 val = 0; 264 break; 265 default: 266 return 0; 267 } 268 break; 269 default: 270 return 0; 271 } 272 273 if (rt < 30) 274 frame->tf_x[rt] = val; 275 else if (rt == 30) 276 frame->tf_lr = val; 277 frame->tf_elr += 4; 278 279 return 1; 280 } 281 282 void 283 do_el1h_sync(struct trapframe *frame) 284 { 285 uint32_t exception; 286 uint64_t esr, far; 287 288 /* Read the esr register to get the exception details */ 289 esr = READ_SPECIALREG(esr_el1); 290 exception = ESR_ELx_EXCEPTION(esr); 291 far = READ_SPECIALREG(far_el1); 292 293 intr_enable(); 294 295 /* 296 * Sanity check we are in an exception er can handle. The IL bit 297 * is used to indicate the instruction length, except in a few 298 * exceptions described in the ARMv8 ARM. 299 * 300 * It is unclear in some cases if the bit is implementation defined. 301 * The Foundation Model and QEMU disagree on if the IL bit should 302 * be set when we are in a data fault from the same EL and the ISV 303 * bit (bit 24) is also set. 304 */ 305 // KASSERT((esr & ESR_ELx_IL) == ESR_ELx_IL || 306 // (exception == EXCP_DATA_ABORT && ((esr & ISS_DATA_ISV) == 0)), 307 // ("Invalid instruction length in exception")); 308 309 switch(exception) { 310 case EXCP_FP_SIMD: 311 case EXCP_TRAP_FP: 312 panic("FP exception in the kernel"); 313 case EXCP_BRANCH_TGT: 314 panic("Branch target exception in the kernel"); 315 case EXCP_FPAC: 316 panic("Faulting PAC trap in kernel"); 317 case EXCP_INSN_ABORT: 318 kdata_abort(frame, esr, far, 1); 319 break; 320 case EXCP_DATA_ABORT: 321 kdata_abort(frame, esr, far, 0); 322 break; 323 case EXCP_BRK: 324 case EXCP_WATCHPT_EL1: 325 case EXCP_SOFTSTP_EL1: 326 #ifdef DDB 327 { 328 /* XXX */ 329 int db_trapper (u_int, u_int, trapframe_t *, int); 330 db_trapper(frame->tf_elr, 0/*XXX*/, frame, exception); 331 } 332 #else 333 panic("No debugger in kernel."); 334 #endif 335 break; 336 default: 337 #ifdef DDB 338 { 339 /* XXX */ 340 int db_trapper (u_int, u_int, trapframe_t *, int); 341 db_trapper(frame->tf_elr, 0/*XXX*/, frame, exception); 342 break; 343 } 344 #endif 345 panic("Unknown kernel exception %x esr_el1 %llx lr %lxpc %lx", 346 exception, 347 esr, frame->tf_lr, frame->tf_elr); 348 } 349 } 350 351 void 352 do_el0_sync(struct trapframe *frame) 353 { 354 struct proc *p = curproc; 355 union sigval sv; 356 uint32_t exception; 357 uint64_t esr, far; 358 359 esr = READ_SPECIALREG(esr_el1); 360 exception = ESR_ELx_EXCEPTION(esr); 361 far = READ_SPECIALREG(far_el1); 362 363 intr_enable(); 364 365 p->p_addr->u_pcb.pcb_tf = frame; 366 refreshcreds(p); 367 368 switch (exception) { 369 case EXCP_UNKNOWN: 370 curcpu()->ci_flush_bp(); 371 sv.sival_ptr = (void *)frame->tf_elr; 372 trapsignal(p, SIGILL, esr, ILL_ILLOPC, sv); 373 break; 374 case EXCP_FP_SIMD: 375 case EXCP_TRAP_FP: 376 fpu_load(p); 377 break; 378 case EXCP_BRANCH_TGT: 379 curcpu()->ci_flush_bp(); 380 sv.sival_ptr = (void *)frame->tf_elr; 381 trapsignal(p, SIGILL, esr, ILL_BTCFI, sv); 382 break; 383 case EXCP_MSR: 384 if (emulate_msr(frame, esr)) 385 break; 386 /* FALLTHROUGH */ 387 case EXCP_FPAC: 388 curcpu()->ci_flush_bp(); 389 sv.sival_ptr = (void *)frame->tf_elr; 390 trapsignal(p, SIGILL, esr, ILL_ILLOPC, sv); 391 break; 392 case EXCP_SVC: 393 svc_handler(frame); 394 break; 395 case EXCP_INSN_ABORT_L: 396 udata_abort(frame, esr, far, 1); 397 break; 398 case EXCP_PC_ALIGN: 399 curcpu()->ci_flush_bp(); 400 sv.sival_ptr = (void *)frame->tf_elr; 401 trapsignal(p, SIGBUS, esr, BUS_ADRALN, sv); 402 break; 403 case EXCP_SP_ALIGN: 404 curcpu()->ci_flush_bp(); 405 sv.sival_ptr = (void *)frame->tf_sp; 406 trapsignal(p, SIGBUS, esr, BUS_ADRALN, sv); 407 break; 408 case EXCP_DATA_ABORT_L: 409 udata_abort(frame, esr, far, 0); 410 break; 411 case EXCP_BRK: 412 sv.sival_ptr = (void *)frame->tf_elr; 413 trapsignal(p, SIGTRAP, esr, TRAP_BRKPT, sv); 414 break; 415 case EXCP_SOFTSTP_EL0: 416 sv.sival_ptr = (void *)frame->tf_elr; 417 trapsignal(p, SIGTRAP, esr, TRAP_TRACE, sv); 418 break; 419 default: 420 // panic("Unknown userland exception %x esr_el1 %lx", exception, 421 // esr); 422 // USERLAND MUST NOT PANIC MACHINE 423 { 424 // only here to debug !?!? 425 printf("exception %x esr_el1 %llx\n", exception, esr); 426 dumpregs(frame); 427 } 428 curcpu()->ci_flush_bp(); 429 KERNEL_LOCK(); 430 sigexit(p, SIGILL); 431 KERNEL_UNLOCK(); 432 } 433 434 userret(p); 435 } 436 437 static void 438 serror(struct trapframe *frame) 439 { 440 struct cpu_info *ci = curcpu(); 441 uint64_t esr, far; 442 443 esr = READ_SPECIALREG(esr_el1); 444 far = READ_SPECIALREG(far_el1); 445 446 printf("SError: %lx esr %llx far %0llx\n", 447 frame->tf_elr, esr, far); 448 449 if (ci->ci_serror) 450 ci->ci_serror(); 451 } 452 453 void 454 do_el0_error(struct trapframe *frame) 455 { 456 serror(frame); 457 panic("do_el0_error"); 458 } 459 460 void 461 do_el1h_error(struct trapframe *frame) 462 { 463 serror(frame); 464 panic("do_el1h_error"); 465 } 466 467 void 468 dumpregs(struct trapframe *frame) 469 { 470 int i; 471 472 for (i = 0; i < 30; i += 2) { 473 printf("x%02d: 0x%016lx 0x%016lx\n", 474 i, frame->tf_x[i], frame->tf_x[i+1]); 475 } 476 printf("sp: 0x%016lx\n", frame->tf_sp); 477 printf("lr: 0x%016lx\n", frame->tf_lr); 478 printf("pc: 0x%016lx\n", frame->tf_elr); 479 printf("spsr: 0x%016lx\n", frame->tf_spsr); 480 } 481