1/* 2 * Copyright 2014, General Dynamics C4 Systems 3 * 4 * SPDX-License-Identifier: GPL-2.0-only 5 */ 6 7#include <config.h> 8#include <util.h> 9 10#ifndef CONFIG_ARM_HYPERVISOR_SUPPORT 11 12#include <machine/assembler.h> 13 14.code 32 15.section .vectors, "ax" 16 17BEGIN_FUNC(arm_vector_table) 18 ldr pc, =arm_reset_exception 19 ldr pc, =arm_undefined_inst_exception 20 ldr pc, =arm_swi_syscall 21 ldr pc, =arm_prefetch_abort_exception 22 ldr pc, =arm_data_abort_exception 23 ldr pc, =arm_reset_exception 24 ldr pc, =arm_irq_exception 25 ldr pc, =arm_fiq_exception 26 27.ltorg 28END_FUNC(arm_vector_table) 29 30.section .vectors.text, "ax" 31 32#include <arch/api/syscall.h> 33#include <arch/machine/hardware.h> 34 35#include <arch/machine/registerset.h> 36#include <sel4/sel4_arch/constants.h> 37 38BEGIN_FUNC(arm_undefined_inst_exception) 39 /* Full save/restore, documented in arm_swi_syscall */ 40 srsia #PMODE_SUPERVISOR 41 cps #PMODE_SUPERVISOR 42 stmdb sp, {r0-lr}^ 43 ldr r8, [sp] 44 sub r8, r8, #4 45 str r8, [sp, #(PT_FaultIP - PT_NextIP)] 46 mrc p15, 0, sp, c13, c0, 4 47 b c_handle_undefined_instruction 48END_FUNC(arm_undefined_inst_exception) 49 50BEGIN_FUNC(arm_swi_syscall) 51 /* Store CPSR and NextIP on supervisor stack, which currently points 52 at the end of the current thread's user context */ 53 srsia #PMODE_SUPERVISOR 54 55 /* Set the FaultIP address, which in ARM mode is the NextIP - 4. 56 * NOTE: This is completely wrong and broken in thumb mode. 57 */ 58 sub lr, lr, #4 59 60 /* Store FaultIP */ 61 str lr, [sp, #(PT_FaultIP - PT_NextIP)] 62 63 /* Stack all user registers */ 64 stmdb sp, {r0-lr}^ 65 66 /* Load the kernel's real stack pointer */ 67 mrc p15, 0, sp, c13, c0, 4 68 69 /* Load system call number as a c_handle_syscall argument. r0 and r1 are passed 70 * unmodified (cptr and msgInfo) respectively. On MCS configurations we also 71 * pass the reply cptr in r2 for fastpath_reply_recv. 72 */ 73 74#ifdef CONFIG_FASTPATH 75 cmp r7, #SYSCALL_CALL 76 beq c_handle_fastpath_call 77 cmp r7, #SYSCALL_REPLY_RECV 78#ifdef CONFIG_KERNEL_MCS 79 moveq r2, r6 80#endif 81 beq c_handle_fastpath_reply_recv 82#endif 83 84 mov r2, r7 85 b c_handle_syscall 86 87END_FUNC(arm_swi_syscall) 88 89BEGIN_FUNC(arm_prefetch_abort_exception) 90 /* Full save/restore, documented in arm_swi_syscall */ 91 srsia #PMODE_SUPERVISOR 92 cps #PMODE_SUPERVISOR 93 stmdb sp, {r0-lr}^ 94 95 /* Load PC and SPSR saved by the "srs" instruction above. */ 96 ldmia sp, {r8,r9} 97 98 /* Ensure the bottom 4 bits of SPSR are zero, indicating we came from 99 * userspace. If not, something has gone amiss in the kernel. */ 100 tst r9, #0xf 101 102 /* Compute the faulting address. */ 103 sub r8, r8, #4 104 105 bne kernel_prefetch_fault 106 107 /* Store faulting address in TCB and call handleVMFaultEvent. */ 108 str r8, [sp, #(PT_FaultIP - PT_NextIP)] 109 110 mrc p15, 0, sp, c13, c0, 4 111 112 b c_handle_instruction_fault 113 114kernel_prefetch_fault: 115#ifdef CONFIG_DEBUG_BUILD 116 mov r0, r8 117 mrc p15, 0, sp, c13, c0, 4 118 blx kernelPrefetchAbort 119 /* Fallthrough to infinite loop should we foolishly return. */ 120#endif 121 /* To aid finding faults in non-debug mode, catch kernel faults here. 122 * - r8 will contain the faulting address. 123 * - r9 will contain the IFSR register. 124 * - lr might contain something useful too if we followed a function 125 * call. 126 * - the original values of r8 and r9 will be obliterated. 127 */ 128 mrc p15, 0, r9, c5, c0, 1 /* Get ISFR. */ 1291: b 1b /* Infinite loop. You'd better have a watchdog. */ 130END_FUNC(arm_prefetch_abort_exception) 131 132BEGIN_FUNC(arm_data_abort_exception) 133 /* Full save/restore, documented in arm_swi_syscall */ 134 srsia #PMODE_SUPERVISOR 135 cps #PMODE_SUPERVISOR 136 stmdb sp, {r0-lr}^ 137 138 /* Load PC and SPSR saved by the "srs" instruction above. */ 139 ldmia sp, {r8,r9} 140 141 /* Ensure the bottom 4 bits of SPSR are zero, indicating we came from 142 * userspace. If not, something has gone amiss in the kernel. */ 143 tst r9, #0xf 144 145 /* Compute the faulting address. 146 * For a Data abort, LR_abt points at PC+8. */ 147 sub r8, r8, #8 148 149 bne kernel_data_fault 150 151 /* Store faulting address in TCB and call handleVMFaultEvent. */ 152 str r8, [sp, #(PT_FaultIP - PT_NextIP)] 153 mrc p15, 0, sp, c13, c0, 4 154 155 b c_handle_data_fault 156 157 158kernel_data_fault: 159#ifdef CONFIG_DEBUG_BUILD 160 mov r0, r8 161 mrc p15, 0, sp, c13, c0, 4 162 blx kernelDataAbort 163 /* Fallthrough to infinite loop should we foolishly return. */ 164#endif 165 /* To aid finding faults in non-debug mode, catch kernel faults here. 166 * - r8 will contain the faulting instruction. 167 * - r9 will contain the memory address that faulted. 168 * - r10 will contain the fault status register (DFSR). 169 * - the original values of r8, r9 and r10 will be obliterated. 170 */ 171 mrc p15, 0, r9, c5, c0, 0 /* Get data fault status register. */ 172 mrc p15, 0, r10, c6, c0, 0 /* Get fault address register. */ 1731: b 1b /* Infinite loop. You'd better have a watchdog. */ 174END_FUNC(arm_data_abort_exception) 175 176BEGIN_FUNC(arm_irq_exception) 177 /* Full save/restore, documented in arm_swi_syscall */ 178 srsia #PMODE_SUPERVISOR 179 cps #PMODE_SUPERVISOR 180 stmdb sp, {r0-lr}^ 181 ldr r8, [sp] 182 sub r8, r8, #4 183 str r8, [sp] 184 str r8, [sp, #(PT_FaultIP - PT_NextIP)] 185 mrc p15, 0, sp, c13, c0, 4 186 b c_handle_interrupt 187END_FUNC(arm_irq_exception) 188 189BEGIN_FUNC(arm_reset_exception) 190 blx halt 191END_FUNC(arm_reset_exception) 192 193BEGIN_FUNC(arm_fiq_exception) 194 blx halt 195END_FUNC(arm_fiq_exception) 196 197#endif /* !CONFIG_ARM_HYP */ 198