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 #include "x86_syscalls.h" 33 34 35 //#define TRACE_ARCH_THREAD 36 #ifdef TRACE_ARCH_THREAD 37 # define TRACE(x) dprintf x 38 #else 39 # define TRACE(x) ; 40 #endif 41 42 43 #ifdef SYSCALL_TRACING 44 45 namespace SyscallTracing { 46 47 class RestartSyscall : public AbstractTraceEntry { 48 public: 49 RestartSyscall() 50 { 51 Initialized(); 52 } 53 54 virtual void AddDump(TraceOutput& out) 55 { 56 out.Print("syscall restart"); 57 } 58 }; 59 60 } 61 62 # define TSYSCALL(x) new(std::nothrow) SyscallTracing::x 63 64 #else 65 # define TSYSCALL(x) 66 #endif // SYSCALL_TRACING 67 68 69 // from arch_interrupts.S 70 extern "C" void i386_stack_init(struct farcall *interrupt_stack_offset); 71 extern "C" void x86_return_to_userland(iframe* frame); 72 73 // from arch_cpu.c 74 extern void (*gX86SwapFPUFunc)(void *oldState, const void *newState); 75 extern bool gHasSSE; 76 77 static struct arch_thread sInitialState _ALIGNED(16); 78 // the fpu_state must be aligned on a 16 byte boundary, so that fxsave can use it 79 80 81 status_t 82 arch_thread_init(struct kernel_args *args) 83 { 84 // save one global valid FPU state; it will be copied in the arch dependent 85 // part of each new thread 86 87 asm volatile ("clts; fninit; fnclex;"); 88 if (gHasSSE) 89 i386_fxsave(sInitialState.fpu_state); 90 else 91 i386_fnsave(sInitialState.fpu_state); 92 93 return B_OK; 94 } 95 96 97 static struct iframe * 98 find_previous_iframe(Thread *thread, addr_t frame) 99 { 100 // iterate backwards through the stack frames, until we hit an iframe 101 while (frame >= thread->kernel_stack_base 102 && frame < thread->kernel_stack_top) { 103 addr_t previousFrame = *(addr_t*)frame; 104 if ((previousFrame & ~IFRAME_TYPE_MASK) == 0) { 105 if (previousFrame == 0) 106 return NULL; 107 return (struct iframe*)frame; 108 } 109 110 frame = previousFrame; 111 } 112 113 return NULL; 114 } 115 116 117 static struct iframe* 118 get_previous_iframe(struct iframe* frame) 119 { 120 if (frame == NULL) 121 return NULL; 122 123 return find_previous_iframe(thread_get_current_thread(), frame->ebp); 124 } 125 126 127 /*! 128 Returns the current iframe structure of the running thread. 129 This function must only be called in a context where it's actually 130 sure that such iframe exists; ie. from syscalls, but usually not 131 from standard kernel threads. 132 */ 133 static struct iframe* 134 get_current_iframe(void) 135 { 136 return find_previous_iframe(thread_get_current_thread(), x86_read_ebp()); 137 } 138 139 140 static inline void 141 set_fs_register(uint32 segment) 142 { 143 asm("movl %0,%%fs" :: "r" (segment)); 144 } 145 146 147 /*! Returns to the userland environment given by \a frame for a thread not 148 having been userland before. 149 150 Before returning to userland all potentially necessary kernel exit work is 151 done. 152 153 \param thread The current thread. 154 \param frame The iframe defining the userland environment. Must point to a 155 location somewhere on the caller's stack (e.g. a local variable). 156 */ 157 static void 158 initial_return_to_userland(Thread* thread, iframe* frame) 159 { 160 // disable interrupts and set up CPU specifics for this thread 161 disable_interrupts(); 162 163 i386_set_tss_and_kstack(thread->kernel_stack_top); 164 x86_set_tls_context(thread); 165 x86_set_syscall_stack(thread->kernel_stack_top); 166 167 // return to userland 168 x86_return_to_userland(frame); 169 } 170 171 172 /*! 173 \brief Returns the current thread's topmost (i.e. most recent) 174 userland->kernel transition iframe (usually the first one, save for 175 interrupts in signal handlers). 176 \return The iframe, or \c NULL, if there is no such iframe (e.g. when 177 the thread is a kernel thread). 178 */ 179 struct iframe * 180 i386_get_user_iframe(void) 181 { 182 struct iframe* frame = get_current_iframe(); 183 184 while (frame != NULL) { 185 if (IFRAME_IS_USER(frame)) 186 return frame; 187 frame = get_previous_iframe(frame); 188 } 189 190 return NULL; 191 } 192 193 194 /*! \brief Like i386_get_user_iframe(), just for the given thread. 195 The thread must not be running and the threads spinlock must be held. 196 */ 197 struct iframe * 198 i386_get_thread_user_iframe(Thread *thread) 199 { 200 if (thread->state == B_THREAD_RUNNING) 201 return NULL; 202 203 // read %ebp from the thread's stack stored by a pushad 204 addr_t ebp = thread->arch_info.current_stack.esp[2]; 205 206 // find the user iframe 207 struct iframe *frame = find_previous_iframe(thread, ebp); 208 209 while (frame != NULL) { 210 if (IFRAME_IS_USER(frame)) 211 return frame; 212 frame = get_previous_iframe(frame); 213 } 214 215 return NULL; 216 } 217 218 219 struct iframe * 220 i386_get_current_iframe(void) 221 { 222 return get_current_iframe(); 223 } 224 225 226 uint32 227 x86_next_page_directory(Thread *from, Thread *to) 228 { 229 VMAddressSpace* toAddressSpace = to->team->address_space; 230 if (from->team->address_space == toAddressSpace) { 231 // don't change the pgdir, same address space 232 return 0; 233 } 234 235 if (toAddressSpace == NULL) 236 toAddressSpace = VMAddressSpace::Kernel(); 237 238 return static_cast<X86VMTranslationMap*>(toAddressSpace->TranslationMap()) 239 ->PagingStructures()->pgdir_phys; 240 } 241 242 243 void 244 x86_restart_syscall(struct iframe* frame) 245 { 246 Thread* thread = thread_get_current_thread(); 247 248 atomic_and(&thread->flags, ~THREAD_FLAGS_RESTART_SYSCALL); 249 atomic_or(&thread->flags, THREAD_FLAGS_SYSCALL_RESTARTED); 250 251 frame->eax = frame->orig_eax; 252 frame->edx = frame->orig_edx; 253 frame->eip -= 2; 254 // undoes the "int $99"/"sysenter"/"syscall" instruction 255 // (so that it'll be executed again) 256 257 TSYSCALL(RestartSyscall()); 258 } 259 260 261 void 262 x86_set_tls_context(Thread *thread) 263 { 264 int entry = smp_get_current_cpu() + TLS_BASE_SEGMENT; 265 266 set_segment_descriptor_base(&gGDT[entry], thread->user_local_storage); 267 set_fs_register((entry << 3) | DPL_USER); 268 } 269 270 271 static uint8* 272 get_signal_stack(Thread* thread, struct iframe* frame, struct sigaction* action) 273 { 274 // use the alternate signal stack if we should and can 275 if (thread->signal_stack_enabled 276 && (action->sa_flags & SA_ONSTACK) != 0 277 && (frame->user_esp < thread->signal_stack_base 278 || frame->user_esp >= thread->signal_stack_base 279 + thread->signal_stack_size)) { 280 return (uint8*)(thread->signal_stack_base + thread->signal_stack_size); 281 } 282 283 return (uint8*)frame->user_esp; 284 } 285 286 287 // #pragma mark - 288 289 290 status_t 291 arch_team_init_team_struct(Team *p, bool kernel) 292 { 293 return B_OK; 294 } 295 296 297 status_t 298 arch_thread_init_thread_struct(Thread *thread) 299 { 300 // set up an initial state (stack & fpu) 301 memcpy(&thread->arch_info, &sInitialState, sizeof(struct arch_thread)); 302 return B_OK; 303 } 304 305 306 /*! Prepares the given thread's kernel stack for executing its entry function. 307 308 \param thread The thread. 309 \param stack The usable bottom of the thread's kernel stack. 310 \param stackTop The usable top of the thread's kernel stack. 311 \param function The entry function the thread shall execute. 312 \param data Pointer to be passed to the entry function. 313 */ 314 void 315 arch_thread_init_kthread_stack(Thread* thread, void* _stack, void* _stackTop, 316 void (*function)(void*), const void* data) 317 { 318 addr_t* stackTop = (addr_t*)_stackTop; 319 320 TRACE(("arch_thread_init_kthread_stack: stack top %p, function %, data: " 321 "%p\n", stackTop, function, data)); 322 323 // push the function argument, a pointer to the data 324 *--stackTop = (addr_t)data; 325 326 // push a dummy return address for the function 327 *--stackTop = 0; 328 329 // push the function address -- that's the return address used after the 330 // context switch 331 *--stackTop = (addr_t)function; 332 333 // simulate pushad as done by x86_context_switch() 334 for (int i = 0; i < 8; i++) 335 *--stackTop = 0; 336 337 // save the stack position 338 thread->arch_info.current_stack.esp = stackTop; 339 thread->arch_info.current_stack.ss = (addr_t*)KERNEL_DATA_SEG; 340 } 341 342 343 /** Initializes the user-space TLS local storage pointer in 344 * the thread structure, and the reserved TLS slots. 345 * 346 * Is called from _create_user_thread_kentry(). 347 */ 348 349 status_t 350 arch_thread_init_tls(Thread *thread) 351 { 352 uint32 tls[TLS_USER_THREAD_SLOT + 1]; 353 354 thread->user_local_storage = thread->user_stack_base 355 + thread->user_stack_size; 356 357 // initialize default TLS fields 358 memset(tls, 0, sizeof(tls)); 359 tls[TLS_BASE_ADDRESS_SLOT] = thread->user_local_storage; 360 tls[TLS_THREAD_ID_SLOT] = thread->id; 361 tls[TLS_USER_THREAD_SLOT] = (addr_t)thread->user_thread; 362 363 return user_memcpy((void *)thread->user_local_storage, tls, sizeof(tls)); 364 } 365 366 367 void 368 arch_thread_context_switch(Thread *from, Thread *to) 369 { 370 i386_set_tss_and_kstack(to->kernel_stack_top); 371 x86_set_syscall_stack(to->kernel_stack_top); 372 373 // set TLS GDT entry to the current thread - since this action is 374 // dependent on the current CPU, we have to do it here 375 if (to->user_local_storage != 0) 376 x86_set_tls_context(to); 377 378 struct cpu_ent* cpuData = to->cpu; 379 X86PagingStructures* activePagingStructures 380 = cpuData->arch.active_paging_structures; 381 VMAddressSpace* toAddressSpace = to->team->address_space; 382 383 X86PagingStructures* toPagingStructures; 384 if (toAddressSpace != NULL 385 && (toPagingStructures = static_cast<X86VMTranslationMap*>( 386 toAddressSpace->TranslationMap())->PagingStructures()) 387 != activePagingStructures) { 388 // update on which CPUs the address space is used 389 int cpu = cpuData->cpu_num; 390 atomic_and(&activePagingStructures->active_on_cpus, 391 ~((uint32)1 << cpu)); 392 atomic_or(&toPagingStructures->active_on_cpus, (uint32)1 << cpu); 393 394 // assign the new paging structures to the CPU 395 toPagingStructures->AddReference(); 396 cpuData->arch.active_paging_structures = toPagingStructures; 397 398 // set the page directory, if it changes 399 uint32 newPageDirectory = toPagingStructures->pgdir_phys; 400 if (newPageDirectory != activePagingStructures->pgdir_phys) 401 x86_swap_pgdir(newPageDirectory); 402 403 // This CPU no longer uses the previous paging structures. 404 activePagingStructures->RemoveReference(); 405 } 406 407 gX86SwapFPUFunc(from->arch_info.fpu_state, to->arch_info.fpu_state); 408 x86_context_switch(&from->arch_info, &to->arch_info); 409 } 410 411 412 void 413 arch_thread_dump_info(void *info) 414 { 415 struct arch_thread *at = (struct arch_thread *)info; 416 417 kprintf("\tesp: %p\n", at->current_stack.esp); 418 kprintf("\tss: %p\n", at->current_stack.ss); 419 kprintf("\tfpu_state at %p\n", at->fpu_state); 420 } 421 422 423 /*! Sets up initial thread context and enters user space 424 */ 425 status_t 426 arch_thread_enter_userspace(Thread* thread, addr_t entry, void* args1, 427 void* args2) 428 { 429 addr_t stackTop = thread->user_stack_base + thread->user_stack_size; 430 uint32 codeSize = (addr_t)x86_end_userspace_thread_exit 431 - (addr_t)x86_userspace_thread_exit; 432 uint32 args[3]; 433 434 TRACE(("arch_thread_enter_userspace: entry 0x%lx, args %p %p, " 435 "ustack_top 0x%lx\n", entry, args1, args2, stackTop)); 436 437 // copy the little stub that calls exit_thread() when the thread entry 438 // function returns, as well as the arguments of the entry function 439 stackTop -= codeSize; 440 441 if (user_memcpy((void *)stackTop, (const void *)&x86_userspace_thread_exit, codeSize) < B_OK) 442 return B_BAD_ADDRESS; 443 444 args[0] = stackTop; 445 args[1] = (uint32)args1; 446 args[2] = (uint32)args2; 447 stackTop -= sizeof(args); 448 449 if (user_memcpy((void *)stackTop, args, sizeof(args)) < B_OK) 450 return B_BAD_ADDRESS; 451 452 // prepare the user iframe 453 iframe frame = {}; 454 frame.type = IFRAME_TYPE_SYSCALL; 455 frame.gs = USER_DATA_SEG; 456 // frame.fs not used, we call x86_set_tls_context() on context switch 457 frame.es = USER_DATA_SEG; 458 frame.ds = USER_DATA_SEG; 459 frame.eip = entry; 460 frame.cs = USER_CODE_SEG; 461 frame.flags = X86_EFLAGS_RESERVED1 | X86_EFLAGS_INTERRUPT 462 | (3 << X86_EFLAGS_IO_PRIVILEG_LEVEL_SHIFT); 463 frame.user_esp = stackTop; 464 frame.user_ss = USER_DATA_SEG; 465 466 // return to userland 467 initial_return_to_userland(thread, &frame); 468 469 return B_OK; 470 // never gets here 471 } 472 473 474 bool 475 arch_on_signal_stack(Thread *thread) 476 { 477 struct iframe *frame = get_current_iframe(); 478 479 return frame->user_esp >= thread->signal_stack_base 480 && frame->user_esp < thread->signal_stack_base 481 + thread->signal_stack_size; 482 } 483 484 485 /*! Sets up the user iframe for invoking a signal handler. 486 487 The function fills in the remaining fields of the given \a signalFrameData, 488 copies it to the thread's userland stack (the one on which the signal shall 489 be handled), and sets up the user iframe so that when returning to userland 490 a wrapper function is executed that calls the user-defined signal handler. 491 When the signal handler returns, the wrapper function shall call the 492 "restore signal frame" syscall with the (possibly modified) signal frame 493 data. 494 495 The following fields of the \a signalFrameData structure still need to be 496 filled in: 497 - \c context.uc_stack: The stack currently used by the thread. 498 - \c context.uc_mcontext: The current userland state of the registers. 499 - \c syscall_restart_return_value: Architecture specific use. On x86 the 500 value of eax and edx which are overwritten by the syscall return value. 501 502 Furthermore the function needs to set \c thread->user_signal_context to the 503 userland pointer to the \c ucontext_t on the user stack. 504 505 \param thread The current thread. 506 \param action The signal action specified for the signal to be handled. 507 \param signalFrameData A partially initialized structure of all the data 508 that need to be copied to userland. 509 \return \c B_OK on success, another error code, if something goes wrong. 510 */ 511 status_t 512 arch_setup_signal_frame(Thread* thread, struct sigaction* action, 513 struct signal_frame_data* signalFrameData) 514 { 515 struct iframe *frame = get_current_iframe(); 516 if (!IFRAME_IS_USER(frame)) { 517 panic("arch_setup_signal_frame(): No user iframe!"); 518 return B_BAD_VALUE; 519 } 520 521 // In case of a BeOS compatible handler map SIGBUS to SIGSEGV, since they 522 // had the same signal number. 523 if ((action->sa_flags & SA_BEOS_COMPATIBLE_HANDLER) != 0 524 && signalFrameData->info.si_signo == SIGBUS) { 525 signalFrameData->info.si_signo = SIGSEGV; 526 } 527 528 // store the register state in signalFrameData->context.uc_mcontext 529 signalFrameData->context.uc_mcontext.eip = frame->eip; 530 signalFrameData->context.uc_mcontext.eflags = frame->flags; 531 signalFrameData->context.uc_mcontext.eax = frame->eax; 532 signalFrameData->context.uc_mcontext.ecx = frame->ecx; 533 signalFrameData->context.uc_mcontext.edx = frame->edx; 534 signalFrameData->context.uc_mcontext.ebp = frame->ebp; 535 signalFrameData->context.uc_mcontext.esp = frame->user_esp; 536 signalFrameData->context.uc_mcontext.edi = frame->edi; 537 signalFrameData->context.uc_mcontext.esi = frame->esi; 538 signalFrameData->context.uc_mcontext.ebx = frame->ebx; 539 i386_fnsave((void *)(&signalFrameData->context.uc_mcontext.xregs)); 540 541 // fill in signalFrameData->context.uc_stack 542 signal_get_user_stack(frame->user_esp, &signalFrameData->context.uc_stack); 543 544 // store orig_eax/orig_edx in syscall_restart_return_value 545 signalFrameData->syscall_restart_return_value 546 = (uint64)frame->orig_edx << 32 | frame->orig_eax; 547 548 // get the stack to use -- that's either the current one or a special signal 549 // stack 550 uint8* userStack = get_signal_stack(thread, frame, action); 551 552 // copy the signal frame data onto the stack 553 userStack -= sizeof(*signalFrameData); 554 signal_frame_data* userSignalFrameData = (signal_frame_data*)userStack; 555 if (user_memcpy(userSignalFrameData, signalFrameData, 556 sizeof(*signalFrameData)) != B_OK) { 557 return B_BAD_ADDRESS; 558 } 559 560 // prepare the user stack frame for a function call to the signal handler 561 // wrapper function 562 uint32 stackFrame[2] = { 563 frame->eip, // return address 564 (addr_t)userSignalFrameData, // parameter: pointer to signal frame data 565 }; 566 567 userStack -= sizeof(stackFrame); 568 if (user_memcpy(userStack, stackFrame, sizeof(stackFrame)) != B_OK) 569 return B_BAD_ADDRESS; 570 571 // Update Thread::user_signal_context, now that everything seems to have 572 // gone fine. 573 thread->user_signal_context = &userSignalFrameData->context; 574 575 // Adjust the iframe's esp and eip, so that the thread will continue with 576 // the prepared stack, executing the signal handler wrapper function. 577 frame->user_esp = (addr_t)userStack; 578 frame->eip = x86_get_user_signal_handler_wrapper( 579 (action->sa_flags & SA_BEOS_COMPATIBLE_HANDLER) != 0); 580 581 return B_OK; 582 } 583 584 585 int64 586 arch_restore_signal_frame(struct signal_frame_data* signalFrameData) 587 { 588 struct iframe* frame = get_current_iframe(); 589 590 TRACE(("### arch_restore_signal_frame: entry\n")); 591 592 frame->orig_eax = (uint32)signalFrameData->syscall_restart_return_value; 593 frame->orig_edx 594 = (uint32)(signalFrameData->syscall_restart_return_value >> 32); 595 596 frame->eip = signalFrameData->context.uc_mcontext.eip; 597 frame->flags = (frame->flags & ~(uint32)X86_EFLAGS_USER_FLAGS) 598 | (signalFrameData->context.uc_mcontext.eflags & X86_EFLAGS_USER_FLAGS); 599 frame->eax = signalFrameData->context.uc_mcontext.eax; 600 frame->ecx = signalFrameData->context.uc_mcontext.ecx; 601 frame->edx = signalFrameData->context.uc_mcontext.edx; 602 frame->ebp = signalFrameData->context.uc_mcontext.ebp; 603 frame->user_esp = signalFrameData->context.uc_mcontext.esp; 604 frame->edi = signalFrameData->context.uc_mcontext.edi; 605 frame->esi = signalFrameData->context.uc_mcontext.esi; 606 frame->ebx = signalFrameData->context.uc_mcontext.ebx; 607 608 i386_frstor((void*)(&signalFrameData->context.uc_mcontext.xregs)); 609 610 TRACE(("### arch_restore_signal_frame: exit\n")); 611 612 return (int64)frame->eax | ((int64)frame->edx << 32); 613 } 614 615 616 /** Saves everything needed to restore the frame in the child fork in the 617 * arch_fork_arg structure to be passed to arch_restore_fork_frame(). 618 * Also makes sure to return the right value. 619 */ 620 621 void 622 arch_store_fork_frame(struct arch_fork_arg *arg) 623 { 624 struct iframe *frame = get_current_iframe(); 625 626 // we need to copy the threads current iframe 627 arg->iframe = *frame; 628 629 // we also want fork() to return 0 for the child 630 arg->iframe.eax = 0; 631 } 632 633 634 /*! Restores the frame from a forked team as specified by the provided 635 arch_fork_arg structure. 636 Needs to be called from within the child team, i.e. instead of 637 arch_thread_enter_userspace() as thread "starter". 638 This function does not return to the caller, but will enter userland 639 in the child team at the same position where the parent team left of. 640 641 \param arg The architecture specific fork arguments including the 642 environment to restore. Must point to a location somewhere on the 643 caller's stack. 644 */ 645 void 646 arch_restore_fork_frame(struct arch_fork_arg* arg) 647 { 648 initial_return_to_userland(thread_get_current_thread(), &arg->iframe); 649 } 650 651 652 void 653 arch_syscall_64_bit_return_value(void) 654 { 655 Thread* thread = thread_get_current_thread(); 656 atomic_or(&thread->flags, THREAD_FLAGS_64_BIT_SYSCALL_RETURN); 657 } 658