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