blob: 3d12bf8d5cf56b059c8b9fd0343535863928f4e9 [file] [log] [blame]
Patrick Georgi11f00792020-03-04 15:10:45 +01001/* SPDX-License-Identifier: GPL-2.0-only */
Aaron Durbin38c326d2013-05-06 12:22:23 -05002
3#include <thread.h>
4
5/* The stack frame looks like the following after a pushad instruction. */
6struct pushad_regs {
7 uint32_t edi; /* Offset 0x00 */
8 uint32_t esi; /* Offset 0x04 */
9 uint32_t ebp; /* Offset 0x08 */
10 uint32_t esp; /* Offset 0x0c */
11 uint32_t ebx; /* Offset 0x10 */
12 uint32_t edx; /* Offset 0x14 */
13 uint32_t ecx; /* Offset 0x18 */
14 uint32_t eax; /* Offset 0x1c */
15};
16
17static inline uintptr_t push_stack(uintptr_t cur_stack, uintptr_t value)
18{
19 uintptr_t *addr;
20
21 cur_stack -= sizeof(value);
22 addr = (uintptr_t *)cur_stack;
23 *addr = value;
24 return cur_stack;
25}
26
27void arch_prepare_thread(struct thread *t,
Lee Leahy024b13d2017-03-16 13:41:11 -070028 asmlinkage void (*thread_entry)(void *), void *arg)
Aaron Durbin38c326d2013-05-06 12:22:23 -050029{
30 uintptr_t stack = t->stack_current;
31
32 /* Imitate thread_entry(t) with return address of 0. thread_entry()
33 * is assumed to never return. */
34 stack = push_stack(stack, (uintptr_t)arg);
35 stack = push_stack(stack, (uintptr_t)0);
36 stack = push_stack(stack, (uintptr_t)thread_entry);
Elyes HAOUAS2f79eb32018-08-07 12:24:42 +020037 /* Make room for the registers. Ignore initial values. */
Aaron Durbin38c326d2013-05-06 12:22:23 -050038 stack -= sizeof(struct pushad_regs);
39
40 t->stack_current = stack;
41}
Ronald G. Minnich34352d12013-08-21 16:03:32 -070042
43void *arch_get_thread_stackbase(void)
44{
45 /* defined in c_start.S */
46 extern u8 thread_stacks[];
47 return &thread_stacks[0];
48}