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 "randomization range is too big"); 103 value -= random_value() & (B_PAGE_SIZE - 1); 104 return value & ~addr_t(0xf); 105 } 106 107 108 static uint8* 109 get_signal_stack(Thread* thread, iframe* frame, struct sigaction* action) 110 { 111 // Use the alternate signal stack if we should and can. 112 if (thread->signal_stack_enabled 113 && (action->sa_flags & SA_ONSTACK) != 0 114 && (frame->user_sp < thread->signal_stack_base 115 || frame->user_sp >= thread->signal_stack_base 116 + thread->signal_stack_size)) { 117 addr_t stackTop = thread->signal_stack_base + thread->signal_stack_size; 118 return (uint8*)arch_randomize_stack_pointer(stackTop); 119 } 120 121 // We are going to use the stack that we are already on. We must not touch 122 // the red zone (128 byte area below the stack pointer, reserved for use 123 // by functions to store temporary data and guaranteed not to be modified 124 // by signal handlers). 125 return (uint8*)(frame->user_sp - 128); 126 } 127 128 129 // #pragma mark - 130 131 132 status_t 133 arch_thread_init(kernel_args* args) 134 { 135 // Save one global valid FPU state; it will be copied in the arch dependent 136 // part of each new thread. 137 asm volatile ( 138 "clts;" \ 139 "fninit;" \ 140 "fnclex;" \ 141 "fxsave %0;" 142 : "=m" (sInitialState.fpu_state)); 143 return B_OK; 144 } 145 146 147 status_t 148 arch_thread_init_thread_struct(Thread* thread) 149 { 150 // Copy the initial saved FPU state to the new thread. 151 memcpy(&thread->arch_info, &sInitialState, sizeof(arch_thread)); 152 153 // Initialise the current thread pointer. 154 thread->arch_info.thread = thread; 155 156 return B_OK; 157 } 158 159 160 /*! Prepares the given thread's kernel stack for executing its entry function. 161 162 \param thread The thread. 163 \param stack The usable bottom of the thread's kernel stack. 164 \param stackTop The usable top of the thread's kernel stack. 165 \param function The entry function the thread shall execute. 166 \param data Pointer to be passed to the entry function. 167 */ 168 void 169 arch_thread_init_kthread_stack(Thread* thread, void* _stack, void* _stackTop, 170 void (*function)(void*), const void* data) 171 { 172 uintptr_t* stackTop = static_cast<uintptr_t*>(_stackTop); 173 174 TRACE("arch_thread_init_kthread_stack: stack top %p, function %p, data: " 175 "%p\n", _stackTop, function, data); 176 177 // Save the stack top for system call entry. 178 thread->arch_info.syscall_rsp = (uint64*)thread->kernel_stack_top; 179 180 thread->arch_info.instruction_pointer 181 = reinterpret_cast<uintptr_t>(x86_64_thread_entry); 182 183 *--stackTop = uintptr_t(data); 184 *--stackTop = uintptr_t(function); 185 186 // Save the stack position. 187 thread->arch_info.current_stack = stackTop; 188 } 189 190 191 void 192 arch_thread_dump_info(void* info) 193 { 194 arch_thread* thread = (arch_thread*)info; 195 196 kprintf("\trsp: %p\n", thread->current_stack); 197 kprintf("\tsyscall_rsp: %p\n", thread->syscall_rsp); 198 kprintf("\tuser_rsp: %p\n", thread->user_rsp); 199 kprintf("\tfpu_state at %p\n", thread->fpu_state); 200 } 201 202 203 /*! Sets up initial thread context and enters user space 204 */ 205 status_t 206 arch_thread_enter_userspace(Thread* thread, addr_t entry, void* args1, 207 void* args2) 208 { 209 addr_t stackTop = thread->user_stack_base + thread->user_stack_size; 210 211 TRACE("arch_thread_enter_userspace: entry %#lx, args %p %p, " 212 "stackTop %#lx\n", entry, args1, args2, stackTop); 213 214 stackTop = arch_randomize_stack_pointer(stackTop); 215 216 // Copy the address of the stub that calls exit_thread() when the thread 217 // entry function returns to the top of the stack to act as the return 218 // address. The stub is inside commpage. 219 addr_t commPageAddress = (addr_t)thread->team->commpage_address; 220 addr_t codeAddr = ((addr_t*)commPageAddress)[COMMPAGE_ENTRY_X86_THREAD_EXIT] 221 + commPageAddress; 222 stackTop -= sizeof(codeAddr); 223 if (user_memcpy((void*)stackTop, (const void*)&codeAddr, sizeof(codeAddr)) 224 != B_OK) 225 return B_BAD_ADDRESS; 226 227 // Prepare the user iframe. 228 iframe frame = {}; 229 frame.type = IFRAME_TYPE_SYSCALL; 230 frame.si = (uint64)args2; 231 frame.di = (uint64)args1; 232 frame.ip = entry; 233 frame.cs = USER_CODE_SELECTOR; 234 frame.flags = X86_EFLAGS_RESERVED1 | X86_EFLAGS_INTERRUPT 235 | (3 << X86_EFLAGS_IO_PRIVILEG_LEVEL_SHIFT); 236 frame.sp = stackTop; 237 frame.ss = USER_DATA_SELECTOR; 238 239 // Return to userland. Never returns. 240 x86_initial_return_to_userland(thread, &frame); 241 242 return B_OK; 243 } 244 245 246 /*! Sets up the user iframe for invoking a signal handler. 247 248 The function fills in the remaining fields of the given \a signalFrameData, 249 copies it to the thread's userland stack (the one on which the signal shall 250 be handled), and sets up the user iframe so that when returning to userland 251 a wrapper function is executed that calls the user-defined signal handler. 252 When the signal handler returns, the wrapper function shall call the 253 "restore signal frame" syscall with the (possibly modified) signal frame 254 data. 255 256 The following fields of the \a signalFrameData structure still need to be 257 filled in: 258 - \c context.uc_stack: The stack currently used by the thread. 259 - \c context.uc_mcontext: The current userland state of the registers. 260 - \c syscall_restart_return_value: Architecture specific use. On x86_64 the 261 value of rax which is overwritten by the syscall return value. 262 263 Furthermore the function needs to set \c thread->user_signal_context to the 264 userland pointer to the \c ucontext_t on the user stack. 265 266 \param thread The current thread. 267 \param action The signal action specified for the signal to be handled. 268 \param signalFrameData A partially initialized structure of all the data 269 that need to be copied to userland. 270 \return \c B_OK on success, another error code, if something goes wrong. 271 */ 272 status_t 273 arch_setup_signal_frame(Thread* thread, struct sigaction* action, 274 struct signal_frame_data* signalFrameData) 275 { 276 iframe* frame = x86_get_current_iframe(); 277 if (!IFRAME_IS_USER(frame)) { 278 panic("arch_setup_signal_frame(): No user iframe!"); 279 return B_BAD_VALUE; 280 } 281 282 // Store the register state. 283 signalFrameData->context.uc_mcontext.rax = frame->ax; 284 signalFrameData->context.uc_mcontext.rbx = frame->bx; 285 signalFrameData->context.uc_mcontext.rcx = frame->cx; 286 signalFrameData->context.uc_mcontext.rdx = frame->dx; 287 signalFrameData->context.uc_mcontext.rdi = frame->di; 288 signalFrameData->context.uc_mcontext.rsi = frame->si; 289 signalFrameData->context.uc_mcontext.rbp = frame->bp; 290 signalFrameData->context.uc_mcontext.r8 = frame->r8; 291 signalFrameData->context.uc_mcontext.r9 = frame->r9; 292 signalFrameData->context.uc_mcontext.r10 = frame->r10; 293 signalFrameData->context.uc_mcontext.r11 = frame->r11; 294 signalFrameData->context.uc_mcontext.r12 = frame->r12; 295 signalFrameData->context.uc_mcontext.r13 = frame->r13; 296 signalFrameData->context.uc_mcontext.r14 = frame->r14; 297 signalFrameData->context.uc_mcontext.r15 = frame->r15; 298 signalFrameData->context.uc_mcontext.rsp = frame->user_sp; 299 signalFrameData->context.uc_mcontext.rip = frame->ip; 300 signalFrameData->context.uc_mcontext.rflags = frame->flags; 301 302 if (frame->fpu != nullptr) { 303 memcpy((void*)&signalFrameData->context.uc_mcontext.fpu, frame->fpu, 304 sizeof(signalFrameData->context.uc_mcontext.fpu)); 305 } else { 306 memcpy((void*)&signalFrameData->context.uc_mcontext.fpu, 307 sInitialState.fpu_state, 308 sizeof(signalFrameData->context.uc_mcontext.fpu)); 309 } 310 311 // Fill in signalFrameData->context.uc_stack. 312 signal_get_user_stack(frame->user_sp, &signalFrameData->context.uc_stack); 313 314 // Store syscall_restart_return_value. 315 signalFrameData->syscall_restart_return_value = frame->orig_rax; 316 317 // Get the stack to use and copy the frame data to it. 318 uint8* userStack = get_signal_stack(thread, frame, action); 319 320 userStack -= sizeof(*signalFrameData); 321 signal_frame_data* userSignalFrameData = (signal_frame_data*)userStack; 322 323 if (user_memcpy(userSignalFrameData, signalFrameData, 324 sizeof(*signalFrameData)) != B_OK) { 325 return B_BAD_ADDRESS; 326 } 327 328 // Copy a return address to the stack so that backtraces will be correct. 329 userStack -= sizeof(frame->ip); 330 if (user_memcpy(userStack, &frame->ip, sizeof(frame->ip)) != B_OK) 331 return B_BAD_ADDRESS; 332 333 // Update Thread::user_signal_context, now that everything seems to have 334 // gone fine. 335 thread->user_signal_context = &userSignalFrameData->context; 336 337 // Set up the iframe to execute the signal handler wrapper on our prepared 338 // stack. First argument points to the frame data. 339 addr_t* commPageAddress = (addr_t*)thread->team->commpage_address; 340 frame->user_sp = (addr_t)userStack; 341 frame->ip = commPageAddress[COMMPAGE_ENTRY_X86_SIGNAL_HANDLER] 342 + (addr_t)commPageAddress; 343 frame->di = (addr_t)userSignalFrameData; 344 345 return B_OK; 346 } 347 348 349 int64 350 arch_restore_signal_frame(struct signal_frame_data* signalFrameData) 351 { 352 iframe* frame = x86_get_current_iframe(); 353 354 frame->orig_rax = signalFrameData->syscall_restart_return_value; 355 frame->ax = signalFrameData->context.uc_mcontext.rax; 356 frame->bx = signalFrameData->context.uc_mcontext.rbx; 357 frame->cx = signalFrameData->context.uc_mcontext.rcx; 358 frame->dx = signalFrameData->context.uc_mcontext.rdx; 359 frame->di = signalFrameData->context.uc_mcontext.rdi; 360 frame->si = signalFrameData->context.uc_mcontext.rsi; 361 frame->bp = signalFrameData->context.uc_mcontext.rbp; 362 frame->r8 = signalFrameData->context.uc_mcontext.r8; 363 frame->r9 = signalFrameData->context.uc_mcontext.r9; 364 frame->r10 = signalFrameData->context.uc_mcontext.r10; 365 frame->r11 = signalFrameData->context.uc_mcontext.r11; 366 frame->r12 = signalFrameData->context.uc_mcontext.r12; 367 frame->r13 = signalFrameData->context.uc_mcontext.r13; 368 frame->r14 = signalFrameData->context.uc_mcontext.r14; 369 frame->r15 = signalFrameData->context.uc_mcontext.r15; 370 frame->user_sp = signalFrameData->context.uc_mcontext.rsp; 371 frame->ip = signalFrameData->context.uc_mcontext.rip; 372 frame->flags = (frame->flags & ~(uint64)X86_EFLAGS_USER_FLAGS) 373 | (signalFrameData->context.uc_mcontext.rflags & X86_EFLAGS_USER_FLAGS); 374 375 Thread* thread = thread_get_current_thread(); 376 377 memcpy(thread->arch_info.fpu_state, 378 (void*)&signalFrameData->context.uc_mcontext.fpu, 379 sizeof(thread->arch_info.fpu_state)); 380 frame->fpu = &thread->arch_info.fpu_state; 381 382 // The syscall return code overwrites frame->ax with the return value of 383 // the syscall, need to return it here to ensure the correct value is 384 // restored. 385 return frame->ax; 386 } 387