aboutsummaryrefslogtreecommitdiff
path: root/semihosting/arm-compat-semi.c
diff options
context:
space:
mode:
Diffstat (limited to 'semihosting/arm-compat-semi.c')
-rw-r--r--semihosting/arm-compat-semi.c91
1 files changed, 60 insertions, 31 deletions
diff --git a/semihosting/arm-compat-semi.c b/semihosting/arm-compat-semi.c
index 86e5260..6100126 100644
--- a/semihosting/arm-compat-semi.c
+++ b/semihosting/arm-compat-semi.c
@@ -100,6 +100,13 @@ static int gdb_open_modeflags[12] = {
GDB_O_RDWR | GDB_O_CREAT | GDB_O_APPEND,
};
+/*
+ * For ARM semihosting, we have a separate structure for routing
+ * data for the console which is outside the guest fd address space.
+ */
+static GuestFD console_in_gf;
+static GuestFD console_out_gf;
+
#ifndef CONFIG_USER_ONLY
/**
@@ -115,7 +122,7 @@ static int gdb_open_modeflags[12] = {
*/
typedef struct LayoutInfo {
- target_ulong rambase;
+ vaddr rambase;
size_t ramsize;
hwaddr heapbase;
hwaddr heaplimit;
@@ -166,8 +173,7 @@ static LayoutInfo common_semi_find_bases(CPUState *cs)
#endif
-#include "cpu.h"
-#include "common-semi-target.h"
+#include "semihosting/common-semi.h"
/*
* Read the input value from the argument block; fail the semihosting
@@ -207,7 +213,7 @@ static LayoutInfo common_semi_find_bases(CPUState *cs)
* global, and we assume that the guest takes care of avoiding any races.
*/
#ifndef CONFIG_USER_ONLY
-static target_ulong syscall_err;
+static uint64_t syscall_err;
#include "semihosting/uaccess.h"
#endif
@@ -253,8 +259,8 @@ static void common_semi_rw_cb(CPUState *cs, uint64_t ret, int err)
{
/* Recover the original length from the third argument. */
CPUArchState *env G_GNUC_UNUSED = cpu_env(cs);
- target_ulong args = common_semi_arg(cs, 1);
- target_ulong arg2;
+ uint64_t args = common_semi_arg(cs, 1);
+ uint64_t arg2;
GET_ARG(2);
if (err) {
@@ -293,9 +299,9 @@ static void common_semi_seek_cb(CPUState *cs, uint64_t ret, int err)
* is defined by GDB's remote protocol and is not target-specific.)
* We put this on the guest's stack just below SP.
*/
-static target_ulong common_semi_flen_buf(CPUState *cs)
+static uint64_t common_semi_flen_buf(CPUState *cs)
{
- target_ulong sp = common_semi_stack_bottom(cs);
+ vaddr sp = common_semi_stack_bottom(cs);
return sp - 64;
}
@@ -352,6 +358,25 @@ static const uint8_t featurefile_data[] = {
SH_EXT_EXIT_EXTENDED | SH_EXT_STDOUT_STDERR, /* Feature byte 0 */
};
+bool semihosting_arm_compatible(void)
+{
+ return true;
+}
+
+void semihosting_arm_compatible_init(void)
+{
+ /* For ARM-compat, the console is in a separate namespace. */
+ if (use_gdb_syscalls()) {
+ console_in_gf.type = GuestFDGDB;
+ console_in_gf.hostfd = 0;
+ console_out_gf.type = GuestFDGDB;
+ console_out_gf.hostfd = 2;
+ } else {
+ console_in_gf.type = GuestFDConsole;
+ console_out_gf.type = GuestFDConsole;
+ }
+}
+
/*
* Do a semihosting call.
*
@@ -363,9 +388,9 @@ static const uint8_t featurefile_data[] = {
void do_common_semihosting(CPUState *cs)
{
CPUArchState *env = cpu_env(cs);
- target_ulong args;
- target_ulong arg0, arg1, arg2, arg3;
- target_ulong ul_ret;
+ uint64_t args;
+ uint64_t arg0, arg1, arg2, arg3;
+ uint64_t ul_ret;
char * s;
int nr;
int64_t elapsed;
@@ -436,7 +461,7 @@ void do_common_semihosting(CPUState *cs)
case TARGET_SYS_WRITEC:
/*
- * FIXME: the byte to be written is in a target_ulong slot,
+ * FIXME: the byte to be written is in a uint64_t slot,
* which means this is wrong for a big-endian guest.
*/
semihost_sys_write_gf(cs, common_semi_dead_cb,
@@ -475,10 +500,13 @@ void do_common_semihosting(CPUState *cs)
break;
case TARGET_SYS_ISERROR:
+ {
GET_ARG(0);
- common_semi_set_ret(cs, (target_long)arg0 < 0);
+ bool ret = is_64bit_semihosting(env) ?
+ (int64_t)arg0 < 0 : (int32_t)arg0 < 0;
+ common_semi_set_ret(cs, ret);
break;
-
+ }
case TARGET_SYS_ISTTY:
GET_ARG(0);
semihost_sys_isatty(cs, common_semi_istty_cb, arg0);
@@ -662,11 +690,11 @@ void do_common_semihosting(CPUState *cs)
case TARGET_SYS_HEAPINFO:
{
- target_ulong retvals[4];
+ uint64_t retvals[4];
int i;
#ifdef CONFIG_USER_ONLY
TaskState *ts = get_task_state(cs);
- target_ulong limit;
+ static abi_ulong heapbase, heaplimit;
#else
LayoutInfo info = common_semi_find_bases(cs);
#endif
@@ -678,25 +706,25 @@ void do_common_semihosting(CPUState *cs)
* Some C libraries assume the heap immediately follows .bss, so
* allocate it using sbrk.
*/
- if (!ts->heap_limit) {
- abi_ulong ret;
-
- ts->heap_base = do_brk(0);
- limit = ts->heap_base + COMMON_SEMI_HEAP_SIZE;
+ if (!heaplimit) {
+ heapbase = do_brk(0);
/* Try a big heap, and reduce the size if that fails. */
- for (;;) {
- ret = do_brk(limit);
+ for (abi_ulong size = COMMON_SEMI_HEAP_SIZE; ; size >>= 1) {
+ abi_ulong limit = heapbase + size;
+ abi_ulong ret = do_brk(limit);
if (ret >= limit) {
+ heaplimit = limit;
break;
}
- limit = (ts->heap_base >> 1) + (limit >> 1);
}
- ts->heap_limit = limit;
}
-
- retvals[0] = ts->heap_base;
- retvals[1] = ts->heap_limit;
- retvals[2] = ts->stack_base;
+ retvals[0] = heapbase;
+ retvals[1] = heaplimit;
+ /*
+ * Note that semihosting is *not* thread aware.
+ * Always return the stack base of the main thread.
+ */
+ retvals[2] = ts->info->start_stack;
retvals[3] = 0; /* Stack limit. */
#else
retvals[0] = info.heapbase; /* Heap Base */
@@ -728,7 +756,8 @@ void do_common_semihosting(CPUState *cs)
{
uint32_t ret;
- if (common_semi_sys_exit_extended(cs, nr)) {
+ if (nr == TARGET_SYS_EXIT_EXTENDED ||
+ common_semi_sys_exit_is_extended(cs)) {
/*
* The A64 version of SYS_EXIT takes a parameter block,
* so the application-exit type can return a subcode which
@@ -759,7 +788,7 @@ void do_common_semihosting(CPUState *cs)
case TARGET_SYS_ELAPSED:
elapsed = get_clock() - clock_start;
- if (sizeof(target_ulong) == 8) {
+ if (is_64bit_semihosting(env)) {
if (SET_ARG(0, elapsed)) {
goto do_fault;
}