mb/amd/padmelon: Drop unnecessary `PADMELON_SOC_IN_USE` option
[coreboot.git] / src / arch / arm / armv7 / thread.c
blob63ef7a83b82d7a438381b2dd66bb6089c65e83f2
1 /* SPDX-License-Identifier: GPL-2.0-only */
3 #include <thread.h>
5 /* The stack frame looks like the following. */
6 struct pushed_regs {
7 u32 r4;
8 u32 r5;
9 u32 r6;
10 u32 r7;
11 u32 r8;
12 u32 r9;
13 u32 r10;
14 u32 r11;
15 u32 lr;
18 static inline uintptr_t push_stack(uintptr_t cur_stack, uintptr_t value)
20 uintptr_t *addr;
22 cur_stack -= sizeof(value);
23 addr = (uintptr_t *)cur_stack;
24 *addr = value;
25 return cur_stack;
28 void arch_prepare_thread(struct thread *t,
29 void asmlinkage(*thread_entry)(void *), void *arg)
31 uintptr_t stack = t->stack_current;
32 int i;
33 uintptr_t poison = 0xdeadbeef;
35 /* Push the LR. thread_entry()
36 * is assumed to never return.
38 stack = push_stack(stack, (uintptr_t)thread_entry);
39 /* Make room for the registers.
40 * Poison the initial stack. This is good hygiene and finds bugs.
41 * Poisoning the stack with different values helps when you're
42 * hunting for (e.g.) misaligned stacks or other such
43 * weirdness. The -1 is because we already pushed lr.
45 for (i = 0; i < sizeof(struct pushed_regs) / sizeof(u32) - 1; i++)
46 stack = push_stack(stack, poison++);
48 t->stack_current = stack;
51 /* We could write this as a .S and the first time around that's how we
52 * did it. But there's always the question of matching our ARM
53 * directives in the .S with how gcc is doing things. It seems best
54 * to follow the pattern of the rest of the ARM port and just use
55 * inline assembly and let gcc get all the ELF magic right.
57 void __attribute__((naked))
58 switch_to_thread(uintptr_t new_stack, uintptr_t *saved_stack)
60 /* Definitions for those of us not totally familiar with ARM:
61 * R15 -- PC, R14 -- LR, R13 -- SP
62 * R0-R3 need not be saved, nor R12.
63 * on entry, the only saved state is in LR -- the old PC.
64 * The args are in R0,R1.
65 * R0 is the new stack
66 * R1 is a pointer to the old stack save location
67 * Push R4-R11 and LR
68 * then switch stacks
69 * then pop R0-R12 and LR
70 * then mov PC,LR
72 * stack layout
73 * +------------+
74 * | LR | <-- sp + 0x20
75 * +------------+
76 * | R11 | <-- sp + 0x1c
77 * +------------+
78 * | R10 | <-- sp + 0x18
79 * +------------+
80 * | R9 | <-- sp + 0x14
81 * +------------+
82 * | R8 | <-- sp + 0x10
83 * +------------+
84 * | R7 | <-- sp + 0x0c
85 * +------------+
86 * | R6 | <-- sp + 0x08
87 * +------------+
88 * | R5 | <-- sp + 0x04
89 * +------------+
90 * | R4 | <-- sp + 0x00
91 * +------------+
93 asm volatile (
94 /* save context. */
95 "push {r4-r11,lr}\n\t"
96 /* Save the current stack */
97 "str sp,[r1]\n\t"
98 /* switch to the new stack */
99 "mov sp,r0\n\t"
100 /* restore the registers */
101 "pop {r4-r11,lr}\n\t"
102 /* resume other thread. */
103 "mov pc,lr\n\t"
107 void *arch_get_thread_stackbase(void)
109 return (void *)CONFIG_STACK_BOTTOM;