Re: [Qemu-devel] [RFC 02/14] Added semihosting support for A64 in full-system mode

2015-08-11 Thread Peter Maydell
On 5 August 2015 at 17:51, Christopher Covington c...@codeaurora.org wrote:
 This is for full-system only; not implemented in user mode

 Written by Derek Hower.

 -cpu_memory_rw_debug(cs, env-regs[13]-64+32, (uint8_t *)size, 4, 0);
 -env-regs[0] = be32_to_cpu(size);
 +if (env-aarch64) {
 +  cpu_memory_rw_debug(cs, env-pc-64+32, (uint8_t *)size, 4, 0);
 +  env-xregs[0] = be32_to_cpu(size);
 +} else {
 +  cpu_memory_rw_debug(cs, env-regs[13]-64+32, (uint8_t *)size, 4, 0);
 +  env-regs[0] = be32_to_cpu(size);
 +}

  case TARGET_SYS_FLEN:
  GET_ARG(0);
  if (use_gdb_syscalls()) {
 +  if (env-aarch64) {
 +gdb_do_syscall(arm_semi_flen_cb, fstat,%x,%x,
 +   arg0, env-pc-64);
 +return env-xregs[0];
 +
 +  } else {
  gdb_do_syscall(arm_semi_flen_cb, fstat,%x,%x,
 arg0, env-regs[13]-64);
  return env-regs[0];
 +  }

These two bits are badly buggy if you ever try to use this semihosting
call with gdb syscalls enabled on A64. r13 is SP, not PC, but your
A64 code is telling gdb to write the struct stat buf to guest memory
starting at pc-64, so it will corrupt the code we've just executed...

(I'm working on an inspired-by-this but rewritten patchset for
A64 semihosting, so this is just in case you were using these
patches somewhere in the interim.)

thanks
-- PMM



[Qemu-devel] [RFC 02/14] Added semihosting support for A64 in full-system mode

2015-08-05 Thread Christopher Covington
This is for full-system only; not implemented in user mode

Written by Derek Hower.

Signed-off-by: Christopher Covington c...@codeaurora.org
---
 include/exec/softmmu-semi.h |  21 ++-
 target-arm/arm-semi.c   | 142 
 target-arm/cpu.h|   3 +-
 target-arm/helper-a64.c |  28 -
 target-arm/helper.c |   1 +
 target-arm/internals.h  |   8 +++
 target-arm/translate-a64.c  |   2 +-
 7 files changed, 174 insertions(+), 31 deletions(-)

diff --git a/include/exec/softmmu-semi.h b/include/exec/softmmu-semi.h
index 8401f7d..9ab8353 100644
--- a/include/exec/softmmu-semi.h
+++ b/include/exec/softmmu-semi.h
@@ -9,6 +9,13 @@
 #ifndef SOFTMMU_SEMI_H
 #define SOFTMMU_SEMI_H 1
 
+static inline uint64_t softmmu_tget64(CPUArchState *env, uint64_t addr)
+{
+uint64_t val;
+
+cpu_memory_rw_debug(ENV_GET_CPU(env), addr, (uint8_t *)val, 8, 0);
+return tswap64(val);
+}
 static inline uint32_t softmmu_tget32(CPUArchState *env, uint32_t addr)
 {
 uint32_t val;
@@ -24,19 +31,27 @@ static inline uint32_t softmmu_tget8(CPUArchState *env, 
uint32_t addr)
 return val;
 }
 
+#define get_user_u64(arg, p) ({ arg = softmmu_tget64(env, p) ; 0; })
 #define get_user_u32(arg, p) ({ arg = softmmu_tget32(env, p) ; 0; })
 #define get_user_u8(arg, p) ({ arg = softmmu_tget8(env, p) ; 0; })
 #define get_user_ual(arg, p) get_user_u32(arg, p)
 
+static inline void softmmu_tput64(CPUArchState *env, uint64_t addr, uint64_t 
val)
+{
+val = tswap64(val);
+cpu_memory_rw_debug(ENV_GET_CPU(env), addr, (uint8_t *)val, 8, 1);
+}
+
 static inline void softmmu_tput32(CPUArchState *env, uint32_t addr, uint32_t 
val)
 {
 val = tswap32(val);
 cpu_memory_rw_debug(ENV_GET_CPU(env), addr, (uint8_t *)val, 4, 1);
 }
+#define put_user_u64(arg, p) ({ softmmu_tput64(env, p, arg) ; 0; })
 #define put_user_u32(arg, p) ({ softmmu_tput32(env, p, arg) ; 0; })
 #define put_user_ual(arg, p) put_user_u32(arg, p)
 
-static void *softmmu_lock_user(CPUArchState *env, uint32_t addr, uint32_t len,
+static void *softmmu_lock_user(CPUArchState *env, target_ulong addr, uint32_t 
len,
int copy)
 {
 uint8_t *p;
@@ -48,11 +63,11 @@ static void *softmmu_lock_user(CPUArchState *env, uint32_t 
addr, uint32_t len,
 return p;
 }
 #define lock_user(type, p, len, copy) softmmu_lock_user(env, p, len, copy)
-static char *softmmu_lock_user_string(CPUArchState *env, uint32_t addr)
+static char *softmmu_lock_user_string(CPUArchState *env, target_ulong addr)
 {
 char *p;
 char *s;
-uint8_t c;
+uint8_t c = 0;
 /* TODO: Make this something that isn't fixed size.  */
 s = p = malloc(1024);
 if (!s) {
diff --git a/target-arm/arm-semi.c b/target-arm/arm-semi.c
index bcc70ec..b89ea8f 100644
--- a/target-arm/arm-semi.c
+++ b/target-arm/arm-semi.c
@@ -4,6 +4,9 @@
  *  Copyright (c) 2005, 2007 CodeSourcery.
  *  Written by Paul Brook.
  *
+ *  Copyright (c) 2015 the Linux Foundation.
+ *  Written by Derek Hower.
+ *
  *  This program is free software; you can redistribute it and/or modify
  *  it under the terms of the GNU General Public License as published by
  *  the Free Software Foundation; either version 2 of the License, or
@@ -140,19 +143,35 @@ static void arm_semi_cb(CPUState *cs, target_ulong ret, 
target_ulong err)
 #else
syscall_err = err;
 #endif
-env-regs[0] = ret;
+if (env-aarch64) {
+  env-xregs[0] = ret;
+} else {
+  env-regs[0] = ret;
+}
 } else {
 /* Fixup syscalls that use nonstardard return conventions.  */
 switch (env-regs[0]) {
 case TARGET_SYS_WRITE:
 case TARGET_SYS_READ:
+  if (env-aarch64) {
+env-xregs[0] = arm_semi_syscall_len - ret;
+  } else {
 env-regs[0] = arm_semi_syscall_len - ret;
+  }
 break;
 case TARGET_SYS_SEEK:
+  if (env-aarch64) {
+env-xregs[0] = 0;
+  } else {
 env-regs[0] = 0;
+  }
 break;
 default:
+  if (env-aarch64) {
+env-xregs[0] = ret;
+  } else {
 env-regs[0] = ret;
+  }
 break;
 }
 }
@@ -165,8 +184,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 value. We assume the size always fit in 32 bits.  */
 uint32_t size;
-cpu_memory_rw_debug(cs, env-regs[13]-64+32, (uint8_t *)size, 4, 0);
-env-regs[0] = be32_to_cpu(size);
+if (env-aarch64) {
+  cpu_memory_rw_debug(cs, env-pc-64+32, (uint8_t *)size, 4, 0);
+  env-xregs[0] = be32_to_cpu(size);
+} else {
+  cpu_memory_rw_debug(cs, env-regs[13]-64+32, (uint8_t *)size, 4, 0);
+  env-regs[0] = be32_to_cpu(size);
+}
 #ifdef CONFIG_USER_ONLY
 ((TaskState *)cs-opaque)-swi_errno = err;
 #else