1/* 2 * Copyright 2017, Data61 3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO) 4 * ABN 41 687 119 230. 5 * 6 * This software may be distributed and modified according to the terms of 7 * the GNU General Public License version 2. Note that NO WARRANTY is provided. 8 * See "LICENSE_GPLv2.txt" for details. 9 * 10 * @TAG(DATA61_GPL) 11 */ 12 13#include <config.h> 14#include <arch/kernel/traps.h> 15#include <arch/object/vcpu.h> 16#include <arch/machine/registerset.h> 17#include <api/syscall.h> 18#include <machine/fpu.h> 19 20#include <benchmark/benchmark_track_types.h> 21#include <benchmark/benchmark_track.h> 22#include <benchmark/benchmark_utilisation.h> 23#include <arch/machine.h> 24 25void VISIBLE NORETURN 26c_handle_undefined_instruction(void) 27{ 28 NODE_LOCK_SYS; 29 c_entry_hook(); 30 31#ifdef TRACK_KERNEL_ENTRIES 32 ksKernelEntry.path = Entry_UserLevelFault; 33 ksKernelEntry.word = getRegister(NODE_STATE(ksCurThread), LR_svc); 34#endif 35 36#if defined(CONFIG_HAVE_FPU) && defined(CONFIG_ARCH_AARCH32) 37 /* We assume the first fault is a FP exception and enable FPU, if not already enabled */ 38 if (!isFpuEnable()) { 39 handleFPUFault(); 40 41 /* Restart the FP instruction that cause the fault */ 42 setNextPC(NODE_STATE(ksCurThread), getRestartPC(NODE_STATE(ksCurThread))); 43 } else { 44 handleUserLevelFault(0, 0); 45 } 46 47 restore_user_context(); 48 UNREACHABLE(); 49#endif 50 51 /* There's only one user-level fault on ARM, and the code is (0,0) */ 52 handleUserLevelFault(0, 0); 53 restore_user_context(); 54 UNREACHABLE(); 55} 56 57#if defined(CONFIG_HAVE_FPU) && defined(CONFIG_ARCH_AARCH64) 58void VISIBLE NORETURN 59c_handle_enfp(void) 60{ 61 c_entry_hook(); 62 63 handleFPUFault(); 64 restore_user_context(); 65 UNREACHABLE(); 66} 67#endif /* CONFIG_HAVE_FPU */ 68 69static inline void NORETURN 70c_handle_vm_fault(vm_fault_type_t type) 71{ 72 NODE_LOCK_SYS; 73 c_entry_hook(); 74 75#ifdef TRACK_KERNEL_ENTRIES 76 ksKernelEntry.path = Entry_VMFault; 77 ksKernelEntry.word = getRegister(NODE_STATE(ksCurThread), LR_svc); 78#endif 79 80 handleVMFaultEvent(type); 81 restore_user_context(); 82 UNREACHABLE(); 83} 84 85void VISIBLE NORETURN 86c_handle_data_fault(void) 87{ 88 c_handle_vm_fault(seL4_DataFault); 89} 90 91void VISIBLE NORETURN 92c_handle_instruction_fault(void) 93{ 94 c_handle_vm_fault(seL4_InstructionFault); 95} 96 97void VISIBLE NORETURN 98c_handle_interrupt(void) 99{ 100 NODE_LOCK_IRQ_IF(getActiveIRQ() != irq_remote_call_ipi); 101 c_entry_hook(); 102 103#ifdef TRACK_KERNEL_ENTRIES 104 ksKernelEntry.path = Entry_Interrupt; 105 ksKernelEntry.word = getActiveIRQ(); 106#endif 107 108 handleInterruptEntry(); 109 restore_user_context(); 110} 111 112void NORETURN 113slowpath(syscall_t syscall) 114{ 115#ifdef TRACK_KERNEL_ENTRIES 116 ksKernelEntry.is_fastpath = 0; 117#endif /* TRACK KERNEL ENTRIES */ 118 handleSyscall(syscall); 119 120 restore_user_context(); 121 UNREACHABLE(); 122} 123 124void VISIBLE 125c_handle_syscall(word_t cptr, word_t msgInfo, syscall_t syscall, word_t reply) 126{ 127 NODE_LOCK_SYS; 128 129 c_entry_hook(); 130#ifdef TRACK_KERNEL_ENTRIES 131 benchmark_debug_syscall_start(cptr, msgInfo, syscall); 132 ksKernelEntry.is_fastpath = 1; 133#endif /* DEBUG */ 134 135#ifdef CONFIG_FASTPATH 136 if (syscall == SysCall) { 137 fastpath_call(cptr, msgInfo); 138 UNREACHABLE(); 139 } else if (syscall == SysReplyRecv) { 140 fastpath_reply_recv(cptr, msgInfo, reply); 141 UNREACHABLE(); 142 } 143#endif /* CONFIG_FASTPATH */ 144 145 if (unlikely(syscall < SYSCALL_MIN || syscall > SYSCALL_MAX)) { 146#ifdef TRACK_KERNEL_ENTRIES 147 ksKernelEntry.path = Entry_UnknownSyscall; 148 /* ksKernelEntry.word word is already set to syscall */ 149#endif /* TRACK_KERNEL_ENTRIES */ 150 handleUnknownSyscall(syscall); 151 restore_user_context(); 152 UNREACHABLE(); 153 } else { 154 slowpath(syscall); 155 UNREACHABLE(); 156 } 157} 158 159#ifdef CONFIG_ARM_HYPERVISOR_SUPPORT 160VISIBLE NORETURN void 161c_handle_vcpu_fault(word_t hsr) 162{ 163 c_entry_hook(); 164 165#ifdef TRACK_KERNEL_ENTRIES 166 ksKernelEntry.path = Entry_VCPUFault; 167 ksKernelEntry.word = hsr; 168#endif 169 handleVCPUFault(hsr); 170 restore_user_context(); 171 UNREACHABLE(); 172} 173#endif /* CONFIG_ARM_HYPERVISOR_SUPPORT */ 174