xref: /openbmc/qemu/tests/tcg/multiarch/arm-compat-semi/semihosting.c (revision d316f1b14615854de1bf4c0a9789e9c8951cc437)
13539d84dSAlex Bennée /*
23539d84dSAlex Bennée  * linux-user semihosting checks
33539d84dSAlex Bennée  *
4*542b10bdSAlex Bennée  * Copyright (c) 2019, 2024
53539d84dSAlex Bennée  * Written by Alex Bennée <alex.bennee@linaro.org>
63539d84dSAlex Bennée  *
7*542b10bdSAlex Bennée  * SPDX-License-Identifier: GPL-2.0-or-later
83539d84dSAlex Bennée  */
93539d84dSAlex Bennée 
103539d84dSAlex Bennée #define SYS_WRITE0      0x04
114593f4d7SAlex Bennée #define SYS_HEAPINFO    0x16
123539d84dSAlex Bennée #define SYS_REPORTEXC   0x18
133539d84dSAlex Bennée 
143539d84dSAlex Bennée #include <stdint.h>
154593f4d7SAlex Bennée #include <stdlib.h>
164593f4d7SAlex Bennée #include <stdio.h>
174593f4d7SAlex Bennée #include <string.h>
183539d84dSAlex Bennée #include "semicall.h"
193539d84dSAlex Bennée 
main(int argc,char * argv[argc])203539d84dSAlex Bennée int main(int argc, char *argv[argc])
213539d84dSAlex Bennée {
223539d84dSAlex Bennée #if UINTPTR_MAX == UINT32_MAX
233539d84dSAlex Bennée     uintptr_t exit_code = 0x20026;
243539d84dSAlex Bennée #else
253539d84dSAlex Bennée     uintptr_t exit_block[2] = {0x20026, 0};
263539d84dSAlex Bennée     uintptr_t exit_code = (uintptr_t) &exit_block;
273539d84dSAlex Bennée #endif
284593f4d7SAlex Bennée     struct {
294593f4d7SAlex Bennée         void *heap_base;
304593f4d7SAlex Bennée         void *heap_limit;
314593f4d7SAlex Bennée         void *stack_base;
324593f4d7SAlex Bennée         void *stack_limit;
334593f4d7SAlex Bennée     } info;
344593f4d7SAlex Bennée     void *ptr_to_info = (void *) &info;
353539d84dSAlex Bennée 
364593f4d7SAlex Bennée     __semi_call(SYS_WRITE0, (uintptr_t) "Checking HeapInfo\n");
374593f4d7SAlex Bennée 
384593f4d7SAlex Bennée     memset(&info, 0, sizeof(info));
394593f4d7SAlex Bennée     __semi_call(SYS_HEAPINFO, (uintptr_t) &ptr_to_info);
404593f4d7SAlex Bennée 
414593f4d7SAlex Bennée     if (info.heap_base == NULL || info.heap_limit == NULL) {
424593f4d7SAlex Bennée         printf("null heap: %p -> %p\n", info.heap_base, info.heap_limit);
434593f4d7SAlex Bennée         exit(1);
444593f4d7SAlex Bennée     }
454593f4d7SAlex Bennée 
464593f4d7SAlex Bennée     /* Error if heap base is above limit */
474593f4d7SAlex Bennée     if ((uintptr_t) info.heap_base >= (uintptr_t) info.heap_limit) {
484593f4d7SAlex Bennée         printf("heap base %p >= heap_limit %p\n",
494593f4d7SAlex Bennée                info.heap_base, info.heap_limit);
504593f4d7SAlex Bennée         exit(2);
514593f4d7SAlex Bennée     }
524593f4d7SAlex Bennée 
534593f4d7SAlex Bennée     if (info.stack_base == NULL || info.stack_limit) {
544593f4d7SAlex Bennée         printf("null stack: %p -> %p\n", info.stack_base, info.stack_limit);
554593f4d7SAlex Bennée         exit(3);
564593f4d7SAlex Bennée     }
574593f4d7SAlex Bennée 
584593f4d7SAlex Bennée     /* check our local variables are indeed inside the reported stack */
594593f4d7SAlex Bennée     if (ptr_to_info > info.stack_base) {
604593f4d7SAlex Bennée         printf("info appears to be above stack: %p > %p\n", ptr_to_info,
614593f4d7SAlex Bennée                info.stack_base);
624593f4d7SAlex Bennée         exit(4);
634593f4d7SAlex Bennée     } else if (ptr_to_info < info.stack_limit) {
644593f4d7SAlex Bennée         printf("info appears to be outside stack: %p < %p\n", ptr_to_info,
654593f4d7SAlex Bennée                info.stack_limit);
664593f4d7SAlex Bennée         exit(5);
674593f4d7SAlex Bennée     }
684593f4d7SAlex Bennée 
694593f4d7SAlex Bennée     if (ptr_to_info > info.heap_base && ptr_to_info < info.heap_limit) {
704593f4d7SAlex Bennée         printf("info appears to be inside the heap: %p in %p:%p\n",
714593f4d7SAlex Bennée                ptr_to_info, info.heap_base, info.heap_limit);
724593f4d7SAlex Bennée         exit(6);
734593f4d7SAlex Bennée     }
744593f4d7SAlex Bennée 
754593f4d7SAlex Bennée     printf("heap: %p -> %p\n", info.heap_base, info.heap_limit);
764593f4d7SAlex Bennée     printf("stack: %p -> %p\n", info.stack_base, info.stack_limit);
774593f4d7SAlex Bennée 
784593f4d7SAlex Bennée     __semi_call(SYS_WRITE0, (uintptr_t) "Passed HeapInfo checks");
793539d84dSAlex Bennée     __semi_call(SYS_REPORTEXC, exit_code);
803539d84dSAlex Bennée     /* if we get here we failed */
813539d84dSAlex Bennée     return -1;
823539d84dSAlex Bennée }
83