1 /* 2 * Copyright 2002-2008, Axel Dörfler, axeld@pinc-software.de. 3 * Distributed under the terms of the MIT License. 4 * 5 * Copyright 2001, Travis Geiselbrecht. All rights reserved. 6 * Distributed under the terms of the NewOS License. 7 */ 8 9 10 #include <arch/thread.h> 11 12 #include <string.h> 13 14 #include <arch/user_debugger.h> 15 #include <arch_cpu.h> 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/AutoLock.h> 27 #include <util/Random.h> 28 #include <vm/vm_types.h> 29 #include <vm/VMAddressSpace.h> 30 31 #include "paging/X86PagingStructures.h" 32 #include "paging/X86VMTranslationMap.h" 33 #include "x86_signals.h" 34 35 36 //#define TRACE_ARCH_THREAD 37 #ifdef TRACE_ARCH_THREAD 38 # define TRACE(x) dprintf x 39 #else 40 # define TRACE(x) ; 41 #endif 42 43 44 #ifdef SYSCALL_TRACING 45 46 namespace SyscallTracing { 47 48 class RestartSyscall : public AbstractTraceEntry { 49 public: 50 RestartSyscall() 51 { 52 Initialized(); 53 } 54 55 virtual void AddDump(TraceOutput& out) 56 { 57 out.Print("syscall restart"); 58 } 59 }; 60 61 } 62 63 # define TSYSCALL(x) new(std::nothrow) SyscallTracing::x 64 65 #else 66 # define TSYSCALL(x) 67 #endif // SYSCALL_TRACING 68 69 70 // from arch_cpu.cpp 71 extern bool gHasSSE; 72 73 static struct arch_thread sInitialState _ALIGNED(16); 74 // the fpu_state must be aligned on a 16 byte boundary, so that fxsave can use it 75 76 77 static inline void 78 set_fs_register(uint32 segment) 79 { 80 asm("movl %0,%%fs" :: "r" (segment)); 81 } 82 83 84 void 85 x86_restart_syscall(struct iframe* frame) 86 { 87 Thread* thread = thread_get_current_thread(); 88 89 atomic_and(&thread->flags, ~THREAD_FLAGS_RESTART_SYSCALL); 90 atomic_or(&thread->flags, THREAD_FLAGS_SYSCALL_RESTARTED); 91 92 frame->ax = frame->orig_eax; 93 frame->dx = frame->orig_edx; 94 frame->ip -= 2; 95 // undoes the "int $99"/"sysenter"/"syscall" instruction 96 // (so that it'll be executed again) 97 98 TSYSCALL(RestartSyscall()); 99 } 100 101 102 void 103 x86_set_tls_context(Thread *thread) 104 { 105 segment_descriptor* gdt = get_gdt(smp_get_current_cpu()); 106 set_segment_descriptor_base(&gdt[USER_TLS_SEGMENT], 107 thread->user_local_storage); 108 set_fs_register((USER_TLS_SEGMENT << 3) | DPL_USER); 109 } 110 111 112 static addr_t 113 arch_randomize_stack_pointer(addr_t value) 114 { 115 STATIC_ASSERT(MAX_RANDOM_VALUE >= B_PAGE_SIZE - 1); 116 value -= random_value() & (B_PAGE_SIZE - 1); 117 return (value & ~addr_t(0xf)) - 4; 118 // This means, result % 16 == 12, which is what esp should adhere to 119 // when a function is entered for the stack to be considered aligned to 120 // 16 byte. 121 } 122 123 124 static uint8* 125 get_signal_stack(Thread* thread, struct iframe* frame, struct sigaction* action, 126 size_t spaceNeeded) 127 { 128 // use the alternate signal stack if we should and can 129 if (thread->signal_stack_enabled 130 && (action->sa_flags & SA_ONSTACK) != 0 131 && (frame->user_sp < thread->signal_stack_base 132 || frame->user_sp >= thread->signal_stack_base 133 + thread->signal_stack_size)) { 134 addr_t stackTop = thread->signal_stack_base + thread->signal_stack_size; 135 return (uint8*)arch_randomize_stack_pointer(stackTop - spaceNeeded); 136 } 137 138 return (uint8*)((frame->user_sp - spaceNeeded) & ~addr_t(0xf)) - 4; 139 // align stack pointer (cf. arch_randomize_stack_pointer()) 140 } 141 142 143 // #pragma mark - 144 145 146 status_t 147 arch_thread_init(struct kernel_args *args) 148 { 149 // save one global valid FPU state; it will be copied in the arch dependent 150 // part of each new thread 151 152 asm volatile ("clts; fninit; fnclex;"); 153 if (gHasSSE) 154 x86_fxsave(sInitialState.fpu_state); 155 else 156 x86_fnsave(sInitialState.fpu_state); 157 158 return B_OK; 159 } 160 161 162 status_t 163 arch_thread_init_thread_struct(Thread *thread) 164 { 165 // set up an initial state (stack & fpu) 166 memcpy(&thread->arch_info, &sInitialState, sizeof(struct arch_thread)); 167 return B_OK; 168 } 169 170 171 /*! Prepares the given thread's kernel stack for executing its entry function. 172 173 \param thread The thread. 174 \param stack The usable bottom of the thread's kernel stack. 175 \param stackTop The usable top of the thread's kernel stack. 176 \param function The entry function the thread shall execute. 177 \param data Pointer to be passed to the entry function. 178 */ 179 void 180 arch_thread_init_kthread_stack(Thread* thread, void* _stack, void* _stackTop, 181 void (*function)(void*), const void* data) 182 { 183 addr_t* stackTop = (addr_t*)_stackTop; 184 185 TRACE(("arch_thread_init_kthread_stack: stack top %p, function %p, data: " 186 "%p\n", stackTop, function, data)); 187 188 // push the function argument, a pointer to the data 189 *--stackTop = (addr_t)data; 190 191 // push a dummy return address for the function 192 *--stackTop = 0; 193 194 // push the function address -- that's the return address used after the 195 // context switch 196 *--stackTop = (addr_t)function; 197 198 // simulate pushad as done by x86_context_switch() 199 for (int i = 0; i < 8; i++) 200 *--stackTop = 0; 201 202 // save the stack position 203 thread->arch_info.current_stack.esp = stackTop; 204 thread->arch_info.current_stack.ss = (addr_t*)KERNEL_DATA_SELECTOR; 205 } 206 207 208 void 209 arch_thread_dump_info(void *info) 210 { 211 struct arch_thread *at = (struct arch_thread *)info; 212 213 kprintf("\tesp: %p\n", at->current_stack.esp); 214 kprintf("\tss: %p\n", at->current_stack.ss); 215 kprintf("\tfpu_state at %p\n", at->fpu_state); 216 } 217 218 219 /*! Sets up initial thread context and enters user space 220 */ 221 status_t 222 arch_thread_enter_userspace(Thread* thread, addr_t entry, void* args1, 223 void* args2) 224 { 225 addr_t stackTop = thread->user_stack_base + thread->user_stack_size; 226 uint32 args[3]; 227 228 TRACE(("arch_thread_enter_userspace: entry 0x%lx, args %p %p, " 229 "ustack_top 0x%lx\n", entry, args1, args2, stackTop)); 230 231 stackTop = arch_randomize_stack_pointer(stackTop - sizeof(args)); 232 233 // Copy the address of the stub that calls exit_thread() when the thread 234 // entry function returns to the top of the stack to act as the return 235 // address. The stub is inside commpage. 236 addr_t commPageAddress = (addr_t)thread->team->commpage_address; 237 args[0] = ((addr_t*)commPageAddress)[COMMPAGE_ENTRY_X86_THREAD_EXIT] 238 + commPageAddress; 239 args[1] = (uint32)args1; 240 args[2] = (uint32)args2; 241 242 if (user_memcpy((void *)stackTop, args, sizeof(args)) < B_OK) 243 return B_BAD_ADDRESS; 244 245 // prepare the user iframe 246 iframe frame = {}; 247 frame.type = IFRAME_TYPE_SYSCALL; 248 frame.gs = USER_DATA_SELECTOR; 249 // frame.fs not used, we call x86_set_tls_context() on context switch 250 frame.es = USER_DATA_SELECTOR; 251 frame.ds = USER_DATA_SELECTOR; 252 frame.ip = entry; 253 frame.cs = USER_CODE_SELECTOR; 254 frame.flags = X86_EFLAGS_RESERVED1 | X86_EFLAGS_INTERRUPT; 255 frame.user_sp = stackTop; 256 frame.user_ss = USER_DATA_SELECTOR; 257 258 // return to userland 259 x86_initial_return_to_userland(thread, &frame); 260 261 return B_OK; 262 // never gets here 263 } 264 265 266 /*! Sets up the user iframe for invoking a signal handler. 267 268 The function fills in the remaining fields of the given \a signalFrameData, 269 copies it to the thread's userland stack (the one on which the signal shall 270 be handled), and sets up the user iframe so that when returning to userland 271 a wrapper function is executed that calls the user-defined signal handler. 272 When the signal handler returns, the wrapper function shall call the 273 "restore signal frame" syscall with the (possibly modified) signal frame 274 data. 275 276 The following fields of the \a signalFrameData structure still need to be 277 filled in: 278 - \c context.uc_stack: The stack currently used by the thread. 279 - \c context.uc_mcontext: The current userland state of the registers. 280 - \c syscall_restart_return_value: Architecture specific use. On x86 the 281 value of eax and edx which are overwritten by the syscall return value. 282 283 Furthermore the function needs to set \c thread->user_signal_context to the 284 userland pointer to the \c ucontext_t on the user stack. 285 286 \param thread The current thread. 287 \param action The signal action specified for the signal to be handled. 288 \param signalFrameData A partially initialized structure of all the data 289 that need to be copied to userland. 290 \return \c B_OK on success, another error code, if something goes wrong. 291 */ 292 status_t 293 arch_setup_signal_frame(Thread* thread, struct sigaction* action, 294 struct signal_frame_data* signalFrameData) 295 { 296 struct iframe *frame = x86_get_current_iframe(); 297 if (!IFRAME_IS_USER(frame)) { 298 panic("arch_setup_signal_frame(): No user iframe!"); 299 return B_BAD_VALUE; 300 } 301 302 // In case of a BeOS compatible handler map SIGBUS to SIGSEGV, since they 303 // had the same signal number. 304 if ((action->sa_flags & SA_BEOS_COMPATIBLE_HANDLER) != 0 305 && signalFrameData->info.si_signo == SIGBUS) { 306 signalFrameData->info.si_signo = SIGSEGV; 307 } 308 309 // store the register state in signalFrameData->context.uc_mcontext 310 signalFrameData->context.uc_mcontext.eip = frame->ip; 311 signalFrameData->context.uc_mcontext.eflags = frame->flags; 312 signalFrameData->context.uc_mcontext.eax = frame->ax; 313 signalFrameData->context.uc_mcontext.ecx = frame->cx; 314 signalFrameData->context.uc_mcontext.edx = frame->dx; 315 signalFrameData->context.uc_mcontext.ebp = frame->bp; 316 signalFrameData->context.uc_mcontext.esp = frame->user_sp; 317 signalFrameData->context.uc_mcontext.edi = frame->di; 318 signalFrameData->context.uc_mcontext.esi = frame->si; 319 signalFrameData->context.uc_mcontext.ebx = frame->bx; 320 x86_fnsave((void *)(&signalFrameData->context.uc_mcontext.xregs)); 321 322 // Fill in signalFrameData->context.uc_stack 323 signal_get_user_stack(frame->user_sp, &signalFrameData->context.uc_stack); 324 325 // store orig_eax/orig_edx in syscall_restart_return_value 326 signalFrameData->syscall_restart_return_value 327 = (uint64)frame->orig_edx << 32 | frame->orig_eax; 328 329 // get the stack to use -- that's either the current one or a special signal 330 // stack 331 uint32 stackFrame[2]; 332 uint8* userStack = get_signal_stack(thread, frame, action, 333 sizeof(*signalFrameData) + sizeof(stackFrame)); 334 335 // copy the signal frame data onto the stack 336 signal_frame_data* userSignalFrameData 337 = (signal_frame_data*)(userStack + sizeof(stackFrame)); 338 if (user_memcpy(userSignalFrameData, signalFrameData, 339 sizeof(*signalFrameData)) != B_OK) { 340 return B_BAD_ADDRESS; 341 } 342 343 // prepare the user stack frame for a function call to the signal handler 344 // wrapper function 345 stackFrame[0] = frame->ip; 346 stackFrame[1] = (addr_t)userSignalFrameData; 347 // parameter: pointer to signal frame data 348 349 if (user_memcpy(userStack, stackFrame, sizeof(stackFrame)) != B_OK) 350 return B_BAD_ADDRESS; 351 352 // Update Thread::user_signal_context, now that everything seems to have 353 // gone fine. 354 thread->user_signal_context = &userSignalFrameData->context; 355 356 // Adjust the iframe's esp and eip, so that the thread will continue with 357 // the prepared stack, executing the signal handler wrapper function. 358 frame->user_sp = (addr_t)userStack; 359 frame->ip = x86_get_user_signal_handler_wrapper( 360 (action->sa_flags & SA_BEOS_COMPATIBLE_HANDLER) != 0, 361 thread->team->commpage_address); 362 frame->flags &= ~(X86_EFLAGS_TRAP | X86_EFLAGS_DIRECTION); 363 364 return B_OK; 365 } 366 367 368 int64 369 arch_restore_signal_frame(struct signal_frame_data* signalFrameData) 370 { 371 struct iframe* frame = x86_get_current_iframe(); 372 373 TRACE(("### arch_restore_signal_frame: entry\n")); 374 375 frame->orig_eax = (uint32)signalFrameData->syscall_restart_return_value; 376 frame->orig_edx 377 = (uint32)(signalFrameData->syscall_restart_return_value >> 32); 378 379 frame->ip = signalFrameData->context.uc_mcontext.eip; 380 frame->flags = (frame->flags & ~(uint32)X86_EFLAGS_USER_FLAGS) 381 | (signalFrameData->context.uc_mcontext.eflags & X86_EFLAGS_USER_FLAGS); 382 frame->ax = signalFrameData->context.uc_mcontext.eax; 383 frame->cx = signalFrameData->context.uc_mcontext.ecx; 384 frame->dx = signalFrameData->context.uc_mcontext.edx; 385 frame->bp = signalFrameData->context.uc_mcontext.ebp; 386 frame->user_sp = signalFrameData->context.uc_mcontext.esp; 387 frame->di = signalFrameData->context.uc_mcontext.edi; 388 frame->si = signalFrameData->context.uc_mcontext.esi; 389 frame->bx = signalFrameData->context.uc_mcontext.ebx; 390 391 x86_frstor((void*)(&signalFrameData->context.uc_mcontext.xregs)); 392 393 TRACE(("### arch_restore_signal_frame: exit\n")); 394 395 return (int64)frame->ax | ((int64)frame->dx << 32); 396 } 397 398 399 void 400 arch_syscall_64_bit_return_value(void) 401 { 402 Thread* thread = thread_get_current_thread(); 403 atomic_or(&thread->flags, THREAD_FLAGS_64_BIT_SYSCALL_RETURN); 404 } 405