1/* 2 * Copyright (c) 2009-2013 ETH Zurich. 3 * Copyright (c) 2015, Hewlett Packard Enterprise Development LP. 4 * All rights reserved. 5 * 6 * This file is distributed under the terms in the attached LICENSE file. 7 * If you do not find this file, copies can be found by writing to: 8 * ETH Zurich D-INFK, Universitaetstrasse 6, CH-8092 Zurich. Attn: Systems Group. 9 */ 10 11#include <kernel.h> 12#include <dispatch.h> 13#include <systime.h> 14#include <arm_hal.h> 15#include <sysreg.h> 16#include <exceptions.h> 17#include <exec.h> 18#include <misc.h> 19#include <stdio.h> 20#include <wakeup.h> 21#include <irq.h> 22#include <arch/arm/arm.h> 23#include <arch/arm/gic.h> 24#include <arch/arm/platform.h> 25#include <dev/armv8_dev.h> 26 27void handle_user_page_fault(lvaddr_t fault_address, 28 arch_registers_state_t* save_area, 29 union registers_aarch64 *resume_area) 30{ 31 lvaddr_t handler; 32 struct dispatcher_shared_aarch64 *disp = 33 get_dispatcher_shared_aarch64(dcb_current->disp); 34 uintptr_t saved_pc = save_area->named.pc; 35 36 disp->d.disabled = dispatcher_is_disabled_ip(dcb_current->disp, saved_pc); 37 bool disabled = (disp->d.disabled != 0); 38 39 assert(dcb_current->disp_cte.cap.type == ObjType_Frame); 40 41 printk(LOG_DEBUG, "user page fault%s in '%.*s': addr %"PRIxLVADDR 42 " IP %"PRIxPTR"\n", 43 disabled ? " WHILE DISABLED" : "", DISP_NAME_LEN, 44 disp->d.name, fault_address, saved_pc); 45 46 if (disabled) { 47 assert(save_area == &disp->trap_save_area); 48 handler = disp->d.dispatcher_pagefault_disabled; 49 dcb_current->faults_taken++; 50 } 51 else { 52 assert(save_area == &disp->enabled_save_area); 53 handler = disp->d.dispatcher_pagefault; 54 } 55 56 if (dcb_current->faults_taken > 2) { 57 printk(LOG_WARN, "handle_user_page_fault: too many faults, " 58 "making domain unrunnable\n"); 59 dcb_current->faults_taken = 0; // just in case it gets restarted 60 scheduler_remove(dcb_current); 61 dispatch(schedule()); 62 } 63 else { 64 // 65 // Upcall to dispatcher 66 // 67 // NB System might be cleaner with a prototype 68 // dispatch context that has R0-R3 to be overwritten 69 // plus initial stack, thread, and gic registers. Could do 70 // a faster resume_for_upcall(). 71 // 72 73 struct dispatcher_shared_generic *disp_gen = 74 get_dispatcher_shared_generic(dcb_current->disp); 75 76 /* XXX - This code leaks the contents of the kernel stack to the 77 * user-level fault handler. */ 78 79 resume_area->named.x0 = disp_gen->udisp; 80 resume_area->named.x1 = fault_address; 81 resume_area->named.x2 = armv8_ESR_EL1_rd(NULL); 82 resume_area->named.x3 = saved_pc; 83 /* Why does the kernel do this? */ 84 resume_area->named.x10 = disp->got_base; 85 resume_area->named.pc = handler; 86 resume_area->named.spsr = CPSR_F_MASK | AARCH64_MODE_USR; 87 88 // SP is set by handler routine. 89 90 // Upcall user to save area 91 disp->d.disabled = true; 92 } 93} 94 95void handle_user_undef(lvaddr_t fault_address, enum aarch64_exception_class cause, 96 arch_registers_state_t* save_area, 97 union registers_aarch64 *resume_area) 98{ 99 struct dispatcher_shared_aarch64 *disp = 100 get_dispatcher_shared_aarch64(dcb_current->disp); 101 102 bool disabled = 103 dispatcher_is_disabled_ip(dcb_current->disp, save_area->named.pc); 104 disp->d.disabled = disabled; 105 106 assert(dcb_current->disp_cte.cap.type == ObjType_Frame); 107 if (disabled) { 108 // assert(save_area == &disp->trap_save_area); 109 } 110 else { 111 assert(save_area == &disp->enabled_save_area); 112 } 113 114 printk(LOG_WARN, "user undef fault (0x%lx)%s in '%.*s': IP 0x%lx x29:%lx x30:%lx sp:%lx\n", 115 cause, disabled ? " WHILE DISABLED" : "", DISP_NAME_LEN, 116 disp->d.name, fault_address, save_area->named.x29, save_area->named.x30, save_area->named.stack); 117 118 struct dispatcher_shared_generic *disp_gen = 119 get_dispatcher_shared_generic(dcb_current->disp); 120 121 resume_area->named.x0 = disp_gen->udisp; 122 resume_area->named.x1 = AARCH64_EVECTOR_UNDEF; 123 resume_area->named.x2 = 0; 124 resume_area->named.x3 = fault_address; 125 /* Why does the kernel do this? */ 126 resume_area->named.x10 = disp->got_base; 127 resume_area->named.pc = disp->d.dispatcher_trap; 128 resume_area->named.spsr = CPSR_F_MASK | AARCH64_MODE_USR; 129 130 // Upcall user to save area 131 disp->d.disabled = true; 132} 133 134void handle_user_fault(lvaddr_t fault_address, uintptr_t cause, 135 arch_registers_state_t* save_area) 136{ 137 union registers_aarch64 resume_area; 138 139 switch(cause) { 140 case aarch64_ec_unknown : 141 case aarch64_ec_wfi : 142 case aarch64_ec_mcr_cp15 : 143 case aarch64_ec_mcrr_cp15 : 144 case aarch64_ec_mcr_cp14 : 145 case aarch64_ec_ldc_cp14 : 146 case aarch64_ec_fpen : 147 case aarch64_ec_mcr_cp10 : 148 case aarch64_ec_mcrr_cp14 : 149 case aarch64_ec_il : 150 handle_user_undef(fault_address, cause, save_area, &resume_area); 151 break; 152 case aarch64_ec_svc_aa32 : 153 case aarch64_ec_hvc_aa32 : 154 case aarch64_ec_smc_aa32 : 155 case aarch64_ec_svc_aa64 : 156 case aarch64_ec_hvc_aa64 : 157 case aarch64_ec_smc_aa64 : 158 panic("syscall ended up in exception handler ? Yuck."); 159 break; 160 case aarch64_ec_mrs : 161 case aarch64_ec_impl : 162 handle_user_undef(fault_address, cause, save_area, &resume_area); 163 break; 164 case aarch64_ec_iabt_low : 165 handle_user_page_fault(fault_address, save_area, &resume_area); 166 break; 167 case aarch64_ec_iabt_high : 168 panic("pagefault while in kernel? Yuck."); 169 break; 170 case aarch64_ec_pc_align : 171 handle_user_undef(fault_address, cause, save_area, &resume_area); 172 break; 173 case aarch64_ec_dabt_low : 174 handle_user_page_fault(fault_address, save_area, &resume_area); 175 break; 176 case aarch64_ec_dabt_high : 177 panic("pagefault while in kernel? Yuck."); 178 break; 179 case aarch64_ec_sp_align : 180 case aarch64_ec_fpu_aa32 : 181 case aarch64_ec_fpu_aa64 : 182 case aarch64_ec_serror : 183 case aarch64_ec_bkpt_low : 184 case aarch64_ec_bkpt_high : 185 case aarch64_ec_step_low : 186 case aarch64_ec_step_high : 187 case aarch64_ec_wpt_low : 188 case aarch64_ec_wpt_high : 189 case aarch64_ec_bkpt_soft : 190 case aarch64_ec_bkpt_el2 : 191 case aarch64_ec_brk : 192 handle_user_undef(fault_address, cause, save_area, &resume_area); 193 break; 194 default: 195 panic("Unknown exception syndrome: %u", cause); 196 break; 197 } 198 199 resume(&resume_area); 200} 201 202void nosave_handle_irq(void) 203{ 204 uint32_t irq = 0; 205 irq = platform_get_active_irq(); 206 207 debug(SUBSYS_DISPATCH, "IRQ %"PRIu32" while %s\n", irq, 208 dcb_current ? (dcb_current->disabled ? "disabled": "enabled") : 209 "in kernel"); 210 211 static int first_timer_interrupt_fired = 0; 212 // Offer it to the timer 213 if (platform_is_timer_interrupt(irq)) { 214 if(!first_timer_interrupt_fired) { 215 printk(LOG_NOTE, "ARMv8-A: Timer interrupt received!\n"); 216 first_timer_interrupt_fired = 1; 217 } 218 platform_acknowledge_irq(irq); 219#ifndef CONFIG_ONESHOT_TIMER 220 // Set next trigger 221 systime_set_timer(kernel_timeslice); 222#endif 223 wakeup_check(systime_now()); 224 dispatch(schedule()); 225 } else { 226 platform_acknowledge_irq(irq); 227 send_user_interrupt(irq); 228 panic("Unhandled IRQ %"PRIu32"\n", irq); 229 } 230} 231 232void save_handle_irq(arch_registers_state_t* save_area, uintptr_t fault_pc, 233 uint64_t x0, uint64_t x1, uint64_t x2, uint64_t x3) 234{ 235 236 /* Save the FPU registers */ 237 __asm volatile( 238 " stp q0, q1, [%x0, #0]\n\t" 239 " stp q2, q3, [%x0, #0x20]\n\t" 240 " stp q4, q5, [%x0, #0x40]\n\t" 241 " stp q6, q7, [%x0, #0x60]\n\t" 242 " stp q8, q9, [%x0, #0x80]\n\t" 243 " stp q10, q11, [%x0, #0xa0]\n\t" 244 " stp q12, q13, [%x0, #0xc0]\n\t" 245 " stp q14, q15, [%x0, #0xe0]\n\t" 246 " stp q16, q17, [%x0, #0x100]\n\t" 247 " stp q18, q19, [%x0, #0x120]\n\t" 248 " stp q20, q21, [%x0, #0x140]\n\t" 249 " stp q22, q23, [%x0, #0x160]\n\t" 250 " stp q24, q25, [%x0, #0x180]\n\t" 251 " stp q26, q27, [%x0, #0x1a0]\n\t" 252 " stp q28, q29, [%x0, #0x1c0]\n\t" 253 " stp q30, q31, [%x0, #0x1e0]\n\t" 254 :: "r" (&save_area->named.v)); 255 256 /* The assembly stub leaves the first 4 registers, the stack pointer, 257 * the exception PC, and the SPSR for us to save, as it's run out of room for 258 * the necessary instructions. */ 259 save_area->named.x0 = x0; 260 save_area->named.x1 = x1; 261 save_area->named.x2 = x2; 262 save_area->named.x3 = x3; 263 save_area->named.stack = armv8_SP_EL0_rd(NULL); 264 save_area->named.spsr = armv8_SPSR_EL1_rd(NULL); 265 save_area->named.pc = fault_pc; 266 267 if (dcb_current != NULL) { 268 dispatcher_handle_t handle = dcb_current->disp; 269 if (save_area == dispatcher_get_disabled_save_area(handle)) { 270 assert(dispatcher_is_disabled_ip(handle, fault_pc)); 271 dcb_current->disabled = true; 272 } else { 273 assert(save_area == dispatcher_get_enabled_save_area(handle)); 274 assert(!dispatcher_is_disabled_ip(handle, fault_pc)); 275 dcb_current->disabled = false; 276 } 277 } 278 279 nosave_handle_irq(); 280} 281 282#define STACK_DUMP_LIMIT 32 283 284/* For unhandled faults, we print a register dump and panic. */ 285void fatal_kernel_fault(lvaddr_t epc, uint64_t spsr, uint64_t esr, 286 uint64_t vector, arch_registers_state_t* save_area) 287{ 288 size_t i; 289 enum aarch64_exception_class exception_class = FIELD(26,6,esr); 290 /* int instruction_length = FIELD(25,1,esr); */ 291 int iss = FIELD(0,25,esr); 292 293 /* Save the FPU registers */ 294 __asm volatile( 295 " stp q0, q1, [%x0, #0]\n\t" 296 " stp q2, q3, [%x0, #0x20]\n\t" 297 " stp q4, q5, [%x0, #0x40]\n\t" 298 " stp q6, q7, [%x0, #0x60]\n\t" 299 " stp q8, q9, [%x0, #0x80]\n\t" 300 " stp q10, q11, [%x0, #0xa0]\n\t" 301 " stp q12, q13, [%x0, #0xc0]\n\t" 302 " stp q14, q15, [%x0, #0xe0]\n\t" 303 " stp q16, q17, [%x0, #0x100]\n\t" 304 " stp q18, q19, [%x0, #0x120]\n\t" 305 " stp q20, q21, [%x0, #0x140]\n\t" 306 " stp q22, q23, [%x0, #0x160]\n\t" 307 " stp q24, q25, [%x0, #0x180]\n\t" 308 " stp q26, q27, [%x0, #0x1a0]\n\t" 309 " stp q28, q29, [%x0, #0x1c0]\n\t" 310 " stp q30, q31, [%x0, #0x1e0]\n\t" 311 :: "r" (&save_area->named.v)); 312 313 printk(LOG_PANIC, "Fatal (unexpected) fault at 0x%"PRIx64 " (%#" PRIx64 ")\n\n", epc, epc - (uintptr_t)&kernel_first_byte); 314 printk(LOG_PANIC, "Register context saved at: %p\n", save_area); 315 printk(LOG_PANIC, "Vector: "); 316 switch(vector) { 317 case AARCH64_EVECTOR_UNDEF: 318 printk(LOG_PANIC, "UNDEF\n"); 319 break; 320 case AARCH64_EVECTOR_EL0_SYNC: 321 printk(LOG_PANIC, "EL0_SYNC\n"); 322 break; 323 case AARCH64_EVECTOR_EL0_IRQ: 324 printk(LOG_PANIC, "EL0_IRQ\n"); 325 break; 326 case AARCH64_EVECTOR_EL0_FIQ: 327 printk(LOG_PANIC, "EL0_FIQ\n"); 328 break; 329 case AARCH64_EVECTOR_EL0_SERROR: 330 printk(LOG_PANIC, "EL0_SERROR\n"); 331 break; 332 case AARCH64_EVECTOR_EL1_SYNC: 333 printk(LOG_PANIC, "EL1_SYNC\n"); 334 break; 335 case AARCH64_EVECTOR_EL1_IRQ: 336 printk(LOG_PANIC, "EL1_IRQ\n"); 337 break; 338 case AARCH64_EVECTOR_EL1_FIQ: 339 printk(LOG_PANIC, "EL1_FIQ\n"); 340 break; 341 case AARCH64_EVECTOR_EL1_SERROR: 342 printk(LOG_PANIC, "EL1_SERROR\n"); 343 break; 344 case AARCH64_EVECTOR_EL2_SYNC: 345 printk(LOG_PANIC, "EL2_SYNC\n"); 346 break; 347 case AARCH64_EVECTOR_EL2_IRQ: 348 printk(LOG_PANIC, "EL2_IRQ\n"); 349 break; 350 case AARCH64_EVECTOR_EL2_FIQ: 351 printk(LOG_PANIC, "EL2_FIQ\n"); 352 break; 353 case AARCH64_EVECTOR_EL2_SERROR: 354 printk(LOG_PANIC, "EL2_SERROR\n"); 355 break; 356 case AARCH32_EVECTOR_EL0_SYNC: 357 printk(LOG_PANIC, "AARCH32_EL0_SYNC\n"); 358 break; 359 case AARCH32_EVECTOR_EL0_IRQ: 360 printk(LOG_PANIC, "AARCH32_EL0_IRQ\n"); 361 break; 362 case AARCH32_EVECTOR_EL0_FIQ: 363 printk(LOG_PANIC, "AARCH32_EL0_FIQ\n"); 364 break; 365 case AARCH32_EVECTOR_EL0_SERROR: 366 printk(LOG_PANIC, "AARCH32_EL0_SERROR\n"); 367 break; 368 } 369 370 for (i = 0; i < 31; i++) { 371 uint64_t reg = save_area->regs[i]; 372 if (reg >= (uintptr_t)&kernel_first_byte && reg <= (uintptr_t)&kernel_text_final_byte) { 373 printk(LOG_PANIC, "x%d\t%"PRIx64" (%#" PRIx64 ")\n", i, reg, reg - (uintptr_t)&kernel_first_byte); 374 } else { 375 printk(LOG_PANIC, "x%d\t%"PRIx64"\n", i, reg); 376 } 377 } 378 379 printk(LOG_PANIC, "sp\t%"PRIx64"\n", save_area->regs[SP_REG]); 380 printk(LOG_PANIC, "pc\t%"PRIx64"\n", epc); 381 printk(LOG_PANIC, "spsr\t%"PRIx64"\n", spsr); 382 printk(LOG_PANIC, "instruction-specific syndrome\t%x\n", iss); 383 384 /* Skip the trap frame to dump the prior stack. */ 385 uint64_t *kstack_base= (void *)save_area + (NUM_REGS * 8); 386 387 if((((uintptr_t)kstack_base) & MASK(3)) != 0) { 388 kstack_base= (uint64_t *)((uint64_t)kstack_base & ~MASK(3)); 389 printk(LOG_PANIC, 390 "Kernel stack is misaligned, dumping from %p\n", 391 kstack_base); 392 } 393 394 uint64_t kstack_len = 395 (((uint64_t)kernel_stack + KERNEL_STACK_SIZE) - 396 (uint64_t)kstack_base) / 397 sizeof(uint64_t); 398 399 printk(LOG_PANIC, 400 "Kernel stack (0x%p - 0x%p):\n", 401 kstack_base, 402 (void *)kernel_stack + KERNEL_STACK_SIZE); 403 404 for(i= 0; i < kstack_len-2; i+=2) { 405 if(i > STACK_DUMP_LIMIT) { 406 printk(LOG_PANIC, "...\n"); 407 break; 408 } 409 410 printk(LOG_PANIC, 411 "%016"PRIx64" %016"PRIx64" %016"PRIx64"\n", 412 (uint64_t)(kstack_base + i), 413 kstack_base[i], 414 kstack_base[i+1]); 415 } 416 417 switch(exception_class) { 418 case aarch64_ec_unknown: 419 panic("Unknown reason/instruction.\n"); 420 421 case aarch64_ec_wfi: 422 panic("Trapped WFI/WFI.\n"); 423 424 case aarch64_ec_mcr_cp15: 425 case aarch64_ec_mcrr_cp15: 426 panic("CP15 abort.\n"); 427 428 case aarch64_ec_mcr_cp14: 429 case aarch64_ec_ldc_cp14: 430 case aarch64_ec_mcrr_cp14: 431 panic("CP14 abort.\n"); 432 433 case aarch64_ec_fpen: 434 case aarch64_ec_fpu_aa32: 435 case aarch64_ec_fpu_aa64: 436 panic("FPU abort.\n"); 437 438 case aarch64_ec_mcr_cp10: 439 panic("CP10 abort.\n"); 440 441 case aarch64_ec_il: 442 panic("PSTATE.IL == 1.\n"); 443 444 case aarch64_ec_svc_aa32: 445 case aarch64_ec_hvc_aa32: 446 case aarch64_ec_svc_aa64: 447 case aarch64_ec_hvc_aa64: 448 case aarch64_ec_smc_aa64: 449 panic("Unhandled system/hypervisor/monitor call.\n"); 450 451 case aarch64_ec_mrs: 452 panic("Exception caused by MSR/MRS.\n"); 453 454 case aarch64_ec_impl: 455 panic("Implementation-specific exception.\n"); 456 457 case aarch64_ec_iabt_low: 458 panic("Instruction abort at user level.\n"); 459 460 case aarch64_ec_iabt_high: 461 panic("Instruction abort in the kernel.\n"); 462 463 case aarch64_ec_pc_align: 464 panic("Misaligned PC @0x%"PRIx64".\n", 465 sysreg_read_far()); 466 467 case aarch64_ec_dabt_low: 468 panic("Data abort at user level @0x%"PRIx64".\n", 469 sysreg_read_far()); 470 471 case aarch64_ec_dabt_high: 472 printk(LOG_PANIC, 473 "Data abort in the kernel @0x%"PRIx64".\n", 474 sysreg_read_far()); 475 printk(LOG_PANIC, "Abort type: "); 476 switch(iss) { 477 case aarch64_dsfc_size_l0: 478 printk(LOG_PANIC, "address size fault, L0/TTBR\n"); 479 break; 480 case aarch64_dsfc_size_l1: 481 printk(LOG_PANIC, "address size fault, L1\n"); 482 break; 483 case aarch64_dsfc_size_l2: 484 printk(LOG_PANIC, "address size fault, L2\n"); 485 break; 486 case aarch64_dsfc_size_l3: 487 printk(LOG_PANIC, "address size fault, L3\n"); 488 break; 489 case aarch64_dsfc_trans_l0: 490 printk(LOG_PANIC, "translation fault, L0/TTBR\n"); 491 break; 492 case aarch64_dsfc_trans_l1: 493 printk(LOG_PANIC, "translation fault, L1\n"); 494 break; 495 case aarch64_dsfc_trans_l2: 496 printk(LOG_PANIC, "translation fault, L2\n"); 497 break; 498 case aarch64_dsfc_trans_l3: 499 printk(LOG_PANIC, "translation fault, L3\n"); 500 break; 501 case aarch64_dsfc_flag_l1: 502 printk(LOG_PANIC, "access flag fault, L1\n"); 503 break; 504 case aarch64_dsfc_flag_l2: 505 printk(LOG_PANIC, "access flag fault, L2\n"); 506 break; 507 case aarch64_dsfc_flag_l3: 508 printk(LOG_PANIC, "access flag fault, L3\n"); 509 break; 510 case aarch64_dsfc_perm_l1: 511 printk(LOG_PANIC, "permission fault, L1\n"); 512 break; 513 case aarch64_dsfc_perm_l2: 514 printk(LOG_PANIC, "permission fault, L2\n"); 515 break; 516 case aarch64_dsfc_perm_l3: 517 printk(LOG_PANIC, "permission fault, L3\n"); 518 break; 519 case aarch64_dsfc_external: 520 printk(LOG_PANIC, "external abort\n"); 521 break; 522 case aarch64_dsfc_external_l0: 523 printk(LOG_PANIC, "external abort on walk, L0/TTBR\n"); 524 break; 525 case aarch64_dsfc_external_l1: 526 printk(LOG_PANIC, "external abort on walk, L1\n"); 527 break; 528 case aarch64_dsfc_external_l2: 529 printk(LOG_PANIC, "external abort on walk, L2\n"); 530 break; 531 case aarch64_dsfc_external_l3: 532 printk(LOG_PANIC, "external abort on walk, L3\n"); 533 break; 534 case aarch64_dsfc_parity: 535 printk(LOG_PANIC, "parity error\n"); 536 break; 537 case aarch64_dsfc_parity_l0: 538 printk(LOG_PANIC, "parity error on walk, L0/TTBR\n"); 539 break; 540 case aarch64_dsfc_parity_l1: 541 printk(LOG_PANIC, "parity error on walk, L1\n"); 542 break; 543 case aarch64_dsfc_parity_l2: 544 printk(LOG_PANIC, "parity error on walk, L2\n"); 545 break; 546 case aarch64_dsfc_parity_l3: 547 printk(LOG_PANIC, "parity error on walk, L3\n"); 548 break; 549 case aarch64_dsfc_alighment: 550 printk(LOG_PANIC, "alignment fault\n"); 551 break; 552 case aarch64_dsfc_tlb_confl: 553 printk(LOG_PANIC, "TLB conflict\n"); 554 break; 555 case aarch64_dsfc_impl1: 556 printk(LOG_PANIC, "implementation-defined fault 1\n"); 557 break; 558 case aarch64_dsfc_impl2: 559 printk(LOG_PANIC, "implementation-defined fault 2\n"); 560 break; 561 case aarch64_dsfc_sect_dom: 562 printk(LOG_PANIC, "domain fault on section\n"); 563 break; 564 case aarch64_dsfc_page_dom: 565 printk(LOG_PANIC, "domain fault on page\n"); 566 break; 567 default: 568 printk(LOG_PANIC, "unknown\n"); 569 break; 570 } 571 panic("halting.\n"); 572 573 case aarch64_ec_sp_align: 574 panic("Misaligned SP.\n"); 575 576 case aarch64_ec_serror: 577 panic("Delayed memory abort.\n"); 578 579 case aarch64_ec_bkpt_low: 580 panic("HW Breakpoint in user code.\n"); 581 582 case aarch64_ec_bkpt_high: 583 panic("HW Breakpoint in the kernel.\n"); 584 585 case aarch64_ec_step_low: 586 panic("Single step in user code.\n"); 587 588 case aarch64_ec_step_high: 589 panic("Single step in the kernel.\n"); 590 591 case aarch64_ec_wpt_low: 592 panic("HW Watchpoint in user code @0x%"PRIx64".\n", 593 sysreg_read_far()); 594 595 case aarch64_ec_wpt_high: 596 panic("HW Watchpoint in the kernel @0x%"PRIx64".\n", 597 sysreg_read_far()); 598 599 case aarch64_ec_bkpt_soft: 600 panic("AArch32 soft breakpoint.\n"); 601 602 case aarch64_ec_bkpt_el2: 603 panic("AArch32 Breakpoint trapped to EL2.\n"); 604 605 case aarch64_ec_brk: 606 panic("AArch64 soft breakpoint.\n"); 607 608 default: 609 panic("Unrecognised exception.\n"); 610 } 611} 612