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