1/*
2 * Copyright 2019, Data61
3 * Commonwealth Scientific and Industrial Research Organisation (CSIRO)
4 * ABN 41 687 119 230.
5 *
6 * This software may be distributed and modified according to the terms of
7 * the BSD 2-Clause license. Note that NO WARRANTY is provided.
8 * See "LICENSE_BSD2.txt" for details.
9 *
10 * @TAG(DATA61_BSD)
11 */
12
13#include <autoconf.h>
14/* test_registers (below) runs in a context without a valid SP. At the end it
15 * needs to call into a C function and needs a valid stack to do this. We
16 * provide it a stack it can switch to here.
17 */
18.section .bss
19.align  4
20.space 4096
21_safe_stack:
22.section .text
23#if defined(CONFIG_ARCH_AARCH32)
24
25/* Trampoline for providing the thread a valid stack before entering
26 * reply_to_parent. No blx required because reply_to_parent does not
27 * return.
28 */
29reply_trampoline:
30    ldr sp, =_safe_stack
31    b reply_to_parent
32
33.global test_registers
34test_registers:
35    /* Assume the PC and CPSR are correct because there's no good way of
36     * testing them. Test each of the registers against the magic numbers our
37     * parent set.
38     */
39    cmp sp, #13
40    bne test_registers_fail
41    cmp r0, #15
42    bne test_registers_fail
43    cmp r1, #1
44    bne test_registers_fail
45    cmp r2, #2
46    bne test_registers_fail
47    cmp r3, #3
48    bne test_registers_fail
49    cmp r4, #4
50    bne test_registers_fail
51    cmp r5, #5
52    bne test_registers_fail
53    cmp r6, #6
54    bne test_registers_fail
55    cmp r7, #7
56    bne test_registers_fail
57    cmp r8, #8
58    bne test_registers_fail
59    cmp r9, #9
60    bne test_registers_fail
61    cmp r10, #10
62    bne test_registers_fail
63    cmp r11, #11
64    bne test_registers_fail
65    cmp r12, #12
66    bne test_registers_fail
67    cmp r14, #14
68    bne test_registers_fail
69
70    /* Return success. Note that we don't bother saving registers or bl because
71     * we're not planning to return here and we don't have a valid stack.
72     */
73    mov r0, #0
74    b reply_trampoline
75
76    /* Return failure. */
77test_registers_fail:
78    mov r0, #1
79    b reply_trampoline
80
81#elif defined(CONFIG_ARCH_AARCH64)
82    /* Trampoline for providing the thread a valid stack before entering
83     * reply_to_parent. No blx required because reply_to_parent does not
84     * return.
85     */
86reply_trampoline:
87    ldr x1, =_safe_stack
88    mov sp, x1
89    b reply_to_parent
90
91.global test_registers
92test_registers:
93    cmp sp, #1
94    bne test_registers_fail
95    cmp x0, #2
96    bne test_registers_fail
97    cmp x1, #3
98    bne test_registers_fail
99    cmp x2, #4
100    bne test_registers_fail
101    cmp x3, #5
102    bne test_registers_fail
103    cmp x4, #6
104    bne test_registers_fail
105    cmp x5, #7
106    bne test_registers_fail
107    cmp x6, #8
108    bne test_registers_fail
109    cmp x7, #9
110    bne test_registers_fail
111    cmp x8, #10
112    bne test_registers_fail
113    cmp x9, #11
114    bne test_registers_fail
115    cmp x10, #12
116    bne test_registers_fail
117    cmp x11, #13
118    bne test_registers_fail
119    cmp x12, #14
120    bne test_registers_fail
121    cmp x13, #15
122    bne test_registers_fail
123    cmp x14, #16
124    bne test_registers_fail
125    cmp x15, #17
126    bne test_registers_fail
127    cmp x16, #18
128    bne test_registers_fail
129    cmp x17, #19
130    bne test_registers_fail
131    cmp x18, #20
132    bne test_registers_fail
133    cmp x19, #21
134    bne test_registers_fail
135    cmp x20, #22
136    bne test_registers_fail
137    cmp x21, #23
138    bne test_registers_fail
139    cmp x22, #24
140    bne test_registers_fail
141    cmp x23, #25
142    bne test_registers_fail
143    cmp x24, #26
144    bne test_registers_fail
145    cmp x25, #27
146    bne test_registers_fail
147    cmp x26, #28
148    bne test_registers_fail
149    cmp x27, #29
150    bne test_registers_fail
151    cmp x28, #30
152    bne test_registers_fail
153    cmp x29, #31
154    bne test_registers_fail
155    cmp x30, #32
156    bne test_registers_fail
157
158    /* Return success. Note that we don't bother saving registers or bl because
159     * we're not planning to return here and we don't have a valid stack.
160     */
161    mov x0, #0
162    b reply_trampoline
163
164/* Return failure. */
165test_registers_fail:
166    mov x0, #1
167    b reply_trampoline
168
169#elif defined(CONFIG_ARCH_X86_64)
170reply_trampoline:
171    leaq  _safe_stack, %rsp
172    movq  %rax, %rdi
173    call  reply_to_parent
174.global test_registers
175test_registers:
176    jb    rflags_ok
177    jmp   test_registers_fail
178    rflags_ok:
179    cmpq  $0x0000000a, %rax
180    jne   test_registers_fail
181    movq  $2, %rax
182    cmpq  $0x0000000b, %rbx
183    jne   test_registers_fail
184    movq  $3, %rax
185    cmpq  $0x0000000c, %rcx
186    jne   test_registers_fail
187    movq  $4, %rax
188    cmpq  $0x0000000d, %rdx
189    jne   test_registers_fail
190    movq  $5, %rax
191    cmpq  $0x00000005, %rsi
192    jne   test_registers_fail
193    movq  $6, %rax
194    cmpq  $0x00000002, %rdi
195    jne   test_registers_fail
196    movq  $7, %rax
197    cmpq  $0x00000003, %rbp
198    jne   test_registers_fail
199    movq  $8, %rax
200    cmpq  $0x00000004, %rsp
201    jne   test_registers_fail
202    movq  $9, %rax
203    cmpq  $0x00000088, %r8
204    jne   test_registers_fail
205    movq  $100, %rax
206    cmpq  $0x00000099, %r9
207    jne   test_registers_fail
208    movq  $11, %rax
209    cmpq  $0x00000010, %r10
210    jne   test_registers_fail
211    movq  $12, %rax
212    cmpq  $0x00000011, %r11
213    jne   test_registers_fail
214    movq  $13, %rax
215    cmpq  $0x00000012, %r12
216    jne   test_registers_fail
217    movq  $14, %rax
218    cmpq  $0x00000013, %r13
219    jne   test_registers_fail
220    movq  $15, %rax
221    cmpq  $0x00000014, %r14
222    jne   test_registers_fail
223    movq  $16, %rax
224    cmpq  $0x00000015, %r15
225    jne   test_registers_fail
226    movq  $0, %rax
227    jmp   reply_trampoline
228    test_registers_fail:
229    movq  $1, %rax
230    jmp   reply_trampoline
231
232#elif defined(CONFIG_ARCH_X86)
233    /* As for the ARM implementation above, but we also need to massage the
234     * calling convention by taking the value test_registers passed us in EAX
235     * and put it on the stack where reply_to_parent expects it.
236     */
237reply_trampoline:
238    leal _safe_stack, %esp
239    pushl %eax
240    call reply_to_parent
241
242.global test_registers
243test_registers:
244    /* Assume EIP, GS and FS are correct. Is there a good way to
245     * test these?
246     *  EIP - If this is incorrect we'll never arrive at this function.
247     *  GS - With an incorrect GDT selector we fault and die immediately.
248     *  FS - Overwritten by the kernel before we jump here.
249     */
250
251    /* We need to test EFLAGS indirectly because we can't cmp it. The jb
252     * should only be taken if CF (bit 0) is set.
253     */
254    jb eflags_ok
255    jmp test_registers_fail
256    eflags_ok:
257    cmpl $0x0000000a, %eax
258    jne test_registers_fail
259    cmpl $0x0000000b, %ebx
260    jne test_registers_fail
261    cmpl $0x0000000c, %ecx
262    jne test_registers_fail
263    cmpl $0x0000000d, %edx
264    jne test_registers_fail
265    cmpl $0x00000005, %esi
266    jne test_registers_fail
267    cmpl $0x00000002, %edi
268    jne test_registers_fail
269    cmpl $0x00000003, %ebp
270    jne test_registers_fail
271    cmpl $0x00000004, %esp
272    jne test_registers_fail
273
274    /* Return success. Note we use a custom calling convention because we
275     * don't have a valid stack.
276     */
277    movl $0, %eax
278    jmp reply_trampoline
279
280    /* Return failure. */
281test_registers_fail:
282    movl $1, %eax
283    jmp reply_trampoline
284#elif defined(CONFIG_ARCH_RISCV)
285/* Trampoline for providing the thread a valid stack before entering
286 * reply_to_parent. No jal required because reply_to_parent does not
287 * return.
288 */
289reply_trampoline:
290    la a1, _safe_stack
291    mv sp, a1
292    j reply_to_parent
293
294.global test_registers
295test_registers:
296
297    li a0, 1
298    bne ra, a0, test_registers_fail
299    li a0, 2
300    bne sp, a0, test_registers_fail
301    li a0, 4
302    bne t0, a0, test_registers_fail
303    li a0, 5
304    bne t1, a0, test_registers_fail
305    li a0, 6
306    bne t2, a0, test_registers_fail
307    li a0, 7
308    bne s0, a0, test_registers_fail
309    li a0, 8
310    bne s1, a0, test_registers_fail
311    li a0, 10
312    bne a1, a0, test_registers_fail
313    li a0, 11
314    bne a2, a0, test_registers_fail
315    li a0, 12
316    bne a0, a3, test_registers_fail
317    li a0, 13
318    bne a0, a4, test_registers_fail
319    li a0, 14
320    bne a0, a5, test_registers_fail
321    li a0, 15
322    bne a0, a6, test_registers_fail
323#if 0
324    /* skip x3, see below */
325    context.x4 = 3;
326#endif
327
328    /* Return success. Note that we don't bother saving registers or bl because
329     * we're not planning to return here and we don't have a valid stack.
330     */
331    mv a0, x0
332    j reply_trampoline
333
334    /* Return failure. */
335test_registers_fail:
336    li a0, 1
337    j reply_trampoline
338
339#else
340#error Unsupported architecture
341#endif
342
343