1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 3 #include <thread.h> 4 5 #if ENV_X86_64 6 #error COOP_MULTITASKING does not currently support x86_64 7 #endif 8 9 /* The stack frame looks like the following after a pushad instruction. */ 10 struct 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 push_stack(uintptr_t cur_stack,uintptr_t value)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 arch_prepare_thread(struct thread * t,asmlinkage void (* thread_entry)(void *),void * arg)31void arch_prepare_thread(struct thread *t, 32 asmlinkage void (*thread_entry)(void *), void *arg) 33 { 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); 41 /* Make room for the registers. Ignore initial values. */ 42 stack -= sizeof(struct pushad_regs); 43 44 t->stack_current = stack; 45 } 46