xref: /qemu/tests/tcg/aarch64/system/semiheap.c (revision 0b58dc456191042dc3b84aa2b80619b71f8b1e3d)
1b904a909SAlex Bennée /*
2b904a909SAlex Bennée  * Semihosting System HEAPINFO Test
3b904a909SAlex Bennée  *
4b904a909SAlex Bennée  * Copyright (c) 2021 Linaro Ltd
5b904a909SAlex Bennée  *
6b904a909SAlex Bennée  * SPDX-License-Identifier: GPL-2.0-or-later
7b904a909SAlex Bennée  */
8b904a909SAlex Bennée 
9bb52a8a2SPaolo Bonzini #include <stdint.h>
10b904a909SAlex Bennée #include <stddef.h>
11b904a909SAlex Bennée #include <minilib.h>
12b904a909SAlex Bennée 
13b904a909SAlex Bennée #define SYS_HEAPINFO    0x16
14b904a909SAlex Bennée 
__semi_call(uintptr_t type,uintptr_t arg0)15b904a909SAlex Bennée uintptr_t __semi_call(uintptr_t type, uintptr_t arg0)
16b904a909SAlex Bennée {
17b904a909SAlex Bennée     register uintptr_t t asm("x0") = type;
18b904a909SAlex Bennée     register uintptr_t a0 asm("x1") = arg0;
19b904a909SAlex Bennée     asm("hlt 0xf000"
20b904a909SAlex Bennée         : "=r" (t)
21b904a909SAlex Bennée         : "r" (t), "r" (a0)
22b904a909SAlex Bennée         : "memory" );
23b904a909SAlex Bennée 
24b904a909SAlex Bennée     return t;
25b904a909SAlex Bennée }
26b904a909SAlex Bennée 
main(int argc,char * argv[argc])27b904a909SAlex Bennée int main(int argc, char *argv[argc])
28b904a909SAlex Bennée {
29b904a909SAlex Bennée     struct {
30b904a909SAlex Bennée         void *heap_base;
31b904a909SAlex Bennée         void *heap_limit;
32b904a909SAlex Bennée         void *stack_base;
33b904a909SAlex Bennée         void *stack_limit;
34b904a909SAlex Bennée     } info = { };
35b904a909SAlex Bennée     void *ptr_to_info = (void *) &info;
36b904a909SAlex Bennée     uint32_t *ptr_to_heap;
37b904a909SAlex Bennée     int i;
38b904a909SAlex Bennée 
39b904a909SAlex Bennée     ml_printf("Semihosting Heap Info Test\n");
40b904a909SAlex Bennée 
41b904a909SAlex Bennée     __semi_call(SYS_HEAPINFO, (uintptr_t) &ptr_to_info);
42b904a909SAlex Bennée 
43b904a909SAlex Bennée     if (info.heap_base == NULL || info.heap_limit == NULL) {
44b904a909SAlex Bennée         ml_printf("null heap: %p -> %p\n", info.heap_base, info.heap_limit);
45b904a909SAlex Bennée         return -1;
46b904a909SAlex Bennée     }
47b904a909SAlex Bennée 
48b904a909SAlex Bennée     /* Error if heap base is above limit */
49b904a909SAlex Bennée     if ((uintptr_t) info.heap_base >= (uintptr_t) info.heap_limit) {
50b904a909SAlex Bennée         ml_printf("heap base %p >= heap_limit %p\n",
51b904a909SAlex Bennée                info.heap_base, info.heap_limit);
52b904a909SAlex Bennée         return -2;
53b904a909SAlex Bennée     }
54b904a909SAlex Bennée 
55b904a909SAlex Bennée     if (info.stack_base == NULL) {
56b904a909SAlex Bennée         ml_printf("null stack: %p -> %p\n", info.stack_base, info.stack_limit);
57b904a909SAlex Bennée         return -3;
58b904a909SAlex Bennée     }
59b904a909SAlex Bennée 
60b904a909SAlex Bennée     /*
61b904a909SAlex Bennée      * boot.S put our stack somewhere inside the data segment of the
62b904a909SAlex Bennée      * ELF file, and we know that SYS_HEAPINFO won't pick a range
63b904a909SAlex Bennée      * that overlaps with part of a loaded ELF file. So the info
64b904a909SAlex Bennée      * struct (on the stack) should not be inside the reported heap.
65b904a909SAlex Bennée      */
66b904a909SAlex Bennée     if (ptr_to_info > info.heap_base && ptr_to_info < info.heap_limit) {
67b904a909SAlex Bennée         ml_printf("info appears to be inside the heap: %p in %p:%p\n",
68b904a909SAlex Bennée                ptr_to_info, info.heap_base, info.heap_limit);
69b904a909SAlex Bennée         return -4;
70b904a909SAlex Bennée     }
71b904a909SAlex Bennée 
72b904a909SAlex Bennée     ml_printf("heap: %p -> %p\n", info.heap_base, info.heap_limit);
73b904a909SAlex Bennée     ml_printf("stack: %p <- %p\n", info.stack_limit, info.stack_base);
74b904a909SAlex Bennée 
75b904a909SAlex Bennée     /* finally can we read/write the heap */
76*3d558330SMarkus Armbruster     ptr_to_heap = info.heap_base;
77b904a909SAlex Bennée     for (i = 0; i < 512; i++) {
78b904a909SAlex Bennée         *ptr_to_heap++ = i;
79b904a909SAlex Bennée     }
80*3d558330SMarkus Armbruster     ptr_to_heap = info.heap_base;
81b904a909SAlex Bennée     for (i = 0; i < 512; i++) {
82b904a909SAlex Bennée         uint32_t tmp = *ptr_to_heap;
83b904a909SAlex Bennée         if (tmp != i) {
84b904a909SAlex Bennée             ml_printf("unexpected value in heap: %d @ %p", tmp, ptr_to_heap);
85b904a909SAlex Bennée             return -5;
86b904a909SAlex Bennée         }
87b904a909SAlex Bennée         ptr_to_heap++;
88b904a909SAlex Bennée     }
89b904a909SAlex Bennée     ml_printf("r/w to heap up to %p\n", ptr_to_heap);
90b904a909SAlex Bennée 
91b904a909SAlex Bennée     ml_printf("Passed HeapInfo checks\n");
92b904a909SAlex Bennée     return 0;
93b904a909SAlex Bennée }
94