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 uintptr_t* stackTop = static_cast<uintptr_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 thread->arch_info.instruction_pointer 177 = reinterpret_cast<uintptr_t>(x86_64_thread_entry); 178 179 *--stackTop = uintptr_t(data); 180 *--stackTop = uintptr_t(function); 181 182 // Save the stack position. 183 thread->arch_info.current_stack = stackTop; 184 } 185 186 187 void 188 arch_thread_dump_info(void* info) 189 { 190 arch_thread* thread = (arch_thread*)info; 191 192 kprintf("\trsp: %p\n", thread->current_stack); 193 kprintf("\tsyscall_rsp: %p\n", thread->syscall_rsp); 194 kprintf("\tuser_rsp: %p\n", thread->user_rsp); 195 kprintf("\tfpu_state at %p\n", thread->fpu_state); 196 } 197 198 199 /*! Sets up initial thread context and enters user space 200 */ 201 status_t 202 arch_thread_enter_userspace(Thread* thread, addr_t entry, void* args1, 203 void* args2) 204 { 205 addr_t stackTop = thread->user_stack_base + thread->user_stack_size; 206 207 TRACE("arch_thread_enter_userspace: entry %#lx, args %p %p, " 208 "stackTop %#lx\n", entry, args1, args2, stackTop); 209 210 stackTop = arch_randomize_stack_pointer(stackTop); 211 212 // Copy the address of the stub that calls exit_thread() when the thread 213 // entry function returns to the top of the stack to act as the return 214 // address. The stub is inside commpage. 215 addr_t commPageAddress = (addr_t)thread->team->commpage_address; 216 addr_t codeAddr = ((addr_t*)commPageAddress)[COMMPAGE_ENTRY_X86_THREAD_EXIT] 217 + commPageAddress; 218 stackTop -= sizeof(codeAddr); 219 if (user_memcpy((void*)stackTop, (const void*)&codeAddr, sizeof(codeAddr)) 220 != B_OK) 221 return B_BAD_ADDRESS; 222 223 // Prepare the user iframe. 224 iframe frame = {}; 225 frame.type = IFRAME_TYPE_SYSCALL; 226 frame.si = (uint64)args2; 227 frame.di = (uint64)args1; 228 frame.ip = entry; 229 frame.cs = USER_CODE_SELECTOR; 230 frame.flags = X86_EFLAGS_RESERVED1 | X86_EFLAGS_INTERRUPT 231 | (3 << X86_EFLAGS_IO_PRIVILEG_LEVEL_SHIFT); 232 frame.sp = stackTop; 233 frame.ss = USER_DATA_SELECTOR; 234 235 // Return to userland. Never returns. 236 x86_initial_return_to_userland(thread, &frame); 237 238 return B_OK; 239 } 240 241 242 /*! Sets up the user iframe for invoking a signal handler. 243 244 The function fills in the remaining fields of the given \a signalFrameData, 245 copies it to the thread's userland stack (the one on which the signal shall 246 be handled), and sets up the user iframe so that when returning to userland 247 a wrapper function is executed that calls the user-defined signal handler. 248 When the signal handler returns, the wrapper function shall call the 249 "restore signal frame" syscall with the (possibly modified) signal frame 250 data. 251 252 The following fields of the \a signalFrameData structure still need to be 253 filled in: 254 - \c context.uc_stack: The stack currently used by the thread. 255 - \c context.uc_mcontext: The current userland state of the registers. 256 - \c syscall_restart_return_value: Architecture specific use. On x86_64 the 257 value of rax which is overwritten by the syscall return value. 258 259 Furthermore the function needs to set \c thread->user_signal_context to the 260 userland pointer to the \c ucontext_t on the user stack. 261 262 \param thread The current thread. 263 \param action The signal action specified for the signal to be handled. 264 \param signalFrameData A partially initialized structure of all the data 265 that need to be copied to userland. 266 \return \c B_OK on success, another error code, if something goes wrong. 267 */ 268 status_t 269 arch_setup_signal_frame(Thread* thread, struct sigaction* action, 270 struct signal_frame_data* signalFrameData) 271 { 272 iframe* frame = x86_get_current_iframe(); 273 if (!IFRAME_IS_USER(frame)) { 274 panic("arch_setup_signal_frame(): No user iframe!"); 275 return B_BAD_VALUE; 276 } 277 278 // Store the register state. 279 signalFrameData->context.uc_mcontext.rax = frame->ax; 280 signalFrameData->context.uc_mcontext.rbx = frame->bx; 281 signalFrameData->context.uc_mcontext.rcx = frame->cx; 282 signalFrameData->context.uc_mcontext.rdx = frame->dx; 283 signalFrameData->context.uc_mcontext.rdi = frame->di; 284 signalFrameData->context.uc_mcontext.rsi = frame->si; 285 signalFrameData->context.uc_mcontext.rbp = frame->bp; 286 signalFrameData->context.uc_mcontext.r8 = frame->r8; 287 signalFrameData->context.uc_mcontext.r9 = frame->r9; 288 signalFrameData->context.uc_mcontext.r10 = frame->r10; 289 signalFrameData->context.uc_mcontext.r11 = frame->r11; 290 signalFrameData->context.uc_mcontext.r12 = frame->r12; 291 signalFrameData->context.uc_mcontext.r13 = frame->r13; 292 signalFrameData->context.uc_mcontext.r14 = frame->r14; 293 signalFrameData->context.uc_mcontext.r15 = frame->r15; 294 signalFrameData->context.uc_mcontext.rsp = frame->user_sp; 295 signalFrameData->context.uc_mcontext.rip = frame->ip; 296 signalFrameData->context.uc_mcontext.rflags = frame->flags; 297 298 // Store the FPU state. There appears to be a bug in GCC where the aligned 299 // attribute on a structure is being ignored when the structure is allocated 300 // on the stack, so even if the fpu_state struct has aligned(16) it may not 301 // get aligned correctly. Instead, use the current thread's FPU save area 302 // and then memcpy() to the frame structure. 303 x86_fxsave(thread->arch_info.fpu_state); 304 memcpy((void*)&signalFrameData->context.uc_mcontext.fpu, 305 thread->arch_info.fpu_state, 306 sizeof(signalFrameData->context.uc_mcontext.fpu)); 307 308 // Fill in signalFrameData->context.uc_stack. 309 signal_get_user_stack(frame->user_sp, &signalFrameData->context.uc_stack); 310 311 // Store syscall_restart_return_value. 312 signalFrameData->syscall_restart_return_value = frame->orig_rax; 313 314 // Get the stack to use and copy the frame data to it. 315 uint8* userStack = get_signal_stack(thread, frame, action); 316 317 userStack -= sizeof(*signalFrameData); 318 signal_frame_data* userSignalFrameData = (signal_frame_data*)userStack; 319 320 if (user_memcpy(userSignalFrameData, signalFrameData, 321 sizeof(*signalFrameData)) != B_OK) { 322 return B_BAD_ADDRESS; 323 } 324 325 // Copy a return address to the stack so that backtraces will be correct. 326 userStack -= sizeof(frame->ip); 327 if (user_memcpy(userStack, &frame->ip, sizeof(frame->ip)) != B_OK) 328 return B_BAD_ADDRESS; 329 330 // Update Thread::user_signal_context, now that everything seems to have 331 // gone fine. 332 thread->user_signal_context = &userSignalFrameData->context; 333 334 // Set up the iframe to execute the signal handler wrapper on our prepared 335 // stack. First argument points to the frame data. 336 addr_t* commPageAddress = (addr_t*)thread->team->commpage_address; 337 frame->user_sp = (addr_t)userStack; 338 frame->ip = commPageAddress[COMMPAGE_ENTRY_X86_SIGNAL_HANDLER] 339 + (addr_t)commPageAddress; 340 frame->di = (addr_t)userSignalFrameData; 341 342 return B_OK; 343 } 344 345 346 int64 347 arch_restore_signal_frame(struct signal_frame_data* signalFrameData) 348 { 349 iframe* frame = x86_get_current_iframe(); 350 351 frame->orig_rax = signalFrameData->syscall_restart_return_value; 352 frame->ax = signalFrameData->context.uc_mcontext.rax; 353 frame->bx = signalFrameData->context.uc_mcontext.rbx; 354 frame->cx = signalFrameData->context.uc_mcontext.rcx; 355 frame->dx = signalFrameData->context.uc_mcontext.rdx; 356 frame->di = signalFrameData->context.uc_mcontext.rdi; 357 frame->si = signalFrameData->context.uc_mcontext.rsi; 358 frame->bp = signalFrameData->context.uc_mcontext.rbp; 359 frame->r8 = signalFrameData->context.uc_mcontext.r8; 360 frame->r9 = signalFrameData->context.uc_mcontext.r9; 361 frame->r10 = signalFrameData->context.uc_mcontext.r10; 362 frame->r11 = signalFrameData->context.uc_mcontext.r11; 363 frame->r12 = signalFrameData->context.uc_mcontext.r12; 364 frame->r13 = signalFrameData->context.uc_mcontext.r13; 365 frame->r14 = signalFrameData->context.uc_mcontext.r14; 366 frame->r15 = signalFrameData->context.uc_mcontext.r15; 367 frame->user_sp = signalFrameData->context.uc_mcontext.rsp; 368 frame->ip = signalFrameData->context.uc_mcontext.rip; 369 frame->flags = (frame->flags & ~(uint64)X86_EFLAGS_USER_FLAGS) 370 | (signalFrameData->context.uc_mcontext.rflags & X86_EFLAGS_USER_FLAGS); 371 372 // Same as above, alignment may not be correct. Copy to thread and restore 373 // from there. 374 Thread* thread = thread_get_current_thread(); 375 memcpy(thread->arch_info.fpu_state, 376 (void*)&signalFrameData->context.uc_mcontext.fpu, 377 sizeof(thread->arch_info.fpu_state)); 378 x86_fxrstor(thread->arch_info.fpu_state); 379 380 // The syscall return code overwrites frame->ax with the return value of 381 // the syscall, need to return it here to ensure the correct value is 382 // restored. 383 return frame->ax; 384 } 385