1/* 2 * Copyright 2014, General Dynamics C4 Systems 3 * 4 * SPDX-License-Identifier: GPL-2.0-only 5 */ 6 7#pragma once 8 9#include <config.h> 10 11/* 12 * We cannot allow async aborts in the verified kernel, but 13 * they are useful in identifying invalid memory access bugs 14 * so we enable them in debug mode. 15 */ 16#ifdef CONFIG_DEBUG_BUILD 17#define CPSR_EXTRA_FLAGS 0 18#else 19#define CPSR_EXTRA_FLAGS PMASK_ASYNC_ABORT 20#endif 21 22#define CPSR_USER ( PMASK_FIRQ \ 23 | PMODE_USER \ 24 | CPSR_EXTRA_FLAGS ) 25 26#define CPSR_KERNEL ( PMASK_FIRQ \ 27 | PMASK_IRQ \ 28 | PMODE_KERNEL \ 29 | CPSR_EXTRA_FLAGS ) 30 31#define CPSR_IDLETHREAD ( PMASK_FIRQ \ 32 | PMODE_IDLE \ 33 | CPSR_EXTRA_FLAGS ) 34 35/* Offsets within the user context, these need to match the order in 36 * register_t below */ 37#define PT_SP (13 * 4) 38#define PT_NextIP (15 * 4) 39#define PT_ELR_hyp (15 * 4) 40#define PT_FaultIP (17 * 4) 41#define PT_TPIDRURW (18 * 4) 42#define PT_R8 (8 * 4) 43 44#ifdef CONFIG_KERNEL_GLOBALS_FRAME 45/* 46 * Virtualise the TPIDRURW register in the globals frame. 47 */ 48#define GLOBALS_TPIDRURW 0 49#endif 50 51#ifndef __ASSEMBLER__ /* C only definitions */ 52 53#include <config.h> 54#include <stdint.h> 55#include <assert.h> 56#include <util.h> 57#include <arch/types.h> 58#include <arch/machine/debug_conf.h> 59#include <sel4/plat/api/constants.h> 60 61/* These are the indices of the registers in the 62 * saved thread context. The values are determined 63 * by the order in which they're saved in the trap 64 * handler. */ 65enum _register { 66 R0 = 0, 67 capRegister = 0, 68 badgeRegister = 0, 69 70 R1 = 1, 71 msgInfoRegister = 1, 72 73 R2 = 2, 74 R3 = 3, 75 R4 = 4, 76 R5 = 5, 77 R6 = 6, 78#ifdef CONFIG_KERNEL_MCS 79 replyRegister = 6, 80#endif 81 R7 = 7, 82 R8 = 8, 83#ifdef CONFIG_KERNEL_MCS 84 nbsendRecvDest = 8, 85#endif 86 87 R9 = 9, 88 R10 = 10, 89 R11 = 11, 90 R12 = 12, 91 92 R13 = 13, 93 SP = 13, 94 95 R14 = 14, 96 LR = 14, 97 98 /* End of GP registers, the following are additional kernel-saved state. */ 99 100 NextIP = 15, /* LR_svc */ 101#ifdef CONFIG_ARM_HYPERVISOR_SUPPORT 102 ELR_hyp = 15, 103#endif 104 CPSR = 16, 105 106 FaultIP = 17, 107 /* user readable/writable thread ID register. 108 * name comes from the ARM manual */ 109 TPIDRURW = 18, 110 TLS_BASE = TPIDRURW, 111 /* user readonly thread ID register. */ 112 TPIDRURO = 19, 113 n_contextRegisters = 20, 114}; 115 116#define NEXT_PC_REG NextIP 117 118compile_assert(sp_offset_correct, SP *sizeof(word_t) == PT_SP) 119compile_assert(lr_svc_offset_correct, NextIP *sizeof(word_t) == PT_NextIP) 120#ifdef CONFIG_ARM_HYPERVISOR_SUPPORT 121compile_assert(elr_hyp_offset_correct, ELR_hyp *sizeof(word_t) == PT_ELR_hyp) 122#endif 123compile_assert(faultinstruction_offset_correct, FaultIP *sizeof(word_t) == PT_FaultIP) 124compile_assert(r8_offset_correct, R8 *sizeof(word_t) == PT_R8) 125 126typedef word_t register_t; 127 128enum messageSizes { 129 n_msgRegisters = seL4_FastMessageRegisters, 130 n_frameRegisters = 10, 131 n_gpRegisters = 9, 132 n_exceptionMessage = 3, 133 n_syscallMessage = 12, 134#ifdef CONFIG_KERNEL_MCS 135 n_timeoutMessage = 17, 136#endif 137}; 138 139#define EXCEPTION_MESSAGE \ 140 {\ 141 [seL4_UserException_FaultIP] = FaultIP,\ 142 [seL4_UserException_SP] = SP,\ 143 [seL4_UserException_CPSR] = CPSR\ 144 } 145 146#define SYSCALL_MESSAGE \ 147{\ 148 [seL4_UnknownSyscall_R0] = R0,\ 149 [seL4_UnknownSyscall_R1] = R1,\ 150 [seL4_UnknownSyscall_R2] = R2,\ 151 [seL4_UnknownSyscall_R3] = R3,\ 152 [seL4_UnknownSyscall_R4] = R4,\ 153 [seL4_UnknownSyscall_R5] = R5,\ 154 [seL4_UnknownSyscall_R6] = R6,\ 155 [seL4_UnknownSyscall_R7] = R7,\ 156 [seL4_UnknownSyscall_FaultIP] = FaultIP,\ 157 [seL4_UnknownSyscall_SP] = SP,\ 158 [seL4_UnknownSyscall_LR] = LR,\ 159 [seL4_UnknownSyscall_CPSR] = CPSR\ 160} 161 162#define TIMEOUT_REPLY_MESSAGE \ 163{\ 164 [seL4_TimeoutReply_FaultIP] = FaultIP,\ 165 [seL4_TimeoutReply_SP] = SP, \ 166 [seL4_TimeoutReply_CPSR] = CPSR,\ 167 [seL4_TimeoutReply_R0] = R0,\ 168 [seL4_TimeoutReply_R1] = R1,\ 169 [seL4_TimeoutReply_R8] = R8,\ 170 [seL4_TimeoutReply_R9] = R9,\ 171 [seL4_TimeoutReply_R10] = R10,\ 172 [seL4_TimeoutReply_R11] = R11,\ 173 [seL4_TimeoutReply_R12] = R12,\ 174 [seL4_TimeoutReply_R2] = R2,\ 175 [seL4_TimeoutReply_R3] = R3,\ 176 [seL4_TimeoutReply_R4] = R4,\ 177 [seL4_TimeoutReply_R5] = R5,\ 178 [seL4_TimeoutReply_R6] = R6,\ 179 [seL4_TimeoutReply_R7] = R7,\ 180 [seL4_TimeoutReply_R14] = R14,\ 181} 182 183extern const register_t msgRegisters[]; 184extern const register_t frameRegisters[]; 185extern const register_t gpRegisters[]; 186 187#ifdef ARM_BASE_CP14_SAVE_AND_RESTORE 188typedef struct debug_register_pair { 189 word_t cr, vr; 190} debug_register_pair_t; 191 192/* 193 * This padding ensures that there is reasonable leeway when determining 194 * the size of the untyped needed for a TCB when watchpoint handling is 195 * involved. 196 */ 197#define EXLUSIVE_WATCHPOINT_PADING 6 198#define EXLUSIVE_WATCHPOINT_PADDED \ 199 (seL4_NumExclusiveWatchpoints > EXLUSIVE_WATCHPOINT_PADING) \ 200 ? seL4_NumExclusiveWatchpoints \ 201 : EXLUSIVE_WATCHPOINT_PADING 202 203typedef struct user_breakpoint_state { 204 /* We don't use context comparisons. */ 205 debug_register_pair_t breakpoint[seL4_NumExclusiveBreakpoints], 206 watchpoint[EXLUSIVE_WATCHPOINT_PADDED]; 207 uint32_t used_breakpoints_bf; 208 word_t n_instructions; 209 bool_t single_step_enabled; 210 uint16_t single_step_hw_bp_num; 211} user_breakpoint_state_t; 212#endif 213 214#ifdef CONFIG_HAVE_FPU 215typedef struct user_fpu_state { 216 uint64_t fpregs[32]; 217 uint32_t fpexc; 218 uint32_t fpscr; 219} user_fpu_state_t; 220#endif /* CONFIG_HAVE_FPU */ 221 222/* ARM user-code context: size = 72 bytes 223 * Or with hardware debug support built in: 224 * 72 + sizeof(word_t) * (NUM_BPS + NUM_WPS) * 2 225 * 226 * The "word_t registers" member of this struct must come first, because in 227 * head.S, we assume that an "ldr %0, =ksCurThread" will point to the beginning 228 * of the current thread's registers. The assert below should help. 229 */ 230struct user_context { 231 word_t registers[n_contextRegisters]; 232#ifdef ARM_BASE_CP14_SAVE_AND_RESTORE 233 user_breakpoint_state_t breakpointState; 234#endif /* CONFIG_HARDWARE_DEBUG_API */ 235#ifdef CONFIG_HAVE_FPU 236 user_fpu_state_t fpuState; 237#endif /* CONFIG_HAVE_FPU */ 238}; 239typedef struct user_context user_context_t; 240 241unverified_compile_assert(registers_are_first_member_of_user_context, 242 OFFSETOF(user_context_t, registers) == 0) 243 244#ifdef ARM_BASE_CP14_SAVE_AND_RESTORE 245void Arch_initBreakpointContext(user_context_t *context); 246#endif 247 248static inline void Arch_initContext(user_context_t *context) 249{ 250 context->registers[CPSR] = CPSR_USER; 251#ifdef ARM_BASE_CP14_SAVE_AND_RESTORE 252 Arch_initBreakpointContext(context); 253#endif 254} 255 256#endif /* !__ASSEMBLER__ */ 257 258