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