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