1/*
2 * Copyright 2019-2022 Haiku, Inc. All Rights Reserved.
3 * Distributed under the terms of the MIT License.
4 */
5#include <thread.h>
6#include <arch_thread.h>
7
8#include <arch_cpu.h>
9#include <arch/thread.h>
10#include <boot/stage2.h>
11#include <commpage_defs.h>
12#include <kernel.h>
13#include <thread.h>
14#include <tls.h>
15#include <vm/vm_types.h>
16#include <vm/VMAddressSpace.h>
17#include <arch_vm.h>
18#include <arch/vm_translation_map.h>
19
20#include <string.h>
21
22//#define TRACE_ARCH_THREAD
23#ifdef TRACE_ARCH_THREAD
24#	define TRACE(x) dprintf x
25#else
26#	define TRACE(x) ;
27#endif
28
29
30void
31arm64_push_iframe(struct iframe_stack *stack, struct iframe *frame)
32{
33	ASSERT(stack->index < IFRAME_TRACE_DEPTH);
34	stack->frames[stack->index++] = frame;
35}
36
37
38void
39arm64_pop_iframe(struct iframe_stack *stack)
40{
41	ASSERT(stack->index > 0);
42	stack->index--;
43}
44
45
46status_t
47arch_thread_init(struct kernel_args *args)
48{
49	return B_OK;
50}
51
52
53status_t
54arch_team_init_team_struct(Team *team, bool kernel)
55{
56	return B_OK;
57}
58
59
60status_t
61arch_thread_init_thread_struct(Thread *thread)
62{
63	return B_OK;
64}
65
66
67void
68arch_thread_init_kthread_stack(Thread* thread, void* _stack, void* _stackTop,
69	void (*function)(void*), const void* data)
70{
71	memset(&thread->arch_info, 0, sizeof(arch_thread));
72	thread->arch_info.regs[10] = (uint64_t)data;
73	thread->arch_info.regs[11] = (uint64_t)function;
74	thread->arch_info.regs[12] = (uint64_t)_stackTop;
75}
76
77
78status_t
79arch_thread_init_tls(Thread *thread)
80{
81	thread->user_local_storage =
82		thread->user_stack_base + thread->user_stack_size;
83	return B_OK;
84}
85
86
87static void
88arm64_set_tls_context(Thread *thread)
89{
90	WRITE_SPECIALREG(tpidrro_el0, thread->user_local_storage);
91}
92
93extern "C" void _arch_context_swap(arch_thread *from, arch_thread *to);
94
95
96void
97arch_thread_context_switch(Thread *from, Thread *to)
98{
99	arm64_set_tls_context(to);
100	_arch_context_swap(&from->arch_info, &to->arch_info);
101}
102
103
104void
105arch_thread_dump_info(void *info)
106{
107}
108
109
110extern "C" void _eret_with_iframe(iframe *frame);
111
112
113status_t
114arch_thread_enter_userspace(Thread *thread, addr_t entry,
115	void *arg1, void *arg2)
116{
117	arm64_set_tls_context(thread);
118
119	addr_t threadExitAddr;
120	{
121		addr_t commpageAdr = (addr_t)thread->team->commpage_address;
122		status_t ret = user_memcpy(&threadExitAddr,
123			&((addr_t*)commpageAdr)[COMMPAGE_ENTRY_ARM64_THREAD_EXIT],
124			sizeof(threadExitAddr));
125		ASSERT(ret == B_OK);
126		threadExitAddr += commpageAdr;
127	}
128
129	iframe frame;
130	memset(&frame, 0, sizeof(frame));
131
132	frame.spsr = 0;
133	frame.elr = entry;
134	frame.x[0] = (uint64_t)arg1;
135	frame.x[1] = (uint64_t)arg2;
136	frame.lr = threadExitAddr;
137	frame.sp = thread->user_stack_base + thread->user_stack_size;
138
139	_eret_with_iframe(&frame);
140	return B_ERROR;
141}
142
143
144bool
145arch_on_signal_stack(Thread *thread)
146{
147	return false;
148}
149
150
151status_t
152arch_setup_signal_frame(Thread *thread, struct sigaction *sa,
153	struct signal_frame_data *signalFrameData)
154{
155	panic("arch_setup_signal_frame");
156	return B_ERROR;
157}
158
159
160int64
161arch_restore_signal_frame(struct signal_frame_data* signalFrameData)
162{
163	return 0;
164}
165
166
167void
168arch_store_fork_frame(struct arch_fork_arg *arg)
169{
170	panic("arch_store_fork_frame");
171}
172
173
174void
175arch_restore_fork_frame(struct arch_fork_arg *arg)
176{
177}
178