1 /* 2 * Copyright 2018, Jérôme Duval, jerome.duval@gmail.com. 3 * Copyright 2012, Alex Smith, alex@alex-smith.me.uk. 4 * Copyright 2002-2008, Axel Dörfler, axeld@pinc-software.de. 5 * Distributed under the terms of the MIT License. 6 * 7 * Copyright 2001, Travis Geiselbrecht. All rights reserved. 8 * Distributed under the terms of the NewOS License. 9 */ 10 11 12 #include <arch/thread.h> 13 14 #include <string.h> 15 16 #include <commpage.h> 17 #include <cpu.h> 18 #include <debug.h> 19 #include <kernel.h> 20 #include <ksignal.h> 21 #include <int.h> 22 #include <team.h> 23 #include <thread.h> 24 #include <tls.h> 25 #include <tracing.h> 26 #include <util/Random.h> 27 #include <vm/vm_types.h> 28 #include <vm/VMAddressSpace.h> 29 30 #include "paging/X86PagingStructures.h" 31 #include "paging/X86VMTranslationMap.h" 32 33 34 //#define TRACE_ARCH_THREAD 35 #ifdef TRACE_ARCH_THREAD 36 # define TRACE(x...) dprintf(x) 37 #else 38 # define TRACE(x...) ; 39 #endif 40 41 42 #ifdef SYSCALL_TRACING 43 44 namespace SyscallTracing { 45 46 class RestartSyscall : public AbstractTraceEntry { 47 public: 48 RestartSyscall() 49 { 50 Initialized(); 51 } 52 53 virtual void AddDump(TraceOutput& out) 54 { 55 out.Print("syscall restart"); 56 } 57 }; 58 59 } 60 61 # define TSYSCALL(x) new(std::nothrow) SyscallTracing::x 62 63 #else 64 # define TSYSCALL(x) 65 #endif // SYSCALL_TRACING 66 67 68 extern "C" void x86_64_thread_entry(); 69 70 // Initial thread saved state. 71 static arch_thread sInitialState; 72 73 74 void 75 x86_restart_syscall(iframe* frame) 76 { 77 Thread* thread = thread_get_current_thread(); 78 79 atomic_and(&thread->flags, ~THREAD_FLAGS_RESTART_SYSCALL); 80 atomic_or(&thread->flags, THREAD_FLAGS_SYSCALL_RESTARTED); 81 82 // Get back the original system call number and modify the frame to 83 // re-execute the syscall instruction. 84 frame->ax = frame->orig_rax; 85 frame->ip -= 2; 86 87 TSYSCALL(RestartSyscall()); 88 } 89 90 91 void 92 x86_set_tls_context(Thread* thread) 93 { 94 // Set FS segment base address to the TLS segment. 95 x86_write_msr(IA32_MSR_FS_BASE, thread->user_local_storage); 96 } 97 98 99 static addr_t 100 arch_randomize_stack_pointer(addr_t value) 101 { 102 static_assert(MAX_RANDOM_VALUE >= B_PAGE_SIZE - 1, 103 "randomization range is too big"); 104 value -= random_value() & (B_PAGE_SIZE - 1); 105 return (value & ~addr_t(0xf)) - 8; 106 // This means, result % 16 == 8, which is what rsp should adhere to 107 // when a function is entered for the stack to be considered aligned to 108 // 16 byte. 109 } 110 111 112 static uint8* 113 get_signal_stack(Thread* thread, iframe* frame, struct sigaction* action, 114 size_t spaceNeeded) 115 { 116 // Use the alternate signal stack if we should and can. 117 if (thread->signal_stack_enabled 118 && (action->sa_flags & SA_ONSTACK) != 0 119 && (frame->user_sp < thread->signal_stack_base 120 || frame->user_sp >= thread->signal_stack_base 121 + thread->signal_stack_size)) { 122 addr_t stackTop = thread->signal_stack_base + thread->signal_stack_size; 123 return (uint8*)arch_randomize_stack_pointer(stackTop - spaceNeeded); 124 } 125 126 // We are going to use the stack that we are already on. We must not touch 127 // the red zone (128 byte area below the stack pointer, reserved for use 128 // by functions to store temporary data and guaranteed not to be modified 129 // by signal handlers). 130 return (uint8*)((frame->user_sp - 128 - spaceNeeded) & ~addr_t(0xf)) - 8; 131 // align stack pointer (cf. arch_randomize_stack_pointer()) 132 } 133 134 135 // #pragma mark - 136 137 138 status_t 139 arch_thread_init(kernel_args* args) 140 { 141 // Save one global valid FPU state; it will be copied in the arch dependent 142 // part of each new thread. 143 asm volatile ( 144 "clts;" \ 145 "fninit;" \ 146 "fnclex;" \ 147 "fxsave %0;" 148 : "=m" (sInitialState.fpu_state)); 149 return B_OK; 150 } 151 152 153 status_t 154 arch_thread_init_thread_struct(Thread* thread) 155 { 156 // Copy the initial saved FPU state to the new thread. 157 memcpy(&thread->arch_info, &sInitialState, sizeof(arch_thread)); 158 159 // Initialise the current thread pointer. 160 thread->arch_info.thread = thread; 161 162 return B_OK; 163 } 164 165 166 /*! Prepares the given thread's kernel stack for executing its entry function. 167 168 \param thread The thread. 169 \param stack The usable bottom of the thread's kernel stack. 170 \param stackTop The usable top of the thread's kernel stack. 171 \param function The entry function the thread shall execute. 172 \param data Pointer to be passed to the entry function. 173 */ 174 void 175 arch_thread_init_kthread_stack(Thread* thread, void* _stack, void* _stackTop, 176 void (*function)(void*), const void* data) 177 { 178 uintptr_t* stackTop = static_cast<uintptr_t*>(_stackTop); 179 180 TRACE("arch_thread_init_kthread_stack: stack top %p, function %p, data: " 181 "%p\n", _stackTop, function, data); 182 183 // Save the stack top for system call entry. 184 thread->arch_info.syscall_rsp = (uint64*)thread->kernel_stack_top; 185 186 thread->arch_info.instruction_pointer 187 = reinterpret_cast<uintptr_t>(x86_64_thread_entry); 188 189 *--stackTop = uintptr_t(data); 190 *--stackTop = uintptr_t(function); 191 192 // Save the stack position. 193 thread->arch_info.current_stack = stackTop; 194 } 195 196 197 void 198 arch_thread_dump_info(void* info) 199 { 200 arch_thread* thread = (arch_thread*)info; 201 202 kprintf("\trsp: %p\n", thread->current_stack); 203 kprintf("\tsyscall_rsp: %p\n", thread->syscall_rsp); 204 kprintf("\tuser_rsp: %p\n", thread->user_rsp); 205 kprintf("\tfpu_state at %p\n", thread->fpu_state); 206 } 207 208 209 /*! Sets up initial thread context and enters user space 210 */ 211 status_t 212 arch_thread_enter_userspace(Thread* thread, addr_t entry, void* args1, 213 void* args2) 214 { 215 addr_t stackTop = thread->user_stack_base + thread->user_stack_size; 216 addr_t codeAddr; 217 218 TRACE("arch_thread_enter_userspace: entry %#lx, args %p %p, " 219 "stackTop %#lx\n", entry, args1, args2, stackTop); 220 221 stackTop = arch_randomize_stack_pointer(stackTop - sizeof(codeAddr)); 222 223 // Copy the address of the stub that calls exit_thread() when the thread 224 // entry function returns to the top of the stack to act as the return 225 // address. The stub is inside commpage. 226 addr_t commPageAddress = (addr_t)thread->team->commpage_address; 227 set_ac(); 228 codeAddr = ((addr_t*)commPageAddress)[COMMPAGE_ENTRY_X86_THREAD_EXIT] 229 + commPageAddress; 230 clear_ac(); 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_SELECTOR; 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_SELECTOR; 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 if (frame->fpu != nullptr) { 311 memcpy((void*)&signalFrameData->context.uc_mcontext.fpu, frame->fpu, 312 sizeof(signalFrameData->context.uc_mcontext.fpu)); 313 } else { 314 memcpy((void*)&signalFrameData->context.uc_mcontext.fpu, 315 sInitialState.fpu_state, 316 sizeof(signalFrameData->context.uc_mcontext.fpu)); 317 } 318 319 // Fill in signalFrameData->context.uc_stack. 320 signal_get_user_stack(frame->user_sp, &signalFrameData->context.uc_stack); 321 322 // Store syscall_restart_return_value. 323 signalFrameData->syscall_restart_return_value = frame->orig_rax; 324 325 // Get the stack to use and copy the frame data to it. 326 uint8* userStack = get_signal_stack(thread, frame, action, 327 sizeof(*signalFrameData) + sizeof(frame->ip)); 328 329 signal_frame_data* userSignalFrameData 330 = (signal_frame_data*)(userStack + sizeof(frame->ip)); 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 if (user_memcpy(userStack, &frame->ip, sizeof(frame->ip)) != B_OK) 339 return B_BAD_ADDRESS; 340 341 // Update Thread::user_signal_context, now that everything seems to have 342 // gone fine. 343 thread->user_signal_context = &userSignalFrameData->context; 344 345 // Set up the iframe to execute the signal handler wrapper on our prepared 346 // stack. First argument points to the frame data. 347 addr_t* commPageAddress = (addr_t*)thread->team->commpage_address; 348 frame->user_sp = (addr_t)userStack; 349 set_ac(); 350 frame->ip = commPageAddress[COMMPAGE_ENTRY_X86_SIGNAL_HANDLER] 351 + (addr_t)commPageAddress; 352 clear_ac(); 353 frame->di = (addr_t)userSignalFrameData; 354 355 return B_OK; 356 } 357 358 359 int64 360 arch_restore_signal_frame(struct signal_frame_data* signalFrameData) 361 { 362 iframe* frame = x86_get_current_iframe(); 363 364 frame->orig_rax = signalFrameData->syscall_restart_return_value; 365 frame->ax = signalFrameData->context.uc_mcontext.rax; 366 frame->bx = signalFrameData->context.uc_mcontext.rbx; 367 frame->cx = signalFrameData->context.uc_mcontext.rcx; 368 frame->dx = signalFrameData->context.uc_mcontext.rdx; 369 frame->di = signalFrameData->context.uc_mcontext.rdi; 370 frame->si = signalFrameData->context.uc_mcontext.rsi; 371 frame->bp = signalFrameData->context.uc_mcontext.rbp; 372 frame->r8 = signalFrameData->context.uc_mcontext.r8; 373 frame->r9 = signalFrameData->context.uc_mcontext.r9; 374 frame->r10 = signalFrameData->context.uc_mcontext.r10; 375 frame->r11 = signalFrameData->context.uc_mcontext.r11; 376 frame->r12 = signalFrameData->context.uc_mcontext.r12; 377 frame->r13 = signalFrameData->context.uc_mcontext.r13; 378 frame->r14 = signalFrameData->context.uc_mcontext.r14; 379 frame->r15 = signalFrameData->context.uc_mcontext.r15; 380 frame->user_sp = signalFrameData->context.uc_mcontext.rsp; 381 frame->ip = signalFrameData->context.uc_mcontext.rip; 382 frame->flags = (frame->flags & ~(uint64)X86_EFLAGS_USER_FLAGS) 383 | (signalFrameData->context.uc_mcontext.rflags & X86_EFLAGS_USER_FLAGS); 384 385 Thread* thread = thread_get_current_thread(); 386 387 memcpy(thread->arch_info.fpu_state, 388 (void*)&signalFrameData->context.uc_mcontext.fpu, 389 sizeof(thread->arch_info.fpu_state)); 390 frame->fpu = &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