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#if defined(CONFIG_ARCH_ARM_V6) && defined(CONFIG_DANGEROUS_CODE_INJECTION_ON_UNDEF_INSTR) 43 /* Call whatever's in r8. See Kconfig for the purpose of this. */ 44 blx r8 45 rfeia sp 46#else 47 stmdb sp, {r0-lr}^ 48 ldr r8, [sp] 49 sub r8, r8, #4 50 str r8, [sp, #(PT_FaultIP - PT_NextIP)] 51#ifdef CONFIG_ARCH_ARM_V6 52 ldr sp, =kernel_stack_alloc + BIT(CONFIG_KERNEL_STACK_BITS) 53#else 54 mrc p15, 0, sp, c13, c0, 4 55#endif /* CONFIG_ARCH_ARM_V6 */ 56 b c_handle_undefined_instruction 57#endif 58END_FUNC(arm_undefined_inst_exception) 59 60BEGIN_FUNC(arm_swi_syscall) 61 /* Store CPSR and NextIP on supervisor stack, which currently points 62 at the end of the current thread's user context */ 63 srsia #PMODE_SUPERVISOR 64 65 /* Set the FaultIP address, which in ARM mode is the NextIP - 4. 66 * NOTE: This is completely wrong and broken in thumb mode. 67 */ 68 sub lr, lr, #4 69 70 /* Store FaultIP */ 71 str lr, [sp, #(PT_FaultIP - PT_NextIP)] 72 73 /* Stack all user registers */ 74 stmdb sp, {r0-lr}^ 75 76 /* Load the kernel's real stack pointer */ 77#ifdef CONFIG_ARCH_ARM_V6 78 ldr sp, =kernel_stack_alloc + BIT(CONFIG_KERNEL_STACK_BITS) 79#else 80 mrc p15, 0, sp, c13, c0, 4 81#endif /* CONFIG_ARCH_ARM_V6 */ 82 83 /* Load system call number as a c_handle_syscall argument. r0 and r1 are passed 84 * unmodified (cptr and msgInfo) respectively. On MCS configurations we also 85 * pass the reply cptr in r2 for fastpath_reply_recv. 86 */ 87 88#ifdef CONFIG_FASTPATH 89 cmp r7, #SYSCALL_CALL 90 beq c_handle_fastpath_call 91 cmp r7, #SYSCALL_REPLY_RECV 92#ifdef CONFIG_KERNEL_MCS 93 moveq r2, r6 94#endif 95 beq c_handle_fastpath_reply_recv 96#endif 97 98 mov r2, r7 99 b c_handle_syscall 100 101END_FUNC(arm_swi_syscall) 102 103BEGIN_FUNC(arm_prefetch_abort_exception) 104 /* Full save/restore, documented in arm_swi_syscall */ 105 srsia #PMODE_SUPERVISOR 106 cps #PMODE_SUPERVISOR 107 stmdb sp, {r0-lr}^ 108 109 /* Load PC and SPSR saved by the "srs" instruction above. */ 110 ldmia sp, {r8,r9} 111 112 /* Ensure the bottom 4 bits of SPSR are zero, indicating we came from 113 * userspace. If not, something has gone amiss in the kernel. */ 114 tst r9, #0xf 115 116 /* Compute the faulting address. */ 117 sub r8, r8, #4 118 119 bne kernel_prefetch_fault 120 121 /* Store faulting address in TCB and call handleVMFaultEvent. */ 122 str r8, [sp, #(PT_FaultIP - PT_NextIP)] 123 124#ifdef CONFIG_ARCH_ARM_V6 125 ldr sp, =kernel_stack_alloc + BIT(CONFIG_KERNEL_STACK_BITS) 126#else 127 mrc p15, 0, sp, c13, c0, 4 128#endif /* CONFIG_ARCH_ARM_V6 */ 129 130 b c_handle_instruction_fault 131 132kernel_prefetch_fault: 133#ifdef CONFIG_DEBUG_BUILD 134 mov r0, r8 135#ifdef CONFIG_ARCH_ARM_V6 136 ldr sp, =kernel_stack_alloc + BIT(CONFIG_KERNEL_STACK_BITS) 137#else 138 mrc p15, 0, sp, c13, c0, 4 139#endif /* CONFIG_ARCH_ARM_V6 */ 140 blx kernelPrefetchAbort 141 /* Fallthrough to infinite loop should we foolishly return. */ 142#endif 143 /* To aid finding faults in non-debug mode, catch kernel faults here. 144 * - r8 will contain the faulting address. 145 * - r9 will contain the IFSR register. 146 * - lr might contain something useful too if we followed a function 147 * call. 148 * - the original values of r8 and r9 will be obliterated. 149 */ 150 mrc p15, 0, r9, c5, c0, 1 /* Get ISFR. */ 1511: b 1b /* Infinite loop. You'd better have a watchdog. */ 152END_FUNC(arm_prefetch_abort_exception) 153 154BEGIN_FUNC(arm_data_abort_exception) 155 /* Full save/restore, documented in arm_swi_syscall */ 156 srsia #PMODE_SUPERVISOR 157 cps #PMODE_SUPERVISOR 158 stmdb sp, {r0-lr}^ 159 160 /* Load PC and SPSR saved by the "srs" instruction above. */ 161 ldmia sp, {r8,r9} 162 163 /* Ensure the bottom 4 bits of SPSR are zero, indicating we came from 164 * userspace. If not, something has gone amiss in the kernel. */ 165 tst r9, #0xf 166 167 /* Compute the faulting address. 168 * For a Data abort, LR_abt points at PC+8. */ 169 sub r8, r8, #8 170 171 bne kernel_data_fault 172 173 /* Store faulting address in TCB and call handleVMFaultEvent. */ 174 str r8, [sp, #(PT_FaultIP - PT_NextIP)] 175#ifdef CONFIG_ARCH_ARM_V6 176 ldr sp, =kernel_stack_alloc + BIT(CONFIG_KERNEL_STACK_BITS) 177#else 178 mrc p15, 0, sp, c13, c0, 4 179#endif /* CONFIG_ARCH_ARM_V6 */ 180 181 b c_handle_data_fault 182 183 184kernel_data_fault: 185#ifdef CONFIG_DEBUG_BUILD 186 mov r0, r8 187#ifdef CONFIG_ARCH_ARM_V6 188 ldr sp, =kernel_stack_alloc + BIT(CONFIG_KERNEL_STACK_BITS) 189#else 190 mrc p15, 0, sp, c13, c0, 4 191#endif /* CONFIG_ARCH_ARM_V6 */ 192 blx kernelDataAbort 193 /* Fallthrough to infinite loop should we foolishly return. */ 194#endif 195 /* To aid finding faults in non-debug mode, catch kernel faults here. 196 * - r8 will contain the faulting instruction. 197 * - r9 will contain the memory address that faulted. 198 * - r10 will contain the fault status register (DFSR). 199 * - the original values of r8, r9 and r10 will be obliterated. 200 */ 201 mrc p15, 0, r9, c5, c0, 0 /* Get data fault status register. */ 202 mrc p15, 0, r10, c6, c0, 0 /* Get fault address register. */ 2031: b 1b /* Infinite loop. You'd better have a watchdog. */ 204END_FUNC(arm_data_abort_exception) 205 206BEGIN_FUNC(arm_irq_exception) 207 /* Full save/restore, documented in arm_swi_syscall */ 208 srsia #PMODE_SUPERVISOR 209 cps #PMODE_SUPERVISOR 210 stmdb sp, {r0-lr}^ 211 ldr r8, [sp] 212 sub r8, r8, #4 213 str r8, [sp] 214 str r8, [sp, #(PT_FaultIP - PT_NextIP)] 215#ifdef CONFIG_ARCH_ARM_V6 216 ldr sp, =kernel_stack_alloc + BIT(CONFIG_KERNEL_STACK_BITS) 217#else 218 mrc p15, 0, sp, c13, c0, 4 219#endif /* CONFIG_ARCH_ARM_V6 */ 220 b c_handle_interrupt 221END_FUNC(arm_irq_exception) 222 223BEGIN_FUNC(arm_reset_exception) 224 blx halt 225END_FUNC(arm_reset_exception) 226 227BEGIN_FUNC(arm_fiq_exception) 228 blx halt 229END_FUNC(arm_fiq_exception) 230 231#endif /* !CONFIG_ARM_HYP */ 232