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 <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/AutoLock.h> 26 #include <vm/vm_types.h> 27 #include <vm/VMAddressSpace.h> 28 29 #include "paging/X86PagingStructures.h" 30 #include "paging/X86VMTranslationMap.h" 31 #include "x86_signals.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 // from arch_cpu.cpp 69 extern bool gHasSSE; 70 extern segment_descriptor* gGDT; 71 72 static struct arch_thread sInitialState _ALIGNED(16); 73 // the fpu_state must be aligned on a 16 byte boundary, so that fxsave can use it 74 75 76 static inline void 77 set_fs_register(uint32 segment) 78 { 79 asm("movl %0,%%fs" :: "r" (segment)); 80 } 81 82 83 void 84 x86_restart_syscall(struct iframe* frame) 85 { 86 Thread* thread = thread_get_current_thread(); 87 88 atomic_and(&thread->flags, ~THREAD_FLAGS_RESTART_SYSCALL); 89 atomic_or(&thread->flags, THREAD_FLAGS_SYSCALL_RESTARTED); 90 91 frame->ax = frame->orig_eax; 92 frame->dx = frame->orig_edx; 93 frame->ip -= 2; 94 // undoes the "int $99"/"sysenter"/"syscall" instruction 95 // (so that it'll be executed again) 96 97 TSYSCALL(RestartSyscall()); 98 } 99 100 101 void 102 x86_set_tls_context(Thread *thread) 103 { 104 int entry = smp_get_current_cpu() + TLS_BASE_SEGMENT; 105 106 set_segment_descriptor_base(&gGDT[entry], thread->user_local_storage); 107 set_fs_register((entry << 3) | DPL_USER); 108 } 109 110 111 static uint8* 112 get_signal_stack(Thread* thread, struct iframe* frame, struct sigaction* action) 113 { 114 // use the alternate signal stack if we should and can 115 if (thread->signal_stack_enabled 116 && (action->sa_flags & SA_ONSTACK) != 0 117 && (frame->user_sp < thread->signal_stack_base 118 || frame->user_sp >= thread->signal_stack_base 119 + thread->signal_stack_size)) { 120 return (uint8*)(thread->signal_stack_base + thread->signal_stack_size); 121 } 122 123 return (uint8*)frame->user_sp; 124 } 125 126 127 // #pragma mark - 128 129 130 status_t 131 arch_thread_init(struct kernel_args *args) 132 { 133 // save one global valid FPU state; it will be copied in the arch dependent 134 // part of each new thread 135 136 asm volatile ("clts; fninit; fnclex;"); 137 if (gHasSSE) 138 x86_fxsave(sInitialState.fpu_state); 139 else 140 x86_fnsave(sInitialState.fpu_state); 141 142 return B_OK; 143 } 144 145 146 status_t 147 arch_thread_init_thread_struct(Thread *thread) 148 { 149 // set up an initial state (stack & fpu) 150 memcpy(&thread->arch_info, &sInitialState, sizeof(struct arch_thread)); 151 return B_OK; 152 } 153 154 155 /*! Prepares the given thread's kernel stack for executing its entry function. 156 157 \param thread The thread. 158 \param stack The usable bottom of the thread's kernel stack. 159 \param stackTop The usable top of the thread's kernel stack. 160 \param function The entry function the thread shall execute. 161 \param data Pointer to be passed to the entry function. 162 */ 163 void 164 arch_thread_init_kthread_stack(Thread* thread, void* _stack, void* _stackTop, 165 void (*function)(void*), const void* data) 166 { 167 addr_t* stackTop = (addr_t*)_stackTop; 168 169 TRACE(("arch_thread_init_kthread_stack: stack top %p, function %p, data: " 170 "%p\n", stackTop, function, data)); 171 172 // push the function argument, a pointer to the data 173 *--stackTop = (addr_t)data; 174 175 // push a dummy return address for the function 176 *--stackTop = 0; 177 178 // push the function address -- that's the return address used after the 179 // context switch 180 *--stackTop = (addr_t)function; 181 182 // simulate pushad as done by x86_context_switch() 183 for (int i = 0; i < 8; i++) 184 *--stackTop = 0; 185 186 // save the stack position 187 thread->arch_info.current_stack.esp = stackTop; 188 thread->arch_info.current_stack.ss = (addr_t*)KERNEL_DATA_SEG; 189 } 190 191 192 void 193 arch_thread_dump_info(void *info) 194 { 195 struct arch_thread *at = (struct arch_thread *)info; 196 197 kprintf("\tesp: %p\n", at->current_stack.esp); 198 kprintf("\tss: %p\n", at->current_stack.ss); 199 kprintf("\tfpu_state at %p\n", at->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 uint32 codeSize = (addr_t)x86_end_userspace_thread_exit 211 - (addr_t)x86_userspace_thread_exit; 212 uint32 args[3]; 213 214 TRACE(("arch_thread_enter_userspace: entry 0x%lx, args %p %p, " 215 "ustack_top 0x%lx\n", entry, args1, args2, stackTop)); 216 217 // copy the little stub that calls exit_thread() when the thread entry 218 // function returns, as well as the arguments of the entry function 219 stackTop -= codeSize; 220 221 if (user_memcpy((void *)stackTop, (const void *)&x86_userspace_thread_exit, codeSize) < B_OK) 222 return B_BAD_ADDRESS; 223 224 args[0] = stackTop; 225 args[1] = (uint32)args1; 226 args[2] = (uint32)args2; 227 stackTop -= sizeof(args); 228 229 if (user_memcpy((void *)stackTop, args, sizeof(args)) < B_OK) 230 return B_BAD_ADDRESS; 231 232 // prepare the user iframe 233 iframe frame = {}; 234 frame.type = IFRAME_TYPE_SYSCALL; 235 frame.gs = USER_DATA_SEG; 236 // frame.fs not used, we call x86_set_tls_context() on context switch 237 frame.es = USER_DATA_SEG; 238 frame.ds = USER_DATA_SEG; 239 frame.ip = entry; 240 frame.cs = USER_CODE_SEG; 241 frame.flags = X86_EFLAGS_RESERVED1 | X86_EFLAGS_INTERRUPT 242 | (3 << X86_EFLAGS_IO_PRIVILEG_LEVEL_SHIFT); 243 frame.user_sp = stackTop; 244 frame.user_ss = USER_DATA_SEG; 245 246 // return to userland 247 x86_initial_return_to_userland(thread, &frame); 248 249 return B_OK; 250 // never gets here 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 the 269 value of eax and edx which are 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 struct 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 // In case of a BeOS compatible handler map SIGBUS to SIGSEGV, since they 291 // had the same signal number. 292 if ((action->sa_flags & SA_BEOS_COMPATIBLE_HANDLER) != 0 293 && signalFrameData->info.si_signo == SIGBUS) { 294 signalFrameData->info.si_signo = SIGSEGV; 295 } 296 297 // store the register state in signalFrameData->context.uc_mcontext 298 signalFrameData->context.uc_mcontext.eip = frame->ip; 299 signalFrameData->context.uc_mcontext.eflags = frame->flags; 300 signalFrameData->context.uc_mcontext.eax = frame->ax; 301 signalFrameData->context.uc_mcontext.ecx = frame->cx; 302 signalFrameData->context.uc_mcontext.edx = frame->dx; 303 signalFrameData->context.uc_mcontext.ebp = frame->bp; 304 signalFrameData->context.uc_mcontext.esp = frame->user_sp; 305 signalFrameData->context.uc_mcontext.edi = frame->di; 306 signalFrameData->context.uc_mcontext.esi = frame->si; 307 signalFrameData->context.uc_mcontext.ebx = frame->bx; 308 x86_fnsave((void *)(&signalFrameData->context.uc_mcontext.xregs)); 309 310 // Fill in signalFrameData->context.uc_stack 311 signal_get_user_stack(frame->user_sp, &signalFrameData->context.uc_stack); 312 313 // store orig_eax/orig_edx in syscall_restart_return_value 314 signalFrameData->syscall_restart_return_value 315 = (uint64)frame->orig_edx << 32 | frame->orig_eax; 316 317 // get the stack to use -- that's either the current one or a special signal 318 // stack 319 uint8* userStack = get_signal_stack(thread, frame, action); 320 321 // copy the signal frame data onto the stack 322 userStack -= sizeof(*signalFrameData); 323 signal_frame_data* userSignalFrameData = (signal_frame_data*)userStack; 324 if (user_memcpy(userSignalFrameData, signalFrameData, 325 sizeof(*signalFrameData)) != B_OK) { 326 return B_BAD_ADDRESS; 327 } 328 329 // prepare the user stack frame for a function call to the signal handler 330 // wrapper function 331 uint32 stackFrame[2] = { 332 frame->ip, // return address 333 (addr_t)userSignalFrameData, // parameter: pointer to signal frame data 334 }; 335 336 userStack -= sizeof(stackFrame); 337 if (user_memcpy(userStack, stackFrame, sizeof(stackFrame)) != B_OK) 338 return B_BAD_ADDRESS; 339 340 // Update Thread::user_signal_context, now that everything seems to have 341 // gone fine. 342 thread->user_signal_context = &userSignalFrameData->context; 343 344 // Adjust the iframe's esp and eip, so that the thread will continue with 345 // the prepared stack, executing the signal handler wrapper function. 346 frame->user_sp = (addr_t)userStack; 347 frame->ip = x86_get_user_signal_handler_wrapper( 348 (action->sa_flags & SA_BEOS_COMPATIBLE_HANDLER) != 0); 349 350 return B_OK; 351 } 352 353 354 int64 355 arch_restore_signal_frame(struct signal_frame_data* signalFrameData) 356 { 357 struct iframe* frame = x86_get_current_iframe(); 358 359 TRACE(("### arch_restore_signal_frame: entry\n")); 360 361 frame->orig_eax = (uint32)signalFrameData->syscall_restart_return_value; 362 frame->orig_edx 363 = (uint32)(signalFrameData->syscall_restart_return_value >> 32); 364 365 frame->ip = signalFrameData->context.uc_mcontext.eip; 366 frame->flags = (frame->flags & ~(uint32)X86_EFLAGS_USER_FLAGS) 367 | (signalFrameData->context.uc_mcontext.eflags & X86_EFLAGS_USER_FLAGS); 368 frame->ax = signalFrameData->context.uc_mcontext.eax; 369 frame->cx = signalFrameData->context.uc_mcontext.ecx; 370 frame->dx = signalFrameData->context.uc_mcontext.edx; 371 frame->bp = signalFrameData->context.uc_mcontext.ebp; 372 frame->user_sp = signalFrameData->context.uc_mcontext.esp; 373 frame->di = signalFrameData->context.uc_mcontext.edi; 374 frame->si = signalFrameData->context.uc_mcontext.esi; 375 frame->bx = signalFrameData->context.uc_mcontext.ebx; 376 377 x86_frstor((void*)(&signalFrameData->context.uc_mcontext.xregs)); 378 379 TRACE(("### arch_restore_signal_frame: exit\n")); 380 381 return (int64)frame->ax | ((int64)frame->dx << 32); 382 } 383 384 385 void 386 arch_syscall_64_bit_return_value(void) 387 { 388 Thread* thread = thread_get_current_thread(); 389 atomic_or(&thread->flags, THREAD_FLAGS_64_BIT_SYSCALL_RETURN); 390 } 391