target-arm/arm-semi.c: Support widening APIs to 64 bits
The 64-bit A64 semihosting API has some pervasive changes from the 32-bit version: * all parameter blocks are arrays of 64-bit values, not 32-bit * the semihosting call number is passed in W0 * the return value is a 64-bit value in X0 Implement the necessary handling for this widening. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Christopher Covington <christopher.covington@linaro.org> Tested-by: Christopher Covington <cov@codeaurora.org> Message-id: 1439483745-28752-7-git-send-email-peter.maydell@linaro.org
This commit is contained in:
parent
44d4a499b7
commit
faacc04161
@ -134,7 +134,7 @@ static void arm_semi_cb(CPUState *cs, target_ulong ret, target_ulong err)
|
|||||||
#ifdef CONFIG_USER_ONLY
|
#ifdef CONFIG_USER_ONLY
|
||||||
TaskState *ts = cs->opaque;
|
TaskState *ts = cs->opaque;
|
||||||
#endif
|
#endif
|
||||||
target_ulong reg0 = env->regs[0];
|
target_ulong reg0 = is_a64(env) ? env->xregs[0] : env->regs[0];
|
||||||
|
|
||||||
if (ret == (target_ulong)-1) {
|
if (ret == (target_ulong)-1) {
|
||||||
#ifdef CONFIG_USER_ONLY
|
#ifdef CONFIG_USER_ONLY
|
||||||
@ -158,7 +158,30 @@ static void arm_semi_cb(CPUState *cs, target_ulong ret, target_ulong err)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
env->regs[0] = reg0;
|
if (is_a64(env)) {
|
||||||
|
env->xregs[0] = reg0;
|
||||||
|
} else {
|
||||||
|
env->regs[0] = reg0;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
static target_ulong arm_flen_buf(ARMCPU *cpu)
|
||||||
|
{
|
||||||
|
/* Return an address in target memory of 64 bytes where the remote
|
||||||
|
* gdb should write its stat struct. (The format of this structure
|
||||||
|
* is defined by GDB's remote protocol and is not target-specific.)
|
||||||
|
* We put this on the guest's stack just below SP.
|
||||||
|
*/
|
||||||
|
CPUARMState *env = &cpu->env;
|
||||||
|
target_ulong sp;
|
||||||
|
|
||||||
|
if (is_a64(env)) {
|
||||||
|
sp = env->xregs[31];
|
||||||
|
} else {
|
||||||
|
sp = env->regs[13];
|
||||||
|
}
|
||||||
|
|
||||||
|
return sp - 64;
|
||||||
}
|
}
|
||||||
|
|
||||||
static void arm_semi_flen_cb(CPUState *cs, target_ulong ret, target_ulong err)
|
static void arm_semi_flen_cb(CPUState *cs, target_ulong ret, target_ulong err)
|
||||||
@ -168,8 +191,13 @@ static void arm_semi_flen_cb(CPUState *cs, target_ulong ret, target_ulong err)
|
|||||||
/* The size is always stored in big-endian order, extract
|
/* The size is always stored in big-endian order, extract
|
||||||
the value. We assume the size always fit in 32 bits. */
|
the value. We assume the size always fit in 32 bits. */
|
||||||
uint32_t size;
|
uint32_t size;
|
||||||
cpu_memory_rw_debug(cs, env->regs[13]-64+32, (uint8_t *)&size, 4, 0);
|
cpu_memory_rw_debug(cs, arm_flen_buf(cpu) + 32, (uint8_t *)&size, 4, 0);
|
||||||
env->regs[0] = be32_to_cpu(size);
|
size = be32_to_cpu(size);
|
||||||
|
if (is_a64(env)) {
|
||||||
|
env->xregs[0] = size;
|
||||||
|
} else {
|
||||||
|
env->regs[0] = size;
|
||||||
|
}
|
||||||
#ifdef CONFIG_USER_ONLY
|
#ifdef CONFIG_USER_ONLY
|
||||||
((TaskState *)cs->opaque)->swi_errno = err;
|
((TaskState *)cs->opaque)->swi_errno = err;
|
||||||
#else
|
#else
|
||||||
@ -193,20 +221,30 @@ static target_ulong arm_gdb_syscall(ARMCPU *cpu, gdb_syscall_complete_cb cb,
|
|||||||
* the callback function.
|
* the callback function.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
return env->regs[0];
|
return is_a64(env) ? env->xregs[0] : env->regs[0];
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Read the input value from the argument block; fail the semihosting
|
/* Read the input value from the argument block; fail the semihosting
|
||||||
* call if the memory read fails.
|
* call if the memory read fails.
|
||||||
*/
|
*/
|
||||||
#define GET_ARG(n) do { \
|
#define GET_ARG(n) do { \
|
||||||
if (get_user_ual(arg ## n, args + (n) * 4)) { \
|
if (is_a64(env)) { \
|
||||||
return (uint32_t)-1; \
|
if (get_user_u64(arg ## n, args + (n) * 8)) { \
|
||||||
|
return -1; \
|
||||||
|
} \
|
||||||
|
} else { \
|
||||||
|
if (get_user_u32(arg ## n, args + (n) * 4)) { \
|
||||||
|
return -1; \
|
||||||
|
} \
|
||||||
} \
|
} \
|
||||||
} while (0)
|
} while (0)
|
||||||
|
|
||||||
#define SET_ARG(n, val) put_user_ual(val, args + (n) * 4)
|
#define SET_ARG(n, val) \
|
||||||
uint32_t do_arm_semihosting(CPUARMState *env)
|
(is_a64(env) ? \
|
||||||
|
put_user_u64(val, args + (n) * 8) : \
|
||||||
|
put_user_u32(val, args + (n) * 4))
|
||||||
|
|
||||||
|
target_ulong do_arm_semihosting(CPUARMState *env)
|
||||||
{
|
{
|
||||||
ARMCPU *cpu = arm_env_get_cpu(env);
|
ARMCPU *cpu = arm_env_get_cpu(env);
|
||||||
CPUState *cs = CPU(cpu);
|
CPUState *cs = CPU(cpu);
|
||||||
@ -222,8 +260,15 @@ uint32_t do_arm_semihosting(CPUARMState *env)
|
|||||||
CPUARMState *ts = env;
|
CPUARMState *ts = env;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
nr = env->regs[0];
|
if (is_a64(env)) {
|
||||||
args = env->regs[1];
|
/* Note that the syscall number is in W0, not X0 */
|
||||||
|
nr = env->xregs[0] & 0xffffffffU;
|
||||||
|
args = env->xregs[1];
|
||||||
|
} else {
|
||||||
|
nr = env->regs[0];
|
||||||
|
args = env->regs[1];
|
||||||
|
}
|
||||||
|
|
||||||
switch (nr) {
|
switch (nr) {
|
||||||
case TARGET_SYS_OPEN:
|
case TARGET_SYS_OPEN:
|
||||||
GET_ARG(0);
|
GET_ARG(0);
|
||||||
@ -355,7 +400,7 @@ uint32_t do_arm_semihosting(CPUARMState *env)
|
|||||||
GET_ARG(0);
|
GET_ARG(0);
|
||||||
if (use_gdb_syscalls()) {
|
if (use_gdb_syscalls()) {
|
||||||
return arm_gdb_syscall(cpu, arm_semi_flen_cb, "fstat,%x,%x",
|
return arm_gdb_syscall(cpu, arm_semi_flen_cb, "fstat,%x,%x",
|
||||||
arg0, env->regs[13]-64);
|
arg0, arm_flen_buf(cpu));
|
||||||
} else {
|
} else {
|
||||||
struct stat buf;
|
struct stat buf;
|
||||||
ret = set_swi_errno(ts, fstat(arg0, &buf));
|
ret = set_swi_errno(ts, fstat(arg0, &buf));
|
||||||
|
@ -504,7 +504,7 @@ typedef struct CPUARMState {
|
|||||||
|
|
||||||
ARMCPU *cpu_arm_init(const char *cpu_model);
|
ARMCPU *cpu_arm_init(const char *cpu_model);
|
||||||
int cpu_arm_exec(CPUState *cpu);
|
int cpu_arm_exec(CPUState *cpu);
|
||||||
uint32_t do_arm_semihosting(CPUARMState *env);
|
target_ulong do_arm_semihosting(CPUARMState *env);
|
||||||
void aarch64_sync_32_to_64(CPUARMState *env);
|
void aarch64_sync_32_to_64(CPUARMState *env);
|
||||||
void aarch64_sync_64_to_32(CPUARMState *env);
|
void aarch64_sync_64_to_32(CPUARMState *env);
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user