xref: /haiku/src/system/kernel/arch/arm/arch_thread.cpp (revision cc65466f0de34d946d9311517f4e7781b7294ef8)
1c9f536d7SFrançois Revol /*
2924a3e5fSIngo Weinhold  * Copyright 2003-2010, Haiku Inc. All rights reserved.
3c9f536d7SFrançois Revol  * Distributed under the terms of the MIT License.
4c9f536d7SFrançois Revol  *
5c9f536d7SFrançois Revol  * Authors:
6c9f536d7SFrançois Revol  * 		Axel Dörfler <axeld@pinc-software.de>
7c9f536d7SFrançois Revol  * 		Ingo Weinhold <bonefish@cs.tu-berlin.de>
8c9f536d7SFrançois Revol  * 		François Revol <revol@free.fr>
9c9f536d7SFrançois Revol  *
10c9f536d7SFrançois Revol  * Copyright 2001, Travis Geiselbrecht. All rights reserved.
11c9f536d7SFrançois Revol  * Distributed under the terms of the NewOS License.
12c9f536d7SFrançois Revol  */
13c9f536d7SFrançois Revol 
14924a3e5fSIngo Weinhold 
158bbaee61SIthamar R. Adema #include <thread.h>
16c9f536d7SFrançois Revol #include <arch_thread.h>
17c9f536d7SFrançois Revol 
18c9f536d7SFrançois Revol #include <arch_cpu.h>
19c9f536d7SFrançois Revol #include <arch/thread.h>
20c9f536d7SFrançois Revol #include <boot/stage2.h>
21c9f536d7SFrançois Revol #include <kernel.h>
22c9f536d7SFrançois Revol #include <thread.h>
234fc1daddSIthamar R. Adema #include <tls.h>
24e50cf876SIngo Weinhold #include <vm/vm_types.h>
25e50cf876SIngo Weinhold #include <vm/VMAddressSpace.h>
26c9f536d7SFrançois Revol #include <arch_vm.h>
274fc1daddSIthamar R. Adema #include <arch/vm_translation_map.h>
28c9f536d7SFrançois Revol 
29c9f536d7SFrançois Revol #include <string.h>
30c9f536d7SFrançois Revol 
31ff163585SIthamar R. Adema //#define TRACE_ARCH_THREAD
324fc1daddSIthamar R. Adema #ifdef TRACE_ARCH_THREAD
334fc1daddSIthamar R. Adema #	define TRACE(x) dprintf x
344fc1daddSIthamar R. Adema #else
354fc1daddSIthamar R. Adema #	define TRACE(x) ;
364fc1daddSIthamar R. Adema #endif
37258d4ef9SAlexander von Gluck IV 
38c9f536d7SFrançois Revol // Valid initial arch_thread state. We just memcpy() it when initializing
39c9f536d7SFrançois Revol // a new thread structure.
40c9f536d7SFrançois Revol static struct arch_thread sInitialState;
41c9f536d7SFrançois Revol 
424535495dSIngo Weinhold Thread *gCurrentThread;
43c9f536d7SFrançois Revol 
44c9f536d7SFrançois Revol 
45*cc65466fSIthamar R. Adema void
46*cc65466fSIthamar R. Adema arm_push_iframe(struct iframe_stack *stack, struct iframe *frame)
47*cc65466fSIthamar R. Adema {
48*cc65466fSIthamar R. Adema 	ASSERT(stack->index < IFRAME_TRACE_DEPTH);
49*cc65466fSIthamar R. Adema 	stack->frames[stack->index++] = frame;
50*cc65466fSIthamar R. Adema }
51*cc65466fSIthamar R. Adema 
52*cc65466fSIthamar R. Adema 
53*cc65466fSIthamar R. Adema void
54*cc65466fSIthamar R. Adema arm_pop_iframe(struct iframe_stack *stack)
55*cc65466fSIthamar R. Adema {
56*cc65466fSIthamar R. Adema 	ASSERT(stack->index > 0);
57*cc65466fSIthamar R. Adema 	stack->index--;
58*cc65466fSIthamar R. Adema }
59*cc65466fSIthamar R. Adema 
60*cc65466fSIthamar R. Adema 
61*cc65466fSIthamar R. Adema 
62c9f536d7SFrançois Revol status_t
63c9f536d7SFrançois Revol arch_thread_init(struct kernel_args *args)
64c9f536d7SFrançois Revol {
65c9f536d7SFrançois Revol 	// Initialize the static initial arch_thread state (sInitialState).
66c9f536d7SFrançois Revol 	// Currently nothing to do, i.e. zero initialized is just fine.
67c9f536d7SFrançois Revol 
68c9f536d7SFrançois Revol 	return B_OK;
69c9f536d7SFrançois Revol }
70c9f536d7SFrançois Revol 
71c9f536d7SFrançois Revol 
72c9f536d7SFrançois Revol status_t
734535495dSIngo Weinhold arch_team_init_team_struct(Team *team, bool kernel)
74c9f536d7SFrançois Revol {
75c9f536d7SFrançois Revol 	// Nothing to do. The structure is empty.
76c9f536d7SFrançois Revol 	return B_OK;
77c9f536d7SFrançois Revol }
78c9f536d7SFrançois Revol 
79c9f536d7SFrançois Revol 
80c9f536d7SFrançois Revol status_t
814535495dSIngo Weinhold arch_thread_init_thread_struct(Thread *thread)
82c9f536d7SFrançois Revol {
83c9f536d7SFrançois Revol 	// set up an initial state (stack & fpu)
84c9f536d7SFrançois Revol 	memcpy(&thread->arch_info, &sInitialState, sizeof(struct arch_thread));
85c9f536d7SFrançois Revol 
86c9f536d7SFrançois Revol 	return B_OK;
87c9f536d7SFrançois Revol }
88c9f536d7SFrançois Revol 
89c9f536d7SFrançois Revol 
9024df6592SIngo Weinhold void
9124df6592SIngo Weinhold arch_thread_init_kthread_stack(Thread* thread, void* _stack, void* _stackTop,
9224df6592SIngo Weinhold 	void (*function)(void*), const void* data)
93c9f536d7SFrançois Revol {
944fc1daddSIthamar R. Adema 	addr_t* stackTop = (addr_t*)_stackTop;
954fc1daddSIthamar R. Adema 
964fc1daddSIthamar R. Adema 	TRACE(("arch_thread_init_kthread_stack(%s): stack top %p, function %p, data: "
974fc1daddSIthamar R. Adema 		"%p\n", thread->name, stackTop, function, data));
984fc1daddSIthamar R. Adema 
994fc1daddSIthamar R. Adema 	// push the function address -- that's the return address used after the
1004fc1daddSIthamar R. Adema 	// context switch (lr/r14 register)
1014fc1daddSIthamar R. Adema 	*--stackTop = (addr_t)function;
1024fc1daddSIthamar R. Adema 
1034fc1daddSIthamar R. Adema 	// simulate storing registers r1-r12
1044fc1daddSIthamar R. Adema 	for (int i = 1; i <= 12; i++)
1054fc1daddSIthamar R. Adema 		*--stackTop = 0;
1064fc1daddSIthamar R. Adema 
1074fc1daddSIthamar R. Adema 	// push the function argument as r0
1084fc1daddSIthamar R. Adema 	*--stackTop = (addr_t)data;
1094fc1daddSIthamar R. Adema 
1104fc1daddSIthamar R. Adema 	// save the stack position
1114fc1daddSIthamar R. Adema 	thread->arch_info.sp = stackTop;
112c9f536d7SFrançois Revol }
113c9f536d7SFrançois Revol 
114c9f536d7SFrançois Revol 
115c9f536d7SFrançois Revol status_t
1164535495dSIngo Weinhold arch_thread_init_tls(Thread *thread)
117c9f536d7SFrançois Revol {
1184fc1daddSIthamar R. Adema 	uint32 tls[TLS_USER_THREAD_SLOT + 1];
1194fc1daddSIthamar R. Adema 
1204fc1daddSIthamar R. Adema 	thread->user_local_storage = thread->user_stack_base
1214fc1daddSIthamar R. Adema 		+ thread->user_stack_size;
1224fc1daddSIthamar R. Adema 
1234fc1daddSIthamar R. Adema 	// initialize default TLS fields
1244fc1daddSIthamar R. Adema 	memset(tls, 0, sizeof(tls));
1254fc1daddSIthamar R. Adema 	tls[TLS_BASE_ADDRESS_SLOT] = thread->user_local_storage;
1264fc1daddSIthamar R. Adema 	tls[TLS_THREAD_ID_SLOT] = thread->id;
1274fc1daddSIthamar R. Adema 	tls[TLS_USER_THREAD_SLOT] = (addr_t)thread->user_thread;
1284fc1daddSIthamar R. Adema 
1294fc1daddSIthamar R. Adema 	return user_memcpy((void *)thread->user_local_storage, tls, sizeof(tls));
130c9f536d7SFrançois Revol }
131c9f536d7SFrançois Revol 
1324fc1daddSIthamar R. Adema extern "C" void arm_context_switch(void *from, void *to);
133c9f536d7SFrançois Revol 
134c9f536d7SFrançois Revol void
1354535495dSIngo Weinhold arch_thread_context_switch(Thread *from, Thread *to)
136c9f536d7SFrançois Revol {
1374fc1daddSIthamar R. Adema 	TRACE(("arch_thread_context_switch: %p(%s/%p) -> %p(%s/%p)\n",
1384fc1daddSIthamar R. Adema 		from, from->name, from->arch_info.sp, to, to->name, to->arch_info.sp));
1394fc1daddSIthamar R. Adema 	arm_context_switch(&from->arch_info, &to->arch_info);
1404fc1daddSIthamar R. Adema 	TRACE(("arch_thread_context_switch %p %p\n", to, from));
141c9f536d7SFrançois Revol }
142c9f536d7SFrançois Revol 
143c9f536d7SFrançois Revol 
144c9f536d7SFrançois Revol void
145c9f536d7SFrançois Revol arch_thread_dump_info(void *info)
146c9f536d7SFrançois Revol {
147c9f536d7SFrançois Revol 	struct arch_thread *at = (struct arch_thread *)info;
148c9f536d7SFrançois Revol 
149c9f536d7SFrançois Revol 	dprintf("\tsp: %p\n", at->sp);
150c9f536d7SFrançois Revol }
151c9f536d7SFrançois Revol 
152c9f536d7SFrançois Revol 
153c9f536d7SFrançois Revol status_t
154258d4ef9SAlexander von Gluck IV arch_thread_enter_userspace(Thread *thread, addr_t entry,
155258d4ef9SAlexander von Gluck IV 	void *arg1, void *arg2)
156c9f536d7SFrançois Revol {
157c9f536d7SFrançois Revol 	panic("arch_thread_enter_uspace(): not yet implemented\n");
158c9f536d7SFrançois Revol 	return B_ERROR;
159c9f536d7SFrançois Revol }
160c9f536d7SFrançois Revol 
161c9f536d7SFrançois Revol 
162c9f536d7SFrançois Revol bool
1634535495dSIngo Weinhold arch_on_signal_stack(Thread *thread)
164c9f536d7SFrançois Revol {
165c9f536d7SFrançois Revol 	return false;
166c9f536d7SFrançois Revol }
167c9f536d7SFrançois Revol 
168c9f536d7SFrançois Revol 
169c9f536d7SFrançois Revol status_t
17024df6592SIngo Weinhold arch_setup_signal_frame(Thread *thread, struct sigaction *sa,
17124df6592SIngo Weinhold 	struct signal_frame_data *signalFrameData)
172c9f536d7SFrançois Revol {
173c9f536d7SFrançois Revol 	return B_ERROR;
174c9f536d7SFrançois Revol }
175c9f536d7SFrançois Revol 
176c9f536d7SFrançois Revol 
177c9f536d7SFrançois Revol int64
17824df6592SIngo Weinhold arch_restore_signal_frame(struct signal_frame_data* signalFrameData)
179c9f536d7SFrançois Revol {
180c9f536d7SFrançois Revol 	return 0;
181c9f536d7SFrançois Revol }
182c9f536d7SFrançois Revol 
183c9f536d7SFrançois Revol 
184c9f536d7SFrançois Revol void
1854535495dSIngo Weinhold arch_check_syscall_restart(Thread *thread)
186c9f536d7SFrançois Revol {
187c9f536d7SFrançois Revol }
188c9f536d7SFrançois Revol 
189c9f536d7SFrançois Revol 
190c9f536d7SFrançois Revol /**	Saves everything needed to restore the frame in the child fork in the
191c9f536d7SFrançois Revol  *	arch_fork_arg structure to be passed to arch_restore_fork_frame().
192c9f536d7SFrançois Revol  *	Also makes sure to return the right value.
193c9f536d7SFrançois Revol  */
194c9f536d7SFrançois Revol void
195c9f536d7SFrançois Revol arch_store_fork_frame(struct arch_fork_arg *arg)
196c9f536d7SFrançois Revol {
197c9f536d7SFrançois Revol }
198c9f536d7SFrançois Revol 
199c9f536d7SFrançois Revol 
200c9f536d7SFrançois Revol /** Restores the frame from a forked team as specified by the provided
201c9f536d7SFrançois Revol  *	arch_fork_arg structure.
202c9f536d7SFrançois Revol  *	Needs to be called from within the child team, ie. instead of
203c9f536d7SFrançois Revol  *	arch_thread_enter_uspace() as thread "starter".
204c9f536d7SFrançois Revol  *	This function does not return to the caller, but will enter userland
205c9f536d7SFrançois Revol  *	in the child team at the same position where the parent team left of.
206c9f536d7SFrançois Revol  */
207c9f536d7SFrançois Revol void
208c9f536d7SFrançois Revol arch_restore_fork_frame(struct arch_fork_arg *arg)
209c9f536d7SFrançois Revol {
210c9f536d7SFrançois Revol }
211