| 358 | } |
| 359 | |
| 360 | void |
| 361 | do_el1h_sync(struct thread *td, struct trapframe *frame) |
| 362 | { |
| 363 | uint32_t exception; |
| 364 | uint64_t esr, far; |
| 365 | int dfsc; |
| 366 | |
| 367 | /* Read the esr register to get the exception details */ |
| 368 | esr = frame->tf_esr; |
| 369 | exception = ESR_ELx_EXCEPTION(esr); |
| 370 | |
| 371 | #ifdef KDTRACE_HOOKS |
| 372 | if (dtrace_trap_func != NULL && (*dtrace_trap_func)(frame, exception)) |
| 373 | return; |
| 374 | #endif |
| 375 | |
| 376 | CTR4(KTR_TRAP, |
| 377 | "do_el1_sync: curthread: %p, esr %lx, elr: %lx, frame: %p", td, |
| 378 | esr, frame->tf_elr, frame); |
| 379 | |
| 380 | switch (exception) { |
| 381 | case EXCP_FP_SIMD: |
| 382 | case EXCP_TRAP_FP: |
| 383 | #ifdef VFP |
| 384 | if ((td->td_pcb->pcb_fpflags & PCB_FP_KERN) != 0) { |
| 385 | vfp_restore_state(); |
| 386 | } else |
| 387 | #endif |
| 388 | { |
| 389 | print_registers(frame); |
| 390 | printf(" esr: %.8lx\n", esr); |
| 391 | panic("VFP exception in the kernel"); |
| 392 | } |
| 393 | break; |
| 394 | case EXCP_INSN_ABORT: |
| 395 | case EXCP_DATA_ABORT: |
| 396 | far = READ_SPECIALREG(far_el1); |
| 397 | dfsc = esr & ISS_DATA_DFSC_MASK; |
| 398 | if (dfsc < nitems(abort_handlers) && |
| 399 | abort_handlers[dfsc] != NULL) { |
| 400 | abort_handlers[dfsc](td, frame, esr, far, 0); |
| 401 | } else { |
| 402 | print_registers(frame); |
| 403 | printf(" far: %16lx\n", far); |
| 404 | printf(" esr: %.8lx\n", esr); |
| 405 | panic("Unhandled EL1 %s abort: %x", |
| 406 | exception == EXCP_INSN_ABORT ? "instruction" : |
| 407 | "data", dfsc); |
| 408 | } |
| 409 | break; |
| 410 | case EXCP_BRK: |
| 411 | #ifdef KDTRACE_HOOKS |
| 412 | if ((esr & ESR_ELx_ISS_MASK) == 0x40d && \ |
| 413 | dtrace_invop_jump_addr != 0) { |
| 414 | dtrace_invop_jump_addr(frame); |
| 415 | break; |
| 416 | } |
| 417 | #endif |
nothing calls this directly
no test coverage detected