aboutsummaryrefslogtreecommitdiffstats
path: root/tests/tcg/multiarch/arm-compat-semi/semihosting.c
diff options
context:
space:
mode:
authorTimos Ampelikiotis <t.ampelikiotis@virtualopensystems.com>2023-10-10 11:40:56 +0000
committerTimos Ampelikiotis <t.ampelikiotis@virtualopensystems.com>2023-10-10 11:40:56 +0000
commite02cda008591317b1625707ff8e115a4841aa889 (patch)
treeaee302e3cf8b59ec2d32ec481be3d1afddfc8968 /tests/tcg/multiarch/arm-compat-semi/semihosting.c
parentcc668e6b7e0ffd8c9d130513d12053cf5eda1d3b (diff)
Introduce Virtio-loopback epsilon release:
Epsilon release introduces a new compatibility layer which make virtio-loopback design to work with QEMU and rust-vmm vhost-user backend without require any changes. Signed-off-by: Timos Ampelikiotis <t.ampelikiotis@virtualopensystems.com> Change-Id: I52e57563e08a7d0bdc002f8e928ee61ba0c53dd9
Diffstat (limited to 'tests/tcg/multiarch/arm-compat-semi/semihosting.c')
-rw-r--r--tests/tcg/multiarch/arm-compat-semi/semihosting.c82
1 files changed, 82 insertions, 0 deletions
diff --git a/tests/tcg/multiarch/arm-compat-semi/semihosting.c b/tests/tcg/multiarch/arm-compat-semi/semihosting.c
new file mode 100644
index 000000000..8627eee3c
--- /dev/null
+++ b/tests/tcg/multiarch/arm-compat-semi/semihosting.c
@@ -0,0 +1,82 @@
+/*
+ * linux-user semihosting checks
+ *
+ * Copyright (c) 2019
+ * Written by Alex Bennée <alex.bennee@linaro.org>
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#define SYS_WRITE0 0x04
+#define SYS_HEAPINFO 0x16
+#define SYS_REPORTEXC 0x18
+
+#include <stdint.h>
+#include <stdlib.h>
+#include <stdio.h>
+#include <string.h>
+#include "semicall.h"
+
+int main(int argc, char *argv[argc])
+{
+#if UINTPTR_MAX == UINT32_MAX
+ uintptr_t exit_code = 0x20026;
+#else
+ uintptr_t exit_block[2] = {0x20026, 0};
+ uintptr_t exit_code = (uintptr_t) &exit_block;
+#endif
+ struct {
+ void *heap_base;
+ void *heap_limit;
+ void *stack_base;
+ void *stack_limit;
+ } info;
+ void *ptr_to_info = (void *) &info;
+
+ __semi_call(SYS_WRITE0, (uintptr_t) "Checking HeapInfo\n");
+
+ memset(&info, 0, sizeof(info));
+ __semi_call(SYS_HEAPINFO, (uintptr_t) &ptr_to_info);
+
+ if (info.heap_base == NULL || info.heap_limit == NULL) {
+ printf("null heap: %p -> %p\n", info.heap_base, info.heap_limit);
+ exit(1);
+ }
+
+ /* Error if heap base is above limit */
+ if ((uintptr_t) info.heap_base >= (uintptr_t) info.heap_limit) {
+ printf("heap base %p >= heap_limit %p\n",
+ info.heap_base, info.heap_limit);
+ exit(2);
+ }
+
+ if (info.stack_base == NULL || info.stack_limit) {
+ printf("null stack: %p -> %p\n", info.stack_base, info.stack_limit);
+ exit(3);
+ }
+
+ /* check our local variables are indeed inside the reported stack */
+ if (ptr_to_info > info.stack_base) {
+ printf("info appears to be above stack: %p > %p\n", ptr_to_info,
+ info.stack_base);
+ exit(4);
+ } else if (ptr_to_info < info.stack_limit) {
+ printf("info appears to be outside stack: %p < %p\n", ptr_to_info,
+ info.stack_limit);
+ exit(5);
+ }
+
+ if (ptr_to_info > info.heap_base && ptr_to_info < info.heap_limit) {
+ printf("info appears to be inside the heap: %p in %p:%p\n",
+ ptr_to_info, info.heap_base, info.heap_limit);
+ exit(6);
+ }
+
+ printf("heap: %p -> %p\n", info.heap_base, info.heap_limit);
+ printf("stack: %p -> %p\n", info.stack_base, info.stack_limit);
+
+ __semi_call(SYS_WRITE0, (uintptr_t) "Passed HeapInfo checks");
+ __semi_call(SYS_REPORTEXC, exit_code);
+ /* if we get here we failed */
+ return -1;
+}