xref: /haiku/src/system/kernel/arch/x86/arch_thread.cpp (revision a6e73cb9e8addfe832c064bfcb68067f1c2fa3eb)
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 static void
148 set_tls_context(Thread *thread)
149 {
150 	int entry = smp_get_current_cpu() + TLS_BASE_SEGMENT;
151 
152 	set_segment_descriptor_base(&gGDT[entry], thread->user_local_storage);
153 	set_fs_register((entry << 3) | DPL_USER);
154 }
155 
156 
157 /*!	Returns to the userland environment given by \a frame for a thread not
158 	having been userland before.
159 
160 	Before returning to userland all potentially necessary kernel exit work is
161 	done.
162 
163 	\param thread The current thread.
164 	\param frame The iframe defining the userland environment. Must point to a
165 		location somewhere on the caller's stack (e.g. a local variable).
166 */
167 static void
168 initial_return_to_userland(Thread* thread, iframe* frame)
169 {
170 	// disable interrupts and set up CPU specifics for this thread
171 	disable_interrupts();
172 
173 	i386_set_tss_and_kstack(thread->kernel_stack_top);
174 	set_tls_context(thread);
175 	x86_set_syscall_stack(thread->kernel_stack_top);
176 
177 	// return to userland
178 	x86_return_to_userland(frame);
179 }
180 
181 
182 /*!
183 	\brief Returns the current thread's topmost (i.e. most recent)
184 	userland->kernel transition iframe (usually the first one, save for
185 	interrupts in signal handlers).
186 	\return The iframe, or \c NULL, if there is no such iframe (e.g. when
187 			the thread is a kernel thread).
188 */
189 struct iframe *
190 i386_get_user_iframe(void)
191 {
192 	struct iframe* frame = get_current_iframe();
193 
194 	while (frame != NULL) {
195 		if (IFRAME_IS_USER(frame))
196 			return frame;
197 		frame = get_previous_iframe(frame);
198 	}
199 
200 	return NULL;
201 }
202 
203 
204 /*!	\brief Like i386_get_user_iframe(), just for the given thread.
205 	The thread must not be running and the threads spinlock must be held.
206 */
207 struct iframe *
208 i386_get_thread_user_iframe(Thread *thread)
209 {
210 	if (thread->state == B_THREAD_RUNNING)
211 		return NULL;
212 
213 	// read %ebp from the thread's stack stored by a pushad
214 	addr_t ebp = thread->arch_info.current_stack.esp[2];
215 
216 	// find the user iframe
217 	struct iframe *frame = find_previous_iframe(thread, ebp);
218 
219 	while (frame != NULL) {
220 		if (IFRAME_IS_USER(frame))
221 			return frame;
222 		frame = get_previous_iframe(frame);
223 	}
224 
225 	return NULL;
226 }
227 
228 
229 struct iframe *
230 i386_get_current_iframe(void)
231 {
232 	return get_current_iframe();
233 }
234 
235 
236 uint32
237 x86_next_page_directory(Thread *from, Thread *to)
238 {
239 	VMAddressSpace* toAddressSpace = to->team->address_space;
240 	if (from->team->address_space == toAddressSpace) {
241 		// don't change the pgdir, same address space
242 		return 0;
243 	}
244 
245 	if (toAddressSpace == NULL)
246 		toAddressSpace = VMAddressSpace::Kernel();
247 
248 	return static_cast<X86VMTranslationMap*>(toAddressSpace->TranslationMap())
249 		->PagingStructures()->pgdir_phys;
250 }
251 
252 
253 void
254 x86_restart_syscall(struct iframe* frame)
255 {
256 	Thread* thread = thread_get_current_thread();
257 
258 	atomic_and(&thread->flags, ~THREAD_FLAGS_RESTART_SYSCALL);
259 	atomic_or(&thread->flags, THREAD_FLAGS_SYSCALL_RESTARTED);
260 
261 	frame->eax = frame->orig_eax;
262 	frame->edx = frame->orig_edx;
263 	frame->eip -= 2;
264 		// undoes the "int $99"/"sysenter"/"syscall" instruction
265 		// (so that it'll be executed again)
266 
267 	TSYSCALL(RestartSyscall());
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 		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 set_tls_context() below
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