2 * Semihosting System HEAPINFO Test
4 * Copyright (c) 2021 Linaro Ltd
6 * SPDX-License-Identifier: GPL-2.0-or-later
13 #define SYS_HEAPINFO 0x16
15 uintptr_t __semi_call(uintptr_t type
, uintptr_t arg0
)
17 register uintptr_t t
asm("x0") = type
;
18 register uintptr_t a0
asm("x1") = arg0
;
27 int main(int argc
, char *argv
[argc
])
35 void *ptr_to_info
= (void *) &info
;
36 uint32_t *ptr_to_heap
;
39 ml_printf("Semihosting Heap Info Test\n");
41 __semi_call(SYS_HEAPINFO
, (uintptr_t) &ptr_to_info
);
43 if (info
.heap_base
== NULL
|| info
.heap_limit
== NULL
) {
44 ml_printf("null heap: %p -> %p\n", info
.heap_base
, info
.heap_limit
);
48 /* Error if heap base is above limit */
49 if ((uintptr_t) info
.heap_base
>= (uintptr_t) info
.heap_limit
) {
50 ml_printf("heap base %p >= heap_limit %p\n",
51 info
.heap_base
, info
.heap_limit
);
55 if (info
.stack_base
== NULL
) {
56 ml_printf("null stack: %p -> %p\n", info
.stack_base
, info
.stack_limit
);
61 * boot.S put our stack somewhere inside the data segment of the
62 * ELF file, and we know that SYS_HEAPINFO won't pick a range
63 * that overlaps with part of a loaded ELF file. So the info
64 * struct (on the stack) should not be inside the reported heap.
66 if (ptr_to_info
> info
.heap_base
&& ptr_to_info
< info
.heap_limit
) {
67 ml_printf("info appears to be inside the heap: %p in %p:%p\n",
68 ptr_to_info
, info
.heap_base
, info
.heap_limit
);
72 ml_printf("heap: %p -> %p\n", info
.heap_base
, info
.heap_limit
);
73 ml_printf("stack: %p <- %p\n", info
.stack_limit
, info
.stack_base
);
75 /* finally can we read/write the heap */
76 ptr_to_heap
= info
.heap_base
;
77 for (i
= 0; i
< 512; i
++) {
80 ptr_to_heap
= info
.heap_base
;
81 for (i
= 0; i
< 512; i
++) {
82 uint32_t tmp
= *ptr_to_heap
;
84 ml_printf("unexpected value in heap: %d @ %p", tmp
, ptr_to_heap
);
89 ml_printf("r/w to heap upto %p\n", ptr_to_heap
);
91 ml_printf("Passed HeapInfo checks\n");