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 #include <arch/types.h> 11 #include <util.h> 12 #include <assert.h> 13 14 #include <mode/machine/registerset.h> 15 16 /* Minimum hardware-enforced alignment needed for FPU state. */ 17 #define MIN_FPU_ALIGNMENT 64 18 19 #ifdef CONFIG_HARDWARE_DEBUG_API 20 /* X86 Debug register context */ 21 struct user_debug_state { 22 /* DR0-3 = Breakpoint linear address. 23 * DR4-5 = reserved or aliased, depending on value of CR4.DE. 24 * DR6 = Debug status register. 25 * DR7 = Debug control register. 26 */ 27 word_t dr[6]; 28 /* For each breakpoint currently being used by a thread, a bit in this 29 * bitfield is set, and for each breakpoint that is cleared, a bit is 30 * cleared. This enables an optimization: when a thread is being context- 31 * switched to, we can check to see if it's using breakpoints, and 32 * if so, we pop the whole register context. 33 * 34 * If it's not using breakpoints, we just pop all 0s into the ENABLED 35 * bits in DR7. 36 */ 37 uint32_t used_breakpoints_bf; 38 39 /* The API supports stepping N instructions forward, where N can 1..N. 40 * That feature is provided using this counter. Everytime a debug exception 41 * occurs, the kernel will decrement, then check the counter, and only when 42 * the counter is 0 will we deliver the fault to the userspace thread. 43 */ 44 word_t n_instructions; 45 46 /* This is part of the state machine that allows a thread to make 47 * syscalls while being single-stepped. Basically helps the kernel to 48 * disable single-stepping while executing the syscall, and then re-enable 49 * it just before returning from the syscall into userspace. 50 */ 51 bool_t single_step_enabled; 52 }; 53 typedef struct user_debug_state user_breakpoint_state_t; 54 #endif /* CONFIG_HARDWARE_DEBUG_API */ 55 56 /* X86 FPU context. */ 57 struct user_fpu_state { 58 uint8_t state[CONFIG_XSAVE_SIZE]; 59 }; 60 typedef struct user_fpu_state user_fpu_state_t; 61 62 /* X86 user-code context */ 63 struct user_context { 64 user_fpu_state_t fpuState; 65 word_t registers[n_contextRegisters]; 66 #if defined(ENABLE_SMP_SUPPORT) && defined(CONFIG_ARCH_IA32) 67 /* stored pointer to kernel stack used when kernel run in current TCB context. */ 68 word_t kernelSP; 69 #endif 70 #ifdef CONFIG_HARDWARE_DEBUG_API 71 user_breakpoint_state_t breakpointState; 72 #endif 73 }; 74 typedef struct user_context user_context_t; 75 76 void Mode_initContext(user_context_t *context); 77 void Arch_initContext(user_context_t *context); 78 word_t Mode_sanitiseRegister(register_t reg, word_t v); 79 80 /* Ensure FPU state is aligned within user context. */ 81 unverified_compile_assert(fpu_state_alignment_valid, 82 OFFSETOF(user_context_t, fpuState) % MIN_FPU_ALIGNMENT == 0) 83 84 #if defined(ENABLE_SMP_SUPPORT) && defined(CONFIG_ARCH_IA32) 85 /* Ensure kernelSP is the first member following the registers. */ 86 unverified_compile_assert( 87 kernelSP_alignment_valid, 88 OFFSETOF(user_context_t, kernelSP) - OFFSETOF(user_context_t, registers) == sizeof(word_t) * n_contextRegisters 89 ) 90 #endif 91 92