diff options
Diffstat (limited to 'semihosting/arm-compat-semi.c')
-rw-r--r-- | semihosting/arm-compat-semi.c | 91 |
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; } |