1 /* 2 * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. 3 * Copyright 2002-2008, Axel Dörfler, axeld@pinc-software.de. 4 * Distributed under the terms of the MIT License. 5 * 6 * Copyright 2001, Travis Geiselbrecht. All rights reserved. 7 * Distributed under the terms of the NewOS License. 8 */ 9 10 11 #include <arch/thread.h> 12 13 #include <string.h> 14 15 #include <commpage.h> 16 #include <cpu.h> 17 #include <debug.h> 18 #include <kernel.h> 19 #include <ksignal.h> 20 #include <int.h> 21 #include <team.h> 22 #include <thread.h> 23 #include <tls.h> 24 #include <tracing.h> 25 #include <vm/vm_types.h> 26 #include <vm/VMAddressSpace.h> 27 28 #include "paging/X86PagingStructures.h" 29 #include "paging/X86VMTranslationMap.h" 30 31 32 //#define TRACE_ARCH_THREAD 33 #ifdef TRACE_ARCH_THREAD 34 # define TRACE(x...) dprintf(x) 35 #else 36 # define TRACE(x...) ; 37 #endif 38 39 40 #ifdef SYSCALL_TRACING 41 42 namespace SyscallTracing { 43 44 class RestartSyscall : public AbstractTraceEntry { 45 public: 46 RestartSyscall() 47 { 48 Initialized(); 49 } 50 51 virtual void AddDump(TraceOutput& out) 52 { 53 out.Print("syscall restart"); 54 } 55 }; 56 57 } 58 59 # define TSYSCALL(x) new(std::nothrow) SyscallTracing::x 60 61 #else 62 # define TSYSCALL(x) 63 #endif // SYSCALL_TRACING 64 65 66 extern "C" void x86_64_thread_entry(); 67 68 // Initial thread saved state. 69 static arch_thread sInitialState; 70 71 72 void 73 x86_restart_syscall(iframe* frame) 74 { 75 Thread* thread = thread_get_current_thread(); 76 77 atomic_and(&thread->flags, ~THREAD_FLAGS_RESTART_SYSCALL); 78 atomic_or(&thread->flags, THREAD_FLAGS_SYSCALL_RESTARTED); 79 80 // Get back the original system call number and modify the frame to 81 // re-execute the syscall instruction. 82 frame->ax = frame->orig_rax; 83 frame->ip -= 2; 84 85 TSYSCALL(RestartSyscall()); 86 } 87 88 89 void 90 x86_set_tls_context(Thread* thread) 91 { 92 // Set FS segment base address to the TLS segment. 93 x86_write_msr(IA32_MSR_FS_BASE, thread->user_local_storage); 94 } 95 96 97 static uint8* 98 get_signal_stack(Thread* thread, iframe* frame, struct sigaction* action) 99 { 100 // Use the alternate signal stack if we should and can. 101 if (thread->signal_stack_enabled 102 && (action->sa_flags & SA_ONSTACK) != 0 103 && (frame->user_sp < thread->signal_stack_base 104 || frame->user_sp >= thread->signal_stack_base 105 + thread->signal_stack_size)) { 106 return (uint8*)(thread->signal_stack_base + thread->signal_stack_size); 107 } 108 109 // We are going to use the stack that we are already on. We must not touch 110 // the red zone (128 byte area below the stack pointer, reserved for use 111 // by functions to store temporary data and guaranteed not to be modified 112 // by signal handlers). 113 return (uint8*)(frame->user_sp - 128); 114 } 115 116 117 // #pragma mark - 118 119 120 status_t 121 arch_thread_init(kernel_args* args) 122 { 123 // Save one global valid FPU state; it will be copied in the arch dependent 124 // part of each new thread. 125 asm volatile ("clts; fninit; fnclex;"); 126 x86_fxsave(sInitialState.fpu_state); 127 128 return B_OK; 129 } 130 131 132 status_t 133 arch_thread_init_thread_struct(Thread* thread) 134 { 135 // Copy the initial saved FPU state to the new thread. 136 memcpy(&thread->arch_info, &sInitialState, sizeof(arch_thread)); 137 138 // Initialise the current thread pointer. 139 thread->arch_info.thread = thread; 140 141 return B_OK; 142 } 143 144 145 /*! Prepares the given thread's kernel stack for executing its entry function. 146 147 \param thread The thread. 148 \param stack The usable bottom of the thread's kernel stack. 149 \param stackTop The usable top of the thread's kernel stack. 150 \param function The entry function the thread shall execute. 151 \param data Pointer to be passed to the entry function. 152 */ 153 void 154 arch_thread_init_kthread_stack(Thread* thread, void* _stack, void* _stackTop, 155 void (*function)(void*), const void* data) 156 { 157 addr_t* stackTop = (addr_t*)_stackTop; 158 159 TRACE("arch_thread_init_kthread_stack: stack top %p, function %p, data: " 160 "%p\n", _stackTop, function, data); 161 162 // Save the stack top for system call entry. 163 thread->arch_info.syscall_rsp = (uint64*)thread->kernel_stack_top; 164 165 // x86_64 uses registers for argument passing, first argument in RDI, 166 // however we don't save RDI on every context switch (there is no need 167 // for us to: it is not callee-save, and only contains the first argument 168 // to x86_context_switch). However, this presents a problem since we 169 // cannot store the argument for the entry function here. Therefore, we 170 // save the function address in R14 and the argument in R15 (which are 171 // restored), and then set up the stack to initially call a wrapper 172 // function which passes the argument correctly. 173 174 *--stackTop = 0; // Dummy return address. 175 *--stackTop = (addr_t)x86_64_thread_entry; // Wrapper function. 176 *--stackTop = (addr_t)data; // R15: argument. 177 *--stackTop = (addr_t)function; // R14: entry function. 178 *--stackTop = 0; // R13. 179 *--stackTop = 0; // R12. 180 *--stackTop = 0; // RBP. 181 *--stackTop = 0; // RBX. 182 183 // Save the stack position. 184 thread->arch_info.current_stack = stackTop; 185 } 186 187 188 void 189 arch_thread_dump_info(void* info) 190 { 191 arch_thread* thread = (arch_thread*)info; 192 193 kprintf("\trsp: %p\n", thread->current_stack); 194 kprintf("\tsyscall_rsp: %p\n", thread->syscall_rsp); 195 kprintf("\tuser_rsp: %p\n", thread->user_rsp); 196 kprintf("\tfpu_state at %p\n", thread->fpu_state); 197 } 198 199 200 /*! Sets up initial thread context and enters user space 201 */ 202 status_t 203 arch_thread_enter_userspace(Thread* thread, addr_t entry, void* args1, 204 void* args2) 205 { 206 addr_t stackTop = thread->user_stack_base + thread->user_stack_size; 207 208 TRACE("arch_thread_enter_userspace: entry %#lx, args %p %p, " 209 "stackTop %#lx\n", entry, args1, args2, stackTop); 210 211 // Copy the little stub that calls exit_thread() when the thread entry 212 // function returns. 213 // TODO: This will become a problem later if we want to support execute 214 // disable, the stack shouldn't really be executable. 215 size_t codeSize = (addr_t)x86_end_userspace_thread_exit 216 - (addr_t)x86_userspace_thread_exit; 217 stackTop -= codeSize; 218 if (user_memcpy((void*)stackTop, (const void*)&x86_userspace_thread_exit, 219 codeSize) != B_OK) 220 return B_BAD_ADDRESS; 221 222 // Copy the address of the stub to the top of the stack to act as the 223 // return address. 224 addr_t codeAddr = stackTop; 225 stackTop -= sizeof(codeAddr); 226 if (user_memcpy((void*)stackTop, (const void*)&codeAddr, sizeof(codeAddr)) 227 != B_OK) 228 return B_BAD_ADDRESS; 229 230 // Prepare the user iframe. 231 iframe frame = {}; 232 frame.type = IFRAME_TYPE_SYSCALL; 233 frame.si = (uint64)args2; 234 frame.di = (uint64)args1; 235 frame.ip = entry; 236 frame.cs = USER_CODE_SEG; 237 frame.flags = X86_EFLAGS_RESERVED1 | X86_EFLAGS_INTERRUPT 238 | (3 << X86_EFLAGS_IO_PRIVILEG_LEVEL_SHIFT); 239 frame.sp = stackTop; 240 frame.ss = USER_DATA_SEG; 241 242 // Return to userland. Never returns. 243 x86_initial_return_to_userland(thread, &frame); 244 245 return B_OK; 246 } 247 248 249 /*! Sets up the user iframe for invoking a signal handler. 250 251 The function fills in the remaining fields of the given \a signalFrameData, 252 copies it to the thread's userland stack (the one on which the signal shall 253 be handled), and sets up the user iframe so that when returning to userland 254 a wrapper function is executed that calls the user-defined signal handler. 255 When the signal handler returns, the wrapper function shall call the 256 "restore signal frame" syscall with the (possibly modified) signal frame 257 data. 258 259 The following fields of the \a signalFrameData structure still need to be 260 filled in: 261 - \c context.uc_stack: The stack currently used by the thread. 262 - \c context.uc_mcontext: The current userland state of the registers. 263 - \c syscall_restart_return_value: Architecture specific use. On x86_64 the 264 value of rax which is overwritten by the syscall return value. 265 266 Furthermore the function needs to set \c thread->user_signal_context to the 267 userland pointer to the \c ucontext_t on the user stack. 268 269 \param thread The current thread. 270 \param action The signal action specified for the signal to be handled. 271 \param signalFrameData A partially initialized structure of all the data 272 that need to be copied to userland. 273 \return \c B_OK on success, another error code, if something goes wrong. 274 */ 275 status_t 276 arch_setup_signal_frame(Thread* thread, struct sigaction* action, 277 struct signal_frame_data* signalFrameData) 278 { 279 iframe* frame = x86_get_current_iframe(); 280 if (!IFRAME_IS_USER(frame)) { 281 panic("arch_setup_signal_frame(): No user iframe!"); 282 return B_BAD_VALUE; 283 } 284 285 // Store the register state. 286 signalFrameData->context.uc_mcontext.rax = frame->ax; 287 signalFrameData->context.uc_mcontext.rbx = frame->bx; 288 signalFrameData->context.uc_mcontext.rcx = frame->cx; 289 signalFrameData->context.uc_mcontext.rdx = frame->dx; 290 signalFrameData->context.uc_mcontext.rdi = frame->di; 291 signalFrameData->context.uc_mcontext.rsi = frame->si; 292 signalFrameData->context.uc_mcontext.rbp = frame->bp; 293 signalFrameData->context.uc_mcontext.r8 = frame->r8; 294 signalFrameData->context.uc_mcontext.r9 = frame->r9; 295 signalFrameData->context.uc_mcontext.r10 = frame->r10; 296 signalFrameData->context.uc_mcontext.r11 = frame->r11; 297 signalFrameData->context.uc_mcontext.r12 = frame->r12; 298 signalFrameData->context.uc_mcontext.r13 = frame->r13; 299 signalFrameData->context.uc_mcontext.r14 = frame->r14; 300 signalFrameData->context.uc_mcontext.r15 = frame->r15; 301 signalFrameData->context.uc_mcontext.rsp = frame->user_sp; 302 signalFrameData->context.uc_mcontext.rip = frame->ip; 303 signalFrameData->context.uc_mcontext.rflags = frame->flags; 304 305 // Store the FPU state. There appears to be a bug in GCC where the aligned 306 // attribute on a structure is being ignored when the structure is allocated 307 // on the stack, so even if the fpu_state struct has aligned(16) it may not 308 // get aligned correctly. Instead, use the current thread's FPU save area 309 // and then memcpy() to the frame structure. 310 x86_fxsave(thread->arch_info.fpu_state); 311 memcpy((void*)&signalFrameData->context.uc_mcontext.fpu, 312 thread->arch_info.fpu_state, 313 sizeof(signalFrameData->context.uc_mcontext.fpu)); 314 315 // Fill in signalFrameData->context.uc_stack. 316 signal_get_user_stack(frame->user_sp, &signalFrameData->context.uc_stack); 317 318 // Store syscall_restart_return_value. 319 signalFrameData->syscall_restart_return_value = frame->orig_rax; 320 321 // Get the stack to use and copy the frame data to it. 322 uint8* userStack = get_signal_stack(thread, frame, action); 323 324 userStack -= sizeof(*signalFrameData); 325 signal_frame_data* userSignalFrameData = (signal_frame_data*)userStack; 326 327 if (user_memcpy(userSignalFrameData, signalFrameData, 328 sizeof(*signalFrameData)) != B_OK) { 329 return B_BAD_ADDRESS; 330 } 331 332 // Copy a return address to the stack so that backtraces will be correct. 333 userStack -= sizeof(frame->ip); 334 if (user_memcpy(userStack, &frame->ip, sizeof(frame->ip)) != B_OK) 335 return B_BAD_ADDRESS; 336 337 // Update Thread::user_signal_context, now that everything seems to have 338 // gone fine. 339 thread->user_signal_context = &userSignalFrameData->context; 340 341 // Set up the iframe to execute the signal handler wrapper on our prepared 342 // stack. First argument points to the frame data. 343 frame->user_sp = (addr_t)userStack; 344 frame->ip = ((addr_t*)USER_COMMPAGE_ADDR)[COMMPAGE_ENTRY_X86_SIGNAL_HANDLER]; 345 frame->di = (addr_t)userSignalFrameData; 346 347 return B_OK; 348 } 349 350 351 int64 352 arch_restore_signal_frame(struct signal_frame_data* signalFrameData) 353 { 354 iframe* frame = x86_get_current_iframe(); 355 356 frame->orig_rax = signalFrameData->syscall_restart_return_value; 357 frame->ax = signalFrameData->context.uc_mcontext.rax; 358 frame->bx = signalFrameData->context.uc_mcontext.rbx; 359 frame->cx = signalFrameData->context.uc_mcontext.rcx; 360 frame->dx = signalFrameData->context.uc_mcontext.rdx; 361 frame->di = signalFrameData->context.uc_mcontext.rdi; 362 frame->si = signalFrameData->context.uc_mcontext.rsi; 363 frame->bp = signalFrameData->context.uc_mcontext.rbp; 364 frame->r8 = signalFrameData->context.uc_mcontext.r8; 365 frame->r9 = signalFrameData->context.uc_mcontext.r9; 366 frame->r10 = signalFrameData->context.uc_mcontext.r10; 367 frame->r11 = signalFrameData->context.uc_mcontext.r11; 368 frame->r12 = signalFrameData->context.uc_mcontext.r12; 369 frame->r13 = signalFrameData->context.uc_mcontext.r13; 370 frame->r14 = signalFrameData->context.uc_mcontext.r14; 371 frame->r15 = signalFrameData->context.uc_mcontext.r15; 372 frame->user_sp = signalFrameData->context.uc_mcontext.rsp; 373 frame->ip = signalFrameData->context.uc_mcontext.rip; 374 frame->flags = (frame->flags & ~(uint64)X86_EFLAGS_USER_FLAGS) 375 | (signalFrameData->context.uc_mcontext.rflags & X86_EFLAGS_USER_FLAGS); 376 377 // Same as above, alignment may not be correct. Copy to thread and restore 378 // from there. 379 Thread* thread = thread_get_current_thread(); 380 memcpy(thread->arch_info.fpu_state, 381 (void*)&signalFrameData->context.uc_mcontext.fpu, 382 sizeof(thread->arch_info.fpu_state)); 383 x86_fxrstor(thread->arch_info.fpu_state); 384 385 // The syscall return code overwrites frame->ax with the return value of 386 // the syscall, need to return it here to ensure the correct value is 387 // restored. 388 return frame->ax; 389 } 390