blob: fa6096161b0c6144a76918b3585b484b12b5db4d [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
Raul E Rangel6a01ac22021-07-23 10:09:45 -06005#if ENV_X86_64
6#error COOP_MULTITASKING does not currently support x86_64
7#endif
8
Aaron Durbin38c326d2013-05-06 12:22:23 -05009/* The stack frame looks like the following after a pushad instruction. */
10struct pushad_regs {
11 uint32_t edi; /* Offset 0x00 */
12 uint32_t esi; /* Offset 0x04 */
13 uint32_t ebp; /* Offset 0x08 */
14 uint32_t esp; /* Offset 0x0c */
15 uint32_t ebx; /* Offset 0x10 */
16 uint32_t edx; /* Offset 0x14 */
17 uint32_t ecx; /* Offset 0x18 */
18 uint32_t eax; /* Offset 0x1c */
19};
20
21static inline uintptr_t push_stack(uintptr_t cur_stack, uintptr_t value)
22{
23 uintptr_t *addr;
24
25 cur_stack -= sizeof(value);
26 addr = (uintptr_t *)cur_stack;
27 *addr = value;
28 return cur_stack;
29}
30
31void arch_prepare_thread(struct thread *t,
Lee Leahy024b13d2017-03-16 13:41:11 -070032 asmlinkage void (*thread_entry)(void *), void *arg)
Aaron Durbin38c326d2013-05-06 12:22:23 -050033{
34 uintptr_t stack = t->stack_current;
35
36 /* Imitate thread_entry(t) with return address of 0. thread_entry()
37 * is assumed to never return. */
38 stack = push_stack(stack, (uintptr_t)arg);
39 stack = push_stack(stack, (uintptr_t)0);
40 stack = push_stack(stack, (uintptr_t)thread_entry);
Elyes HAOUAS2f79eb32018-08-07 12:24:42 +020041 /* Make room for the registers. Ignore initial values. */
Aaron Durbin38c326d2013-05-06 12:22:23 -050042 stack -= sizeof(struct pushad_regs);
43
44 t->stack_current = stack;
45}