All of lore.kernel.org
 help / color / mirror / Atom feed
* [PATCH 0/4] riscv: Add semihosting support [v10]
@ 2020-10-26 21:28 ` Keith Packard
  0 siblings, 0 replies; 32+ messages in thread
From: Keith Packard via @ 2020-10-26 21:28 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alex Bennée, Laurent Vivier, Peter Maydell, qemu-arm,
	Palmer Dabbelt, Alistair Francis, Sagar Karandikar,
	Bastian Koppelmann, qemu-riscv

This series first adapts the existing ARM semihosting code to be
architecture-neutral, then adds RISC-V semihosting support using that.

Patch 1/4 moves the ARM semihosting support code to common directories and
adapts the build system to match.

Patch 2/4 changes the public API to this code to use
architecture-independent names and types.

Patch 3/4 changes the internals of this code to use architecture
neutral types where practical, and adds helper functions to abstract
away the architecture-specific details.

Patch 4/4 adds the RISC-V support, including modifying the breakpoint
handling code to recognize a semihosting sequence and adding RISC-V
specific implementations of the helper functions.




^ permalink raw reply	[flat|nested] 32+ messages in thread

* [PATCH 0/4] riscv: Add semihosting support [v10]
@ 2020-10-26 21:28 ` Keith Packard
  0 siblings, 0 replies; 32+ messages in thread
From: Keith Packard @ 2020-10-26 21:28 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alex Bennée, Laurent Vivier, Peter Maydell, qemu-arm,
	Palmer Dabbelt, Alistair Francis, Sagar Karandikar,
	Bastian Koppelmann, qemu-riscv

This series first adapts the existing ARM semihosting code to be
architecture-neutral, then adds RISC-V semihosting support using that.

Patch 1/4 moves the ARM semihosting support code to common directories and
adapts the build system to match.

Patch 2/4 changes the public API to this code to use
architecture-independent names and types.

Patch 3/4 changes the internals of this code to use architecture
neutral types where practical, and adds helper functions to abstract
away the architecture-specific details.

Patch 4/4 adds the RISC-V support, including modifying the breakpoint
handling code to recognize a semihosting sequence and adding RISC-V
specific implementations of the helper functions.




^ permalink raw reply	[flat|nested] 32+ messages in thread

* [PATCH 1/4] semihosting: Move ARM semihosting code to shared directories
  2020-10-26 21:28 ` Keith Packard
@ 2020-10-26 21:28   ` Keith Packard
  -1 siblings, 0 replies; 32+ messages in thread
From: Keith Packard via @ 2020-10-26 21:28 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alex Bennée, Laurent Vivier, Peter Maydell, qemu-arm,
	Palmer Dabbelt, Alistair Francis, Sagar Karandikar,
	Bastian Koppelmann, qemu-riscv, Keith Packard

This commit renames two files which provide ARM semihosting support so
that they can be shared by other architectures:

 1. target/arm/arm-semi.c     -> hw/semihosting/common-semi.c
 2. linux-user/arm/semihost.c -> linux-user/semihost.c

The build system was modified to reflect this change, but the contents
of the two files are unchanged.

Signed-off-by: Keith Packard <keithp@keithp.com>
---
 target/arm/arm-semi.c => hw/semihosting/common-semi.c | 0
 hw/semihosting/meson.build                            | 2 ++
 linux-user/arm/meson.build                            | 3 ---
 linux-user/meson.build                                | 2 ++
 linux-user/{arm => }/semihost.c                       | 0
 target/arm/meson.build                                | 2 --
 6 files changed, 4 insertions(+), 5 deletions(-)
 rename target/arm/arm-semi.c => hw/semihosting/common-semi.c (100%)
 rename linux-user/{arm => }/semihost.c (100%)

diff --git a/target/arm/arm-semi.c b/hw/semihosting/common-semi.c
similarity index 100%
rename from target/arm/arm-semi.c
rename to hw/semihosting/common-semi.c
diff --git a/hw/semihosting/meson.build b/hw/semihosting/meson.build
index f40ac574c4..fbd2841e59 100644
--- a/hw/semihosting/meson.build
+++ b/hw/semihosting/meson.build
@@ -2,3 +2,5 @@ specific_ss.add(when: 'CONFIG_SEMIHOSTING', if_true: files(
   'config.c',
   'console.c',
 ))
+
+specific_ss.add(when: 'CONFIG_TCG', if_true: files ('common-semi.c'))
diff --git a/linux-user/arm/meson.build b/linux-user/arm/meson.build
index 432984b58e..5a93c925cf 100644
--- a/linux-user/arm/meson.build
+++ b/linux-user/arm/meson.build
@@ -1,6 +1,3 @@
-linux_user_ss.add(when: 'TARGET_AARCH64', if_true: files('semihost.c'))
-linux_user_ss.add(when: 'TARGET_ARM', if_true: files('semihost.c'))
-
 subdir('nwfpe')
 
 syscall_nr_generators += {
diff --git a/linux-user/meson.build b/linux-user/meson.build
index 2b94e4ba24..2fdd12cee5 100644
--- a/linux-user/meson.build
+++ b/linux-user/meson.build
@@ -17,6 +17,8 @@ linux_user_ss.add(rt)
 linux_user_ss.add(when: 'TARGET_HAS_BFLT', if_true: files('flatload.c'))
 linux_user_ss.add(when: 'TARGET_I386', if_true: files('vm86.c'))
 
+linux_user_ss.add(when: 'TARGET_AARCH64', if_true: files('semihost.c'))
+linux_user_ss.add(when: 'TARGET_ARM', if_true: files('semihost.c'))
 
 syscall_nr_generators = {}
 
diff --git a/linux-user/arm/semihost.c b/linux-user/semihost.c
similarity index 100%
rename from linux-user/arm/semihost.c
rename to linux-user/semihost.c
diff --git a/target/arm/meson.build b/target/arm/meson.build
index f5de2a77b8..15b936c101 100644
--- a/target/arm/meson.build
+++ b/target/arm/meson.build
@@ -32,8 +32,6 @@ arm_ss.add(files(
 ))
 arm_ss.add(zlib)
 
-arm_ss.add(when: 'CONFIG_TCG', if_true: files('arm-semi.c'))
-
 arm_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c', 'kvm64.c'), if_false: files('kvm-stub.c'))
 
 arm_ss.add(when: 'TARGET_AARCH64', if_true: files(
-- 
2.28.0



^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH 1/4] semihosting: Move ARM semihosting code to shared directories
@ 2020-10-26 21:28   ` Keith Packard
  0 siblings, 0 replies; 32+ messages in thread
From: Keith Packard @ 2020-10-26 21:28 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alex Bennée, Laurent Vivier, Peter Maydell, qemu-arm,
	Palmer Dabbelt, Alistair Francis, Sagar Karandikar,
	Bastian Koppelmann, qemu-riscv, Keith Packard

This commit renames two files which provide ARM semihosting support so
that they can be shared by other architectures:

 1. target/arm/arm-semi.c     -> hw/semihosting/common-semi.c
 2. linux-user/arm/semihost.c -> linux-user/semihost.c

The build system was modified to reflect this change, but the contents
of the two files are unchanged.

Signed-off-by: Keith Packard <keithp@keithp.com>
---
 target/arm/arm-semi.c => hw/semihosting/common-semi.c | 0
 hw/semihosting/meson.build                            | 2 ++
 linux-user/arm/meson.build                            | 3 ---
 linux-user/meson.build                                | 2 ++
 linux-user/{arm => }/semihost.c                       | 0
 target/arm/meson.build                                | 2 --
 6 files changed, 4 insertions(+), 5 deletions(-)
 rename target/arm/arm-semi.c => hw/semihosting/common-semi.c (100%)
 rename linux-user/{arm => }/semihost.c (100%)

diff --git a/target/arm/arm-semi.c b/hw/semihosting/common-semi.c
similarity index 100%
rename from target/arm/arm-semi.c
rename to hw/semihosting/common-semi.c
diff --git a/hw/semihosting/meson.build b/hw/semihosting/meson.build
index f40ac574c4..fbd2841e59 100644
--- a/hw/semihosting/meson.build
+++ b/hw/semihosting/meson.build
@@ -2,3 +2,5 @@ specific_ss.add(when: 'CONFIG_SEMIHOSTING', if_true: files(
   'config.c',
   'console.c',
 ))
+
+specific_ss.add(when: 'CONFIG_TCG', if_true: files ('common-semi.c'))
diff --git a/linux-user/arm/meson.build b/linux-user/arm/meson.build
index 432984b58e..5a93c925cf 100644
--- a/linux-user/arm/meson.build
+++ b/linux-user/arm/meson.build
@@ -1,6 +1,3 @@
-linux_user_ss.add(when: 'TARGET_AARCH64', if_true: files('semihost.c'))
-linux_user_ss.add(when: 'TARGET_ARM', if_true: files('semihost.c'))
-
 subdir('nwfpe')
 
 syscall_nr_generators += {
diff --git a/linux-user/meson.build b/linux-user/meson.build
index 2b94e4ba24..2fdd12cee5 100644
--- a/linux-user/meson.build
+++ b/linux-user/meson.build
@@ -17,6 +17,8 @@ linux_user_ss.add(rt)
 linux_user_ss.add(when: 'TARGET_HAS_BFLT', if_true: files('flatload.c'))
 linux_user_ss.add(when: 'TARGET_I386', if_true: files('vm86.c'))
 
+linux_user_ss.add(when: 'TARGET_AARCH64', if_true: files('semihost.c'))
+linux_user_ss.add(when: 'TARGET_ARM', if_true: files('semihost.c'))
 
 syscall_nr_generators = {}
 
diff --git a/linux-user/arm/semihost.c b/linux-user/semihost.c
similarity index 100%
rename from linux-user/arm/semihost.c
rename to linux-user/semihost.c
diff --git a/target/arm/meson.build b/target/arm/meson.build
index f5de2a77b8..15b936c101 100644
--- a/target/arm/meson.build
+++ b/target/arm/meson.build
@@ -32,8 +32,6 @@ arm_ss.add(files(
 ))
 arm_ss.add(zlib)
 
-arm_ss.add(when: 'CONFIG_TCG', if_true: files('arm-semi.c'))
-
 arm_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c', 'kvm64.c'), if_false: files('kvm-stub.c'))
 
 arm_ss.add(when: 'TARGET_AARCH64', if_true: files(
-- 
2.28.0



^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH 2/4] semihosting: Change common-semi API to be architecture-independent
  2020-10-26 21:28 ` Keith Packard
@ 2020-10-26 21:28   ` Keith Packard
  -1 siblings, 0 replies; 32+ messages in thread
From: Keith Packard via @ 2020-10-26 21:28 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alex Bennée, Laurent Vivier, Peter Maydell, qemu-arm,
	Palmer Dabbelt, Alistair Francis, Sagar Karandikar,
	Bastian Koppelmann, qemu-riscv, Keith Packard

The public API is now defined in
hw/semihosting/common-semi.h. do_common_semihosting takes CPUState *
instead of CPUARMState *. All internal functions have been renamed
common_semi_ instead of arm_semi_ or arm_. Aside from the API change,
there are no functional changes in this patch.

Signed-off-by: Keith Packard <keithp@keithp.com>
---
 hw/semihosting/common-semi.c  | 16 ++++++++++------
 hw/semihosting/common-semi.h  | 36 +++++++++++++++++++++++++++++++++++
 linux-user/aarch64/cpu_loop.c |  3 ++-
 linux-user/arm/cpu_loop.c     |  3 ++-
 target/arm/cpu.h              |  8 --------
 target/arm/helper.c           |  5 +++--
 target/arm/m_helper.c         |  7 ++++++-
 7 files changed, 59 insertions(+), 19 deletions(-)
 create mode 100644 hw/semihosting/common-semi.h

diff --git a/hw/semihosting/common-semi.c b/hw/semihosting/common-semi.c
index 8718fd0194..e0c59bc599 100644
--- a/hw/semihosting/common-semi.c
+++ b/hw/semihosting/common-semi.c
@@ -1,10 +1,14 @@
 /*
- *  Arm "Angel" semihosting syscalls
+ *  Semihosting support for systems modeled on the Arm "Angel"
+ *  semihosting syscalls design.
  *
  *  Copyright (c) 2005, 2007 CodeSourcery.
  *  Copyright (c) 2019 Linaro
  *  Written by Paul Brook.
  *
+ *  Copyright © 2020 by Keith Packard <keithp@keithp.com>
+ *  Adapted for systems other than ARM, including RISC-V, by Keith Packard
+ *
  *  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
@@ -371,12 +375,12 @@ static target_ulong arm_gdb_syscall(ARMCPU *cpu, gdb_syscall_complete_cb cb,
      * do anything with its return value, because it is not necessarily
      * the result of the syscall, but could just be the old value of X0.
      * The only thing safe to do with this is that the callers of
-     * do_arm_semihosting() will write it straight back into X0.
+     * do_common_semihosting() will write it straight back into X0.
      * (In linux-user mode, the callback will have happened before
      * gdb_do_syscallv() returns.)
      *
      * We should tidy this up so neither this function nor
-     * do_arm_semihosting() return a value, so the mistake of
+     * do_common_semihosting() return a value, so the mistake of
      * doing something with the return value is not possible to make.
      */
 
@@ -673,10 +677,10 @@ static const GuestFDFunctions guestfd_fns[] = {
  * leave the register unchanged. We use 0xdeadbeef as the return value
  * when there isn't a defined return value for the call.
  */
-target_ulong do_arm_semihosting(CPUARMState *env)
+target_ulong do_common_semihosting(CPUState *cs)
 {
-    ARMCPU *cpu = env_archcpu(env);
-    CPUState *cs = env_cpu(env);
+    ARMCPU *cpu = ARM_CPU(cs);
+    CPUARMState *env = &cpu->env;
     target_ulong args;
     target_ulong arg0, arg1, arg2, arg3;
     char * s;
diff --git a/hw/semihosting/common-semi.h b/hw/semihosting/common-semi.h
new file mode 100644
index 0000000000..bc53e92c79
--- /dev/null
+++ b/hw/semihosting/common-semi.h
@@ -0,0 +1,36 @@
+/*
+ *  Semihosting support for systems modeled on the Arm "Angel"
+ *  semihosting syscalls design.
+ *
+ *  Copyright (c) 2005, 2007 CodeSourcery.
+ *  Copyright (c) 2019 Linaro
+ *  Written by Paul Brook.
+ *
+ *  Copyright © 2020 by Keith Packard <keithp@keithp.com>
+ *  Adapted for systems other than ARM, including RISC-V, by Keith Packard
+ *
+ *  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
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ *  ARM Semihosting is documented in:
+ *     Semihosting for AArch32 and AArch64 Release 2.0
+ *     https://static.docs.arm.com/100863/0200/semihosting.pdf
+ *
+ */
+
+#ifndef COMMON_SEMI_H
+#define COMMON_SEMI_H
+
+target_ulong do_common_semihosting(CPUState *cs);
+
+#endif /* COMMON_SEMI_H */
diff --git a/linux-user/aarch64/cpu_loop.c b/linux-user/aarch64/cpu_loop.c
index bbe9fefca8..42b9c15f53 100644
--- a/linux-user/aarch64/cpu_loop.c
+++ b/linux-user/aarch64/cpu_loop.c
@@ -22,6 +22,7 @@
 #include "qemu.h"
 #include "cpu_loop-common.h"
 #include "qemu/guest-random.h"
+#include "hw/semihosting/common-semi.h"
 
 #define get_user_code_u32(x, gaddr, env)                \
     ({ abi_long __r = get_user_u32((x), (gaddr));       \
@@ -129,7 +130,7 @@ void cpu_loop(CPUARMState *env)
             queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
             break;
         case EXCP_SEMIHOST:
-            env->xregs[0] = do_arm_semihosting(env);
+            env->xregs[0] = do_common_semihosting(cs);
             env->pc += 4;
             break;
         case EXCP_YIELD:
diff --git a/linux-user/arm/cpu_loop.c b/linux-user/arm/cpu_loop.c
index 13629ee1f6..31dbb4d1af 100644
--- a/linux-user/arm/cpu_loop.c
+++ b/linux-user/arm/cpu_loop.c
@@ -22,6 +22,7 @@
 #include "qemu.h"
 #include "elf.h"
 #include "cpu_loop-common.h"
+#include "hw/semihosting/common-semi.h"
 
 #define get_user_code_u32(x, gaddr, env)                \
     ({ abi_long __r = get_user_u32((x), (gaddr));       \
@@ -393,7 +394,7 @@ void cpu_loop(CPUARMState *env)
             }
             break;
         case EXCP_SEMIHOST:
-            env->regs[0] = do_arm_semihosting(env);
+            env->regs[0] = do_common_semihosting(cs);
             env->regs[15] += env->thumb ? 2 : 4;
             break;
         case EXCP_INTERRUPT:
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 49cd5cabcf..c7ece27c56 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -1068,14 +1068,6 @@ static inline void aarch64_sve_change_el(CPUARMState *env, int o,
 static inline void aarch64_add_sve_properties(Object *obj) { }
 #endif
 
-#if !defined(CONFIG_TCG)
-static inline target_ulong do_arm_semihosting(CPUARMState *env)
-{
-    g_assert_not_reached();
-}
-#else
-target_ulong do_arm_semihosting(CPUARMState *env);
-#endif
 void aarch64_sync_32_to_64(CPUARMState *env);
 void aarch64_sync_64_to_32(CPUARMState *env);
 
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 97bb6b8c01..8dbb0ef5d3 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -34,6 +34,7 @@
 #ifdef CONFIG_TCG
 #include "arm_ldst.h"
 #include "exec/cpu_ldst.h"
+#include "hw/semihosting/common-semi.h"
 #endif
 
 #define ARM_CPU_FREQ 1000000000 /* FIXME: 1 GHz, should be configurable */
@@ -9889,13 +9890,13 @@ static void handle_semihosting(CPUState *cs)
         qemu_log_mask(CPU_LOG_INT,
                       "...handling as semihosting call 0x%" PRIx64 "\n",
                       env->xregs[0]);
-        env->xregs[0] = do_arm_semihosting(env);
+        env->xregs[0] = do_common_semihosting(cs);
         env->pc += 4;
     } else {
         qemu_log_mask(CPU_LOG_INT,
                       "...handling as semihosting call 0x%x\n",
                       env->regs[0]);
-        env->regs[0] = do_arm_semihosting(env);
+        env->regs[0] = do_common_semihosting(cs);
         env->regs[15] += env->thumb ? 2 : 4;
     }
 }
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
index 036454234c..ef897382de 100644
--- a/target/arm/m_helper.c
+++ b/target/arm/m_helper.c
@@ -31,6 +31,7 @@
 #ifdef CONFIG_TCG
 #include "arm_ldst.h"
 #include "exec/cpu_ldst.h"
+#include "hw/semihosting/common-semi.h"
 #endif
 
 static void v7m_msr_xpsr(CPUARMState *env, uint32_t mask,
@@ -2188,7 +2189,11 @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
         qemu_log_mask(CPU_LOG_INT,
                       "...handling as semihosting call 0x%x\n",
                       env->regs[0]);
-        env->regs[0] = do_arm_semihosting(env);
+#ifdef CONFIG_TCG
+        env->regs[0] = do_common_semihosting(cs);
+#else
+        g_assert_not_reached();
+#endif
         env->regs[15] += env->thumb ? 2 : 4;
         return;
     case EXCP_BKPT:
-- 
2.28.0



^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH 2/4] semihosting: Change common-semi API to be architecture-independent
@ 2020-10-26 21:28   ` Keith Packard
  0 siblings, 0 replies; 32+ messages in thread
From: Keith Packard @ 2020-10-26 21:28 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alex Bennée, Laurent Vivier, Peter Maydell, qemu-arm,
	Palmer Dabbelt, Alistair Francis, Sagar Karandikar,
	Bastian Koppelmann, qemu-riscv, Keith Packard

The public API is now defined in
hw/semihosting/common-semi.h. do_common_semihosting takes CPUState *
instead of CPUARMState *. All internal functions have been renamed
common_semi_ instead of arm_semi_ or arm_. Aside from the API change,
there are no functional changes in this patch.

Signed-off-by: Keith Packard <keithp@keithp.com>
---
 hw/semihosting/common-semi.c  | 16 ++++++++++------
 hw/semihosting/common-semi.h  | 36 +++++++++++++++++++++++++++++++++++
 linux-user/aarch64/cpu_loop.c |  3 ++-
 linux-user/arm/cpu_loop.c     |  3 ++-
 target/arm/cpu.h              |  8 --------
 target/arm/helper.c           |  5 +++--
 target/arm/m_helper.c         |  7 ++++++-
 7 files changed, 59 insertions(+), 19 deletions(-)
 create mode 100644 hw/semihosting/common-semi.h

diff --git a/hw/semihosting/common-semi.c b/hw/semihosting/common-semi.c
index 8718fd0194..e0c59bc599 100644
--- a/hw/semihosting/common-semi.c
+++ b/hw/semihosting/common-semi.c
@@ -1,10 +1,14 @@
 /*
- *  Arm "Angel" semihosting syscalls
+ *  Semihosting support for systems modeled on the Arm "Angel"
+ *  semihosting syscalls design.
  *
  *  Copyright (c) 2005, 2007 CodeSourcery.
  *  Copyright (c) 2019 Linaro
  *  Written by Paul Brook.
  *
+ *  Copyright © 2020 by Keith Packard <keithp@keithp.com>
+ *  Adapted for systems other than ARM, including RISC-V, by Keith Packard
+ *
  *  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
@@ -371,12 +375,12 @@ static target_ulong arm_gdb_syscall(ARMCPU *cpu, gdb_syscall_complete_cb cb,
      * do anything with its return value, because it is not necessarily
      * the result of the syscall, but could just be the old value of X0.
      * The only thing safe to do with this is that the callers of
-     * do_arm_semihosting() will write it straight back into X0.
+     * do_common_semihosting() will write it straight back into X0.
      * (In linux-user mode, the callback will have happened before
      * gdb_do_syscallv() returns.)
      *
      * We should tidy this up so neither this function nor
-     * do_arm_semihosting() return a value, so the mistake of
+     * do_common_semihosting() return a value, so the mistake of
      * doing something with the return value is not possible to make.
      */
 
@@ -673,10 +677,10 @@ static const GuestFDFunctions guestfd_fns[] = {
  * leave the register unchanged. We use 0xdeadbeef as the return value
  * when there isn't a defined return value for the call.
  */
-target_ulong do_arm_semihosting(CPUARMState *env)
+target_ulong do_common_semihosting(CPUState *cs)
 {
-    ARMCPU *cpu = env_archcpu(env);
-    CPUState *cs = env_cpu(env);
+    ARMCPU *cpu = ARM_CPU(cs);
+    CPUARMState *env = &cpu->env;
     target_ulong args;
     target_ulong arg0, arg1, arg2, arg3;
     char * s;
diff --git a/hw/semihosting/common-semi.h b/hw/semihosting/common-semi.h
new file mode 100644
index 0000000000..bc53e92c79
--- /dev/null
+++ b/hw/semihosting/common-semi.h
@@ -0,0 +1,36 @@
+/*
+ *  Semihosting support for systems modeled on the Arm "Angel"
+ *  semihosting syscalls design.
+ *
+ *  Copyright (c) 2005, 2007 CodeSourcery.
+ *  Copyright (c) 2019 Linaro
+ *  Written by Paul Brook.
+ *
+ *  Copyright © 2020 by Keith Packard <keithp@keithp.com>
+ *  Adapted for systems other than ARM, including RISC-V, by Keith Packard
+ *
+ *  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
+ *  (at your option) any later version.
+ *
+ *  This program is distributed in the hope that it will be useful,
+ *  but WITHOUT ANY WARRANTY; without even the implied warranty of
+ *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ *  GNU General Public License for more details.
+ *
+ *  You should have received a copy of the GNU General Public License
+ *  along with this program; if not, see <http://www.gnu.org/licenses/>.
+ *
+ *  ARM Semihosting is documented in:
+ *     Semihosting for AArch32 and AArch64 Release 2.0
+ *     https://static.docs.arm.com/100863/0200/semihosting.pdf
+ *
+ */
+
+#ifndef COMMON_SEMI_H
+#define COMMON_SEMI_H
+
+target_ulong do_common_semihosting(CPUState *cs);
+
+#endif /* COMMON_SEMI_H */
diff --git a/linux-user/aarch64/cpu_loop.c b/linux-user/aarch64/cpu_loop.c
index bbe9fefca8..42b9c15f53 100644
--- a/linux-user/aarch64/cpu_loop.c
+++ b/linux-user/aarch64/cpu_loop.c
@@ -22,6 +22,7 @@
 #include "qemu.h"
 #include "cpu_loop-common.h"
 #include "qemu/guest-random.h"
+#include "hw/semihosting/common-semi.h"
 
 #define get_user_code_u32(x, gaddr, env)                \
     ({ abi_long __r = get_user_u32((x), (gaddr));       \
@@ -129,7 +130,7 @@ void cpu_loop(CPUARMState *env)
             queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info);
             break;
         case EXCP_SEMIHOST:
-            env->xregs[0] = do_arm_semihosting(env);
+            env->xregs[0] = do_common_semihosting(cs);
             env->pc += 4;
             break;
         case EXCP_YIELD:
diff --git a/linux-user/arm/cpu_loop.c b/linux-user/arm/cpu_loop.c
index 13629ee1f6..31dbb4d1af 100644
--- a/linux-user/arm/cpu_loop.c
+++ b/linux-user/arm/cpu_loop.c
@@ -22,6 +22,7 @@
 #include "qemu.h"
 #include "elf.h"
 #include "cpu_loop-common.h"
+#include "hw/semihosting/common-semi.h"
 
 #define get_user_code_u32(x, gaddr, env)                \
     ({ abi_long __r = get_user_u32((x), (gaddr));       \
@@ -393,7 +394,7 @@ void cpu_loop(CPUARMState *env)
             }
             break;
         case EXCP_SEMIHOST:
-            env->regs[0] = do_arm_semihosting(env);
+            env->regs[0] = do_common_semihosting(cs);
             env->regs[15] += env->thumb ? 2 : 4;
             break;
         case EXCP_INTERRUPT:
diff --git a/target/arm/cpu.h b/target/arm/cpu.h
index 49cd5cabcf..c7ece27c56 100644
--- a/target/arm/cpu.h
+++ b/target/arm/cpu.h
@@ -1068,14 +1068,6 @@ static inline void aarch64_sve_change_el(CPUARMState *env, int o,
 static inline void aarch64_add_sve_properties(Object *obj) { }
 #endif
 
-#if !defined(CONFIG_TCG)
-static inline target_ulong do_arm_semihosting(CPUARMState *env)
-{
-    g_assert_not_reached();
-}
-#else
-target_ulong do_arm_semihosting(CPUARMState *env);
-#endif
 void aarch64_sync_32_to_64(CPUARMState *env);
 void aarch64_sync_64_to_32(CPUARMState *env);
 
diff --git a/target/arm/helper.c b/target/arm/helper.c
index 97bb6b8c01..8dbb0ef5d3 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -34,6 +34,7 @@
 #ifdef CONFIG_TCG
 #include "arm_ldst.h"
 #include "exec/cpu_ldst.h"
+#include "hw/semihosting/common-semi.h"
 #endif
 
 #define ARM_CPU_FREQ 1000000000 /* FIXME: 1 GHz, should be configurable */
@@ -9889,13 +9890,13 @@ static void handle_semihosting(CPUState *cs)
         qemu_log_mask(CPU_LOG_INT,
                       "...handling as semihosting call 0x%" PRIx64 "\n",
                       env->xregs[0]);
-        env->xregs[0] = do_arm_semihosting(env);
+        env->xregs[0] = do_common_semihosting(cs);
         env->pc += 4;
     } else {
         qemu_log_mask(CPU_LOG_INT,
                       "...handling as semihosting call 0x%x\n",
                       env->regs[0]);
-        env->regs[0] = do_arm_semihosting(env);
+        env->regs[0] = do_common_semihosting(cs);
         env->regs[15] += env->thumb ? 2 : 4;
     }
 }
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
index 036454234c..ef897382de 100644
--- a/target/arm/m_helper.c
+++ b/target/arm/m_helper.c
@@ -31,6 +31,7 @@
 #ifdef CONFIG_TCG
 #include "arm_ldst.h"
 #include "exec/cpu_ldst.h"
+#include "hw/semihosting/common-semi.h"
 #endif
 
 static void v7m_msr_xpsr(CPUARMState *env, uint32_t mask,
@@ -2188,7 +2189,11 @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
         qemu_log_mask(CPU_LOG_INT,
                       "...handling as semihosting call 0x%x\n",
                       env->regs[0]);
-        env->regs[0] = do_arm_semihosting(env);
+#ifdef CONFIG_TCG
+        env->regs[0] = do_common_semihosting(cs);
+#else
+        g_assert_not_reached();
+#endif
         env->regs[15] += env->thumb ? 2 : 4;
         return;
     case EXCP_BKPT:
-- 
2.28.0



^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH 3/4] semihosting: Change internal common-semi interfaces to use CPUState *
  2020-10-26 21:28 ` Keith Packard
@ 2020-10-26 21:28   ` Keith Packard
  -1 siblings, 0 replies; 32+ messages in thread
From: Keith Packard via @ 2020-10-26 21:28 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alex Bennée, Laurent Vivier, Peter Maydell, qemu-arm,
	Palmer Dabbelt, Alistair Francis, Sagar Karandikar,
	Bastian Koppelmann, qemu-riscv, Keith Packard

This makes all of the internal interfaces architecture-independent and
renames the internal functions to use the 'common_semi' prefix instead
of 'arm' or 'arm_semi'.

To do this, some new architecture-specific internal helper functions
were created:

    static inline target_ulong
    common_semi_arg(CPUState *cs, int argno)

	Returns the argno'th semihosting argument, where argno can be
	either 0 or 1.

    static inline void
    common_semi_set_ret(CPUState *cs, target_ulong ret)

	Sets the semihosting return value.

    static inline bool
    common_semi_sys_exit_extended(CPUState *cs, int nr)

	This detects whether the specified semihosting call, which
	is either TARGET_SYS_EXIT or TARGET_SYS_EXIT_EXTENDED should
	be executed using the TARGET_SYS_EXIT_EXTENDED semantics.

In addition, several existing functions have been changed to flag
areas of code which are architecture specific:

    static target_ulong
    common_semi_flen_buf(CPUState *cs)

	Returns the current stack pointer minus 64, which is
	where a stat structure will be placed on the stack

    #define GET_ARG(n)

	This fetches arguments from the semihosting command's argument
	block. The address of this is available implicitly through the
	local 'args' variable. This is *mostly* architecture
	independent, but does depend on the current ABI's notion of
	the size of a 'long' parameter, which may need run-time checks
	(as it does on AARCH64)

    #define SET_ARG(n, val)

	This mirrors GET_ARG and stores data back into the argument
	block.

Signed-off-by: Keith Packard <keithp@keithp.com>
---
 hw/semihosting/common-semi.c | 326 ++++++++++++++++++-----------------
 1 file changed, 164 insertions(+), 162 deletions(-)

diff --git a/hw/semihosting/common-semi.c b/hw/semihosting/common-semi.c
index e0c59bc599..c77fb21bec 100644
--- a/hw/semihosting/common-semi.c
+++ b/hw/semihosting/common-semi.c
@@ -32,11 +32,12 @@
 #include "cpu.h"
 #include "hw/semihosting/semihost.h"
 #include "hw/semihosting/console.h"
+#include "hw/semihosting/common-semi.h"
 #include "qemu/log.h"
 #ifdef CONFIG_USER_ONLY
 #include "qemu.h"
 
-#define ARM_ANGEL_HEAP_SIZE (128 * 1024 * 1024)
+#define COMMON_SEMI_HEAP_SIZE (128 * 1024 * 1024)
 #else
 #include "exec/gdbstub.h"
 #include "qemu/cutils.h"
@@ -132,6 +133,36 @@ typedef struct GuestFD {
 
 static GArray *guestfd_array;
 
+#ifdef TARGET_ARM
+static inline target_ulong
+common_semi_arg(CPUState *cs, int argno)
+{
+    ARMCPU *cpu = ARM_CPU(cs);
+    CPUARMState *env = &cpu->env;
+    if (is_a64(env))
+        return env->xregs[argno];
+    else
+        return env->regs[argno];
+}
+
+static inline void
+common_semi_set_ret(CPUState *cs, target_ulong ret)
+{
+    ARMCPU *cpu = ARM_CPU(cs);
+    CPUARMState *env = &cpu->env;
+    if (is_a64(env))
+        env->xregs[0] = ret;
+    else
+        env->regs[0] = ret;
+}
+
+static inline bool
+common_semi_sys_exit_extended(CPUState *cs, int nr)
+{
+    return (nr == TARGET_SYS_EXIT_EXTENDED || is_a64(cs->env_ptr));
+}
+#endif /* TARGET_ARM */
+
 /*
  * Allocate a new guest file descriptor and return it; if we
  * couldn't allocate a new fd then return -1.
@@ -237,11 +268,10 @@ static target_ulong syscall_err;
 #include "exec/softmmu-semi.h"
 #endif
 
-static inline uint32_t set_swi_errno(CPUARMState *env, uint32_t code)
+static inline uint32_t set_swi_errno(CPUState *cs, uint32_t code)
 {
     if (code == (uint32_t)-1) {
 #ifdef CONFIG_USER_ONLY
-        CPUState *cs = env_cpu(env);
         TaskState *ts = cs->opaque;
 
         ts->swi_errno = errno;
@@ -252,10 +282,9 @@ static inline uint32_t set_swi_errno(CPUARMState *env, uint32_t code)
     return code;
 }
 
-static inline uint32_t get_swi_errno(CPUARMState *env)
+static inline uint32_t get_swi_errno(CPUState *cs)
 {
 #ifdef CONFIG_USER_ONLY
-    CPUState *cs = env_cpu(env);
     TaskState *ts = cs->opaque;
 
     return ts->swi_errno;
@@ -264,24 +293,22 @@ static inline uint32_t get_swi_errno(CPUARMState *env)
 #endif
 }
 
-static target_ulong arm_semi_syscall_len;
+static target_ulong common_semi_syscall_len;
 
-static void arm_semi_cb(CPUState *cs, target_ulong ret, target_ulong err)
+static void common_semi_cb(CPUState *cs, target_ulong ret, target_ulong err)
 {
-    ARMCPU *cpu = ARM_CPU(cs);
-    CPUARMState *env = &cpu->env;
-    target_ulong reg0 = is_a64(env) ? env->xregs[0] : env->regs[0];
+    target_ulong reg0 = common_semi_arg(cs, 0);
 
     if (ret == (target_ulong)-1) {
         errno = err;
-        set_swi_errno(env, -1);
+        set_swi_errno(cs, -1);
         reg0 = ret;
     } else {
         /* Fixup syscalls that use nonstardard return conventions.  */
         switch (reg0) {
         case TARGET_SYS_WRITE:
         case TARGET_SYS_READ:
-            reg0 = arm_semi_syscall_len - ret;
+            reg0 = common_semi_syscall_len - ret;
             break;
         case TARGET_SYS_SEEK:
             reg0 = 0;
@@ -291,77 +318,62 @@ static void arm_semi_cb(CPUState *cs, target_ulong ret, target_ulong err)
             break;
         }
     }
-    if (is_a64(env)) {
-        env->xregs[0] = reg0;
-    } else {
-        env->regs[0] = reg0;
-    }
+    common_semi_set_ret(cs, reg0);
 }
 
-static target_ulong arm_flen_buf(ARMCPU *cpu)
+static target_ulong common_semi_flen_buf(CPUState *cs)
 {
+    target_ulong sp;
+#ifdef TARGET_ARM
     /* 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.
      */
+    ARMCPU *cpu = ARM_CPU(cs);
     CPUARMState *env = &cpu->env;
-    target_ulong sp;
 
     if (is_a64(env)) {
         sp = env->xregs[31];
     } else {
         sp = env->regs[13];
     }
+#endif
 
     return sp - 64;
 }
 
-static void arm_semi_flen_cb(CPUState *cs, target_ulong ret, target_ulong err)
+static void common_semi_flen_cb(CPUState *cs, target_ulong ret, target_ulong err)
 {
-    ARMCPU *cpu = ARM_CPU(cs);
-    CPUARMState *env = &cpu->env;
     /* 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, arm_flen_buf(cpu) + 32, (uint8_t *)&size, 4, 0);
+    cpu_memory_rw_debug(cs, common_semi_flen_buf(cs) + 32, (uint8_t *)&size, 4, 0);
     size = be32_to_cpu(size);
-    if (is_a64(env)) {
-        env->xregs[0] = size;
-    } else {
-        env->regs[0] = size;
-    }
+    common_semi_set_ret(cs, size);
     errno = err;
-    set_swi_errno(env, -1);
+    set_swi_errno(cs, -1);
 }
 
-static int arm_semi_open_guestfd;
+static int common_semi_open_guestfd;
 
-static void arm_semi_open_cb(CPUState *cs, target_ulong ret, target_ulong err)
+static void common_semi_open_cb(CPUState *cs, target_ulong ret, target_ulong err)
 {
-    ARMCPU *cpu = ARM_CPU(cs);
-    CPUARMState *env = &cpu->env;
     if (ret == (target_ulong)-1) {
         errno = err;
-        set_swi_errno(env, -1);
-        dealloc_guestfd(arm_semi_open_guestfd);
-    } else {
-        associate_guestfd(arm_semi_open_guestfd, ret);
-        ret = arm_semi_open_guestfd;
-    }
-
-    if (is_a64(env)) {
-        env->xregs[0] = ret;
+        set_swi_errno(cs, -1);
+        dealloc_guestfd(common_semi_open_guestfd);
     } else {
-        env->regs[0] = ret;
+        associate_guestfd(common_semi_open_guestfd, ret);
+        ret = common_semi_open_guestfd;
     }
+    common_semi_set_ret(cs, ret);
 }
 
-static target_ulong arm_gdb_syscall(ARMCPU *cpu, gdb_syscall_complete_cb cb,
-                                    const char *fmt, ...)
+static target_ulong common_semi_gdb_syscall(CPUState *cs, gdb_syscall_complete_cb cb,
+                                            const char *fmt, ...)
 {
     va_list va;
-    CPUARMState *env = &cpu->env;
 
     va_start(va, fmt);
     gdb_do_syscallv(cb, fmt, va);
@@ -384,7 +396,7 @@ static target_ulong arm_gdb_syscall(ARMCPU *cpu, gdb_syscall_complete_cb cb,
      * doing something with the return value is not possible to make.
      */
 
-    return is_a64(env) ? env->xregs[0] : env->regs[0];
+    return common_semi_arg(cs, 0);
 }
 
 /*
@@ -393,20 +405,18 @@ static target_ulong arm_gdb_syscall(ARMCPU *cpu, gdb_syscall_complete_cb cb,
  * do the work and return the required return value for the guest,
  * setting the guest errno if appropriate.
  */
-typedef uint32_t sys_closefn(ARMCPU *cpu, GuestFD *gf);
-typedef uint32_t sys_writefn(ARMCPU *cpu, GuestFD *gf,
+typedef uint32_t sys_closefn(CPUState *cs, GuestFD *gf);
+typedef uint32_t sys_writefn(CPUState *cs, GuestFD *gf,
                              target_ulong buf, uint32_t len);
-typedef uint32_t sys_readfn(ARMCPU *cpu, GuestFD *gf,
+typedef uint32_t sys_readfn(CPUState *cs, GuestFD *gf,
                             target_ulong buf, uint32_t len);
-typedef uint32_t sys_isattyfn(ARMCPU *cpu, GuestFD *gf);
-typedef uint32_t sys_seekfn(ARMCPU *cpu, GuestFD *gf,
+typedef uint32_t sys_isattyfn(CPUState *cs, GuestFD *gf);
+typedef uint32_t sys_seekfn(CPUState *cs, GuestFD *gf,
                             target_ulong offset);
-typedef uint32_t sys_flenfn(ARMCPU *cpu, GuestFD *gf);
+typedef uint32_t sys_flenfn(CPUState *cs, GuestFD *gf);
 
-static uint32_t host_closefn(ARMCPU *cpu, GuestFD *gf)
+static uint32_t host_closefn(CPUState *cs, GuestFD *gf)
 {
-    CPUARMState *env = &cpu->env;
-
     /*
      * Only close the underlying host fd if it's one we opened on behalf
      * of the guest in SYS_OPEN.
@@ -416,20 +426,21 @@ static uint32_t host_closefn(ARMCPU *cpu, GuestFD *gf)
         gf->hostfd == STDERR_FILENO) {
         return 0;
     }
-    return set_swi_errno(env, close(gf->hostfd));
+    return set_swi_errno(cs, close(gf->hostfd));
 }
 
-static uint32_t host_writefn(ARMCPU *cpu, GuestFD *gf,
+static uint32_t host_writefn(CPUState *cs, GuestFD *gf,
                              target_ulong buf, uint32_t len)
 {
+    CPUArchState *env = cs->env_ptr;
     uint32_t ret;
-    CPUARMState *env = &cpu->env;
     char *s = lock_user(VERIFY_READ, buf, len, 1);
+    (void) env; /* Used in arm softmmu lock_user implicitly */
     if (!s) {
         /* Return bytes not written on error */
         return len;
     }
-    ret = set_swi_errno(env, write(gf->hostfd, s, len));
+    ret = set_swi_errno(cs, write(gf->hostfd, s, len));
     unlock_user(s, buf, 0);
     if (ret == (uint32_t)-1) {
         ret = 0;
@@ -438,18 +449,19 @@ static uint32_t host_writefn(ARMCPU *cpu, GuestFD *gf,
     return len - ret;
 }
 
-static uint32_t host_readfn(ARMCPU *cpu, GuestFD *gf,
+static uint32_t host_readfn(CPUState *cs, GuestFD *gf,
                             target_ulong buf, uint32_t len)
 {
+    CPUArchState *env = cs->env_ptr;
     uint32_t ret;
-    CPUARMState *env = &cpu->env;
     char *s = lock_user(VERIFY_WRITE, buf, len, 0);
+    (void) env; /* Used in arm softmmu lock_user implicitly */
     if (!s) {
         /* return bytes not read */
         return len;
     }
     do {
-        ret = set_swi_errno(env, read(gf->hostfd, s, len));
+        ret = set_swi_errno(cs, read(gf->hostfd, s, len));
     } while (ret == -1 && errno == EINTR);
     unlock_user(s, buf, len);
     if (ret == (uint32_t)-1) {
@@ -459,68 +471,66 @@ static uint32_t host_readfn(ARMCPU *cpu, GuestFD *gf,
     return len - ret;
 }
 
-static uint32_t host_isattyfn(ARMCPU *cpu, GuestFD *gf)
+static uint32_t host_isattyfn(CPUState *cs, GuestFD *gf)
 {
     return isatty(gf->hostfd);
 }
 
-static uint32_t host_seekfn(ARMCPU *cpu, GuestFD *gf, target_ulong offset)
+static uint32_t host_seekfn(CPUState *cs, GuestFD *gf, target_ulong offset)
 {
-    CPUARMState *env = &cpu->env;
-    uint32_t ret = set_swi_errno(env, lseek(gf->hostfd, offset, SEEK_SET));
+    uint32_t ret = set_swi_errno(cs, lseek(gf->hostfd, offset, SEEK_SET));
     if (ret == (uint32_t)-1) {
         return -1;
     }
     return 0;
 }
 
-static uint32_t host_flenfn(ARMCPU *cpu, GuestFD *gf)
+static uint32_t host_flenfn(CPUState *cs, GuestFD *gf)
 {
-    CPUARMState *env = &cpu->env;
     struct stat buf;
-    uint32_t ret = set_swi_errno(env, fstat(gf->hostfd, &buf));
+    uint32_t ret = set_swi_errno(cs, fstat(gf->hostfd, &buf));
     if (ret == (uint32_t)-1) {
         return -1;
     }
     return buf.st_size;
 }
 
-static uint32_t gdb_closefn(ARMCPU *cpu, GuestFD *gf)
+static uint32_t gdb_closefn(CPUState *cs, GuestFD *gf)
 {
-    return arm_gdb_syscall(cpu, arm_semi_cb, "close,%x", gf->hostfd);
+    return common_semi_gdb_syscall(cs, common_semi_cb, "close,%x", gf->hostfd);
 }
 
-static uint32_t gdb_writefn(ARMCPU *cpu, GuestFD *gf,
+static uint32_t gdb_writefn(CPUState *cs, GuestFD *gf,
                             target_ulong buf, uint32_t len)
 {
-    arm_semi_syscall_len = len;
-    return arm_gdb_syscall(cpu, arm_semi_cb, "write,%x,%x,%x",
-                           gf->hostfd, buf, len);
+    common_semi_syscall_len = len;
+    return common_semi_gdb_syscall(cs, common_semi_cb, "write,%x,%x,%x",
+                                   gf->hostfd, buf, len);
 }
 
-static uint32_t gdb_readfn(ARMCPU *cpu, GuestFD *gf,
+static uint32_t gdb_readfn(CPUState *cs, GuestFD *gf,
                            target_ulong buf, uint32_t len)
 {
-    arm_semi_syscall_len = len;
-    return arm_gdb_syscall(cpu, arm_semi_cb, "read,%x,%x,%x",
-                           gf->hostfd, buf, len);
+    common_semi_syscall_len = len;
+    return common_semi_gdb_syscall(cs, common_semi_cb, "read,%x,%x,%x",
+                                   gf->hostfd, buf, len);
 }
 
-static uint32_t gdb_isattyfn(ARMCPU *cpu, GuestFD *gf)
+static uint32_t gdb_isattyfn(CPUState *cs, GuestFD *gf)
 {
-    return arm_gdb_syscall(cpu, arm_semi_cb, "isatty,%x", gf->hostfd);
+    return common_semi_gdb_syscall(cs, common_semi_cb, "isatty,%x", gf->hostfd);
 }
 
-static uint32_t gdb_seekfn(ARMCPU *cpu, GuestFD *gf, target_ulong offset)
+static uint32_t gdb_seekfn(CPUState *cs, GuestFD *gf, target_ulong offset)
 {
-    return arm_gdb_syscall(cpu, arm_semi_cb, "lseek,%x,%x,0",
-                           gf->hostfd, offset);
+    return common_semi_gdb_syscall(cs, common_semi_cb, "lseek,%x,%x,0",
+                                   gf->hostfd, offset);
 }
 
-static uint32_t gdb_flenfn(ARMCPU *cpu, GuestFD *gf)
+static uint32_t gdb_flenfn(CPUState *cs, GuestFD *gf)
 {
-    return arm_gdb_syscall(cpu, arm_semi_flen_cb, "fstat,%x,%x",
-                           gf->hostfd, arm_flen_buf(cpu));
+    return common_semi_gdb_syscall(cs, common_semi_flen_cb, "fstat,%x,%x",
+                                   gf->hostfd, common_semi_flen_buf(cs));
 }
 
 #define SHFB_MAGIC_0 0x53
@@ -549,31 +559,29 @@ static void init_featurefile_guestfd(int guestfd)
     gf->featurefile_offset = 0;
 }
 
-static uint32_t featurefile_closefn(ARMCPU *cpu, GuestFD *gf)
+static uint32_t featurefile_closefn(CPUState *cs, GuestFD *gf)
 {
     /* Nothing to do */
     return 0;
 }
 
-static uint32_t featurefile_writefn(ARMCPU *cpu, GuestFD *gf,
+static uint32_t featurefile_writefn(CPUState *cs, GuestFD *gf,
                                     target_ulong buf, uint32_t len)
 {
     /* This fd can never be open for writing */
-    CPUARMState *env = &cpu->env;
 
     errno = EBADF;
-    return set_swi_errno(env, -1);
+    return set_swi_errno(cs, -1);
 }
 
-static uint32_t featurefile_readfn(ARMCPU *cpu, GuestFD *gf,
+static uint32_t featurefile_readfn(CPUState *cs, GuestFD *gf,
                                    target_ulong buf, uint32_t len)
 {
+    CPUArchState *env = cs->env_ptr;
     uint32_t i;
-#ifndef CONFIG_USER_ONLY
-    CPUARMState *env = &cpu->env;
-#endif
     char *s;
 
+    (void) env; /* Used in arm softmmu lock_user implicitly */
     s = lock_user(VERIFY_WRITE, buf, len, 0);
     if (!s) {
         return len;
@@ -593,19 +601,19 @@ static uint32_t featurefile_readfn(ARMCPU *cpu, GuestFD *gf,
     return len - i;
 }
 
-static uint32_t featurefile_isattyfn(ARMCPU *cpu, GuestFD *gf)
+static uint32_t featurefile_isattyfn(CPUState *cs, GuestFD *gf)
 {
     return 0;
 }
 
-static uint32_t featurefile_seekfn(ARMCPU *cpu, GuestFD *gf,
+static uint32_t featurefile_seekfn(CPUState *cs, GuestFD *gf,
                                    target_ulong offset)
 {
     gf->featurefile_offset = offset;
     return 0;
 }
 
-static uint32_t featurefile_flenfn(ARMCPU *cpu, GuestFD *gf)
+static uint32_t featurefile_flenfn(CPUState *cs, GuestFD *gf)
 {
     return sizeof(featurefile_data);
 }
@@ -649,16 +657,17 @@ static const GuestFDFunctions guestfd_fns[] = {
 /* Read the input value from the argument block; fail the semihosting
  * call if the memory read fails.
  */
+#ifdef TARGET_ARM
 #define GET_ARG(n) do {                                 \
     if (is_a64(env)) {                                  \
         if (get_user_u64(arg ## n, args + (n) * 8)) {   \
             errno = EFAULT;                             \
-            return set_swi_errno(env, -1);              \
+            return set_swi_errno(cs, -1);              \
         }                                               \
     } else {                                            \
         if (get_user_u32(arg ## n, args + (n) * 4)) {   \
             errno = EFAULT;                             \
-            return set_swi_errno(env, -1);              \
+            return set_swi_errno(cs, -1);              \
         }                                               \
     }                                                   \
 } while (0)
@@ -667,6 +676,7 @@ static const GuestFDFunctions guestfd_fns[] = {
     (is_a64(env) ?                                      \
      put_user_u64(val, args + (n) * 8) :                \
      put_user_u32(val, args + (n) * 4))
+#endif
 
 /*
  * Do a semihosting call.
@@ -679,8 +689,7 @@ static const GuestFDFunctions guestfd_fns[] = {
  */
 target_ulong do_common_semihosting(CPUState *cs)
 {
-    ARMCPU *cpu = ARM_CPU(cs);
-    CPUARMState *env = &cpu->env;
+    CPUArchState *env = cs->env_ptr;
     target_ulong args;
     target_ulong arg0, arg1, arg2, arg3;
     char * s;
@@ -689,14 +698,9 @@ target_ulong do_common_semihosting(CPUState *cs)
     uint32_t len;
     GuestFD *gf;
 
-    if (is_a64(env)) {
-        /* 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];
-    }
+    (void) env; /* Used implicitly by arm lock_user macro */
+    nr = common_semi_arg(cs, 0) & 0xffffffffU;
+    args = common_semi_arg(cs, 1);
 
     switch (nr) {
     case TARGET_SYS_OPEN:
@@ -709,19 +713,19 @@ target_ulong do_common_semihosting(CPUState *cs)
         s = lock_user_string(arg0);
         if (!s) {
             errno = EFAULT;
-            return set_swi_errno(env, -1);
+            return set_swi_errno(cs, -1);
         }
         if (arg1 >= 12) {
             unlock_user(s, arg0, 0);
             errno = EINVAL;
-            return set_swi_errno(env, -1);
+            return set_swi_errno(cs, -1);
         }
 
         guestfd = alloc_guestfd();
         if (guestfd < 0) {
             unlock_user(s, arg0, 0);
             errno = EMFILE;
-            return set_swi_errno(env, -1);
+            return set_swi_errno(cs, -1);
         }
 
         if (strcmp(s, ":tt") == 0) {
@@ -750,18 +754,18 @@ target_ulong do_common_semihosting(CPUState *cs)
             if (arg1 != 0 && arg1 != 1) {
                 dealloc_guestfd(guestfd);
                 errno = EACCES;
-                return set_swi_errno(env, -1);
+                return set_swi_errno(cs, -1);
             }
             init_featurefile_guestfd(guestfd);
             return guestfd;
         }
 
         if (use_gdb_syscalls()) {
-            arm_semi_open_guestfd = guestfd;
-            ret = arm_gdb_syscall(cpu, arm_semi_open_cb, "open,%s,%x,1a4", arg0,
-                                  (int)arg2+1, gdb_open_modeflags[arg1]);
+            common_semi_open_guestfd = guestfd;
+            ret = common_semi_gdb_syscall(cs, common_semi_open_cb, "open,%s,%x,1a4", arg0,
+                                          (int)arg2+1, gdb_open_modeflags[arg1]);
         } else {
-            ret = set_swi_errno(env, open(s, open_modeflags[arg1], 0644));
+            ret = set_swi_errno(cs, open(s, open_modeflags[arg1], 0644));
             if (ret == (uint32_t)-1) {
                 dealloc_guestfd(guestfd);
             } else {
@@ -778,17 +782,17 @@ target_ulong do_common_semihosting(CPUState *cs)
         gf = get_guestfd(arg0);
         if (!gf) {
             errno = EBADF;
-            return set_swi_errno(env, -1);
+            return set_swi_errno(cs, -1);
         }
 
-        ret = guestfd_fns[gf->type].closefn(cpu, gf);
+        ret = guestfd_fns[gf->type].closefn(cs, gf);
         dealloc_guestfd(arg0);
         return ret;
     case TARGET_SYS_WRITEC:
-        qemu_semihosting_console_outc(env, args);
+        qemu_semihosting_console_outc(cs->env_ptr, args);
         return 0xdeadbeef;
     case TARGET_SYS_WRITE0:
-        return qemu_semihosting_console_outs(env, args);
+        return qemu_semihosting_console_outs(cs->env_ptr, args);
     case TARGET_SYS_WRITE:
         GET_ARG(0);
         GET_ARG(1);
@@ -798,10 +802,10 @@ target_ulong do_common_semihosting(CPUState *cs)
         gf = get_guestfd(arg0);
         if (!gf) {
             errno = EBADF;
-            return set_swi_errno(env, -1);
+            return set_swi_errno(cs, -1);
         }
 
-        return guestfd_fns[gf->type].writefn(cpu, gf, arg1, len);
+        return guestfd_fns[gf->type].writefn(cs, gf, arg1, len);
     case TARGET_SYS_READ:
         GET_ARG(0);
         GET_ARG(1);
@@ -811,22 +815,22 @@ target_ulong do_common_semihosting(CPUState *cs)
         gf = get_guestfd(arg0);
         if (!gf) {
             errno = EBADF;
-            return set_swi_errno(env, -1);
+            return set_swi_errno(cs, -1);
         }
 
-        return guestfd_fns[gf->type].readfn(cpu, gf, arg1, len);
+        return guestfd_fns[gf->type].readfn(cs, gf, arg1, len);
     case TARGET_SYS_READC:
-        return qemu_semihosting_console_inc(env);
+        return qemu_semihosting_console_inc(cs->env_ptr);
     case TARGET_SYS_ISTTY:
         GET_ARG(0);
 
         gf = get_guestfd(arg0);
         if (!gf) {
             errno = EBADF;
-            return set_swi_errno(env, -1);
+            return set_swi_errno(cs, -1);
         }
 
-        return guestfd_fns[gf->type].isattyfn(cpu, gf);
+        return guestfd_fns[gf->type].isattyfn(cs, gf);
     case TARGET_SYS_SEEK:
         GET_ARG(0);
         GET_ARG(1);
@@ -834,20 +838,20 @@ target_ulong do_common_semihosting(CPUState *cs)
         gf = get_guestfd(arg0);
         if (!gf) {
             errno = EBADF;
-            return set_swi_errno(env, -1);
+            return set_swi_errno(cs, -1);
         }
 
-        return guestfd_fns[gf->type].seekfn(cpu, gf, arg1);
+        return guestfd_fns[gf->type].seekfn(cs, gf, arg1);
     case TARGET_SYS_FLEN:
         GET_ARG(0);
 
         gf = get_guestfd(arg0);
         if (!gf) {
             errno = EBADF;
-            return set_swi_errno(env, -1);
+            return set_swi_errno(cs, -1);
         }
 
-        return guestfd_fns[gf->type].flenfn(cpu, gf);
+        return guestfd_fns[gf->type].flenfn(cs, gf);
     case TARGET_SYS_TMPNAM:
         qemu_log_mask(LOG_UNIMP, "%s: SYS_TMPNAM not implemented", __func__);
         return -1;
@@ -855,15 +859,15 @@ target_ulong do_common_semihosting(CPUState *cs)
         GET_ARG(0);
         GET_ARG(1);
         if (use_gdb_syscalls()) {
-            ret = arm_gdb_syscall(cpu, arm_semi_cb, "unlink,%s",
-                                  arg0, (int)arg1+1);
+            ret = common_semi_gdb_syscall(cs, common_semi_cb, "unlink,%s",
+                                          arg0, (int)arg1+1);
         } else {
             s = lock_user_string(arg0);
             if (!s) {
                 errno = EFAULT;
-                return set_swi_errno(env, -1);
+                return set_swi_errno(cs, -1);
             }
-            ret =  set_swi_errno(env, remove(s));
+            ret =  set_swi_errno(cs, remove(s));
             unlock_user(s, arg0, 0);
         }
         return ret;
@@ -873,17 +877,17 @@ target_ulong do_common_semihosting(CPUState *cs)
         GET_ARG(2);
         GET_ARG(3);
         if (use_gdb_syscalls()) {
-            return arm_gdb_syscall(cpu, arm_semi_cb, "rename,%s,%s",
-                                   arg0, (int)arg1+1, arg2, (int)arg3+1);
+            return common_semi_gdb_syscall(cs, common_semi_cb, "rename,%s,%s",
+                                           arg0, (int)arg1+1, arg2, (int)arg3+1);
         } else {
             char *s2;
             s = lock_user_string(arg0);
             s2 = lock_user_string(arg2);
             if (!s || !s2) {
                 errno = EFAULT;
-                ret = set_swi_errno(env, -1);
+                ret = set_swi_errno(cs, -1);
             } else {
-                ret = set_swi_errno(env, rename(s, s2));
+                ret = set_swi_errno(cs, rename(s, s2));
             }
             if (s2)
                 unlock_user(s2, arg2, 0);
@@ -894,25 +898,25 @@ target_ulong do_common_semihosting(CPUState *cs)
     case TARGET_SYS_CLOCK:
         return clock() / (CLOCKS_PER_SEC / 100);
     case TARGET_SYS_TIME:
-        return set_swi_errno(env, time(NULL));
+        return set_swi_errno(cs, time(NULL));
     case TARGET_SYS_SYSTEM:
         GET_ARG(0);
         GET_ARG(1);
         if (use_gdb_syscalls()) {
-            return arm_gdb_syscall(cpu, arm_semi_cb, "system,%s",
-                                   arg0, (int)arg1+1);
+            return common_semi_gdb_syscall(cs, common_semi_cb, "system,%s",
+                                           arg0, (int)arg1+1);
         } else {
             s = lock_user_string(arg0);
             if (!s) {
                 errno = EFAULT;
-                return set_swi_errno(env, -1);
+                return set_swi_errno(cs, -1);
             }
-            ret = set_swi_errno(env, system(s));
+            ret = set_swi_errno(cs, system(s));
             unlock_user(s, arg0, 0);
             return ret;
         }
     case TARGET_SYS_ERRNO:
-        return get_swi_errno(env);
+        return get_swi_errno(cs);
     case TARGET_SYS_GET_CMDLINE:
         {
             /* Build a command-line from the original argv.
@@ -964,21 +968,21 @@ target_ulong do_common_semihosting(CPUState *cs)
             if (output_size > input_size) {
                 /* Not enough space to store command-line arguments.  */
                 errno = E2BIG;
-                return set_swi_errno(env, -1);
+                return set_swi_errno(cs, -1);
             }
 
             /* Adjust the command-line length.  */
             if (SET_ARG(1, output_size - 1)) {
                 /* Couldn't write back to argument block */
                 errno = EFAULT;
-                return set_swi_errno(env, -1);
+                return set_swi_errno(cs, -1);
             }
 
             /* Lock the buffer on the ARM side.  */
             output_buffer = lock_user(VERIFY_WRITE, arg0, output_size, 0);
             if (!output_buffer) {
                 errno = EFAULT;
-                return set_swi_errno(env, -1);
+                return set_swi_errno(cs, -1);
             }
 
             /* Copy the command-line arguments.  */
@@ -994,7 +998,7 @@ target_ulong do_common_semihosting(CPUState *cs)
             if (copy_from_user(output_buffer, ts->info->arg_start,
                                output_size)) {
                 errno = EFAULT;
-                status = set_swi_errno(env, -1);
+                status = set_swi_errno(cs, -1);
                 goto out;
             }
 
@@ -1031,7 +1035,7 @@ target_ulong do_common_semihosting(CPUState *cs)
                 abi_ulong ret;
 
                 ts->heap_base = do_brk(0);
-                limit = ts->heap_base + ARM_ANGEL_HEAP_SIZE;
+                limit = ts->heap_base + COMMON_SEMI_HEAP_SIZE;
                 /* Try a big heap, and reduce the size if that fails.  */
                 for (;;) {
                     ret = do_brk(limit);
@@ -1059,23 +1063,19 @@ target_ulong do_common_semihosting(CPUState *cs)
             for (i = 0; i < ARRAY_SIZE(retvals); i++) {
                 bool fail;
 
-                if (is_a64(env)) {
-                    fail = put_user_u64(retvals[i], arg0 + i * 8);
-                } else {
-                    fail = put_user_u32(retvals[i], arg0 + i * 4);
-                }
+                fail = SET_ARG(i, retvals[i]);
 
                 if (fail) {
                     /* Couldn't write back to argument block */
                     errno = EFAULT;
-                    return set_swi_errno(env, -1);
+                    return set_swi_errno(cs, -1);
                 }
             }
             return 0;
         }
     case TARGET_SYS_EXIT:
     case TARGET_SYS_EXIT_EXTENDED:
-        if (nr == TARGET_SYS_EXIT_EXTENDED || is_a64(env)) {
+        if (common_semi_sys_exit_extended(cs, nr)) {
             /*
              * The A64 version of SYS_EXIT takes a parameter block,
              * so the application-exit type can return a subcode which
@@ -1100,7 +1100,7 @@ target_ulong do_common_semihosting(CPUState *cs)
              */
             ret = (args == ADP_Stopped_ApplicationExit) ? 0 : 1;
         }
-        gdb_exit(env, ret);
+        gdb_exit(cs->env_ptr, ret);
         exit(ret);
     case TARGET_SYS_SYNCCACHE:
         /*
@@ -1108,9 +1108,11 @@ target_ulong do_common_semihosting(CPUState *cs)
          * virtual address range. This is a nop for us since we don't
          * implement caches. This is only present on A64.
          */
-        if (is_a64(env)) {
+#ifdef TARGET_ARM
+        if (is_a64(cs->env_ptr)) {
             return 0;
         }
+#endif
         /* fall through -- invalid for A32/T32 */
     default:
         fprintf(stderr, "qemu: Unsupported SemiHosting SWI 0x%02x\n", nr);
-- 
2.28.0



^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH 3/4] semihosting: Change internal common-semi interfaces to use CPUState *
@ 2020-10-26 21:28   ` Keith Packard
  0 siblings, 0 replies; 32+ messages in thread
From: Keith Packard @ 2020-10-26 21:28 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alex Bennée, Laurent Vivier, Peter Maydell, qemu-arm,
	Palmer Dabbelt, Alistair Francis, Sagar Karandikar,
	Bastian Koppelmann, qemu-riscv, Keith Packard

This makes all of the internal interfaces architecture-independent and
renames the internal functions to use the 'common_semi' prefix instead
of 'arm' or 'arm_semi'.

To do this, some new architecture-specific internal helper functions
were created:

    static inline target_ulong
    common_semi_arg(CPUState *cs, int argno)

	Returns the argno'th semihosting argument, where argno can be
	either 0 or 1.

    static inline void
    common_semi_set_ret(CPUState *cs, target_ulong ret)

	Sets the semihosting return value.

    static inline bool
    common_semi_sys_exit_extended(CPUState *cs, int nr)

	This detects whether the specified semihosting call, which
	is either TARGET_SYS_EXIT or TARGET_SYS_EXIT_EXTENDED should
	be executed using the TARGET_SYS_EXIT_EXTENDED semantics.

In addition, several existing functions have been changed to flag
areas of code which are architecture specific:

    static target_ulong
    common_semi_flen_buf(CPUState *cs)

	Returns the current stack pointer minus 64, which is
	where a stat structure will be placed on the stack

    #define GET_ARG(n)

	This fetches arguments from the semihosting command's argument
	block. The address of this is available implicitly through the
	local 'args' variable. This is *mostly* architecture
	independent, but does depend on the current ABI's notion of
	the size of a 'long' parameter, which may need run-time checks
	(as it does on AARCH64)

    #define SET_ARG(n, val)

	This mirrors GET_ARG and stores data back into the argument
	block.

Signed-off-by: Keith Packard <keithp@keithp.com>
---
 hw/semihosting/common-semi.c | 326 ++++++++++++++++++-----------------
 1 file changed, 164 insertions(+), 162 deletions(-)

diff --git a/hw/semihosting/common-semi.c b/hw/semihosting/common-semi.c
index e0c59bc599..c77fb21bec 100644
--- a/hw/semihosting/common-semi.c
+++ b/hw/semihosting/common-semi.c
@@ -32,11 +32,12 @@
 #include "cpu.h"
 #include "hw/semihosting/semihost.h"
 #include "hw/semihosting/console.h"
+#include "hw/semihosting/common-semi.h"
 #include "qemu/log.h"
 #ifdef CONFIG_USER_ONLY
 #include "qemu.h"
 
-#define ARM_ANGEL_HEAP_SIZE (128 * 1024 * 1024)
+#define COMMON_SEMI_HEAP_SIZE (128 * 1024 * 1024)
 #else
 #include "exec/gdbstub.h"
 #include "qemu/cutils.h"
@@ -132,6 +133,36 @@ typedef struct GuestFD {
 
 static GArray *guestfd_array;
 
+#ifdef TARGET_ARM
+static inline target_ulong
+common_semi_arg(CPUState *cs, int argno)
+{
+    ARMCPU *cpu = ARM_CPU(cs);
+    CPUARMState *env = &cpu->env;
+    if (is_a64(env))
+        return env->xregs[argno];
+    else
+        return env->regs[argno];
+}
+
+static inline void
+common_semi_set_ret(CPUState *cs, target_ulong ret)
+{
+    ARMCPU *cpu = ARM_CPU(cs);
+    CPUARMState *env = &cpu->env;
+    if (is_a64(env))
+        env->xregs[0] = ret;
+    else
+        env->regs[0] = ret;
+}
+
+static inline bool
+common_semi_sys_exit_extended(CPUState *cs, int nr)
+{
+    return (nr == TARGET_SYS_EXIT_EXTENDED || is_a64(cs->env_ptr));
+}
+#endif /* TARGET_ARM */
+
 /*
  * Allocate a new guest file descriptor and return it; if we
  * couldn't allocate a new fd then return -1.
@@ -237,11 +268,10 @@ static target_ulong syscall_err;
 #include "exec/softmmu-semi.h"
 #endif
 
-static inline uint32_t set_swi_errno(CPUARMState *env, uint32_t code)
+static inline uint32_t set_swi_errno(CPUState *cs, uint32_t code)
 {
     if (code == (uint32_t)-1) {
 #ifdef CONFIG_USER_ONLY
-        CPUState *cs = env_cpu(env);
         TaskState *ts = cs->opaque;
 
         ts->swi_errno = errno;
@@ -252,10 +282,9 @@ static inline uint32_t set_swi_errno(CPUARMState *env, uint32_t code)
     return code;
 }
 
-static inline uint32_t get_swi_errno(CPUARMState *env)
+static inline uint32_t get_swi_errno(CPUState *cs)
 {
 #ifdef CONFIG_USER_ONLY
-    CPUState *cs = env_cpu(env);
     TaskState *ts = cs->opaque;
 
     return ts->swi_errno;
@@ -264,24 +293,22 @@ static inline uint32_t get_swi_errno(CPUARMState *env)
 #endif
 }
 
-static target_ulong arm_semi_syscall_len;
+static target_ulong common_semi_syscall_len;
 
-static void arm_semi_cb(CPUState *cs, target_ulong ret, target_ulong err)
+static void common_semi_cb(CPUState *cs, target_ulong ret, target_ulong err)
 {
-    ARMCPU *cpu = ARM_CPU(cs);
-    CPUARMState *env = &cpu->env;
-    target_ulong reg0 = is_a64(env) ? env->xregs[0] : env->regs[0];
+    target_ulong reg0 = common_semi_arg(cs, 0);
 
     if (ret == (target_ulong)-1) {
         errno = err;
-        set_swi_errno(env, -1);
+        set_swi_errno(cs, -1);
         reg0 = ret;
     } else {
         /* Fixup syscalls that use nonstardard return conventions.  */
         switch (reg0) {
         case TARGET_SYS_WRITE:
         case TARGET_SYS_READ:
-            reg0 = arm_semi_syscall_len - ret;
+            reg0 = common_semi_syscall_len - ret;
             break;
         case TARGET_SYS_SEEK:
             reg0 = 0;
@@ -291,77 +318,62 @@ static void arm_semi_cb(CPUState *cs, target_ulong ret, target_ulong err)
             break;
         }
     }
-    if (is_a64(env)) {
-        env->xregs[0] = reg0;
-    } else {
-        env->regs[0] = reg0;
-    }
+    common_semi_set_ret(cs, reg0);
 }
 
-static target_ulong arm_flen_buf(ARMCPU *cpu)
+static target_ulong common_semi_flen_buf(CPUState *cs)
 {
+    target_ulong sp;
+#ifdef TARGET_ARM
     /* 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.
      */
+    ARMCPU *cpu = ARM_CPU(cs);
     CPUARMState *env = &cpu->env;
-    target_ulong sp;
 
     if (is_a64(env)) {
         sp = env->xregs[31];
     } else {
         sp = env->regs[13];
     }
+#endif
 
     return sp - 64;
 }
 
-static void arm_semi_flen_cb(CPUState *cs, target_ulong ret, target_ulong err)
+static void common_semi_flen_cb(CPUState *cs, target_ulong ret, target_ulong err)
 {
-    ARMCPU *cpu = ARM_CPU(cs);
-    CPUARMState *env = &cpu->env;
     /* 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, arm_flen_buf(cpu) + 32, (uint8_t *)&size, 4, 0);
+    cpu_memory_rw_debug(cs, common_semi_flen_buf(cs) + 32, (uint8_t *)&size, 4, 0);
     size = be32_to_cpu(size);
-    if (is_a64(env)) {
-        env->xregs[0] = size;
-    } else {
-        env->regs[0] = size;
-    }
+    common_semi_set_ret(cs, size);
     errno = err;
-    set_swi_errno(env, -1);
+    set_swi_errno(cs, -1);
 }
 
-static int arm_semi_open_guestfd;
+static int common_semi_open_guestfd;
 
-static void arm_semi_open_cb(CPUState *cs, target_ulong ret, target_ulong err)
+static void common_semi_open_cb(CPUState *cs, target_ulong ret, target_ulong err)
 {
-    ARMCPU *cpu = ARM_CPU(cs);
-    CPUARMState *env = &cpu->env;
     if (ret == (target_ulong)-1) {
         errno = err;
-        set_swi_errno(env, -1);
-        dealloc_guestfd(arm_semi_open_guestfd);
-    } else {
-        associate_guestfd(arm_semi_open_guestfd, ret);
-        ret = arm_semi_open_guestfd;
-    }
-
-    if (is_a64(env)) {
-        env->xregs[0] = ret;
+        set_swi_errno(cs, -1);
+        dealloc_guestfd(common_semi_open_guestfd);
     } else {
-        env->regs[0] = ret;
+        associate_guestfd(common_semi_open_guestfd, ret);
+        ret = common_semi_open_guestfd;
     }
+    common_semi_set_ret(cs, ret);
 }
 
-static target_ulong arm_gdb_syscall(ARMCPU *cpu, gdb_syscall_complete_cb cb,
-                                    const char *fmt, ...)
+static target_ulong common_semi_gdb_syscall(CPUState *cs, gdb_syscall_complete_cb cb,
+                                            const char *fmt, ...)
 {
     va_list va;
-    CPUARMState *env = &cpu->env;
 
     va_start(va, fmt);
     gdb_do_syscallv(cb, fmt, va);
@@ -384,7 +396,7 @@ static target_ulong arm_gdb_syscall(ARMCPU *cpu, gdb_syscall_complete_cb cb,
      * doing something with the return value is not possible to make.
      */
 
-    return is_a64(env) ? env->xregs[0] : env->regs[0];
+    return common_semi_arg(cs, 0);
 }
 
 /*
@@ -393,20 +405,18 @@ static target_ulong arm_gdb_syscall(ARMCPU *cpu, gdb_syscall_complete_cb cb,
  * do the work and return the required return value for the guest,
  * setting the guest errno if appropriate.
  */
-typedef uint32_t sys_closefn(ARMCPU *cpu, GuestFD *gf);
-typedef uint32_t sys_writefn(ARMCPU *cpu, GuestFD *gf,
+typedef uint32_t sys_closefn(CPUState *cs, GuestFD *gf);
+typedef uint32_t sys_writefn(CPUState *cs, GuestFD *gf,
                              target_ulong buf, uint32_t len);
-typedef uint32_t sys_readfn(ARMCPU *cpu, GuestFD *gf,
+typedef uint32_t sys_readfn(CPUState *cs, GuestFD *gf,
                             target_ulong buf, uint32_t len);
-typedef uint32_t sys_isattyfn(ARMCPU *cpu, GuestFD *gf);
-typedef uint32_t sys_seekfn(ARMCPU *cpu, GuestFD *gf,
+typedef uint32_t sys_isattyfn(CPUState *cs, GuestFD *gf);
+typedef uint32_t sys_seekfn(CPUState *cs, GuestFD *gf,
                             target_ulong offset);
-typedef uint32_t sys_flenfn(ARMCPU *cpu, GuestFD *gf);
+typedef uint32_t sys_flenfn(CPUState *cs, GuestFD *gf);
 
-static uint32_t host_closefn(ARMCPU *cpu, GuestFD *gf)
+static uint32_t host_closefn(CPUState *cs, GuestFD *gf)
 {
-    CPUARMState *env = &cpu->env;
-
     /*
      * Only close the underlying host fd if it's one we opened on behalf
      * of the guest in SYS_OPEN.
@@ -416,20 +426,21 @@ static uint32_t host_closefn(ARMCPU *cpu, GuestFD *gf)
         gf->hostfd == STDERR_FILENO) {
         return 0;
     }
-    return set_swi_errno(env, close(gf->hostfd));
+    return set_swi_errno(cs, close(gf->hostfd));
 }
 
-static uint32_t host_writefn(ARMCPU *cpu, GuestFD *gf,
+static uint32_t host_writefn(CPUState *cs, GuestFD *gf,
                              target_ulong buf, uint32_t len)
 {
+    CPUArchState *env = cs->env_ptr;
     uint32_t ret;
-    CPUARMState *env = &cpu->env;
     char *s = lock_user(VERIFY_READ, buf, len, 1);
+    (void) env; /* Used in arm softmmu lock_user implicitly */
     if (!s) {
         /* Return bytes not written on error */
         return len;
     }
-    ret = set_swi_errno(env, write(gf->hostfd, s, len));
+    ret = set_swi_errno(cs, write(gf->hostfd, s, len));
     unlock_user(s, buf, 0);
     if (ret == (uint32_t)-1) {
         ret = 0;
@@ -438,18 +449,19 @@ static uint32_t host_writefn(ARMCPU *cpu, GuestFD *gf,
     return len - ret;
 }
 
-static uint32_t host_readfn(ARMCPU *cpu, GuestFD *gf,
+static uint32_t host_readfn(CPUState *cs, GuestFD *gf,
                             target_ulong buf, uint32_t len)
 {
+    CPUArchState *env = cs->env_ptr;
     uint32_t ret;
-    CPUARMState *env = &cpu->env;
     char *s = lock_user(VERIFY_WRITE, buf, len, 0);
+    (void) env; /* Used in arm softmmu lock_user implicitly */
     if (!s) {
         /* return bytes not read */
         return len;
     }
     do {
-        ret = set_swi_errno(env, read(gf->hostfd, s, len));
+        ret = set_swi_errno(cs, read(gf->hostfd, s, len));
     } while (ret == -1 && errno == EINTR);
     unlock_user(s, buf, len);
     if (ret == (uint32_t)-1) {
@@ -459,68 +471,66 @@ static uint32_t host_readfn(ARMCPU *cpu, GuestFD *gf,
     return len - ret;
 }
 
-static uint32_t host_isattyfn(ARMCPU *cpu, GuestFD *gf)
+static uint32_t host_isattyfn(CPUState *cs, GuestFD *gf)
 {
     return isatty(gf->hostfd);
 }
 
-static uint32_t host_seekfn(ARMCPU *cpu, GuestFD *gf, target_ulong offset)
+static uint32_t host_seekfn(CPUState *cs, GuestFD *gf, target_ulong offset)
 {
-    CPUARMState *env = &cpu->env;
-    uint32_t ret = set_swi_errno(env, lseek(gf->hostfd, offset, SEEK_SET));
+    uint32_t ret = set_swi_errno(cs, lseek(gf->hostfd, offset, SEEK_SET));
     if (ret == (uint32_t)-1) {
         return -1;
     }
     return 0;
 }
 
-static uint32_t host_flenfn(ARMCPU *cpu, GuestFD *gf)
+static uint32_t host_flenfn(CPUState *cs, GuestFD *gf)
 {
-    CPUARMState *env = &cpu->env;
     struct stat buf;
-    uint32_t ret = set_swi_errno(env, fstat(gf->hostfd, &buf));
+    uint32_t ret = set_swi_errno(cs, fstat(gf->hostfd, &buf));
     if (ret == (uint32_t)-1) {
         return -1;
     }
     return buf.st_size;
 }
 
-static uint32_t gdb_closefn(ARMCPU *cpu, GuestFD *gf)
+static uint32_t gdb_closefn(CPUState *cs, GuestFD *gf)
 {
-    return arm_gdb_syscall(cpu, arm_semi_cb, "close,%x", gf->hostfd);
+    return common_semi_gdb_syscall(cs, common_semi_cb, "close,%x", gf->hostfd);
 }
 
-static uint32_t gdb_writefn(ARMCPU *cpu, GuestFD *gf,
+static uint32_t gdb_writefn(CPUState *cs, GuestFD *gf,
                             target_ulong buf, uint32_t len)
 {
-    arm_semi_syscall_len = len;
-    return arm_gdb_syscall(cpu, arm_semi_cb, "write,%x,%x,%x",
-                           gf->hostfd, buf, len);
+    common_semi_syscall_len = len;
+    return common_semi_gdb_syscall(cs, common_semi_cb, "write,%x,%x,%x",
+                                   gf->hostfd, buf, len);
 }
 
-static uint32_t gdb_readfn(ARMCPU *cpu, GuestFD *gf,
+static uint32_t gdb_readfn(CPUState *cs, GuestFD *gf,
                            target_ulong buf, uint32_t len)
 {
-    arm_semi_syscall_len = len;
-    return arm_gdb_syscall(cpu, arm_semi_cb, "read,%x,%x,%x",
-                           gf->hostfd, buf, len);
+    common_semi_syscall_len = len;
+    return common_semi_gdb_syscall(cs, common_semi_cb, "read,%x,%x,%x",
+                                   gf->hostfd, buf, len);
 }
 
-static uint32_t gdb_isattyfn(ARMCPU *cpu, GuestFD *gf)
+static uint32_t gdb_isattyfn(CPUState *cs, GuestFD *gf)
 {
-    return arm_gdb_syscall(cpu, arm_semi_cb, "isatty,%x", gf->hostfd);
+    return common_semi_gdb_syscall(cs, common_semi_cb, "isatty,%x", gf->hostfd);
 }
 
-static uint32_t gdb_seekfn(ARMCPU *cpu, GuestFD *gf, target_ulong offset)
+static uint32_t gdb_seekfn(CPUState *cs, GuestFD *gf, target_ulong offset)
 {
-    return arm_gdb_syscall(cpu, arm_semi_cb, "lseek,%x,%x,0",
-                           gf->hostfd, offset);
+    return common_semi_gdb_syscall(cs, common_semi_cb, "lseek,%x,%x,0",
+                                   gf->hostfd, offset);
 }
 
-static uint32_t gdb_flenfn(ARMCPU *cpu, GuestFD *gf)
+static uint32_t gdb_flenfn(CPUState *cs, GuestFD *gf)
 {
-    return arm_gdb_syscall(cpu, arm_semi_flen_cb, "fstat,%x,%x",
-                           gf->hostfd, arm_flen_buf(cpu));
+    return common_semi_gdb_syscall(cs, common_semi_flen_cb, "fstat,%x,%x",
+                                   gf->hostfd, common_semi_flen_buf(cs));
 }
 
 #define SHFB_MAGIC_0 0x53
@@ -549,31 +559,29 @@ static void init_featurefile_guestfd(int guestfd)
     gf->featurefile_offset = 0;
 }
 
-static uint32_t featurefile_closefn(ARMCPU *cpu, GuestFD *gf)
+static uint32_t featurefile_closefn(CPUState *cs, GuestFD *gf)
 {
     /* Nothing to do */
     return 0;
 }
 
-static uint32_t featurefile_writefn(ARMCPU *cpu, GuestFD *gf,
+static uint32_t featurefile_writefn(CPUState *cs, GuestFD *gf,
                                     target_ulong buf, uint32_t len)
 {
     /* This fd can never be open for writing */
-    CPUARMState *env = &cpu->env;
 
     errno = EBADF;
-    return set_swi_errno(env, -1);
+    return set_swi_errno(cs, -1);
 }
 
-static uint32_t featurefile_readfn(ARMCPU *cpu, GuestFD *gf,
+static uint32_t featurefile_readfn(CPUState *cs, GuestFD *gf,
                                    target_ulong buf, uint32_t len)
 {
+    CPUArchState *env = cs->env_ptr;
     uint32_t i;
-#ifndef CONFIG_USER_ONLY
-    CPUARMState *env = &cpu->env;
-#endif
     char *s;
 
+    (void) env; /* Used in arm softmmu lock_user implicitly */
     s = lock_user(VERIFY_WRITE, buf, len, 0);
     if (!s) {
         return len;
@@ -593,19 +601,19 @@ static uint32_t featurefile_readfn(ARMCPU *cpu, GuestFD *gf,
     return len - i;
 }
 
-static uint32_t featurefile_isattyfn(ARMCPU *cpu, GuestFD *gf)
+static uint32_t featurefile_isattyfn(CPUState *cs, GuestFD *gf)
 {
     return 0;
 }
 
-static uint32_t featurefile_seekfn(ARMCPU *cpu, GuestFD *gf,
+static uint32_t featurefile_seekfn(CPUState *cs, GuestFD *gf,
                                    target_ulong offset)
 {
     gf->featurefile_offset = offset;
     return 0;
 }
 
-static uint32_t featurefile_flenfn(ARMCPU *cpu, GuestFD *gf)
+static uint32_t featurefile_flenfn(CPUState *cs, GuestFD *gf)
 {
     return sizeof(featurefile_data);
 }
@@ -649,16 +657,17 @@ static const GuestFDFunctions guestfd_fns[] = {
 /* Read the input value from the argument block; fail the semihosting
  * call if the memory read fails.
  */
+#ifdef TARGET_ARM
 #define GET_ARG(n) do {                                 \
     if (is_a64(env)) {                                  \
         if (get_user_u64(arg ## n, args + (n) * 8)) {   \
             errno = EFAULT;                             \
-            return set_swi_errno(env, -1);              \
+            return set_swi_errno(cs, -1);              \
         }                                               \
     } else {                                            \
         if (get_user_u32(arg ## n, args + (n) * 4)) {   \
             errno = EFAULT;                             \
-            return set_swi_errno(env, -1);              \
+            return set_swi_errno(cs, -1);              \
         }                                               \
     }                                                   \
 } while (0)
@@ -667,6 +676,7 @@ static const GuestFDFunctions guestfd_fns[] = {
     (is_a64(env) ?                                      \
      put_user_u64(val, args + (n) * 8) :                \
      put_user_u32(val, args + (n) * 4))
+#endif
 
 /*
  * Do a semihosting call.
@@ -679,8 +689,7 @@ static const GuestFDFunctions guestfd_fns[] = {
  */
 target_ulong do_common_semihosting(CPUState *cs)
 {
-    ARMCPU *cpu = ARM_CPU(cs);
-    CPUARMState *env = &cpu->env;
+    CPUArchState *env = cs->env_ptr;
     target_ulong args;
     target_ulong arg0, arg1, arg2, arg3;
     char * s;
@@ -689,14 +698,9 @@ target_ulong do_common_semihosting(CPUState *cs)
     uint32_t len;
     GuestFD *gf;
 
-    if (is_a64(env)) {
-        /* 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];
-    }
+    (void) env; /* Used implicitly by arm lock_user macro */
+    nr = common_semi_arg(cs, 0) & 0xffffffffU;
+    args = common_semi_arg(cs, 1);
 
     switch (nr) {
     case TARGET_SYS_OPEN:
@@ -709,19 +713,19 @@ target_ulong do_common_semihosting(CPUState *cs)
         s = lock_user_string(arg0);
         if (!s) {
             errno = EFAULT;
-            return set_swi_errno(env, -1);
+            return set_swi_errno(cs, -1);
         }
         if (arg1 >= 12) {
             unlock_user(s, arg0, 0);
             errno = EINVAL;
-            return set_swi_errno(env, -1);
+            return set_swi_errno(cs, -1);
         }
 
         guestfd = alloc_guestfd();
         if (guestfd < 0) {
             unlock_user(s, arg0, 0);
             errno = EMFILE;
-            return set_swi_errno(env, -1);
+            return set_swi_errno(cs, -1);
         }
 
         if (strcmp(s, ":tt") == 0) {
@@ -750,18 +754,18 @@ target_ulong do_common_semihosting(CPUState *cs)
             if (arg1 != 0 && arg1 != 1) {
                 dealloc_guestfd(guestfd);
                 errno = EACCES;
-                return set_swi_errno(env, -1);
+                return set_swi_errno(cs, -1);
             }
             init_featurefile_guestfd(guestfd);
             return guestfd;
         }
 
         if (use_gdb_syscalls()) {
-            arm_semi_open_guestfd = guestfd;
-            ret = arm_gdb_syscall(cpu, arm_semi_open_cb, "open,%s,%x,1a4", arg0,
-                                  (int)arg2+1, gdb_open_modeflags[arg1]);
+            common_semi_open_guestfd = guestfd;
+            ret = common_semi_gdb_syscall(cs, common_semi_open_cb, "open,%s,%x,1a4", arg0,
+                                          (int)arg2+1, gdb_open_modeflags[arg1]);
         } else {
-            ret = set_swi_errno(env, open(s, open_modeflags[arg1], 0644));
+            ret = set_swi_errno(cs, open(s, open_modeflags[arg1], 0644));
             if (ret == (uint32_t)-1) {
                 dealloc_guestfd(guestfd);
             } else {
@@ -778,17 +782,17 @@ target_ulong do_common_semihosting(CPUState *cs)
         gf = get_guestfd(arg0);
         if (!gf) {
             errno = EBADF;
-            return set_swi_errno(env, -1);
+            return set_swi_errno(cs, -1);
         }
 
-        ret = guestfd_fns[gf->type].closefn(cpu, gf);
+        ret = guestfd_fns[gf->type].closefn(cs, gf);
         dealloc_guestfd(arg0);
         return ret;
     case TARGET_SYS_WRITEC:
-        qemu_semihosting_console_outc(env, args);
+        qemu_semihosting_console_outc(cs->env_ptr, args);
         return 0xdeadbeef;
     case TARGET_SYS_WRITE0:
-        return qemu_semihosting_console_outs(env, args);
+        return qemu_semihosting_console_outs(cs->env_ptr, args);
     case TARGET_SYS_WRITE:
         GET_ARG(0);
         GET_ARG(1);
@@ -798,10 +802,10 @@ target_ulong do_common_semihosting(CPUState *cs)
         gf = get_guestfd(arg0);
         if (!gf) {
             errno = EBADF;
-            return set_swi_errno(env, -1);
+            return set_swi_errno(cs, -1);
         }
 
-        return guestfd_fns[gf->type].writefn(cpu, gf, arg1, len);
+        return guestfd_fns[gf->type].writefn(cs, gf, arg1, len);
     case TARGET_SYS_READ:
         GET_ARG(0);
         GET_ARG(1);
@@ -811,22 +815,22 @@ target_ulong do_common_semihosting(CPUState *cs)
         gf = get_guestfd(arg0);
         if (!gf) {
             errno = EBADF;
-            return set_swi_errno(env, -1);
+            return set_swi_errno(cs, -1);
         }
 
-        return guestfd_fns[gf->type].readfn(cpu, gf, arg1, len);
+        return guestfd_fns[gf->type].readfn(cs, gf, arg1, len);
     case TARGET_SYS_READC:
-        return qemu_semihosting_console_inc(env);
+        return qemu_semihosting_console_inc(cs->env_ptr);
     case TARGET_SYS_ISTTY:
         GET_ARG(0);
 
         gf = get_guestfd(arg0);
         if (!gf) {
             errno = EBADF;
-            return set_swi_errno(env, -1);
+            return set_swi_errno(cs, -1);
         }
 
-        return guestfd_fns[gf->type].isattyfn(cpu, gf);
+        return guestfd_fns[gf->type].isattyfn(cs, gf);
     case TARGET_SYS_SEEK:
         GET_ARG(0);
         GET_ARG(1);
@@ -834,20 +838,20 @@ target_ulong do_common_semihosting(CPUState *cs)
         gf = get_guestfd(arg0);
         if (!gf) {
             errno = EBADF;
-            return set_swi_errno(env, -1);
+            return set_swi_errno(cs, -1);
         }
 
-        return guestfd_fns[gf->type].seekfn(cpu, gf, arg1);
+        return guestfd_fns[gf->type].seekfn(cs, gf, arg1);
     case TARGET_SYS_FLEN:
         GET_ARG(0);
 
         gf = get_guestfd(arg0);
         if (!gf) {
             errno = EBADF;
-            return set_swi_errno(env, -1);
+            return set_swi_errno(cs, -1);
         }
 
-        return guestfd_fns[gf->type].flenfn(cpu, gf);
+        return guestfd_fns[gf->type].flenfn(cs, gf);
     case TARGET_SYS_TMPNAM:
         qemu_log_mask(LOG_UNIMP, "%s: SYS_TMPNAM not implemented", __func__);
         return -1;
@@ -855,15 +859,15 @@ target_ulong do_common_semihosting(CPUState *cs)
         GET_ARG(0);
         GET_ARG(1);
         if (use_gdb_syscalls()) {
-            ret = arm_gdb_syscall(cpu, arm_semi_cb, "unlink,%s",
-                                  arg0, (int)arg1+1);
+            ret = common_semi_gdb_syscall(cs, common_semi_cb, "unlink,%s",
+                                          arg0, (int)arg1+1);
         } else {
             s = lock_user_string(arg0);
             if (!s) {
                 errno = EFAULT;
-                return set_swi_errno(env, -1);
+                return set_swi_errno(cs, -1);
             }
-            ret =  set_swi_errno(env, remove(s));
+            ret =  set_swi_errno(cs, remove(s));
             unlock_user(s, arg0, 0);
         }
         return ret;
@@ -873,17 +877,17 @@ target_ulong do_common_semihosting(CPUState *cs)
         GET_ARG(2);
         GET_ARG(3);
         if (use_gdb_syscalls()) {
-            return arm_gdb_syscall(cpu, arm_semi_cb, "rename,%s,%s",
-                                   arg0, (int)arg1+1, arg2, (int)arg3+1);
+            return common_semi_gdb_syscall(cs, common_semi_cb, "rename,%s,%s",
+                                           arg0, (int)arg1+1, arg2, (int)arg3+1);
         } else {
             char *s2;
             s = lock_user_string(arg0);
             s2 = lock_user_string(arg2);
             if (!s || !s2) {
                 errno = EFAULT;
-                ret = set_swi_errno(env, -1);
+                ret = set_swi_errno(cs, -1);
             } else {
-                ret = set_swi_errno(env, rename(s, s2));
+                ret = set_swi_errno(cs, rename(s, s2));
             }
             if (s2)
                 unlock_user(s2, arg2, 0);
@@ -894,25 +898,25 @@ target_ulong do_common_semihosting(CPUState *cs)
     case TARGET_SYS_CLOCK:
         return clock() / (CLOCKS_PER_SEC / 100);
     case TARGET_SYS_TIME:
-        return set_swi_errno(env, time(NULL));
+        return set_swi_errno(cs, time(NULL));
     case TARGET_SYS_SYSTEM:
         GET_ARG(0);
         GET_ARG(1);
         if (use_gdb_syscalls()) {
-            return arm_gdb_syscall(cpu, arm_semi_cb, "system,%s",
-                                   arg0, (int)arg1+1);
+            return common_semi_gdb_syscall(cs, common_semi_cb, "system,%s",
+                                           arg0, (int)arg1+1);
         } else {
             s = lock_user_string(arg0);
             if (!s) {
                 errno = EFAULT;
-                return set_swi_errno(env, -1);
+                return set_swi_errno(cs, -1);
             }
-            ret = set_swi_errno(env, system(s));
+            ret = set_swi_errno(cs, system(s));
             unlock_user(s, arg0, 0);
             return ret;
         }
     case TARGET_SYS_ERRNO:
-        return get_swi_errno(env);
+        return get_swi_errno(cs);
     case TARGET_SYS_GET_CMDLINE:
         {
             /* Build a command-line from the original argv.
@@ -964,21 +968,21 @@ target_ulong do_common_semihosting(CPUState *cs)
             if (output_size > input_size) {
                 /* Not enough space to store command-line arguments.  */
                 errno = E2BIG;
-                return set_swi_errno(env, -1);
+                return set_swi_errno(cs, -1);
             }
 
             /* Adjust the command-line length.  */
             if (SET_ARG(1, output_size - 1)) {
                 /* Couldn't write back to argument block */
                 errno = EFAULT;
-                return set_swi_errno(env, -1);
+                return set_swi_errno(cs, -1);
             }
 
             /* Lock the buffer on the ARM side.  */
             output_buffer = lock_user(VERIFY_WRITE, arg0, output_size, 0);
             if (!output_buffer) {
                 errno = EFAULT;
-                return set_swi_errno(env, -1);
+                return set_swi_errno(cs, -1);
             }
 
             /* Copy the command-line arguments.  */
@@ -994,7 +998,7 @@ target_ulong do_common_semihosting(CPUState *cs)
             if (copy_from_user(output_buffer, ts->info->arg_start,
                                output_size)) {
                 errno = EFAULT;
-                status = set_swi_errno(env, -1);
+                status = set_swi_errno(cs, -1);
                 goto out;
             }
 
@@ -1031,7 +1035,7 @@ target_ulong do_common_semihosting(CPUState *cs)
                 abi_ulong ret;
 
                 ts->heap_base = do_brk(0);
-                limit = ts->heap_base + ARM_ANGEL_HEAP_SIZE;
+                limit = ts->heap_base + COMMON_SEMI_HEAP_SIZE;
                 /* Try a big heap, and reduce the size if that fails.  */
                 for (;;) {
                     ret = do_brk(limit);
@@ -1059,23 +1063,19 @@ target_ulong do_common_semihosting(CPUState *cs)
             for (i = 0; i < ARRAY_SIZE(retvals); i++) {
                 bool fail;
 
-                if (is_a64(env)) {
-                    fail = put_user_u64(retvals[i], arg0 + i * 8);
-                } else {
-                    fail = put_user_u32(retvals[i], arg0 + i * 4);
-                }
+                fail = SET_ARG(i, retvals[i]);
 
                 if (fail) {
                     /* Couldn't write back to argument block */
                     errno = EFAULT;
-                    return set_swi_errno(env, -1);
+                    return set_swi_errno(cs, -1);
                 }
             }
             return 0;
         }
     case TARGET_SYS_EXIT:
     case TARGET_SYS_EXIT_EXTENDED:
-        if (nr == TARGET_SYS_EXIT_EXTENDED || is_a64(env)) {
+        if (common_semi_sys_exit_extended(cs, nr)) {
             /*
              * The A64 version of SYS_EXIT takes a parameter block,
              * so the application-exit type can return a subcode which
@@ -1100,7 +1100,7 @@ target_ulong do_common_semihosting(CPUState *cs)
              */
             ret = (args == ADP_Stopped_ApplicationExit) ? 0 : 1;
         }
-        gdb_exit(env, ret);
+        gdb_exit(cs->env_ptr, ret);
         exit(ret);
     case TARGET_SYS_SYNCCACHE:
         /*
@@ -1108,9 +1108,11 @@ target_ulong do_common_semihosting(CPUState *cs)
          * virtual address range. This is a nop for us since we don't
          * implement caches. This is only present on A64.
          */
-        if (is_a64(env)) {
+#ifdef TARGET_ARM
+        if (is_a64(cs->env_ptr)) {
             return 0;
         }
+#endif
         /* fall through -- invalid for A32/T32 */
     default:
         fprintf(stderr, "qemu: Unsupported SemiHosting SWI 0x%02x\n", nr);
-- 
2.28.0



^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH 4/4] riscv: Add semihosting support [v10]
  2020-10-26 21:28 ` Keith Packard
@ 2020-10-26 21:28   ` Keith Packard
  -1 siblings, 0 replies; 32+ messages in thread
From: Keith Packard via @ 2020-10-26 21:28 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alex Bennée, Laurent Vivier, Peter Maydell, qemu-arm,
	Palmer Dabbelt, Alistair Francis, Sagar Karandikar,
	Bastian Koppelmann, qemu-riscv, Keith Packard

Adapt the arm semihosting support code for RISCV. This implementation
is based on the standard for RISC-V semihosting version 0.2 as
documented in

   https://github.com/riscv/riscv-semihosting-spec/releases/tag/0.2

Signed-off-by: Keith Packard <keithp@keithp.com>

---

v2:
	Update PC after exception is handled to follow
	change in the ARM version for SYS_READC

v3:
	Disallow semihosting in user mode; report a regular
	breakpoint in that case.

v4:
	Fix errors reported by checkpatch

v5:
	Reference current RISC-V semihosting specification

v6:
	Add support for semihosting in riscv64-linux-user and
	riscv32-linux-user

v7:
	Add meson build support

v8:
	Fix errors reported by checkpatch that crept in.

v9:
	Changes suggested by Alistair Francis <alistair23@gmail.com>:
	Don't add me to the MAINTAINERS file.
	Remove duplicate #include in target/riscv/cpu.h
	Reference RISC-V semihosting spec in target/riscv/riscv-semi.c

v10:
	Use common semihosting implementation instead of a separate copy.

	Make sure addresses of the three breakpoint-signaling
	instructions all lie within the same page. Change suggested by
	Richard Henderson <richard.henderson@linaro.org>
---
 default-configs/devices/riscv32-softmmu.mak   |  1 +
 default-configs/devices/riscv64-softmmu.mak   |  1 +
 hw/semihosting/common-semi.c                  | 51 ++++++++++++++++++-
 hw/semihosting/common-semi.h                  |  5 +-
 hw/semihosting/meson.build                    |  2 +
 linux-user/meson.build                        |  3 ++
 linux-user/qemu.h                             |  4 +-
 linux-user/semihost.c                         |  8 +--
 qemu-options.hx                               | 10 ++--
 target/riscv/cpu_bits.h                       |  1 +
 target/riscv/cpu_helper.c                     | 10 ++++
 .../riscv/insn_trans/trans_privileged.c.inc   | 37 +++++++++++++-
 target/riscv/translate.c                      | 11 ++++
 13 files changed, 132 insertions(+), 12 deletions(-)

diff --git a/default-configs/devices/riscv32-softmmu.mak b/default-configs/devices/riscv32-softmmu.mak
index 94a236c9c2..e8a4eeebec 100644
--- a/default-configs/devices/riscv32-softmmu.mak
+++ b/default-configs/devices/riscv32-softmmu.mak
@@ -3,6 +3,7 @@
 # Uncomment the following lines to disable these optional devices:
 #
 #CONFIG_PCI_DEVICES=n
+CONFIG_SEMIHOSTING=y
 
 # Boards:
 #
diff --git a/default-configs/devices/riscv64-softmmu.mak b/default-configs/devices/riscv64-softmmu.mak
index 76b6195648..d8a87b7671 100644
--- a/default-configs/devices/riscv64-softmmu.mak
+++ b/default-configs/devices/riscv64-softmmu.mak
@@ -3,6 +3,7 @@
 # Uncomment the following lines to disable these optional devices:
 #
 #CONFIG_PCI_DEVICES=n
+CONFIG_SEMIHOSTING=y
 
 # Boards:
 #
diff --git a/hw/semihosting/common-semi.c b/hw/semihosting/common-semi.c
index c77fb21bec..8675934a71 100644
--- a/hw/semihosting/common-semi.c
+++ b/hw/semihosting/common-semi.c
@@ -1,6 +1,6 @@
 /*
  *  Semihosting support for systems modeled on the Arm "Angel"
- *  semihosting syscalls design.
+ *  semihosting syscalls design. This includes Arm and RISC-V processors
  *
  *  Copyright (c) 2005, 2007 CodeSourcery.
  *  Copyright (c) 2019 Linaro
@@ -25,6 +25,10 @@
  *  ARM Semihosting is documented in:
  *     Semihosting for AArch32 and AArch64 Release 2.0
  *     https://static.docs.arm.com/100863/0200/semihosting.pdf
+ *
+ *  RISC-V Semihosting is documented in:
+ *     RISC-V Semihosting
+ *     https://github.com/riscv/riscv-semihosting-spec/blob/main/riscv-semihosting-spec.adoc
  */
 
 #include "qemu/osdep.h"
@@ -163,6 +167,30 @@ common_semi_sys_exit_extended(CPUState *cs, int nr)
 }
 #endif /* TARGET_ARM */
 
+#ifdef TARGET_RISCV
+static inline target_ulong
+common_semi_arg(CPUState *cs, int argno)
+{
+    RISCVCPU *cpu = RISCV_CPU(cs);
+    CPURISCVState *env = &cpu->env;
+    return env->gpr[xA0 + argno];
+}
+
+static inline void
+common_semi_set_ret(CPUState *cs, target_ulong ret)
+{
+    RISCVCPU *cpu = RISCV_CPU(cs);
+    CPURISCVState *env = &cpu->env;
+    env->gpr[xA0] = ret;
+}
+
+static inline bool
+common_semi_sys_exit_extended(CPUState *cs, int nr)
+{
+    return (nr == TARGET_SYS_EXIT_EXTENDED || sizeof(target_ulong) == 0);
+}
+#endif
+
 /*
  * Allocate a new guest file descriptor and return it; if we
  * couldn't allocate a new fd then return -1.
@@ -339,6 +367,12 @@ static target_ulong common_semi_flen_buf(CPUState *cs)
         sp = env->regs[13];
     }
 #endif
+#ifdef TARGET_RISCV
+    RISCVCPU *cpu = RISCV_CPU(cs);
+    CPURISCVState *env = &cpu->env;
+
+    sp = env->gpr[xSP];
+#endif
 
     return sp - 64;
 }
@@ -678,6 +712,18 @@ static const GuestFDFunctions guestfd_fns[] = {
      put_user_u32(val, args + (n) * 4))
 #endif
 
+#ifdef TARGET_RISCV
+#define GET_ARG(n) do {                                                 \
+        if (get_user_ual(arg ## n, args + (n) * sizeof(target_ulong))) { \
+            errno = EFAULT;                                             \
+            return set_swi_errno(cs, -1);                              \
+        }                                                               \
+    } while (0)
+
+#define SET_ARG(n, val)                                 \
+    put_user_ual(val, args + (n) * sizeof(target_ulong))
+#endif
+
 /*
  * Do a semihosting call.
  *
@@ -1112,6 +1158,9 @@ target_ulong do_common_semihosting(CPUState *cs)
         if (is_a64(cs->env_ptr)) {
             return 0;
         }
+#endif
+#ifdef TARGET_RISCV
+        return 0;
 #endif
         /* fall through -- invalid for A32/T32 */
     default:
diff --git a/hw/semihosting/common-semi.h b/hw/semihosting/common-semi.h
index bc53e92c79..0bfab1c669 100644
--- a/hw/semihosting/common-semi.h
+++ b/hw/semihosting/common-semi.h
@@ -1,6 +1,6 @@
 /*
  *  Semihosting support for systems modeled on the Arm "Angel"
- *  semihosting syscalls design.
+ *  semihosting syscalls design. This includes Arm and RISC-V processors
  *
  *  Copyright (c) 2005, 2007 CodeSourcery.
  *  Copyright (c) 2019 Linaro
@@ -26,6 +26,9 @@
  *     Semihosting for AArch32 and AArch64 Release 2.0
  *     https://static.docs.arm.com/100863/0200/semihosting.pdf
  *
+ *  RISC-V Semihosting is documented in:
+ *     RISC-V Semihosting
+ *     https://github.com/riscv/riscv-semihosting-spec/blob/main/riscv-semihosting-spec.adoc
  */
 
 #ifndef COMMON_SEMI_H
diff --git a/hw/semihosting/meson.build b/hw/semihosting/meson.build
index fbd2841e59..48a6c9b3e5 100644
--- a/hw/semihosting/meson.build
+++ b/hw/semihosting/meson.build
@@ -4,3 +4,5 @@ specific_ss.add(when: 'CONFIG_SEMIHOSTING', if_true: files(
 ))
 
 specific_ss.add(when: 'CONFIG_TCG', if_true: files ('common-semi.c'))
+specific_ss.add(when: 'TARGET_RISCV32', if_true: files ('common-semi.c'))
+specific_ss.add(when: 'TARGET_RISCV64', if_true: files ('common-semi.c'))
diff --git a/linux-user/meson.build b/linux-user/meson.build
index 2fdd12cee5..68fce095fb 100644
--- a/linux-user/meson.build
+++ b/linux-user/meson.build
@@ -20,6 +20,9 @@ linux_user_ss.add(when: 'TARGET_I386', if_true: files('vm86.c'))
 linux_user_ss.add(when: 'TARGET_AARCH64', if_true: files('semihost.c'))
 linux_user_ss.add(when: 'TARGET_ARM', if_true: files('semihost.c'))
 
+linux_user_ss.add(when: 'TARGET_RISCV64', if_true: files('semihost.c'))
+linux_user_ss.add(when: 'TARGET_RISCV32', if_true: files('semihost.c'))
+
 syscall_nr_generators = {}
 
 subdir('alpha')
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index 941ca99722..faeaab9614 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -105,6 +105,8 @@ typedef struct TaskState {
     /* FPA state */
     FPA11 fpa;
 # endif
+#endif
+#if defined(TARGET_ARM) || defined(TARGET_RISCV)
     int swi_errno;
 #endif
 #if defined(TARGET_I386) && !defined(TARGET_X86_64)
@@ -118,7 +120,7 @@ typedef struct TaskState {
 #ifdef TARGET_M68K
     abi_ulong tp_value;
 #endif
-#if defined(TARGET_ARM) || defined(TARGET_M68K)
+#if defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_RISCV)
     /* Extra fields for semihosted binaries.  */
     abi_ulong heap_base;
     abi_ulong heap_limit;
diff --git a/linux-user/semihost.c b/linux-user/semihost.c
index a1f0f6050e..c0015ee7f6 100644
--- a/linux-user/semihost.c
+++ b/linux-user/semihost.c
@@ -1,11 +1,11 @@
 /*
- * ARM Semihosting Console Support
+ * ARM Compatible Semihosting Console Support.
  *
  * Copyright (c) 2019 Linaro Ltd
  *
- * Currently ARM is unique in having support for semihosting support
- * in linux-user. So for now we implement the common console API but
- * just for arm linux-user.
+ * Currently ARM and RISC-V are unique in having support for
+ * semihosting support in linux-user. So for now we implement the
+ * common console API but just for arm and risc-v linux-user.
  *
  * SPDX-License-Identifier: GPL-2.0-or-later
  */
diff --git a/qemu-options.hx b/qemu-options.hx
index 2c83390504..9a606946c4 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -4184,10 +4184,10 @@ ERST
 DEF("semihosting", 0, QEMU_OPTION_semihosting,
     "-semihosting    semihosting mode\n",
     QEMU_ARCH_ARM | QEMU_ARCH_M68K | QEMU_ARCH_XTENSA | QEMU_ARCH_LM32 |
-    QEMU_ARCH_MIPS | QEMU_ARCH_NIOS2)
+    QEMU_ARCH_MIPS | QEMU_ARCH_NIOS2 | QEMU_ARCH_RISCV)
 SRST
 ``-semihosting``
-    Enable semihosting mode (ARM, M68K, Xtensa, MIPS, Nios II only).
+    Enable semihosting mode (ARM, M68K, Xtensa, MIPS, Nios II, RISC-V only).
 
     Note that this allows guest direct access to the host filesystem, so
     should only be used with a trusted guest OS.
@@ -4199,10 +4199,10 @@ DEF("semihosting-config", HAS_ARG, QEMU_OPTION_semihosting_config,
     "-semihosting-config [enable=on|off][,target=native|gdb|auto][,chardev=id][,arg=str[,...]]\n" \
     "                semihosting configuration\n",
 QEMU_ARCH_ARM | QEMU_ARCH_M68K | QEMU_ARCH_XTENSA | QEMU_ARCH_LM32 |
-QEMU_ARCH_MIPS | QEMU_ARCH_NIOS2)
+QEMU_ARCH_MIPS | QEMU_ARCH_NIOS2 | QEMU_ARCH_RISCV)
 SRST
 ``-semihosting-config [enable=on|off][,target=native|gdb|auto][,chardev=id][,arg=str[,...]]``
-    Enable and configure semihosting (ARM, M68K, Xtensa, MIPS, Nios II
+    Enable and configure semihosting (ARM, M68K, Xtensa, MIPS, Nios II, RISC-V
     only).
 
     Note that this allows guest direct access to the host filesystem, so
@@ -4217,6 +4217,8 @@ SRST
     open/read/write/seek/select. Tensilica baremetal libc for ISS and
     linux platform "sim" use this interface.
 
+    On RISC-V this implements the standard semihosting API, version 0.2.
+
     ``target=native|gdb|auto``
         Defines where the semihosting calls will be addressed, to QEMU
         (``native``) or to GDB (``gdb``). The default is ``auto``, which
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index bd36062877..26a60b9e27 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -556,6 +556,7 @@
 #define RISCV_EXCP_INST_PAGE_FAULT               0xc /* since: priv-1.10.0 */
 #define RISCV_EXCP_LOAD_PAGE_FAULT               0xd /* since: priv-1.10.0 */
 #define RISCV_EXCP_STORE_PAGE_FAULT              0xf /* since: priv-1.10.0 */
+#define RISCV_EXCP_SEMIHOST                      0x10
 #define RISCV_EXCP_INST_GUEST_PAGE_FAULT         0x14
 #define RISCV_EXCP_LOAD_GUEST_ACCESS_FAULT       0x15
 #define RISCV_EXCP_VIRT_INSTRUCTION_FAULT        0x16
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 4652082df1..d71611ec02 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -24,6 +24,7 @@
 #include "exec/exec-all.h"
 #include "tcg/tcg-op.h"
 #include "trace.h"
+#include "hw/semihosting/common-semi.h"
 
 int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch)
 {
@@ -875,6 +876,15 @@ void riscv_cpu_do_interrupt(CPUState *cs)
     target_ulong htval = 0;
     target_ulong mtval2 = 0;
 
+    if  (cause == RISCV_EXCP_SEMIHOST) {
+        if (env->priv >= PRV_S) {
+            env->gpr[xA0] = do_common_semihosting(cs);
+            env->pc += 4;
+            return;
+        }
+        cause = RISCV_EXCP_BREAKPOINT;
+    }
+
     if (!async) {
         /* set tval to badaddr for traps with address information */
         switch (cause) {
diff --git a/target/riscv/insn_trans/trans_privileged.c.inc b/target/riscv/insn_trans/trans_privileged.c.inc
index 2a61a853bf..32312be202 100644
--- a/target/riscv/insn_trans/trans_privileged.c.inc
+++ b/target/riscv/insn_trans/trans_privileged.c.inc
@@ -29,7 +29,42 @@ static bool trans_ecall(DisasContext *ctx, arg_ecall *a)
 
 static bool trans_ebreak(DisasContext *ctx, arg_ebreak *a)
 {
-    generate_exception(ctx, RISCV_EXCP_BREAKPOINT);
+    target_ulong    ebreak_addr = ctx->base.pc_next;
+    target_ulong    pre_addr = ebreak_addr - 4;
+    target_ulong    post_addr = ebreak_addr + 4;
+    uint32_t pre    = 0;
+    uint32_t ebreak = 0;
+    uint32_t post   = 0;
+
+    /*
+     * The RISC-V semihosting spec specifies the following
+     * three-instruction sequence to flag a semihosting call:
+     *
+     *      slli zero, zero, 0x1f       0x01f01013
+     *      ebreak                      0x00100073
+     *      srai zero, zero, 0x7        0x40705013
+     *
+     * The two shift operations on the zero register are no-ops, used
+     * here to signify a semihosting exception, rather than a breakpoint.
+     *
+     * Uncompressed instructions are required so that the sequence is easy
+     * to validate.
+     *
+     * The three instructions are required to lie in the same page so
+     * that no exception will be raised when fetching them.
+     */
+
+    if ((pre_addr & TARGET_PAGE_MASK) == (post_addr & TARGET_PAGE_MASK)) {
+        pre    = opcode_at(&ctx->base, pre_addr);
+        ebreak = opcode_at(&ctx->base, ebreak_addr);
+        post   = opcode_at(&ctx->base, post_addr);
+    }
+
+    if  (pre == 0x01f01013 && ebreak == 0x00100073 && post == 0x40705013) {
+        generate_exception(ctx, RISCV_EXCP_SEMIHOST);
+    } else {
+        generate_exception(ctx, RISCV_EXCP_BREAKPOINT);
+    }
     exit_tb(ctx); /* no chaining */
     ctx->base.is_jmp = DISAS_NORETURN;
     return true;
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 79dca2291b..ecf594babc 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -63,6 +63,7 @@ typedef struct DisasContext {
     uint16_t vlen;
     uint16_t mlen;
     bool vl_eq_vlmax;
+    CPUState *cs;
 } DisasContext;
 
 #ifdef TARGET_RISCV64
@@ -746,6 +747,15 @@ static bool gen_shift(DisasContext *ctx, arg_r *a,
     return true;
 }
 
+static uint32_t opcode_at(DisasContextBase *dcbase, target_ulong pc)
+{
+    DisasContext *ctx = container_of(dcbase, DisasContext, base);
+    CPUState *cpu = ctx->cs;
+    CPURISCVState *env = cpu->env_ptr;
+
+    return cpu_ldl_code(env, pc);
+}
+
 /* Include insn module translation function */
 #include "insn_trans/trans_rvi.c.inc"
 #include "insn_trans/trans_rvm.c.inc"
@@ -812,6 +822,7 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
     ctx->lmul = FIELD_EX32(tb_flags, TB_FLAGS, LMUL);
     ctx->mlen = 1 << (ctx->sew  + 3 - ctx->lmul);
     ctx->vl_eq_vlmax = FIELD_EX32(tb_flags, TB_FLAGS, VL_EQ_VLMAX);
+    ctx->cs = cs;
 }
 
 static void riscv_tr_tb_start(DisasContextBase *db, CPUState *cpu)
-- 
2.28.0



^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH 4/4] riscv: Add semihosting support [v10]
@ 2020-10-26 21:28   ` Keith Packard
  0 siblings, 0 replies; 32+ messages in thread
From: Keith Packard @ 2020-10-26 21:28 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alex Bennée, Laurent Vivier, Peter Maydell, qemu-arm,
	Palmer Dabbelt, Alistair Francis, Sagar Karandikar,
	Bastian Koppelmann, qemu-riscv, Keith Packard

Adapt the arm semihosting support code for RISCV. This implementation
is based on the standard for RISC-V semihosting version 0.2 as
documented in

   https://github.com/riscv/riscv-semihosting-spec/releases/tag/0.2

Signed-off-by: Keith Packard <keithp@keithp.com>

---

v2:
	Update PC after exception is handled to follow
	change in the ARM version for SYS_READC

v3:
	Disallow semihosting in user mode; report a regular
	breakpoint in that case.

v4:
	Fix errors reported by checkpatch

v5:
	Reference current RISC-V semihosting specification

v6:
	Add support for semihosting in riscv64-linux-user and
	riscv32-linux-user

v7:
	Add meson build support

v8:
	Fix errors reported by checkpatch that crept in.

v9:
	Changes suggested by Alistair Francis <alistair23@gmail.com>:
	Don't add me to the MAINTAINERS file.
	Remove duplicate #include in target/riscv/cpu.h
	Reference RISC-V semihosting spec in target/riscv/riscv-semi.c

v10:
	Use common semihosting implementation instead of a separate copy.

	Make sure addresses of the three breakpoint-signaling
	instructions all lie within the same page. Change suggested by
	Richard Henderson <richard.henderson@linaro.org>
---
 default-configs/devices/riscv32-softmmu.mak   |  1 +
 default-configs/devices/riscv64-softmmu.mak   |  1 +
 hw/semihosting/common-semi.c                  | 51 ++++++++++++++++++-
 hw/semihosting/common-semi.h                  |  5 +-
 hw/semihosting/meson.build                    |  2 +
 linux-user/meson.build                        |  3 ++
 linux-user/qemu.h                             |  4 +-
 linux-user/semihost.c                         |  8 +--
 qemu-options.hx                               | 10 ++--
 target/riscv/cpu_bits.h                       |  1 +
 target/riscv/cpu_helper.c                     | 10 ++++
 .../riscv/insn_trans/trans_privileged.c.inc   | 37 +++++++++++++-
 target/riscv/translate.c                      | 11 ++++
 13 files changed, 132 insertions(+), 12 deletions(-)

diff --git a/default-configs/devices/riscv32-softmmu.mak b/default-configs/devices/riscv32-softmmu.mak
index 94a236c9c2..e8a4eeebec 100644
--- a/default-configs/devices/riscv32-softmmu.mak
+++ b/default-configs/devices/riscv32-softmmu.mak
@@ -3,6 +3,7 @@
 # Uncomment the following lines to disable these optional devices:
 #
 #CONFIG_PCI_DEVICES=n
+CONFIG_SEMIHOSTING=y
 
 # Boards:
 #
diff --git a/default-configs/devices/riscv64-softmmu.mak b/default-configs/devices/riscv64-softmmu.mak
index 76b6195648..d8a87b7671 100644
--- a/default-configs/devices/riscv64-softmmu.mak
+++ b/default-configs/devices/riscv64-softmmu.mak
@@ -3,6 +3,7 @@
 # Uncomment the following lines to disable these optional devices:
 #
 #CONFIG_PCI_DEVICES=n
+CONFIG_SEMIHOSTING=y
 
 # Boards:
 #
diff --git a/hw/semihosting/common-semi.c b/hw/semihosting/common-semi.c
index c77fb21bec..8675934a71 100644
--- a/hw/semihosting/common-semi.c
+++ b/hw/semihosting/common-semi.c
@@ -1,6 +1,6 @@
 /*
  *  Semihosting support for systems modeled on the Arm "Angel"
- *  semihosting syscalls design.
+ *  semihosting syscalls design. This includes Arm and RISC-V processors
  *
  *  Copyright (c) 2005, 2007 CodeSourcery.
  *  Copyright (c) 2019 Linaro
@@ -25,6 +25,10 @@
  *  ARM Semihosting is documented in:
  *     Semihosting for AArch32 and AArch64 Release 2.0
  *     https://static.docs.arm.com/100863/0200/semihosting.pdf
+ *
+ *  RISC-V Semihosting is documented in:
+ *     RISC-V Semihosting
+ *     https://github.com/riscv/riscv-semihosting-spec/blob/main/riscv-semihosting-spec.adoc
  */
 
 #include "qemu/osdep.h"
@@ -163,6 +167,30 @@ common_semi_sys_exit_extended(CPUState *cs, int nr)
 }
 #endif /* TARGET_ARM */
 
+#ifdef TARGET_RISCV
+static inline target_ulong
+common_semi_arg(CPUState *cs, int argno)
+{
+    RISCVCPU *cpu = RISCV_CPU(cs);
+    CPURISCVState *env = &cpu->env;
+    return env->gpr[xA0 + argno];
+}
+
+static inline void
+common_semi_set_ret(CPUState *cs, target_ulong ret)
+{
+    RISCVCPU *cpu = RISCV_CPU(cs);
+    CPURISCVState *env = &cpu->env;
+    env->gpr[xA0] = ret;
+}
+
+static inline bool
+common_semi_sys_exit_extended(CPUState *cs, int nr)
+{
+    return (nr == TARGET_SYS_EXIT_EXTENDED || sizeof(target_ulong) == 0);
+}
+#endif
+
 /*
  * Allocate a new guest file descriptor and return it; if we
  * couldn't allocate a new fd then return -1.
@@ -339,6 +367,12 @@ static target_ulong common_semi_flen_buf(CPUState *cs)
         sp = env->regs[13];
     }
 #endif
+#ifdef TARGET_RISCV
+    RISCVCPU *cpu = RISCV_CPU(cs);
+    CPURISCVState *env = &cpu->env;
+
+    sp = env->gpr[xSP];
+#endif
 
     return sp - 64;
 }
@@ -678,6 +712,18 @@ static const GuestFDFunctions guestfd_fns[] = {
      put_user_u32(val, args + (n) * 4))
 #endif
 
+#ifdef TARGET_RISCV
+#define GET_ARG(n) do {                                                 \
+        if (get_user_ual(arg ## n, args + (n) * sizeof(target_ulong))) { \
+            errno = EFAULT;                                             \
+            return set_swi_errno(cs, -1);                              \
+        }                                                               \
+    } while (0)
+
+#define SET_ARG(n, val)                                 \
+    put_user_ual(val, args + (n) * sizeof(target_ulong))
+#endif
+
 /*
  * Do a semihosting call.
  *
@@ -1112,6 +1158,9 @@ target_ulong do_common_semihosting(CPUState *cs)
         if (is_a64(cs->env_ptr)) {
             return 0;
         }
+#endif
+#ifdef TARGET_RISCV
+        return 0;
 #endif
         /* fall through -- invalid for A32/T32 */
     default:
diff --git a/hw/semihosting/common-semi.h b/hw/semihosting/common-semi.h
index bc53e92c79..0bfab1c669 100644
--- a/hw/semihosting/common-semi.h
+++ b/hw/semihosting/common-semi.h
@@ -1,6 +1,6 @@
 /*
  *  Semihosting support for systems modeled on the Arm "Angel"
- *  semihosting syscalls design.
+ *  semihosting syscalls design. This includes Arm and RISC-V processors
  *
  *  Copyright (c) 2005, 2007 CodeSourcery.
  *  Copyright (c) 2019 Linaro
@@ -26,6 +26,9 @@
  *     Semihosting for AArch32 and AArch64 Release 2.0
  *     https://static.docs.arm.com/100863/0200/semihosting.pdf
  *
+ *  RISC-V Semihosting is documented in:
+ *     RISC-V Semihosting
+ *     https://github.com/riscv/riscv-semihosting-spec/blob/main/riscv-semihosting-spec.adoc
  */
 
 #ifndef COMMON_SEMI_H
diff --git a/hw/semihosting/meson.build b/hw/semihosting/meson.build
index fbd2841e59..48a6c9b3e5 100644
--- a/hw/semihosting/meson.build
+++ b/hw/semihosting/meson.build
@@ -4,3 +4,5 @@ specific_ss.add(when: 'CONFIG_SEMIHOSTING', if_true: files(
 ))
 
 specific_ss.add(when: 'CONFIG_TCG', if_true: files ('common-semi.c'))
+specific_ss.add(when: 'TARGET_RISCV32', if_true: files ('common-semi.c'))
+specific_ss.add(when: 'TARGET_RISCV64', if_true: files ('common-semi.c'))
diff --git a/linux-user/meson.build b/linux-user/meson.build
index 2fdd12cee5..68fce095fb 100644
--- a/linux-user/meson.build
+++ b/linux-user/meson.build
@@ -20,6 +20,9 @@ linux_user_ss.add(when: 'TARGET_I386', if_true: files('vm86.c'))
 linux_user_ss.add(when: 'TARGET_AARCH64', if_true: files('semihost.c'))
 linux_user_ss.add(when: 'TARGET_ARM', if_true: files('semihost.c'))
 
+linux_user_ss.add(when: 'TARGET_RISCV64', if_true: files('semihost.c'))
+linux_user_ss.add(when: 'TARGET_RISCV32', if_true: files('semihost.c'))
+
 syscall_nr_generators = {}
 
 subdir('alpha')
diff --git a/linux-user/qemu.h b/linux-user/qemu.h
index 941ca99722..faeaab9614 100644
--- a/linux-user/qemu.h
+++ b/linux-user/qemu.h
@@ -105,6 +105,8 @@ typedef struct TaskState {
     /* FPA state */
     FPA11 fpa;
 # endif
+#endif
+#if defined(TARGET_ARM) || defined(TARGET_RISCV)
     int swi_errno;
 #endif
 #if defined(TARGET_I386) && !defined(TARGET_X86_64)
@@ -118,7 +120,7 @@ typedef struct TaskState {
 #ifdef TARGET_M68K
     abi_ulong tp_value;
 #endif
-#if defined(TARGET_ARM) || defined(TARGET_M68K)
+#if defined(TARGET_ARM) || defined(TARGET_M68K) || defined(TARGET_RISCV)
     /* Extra fields for semihosted binaries.  */
     abi_ulong heap_base;
     abi_ulong heap_limit;
diff --git a/linux-user/semihost.c b/linux-user/semihost.c
index a1f0f6050e..c0015ee7f6 100644
--- a/linux-user/semihost.c
+++ b/linux-user/semihost.c
@@ -1,11 +1,11 @@
 /*
- * ARM Semihosting Console Support
+ * ARM Compatible Semihosting Console Support.
  *
  * Copyright (c) 2019 Linaro Ltd
  *
- * Currently ARM is unique in having support for semihosting support
- * in linux-user. So for now we implement the common console API but
- * just for arm linux-user.
+ * Currently ARM and RISC-V are unique in having support for
+ * semihosting support in linux-user. So for now we implement the
+ * common console API but just for arm and risc-v linux-user.
  *
  * SPDX-License-Identifier: GPL-2.0-or-later
  */
diff --git a/qemu-options.hx b/qemu-options.hx
index 2c83390504..9a606946c4 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -4184,10 +4184,10 @@ ERST
 DEF("semihosting", 0, QEMU_OPTION_semihosting,
     "-semihosting    semihosting mode\n",
     QEMU_ARCH_ARM | QEMU_ARCH_M68K | QEMU_ARCH_XTENSA | QEMU_ARCH_LM32 |
-    QEMU_ARCH_MIPS | QEMU_ARCH_NIOS2)
+    QEMU_ARCH_MIPS | QEMU_ARCH_NIOS2 | QEMU_ARCH_RISCV)
 SRST
 ``-semihosting``
-    Enable semihosting mode (ARM, M68K, Xtensa, MIPS, Nios II only).
+    Enable semihosting mode (ARM, M68K, Xtensa, MIPS, Nios II, RISC-V only).
 
     Note that this allows guest direct access to the host filesystem, so
     should only be used with a trusted guest OS.
@@ -4199,10 +4199,10 @@ DEF("semihosting-config", HAS_ARG, QEMU_OPTION_semihosting_config,
     "-semihosting-config [enable=on|off][,target=native|gdb|auto][,chardev=id][,arg=str[,...]]\n" \
     "                semihosting configuration\n",
 QEMU_ARCH_ARM | QEMU_ARCH_M68K | QEMU_ARCH_XTENSA | QEMU_ARCH_LM32 |
-QEMU_ARCH_MIPS | QEMU_ARCH_NIOS2)
+QEMU_ARCH_MIPS | QEMU_ARCH_NIOS2 | QEMU_ARCH_RISCV)
 SRST
 ``-semihosting-config [enable=on|off][,target=native|gdb|auto][,chardev=id][,arg=str[,...]]``
-    Enable and configure semihosting (ARM, M68K, Xtensa, MIPS, Nios II
+    Enable and configure semihosting (ARM, M68K, Xtensa, MIPS, Nios II, RISC-V
     only).
 
     Note that this allows guest direct access to the host filesystem, so
@@ -4217,6 +4217,8 @@ SRST
     open/read/write/seek/select. Tensilica baremetal libc for ISS and
     linux platform "sim" use this interface.
 
+    On RISC-V this implements the standard semihosting API, version 0.2.
+
     ``target=native|gdb|auto``
         Defines where the semihosting calls will be addressed, to QEMU
         (``native``) or to GDB (``gdb``). The default is ``auto``, which
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index bd36062877..26a60b9e27 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -556,6 +556,7 @@
 #define RISCV_EXCP_INST_PAGE_FAULT               0xc /* since: priv-1.10.0 */
 #define RISCV_EXCP_LOAD_PAGE_FAULT               0xd /* since: priv-1.10.0 */
 #define RISCV_EXCP_STORE_PAGE_FAULT              0xf /* since: priv-1.10.0 */
+#define RISCV_EXCP_SEMIHOST                      0x10
 #define RISCV_EXCP_INST_GUEST_PAGE_FAULT         0x14
 #define RISCV_EXCP_LOAD_GUEST_ACCESS_FAULT       0x15
 #define RISCV_EXCP_VIRT_INSTRUCTION_FAULT        0x16
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 4652082df1..d71611ec02 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -24,6 +24,7 @@
 #include "exec/exec-all.h"
 #include "tcg/tcg-op.h"
 #include "trace.h"
+#include "hw/semihosting/common-semi.h"
 
 int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch)
 {
@@ -875,6 +876,15 @@ void riscv_cpu_do_interrupt(CPUState *cs)
     target_ulong htval = 0;
     target_ulong mtval2 = 0;
 
+    if  (cause == RISCV_EXCP_SEMIHOST) {
+        if (env->priv >= PRV_S) {
+            env->gpr[xA0] = do_common_semihosting(cs);
+            env->pc += 4;
+            return;
+        }
+        cause = RISCV_EXCP_BREAKPOINT;
+    }
+
     if (!async) {
         /* set tval to badaddr for traps with address information */
         switch (cause) {
diff --git a/target/riscv/insn_trans/trans_privileged.c.inc b/target/riscv/insn_trans/trans_privileged.c.inc
index 2a61a853bf..32312be202 100644
--- a/target/riscv/insn_trans/trans_privileged.c.inc
+++ b/target/riscv/insn_trans/trans_privileged.c.inc
@@ -29,7 +29,42 @@ static bool trans_ecall(DisasContext *ctx, arg_ecall *a)
 
 static bool trans_ebreak(DisasContext *ctx, arg_ebreak *a)
 {
-    generate_exception(ctx, RISCV_EXCP_BREAKPOINT);
+    target_ulong    ebreak_addr = ctx->base.pc_next;
+    target_ulong    pre_addr = ebreak_addr - 4;
+    target_ulong    post_addr = ebreak_addr + 4;
+    uint32_t pre    = 0;
+    uint32_t ebreak = 0;
+    uint32_t post   = 0;
+
+    /*
+     * The RISC-V semihosting spec specifies the following
+     * three-instruction sequence to flag a semihosting call:
+     *
+     *      slli zero, zero, 0x1f       0x01f01013
+     *      ebreak                      0x00100073
+     *      srai zero, zero, 0x7        0x40705013
+     *
+     * The two shift operations on the zero register are no-ops, used
+     * here to signify a semihosting exception, rather than a breakpoint.
+     *
+     * Uncompressed instructions are required so that the sequence is easy
+     * to validate.
+     *
+     * The three instructions are required to lie in the same page so
+     * that no exception will be raised when fetching them.
+     */
+
+    if ((pre_addr & TARGET_PAGE_MASK) == (post_addr & TARGET_PAGE_MASK)) {
+        pre    = opcode_at(&ctx->base, pre_addr);
+        ebreak = opcode_at(&ctx->base, ebreak_addr);
+        post   = opcode_at(&ctx->base, post_addr);
+    }
+
+    if  (pre == 0x01f01013 && ebreak == 0x00100073 && post == 0x40705013) {
+        generate_exception(ctx, RISCV_EXCP_SEMIHOST);
+    } else {
+        generate_exception(ctx, RISCV_EXCP_BREAKPOINT);
+    }
     exit_tb(ctx); /* no chaining */
     ctx->base.is_jmp = DISAS_NORETURN;
     return true;
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 79dca2291b..ecf594babc 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -63,6 +63,7 @@ typedef struct DisasContext {
     uint16_t vlen;
     uint16_t mlen;
     bool vl_eq_vlmax;
+    CPUState *cs;
 } DisasContext;
 
 #ifdef TARGET_RISCV64
@@ -746,6 +747,15 @@ static bool gen_shift(DisasContext *ctx, arg_r *a,
     return true;
 }
 
+static uint32_t opcode_at(DisasContextBase *dcbase, target_ulong pc)
+{
+    DisasContext *ctx = container_of(dcbase, DisasContext, base);
+    CPUState *cpu = ctx->cs;
+    CPURISCVState *env = cpu->env_ptr;
+
+    return cpu_ldl_code(env, pc);
+}
+
 /* Include insn module translation function */
 #include "insn_trans/trans_rvi.c.inc"
 #include "insn_trans/trans_rvm.c.inc"
@@ -812,6 +822,7 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
     ctx->lmul = FIELD_EX32(tb_flags, TB_FLAGS, LMUL);
     ctx->mlen = 1 << (ctx->sew  + 3 - ctx->lmul);
     ctx->vl_eq_vlmax = FIELD_EX32(tb_flags, TB_FLAGS, VL_EQ_VLMAX);
+    ctx->cs = cs;
 }
 
 static void riscv_tr_tb_start(DisasContextBase *db, CPUState *cpu)
-- 
2.28.0



^ permalink raw reply related	[flat|nested] 32+ messages in thread

* Re: [PATCH 0/4] riscv: Add semihosting support [v10]
  2020-10-26 21:28 ` Keith Packard
@ 2020-10-26 21:42   ` no-reply
  -1 siblings, 0 replies; 32+ messages in thread
From: no-reply @ 2020-10-26 21:42 UTC (permalink / raw)
  To: qemu-devel
  Cc: peter.maydell, qemu-riscv, sagark, kbastian, qemu-devel, laurent,
	qemu-arm, palmer, Alistair.Francis, alex.bennee

Patchew URL: https://patchew.org/QEMU/20201026212853.92880-1-keithp@keithp.com/



Hi,

This series seems to have some coding style problems. See output below for
more information:

Type: series
Message-id: 20201026212853.92880-1-keithp@keithp.com
Subject: [PATCH 0/4] riscv: Add semihosting support [v10]

=== TEST SCRIPT BEGIN ===
#!/bin/bash
git rev-parse base > /dev/null || exit 0
git config --local diff.renamelimit 0
git config --local diff.renames True
git config --local diff.algorithm histogram
./scripts/checkpatch.pl --mailback base..
=== TEST SCRIPT END ===

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
From https://github.com/patchew-project/qemu
 * [new tag]         patchew/20201026212853.92880-1-keithp@keithp.com -> patchew/20201026212853.92880-1-keithp@keithp.com
Switched to a new branch 'test'
e13a1a6 riscv: Add semihosting support [v10]
3ecdba3 semihosting: Change internal common-semi interfaces to use CPUState *
ee6bc19 semihosting: Change common-semi API to be architecture-independent
5565c62 semihosting: Move ARM semihosting code to shared directories

=== OUTPUT BEGIN ===
1/4 Checking commit 5565c62ebb1a (semihosting: Move ARM semihosting code to shared directories)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#21: 
rename from target/arm/arm-semi.c

total: 0 errors, 1 warnings, 27 lines checked

Patch 1/4 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
2/4 Checking commit ee6bc19d36dd (semihosting: Change common-semi API to be architecture-independent)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#66: 
new file mode 100644

total: 0 errors, 1 warnings, 163 lines checked

Patch 2/4 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
3/4 Checking commit 3ecdba3733cf (semihosting: Change internal common-semi interfaces to use CPUState *)
ERROR: braces {} are necessary for all arms of this statement
#86: FILE: hw/semihosting/common-semi.c:142:
+    if (is_a64(env))
[...]
+    else
[...]

ERROR: braces {} are necessary for all arms of this statement
#97: FILE: hw/semihosting/common-semi.c:153:
+    if (is_a64(env))
[...]
+    else
[...]

WARNING: line over 80 characters
#205: FILE: hw/semihosting/common-semi.c:346:
+static void common_semi_flen_cb(CPUState *cs, target_ulong ret, target_ulong err)

WARNING: line over 80 characters
#213: FILE: hw/semihosting/common-semi.c:351:
+    cpu_memory_rw_debug(cs, common_semi_flen_buf(cs) + 32, (uint8_t *)&size, 4, 0);

WARNING: line over 80 characters
#230: FILE: hw/semihosting/common-semi.c:360:
+static void common_semi_open_cb(CPUState *cs, target_ulong ret, target_ulong err)

WARNING: line over 80 characters
#257: FILE: hw/semihosting/common-semi.c:373:
+static target_ulong common_semi_gdb_syscall(CPUState *cs, gdb_syscall_complete_cb cb,

WARNING: line over 80 characters
#599: FILE: hw/semihosting/common-semi.c:765:
+            ret = common_semi_gdb_syscall(cs, common_semi_open_cb, "open,%s,%x,1a4", arg0,

WARNING: line over 80 characters
#600: FILE: hw/semihosting/common-semi.c:766:
+                                          (int)arg2+1, gdb_open_modeflags[arg1]);

ERROR: spaces required around that '+' (ctx:VxV)
#600: FILE: hw/semihosting/common-semi.c:766:
+                                          (int)arg2+1, gdb_open_modeflags[arg1]);
                                                    ^

ERROR: spaces required around that '+' (ctx:VxV)
#702: FILE: hw/semihosting/common-semi.c:863:
+                                          arg0, (int)arg1+1);
                                                          ^

WARNING: line over 80 characters
#722: FILE: hw/semihosting/common-semi.c:881:
+                                           arg0, (int)arg1+1, arg2, (int)arg3+1);

ERROR: spaces required around that '+' (ctx:VxV)
#722: FILE: hw/semihosting/common-semi.c:881:
+                                           arg0, (int)arg1+1, arg2, (int)arg3+1);
                                                           ^

ERROR: spaces required around that '+' (ctx:VxV)
#722: FILE: hw/semihosting/common-semi.c:881:
+                                           arg0, (int)arg1+1, arg2, (int)arg3+1);
                                                                              ^

ERROR: spaces required around that '+' (ctx:VxV)
#750: FILE: hw/semihosting/common-semi.c:907:
+                                           arg0, (int)arg1+1);
                                                           ^

total: 7 errors, 7 warnings, 767 lines checked

Patch 3/4 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.

4/4 Checking commit e13a1a60ecc7 (riscv: Add semihosting support [v10])
=== OUTPUT END ===

Test command exited with code: 1


The full log is available at
http://patchew.org/logs/20201026212853.92880-1-keithp@keithp.com/testing.checkpatch/?type=message.
---
Email generated automatically by Patchew [https://patchew.org/].
Please send your feedback to patchew-devel@redhat.com

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH 0/4] riscv: Add semihosting support [v10]
@ 2020-10-26 21:42   ` no-reply
  0 siblings, 0 replies; 32+ messages in thread
From: no-reply @ 2020-10-26 21:42 UTC (permalink / raw)
  To: qemu-devel
  Cc: qemu-devel, alex.bennee, laurent, peter.maydell, qemu-arm,
	palmer, Alistair.Francis, sagark, kbastian, qemu-riscv

Patchew URL: https://patchew.org/QEMU/20201026212853.92880-1-keithp@keithp.com/



Hi,

This series seems to have some coding style problems. See output below for
more information:

Type: series
Message-id: 20201026212853.92880-1-keithp@keithp.com
Subject: [PATCH 0/4] riscv: Add semihosting support [v10]

=== TEST SCRIPT BEGIN ===
#!/bin/bash
git rev-parse base > /dev/null || exit 0
git config --local diff.renamelimit 0
git config --local diff.renames True
git config --local diff.algorithm histogram
./scripts/checkpatch.pl --mailback base..
=== TEST SCRIPT END ===

Updating 3c8cf5a9c21ff8782164d1def7f44bd888713384
From https://github.com/patchew-project/qemu
 * [new tag]         patchew/20201026212853.92880-1-keithp@keithp.com -> patchew/20201026212853.92880-1-keithp@keithp.com
Switched to a new branch 'test'
e13a1a6 riscv: Add semihosting support [v10]
3ecdba3 semihosting: Change internal common-semi interfaces to use CPUState *
ee6bc19 semihosting: Change common-semi API to be architecture-independent
5565c62 semihosting: Move ARM semihosting code to shared directories

=== OUTPUT BEGIN ===
1/4 Checking commit 5565c62ebb1a (semihosting: Move ARM semihosting code to shared directories)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#21: 
rename from target/arm/arm-semi.c

total: 0 errors, 1 warnings, 27 lines checked

Patch 1/4 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
2/4 Checking commit ee6bc19d36dd (semihosting: Change common-semi API to be architecture-independent)
WARNING: added, moved or deleted file(s), does MAINTAINERS need updating?
#66: 
new file mode 100644

total: 0 errors, 1 warnings, 163 lines checked

Patch 2/4 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.
3/4 Checking commit 3ecdba3733cf (semihosting: Change internal common-semi interfaces to use CPUState *)
ERROR: braces {} are necessary for all arms of this statement
#86: FILE: hw/semihosting/common-semi.c:142:
+    if (is_a64(env))
[...]
+    else
[...]

ERROR: braces {} are necessary for all arms of this statement
#97: FILE: hw/semihosting/common-semi.c:153:
+    if (is_a64(env))
[...]
+    else
[...]

WARNING: line over 80 characters
#205: FILE: hw/semihosting/common-semi.c:346:
+static void common_semi_flen_cb(CPUState *cs, target_ulong ret, target_ulong err)

WARNING: line over 80 characters
#213: FILE: hw/semihosting/common-semi.c:351:
+    cpu_memory_rw_debug(cs, common_semi_flen_buf(cs) + 32, (uint8_t *)&size, 4, 0);

WARNING: line over 80 characters
#230: FILE: hw/semihosting/common-semi.c:360:
+static void common_semi_open_cb(CPUState *cs, target_ulong ret, target_ulong err)

WARNING: line over 80 characters
#257: FILE: hw/semihosting/common-semi.c:373:
+static target_ulong common_semi_gdb_syscall(CPUState *cs, gdb_syscall_complete_cb cb,

WARNING: line over 80 characters
#599: FILE: hw/semihosting/common-semi.c:765:
+            ret = common_semi_gdb_syscall(cs, common_semi_open_cb, "open,%s,%x,1a4", arg0,

WARNING: line over 80 characters
#600: FILE: hw/semihosting/common-semi.c:766:
+                                          (int)arg2+1, gdb_open_modeflags[arg1]);

ERROR: spaces required around that '+' (ctx:VxV)
#600: FILE: hw/semihosting/common-semi.c:766:
+                                          (int)arg2+1, gdb_open_modeflags[arg1]);
                                                    ^

ERROR: spaces required around that '+' (ctx:VxV)
#702: FILE: hw/semihosting/common-semi.c:863:
+                                          arg0, (int)arg1+1);
                                                          ^

WARNING: line over 80 characters
#722: FILE: hw/semihosting/common-semi.c:881:
+                                           arg0, (int)arg1+1, arg2, (int)arg3+1);

ERROR: spaces required around that '+' (ctx:VxV)
#722: FILE: hw/semihosting/common-semi.c:881:
+                                           arg0, (int)arg1+1, arg2, (int)arg3+1);
                                                           ^

ERROR: spaces required around that '+' (ctx:VxV)
#722: FILE: hw/semihosting/common-semi.c:881:
+                                           arg0, (int)arg1+1, arg2, (int)arg3+1);
                                                                              ^

ERROR: spaces required around that '+' (ctx:VxV)
#750: FILE: hw/semihosting/common-semi.c:907:
+                                           arg0, (int)arg1+1);
                                                           ^

total: 7 errors, 7 warnings, 767 lines checked

Patch 3/4 has style problems, please review.  If any of these errors
are false positives report them to the maintainer, see
CHECKPATCH in MAINTAINERS.

4/4 Checking commit e13a1a60ecc7 (riscv: Add semihosting support [v10])
=== OUTPUT END ===

Test command exited with code: 1


The full log is available at
http://patchew.org/logs/20201026212853.92880-1-keithp@keithp.com/testing.checkpatch/?type=message.
---
Email generated automatically by Patchew [https://patchew.org/].
Please send your feedback to patchew-devel@redhat.com

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH 1/4] semihosting: Move ARM semihosting code to shared directories
  2020-10-26 21:28   ` Keith Packard
@ 2020-10-27 20:32     ` Alistair Francis
  -1 siblings, 0 replies; 32+ messages in thread
From: Alistair Francis @ 2020-10-27 20:32 UTC (permalink / raw)
  To: Keith Packard
  Cc: Peter Maydell, open list:RISC-V, Sagar Karandikar,
	Bastian Koppelmann, qemu-devel@nongnu.org Developers,
	Laurent Vivier, qemu-arm, Palmer Dabbelt, Alistair Francis,
	Alex Bennée

On Mon, Oct 26, 2020 at 2:34 PM Keith Packard via <qemu-devel@nongnu.org> wrote:
>
> This commit renames two files which provide ARM semihosting support so
> that they can be shared by other architectures:
>
>  1. target/arm/arm-semi.c     -> hw/semihosting/common-semi.c
>  2. linux-user/arm/semihost.c -> linux-user/semihost.c
>
> The build system was modified to reflect this change, but the contents
> of the two files are unchanged.
>
> Signed-off-by: Keith Packard <keithp@keithp.com>

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  target/arm/arm-semi.c => hw/semihosting/common-semi.c | 0
>  hw/semihosting/meson.build                            | 2 ++
>  linux-user/arm/meson.build                            | 3 ---
>  linux-user/meson.build                                | 2 ++
>  linux-user/{arm => }/semihost.c                       | 0
>  target/arm/meson.build                                | 2 --
>  6 files changed, 4 insertions(+), 5 deletions(-)
>  rename target/arm/arm-semi.c => hw/semihosting/common-semi.c (100%)
>  rename linux-user/{arm => }/semihost.c (100%)
>
> diff --git a/target/arm/arm-semi.c b/hw/semihosting/common-semi.c
> similarity index 100%
> rename from target/arm/arm-semi.c
> rename to hw/semihosting/common-semi.c
> diff --git a/hw/semihosting/meson.build b/hw/semihosting/meson.build
> index f40ac574c4..fbd2841e59 100644
> --- a/hw/semihosting/meson.build
> +++ b/hw/semihosting/meson.build
> @@ -2,3 +2,5 @@ specific_ss.add(when: 'CONFIG_SEMIHOSTING', if_true: files(
>    'config.c',
>    'console.c',
>  ))
> +
> +specific_ss.add(when: 'CONFIG_TCG', if_true: files ('common-semi.c'))
> diff --git a/linux-user/arm/meson.build b/linux-user/arm/meson.build
> index 432984b58e..5a93c925cf 100644
> --- a/linux-user/arm/meson.build
> +++ b/linux-user/arm/meson.build
> @@ -1,6 +1,3 @@
> -linux_user_ss.add(when: 'TARGET_AARCH64', if_true: files('semihost.c'))
> -linux_user_ss.add(when: 'TARGET_ARM', if_true: files('semihost.c'))
> -
>  subdir('nwfpe')
>
>  syscall_nr_generators += {
> diff --git a/linux-user/meson.build b/linux-user/meson.build
> index 2b94e4ba24..2fdd12cee5 100644
> --- a/linux-user/meson.build
> +++ b/linux-user/meson.build
> @@ -17,6 +17,8 @@ linux_user_ss.add(rt)
>  linux_user_ss.add(when: 'TARGET_HAS_BFLT', if_true: files('flatload.c'))
>  linux_user_ss.add(when: 'TARGET_I386', if_true: files('vm86.c'))
>
> +linux_user_ss.add(when: 'TARGET_AARCH64', if_true: files('semihost.c'))
> +linux_user_ss.add(when: 'TARGET_ARM', if_true: files('semihost.c'))
>
>  syscall_nr_generators = {}
>
> diff --git a/linux-user/arm/semihost.c b/linux-user/semihost.c
> similarity index 100%
> rename from linux-user/arm/semihost.c
> rename to linux-user/semihost.c
> diff --git a/target/arm/meson.build b/target/arm/meson.build
> index f5de2a77b8..15b936c101 100644
> --- a/target/arm/meson.build
> +++ b/target/arm/meson.build
> @@ -32,8 +32,6 @@ arm_ss.add(files(
>  ))
>  arm_ss.add(zlib)
>
> -arm_ss.add(when: 'CONFIG_TCG', if_true: files('arm-semi.c'))
> -
>  arm_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c', 'kvm64.c'), if_false: files('kvm-stub.c'))
>
>  arm_ss.add(when: 'TARGET_AARCH64', if_true: files(
> --
> 2.28.0
>
>


^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH 1/4] semihosting: Move ARM semihosting code to shared directories
@ 2020-10-27 20:32     ` Alistair Francis
  0 siblings, 0 replies; 32+ messages in thread
From: Alistair Francis @ 2020-10-27 20:32 UTC (permalink / raw)
  To: Keith Packard
  Cc: qemu-devel@nongnu.org Developers, Alex Bennée,
	Laurent Vivier, Peter Maydell, qemu-arm, Palmer Dabbelt,
	Alistair Francis, Sagar Karandikar, Bastian Koppelmann,
	open list:RISC-V

On Mon, Oct 26, 2020 at 2:34 PM Keith Packard via <qemu-devel@nongnu.org> wrote:
>
> This commit renames two files which provide ARM semihosting support so
> that they can be shared by other architectures:
>
>  1. target/arm/arm-semi.c     -> hw/semihosting/common-semi.c
>  2. linux-user/arm/semihost.c -> linux-user/semihost.c
>
> The build system was modified to reflect this change, but the contents
> of the two files are unchanged.
>
> Signed-off-by: Keith Packard <keithp@keithp.com>

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  target/arm/arm-semi.c => hw/semihosting/common-semi.c | 0
>  hw/semihosting/meson.build                            | 2 ++
>  linux-user/arm/meson.build                            | 3 ---
>  linux-user/meson.build                                | 2 ++
>  linux-user/{arm => }/semihost.c                       | 0
>  target/arm/meson.build                                | 2 --
>  6 files changed, 4 insertions(+), 5 deletions(-)
>  rename target/arm/arm-semi.c => hw/semihosting/common-semi.c (100%)
>  rename linux-user/{arm => }/semihost.c (100%)
>
> diff --git a/target/arm/arm-semi.c b/hw/semihosting/common-semi.c
> similarity index 100%
> rename from target/arm/arm-semi.c
> rename to hw/semihosting/common-semi.c
> diff --git a/hw/semihosting/meson.build b/hw/semihosting/meson.build
> index f40ac574c4..fbd2841e59 100644
> --- a/hw/semihosting/meson.build
> +++ b/hw/semihosting/meson.build
> @@ -2,3 +2,5 @@ specific_ss.add(when: 'CONFIG_SEMIHOSTING', if_true: files(
>    'config.c',
>    'console.c',
>  ))
> +
> +specific_ss.add(when: 'CONFIG_TCG', if_true: files ('common-semi.c'))
> diff --git a/linux-user/arm/meson.build b/linux-user/arm/meson.build
> index 432984b58e..5a93c925cf 100644
> --- a/linux-user/arm/meson.build
> +++ b/linux-user/arm/meson.build
> @@ -1,6 +1,3 @@
> -linux_user_ss.add(when: 'TARGET_AARCH64', if_true: files('semihost.c'))
> -linux_user_ss.add(when: 'TARGET_ARM', if_true: files('semihost.c'))
> -
>  subdir('nwfpe')
>
>  syscall_nr_generators += {
> diff --git a/linux-user/meson.build b/linux-user/meson.build
> index 2b94e4ba24..2fdd12cee5 100644
> --- a/linux-user/meson.build
> +++ b/linux-user/meson.build
> @@ -17,6 +17,8 @@ linux_user_ss.add(rt)
>  linux_user_ss.add(when: 'TARGET_HAS_BFLT', if_true: files('flatload.c'))
>  linux_user_ss.add(when: 'TARGET_I386', if_true: files('vm86.c'))
>
> +linux_user_ss.add(when: 'TARGET_AARCH64', if_true: files('semihost.c'))
> +linux_user_ss.add(when: 'TARGET_ARM', if_true: files('semihost.c'))
>
>  syscall_nr_generators = {}
>
> diff --git a/linux-user/arm/semihost.c b/linux-user/semihost.c
> similarity index 100%
> rename from linux-user/arm/semihost.c
> rename to linux-user/semihost.c
> diff --git a/target/arm/meson.build b/target/arm/meson.build
> index f5de2a77b8..15b936c101 100644
> --- a/target/arm/meson.build
> +++ b/target/arm/meson.build
> @@ -32,8 +32,6 @@ arm_ss.add(files(
>  ))
>  arm_ss.add(zlib)
>
> -arm_ss.add(when: 'CONFIG_TCG', if_true: files('arm-semi.c'))
> -
>  arm_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c', 'kvm64.c'), if_false: files('kvm-stub.c'))
>
>  arm_ss.add(when: 'TARGET_AARCH64', if_true: files(
> --
> 2.28.0
>
>


^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH 1/4] semihosting: Move ARM semihosting code to shared directories
  2020-10-26 21:28   ` Keith Packard
@ 2020-10-27 21:20     ` Peter Maydell
  -1 siblings, 0 replies; 32+ messages in thread
From: Peter Maydell @ 2020-10-27 21:20 UTC (permalink / raw)
  To: Keith Packard
  Cc: open list:RISC-V, Sagar Karandikar, Bastian Koppelmann,
	QEMU Developers, Laurent Vivier, qemu-arm, Palmer Dabbelt,
	Alistair Francis, Alex Bennée

On Mon, 26 Oct 2020 at 21:29, Keith Packard <keithp@keithp.com> wrote:
>
> This commit renames two files which provide ARM semihosting support so
> that they can be shared by other architectures:
>
>  1. target/arm/arm-semi.c     -> hw/semihosting/common-semi.c
>  2. linux-user/arm/semihost.c -> linux-user/semihost.c
>
> The build system was modified to reflect this change, but the contents
> of the two files are unchanged.
>
> Signed-off-by: Keith Packard <keithp@keithp.com>
> ---
> diff --git a/target/arm/arm-semi.c b/hw/semihosting/common-semi.c
> similarity index 100%
> rename from target/arm/arm-semi.c
> rename to hw/semihosting/common-semi.c
> diff --git a/hw/semihosting/meson.build b/hw/semihosting/meson.build
> index f40ac574c4..fbd2841e59 100644
> --- a/hw/semihosting/meson.build
> +++ b/hw/semihosting/meson.build
> @@ -2,3 +2,5 @@ specific_ss.add(when: 'CONFIG_SEMIHOSTING', if_true: files(
>    'config.c',
>    'console.c',
>  ))
> +
> +specific_ss.add(when: 'CONFIG_TCG', if_true: files ('common-semi.c'))

I think this adds this file to the compilation for all TCG targets;
you only want it for targets which have Arm-semihosting-ABI compatible
semihosting. (Various other targets either don't have semihosting
or have their own ABI.)

thanks
-- PMM


^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH 1/4] semihosting: Move ARM semihosting code to shared directories
@ 2020-10-27 21:20     ` Peter Maydell
  0 siblings, 0 replies; 32+ messages in thread
From: Peter Maydell @ 2020-10-27 21:20 UTC (permalink / raw)
  To: Keith Packard
  Cc: QEMU Developers, Alex Bennée, Laurent Vivier, qemu-arm,
	Palmer Dabbelt, Alistair Francis, Sagar Karandikar,
	Bastian Koppelmann, open list:RISC-V

On Mon, 26 Oct 2020 at 21:29, Keith Packard <keithp@keithp.com> wrote:
>
> This commit renames two files which provide ARM semihosting support so
> that they can be shared by other architectures:
>
>  1. target/arm/arm-semi.c     -> hw/semihosting/common-semi.c
>  2. linux-user/arm/semihost.c -> linux-user/semihost.c
>
> The build system was modified to reflect this change, but the contents
> of the two files are unchanged.
>
> Signed-off-by: Keith Packard <keithp@keithp.com>
> ---
> diff --git a/target/arm/arm-semi.c b/hw/semihosting/common-semi.c
> similarity index 100%
> rename from target/arm/arm-semi.c
> rename to hw/semihosting/common-semi.c
> diff --git a/hw/semihosting/meson.build b/hw/semihosting/meson.build
> index f40ac574c4..fbd2841e59 100644
> --- a/hw/semihosting/meson.build
> +++ b/hw/semihosting/meson.build
> @@ -2,3 +2,5 @@ specific_ss.add(when: 'CONFIG_SEMIHOSTING', if_true: files(
>    'config.c',
>    'console.c',
>  ))
> +
> +specific_ss.add(when: 'CONFIG_TCG', if_true: files ('common-semi.c'))

I think this adds this file to the compilation for all TCG targets;
you only want it for targets which have Arm-semihosting-ABI compatible
semihosting. (Various other targets either don't have semihosting
or have their own ABI.)

thanks
-- PMM


^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH 1/4] semihosting: Move ARM semihosting code to shared directories
  2020-10-27 21:20     ` Peter Maydell
@ 2020-10-27 21:56       ` Keith Packard
  -1 siblings, 0 replies; 32+ messages in thread
From: Keith Packard via @ 2020-10-27 21:56 UTC (permalink / raw)
  To: Peter Maydell
  Cc: QEMU Developers, Alex Bennée, Laurent Vivier, qemu-arm,
	Palmer Dabbelt, Alistair Francis, Sagar Karandikar,
	Bastian Koppelmann, open list:RISC-V

[-- Attachment #1: Type: text/plain, Size: 702 bytes --]

Peter Maydell <peter.maydell@linaro.org> writes:

>> +specific_ss.add(when: 'CONFIG_TCG', if_true: files ('common-semi.c'))
>
> I think this adds this file to the compilation for all TCG targets;
> you only want it for targets which have Arm-semihosting-ABI compatible
> semihosting. (Various other targets either don't have semihosting
> or have their own ABI.)

Right. These should have been target-specific source sets so that the
file was only added to those targets:

        arm_ss.add(when: 'CONFIG_TCG', if_true: files ('common-semi.c'))
        riscv_ss.add(files('common-semi.c'))

This appears to work in my testing (building arm, risc-v and x86_64
configs).

-- 
-keith

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 832 bytes --]

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH 1/4] semihosting: Move ARM semihosting code to shared directories
@ 2020-10-27 21:56       ` Keith Packard
  0 siblings, 0 replies; 32+ messages in thread
From: Keith Packard @ 2020-10-27 21:56 UTC (permalink / raw)
  To: Peter Maydell
  Cc: QEMU Developers, Alex Bennée, Laurent Vivier, qemu-arm,
	Palmer Dabbelt, Alistair Francis, Sagar Karandikar,
	Bastian Koppelmann, open list:RISC-V

[-- Attachment #1: Type: text/plain, Size: 702 bytes --]

Peter Maydell <peter.maydell@linaro.org> writes:

>> +specific_ss.add(when: 'CONFIG_TCG', if_true: files ('common-semi.c'))
>
> I think this adds this file to the compilation for all TCG targets;
> you only want it for targets which have Arm-semihosting-ABI compatible
> semihosting. (Various other targets either don't have semihosting
> or have their own ABI.)

Right. These should have been target-specific source sets so that the
file was only added to those targets:

        arm_ss.add(when: 'CONFIG_TCG', if_true: files ('common-semi.c'))
        riscv_ss.add(files('common-semi.c'))

This appears to work in my testing (building arm, risc-v and x86_64
configs).

-- 
-keith

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 832 bytes --]

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH 1/4] semihosting: Move ARM semihosting code to shared directories
  2020-10-27 21:56       ` Keith Packard
@ 2020-10-27 23:38         ` Peter Maydell
  -1 siblings, 0 replies; 32+ messages in thread
From: Peter Maydell @ 2020-10-27 23:38 UTC (permalink / raw)
  To: Keith Packard
  Cc: open list:RISC-V, Sagar Karandikar, Bastian Koppelmann,
	QEMU Developers, Laurent Vivier, qemu-arm, Palmer Dabbelt,
	Alistair Francis, Alex Bennée

On Tue, 27 Oct 2020 at 21:56, Keith Packard <keithp@keithp.com> wrote:
>
> Peter Maydell <peter.maydell@linaro.org> writes:
>
> >> +specific_ss.add(when: 'CONFIG_TCG', if_true: files ('common-semi.c'))
> >
> > I think this adds this file to the compilation for all TCG targets;
> > you only want it for targets which have Arm-semihosting-ABI compatible
> > semihosting. (Various other targets either don't have semihosting
> > or have their own ABI.)
>
> Right. These should have been target-specific source sets so that the
> file was only added to those targets:
>
>         arm_ss.add(when: 'CONFIG_TCG', if_true: files ('common-semi.c'))
>         riscv_ss.add(files('common-semi.c'))
>
> This appears to work in my testing (building arm, risc-v and x86_64
> configs).

I'm not a kconfig expert but it might be preferable to have
a new CONFIG_ for arm-semihosting-ABI which the relevant
targets enable. Somebody else may be able to advise.

thanks
-- PMM


^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH 1/4] semihosting: Move ARM semihosting code to shared directories
@ 2020-10-27 23:38         ` Peter Maydell
  0 siblings, 0 replies; 32+ messages in thread
From: Peter Maydell @ 2020-10-27 23:38 UTC (permalink / raw)
  To: Keith Packard
  Cc: QEMU Developers, Alex Bennée, Laurent Vivier, qemu-arm,
	Palmer Dabbelt, Alistair Francis, Sagar Karandikar,
	Bastian Koppelmann, open list:RISC-V

On Tue, 27 Oct 2020 at 21:56, Keith Packard <keithp@keithp.com> wrote:
>
> Peter Maydell <peter.maydell@linaro.org> writes:
>
> >> +specific_ss.add(when: 'CONFIG_TCG', if_true: files ('common-semi.c'))
> >
> > I think this adds this file to the compilation for all TCG targets;
> > you only want it for targets which have Arm-semihosting-ABI compatible
> > semihosting. (Various other targets either don't have semihosting
> > or have their own ABI.)
>
> Right. These should have been target-specific source sets so that the
> file was only added to those targets:
>
>         arm_ss.add(when: 'CONFIG_TCG', if_true: files ('common-semi.c'))
>         riscv_ss.add(files('common-semi.c'))
>
> This appears to work in my testing (building arm, risc-v and x86_64
> configs).

I'm not a kconfig expert but it might be preferable to have
a new CONFIG_ for arm-semihosting-ABI which the relevant
targets enable. Somebody else may be able to advise.

thanks
-- PMM


^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH 1/4] semihosting: Move ARM semihosting code to shared directories
  2020-10-27 23:38         ` Peter Maydell
@ 2020-10-28  1:33           ` Keith Packard
  -1 siblings, 0 replies; 32+ messages in thread
From: Keith Packard via @ 2020-10-28  1:33 UTC (permalink / raw)
  To: Peter Maydell
  Cc: QEMU Developers, Alex Bennée, Laurent Vivier, qemu-arm,
	Palmer Dabbelt, Alistair Francis, Sagar Karandikar,
	Bastian Koppelmann, open list:RISC-V

[-- Attachment #1: Type: text/plain, Size: 1597 bytes --]

Peter Maydell <peter.maydell@linaro.org> writes:

>>         arm_ss.add(when: 'CONFIG_TCG', if_true: files ('common-semi.c'))
>>         riscv_ss.add(files('common-semi.c'))
>>
>> This appears to work in my testing (building arm, risc-v and x86_64
>> configs).
>
> I'm not a kconfig expert but it might be preferable to have
> a new CONFIG_ for arm-semihosting-ABI which the relevant
> targets enable. Somebody else may be able to advise.

The change above makes this do exactly what the old code did -- add this
file to the arm_ss sourceset whenever CONFIG_TCG is true. arm_ss is
only used to build ARM targets, so this file gets added only for those
targets. Here's what the patch to target/arm/meson.build and
hw/semihosting/meson.build looks like now.

diff --git a/target/arm/meson.build b/target/arm/meson.build
index f5de2a77b8..15b936c101 100644
--- a/target/arm/meson.build
+++ b/target/arm/meson.build
@@ -32,8 +32,6 @@ arm_ss.add(files(
 ))
 arm_ss.add(zlib)
 
-arm_ss.add(when: 'CONFIG_TCG', if_true: files('arm-semi.c'))
-
 arm_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c', 'kvm64.c'), if_false: files('kvm-stub.c'))
 
 arm_ss.add(when: 'TARGET_AARCH64', if_true: files(

diff --git a/hw/semihosting/meson.build b/hw/semihosting/meson.build
index f40ac574c4..26538e81e7 100644
--- a/hw/semihosting/meson.build
+++ b/hw/semihosting/meson.build
@@ -2,3 +2,5 @@ specific_ss.add(when: 'CONFIG_SEMIHOSTING', if_true: files(
   'config.c',
   'console.c',
 ))
+
+arm_ss.add(when: 'CONFIG_TCG', if_true: files ('common-semi.c'))

-- 
-keith

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 832 bytes --]

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* Re: [PATCH 1/4] semihosting: Move ARM semihosting code to shared directories
@ 2020-10-28  1:33           ` Keith Packard
  0 siblings, 0 replies; 32+ messages in thread
From: Keith Packard @ 2020-10-28  1:33 UTC (permalink / raw)
  To: Peter Maydell
  Cc: QEMU Developers, Alex Bennée, Laurent Vivier, qemu-arm,
	Palmer Dabbelt, Alistair Francis, Sagar Karandikar,
	Bastian Koppelmann, open list:RISC-V

[-- Attachment #1: Type: text/plain, Size: 1597 bytes --]

Peter Maydell <peter.maydell@linaro.org> writes:

>>         arm_ss.add(when: 'CONFIG_TCG', if_true: files ('common-semi.c'))
>>         riscv_ss.add(files('common-semi.c'))
>>
>> This appears to work in my testing (building arm, risc-v and x86_64
>> configs).
>
> I'm not a kconfig expert but it might be preferable to have
> a new CONFIG_ for arm-semihosting-ABI which the relevant
> targets enable. Somebody else may be able to advise.

The change above makes this do exactly what the old code did -- add this
file to the arm_ss sourceset whenever CONFIG_TCG is true. arm_ss is
only used to build ARM targets, so this file gets added only for those
targets. Here's what the patch to target/arm/meson.build and
hw/semihosting/meson.build looks like now.

diff --git a/target/arm/meson.build b/target/arm/meson.build
index f5de2a77b8..15b936c101 100644
--- a/target/arm/meson.build
+++ b/target/arm/meson.build
@@ -32,8 +32,6 @@ arm_ss.add(files(
 ))
 arm_ss.add(zlib)
 
-arm_ss.add(when: 'CONFIG_TCG', if_true: files('arm-semi.c'))
-
 arm_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c', 'kvm64.c'), if_false: files('kvm-stub.c'))
 
 arm_ss.add(when: 'TARGET_AARCH64', if_true: files(

diff --git a/hw/semihosting/meson.build b/hw/semihosting/meson.build
index f40ac574c4..26538e81e7 100644
--- a/hw/semihosting/meson.build
+++ b/hw/semihosting/meson.build
@@ -2,3 +2,5 @@ specific_ss.add(when: 'CONFIG_SEMIHOSTING', if_true: files(
   'config.c',
   'console.c',
 ))
+
+arm_ss.add(when: 'CONFIG_TCG', if_true: files ('common-semi.c'))

-- 
-keith

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 832 bytes --]

^ permalink raw reply related	[flat|nested] 32+ messages in thread

* Re: [PATCH 1/4] semihosting: Move ARM semihosting code to shared directories
       [not found]           ` <87lffqmwi6.fsf@linaro.org>
@ 2020-10-28 15:37               ` Keith Packard
  2020-10-28 19:14               ` Keith Packard
  1 sibling, 0 replies; 32+ messages in thread
From: Keith Packard via @ 2020-10-28 15:37 UTC (permalink / raw)
  To: Alex Bennée
  Cc: Peter Maydell, QEMU Developers, Laurent Vivier, qemu-arm,
	Palmer Dabbelt, Alistair Francis, Sagar Karandikar,
	Bastian Koppelmann, open list:RISC-V

[-- Attachment #1: Type: text/plain, Size: 581 bytes --]

Alex Bennée <alex.bennee@linaro.org> writes:

> I don't think we want arm specific adds in the common code. I think what
> Peter was suggesting is a new config symbol that only ARM and RISC
> define, e.g something like:
>
>   specific_ss.add(when: 'CONFIG_ARM_STYLE_SEMIHOSTING',
>                   if_true: files ('common-semi.c'))
>
> or some other suitably descriptive symbol. Otherwise you have to keep
> adding an foo_ss.add line for each architecture that wants it.

Sure, that will also work, just a few lines of additional config file
stuff.

-- 
-keith

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 832 bytes --]

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH 1/4] semihosting: Move ARM semihosting code to shared directories
@ 2020-10-28 15:37               ` Keith Packard
  0 siblings, 0 replies; 32+ messages in thread
From: Keith Packard @ 2020-10-28 15:37 UTC (permalink / raw)
  To: Alex Bennée
  Cc: Peter Maydell, QEMU Developers, Laurent Vivier, qemu-arm,
	Palmer Dabbelt, Alistair Francis, Sagar Karandikar,
	Bastian Koppelmann, open list:RISC-V

[-- Attachment #1: Type: text/plain, Size: 581 bytes --]

Alex Bennée <alex.bennee@linaro.org> writes:

> I don't think we want arm specific adds in the common code. I think what
> Peter was suggesting is a new config symbol that only ARM and RISC
> define, e.g something like:
>
>   specific_ss.add(when: 'CONFIG_ARM_STYLE_SEMIHOSTING',
>                   if_true: files ('common-semi.c'))
>
> or some other suitably descriptive symbol. Otherwise you have to keep
> adding an foo_ss.add line for each architecture that wants it.

Sure, that will also work, just a few lines of additional config file
stuff.

-- 
-keith

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 832 bytes --]

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH 1/4] semihosting: Move ARM semihosting code to shared directories
       [not found]           ` <87lffqmwi6.fsf@linaro.org>
@ 2020-10-28 19:14               ` Keith Packard
  2020-10-28 19:14               ` Keith Packard
  1 sibling, 0 replies; 32+ messages in thread
From: Keith Packard via @ 2020-10-28 19:14 UTC (permalink / raw)
  To: Alex Bennée
  Cc: Peter Maydell, QEMU Developers, Laurent Vivier, qemu-arm,
	Palmer Dabbelt, Alistair Francis, Sagar Karandikar,
	Bastian Koppelmann, open list:RISC-V

[-- Attachment #1: Type: text/plain, Size: 448 bytes --]

Alex Bennée <alex.bennee@linaro.org> writes:

>   specific_ss.add(when: 'CONFIG_ARM_STYLE_SEMIHOSTING',
>                   if_true: files ('common-semi.c'))

I've sent another version of the series using this plan. It does look a
bit nicer as the only changes required when adding support to another
target is to place this option in the config file.

Thanks for the suggestion, and thanks for helping review this patch!

-- 
-keith

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 832 bytes --]

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH 1/4] semihosting: Move ARM semihosting code to shared directories
@ 2020-10-28 19:14               ` Keith Packard
  0 siblings, 0 replies; 32+ messages in thread
From: Keith Packard @ 2020-10-28 19:14 UTC (permalink / raw)
  To: Alex Bennée
  Cc: Peter Maydell, QEMU Developers, Laurent Vivier, qemu-arm,
	Palmer Dabbelt, Alistair Francis, Sagar Karandikar,
	Bastian Koppelmann, open list:RISC-V

[-- Attachment #1: Type: text/plain, Size: 448 bytes --]

Alex Bennée <alex.bennee@linaro.org> writes:

>   specific_ss.add(when: 'CONFIG_ARM_STYLE_SEMIHOSTING',
>                   if_true: files ('common-semi.c'))

I've sent another version of the series using this plan. It does look a
bit nicer as the only changes required when adding support to another
target is to place this option in the config file.

Thanks for the suggestion, and thanks for helping review this patch!

-- 
-keith

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 832 bytes --]

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH 3/4] semihosting: Change internal common-semi interfaces to use CPUState *
  2020-11-11 22:29     ` Alistair Francis
@ 2020-11-11 22:55       ` Keith Packard
  -1 siblings, 0 replies; 32+ messages in thread
From: Keith Packard via @ 2020-11-11 22:55 UTC (permalink / raw)
  To: Alistair Francis
  Cc: qemu-devel@nongnu.org Developers, Alex Bennée,
	Laurent Vivier, Peter Maydell, qemu-arm, Palmer Dabbelt,
	Alistair Francis, Sagar Karandikar, Bastian Koppelmann,
	open list:RISC-V

[-- Attachment #1: Type: text/plain, Size: 484 bytes --]

Alistair Francis <alistair23@gmail.com> writes:

> I'm not sure common is the right name here, as it is really just ARM
> and RISC-V, but I don't have a better name to use.

We've already seen some interest for other architectures; Benjamin
Herrenschmidt was looking at using this for PPC, for instance. He got
stuck at the same point -- attempting to split out this
architecture-neutral code.

In any case, naming is hard, and if anyone has suggestions ...

-- 
-keith

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 832 bytes --]

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH 3/4] semihosting: Change internal common-semi interfaces to use CPUState *
@ 2020-11-11 22:55       ` Keith Packard
  0 siblings, 0 replies; 32+ messages in thread
From: Keith Packard @ 2020-11-11 22:55 UTC (permalink / raw)
  To: Alistair Francis
  Cc: qemu-devel@nongnu.org Developers, Alex Bennée,
	Laurent Vivier, Peter Maydell, qemu-arm, Palmer Dabbelt,
	Alistair Francis, Sagar Karandikar, Bastian Koppelmann,
	open list:RISC-V

[-- Attachment #1: Type: text/plain, Size: 484 bytes --]

Alistair Francis <alistair23@gmail.com> writes:

> I'm not sure common is the right name here, as it is really just ARM
> and RISC-V, but I don't have a better name to use.

We've already seen some interest for other architectures; Benjamin
Herrenschmidt was looking at using this for PPC, for instance. He got
stuck at the same point -- attempting to split out this
architecture-neutral code.

In any case, naming is hard, and if anyone has suggestions ...

-- 
-keith

[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 832 bytes --]

^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH 3/4] semihosting: Change internal common-semi interfaces to use CPUState *
  2020-10-28 18:57   ` Keith Packard
@ 2020-11-11 22:29     ` Alistair Francis
  -1 siblings, 0 replies; 32+ messages in thread
From: Alistair Francis @ 2020-11-11 22:29 UTC (permalink / raw)
  To: Keith Packard
  Cc: Peter Maydell, open list:RISC-V, Sagar Karandikar,
	Bastian Koppelmann, qemu-devel@nongnu.org Developers,
	Laurent Vivier, qemu-arm, Palmer Dabbelt, Alistair Francis,
	Alex Bennée

On Wed, Oct 28, 2020 at 12:00 PM Keith Packard via
<qemu-devel@nongnu.org> wrote:
>
> This makes all of the internal interfaces architecture-independent and
> renames the internal functions to use the 'common_semi' prefix instead
> of 'arm' or 'arm_semi'.
>
> To do this, some new architecture-specific internal helper functions
> were created:
>
>     static inline target_ulong
>     common_semi_arg(CPUState *cs, int argno)
>
>         Returns the argno'th semihosting argument, where argno can be
>         either 0 or 1.
>
>     static inline void
>     common_semi_set_ret(CPUState *cs, target_ulong ret)
>
>         Sets the semihosting return value.
>
>     static inline bool
>     common_semi_sys_exit_extended(CPUState *cs, int nr)
>
>         This detects whether the specified semihosting call, which
>         is either TARGET_SYS_EXIT or TARGET_SYS_EXIT_EXTENDED should
>         be executed using the TARGET_SYS_EXIT_EXTENDED semantics.
>
> In addition, several existing functions have been changed to flag
> areas of code which are architecture specific:
>
>     static target_ulong
>     common_semi_flen_buf(CPUState *cs)
>
>         Returns the current stack pointer minus 64, which is
>         where a stat structure will be placed on the stack
>
>     #define GET_ARG(n)
>
>         This fetches arguments from the semihosting command's argument
>         block. The address of this is available implicitly through the
>         local 'args' variable. This is *mostly* architecture
>         independent, but does depend on the current ABI's notion of
>         the size of a 'long' parameter, which may need run-time checks
>         (as it does on AARCH64)
>
>     #define SET_ARG(n, val)
>
>         This mirrors GET_ARG and stores data back into the argument
>         block.
>
> Signed-off-by: Keith Packard <keithp@keithp.com>

I'm not sure common is the right name here, as it is really just ARM
and RISC-V, but I don't have a better name to use.

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  hw/semihosting/common-semi.c | 326 ++++++++++++++++++-----------------
>  1 file changed, 164 insertions(+), 162 deletions(-)
>
> diff --git a/hw/semihosting/common-semi.c b/hw/semihosting/common-semi.c
> index e0c59bc599..c77fb21bec 100644
> --- a/hw/semihosting/common-semi.c
> +++ b/hw/semihosting/common-semi.c
> @@ -32,11 +32,12 @@
>  #include "cpu.h"
>  #include "hw/semihosting/semihost.h"
>  #include "hw/semihosting/console.h"
> +#include "hw/semihosting/common-semi.h"
>  #include "qemu/log.h"
>  #ifdef CONFIG_USER_ONLY
>  #include "qemu.h"
>
> -#define ARM_ANGEL_HEAP_SIZE (128 * 1024 * 1024)
> +#define COMMON_SEMI_HEAP_SIZE (128 * 1024 * 1024)
>  #else
>  #include "exec/gdbstub.h"
>  #include "qemu/cutils.h"
> @@ -132,6 +133,36 @@ typedef struct GuestFD {
>
>  static GArray *guestfd_array;
>
> +#ifdef TARGET_ARM
> +static inline target_ulong
> +common_semi_arg(CPUState *cs, int argno)
> +{
> +    ARMCPU *cpu = ARM_CPU(cs);
> +    CPUARMState *env = &cpu->env;
> +    if (is_a64(env))
> +        return env->xregs[argno];
> +    else
> +        return env->regs[argno];
> +}
> +
> +static inline void
> +common_semi_set_ret(CPUState *cs, target_ulong ret)
> +{
> +    ARMCPU *cpu = ARM_CPU(cs);
> +    CPUARMState *env = &cpu->env;
> +    if (is_a64(env))
> +        env->xregs[0] = ret;
> +    else
> +        env->regs[0] = ret;
> +}
> +
> +static inline bool
> +common_semi_sys_exit_extended(CPUState *cs, int nr)
> +{
> +    return (nr == TARGET_SYS_EXIT_EXTENDED || is_a64(cs->env_ptr));
> +}
> +#endif /* TARGET_ARM */
> +
>  /*
>   * Allocate a new guest file descriptor and return it; if we
>   * couldn't allocate a new fd then return -1.
> @@ -237,11 +268,10 @@ static target_ulong syscall_err;
>  #include "exec/softmmu-semi.h"
>  #endif
>
> -static inline uint32_t set_swi_errno(CPUARMState *env, uint32_t code)
> +static inline uint32_t set_swi_errno(CPUState *cs, uint32_t code)
>  {
>      if (code == (uint32_t)-1) {
>  #ifdef CONFIG_USER_ONLY
> -        CPUState *cs = env_cpu(env);
>          TaskState *ts = cs->opaque;
>
>          ts->swi_errno = errno;
> @@ -252,10 +282,9 @@ static inline uint32_t set_swi_errno(CPUARMState *env, uint32_t code)
>      return code;
>  }
>
> -static inline uint32_t get_swi_errno(CPUARMState *env)
> +static inline uint32_t get_swi_errno(CPUState *cs)
>  {
>  #ifdef CONFIG_USER_ONLY
> -    CPUState *cs = env_cpu(env);
>      TaskState *ts = cs->opaque;
>
>      return ts->swi_errno;
> @@ -264,24 +293,22 @@ static inline uint32_t get_swi_errno(CPUARMState *env)
>  #endif
>  }
>
> -static target_ulong arm_semi_syscall_len;
> +static target_ulong common_semi_syscall_len;
>
> -static void arm_semi_cb(CPUState *cs, target_ulong ret, target_ulong err)
> +static void common_semi_cb(CPUState *cs, target_ulong ret, target_ulong err)
>  {
> -    ARMCPU *cpu = ARM_CPU(cs);
> -    CPUARMState *env = &cpu->env;
> -    target_ulong reg0 = is_a64(env) ? env->xregs[0] : env->regs[0];
> +    target_ulong reg0 = common_semi_arg(cs, 0);
>
>      if (ret == (target_ulong)-1) {
>          errno = err;
> -        set_swi_errno(env, -1);
> +        set_swi_errno(cs, -1);
>          reg0 = ret;
>      } else {
>          /* Fixup syscalls that use nonstardard return conventions.  */
>          switch (reg0) {
>          case TARGET_SYS_WRITE:
>          case TARGET_SYS_READ:
> -            reg0 = arm_semi_syscall_len - ret;
> +            reg0 = common_semi_syscall_len - ret;
>              break;
>          case TARGET_SYS_SEEK:
>              reg0 = 0;
> @@ -291,77 +318,62 @@ static void arm_semi_cb(CPUState *cs, target_ulong ret, target_ulong err)
>              break;
>          }
>      }
> -    if (is_a64(env)) {
> -        env->xregs[0] = reg0;
> -    } else {
> -        env->regs[0] = reg0;
> -    }
> +    common_semi_set_ret(cs, reg0);
>  }
>
> -static target_ulong arm_flen_buf(ARMCPU *cpu)
> +static target_ulong common_semi_flen_buf(CPUState *cs)
>  {
> +    target_ulong sp;
> +#ifdef TARGET_ARM
>      /* 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.
>       */
> +    ARMCPU *cpu = ARM_CPU(cs);
>      CPUARMState *env = &cpu->env;
> -    target_ulong sp;
>
>      if (is_a64(env)) {
>          sp = env->xregs[31];
>      } else {
>          sp = env->regs[13];
>      }
> +#endif
>
>      return sp - 64;
>  }
>
> -static void arm_semi_flen_cb(CPUState *cs, target_ulong ret, target_ulong err)
> +static void common_semi_flen_cb(CPUState *cs, target_ulong ret, target_ulong err)
>  {
> -    ARMCPU *cpu = ARM_CPU(cs);
> -    CPUARMState *env = &cpu->env;
>      /* 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, arm_flen_buf(cpu) + 32, (uint8_t *)&size, 4, 0);
> +    cpu_memory_rw_debug(cs, common_semi_flen_buf(cs) + 32, (uint8_t *)&size, 4, 0);
>      size = be32_to_cpu(size);
> -    if (is_a64(env)) {
> -        env->xregs[0] = size;
> -    } else {
> -        env->regs[0] = size;
> -    }
> +    common_semi_set_ret(cs, size);
>      errno = err;
> -    set_swi_errno(env, -1);
> +    set_swi_errno(cs, -1);
>  }
>
> -static int arm_semi_open_guestfd;
> +static int common_semi_open_guestfd;
>
> -static void arm_semi_open_cb(CPUState *cs, target_ulong ret, target_ulong err)
> +static void common_semi_open_cb(CPUState *cs, target_ulong ret, target_ulong err)
>  {
> -    ARMCPU *cpu = ARM_CPU(cs);
> -    CPUARMState *env = &cpu->env;
>      if (ret == (target_ulong)-1) {
>          errno = err;
> -        set_swi_errno(env, -1);
> -        dealloc_guestfd(arm_semi_open_guestfd);
> -    } else {
> -        associate_guestfd(arm_semi_open_guestfd, ret);
> -        ret = arm_semi_open_guestfd;
> -    }
> -
> -    if (is_a64(env)) {
> -        env->xregs[0] = ret;
> +        set_swi_errno(cs, -1);
> +        dealloc_guestfd(common_semi_open_guestfd);
>      } else {
> -        env->regs[0] = ret;
> +        associate_guestfd(common_semi_open_guestfd, ret);
> +        ret = common_semi_open_guestfd;
>      }
> +    common_semi_set_ret(cs, ret);
>  }
>
> -static target_ulong arm_gdb_syscall(ARMCPU *cpu, gdb_syscall_complete_cb cb,
> -                                    const char *fmt, ...)
> +static target_ulong common_semi_gdb_syscall(CPUState *cs, gdb_syscall_complete_cb cb,
> +                                            const char *fmt, ...)
>  {
>      va_list va;
> -    CPUARMState *env = &cpu->env;
>
>      va_start(va, fmt);
>      gdb_do_syscallv(cb, fmt, va);
> @@ -384,7 +396,7 @@ static target_ulong arm_gdb_syscall(ARMCPU *cpu, gdb_syscall_complete_cb cb,
>       * doing something with the return value is not possible to make.
>       */
>
> -    return is_a64(env) ? env->xregs[0] : env->regs[0];
> +    return common_semi_arg(cs, 0);
>  }
>
>  /*
> @@ -393,20 +405,18 @@ static target_ulong arm_gdb_syscall(ARMCPU *cpu, gdb_syscall_complete_cb cb,
>   * do the work and return the required return value for the guest,
>   * setting the guest errno if appropriate.
>   */
> -typedef uint32_t sys_closefn(ARMCPU *cpu, GuestFD *gf);
> -typedef uint32_t sys_writefn(ARMCPU *cpu, GuestFD *gf,
> +typedef uint32_t sys_closefn(CPUState *cs, GuestFD *gf);
> +typedef uint32_t sys_writefn(CPUState *cs, GuestFD *gf,
>                               target_ulong buf, uint32_t len);
> -typedef uint32_t sys_readfn(ARMCPU *cpu, GuestFD *gf,
> +typedef uint32_t sys_readfn(CPUState *cs, GuestFD *gf,
>                              target_ulong buf, uint32_t len);
> -typedef uint32_t sys_isattyfn(ARMCPU *cpu, GuestFD *gf);
> -typedef uint32_t sys_seekfn(ARMCPU *cpu, GuestFD *gf,
> +typedef uint32_t sys_isattyfn(CPUState *cs, GuestFD *gf);
> +typedef uint32_t sys_seekfn(CPUState *cs, GuestFD *gf,
>                              target_ulong offset);
> -typedef uint32_t sys_flenfn(ARMCPU *cpu, GuestFD *gf);
> +typedef uint32_t sys_flenfn(CPUState *cs, GuestFD *gf);
>
> -static uint32_t host_closefn(ARMCPU *cpu, GuestFD *gf)
> +static uint32_t host_closefn(CPUState *cs, GuestFD *gf)
>  {
> -    CPUARMState *env = &cpu->env;
> -
>      /*
>       * Only close the underlying host fd if it's one we opened on behalf
>       * of the guest in SYS_OPEN.
> @@ -416,20 +426,21 @@ static uint32_t host_closefn(ARMCPU *cpu, GuestFD *gf)
>          gf->hostfd == STDERR_FILENO) {
>          return 0;
>      }
> -    return set_swi_errno(env, close(gf->hostfd));
> +    return set_swi_errno(cs, close(gf->hostfd));
>  }
>
> -static uint32_t host_writefn(ARMCPU *cpu, GuestFD *gf,
> +static uint32_t host_writefn(CPUState *cs, GuestFD *gf,
>                               target_ulong buf, uint32_t len)
>  {
> +    CPUArchState *env = cs->env_ptr;
>      uint32_t ret;
> -    CPUARMState *env = &cpu->env;
>      char *s = lock_user(VERIFY_READ, buf, len, 1);
> +    (void) env; /* Used in arm softmmu lock_user implicitly */
>      if (!s) {
>          /* Return bytes not written on error */
>          return len;
>      }
> -    ret = set_swi_errno(env, write(gf->hostfd, s, len));
> +    ret = set_swi_errno(cs, write(gf->hostfd, s, len));
>      unlock_user(s, buf, 0);
>      if (ret == (uint32_t)-1) {
>          ret = 0;
> @@ -438,18 +449,19 @@ static uint32_t host_writefn(ARMCPU *cpu, GuestFD *gf,
>      return len - ret;
>  }
>
> -static uint32_t host_readfn(ARMCPU *cpu, GuestFD *gf,
> +static uint32_t host_readfn(CPUState *cs, GuestFD *gf,
>                              target_ulong buf, uint32_t len)
>  {
> +    CPUArchState *env = cs->env_ptr;
>      uint32_t ret;
> -    CPUARMState *env = &cpu->env;
>      char *s = lock_user(VERIFY_WRITE, buf, len, 0);
> +    (void) env; /* Used in arm softmmu lock_user implicitly */
>      if (!s) {
>          /* return bytes not read */
>          return len;
>      }
>      do {
> -        ret = set_swi_errno(env, read(gf->hostfd, s, len));
> +        ret = set_swi_errno(cs, read(gf->hostfd, s, len));
>      } while (ret == -1 && errno == EINTR);
>      unlock_user(s, buf, len);
>      if (ret == (uint32_t)-1) {
> @@ -459,68 +471,66 @@ static uint32_t host_readfn(ARMCPU *cpu, GuestFD *gf,
>      return len - ret;
>  }
>
> -static uint32_t host_isattyfn(ARMCPU *cpu, GuestFD *gf)
> +static uint32_t host_isattyfn(CPUState *cs, GuestFD *gf)
>  {
>      return isatty(gf->hostfd);
>  }
>
> -static uint32_t host_seekfn(ARMCPU *cpu, GuestFD *gf, target_ulong offset)
> +static uint32_t host_seekfn(CPUState *cs, GuestFD *gf, target_ulong offset)
>  {
> -    CPUARMState *env = &cpu->env;
> -    uint32_t ret = set_swi_errno(env, lseek(gf->hostfd, offset, SEEK_SET));
> +    uint32_t ret = set_swi_errno(cs, lseek(gf->hostfd, offset, SEEK_SET));
>      if (ret == (uint32_t)-1) {
>          return -1;
>      }
>      return 0;
>  }
>
> -static uint32_t host_flenfn(ARMCPU *cpu, GuestFD *gf)
> +static uint32_t host_flenfn(CPUState *cs, GuestFD *gf)
>  {
> -    CPUARMState *env = &cpu->env;
>      struct stat buf;
> -    uint32_t ret = set_swi_errno(env, fstat(gf->hostfd, &buf));
> +    uint32_t ret = set_swi_errno(cs, fstat(gf->hostfd, &buf));
>      if (ret == (uint32_t)-1) {
>          return -1;
>      }
>      return buf.st_size;
>  }
>
> -static uint32_t gdb_closefn(ARMCPU *cpu, GuestFD *gf)
> +static uint32_t gdb_closefn(CPUState *cs, GuestFD *gf)
>  {
> -    return arm_gdb_syscall(cpu, arm_semi_cb, "close,%x", gf->hostfd);
> +    return common_semi_gdb_syscall(cs, common_semi_cb, "close,%x", gf->hostfd);
>  }
>
> -static uint32_t gdb_writefn(ARMCPU *cpu, GuestFD *gf,
> +static uint32_t gdb_writefn(CPUState *cs, GuestFD *gf,
>                              target_ulong buf, uint32_t len)
>  {
> -    arm_semi_syscall_len = len;
> -    return arm_gdb_syscall(cpu, arm_semi_cb, "write,%x,%x,%x",
> -                           gf->hostfd, buf, len);
> +    common_semi_syscall_len = len;
> +    return common_semi_gdb_syscall(cs, common_semi_cb, "write,%x,%x,%x",
> +                                   gf->hostfd, buf, len);
>  }
>
> -static uint32_t gdb_readfn(ARMCPU *cpu, GuestFD *gf,
> +static uint32_t gdb_readfn(CPUState *cs, GuestFD *gf,
>                             target_ulong buf, uint32_t len)
>  {
> -    arm_semi_syscall_len = len;
> -    return arm_gdb_syscall(cpu, arm_semi_cb, "read,%x,%x,%x",
> -                           gf->hostfd, buf, len);
> +    common_semi_syscall_len = len;
> +    return common_semi_gdb_syscall(cs, common_semi_cb, "read,%x,%x,%x",
> +                                   gf->hostfd, buf, len);
>  }
>
> -static uint32_t gdb_isattyfn(ARMCPU *cpu, GuestFD *gf)
> +static uint32_t gdb_isattyfn(CPUState *cs, GuestFD *gf)
>  {
> -    return arm_gdb_syscall(cpu, arm_semi_cb, "isatty,%x", gf->hostfd);
> +    return common_semi_gdb_syscall(cs, common_semi_cb, "isatty,%x", gf->hostfd);
>  }
>
> -static uint32_t gdb_seekfn(ARMCPU *cpu, GuestFD *gf, target_ulong offset)
> +static uint32_t gdb_seekfn(CPUState *cs, GuestFD *gf, target_ulong offset)
>  {
> -    return arm_gdb_syscall(cpu, arm_semi_cb, "lseek,%x,%x,0",
> -                           gf->hostfd, offset);
> +    return common_semi_gdb_syscall(cs, common_semi_cb, "lseek,%x,%x,0",
> +                                   gf->hostfd, offset);
>  }
>
> -static uint32_t gdb_flenfn(ARMCPU *cpu, GuestFD *gf)
> +static uint32_t gdb_flenfn(CPUState *cs, GuestFD *gf)
>  {
> -    return arm_gdb_syscall(cpu, arm_semi_flen_cb, "fstat,%x,%x",
> -                           gf->hostfd, arm_flen_buf(cpu));
> +    return common_semi_gdb_syscall(cs, common_semi_flen_cb, "fstat,%x,%x",
> +                                   gf->hostfd, common_semi_flen_buf(cs));
>  }
>
>  #define SHFB_MAGIC_0 0x53
> @@ -549,31 +559,29 @@ static void init_featurefile_guestfd(int guestfd)
>      gf->featurefile_offset = 0;
>  }
>
> -static uint32_t featurefile_closefn(ARMCPU *cpu, GuestFD *gf)
> +static uint32_t featurefile_closefn(CPUState *cs, GuestFD *gf)
>  {
>      /* Nothing to do */
>      return 0;
>  }
>
> -static uint32_t featurefile_writefn(ARMCPU *cpu, GuestFD *gf,
> +static uint32_t featurefile_writefn(CPUState *cs, GuestFD *gf,
>                                      target_ulong buf, uint32_t len)
>  {
>      /* This fd can never be open for writing */
> -    CPUARMState *env = &cpu->env;
>
>      errno = EBADF;
> -    return set_swi_errno(env, -1);
> +    return set_swi_errno(cs, -1);
>  }
>
> -static uint32_t featurefile_readfn(ARMCPU *cpu, GuestFD *gf,
> +static uint32_t featurefile_readfn(CPUState *cs, GuestFD *gf,
>                                     target_ulong buf, uint32_t len)
>  {
> +    CPUArchState *env = cs->env_ptr;
>      uint32_t i;
> -#ifndef CONFIG_USER_ONLY
> -    CPUARMState *env = &cpu->env;
> -#endif
>      char *s;
>
> +    (void) env; /* Used in arm softmmu lock_user implicitly */
>      s = lock_user(VERIFY_WRITE, buf, len, 0);
>      if (!s) {
>          return len;
> @@ -593,19 +601,19 @@ static uint32_t featurefile_readfn(ARMCPU *cpu, GuestFD *gf,
>      return len - i;
>  }
>
> -static uint32_t featurefile_isattyfn(ARMCPU *cpu, GuestFD *gf)
> +static uint32_t featurefile_isattyfn(CPUState *cs, GuestFD *gf)
>  {
>      return 0;
>  }
>
> -static uint32_t featurefile_seekfn(ARMCPU *cpu, GuestFD *gf,
> +static uint32_t featurefile_seekfn(CPUState *cs, GuestFD *gf,
>                                     target_ulong offset)
>  {
>      gf->featurefile_offset = offset;
>      return 0;
>  }
>
> -static uint32_t featurefile_flenfn(ARMCPU *cpu, GuestFD *gf)
> +static uint32_t featurefile_flenfn(CPUState *cs, GuestFD *gf)
>  {
>      return sizeof(featurefile_data);
>  }
> @@ -649,16 +657,17 @@ static const GuestFDFunctions guestfd_fns[] = {
>  /* Read the input value from the argument block; fail the semihosting
>   * call if the memory read fails.
>   */
> +#ifdef TARGET_ARM
>  #define GET_ARG(n) do {                                 \
>      if (is_a64(env)) {                                  \
>          if (get_user_u64(arg ## n, args + (n) * 8)) {   \
>              errno = EFAULT;                             \
> -            return set_swi_errno(env, -1);              \
> +            return set_swi_errno(cs, -1);              \
>          }                                               \
>      } else {                                            \
>          if (get_user_u32(arg ## n, args + (n) * 4)) {   \
>              errno = EFAULT;                             \
> -            return set_swi_errno(env, -1);              \
> +            return set_swi_errno(cs, -1);              \
>          }                                               \
>      }                                                   \
>  } while (0)
> @@ -667,6 +676,7 @@ static const GuestFDFunctions guestfd_fns[] = {
>      (is_a64(env) ?                                      \
>       put_user_u64(val, args + (n) * 8) :                \
>       put_user_u32(val, args + (n) * 4))
> +#endif
>
>  /*
>   * Do a semihosting call.
> @@ -679,8 +689,7 @@ static const GuestFDFunctions guestfd_fns[] = {
>   */
>  target_ulong do_common_semihosting(CPUState *cs)
>  {
> -    ARMCPU *cpu = ARM_CPU(cs);
> -    CPUARMState *env = &cpu->env;
> +    CPUArchState *env = cs->env_ptr;
>      target_ulong args;
>      target_ulong arg0, arg1, arg2, arg3;
>      char * s;
> @@ -689,14 +698,9 @@ target_ulong do_common_semihosting(CPUState *cs)
>      uint32_t len;
>      GuestFD *gf;
>
> -    if (is_a64(env)) {
> -        /* 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];
> -    }
> +    (void) env; /* Used implicitly by arm lock_user macro */
> +    nr = common_semi_arg(cs, 0) & 0xffffffffU;
> +    args = common_semi_arg(cs, 1);
>
>      switch (nr) {
>      case TARGET_SYS_OPEN:
> @@ -709,19 +713,19 @@ target_ulong do_common_semihosting(CPUState *cs)
>          s = lock_user_string(arg0);
>          if (!s) {
>              errno = EFAULT;
> -            return set_swi_errno(env, -1);
> +            return set_swi_errno(cs, -1);
>          }
>          if (arg1 >= 12) {
>              unlock_user(s, arg0, 0);
>              errno = EINVAL;
> -            return set_swi_errno(env, -1);
> +            return set_swi_errno(cs, -1);
>          }
>
>          guestfd = alloc_guestfd();
>          if (guestfd < 0) {
>              unlock_user(s, arg0, 0);
>              errno = EMFILE;
> -            return set_swi_errno(env, -1);
> +            return set_swi_errno(cs, -1);
>          }
>
>          if (strcmp(s, ":tt") == 0) {
> @@ -750,18 +754,18 @@ target_ulong do_common_semihosting(CPUState *cs)
>              if (arg1 != 0 && arg1 != 1) {
>                  dealloc_guestfd(guestfd);
>                  errno = EACCES;
> -                return set_swi_errno(env, -1);
> +                return set_swi_errno(cs, -1);
>              }
>              init_featurefile_guestfd(guestfd);
>              return guestfd;
>          }
>
>          if (use_gdb_syscalls()) {
> -            arm_semi_open_guestfd = guestfd;
> -            ret = arm_gdb_syscall(cpu, arm_semi_open_cb, "open,%s,%x,1a4", arg0,
> -                                  (int)arg2+1, gdb_open_modeflags[arg1]);
> +            common_semi_open_guestfd = guestfd;
> +            ret = common_semi_gdb_syscall(cs, common_semi_open_cb, "open,%s,%x,1a4", arg0,
> +                                          (int)arg2+1, gdb_open_modeflags[arg1]);
>          } else {
> -            ret = set_swi_errno(env, open(s, open_modeflags[arg1], 0644));
> +            ret = set_swi_errno(cs, open(s, open_modeflags[arg1], 0644));
>              if (ret == (uint32_t)-1) {
>                  dealloc_guestfd(guestfd);
>              } else {
> @@ -778,17 +782,17 @@ target_ulong do_common_semihosting(CPUState *cs)
>          gf = get_guestfd(arg0);
>          if (!gf) {
>              errno = EBADF;
> -            return set_swi_errno(env, -1);
> +            return set_swi_errno(cs, -1);
>          }
>
> -        ret = guestfd_fns[gf->type].closefn(cpu, gf);
> +        ret = guestfd_fns[gf->type].closefn(cs, gf);
>          dealloc_guestfd(arg0);
>          return ret;
>      case TARGET_SYS_WRITEC:
> -        qemu_semihosting_console_outc(env, args);
> +        qemu_semihosting_console_outc(cs->env_ptr, args);
>          return 0xdeadbeef;
>      case TARGET_SYS_WRITE0:
> -        return qemu_semihosting_console_outs(env, args);
> +        return qemu_semihosting_console_outs(cs->env_ptr, args);
>      case TARGET_SYS_WRITE:
>          GET_ARG(0);
>          GET_ARG(1);
> @@ -798,10 +802,10 @@ target_ulong do_common_semihosting(CPUState *cs)
>          gf = get_guestfd(arg0);
>          if (!gf) {
>              errno = EBADF;
> -            return set_swi_errno(env, -1);
> +            return set_swi_errno(cs, -1);
>          }
>
> -        return guestfd_fns[gf->type].writefn(cpu, gf, arg1, len);
> +        return guestfd_fns[gf->type].writefn(cs, gf, arg1, len);
>      case TARGET_SYS_READ:
>          GET_ARG(0);
>          GET_ARG(1);
> @@ -811,22 +815,22 @@ target_ulong do_common_semihosting(CPUState *cs)
>          gf = get_guestfd(arg0);
>          if (!gf) {
>              errno = EBADF;
> -            return set_swi_errno(env, -1);
> +            return set_swi_errno(cs, -1);
>          }
>
> -        return guestfd_fns[gf->type].readfn(cpu, gf, arg1, len);
> +        return guestfd_fns[gf->type].readfn(cs, gf, arg1, len);
>      case TARGET_SYS_READC:
> -        return qemu_semihosting_console_inc(env);
> +        return qemu_semihosting_console_inc(cs->env_ptr);
>      case TARGET_SYS_ISTTY:
>          GET_ARG(0);
>
>          gf = get_guestfd(arg0);
>          if (!gf) {
>              errno = EBADF;
> -            return set_swi_errno(env, -1);
> +            return set_swi_errno(cs, -1);
>          }
>
> -        return guestfd_fns[gf->type].isattyfn(cpu, gf);
> +        return guestfd_fns[gf->type].isattyfn(cs, gf);
>      case TARGET_SYS_SEEK:
>          GET_ARG(0);
>          GET_ARG(1);
> @@ -834,20 +838,20 @@ target_ulong do_common_semihosting(CPUState *cs)
>          gf = get_guestfd(arg0);
>          if (!gf) {
>              errno = EBADF;
> -            return set_swi_errno(env, -1);
> +            return set_swi_errno(cs, -1);
>          }
>
> -        return guestfd_fns[gf->type].seekfn(cpu, gf, arg1);
> +        return guestfd_fns[gf->type].seekfn(cs, gf, arg1);
>      case TARGET_SYS_FLEN:
>          GET_ARG(0);
>
>          gf = get_guestfd(arg0);
>          if (!gf) {
>              errno = EBADF;
> -            return set_swi_errno(env, -1);
> +            return set_swi_errno(cs, -1);
>          }
>
> -        return guestfd_fns[gf->type].flenfn(cpu, gf);
> +        return guestfd_fns[gf->type].flenfn(cs, gf);
>      case TARGET_SYS_TMPNAM:
>          qemu_log_mask(LOG_UNIMP, "%s: SYS_TMPNAM not implemented", __func__);
>          return -1;
> @@ -855,15 +859,15 @@ target_ulong do_common_semihosting(CPUState *cs)
>          GET_ARG(0);
>          GET_ARG(1);
>          if (use_gdb_syscalls()) {
> -            ret = arm_gdb_syscall(cpu, arm_semi_cb, "unlink,%s",
> -                                  arg0, (int)arg1+1);
> +            ret = common_semi_gdb_syscall(cs, common_semi_cb, "unlink,%s",
> +                                          arg0, (int)arg1+1);
>          } else {
>              s = lock_user_string(arg0);
>              if (!s) {
>                  errno = EFAULT;
> -                return set_swi_errno(env, -1);
> +                return set_swi_errno(cs, -1);
>              }
> -            ret =  set_swi_errno(env, remove(s));
> +            ret =  set_swi_errno(cs, remove(s));
>              unlock_user(s, arg0, 0);
>          }
>          return ret;
> @@ -873,17 +877,17 @@ target_ulong do_common_semihosting(CPUState *cs)
>          GET_ARG(2);
>          GET_ARG(3);
>          if (use_gdb_syscalls()) {
> -            return arm_gdb_syscall(cpu, arm_semi_cb, "rename,%s,%s",
> -                                   arg0, (int)arg1+1, arg2, (int)arg3+1);
> +            return common_semi_gdb_syscall(cs, common_semi_cb, "rename,%s,%s",
> +                                           arg0, (int)arg1+1, arg2, (int)arg3+1);
>          } else {
>              char *s2;
>              s = lock_user_string(arg0);
>              s2 = lock_user_string(arg2);
>              if (!s || !s2) {
>                  errno = EFAULT;
> -                ret = set_swi_errno(env, -1);
> +                ret = set_swi_errno(cs, -1);
>              } else {
> -                ret = set_swi_errno(env, rename(s, s2));
> +                ret = set_swi_errno(cs, rename(s, s2));
>              }
>              if (s2)
>                  unlock_user(s2, arg2, 0);
> @@ -894,25 +898,25 @@ target_ulong do_common_semihosting(CPUState *cs)
>      case TARGET_SYS_CLOCK:
>          return clock() / (CLOCKS_PER_SEC / 100);
>      case TARGET_SYS_TIME:
> -        return set_swi_errno(env, time(NULL));
> +        return set_swi_errno(cs, time(NULL));
>      case TARGET_SYS_SYSTEM:
>          GET_ARG(0);
>          GET_ARG(1);
>          if (use_gdb_syscalls()) {
> -            return arm_gdb_syscall(cpu, arm_semi_cb, "system,%s",
> -                                   arg0, (int)arg1+1);
> +            return common_semi_gdb_syscall(cs, common_semi_cb, "system,%s",
> +                                           arg0, (int)arg1+1);
>          } else {
>              s = lock_user_string(arg0);
>              if (!s) {
>                  errno = EFAULT;
> -                return set_swi_errno(env, -1);
> +                return set_swi_errno(cs, -1);
>              }
> -            ret = set_swi_errno(env, system(s));
> +            ret = set_swi_errno(cs, system(s));
>              unlock_user(s, arg0, 0);
>              return ret;
>          }
>      case TARGET_SYS_ERRNO:
> -        return get_swi_errno(env);
> +        return get_swi_errno(cs);
>      case TARGET_SYS_GET_CMDLINE:
>          {
>              /* Build a command-line from the original argv.
> @@ -964,21 +968,21 @@ target_ulong do_common_semihosting(CPUState *cs)
>              if (output_size > input_size) {
>                  /* Not enough space to store command-line arguments.  */
>                  errno = E2BIG;
> -                return set_swi_errno(env, -1);
> +                return set_swi_errno(cs, -1);
>              }
>
>              /* Adjust the command-line length.  */
>              if (SET_ARG(1, output_size - 1)) {
>                  /* Couldn't write back to argument block */
>                  errno = EFAULT;
> -                return set_swi_errno(env, -1);
> +                return set_swi_errno(cs, -1);
>              }
>
>              /* Lock the buffer on the ARM side.  */
>              output_buffer = lock_user(VERIFY_WRITE, arg0, output_size, 0);
>              if (!output_buffer) {
>                  errno = EFAULT;
> -                return set_swi_errno(env, -1);
> +                return set_swi_errno(cs, -1);
>              }
>
>              /* Copy the command-line arguments.  */
> @@ -994,7 +998,7 @@ target_ulong do_common_semihosting(CPUState *cs)
>              if (copy_from_user(output_buffer, ts->info->arg_start,
>                                 output_size)) {
>                  errno = EFAULT;
> -                status = set_swi_errno(env, -1);
> +                status = set_swi_errno(cs, -1);
>                  goto out;
>              }
>
> @@ -1031,7 +1035,7 @@ target_ulong do_common_semihosting(CPUState *cs)
>                  abi_ulong ret;
>
>                  ts->heap_base = do_brk(0);
> -                limit = ts->heap_base + ARM_ANGEL_HEAP_SIZE;
> +                limit = ts->heap_base + COMMON_SEMI_HEAP_SIZE;
>                  /* Try a big heap, and reduce the size if that fails.  */
>                  for (;;) {
>                      ret = do_brk(limit);
> @@ -1059,23 +1063,19 @@ target_ulong do_common_semihosting(CPUState *cs)
>              for (i = 0; i < ARRAY_SIZE(retvals); i++) {
>                  bool fail;
>
> -                if (is_a64(env)) {
> -                    fail = put_user_u64(retvals[i], arg0 + i * 8);
> -                } else {
> -                    fail = put_user_u32(retvals[i], arg0 + i * 4);
> -                }
> +                fail = SET_ARG(i, retvals[i]);
>
>                  if (fail) {
>                      /* Couldn't write back to argument block */
>                      errno = EFAULT;
> -                    return set_swi_errno(env, -1);
> +                    return set_swi_errno(cs, -1);
>                  }
>              }
>              return 0;
>          }
>      case TARGET_SYS_EXIT:
>      case TARGET_SYS_EXIT_EXTENDED:
> -        if (nr == TARGET_SYS_EXIT_EXTENDED || is_a64(env)) {
> +        if (common_semi_sys_exit_extended(cs, nr)) {
>              /*
>               * The A64 version of SYS_EXIT takes a parameter block,
>               * so the application-exit type can return a subcode which
> @@ -1100,7 +1100,7 @@ target_ulong do_common_semihosting(CPUState *cs)
>               */
>              ret = (args == ADP_Stopped_ApplicationExit) ? 0 : 1;
>          }
> -        gdb_exit(env, ret);
> +        gdb_exit(cs->env_ptr, ret);
>          exit(ret);
>      case TARGET_SYS_SYNCCACHE:
>          /*
> @@ -1108,9 +1108,11 @@ target_ulong do_common_semihosting(CPUState *cs)
>           * virtual address range. This is a nop for us since we don't
>           * implement caches. This is only present on A64.
>           */
> -        if (is_a64(env)) {
> +#ifdef TARGET_ARM
> +        if (is_a64(cs->env_ptr)) {
>              return 0;
>          }
> +#endif
>          /* fall through -- invalid for A32/T32 */
>      default:
>          fprintf(stderr, "qemu: Unsupported SemiHosting SWI 0x%02x\n", nr);
> --
> 2.28.0
>
>


^ permalink raw reply	[flat|nested] 32+ messages in thread

* Re: [PATCH 3/4] semihosting: Change internal common-semi interfaces to use CPUState *
@ 2020-11-11 22:29     ` Alistair Francis
  0 siblings, 0 replies; 32+ messages in thread
From: Alistair Francis @ 2020-11-11 22:29 UTC (permalink / raw)
  To: Keith Packard
  Cc: qemu-devel@nongnu.org Developers, Alex Bennée,
	Laurent Vivier, Peter Maydell, qemu-arm, Palmer Dabbelt,
	Alistair Francis, Sagar Karandikar, Bastian Koppelmann,
	open list:RISC-V

On Wed, Oct 28, 2020 at 12:00 PM Keith Packard via
<qemu-devel@nongnu.org> wrote:
>
> This makes all of the internal interfaces architecture-independent and
> renames the internal functions to use the 'common_semi' prefix instead
> of 'arm' or 'arm_semi'.
>
> To do this, some new architecture-specific internal helper functions
> were created:
>
>     static inline target_ulong
>     common_semi_arg(CPUState *cs, int argno)
>
>         Returns the argno'th semihosting argument, where argno can be
>         either 0 or 1.
>
>     static inline void
>     common_semi_set_ret(CPUState *cs, target_ulong ret)
>
>         Sets the semihosting return value.
>
>     static inline bool
>     common_semi_sys_exit_extended(CPUState *cs, int nr)
>
>         This detects whether the specified semihosting call, which
>         is either TARGET_SYS_EXIT or TARGET_SYS_EXIT_EXTENDED should
>         be executed using the TARGET_SYS_EXIT_EXTENDED semantics.
>
> In addition, several existing functions have been changed to flag
> areas of code which are architecture specific:
>
>     static target_ulong
>     common_semi_flen_buf(CPUState *cs)
>
>         Returns the current stack pointer minus 64, which is
>         where a stat structure will be placed on the stack
>
>     #define GET_ARG(n)
>
>         This fetches arguments from the semihosting command's argument
>         block. The address of this is available implicitly through the
>         local 'args' variable. This is *mostly* architecture
>         independent, but does depend on the current ABI's notion of
>         the size of a 'long' parameter, which may need run-time checks
>         (as it does on AARCH64)
>
>     #define SET_ARG(n, val)
>
>         This mirrors GET_ARG and stores data back into the argument
>         block.
>
> Signed-off-by: Keith Packard <keithp@keithp.com>

I'm not sure common is the right name here, as it is really just ARM
and RISC-V, but I don't have a better name to use.

Reviewed-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  hw/semihosting/common-semi.c | 326 ++++++++++++++++++-----------------
>  1 file changed, 164 insertions(+), 162 deletions(-)
>
> diff --git a/hw/semihosting/common-semi.c b/hw/semihosting/common-semi.c
> index e0c59bc599..c77fb21bec 100644
> --- a/hw/semihosting/common-semi.c
> +++ b/hw/semihosting/common-semi.c
> @@ -32,11 +32,12 @@
>  #include "cpu.h"
>  #include "hw/semihosting/semihost.h"
>  #include "hw/semihosting/console.h"
> +#include "hw/semihosting/common-semi.h"
>  #include "qemu/log.h"
>  #ifdef CONFIG_USER_ONLY
>  #include "qemu.h"
>
> -#define ARM_ANGEL_HEAP_SIZE (128 * 1024 * 1024)
> +#define COMMON_SEMI_HEAP_SIZE (128 * 1024 * 1024)
>  #else
>  #include "exec/gdbstub.h"
>  #include "qemu/cutils.h"
> @@ -132,6 +133,36 @@ typedef struct GuestFD {
>
>  static GArray *guestfd_array;
>
> +#ifdef TARGET_ARM
> +static inline target_ulong
> +common_semi_arg(CPUState *cs, int argno)
> +{
> +    ARMCPU *cpu = ARM_CPU(cs);
> +    CPUARMState *env = &cpu->env;
> +    if (is_a64(env))
> +        return env->xregs[argno];
> +    else
> +        return env->regs[argno];
> +}
> +
> +static inline void
> +common_semi_set_ret(CPUState *cs, target_ulong ret)
> +{
> +    ARMCPU *cpu = ARM_CPU(cs);
> +    CPUARMState *env = &cpu->env;
> +    if (is_a64(env))
> +        env->xregs[0] = ret;
> +    else
> +        env->regs[0] = ret;
> +}
> +
> +static inline bool
> +common_semi_sys_exit_extended(CPUState *cs, int nr)
> +{
> +    return (nr == TARGET_SYS_EXIT_EXTENDED || is_a64(cs->env_ptr));
> +}
> +#endif /* TARGET_ARM */
> +
>  /*
>   * Allocate a new guest file descriptor and return it; if we
>   * couldn't allocate a new fd then return -1.
> @@ -237,11 +268,10 @@ static target_ulong syscall_err;
>  #include "exec/softmmu-semi.h"
>  #endif
>
> -static inline uint32_t set_swi_errno(CPUARMState *env, uint32_t code)
> +static inline uint32_t set_swi_errno(CPUState *cs, uint32_t code)
>  {
>      if (code == (uint32_t)-1) {
>  #ifdef CONFIG_USER_ONLY
> -        CPUState *cs = env_cpu(env);
>          TaskState *ts = cs->opaque;
>
>          ts->swi_errno = errno;
> @@ -252,10 +282,9 @@ static inline uint32_t set_swi_errno(CPUARMState *env, uint32_t code)
>      return code;
>  }
>
> -static inline uint32_t get_swi_errno(CPUARMState *env)
> +static inline uint32_t get_swi_errno(CPUState *cs)
>  {
>  #ifdef CONFIG_USER_ONLY
> -    CPUState *cs = env_cpu(env);
>      TaskState *ts = cs->opaque;
>
>      return ts->swi_errno;
> @@ -264,24 +293,22 @@ static inline uint32_t get_swi_errno(CPUARMState *env)
>  #endif
>  }
>
> -static target_ulong arm_semi_syscall_len;
> +static target_ulong common_semi_syscall_len;
>
> -static void arm_semi_cb(CPUState *cs, target_ulong ret, target_ulong err)
> +static void common_semi_cb(CPUState *cs, target_ulong ret, target_ulong err)
>  {
> -    ARMCPU *cpu = ARM_CPU(cs);
> -    CPUARMState *env = &cpu->env;
> -    target_ulong reg0 = is_a64(env) ? env->xregs[0] : env->regs[0];
> +    target_ulong reg0 = common_semi_arg(cs, 0);
>
>      if (ret == (target_ulong)-1) {
>          errno = err;
> -        set_swi_errno(env, -1);
> +        set_swi_errno(cs, -1);
>          reg0 = ret;
>      } else {
>          /* Fixup syscalls that use nonstardard return conventions.  */
>          switch (reg0) {
>          case TARGET_SYS_WRITE:
>          case TARGET_SYS_READ:
> -            reg0 = arm_semi_syscall_len - ret;
> +            reg0 = common_semi_syscall_len - ret;
>              break;
>          case TARGET_SYS_SEEK:
>              reg0 = 0;
> @@ -291,77 +318,62 @@ static void arm_semi_cb(CPUState *cs, target_ulong ret, target_ulong err)
>              break;
>          }
>      }
> -    if (is_a64(env)) {
> -        env->xregs[0] = reg0;
> -    } else {
> -        env->regs[0] = reg0;
> -    }
> +    common_semi_set_ret(cs, reg0);
>  }
>
> -static target_ulong arm_flen_buf(ARMCPU *cpu)
> +static target_ulong common_semi_flen_buf(CPUState *cs)
>  {
> +    target_ulong sp;
> +#ifdef TARGET_ARM
>      /* 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.
>       */
> +    ARMCPU *cpu = ARM_CPU(cs);
>      CPUARMState *env = &cpu->env;
> -    target_ulong sp;
>
>      if (is_a64(env)) {
>          sp = env->xregs[31];
>      } else {
>          sp = env->regs[13];
>      }
> +#endif
>
>      return sp - 64;
>  }
>
> -static void arm_semi_flen_cb(CPUState *cs, target_ulong ret, target_ulong err)
> +static void common_semi_flen_cb(CPUState *cs, target_ulong ret, target_ulong err)
>  {
> -    ARMCPU *cpu = ARM_CPU(cs);
> -    CPUARMState *env = &cpu->env;
>      /* 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, arm_flen_buf(cpu) + 32, (uint8_t *)&size, 4, 0);
> +    cpu_memory_rw_debug(cs, common_semi_flen_buf(cs) + 32, (uint8_t *)&size, 4, 0);
>      size = be32_to_cpu(size);
> -    if (is_a64(env)) {
> -        env->xregs[0] = size;
> -    } else {
> -        env->regs[0] = size;
> -    }
> +    common_semi_set_ret(cs, size);
>      errno = err;
> -    set_swi_errno(env, -1);
> +    set_swi_errno(cs, -1);
>  }
>
> -static int arm_semi_open_guestfd;
> +static int common_semi_open_guestfd;
>
> -static void arm_semi_open_cb(CPUState *cs, target_ulong ret, target_ulong err)
> +static void common_semi_open_cb(CPUState *cs, target_ulong ret, target_ulong err)
>  {
> -    ARMCPU *cpu = ARM_CPU(cs);
> -    CPUARMState *env = &cpu->env;
>      if (ret == (target_ulong)-1) {
>          errno = err;
> -        set_swi_errno(env, -1);
> -        dealloc_guestfd(arm_semi_open_guestfd);
> -    } else {
> -        associate_guestfd(arm_semi_open_guestfd, ret);
> -        ret = arm_semi_open_guestfd;
> -    }
> -
> -    if (is_a64(env)) {
> -        env->xregs[0] = ret;
> +        set_swi_errno(cs, -1);
> +        dealloc_guestfd(common_semi_open_guestfd);
>      } else {
> -        env->regs[0] = ret;
> +        associate_guestfd(common_semi_open_guestfd, ret);
> +        ret = common_semi_open_guestfd;
>      }
> +    common_semi_set_ret(cs, ret);
>  }
>
> -static target_ulong arm_gdb_syscall(ARMCPU *cpu, gdb_syscall_complete_cb cb,
> -                                    const char *fmt, ...)
> +static target_ulong common_semi_gdb_syscall(CPUState *cs, gdb_syscall_complete_cb cb,
> +                                            const char *fmt, ...)
>  {
>      va_list va;
> -    CPUARMState *env = &cpu->env;
>
>      va_start(va, fmt);
>      gdb_do_syscallv(cb, fmt, va);
> @@ -384,7 +396,7 @@ static target_ulong arm_gdb_syscall(ARMCPU *cpu, gdb_syscall_complete_cb cb,
>       * doing something with the return value is not possible to make.
>       */
>
> -    return is_a64(env) ? env->xregs[0] : env->regs[0];
> +    return common_semi_arg(cs, 0);
>  }
>
>  /*
> @@ -393,20 +405,18 @@ static target_ulong arm_gdb_syscall(ARMCPU *cpu, gdb_syscall_complete_cb cb,
>   * do the work and return the required return value for the guest,
>   * setting the guest errno if appropriate.
>   */
> -typedef uint32_t sys_closefn(ARMCPU *cpu, GuestFD *gf);
> -typedef uint32_t sys_writefn(ARMCPU *cpu, GuestFD *gf,
> +typedef uint32_t sys_closefn(CPUState *cs, GuestFD *gf);
> +typedef uint32_t sys_writefn(CPUState *cs, GuestFD *gf,
>                               target_ulong buf, uint32_t len);
> -typedef uint32_t sys_readfn(ARMCPU *cpu, GuestFD *gf,
> +typedef uint32_t sys_readfn(CPUState *cs, GuestFD *gf,
>                              target_ulong buf, uint32_t len);
> -typedef uint32_t sys_isattyfn(ARMCPU *cpu, GuestFD *gf);
> -typedef uint32_t sys_seekfn(ARMCPU *cpu, GuestFD *gf,
> +typedef uint32_t sys_isattyfn(CPUState *cs, GuestFD *gf);
> +typedef uint32_t sys_seekfn(CPUState *cs, GuestFD *gf,
>                              target_ulong offset);
> -typedef uint32_t sys_flenfn(ARMCPU *cpu, GuestFD *gf);
> +typedef uint32_t sys_flenfn(CPUState *cs, GuestFD *gf);
>
> -static uint32_t host_closefn(ARMCPU *cpu, GuestFD *gf)
> +static uint32_t host_closefn(CPUState *cs, GuestFD *gf)
>  {
> -    CPUARMState *env = &cpu->env;
> -
>      /*
>       * Only close the underlying host fd if it's one we opened on behalf
>       * of the guest in SYS_OPEN.
> @@ -416,20 +426,21 @@ static uint32_t host_closefn(ARMCPU *cpu, GuestFD *gf)
>          gf->hostfd == STDERR_FILENO) {
>          return 0;
>      }
> -    return set_swi_errno(env, close(gf->hostfd));
> +    return set_swi_errno(cs, close(gf->hostfd));
>  }
>
> -static uint32_t host_writefn(ARMCPU *cpu, GuestFD *gf,
> +static uint32_t host_writefn(CPUState *cs, GuestFD *gf,
>                               target_ulong buf, uint32_t len)
>  {
> +    CPUArchState *env = cs->env_ptr;
>      uint32_t ret;
> -    CPUARMState *env = &cpu->env;
>      char *s = lock_user(VERIFY_READ, buf, len, 1);
> +    (void) env; /* Used in arm softmmu lock_user implicitly */
>      if (!s) {
>          /* Return bytes not written on error */
>          return len;
>      }
> -    ret = set_swi_errno(env, write(gf->hostfd, s, len));
> +    ret = set_swi_errno(cs, write(gf->hostfd, s, len));
>      unlock_user(s, buf, 0);
>      if (ret == (uint32_t)-1) {
>          ret = 0;
> @@ -438,18 +449,19 @@ static uint32_t host_writefn(ARMCPU *cpu, GuestFD *gf,
>      return len - ret;
>  }
>
> -static uint32_t host_readfn(ARMCPU *cpu, GuestFD *gf,
> +static uint32_t host_readfn(CPUState *cs, GuestFD *gf,
>                              target_ulong buf, uint32_t len)
>  {
> +    CPUArchState *env = cs->env_ptr;
>      uint32_t ret;
> -    CPUARMState *env = &cpu->env;
>      char *s = lock_user(VERIFY_WRITE, buf, len, 0);
> +    (void) env; /* Used in arm softmmu lock_user implicitly */
>      if (!s) {
>          /* return bytes not read */
>          return len;
>      }
>      do {
> -        ret = set_swi_errno(env, read(gf->hostfd, s, len));
> +        ret = set_swi_errno(cs, read(gf->hostfd, s, len));
>      } while (ret == -1 && errno == EINTR);
>      unlock_user(s, buf, len);
>      if (ret == (uint32_t)-1) {
> @@ -459,68 +471,66 @@ static uint32_t host_readfn(ARMCPU *cpu, GuestFD *gf,
>      return len - ret;
>  }
>
> -static uint32_t host_isattyfn(ARMCPU *cpu, GuestFD *gf)
> +static uint32_t host_isattyfn(CPUState *cs, GuestFD *gf)
>  {
>      return isatty(gf->hostfd);
>  }
>
> -static uint32_t host_seekfn(ARMCPU *cpu, GuestFD *gf, target_ulong offset)
> +static uint32_t host_seekfn(CPUState *cs, GuestFD *gf, target_ulong offset)
>  {
> -    CPUARMState *env = &cpu->env;
> -    uint32_t ret = set_swi_errno(env, lseek(gf->hostfd, offset, SEEK_SET));
> +    uint32_t ret = set_swi_errno(cs, lseek(gf->hostfd, offset, SEEK_SET));
>      if (ret == (uint32_t)-1) {
>          return -1;
>      }
>      return 0;
>  }
>
> -static uint32_t host_flenfn(ARMCPU *cpu, GuestFD *gf)
> +static uint32_t host_flenfn(CPUState *cs, GuestFD *gf)
>  {
> -    CPUARMState *env = &cpu->env;
>      struct stat buf;
> -    uint32_t ret = set_swi_errno(env, fstat(gf->hostfd, &buf));
> +    uint32_t ret = set_swi_errno(cs, fstat(gf->hostfd, &buf));
>      if (ret == (uint32_t)-1) {
>          return -1;
>      }
>      return buf.st_size;
>  }
>
> -static uint32_t gdb_closefn(ARMCPU *cpu, GuestFD *gf)
> +static uint32_t gdb_closefn(CPUState *cs, GuestFD *gf)
>  {
> -    return arm_gdb_syscall(cpu, arm_semi_cb, "close,%x", gf->hostfd);
> +    return common_semi_gdb_syscall(cs, common_semi_cb, "close,%x", gf->hostfd);
>  }
>
> -static uint32_t gdb_writefn(ARMCPU *cpu, GuestFD *gf,
> +static uint32_t gdb_writefn(CPUState *cs, GuestFD *gf,
>                              target_ulong buf, uint32_t len)
>  {
> -    arm_semi_syscall_len = len;
> -    return arm_gdb_syscall(cpu, arm_semi_cb, "write,%x,%x,%x",
> -                           gf->hostfd, buf, len);
> +    common_semi_syscall_len = len;
> +    return common_semi_gdb_syscall(cs, common_semi_cb, "write,%x,%x,%x",
> +                                   gf->hostfd, buf, len);
>  }
>
> -static uint32_t gdb_readfn(ARMCPU *cpu, GuestFD *gf,
> +static uint32_t gdb_readfn(CPUState *cs, GuestFD *gf,
>                             target_ulong buf, uint32_t len)
>  {
> -    arm_semi_syscall_len = len;
> -    return arm_gdb_syscall(cpu, arm_semi_cb, "read,%x,%x,%x",
> -                           gf->hostfd, buf, len);
> +    common_semi_syscall_len = len;
> +    return common_semi_gdb_syscall(cs, common_semi_cb, "read,%x,%x,%x",
> +                                   gf->hostfd, buf, len);
>  }
>
> -static uint32_t gdb_isattyfn(ARMCPU *cpu, GuestFD *gf)
> +static uint32_t gdb_isattyfn(CPUState *cs, GuestFD *gf)
>  {
> -    return arm_gdb_syscall(cpu, arm_semi_cb, "isatty,%x", gf->hostfd);
> +    return common_semi_gdb_syscall(cs, common_semi_cb, "isatty,%x", gf->hostfd);
>  }
>
> -static uint32_t gdb_seekfn(ARMCPU *cpu, GuestFD *gf, target_ulong offset)
> +static uint32_t gdb_seekfn(CPUState *cs, GuestFD *gf, target_ulong offset)
>  {
> -    return arm_gdb_syscall(cpu, arm_semi_cb, "lseek,%x,%x,0",
> -                           gf->hostfd, offset);
> +    return common_semi_gdb_syscall(cs, common_semi_cb, "lseek,%x,%x,0",
> +                                   gf->hostfd, offset);
>  }
>
> -static uint32_t gdb_flenfn(ARMCPU *cpu, GuestFD *gf)
> +static uint32_t gdb_flenfn(CPUState *cs, GuestFD *gf)
>  {
> -    return arm_gdb_syscall(cpu, arm_semi_flen_cb, "fstat,%x,%x",
> -                           gf->hostfd, arm_flen_buf(cpu));
> +    return common_semi_gdb_syscall(cs, common_semi_flen_cb, "fstat,%x,%x",
> +                                   gf->hostfd, common_semi_flen_buf(cs));
>  }
>
>  #define SHFB_MAGIC_0 0x53
> @@ -549,31 +559,29 @@ static void init_featurefile_guestfd(int guestfd)
>      gf->featurefile_offset = 0;
>  }
>
> -static uint32_t featurefile_closefn(ARMCPU *cpu, GuestFD *gf)
> +static uint32_t featurefile_closefn(CPUState *cs, GuestFD *gf)
>  {
>      /* Nothing to do */
>      return 0;
>  }
>
> -static uint32_t featurefile_writefn(ARMCPU *cpu, GuestFD *gf,
> +static uint32_t featurefile_writefn(CPUState *cs, GuestFD *gf,
>                                      target_ulong buf, uint32_t len)
>  {
>      /* This fd can never be open for writing */
> -    CPUARMState *env = &cpu->env;
>
>      errno = EBADF;
> -    return set_swi_errno(env, -1);
> +    return set_swi_errno(cs, -1);
>  }
>
> -static uint32_t featurefile_readfn(ARMCPU *cpu, GuestFD *gf,
> +static uint32_t featurefile_readfn(CPUState *cs, GuestFD *gf,
>                                     target_ulong buf, uint32_t len)
>  {
> +    CPUArchState *env = cs->env_ptr;
>      uint32_t i;
> -#ifndef CONFIG_USER_ONLY
> -    CPUARMState *env = &cpu->env;
> -#endif
>      char *s;
>
> +    (void) env; /* Used in arm softmmu lock_user implicitly */
>      s = lock_user(VERIFY_WRITE, buf, len, 0);
>      if (!s) {
>          return len;
> @@ -593,19 +601,19 @@ static uint32_t featurefile_readfn(ARMCPU *cpu, GuestFD *gf,
>      return len - i;
>  }
>
> -static uint32_t featurefile_isattyfn(ARMCPU *cpu, GuestFD *gf)
> +static uint32_t featurefile_isattyfn(CPUState *cs, GuestFD *gf)
>  {
>      return 0;
>  }
>
> -static uint32_t featurefile_seekfn(ARMCPU *cpu, GuestFD *gf,
> +static uint32_t featurefile_seekfn(CPUState *cs, GuestFD *gf,
>                                     target_ulong offset)
>  {
>      gf->featurefile_offset = offset;
>      return 0;
>  }
>
> -static uint32_t featurefile_flenfn(ARMCPU *cpu, GuestFD *gf)
> +static uint32_t featurefile_flenfn(CPUState *cs, GuestFD *gf)
>  {
>      return sizeof(featurefile_data);
>  }
> @@ -649,16 +657,17 @@ static const GuestFDFunctions guestfd_fns[] = {
>  /* Read the input value from the argument block; fail the semihosting
>   * call if the memory read fails.
>   */
> +#ifdef TARGET_ARM
>  #define GET_ARG(n) do {                                 \
>      if (is_a64(env)) {                                  \
>          if (get_user_u64(arg ## n, args + (n) * 8)) {   \
>              errno = EFAULT;                             \
> -            return set_swi_errno(env, -1);              \
> +            return set_swi_errno(cs, -1);              \
>          }                                               \
>      } else {                                            \
>          if (get_user_u32(arg ## n, args + (n) * 4)) {   \
>              errno = EFAULT;                             \
> -            return set_swi_errno(env, -1);              \
> +            return set_swi_errno(cs, -1);              \
>          }                                               \
>      }                                                   \
>  } while (0)
> @@ -667,6 +676,7 @@ static const GuestFDFunctions guestfd_fns[] = {
>      (is_a64(env) ?                                      \
>       put_user_u64(val, args + (n) * 8) :                \
>       put_user_u32(val, args + (n) * 4))
> +#endif
>
>  /*
>   * Do a semihosting call.
> @@ -679,8 +689,7 @@ static const GuestFDFunctions guestfd_fns[] = {
>   */
>  target_ulong do_common_semihosting(CPUState *cs)
>  {
> -    ARMCPU *cpu = ARM_CPU(cs);
> -    CPUARMState *env = &cpu->env;
> +    CPUArchState *env = cs->env_ptr;
>      target_ulong args;
>      target_ulong arg0, arg1, arg2, arg3;
>      char * s;
> @@ -689,14 +698,9 @@ target_ulong do_common_semihosting(CPUState *cs)
>      uint32_t len;
>      GuestFD *gf;
>
> -    if (is_a64(env)) {
> -        /* 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];
> -    }
> +    (void) env; /* Used implicitly by arm lock_user macro */
> +    nr = common_semi_arg(cs, 0) & 0xffffffffU;
> +    args = common_semi_arg(cs, 1);
>
>      switch (nr) {
>      case TARGET_SYS_OPEN:
> @@ -709,19 +713,19 @@ target_ulong do_common_semihosting(CPUState *cs)
>          s = lock_user_string(arg0);
>          if (!s) {
>              errno = EFAULT;
> -            return set_swi_errno(env, -1);
> +            return set_swi_errno(cs, -1);
>          }
>          if (arg1 >= 12) {
>              unlock_user(s, arg0, 0);
>              errno = EINVAL;
> -            return set_swi_errno(env, -1);
> +            return set_swi_errno(cs, -1);
>          }
>
>          guestfd = alloc_guestfd();
>          if (guestfd < 0) {
>              unlock_user(s, arg0, 0);
>              errno = EMFILE;
> -            return set_swi_errno(env, -1);
> +            return set_swi_errno(cs, -1);
>          }
>
>          if (strcmp(s, ":tt") == 0) {
> @@ -750,18 +754,18 @@ target_ulong do_common_semihosting(CPUState *cs)
>              if (arg1 != 0 && arg1 != 1) {
>                  dealloc_guestfd(guestfd);
>                  errno = EACCES;
> -                return set_swi_errno(env, -1);
> +                return set_swi_errno(cs, -1);
>              }
>              init_featurefile_guestfd(guestfd);
>              return guestfd;
>          }
>
>          if (use_gdb_syscalls()) {
> -            arm_semi_open_guestfd = guestfd;
> -            ret = arm_gdb_syscall(cpu, arm_semi_open_cb, "open,%s,%x,1a4", arg0,
> -                                  (int)arg2+1, gdb_open_modeflags[arg1]);
> +            common_semi_open_guestfd = guestfd;
> +            ret = common_semi_gdb_syscall(cs, common_semi_open_cb, "open,%s,%x,1a4", arg0,
> +                                          (int)arg2+1, gdb_open_modeflags[arg1]);
>          } else {
> -            ret = set_swi_errno(env, open(s, open_modeflags[arg1], 0644));
> +            ret = set_swi_errno(cs, open(s, open_modeflags[arg1], 0644));
>              if (ret == (uint32_t)-1) {
>                  dealloc_guestfd(guestfd);
>              } else {
> @@ -778,17 +782,17 @@ target_ulong do_common_semihosting(CPUState *cs)
>          gf = get_guestfd(arg0);
>          if (!gf) {
>              errno = EBADF;
> -            return set_swi_errno(env, -1);
> +            return set_swi_errno(cs, -1);
>          }
>
> -        ret = guestfd_fns[gf->type].closefn(cpu, gf);
> +        ret = guestfd_fns[gf->type].closefn(cs, gf);
>          dealloc_guestfd(arg0);
>          return ret;
>      case TARGET_SYS_WRITEC:
> -        qemu_semihosting_console_outc(env, args);
> +        qemu_semihosting_console_outc(cs->env_ptr, args);
>          return 0xdeadbeef;
>      case TARGET_SYS_WRITE0:
> -        return qemu_semihosting_console_outs(env, args);
> +        return qemu_semihosting_console_outs(cs->env_ptr, args);
>      case TARGET_SYS_WRITE:
>          GET_ARG(0);
>          GET_ARG(1);
> @@ -798,10 +802,10 @@ target_ulong do_common_semihosting(CPUState *cs)
>          gf = get_guestfd(arg0);
>          if (!gf) {
>              errno = EBADF;
> -            return set_swi_errno(env, -1);
> +            return set_swi_errno(cs, -1);
>          }
>
> -        return guestfd_fns[gf->type].writefn(cpu, gf, arg1, len);
> +        return guestfd_fns[gf->type].writefn(cs, gf, arg1, len);
>      case TARGET_SYS_READ:
>          GET_ARG(0);
>          GET_ARG(1);
> @@ -811,22 +815,22 @@ target_ulong do_common_semihosting(CPUState *cs)
>          gf = get_guestfd(arg0);
>          if (!gf) {
>              errno = EBADF;
> -            return set_swi_errno(env, -1);
> +            return set_swi_errno(cs, -1);
>          }
>
> -        return guestfd_fns[gf->type].readfn(cpu, gf, arg1, len);
> +        return guestfd_fns[gf->type].readfn(cs, gf, arg1, len);
>      case TARGET_SYS_READC:
> -        return qemu_semihosting_console_inc(env);
> +        return qemu_semihosting_console_inc(cs->env_ptr);
>      case TARGET_SYS_ISTTY:
>          GET_ARG(0);
>
>          gf = get_guestfd(arg0);
>          if (!gf) {
>              errno = EBADF;
> -            return set_swi_errno(env, -1);
> +            return set_swi_errno(cs, -1);
>          }
>
> -        return guestfd_fns[gf->type].isattyfn(cpu, gf);
> +        return guestfd_fns[gf->type].isattyfn(cs, gf);
>      case TARGET_SYS_SEEK:
>          GET_ARG(0);
>          GET_ARG(1);
> @@ -834,20 +838,20 @@ target_ulong do_common_semihosting(CPUState *cs)
>          gf = get_guestfd(arg0);
>          if (!gf) {
>              errno = EBADF;
> -            return set_swi_errno(env, -1);
> +            return set_swi_errno(cs, -1);
>          }
>
> -        return guestfd_fns[gf->type].seekfn(cpu, gf, arg1);
> +        return guestfd_fns[gf->type].seekfn(cs, gf, arg1);
>      case TARGET_SYS_FLEN:
>          GET_ARG(0);
>
>          gf = get_guestfd(arg0);
>          if (!gf) {
>              errno = EBADF;
> -            return set_swi_errno(env, -1);
> +            return set_swi_errno(cs, -1);
>          }
>
> -        return guestfd_fns[gf->type].flenfn(cpu, gf);
> +        return guestfd_fns[gf->type].flenfn(cs, gf);
>      case TARGET_SYS_TMPNAM:
>          qemu_log_mask(LOG_UNIMP, "%s: SYS_TMPNAM not implemented", __func__);
>          return -1;
> @@ -855,15 +859,15 @@ target_ulong do_common_semihosting(CPUState *cs)
>          GET_ARG(0);
>          GET_ARG(1);
>          if (use_gdb_syscalls()) {
> -            ret = arm_gdb_syscall(cpu, arm_semi_cb, "unlink,%s",
> -                                  arg0, (int)arg1+1);
> +            ret = common_semi_gdb_syscall(cs, common_semi_cb, "unlink,%s",
> +                                          arg0, (int)arg1+1);
>          } else {
>              s = lock_user_string(arg0);
>              if (!s) {
>                  errno = EFAULT;
> -                return set_swi_errno(env, -1);
> +                return set_swi_errno(cs, -1);
>              }
> -            ret =  set_swi_errno(env, remove(s));
> +            ret =  set_swi_errno(cs, remove(s));
>              unlock_user(s, arg0, 0);
>          }
>          return ret;
> @@ -873,17 +877,17 @@ target_ulong do_common_semihosting(CPUState *cs)
>          GET_ARG(2);
>          GET_ARG(3);
>          if (use_gdb_syscalls()) {
> -            return arm_gdb_syscall(cpu, arm_semi_cb, "rename,%s,%s",
> -                                   arg0, (int)arg1+1, arg2, (int)arg3+1);
> +            return common_semi_gdb_syscall(cs, common_semi_cb, "rename,%s,%s",
> +                                           arg0, (int)arg1+1, arg2, (int)arg3+1);
>          } else {
>              char *s2;
>              s = lock_user_string(arg0);
>              s2 = lock_user_string(arg2);
>              if (!s || !s2) {
>                  errno = EFAULT;
> -                ret = set_swi_errno(env, -1);
> +                ret = set_swi_errno(cs, -1);
>              } else {
> -                ret = set_swi_errno(env, rename(s, s2));
> +                ret = set_swi_errno(cs, rename(s, s2));
>              }
>              if (s2)
>                  unlock_user(s2, arg2, 0);
> @@ -894,25 +898,25 @@ target_ulong do_common_semihosting(CPUState *cs)
>      case TARGET_SYS_CLOCK:
>          return clock() / (CLOCKS_PER_SEC / 100);
>      case TARGET_SYS_TIME:
> -        return set_swi_errno(env, time(NULL));
> +        return set_swi_errno(cs, time(NULL));
>      case TARGET_SYS_SYSTEM:
>          GET_ARG(0);
>          GET_ARG(1);
>          if (use_gdb_syscalls()) {
> -            return arm_gdb_syscall(cpu, arm_semi_cb, "system,%s",
> -                                   arg0, (int)arg1+1);
> +            return common_semi_gdb_syscall(cs, common_semi_cb, "system,%s",
> +                                           arg0, (int)arg1+1);
>          } else {
>              s = lock_user_string(arg0);
>              if (!s) {
>                  errno = EFAULT;
> -                return set_swi_errno(env, -1);
> +                return set_swi_errno(cs, -1);
>              }
> -            ret = set_swi_errno(env, system(s));
> +            ret = set_swi_errno(cs, system(s));
>              unlock_user(s, arg0, 0);
>              return ret;
>          }
>      case TARGET_SYS_ERRNO:
> -        return get_swi_errno(env);
> +        return get_swi_errno(cs);
>      case TARGET_SYS_GET_CMDLINE:
>          {
>              /* Build a command-line from the original argv.
> @@ -964,21 +968,21 @@ target_ulong do_common_semihosting(CPUState *cs)
>              if (output_size > input_size) {
>                  /* Not enough space to store command-line arguments.  */
>                  errno = E2BIG;
> -                return set_swi_errno(env, -1);
> +                return set_swi_errno(cs, -1);
>              }
>
>              /* Adjust the command-line length.  */
>              if (SET_ARG(1, output_size - 1)) {
>                  /* Couldn't write back to argument block */
>                  errno = EFAULT;
> -                return set_swi_errno(env, -1);
> +                return set_swi_errno(cs, -1);
>              }
>
>              /* Lock the buffer on the ARM side.  */
>              output_buffer = lock_user(VERIFY_WRITE, arg0, output_size, 0);
>              if (!output_buffer) {
>                  errno = EFAULT;
> -                return set_swi_errno(env, -1);
> +                return set_swi_errno(cs, -1);
>              }
>
>              /* Copy the command-line arguments.  */
> @@ -994,7 +998,7 @@ target_ulong do_common_semihosting(CPUState *cs)
>              if (copy_from_user(output_buffer, ts->info->arg_start,
>                                 output_size)) {
>                  errno = EFAULT;
> -                status = set_swi_errno(env, -1);
> +                status = set_swi_errno(cs, -1);
>                  goto out;
>              }
>
> @@ -1031,7 +1035,7 @@ target_ulong do_common_semihosting(CPUState *cs)
>                  abi_ulong ret;
>
>                  ts->heap_base = do_brk(0);
> -                limit = ts->heap_base + ARM_ANGEL_HEAP_SIZE;
> +                limit = ts->heap_base + COMMON_SEMI_HEAP_SIZE;
>                  /* Try a big heap, and reduce the size if that fails.  */
>                  for (;;) {
>                      ret = do_brk(limit);
> @@ -1059,23 +1063,19 @@ target_ulong do_common_semihosting(CPUState *cs)
>              for (i = 0; i < ARRAY_SIZE(retvals); i++) {
>                  bool fail;
>
> -                if (is_a64(env)) {
> -                    fail = put_user_u64(retvals[i], arg0 + i * 8);
> -                } else {
> -                    fail = put_user_u32(retvals[i], arg0 + i * 4);
> -                }
> +                fail = SET_ARG(i, retvals[i]);
>
>                  if (fail) {
>                      /* Couldn't write back to argument block */
>                      errno = EFAULT;
> -                    return set_swi_errno(env, -1);
> +                    return set_swi_errno(cs, -1);
>                  }
>              }
>              return 0;
>          }
>      case TARGET_SYS_EXIT:
>      case TARGET_SYS_EXIT_EXTENDED:
> -        if (nr == TARGET_SYS_EXIT_EXTENDED || is_a64(env)) {
> +        if (common_semi_sys_exit_extended(cs, nr)) {
>              /*
>               * The A64 version of SYS_EXIT takes a parameter block,
>               * so the application-exit type can return a subcode which
> @@ -1100,7 +1100,7 @@ target_ulong do_common_semihosting(CPUState *cs)
>               */
>              ret = (args == ADP_Stopped_ApplicationExit) ? 0 : 1;
>          }
> -        gdb_exit(env, ret);
> +        gdb_exit(cs->env_ptr, ret);
>          exit(ret);
>      case TARGET_SYS_SYNCCACHE:
>          /*
> @@ -1108,9 +1108,11 @@ target_ulong do_common_semihosting(CPUState *cs)
>           * virtual address range. This is a nop for us since we don't
>           * implement caches. This is only present on A64.
>           */
> -        if (is_a64(env)) {
> +#ifdef TARGET_ARM
> +        if (is_a64(cs->env_ptr)) {
>              return 0;
>          }
> +#endif
>          /* fall through -- invalid for A32/T32 */
>      default:
>          fprintf(stderr, "qemu: Unsupported SemiHosting SWI 0x%02x\n", nr);
> --
> 2.28.0
>
>


^ permalink raw reply	[flat|nested] 32+ messages in thread

* [PATCH 3/4] semihosting: Change internal common-semi interfaces to use CPUState *
  2020-10-28 18:57 [PATCH 0/4] Add RISC-V semihosting support Keith Packard via
@ 2020-10-28 18:57   ` Keith Packard
  0 siblings, 0 replies; 32+ messages in thread
From: Keith Packard via @ 2020-10-28 18:57 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alex Bennée, Laurent Vivier, Peter Maydell, qemu-arm,
	Palmer Dabbelt, Alistair Francis, Sagar Karandikar,
	Bastian Koppelmann, qemu-riscv, Keith Packard

This makes all of the internal interfaces architecture-independent and
renames the internal functions to use the 'common_semi' prefix instead
of 'arm' or 'arm_semi'.

To do this, some new architecture-specific internal helper functions
were created:

    static inline target_ulong
    common_semi_arg(CPUState *cs, int argno)

	Returns the argno'th semihosting argument, where argno can be
	either 0 or 1.

    static inline void
    common_semi_set_ret(CPUState *cs, target_ulong ret)

	Sets the semihosting return value.

    static inline bool
    common_semi_sys_exit_extended(CPUState *cs, int nr)

	This detects whether the specified semihosting call, which
	is either TARGET_SYS_EXIT or TARGET_SYS_EXIT_EXTENDED should
	be executed using the TARGET_SYS_EXIT_EXTENDED semantics.

In addition, several existing functions have been changed to flag
areas of code which are architecture specific:

    static target_ulong
    common_semi_flen_buf(CPUState *cs)

	Returns the current stack pointer minus 64, which is
	where a stat structure will be placed on the stack

    #define GET_ARG(n)

	This fetches arguments from the semihosting command's argument
	block. The address of this is available implicitly through the
	local 'args' variable. This is *mostly* architecture
	independent, but does depend on the current ABI's notion of
	the size of a 'long' parameter, which may need run-time checks
	(as it does on AARCH64)

    #define SET_ARG(n, val)

	This mirrors GET_ARG and stores data back into the argument
	block.

Signed-off-by: Keith Packard <keithp@keithp.com>
---
 hw/semihosting/common-semi.c | 326 ++++++++++++++++++-----------------
 1 file changed, 164 insertions(+), 162 deletions(-)

diff --git a/hw/semihosting/common-semi.c b/hw/semihosting/common-semi.c
index e0c59bc599..c77fb21bec 100644
--- a/hw/semihosting/common-semi.c
+++ b/hw/semihosting/common-semi.c
@@ -32,11 +32,12 @@
 #include "cpu.h"
 #include "hw/semihosting/semihost.h"
 #include "hw/semihosting/console.h"
+#include "hw/semihosting/common-semi.h"
 #include "qemu/log.h"
 #ifdef CONFIG_USER_ONLY
 #include "qemu.h"
 
-#define ARM_ANGEL_HEAP_SIZE (128 * 1024 * 1024)
+#define COMMON_SEMI_HEAP_SIZE (128 * 1024 * 1024)
 #else
 #include "exec/gdbstub.h"
 #include "qemu/cutils.h"
@@ -132,6 +133,36 @@ typedef struct GuestFD {
 
 static GArray *guestfd_array;
 
+#ifdef TARGET_ARM
+static inline target_ulong
+common_semi_arg(CPUState *cs, int argno)
+{
+    ARMCPU *cpu = ARM_CPU(cs);
+    CPUARMState *env = &cpu->env;
+    if (is_a64(env))
+        return env->xregs[argno];
+    else
+        return env->regs[argno];
+}
+
+static inline void
+common_semi_set_ret(CPUState *cs, target_ulong ret)
+{
+    ARMCPU *cpu = ARM_CPU(cs);
+    CPUARMState *env = &cpu->env;
+    if (is_a64(env))
+        env->xregs[0] = ret;
+    else
+        env->regs[0] = ret;
+}
+
+static inline bool
+common_semi_sys_exit_extended(CPUState *cs, int nr)
+{
+    return (nr == TARGET_SYS_EXIT_EXTENDED || is_a64(cs->env_ptr));
+}
+#endif /* TARGET_ARM */
+
 /*
  * Allocate a new guest file descriptor and return it; if we
  * couldn't allocate a new fd then return -1.
@@ -237,11 +268,10 @@ static target_ulong syscall_err;
 #include "exec/softmmu-semi.h"
 #endif
 
-static inline uint32_t set_swi_errno(CPUARMState *env, uint32_t code)
+static inline uint32_t set_swi_errno(CPUState *cs, uint32_t code)
 {
     if (code == (uint32_t)-1) {
 #ifdef CONFIG_USER_ONLY
-        CPUState *cs = env_cpu(env);
         TaskState *ts = cs->opaque;
 
         ts->swi_errno = errno;
@@ -252,10 +282,9 @@ static inline uint32_t set_swi_errno(CPUARMState *env, uint32_t code)
     return code;
 }
 
-static inline uint32_t get_swi_errno(CPUARMState *env)
+static inline uint32_t get_swi_errno(CPUState *cs)
 {
 #ifdef CONFIG_USER_ONLY
-    CPUState *cs = env_cpu(env);
     TaskState *ts = cs->opaque;
 
     return ts->swi_errno;
@@ -264,24 +293,22 @@ static inline uint32_t get_swi_errno(CPUARMState *env)
 #endif
 }
 
-static target_ulong arm_semi_syscall_len;
+static target_ulong common_semi_syscall_len;
 
-static void arm_semi_cb(CPUState *cs, target_ulong ret, target_ulong err)
+static void common_semi_cb(CPUState *cs, target_ulong ret, target_ulong err)
 {
-    ARMCPU *cpu = ARM_CPU(cs);
-    CPUARMState *env = &cpu->env;
-    target_ulong reg0 = is_a64(env) ? env->xregs[0] : env->regs[0];
+    target_ulong reg0 = common_semi_arg(cs, 0);
 
     if (ret == (target_ulong)-1) {
         errno = err;
-        set_swi_errno(env, -1);
+        set_swi_errno(cs, -1);
         reg0 = ret;
     } else {
         /* Fixup syscalls that use nonstardard return conventions.  */
         switch (reg0) {
         case TARGET_SYS_WRITE:
         case TARGET_SYS_READ:
-            reg0 = arm_semi_syscall_len - ret;
+            reg0 = common_semi_syscall_len - ret;
             break;
         case TARGET_SYS_SEEK:
             reg0 = 0;
@@ -291,77 +318,62 @@ static void arm_semi_cb(CPUState *cs, target_ulong ret, target_ulong err)
             break;
         }
     }
-    if (is_a64(env)) {
-        env->xregs[0] = reg0;
-    } else {
-        env->regs[0] = reg0;
-    }
+    common_semi_set_ret(cs, reg0);
 }
 
-static target_ulong arm_flen_buf(ARMCPU *cpu)
+static target_ulong common_semi_flen_buf(CPUState *cs)
 {
+    target_ulong sp;
+#ifdef TARGET_ARM
     /* 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.
      */
+    ARMCPU *cpu = ARM_CPU(cs);
     CPUARMState *env = &cpu->env;
-    target_ulong sp;
 
     if (is_a64(env)) {
         sp = env->xregs[31];
     } else {
         sp = env->regs[13];
     }
+#endif
 
     return sp - 64;
 }
 
-static void arm_semi_flen_cb(CPUState *cs, target_ulong ret, target_ulong err)
+static void common_semi_flen_cb(CPUState *cs, target_ulong ret, target_ulong err)
 {
-    ARMCPU *cpu = ARM_CPU(cs);
-    CPUARMState *env = &cpu->env;
     /* 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, arm_flen_buf(cpu) + 32, (uint8_t *)&size, 4, 0);
+    cpu_memory_rw_debug(cs, common_semi_flen_buf(cs) + 32, (uint8_t *)&size, 4, 0);
     size = be32_to_cpu(size);
-    if (is_a64(env)) {
-        env->xregs[0] = size;
-    } else {
-        env->regs[0] = size;
-    }
+    common_semi_set_ret(cs, size);
     errno = err;
-    set_swi_errno(env, -1);
+    set_swi_errno(cs, -1);
 }
 
-static int arm_semi_open_guestfd;
+static int common_semi_open_guestfd;
 
-static void arm_semi_open_cb(CPUState *cs, target_ulong ret, target_ulong err)
+static void common_semi_open_cb(CPUState *cs, target_ulong ret, target_ulong err)
 {
-    ARMCPU *cpu = ARM_CPU(cs);
-    CPUARMState *env = &cpu->env;
     if (ret == (target_ulong)-1) {
         errno = err;
-        set_swi_errno(env, -1);
-        dealloc_guestfd(arm_semi_open_guestfd);
-    } else {
-        associate_guestfd(arm_semi_open_guestfd, ret);
-        ret = arm_semi_open_guestfd;
-    }
-
-    if (is_a64(env)) {
-        env->xregs[0] = ret;
+        set_swi_errno(cs, -1);
+        dealloc_guestfd(common_semi_open_guestfd);
     } else {
-        env->regs[0] = ret;
+        associate_guestfd(common_semi_open_guestfd, ret);
+        ret = common_semi_open_guestfd;
     }
+    common_semi_set_ret(cs, ret);
 }
 
-static target_ulong arm_gdb_syscall(ARMCPU *cpu, gdb_syscall_complete_cb cb,
-                                    const char *fmt, ...)
+static target_ulong common_semi_gdb_syscall(CPUState *cs, gdb_syscall_complete_cb cb,
+                                            const char *fmt, ...)
 {
     va_list va;
-    CPUARMState *env = &cpu->env;
 
     va_start(va, fmt);
     gdb_do_syscallv(cb, fmt, va);
@@ -384,7 +396,7 @@ static target_ulong arm_gdb_syscall(ARMCPU *cpu, gdb_syscall_complete_cb cb,
      * doing something with the return value is not possible to make.
      */
 
-    return is_a64(env) ? env->xregs[0] : env->regs[0];
+    return common_semi_arg(cs, 0);
 }
 
 /*
@@ -393,20 +405,18 @@ static target_ulong arm_gdb_syscall(ARMCPU *cpu, gdb_syscall_complete_cb cb,
  * do the work and return the required return value for the guest,
  * setting the guest errno if appropriate.
  */
-typedef uint32_t sys_closefn(ARMCPU *cpu, GuestFD *gf);
-typedef uint32_t sys_writefn(ARMCPU *cpu, GuestFD *gf,
+typedef uint32_t sys_closefn(CPUState *cs, GuestFD *gf);
+typedef uint32_t sys_writefn(CPUState *cs, GuestFD *gf,
                              target_ulong buf, uint32_t len);
-typedef uint32_t sys_readfn(ARMCPU *cpu, GuestFD *gf,
+typedef uint32_t sys_readfn(CPUState *cs, GuestFD *gf,
                             target_ulong buf, uint32_t len);
-typedef uint32_t sys_isattyfn(ARMCPU *cpu, GuestFD *gf);
-typedef uint32_t sys_seekfn(ARMCPU *cpu, GuestFD *gf,
+typedef uint32_t sys_isattyfn(CPUState *cs, GuestFD *gf);
+typedef uint32_t sys_seekfn(CPUState *cs, GuestFD *gf,
                             target_ulong offset);
-typedef uint32_t sys_flenfn(ARMCPU *cpu, GuestFD *gf);
+typedef uint32_t sys_flenfn(CPUState *cs, GuestFD *gf);
 
-static uint32_t host_closefn(ARMCPU *cpu, GuestFD *gf)
+static uint32_t host_closefn(CPUState *cs, GuestFD *gf)
 {
-    CPUARMState *env = &cpu->env;
-
     /*
      * Only close the underlying host fd if it's one we opened on behalf
      * of the guest in SYS_OPEN.
@@ -416,20 +426,21 @@ static uint32_t host_closefn(ARMCPU *cpu, GuestFD *gf)
         gf->hostfd == STDERR_FILENO) {
         return 0;
     }
-    return set_swi_errno(env, close(gf->hostfd));
+    return set_swi_errno(cs, close(gf->hostfd));
 }
 
-static uint32_t host_writefn(ARMCPU *cpu, GuestFD *gf,
+static uint32_t host_writefn(CPUState *cs, GuestFD *gf,
                              target_ulong buf, uint32_t len)
 {
+    CPUArchState *env = cs->env_ptr;
     uint32_t ret;
-    CPUARMState *env = &cpu->env;
     char *s = lock_user(VERIFY_READ, buf, len, 1);
+    (void) env; /* Used in arm softmmu lock_user implicitly */
     if (!s) {
         /* Return bytes not written on error */
         return len;
     }
-    ret = set_swi_errno(env, write(gf->hostfd, s, len));
+    ret = set_swi_errno(cs, write(gf->hostfd, s, len));
     unlock_user(s, buf, 0);
     if (ret == (uint32_t)-1) {
         ret = 0;
@@ -438,18 +449,19 @@ static uint32_t host_writefn(ARMCPU *cpu, GuestFD *gf,
     return len - ret;
 }
 
-static uint32_t host_readfn(ARMCPU *cpu, GuestFD *gf,
+static uint32_t host_readfn(CPUState *cs, GuestFD *gf,
                             target_ulong buf, uint32_t len)
 {
+    CPUArchState *env = cs->env_ptr;
     uint32_t ret;
-    CPUARMState *env = &cpu->env;
     char *s = lock_user(VERIFY_WRITE, buf, len, 0);
+    (void) env; /* Used in arm softmmu lock_user implicitly */
     if (!s) {
         /* return bytes not read */
         return len;
     }
     do {
-        ret = set_swi_errno(env, read(gf->hostfd, s, len));
+        ret = set_swi_errno(cs, read(gf->hostfd, s, len));
     } while (ret == -1 && errno == EINTR);
     unlock_user(s, buf, len);
     if (ret == (uint32_t)-1) {
@@ -459,68 +471,66 @@ static uint32_t host_readfn(ARMCPU *cpu, GuestFD *gf,
     return len - ret;
 }
 
-static uint32_t host_isattyfn(ARMCPU *cpu, GuestFD *gf)
+static uint32_t host_isattyfn(CPUState *cs, GuestFD *gf)
 {
     return isatty(gf->hostfd);
 }
 
-static uint32_t host_seekfn(ARMCPU *cpu, GuestFD *gf, target_ulong offset)
+static uint32_t host_seekfn(CPUState *cs, GuestFD *gf, target_ulong offset)
 {
-    CPUARMState *env = &cpu->env;
-    uint32_t ret = set_swi_errno(env, lseek(gf->hostfd, offset, SEEK_SET));
+    uint32_t ret = set_swi_errno(cs, lseek(gf->hostfd, offset, SEEK_SET));
     if (ret == (uint32_t)-1) {
         return -1;
     }
     return 0;
 }
 
-static uint32_t host_flenfn(ARMCPU *cpu, GuestFD *gf)
+static uint32_t host_flenfn(CPUState *cs, GuestFD *gf)
 {
-    CPUARMState *env = &cpu->env;
     struct stat buf;
-    uint32_t ret = set_swi_errno(env, fstat(gf->hostfd, &buf));
+    uint32_t ret = set_swi_errno(cs, fstat(gf->hostfd, &buf));
     if (ret == (uint32_t)-1) {
         return -1;
     }
     return buf.st_size;
 }
 
-static uint32_t gdb_closefn(ARMCPU *cpu, GuestFD *gf)
+static uint32_t gdb_closefn(CPUState *cs, GuestFD *gf)
 {
-    return arm_gdb_syscall(cpu, arm_semi_cb, "close,%x", gf->hostfd);
+    return common_semi_gdb_syscall(cs, common_semi_cb, "close,%x", gf->hostfd);
 }
 
-static uint32_t gdb_writefn(ARMCPU *cpu, GuestFD *gf,
+static uint32_t gdb_writefn(CPUState *cs, GuestFD *gf,
                             target_ulong buf, uint32_t len)
 {
-    arm_semi_syscall_len = len;
-    return arm_gdb_syscall(cpu, arm_semi_cb, "write,%x,%x,%x",
-                           gf->hostfd, buf, len);
+    common_semi_syscall_len = len;
+    return common_semi_gdb_syscall(cs, common_semi_cb, "write,%x,%x,%x",
+                                   gf->hostfd, buf, len);
 }
 
-static uint32_t gdb_readfn(ARMCPU *cpu, GuestFD *gf,
+static uint32_t gdb_readfn(CPUState *cs, GuestFD *gf,
                            target_ulong buf, uint32_t len)
 {
-    arm_semi_syscall_len = len;
-    return arm_gdb_syscall(cpu, arm_semi_cb, "read,%x,%x,%x",
-                           gf->hostfd, buf, len);
+    common_semi_syscall_len = len;
+    return common_semi_gdb_syscall(cs, common_semi_cb, "read,%x,%x,%x",
+                                   gf->hostfd, buf, len);
 }
 
-static uint32_t gdb_isattyfn(ARMCPU *cpu, GuestFD *gf)
+static uint32_t gdb_isattyfn(CPUState *cs, GuestFD *gf)
 {
-    return arm_gdb_syscall(cpu, arm_semi_cb, "isatty,%x", gf->hostfd);
+    return common_semi_gdb_syscall(cs, common_semi_cb, "isatty,%x", gf->hostfd);
 }
 
-static uint32_t gdb_seekfn(ARMCPU *cpu, GuestFD *gf, target_ulong offset)
+static uint32_t gdb_seekfn(CPUState *cs, GuestFD *gf, target_ulong offset)
 {
-    return arm_gdb_syscall(cpu, arm_semi_cb, "lseek,%x,%x,0",
-                           gf->hostfd, offset);
+    return common_semi_gdb_syscall(cs, common_semi_cb, "lseek,%x,%x,0",
+                                   gf->hostfd, offset);
 }
 
-static uint32_t gdb_flenfn(ARMCPU *cpu, GuestFD *gf)
+static uint32_t gdb_flenfn(CPUState *cs, GuestFD *gf)
 {
-    return arm_gdb_syscall(cpu, arm_semi_flen_cb, "fstat,%x,%x",
-                           gf->hostfd, arm_flen_buf(cpu));
+    return common_semi_gdb_syscall(cs, common_semi_flen_cb, "fstat,%x,%x",
+                                   gf->hostfd, common_semi_flen_buf(cs));
 }
 
 #define SHFB_MAGIC_0 0x53
@@ -549,31 +559,29 @@ static void init_featurefile_guestfd(int guestfd)
     gf->featurefile_offset = 0;
 }
 
-static uint32_t featurefile_closefn(ARMCPU *cpu, GuestFD *gf)
+static uint32_t featurefile_closefn(CPUState *cs, GuestFD *gf)
 {
     /* Nothing to do */
     return 0;
 }
 
-static uint32_t featurefile_writefn(ARMCPU *cpu, GuestFD *gf,
+static uint32_t featurefile_writefn(CPUState *cs, GuestFD *gf,
                                     target_ulong buf, uint32_t len)
 {
     /* This fd can never be open for writing */
-    CPUARMState *env = &cpu->env;
 
     errno = EBADF;
-    return set_swi_errno(env, -1);
+    return set_swi_errno(cs, -1);
 }
 
-static uint32_t featurefile_readfn(ARMCPU *cpu, GuestFD *gf,
+static uint32_t featurefile_readfn(CPUState *cs, GuestFD *gf,
                                    target_ulong buf, uint32_t len)
 {
+    CPUArchState *env = cs->env_ptr;
     uint32_t i;
-#ifndef CONFIG_USER_ONLY
-    CPUARMState *env = &cpu->env;
-#endif
     char *s;
 
+    (void) env; /* Used in arm softmmu lock_user implicitly */
     s = lock_user(VERIFY_WRITE, buf, len, 0);
     if (!s) {
         return len;
@@ -593,19 +601,19 @@ static uint32_t featurefile_readfn(ARMCPU *cpu, GuestFD *gf,
     return len - i;
 }
 
-static uint32_t featurefile_isattyfn(ARMCPU *cpu, GuestFD *gf)
+static uint32_t featurefile_isattyfn(CPUState *cs, GuestFD *gf)
 {
     return 0;
 }
 
-static uint32_t featurefile_seekfn(ARMCPU *cpu, GuestFD *gf,
+static uint32_t featurefile_seekfn(CPUState *cs, GuestFD *gf,
                                    target_ulong offset)
 {
     gf->featurefile_offset = offset;
     return 0;
 }
 
-static uint32_t featurefile_flenfn(ARMCPU *cpu, GuestFD *gf)
+static uint32_t featurefile_flenfn(CPUState *cs, GuestFD *gf)
 {
     return sizeof(featurefile_data);
 }
@@ -649,16 +657,17 @@ static const GuestFDFunctions guestfd_fns[] = {
 /* Read the input value from the argument block; fail the semihosting
  * call if the memory read fails.
  */
+#ifdef TARGET_ARM
 #define GET_ARG(n) do {                                 \
     if (is_a64(env)) {                                  \
         if (get_user_u64(arg ## n, args + (n) * 8)) {   \
             errno = EFAULT;                             \
-            return set_swi_errno(env, -1);              \
+            return set_swi_errno(cs, -1);              \
         }                                               \
     } else {                                            \
         if (get_user_u32(arg ## n, args + (n) * 4)) {   \
             errno = EFAULT;                             \
-            return set_swi_errno(env, -1);              \
+            return set_swi_errno(cs, -1);              \
         }                                               \
     }                                                   \
 } while (0)
@@ -667,6 +676,7 @@ static const GuestFDFunctions guestfd_fns[] = {
     (is_a64(env) ?                                      \
      put_user_u64(val, args + (n) * 8) :                \
      put_user_u32(val, args + (n) * 4))
+#endif
 
 /*
  * Do a semihosting call.
@@ -679,8 +689,7 @@ static const GuestFDFunctions guestfd_fns[] = {
  */
 target_ulong do_common_semihosting(CPUState *cs)
 {
-    ARMCPU *cpu = ARM_CPU(cs);
-    CPUARMState *env = &cpu->env;
+    CPUArchState *env = cs->env_ptr;
     target_ulong args;
     target_ulong arg0, arg1, arg2, arg3;
     char * s;
@@ -689,14 +698,9 @@ target_ulong do_common_semihosting(CPUState *cs)
     uint32_t len;
     GuestFD *gf;
 
-    if (is_a64(env)) {
-        /* 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];
-    }
+    (void) env; /* Used implicitly by arm lock_user macro */
+    nr = common_semi_arg(cs, 0) & 0xffffffffU;
+    args = common_semi_arg(cs, 1);
 
     switch (nr) {
     case TARGET_SYS_OPEN:
@@ -709,19 +713,19 @@ target_ulong do_common_semihosting(CPUState *cs)
         s = lock_user_string(arg0);
         if (!s) {
             errno = EFAULT;
-            return set_swi_errno(env, -1);
+            return set_swi_errno(cs, -1);
         }
         if (arg1 >= 12) {
             unlock_user(s, arg0, 0);
             errno = EINVAL;
-            return set_swi_errno(env, -1);
+            return set_swi_errno(cs, -1);
         }
 
         guestfd = alloc_guestfd();
         if (guestfd < 0) {
             unlock_user(s, arg0, 0);
             errno = EMFILE;
-            return set_swi_errno(env, -1);
+            return set_swi_errno(cs, -1);
         }
 
         if (strcmp(s, ":tt") == 0) {
@@ -750,18 +754,18 @@ target_ulong do_common_semihosting(CPUState *cs)
             if (arg1 != 0 && arg1 != 1) {
                 dealloc_guestfd(guestfd);
                 errno = EACCES;
-                return set_swi_errno(env, -1);
+                return set_swi_errno(cs, -1);
             }
             init_featurefile_guestfd(guestfd);
             return guestfd;
         }
 
         if (use_gdb_syscalls()) {
-            arm_semi_open_guestfd = guestfd;
-            ret = arm_gdb_syscall(cpu, arm_semi_open_cb, "open,%s,%x,1a4", arg0,
-                                  (int)arg2+1, gdb_open_modeflags[arg1]);
+            common_semi_open_guestfd = guestfd;
+            ret = common_semi_gdb_syscall(cs, common_semi_open_cb, "open,%s,%x,1a4", arg0,
+                                          (int)arg2+1, gdb_open_modeflags[arg1]);
         } else {
-            ret = set_swi_errno(env, open(s, open_modeflags[arg1], 0644));
+            ret = set_swi_errno(cs, open(s, open_modeflags[arg1], 0644));
             if (ret == (uint32_t)-1) {
                 dealloc_guestfd(guestfd);
             } else {
@@ -778,17 +782,17 @@ target_ulong do_common_semihosting(CPUState *cs)
         gf = get_guestfd(arg0);
         if (!gf) {
             errno = EBADF;
-            return set_swi_errno(env, -1);
+            return set_swi_errno(cs, -1);
         }
 
-        ret = guestfd_fns[gf->type].closefn(cpu, gf);
+        ret = guestfd_fns[gf->type].closefn(cs, gf);
         dealloc_guestfd(arg0);
         return ret;
     case TARGET_SYS_WRITEC:
-        qemu_semihosting_console_outc(env, args);
+        qemu_semihosting_console_outc(cs->env_ptr, args);
         return 0xdeadbeef;
     case TARGET_SYS_WRITE0:
-        return qemu_semihosting_console_outs(env, args);
+        return qemu_semihosting_console_outs(cs->env_ptr, args);
     case TARGET_SYS_WRITE:
         GET_ARG(0);
         GET_ARG(1);
@@ -798,10 +802,10 @@ target_ulong do_common_semihosting(CPUState *cs)
         gf = get_guestfd(arg0);
         if (!gf) {
             errno = EBADF;
-            return set_swi_errno(env, -1);
+            return set_swi_errno(cs, -1);
         }
 
-        return guestfd_fns[gf->type].writefn(cpu, gf, arg1, len);
+        return guestfd_fns[gf->type].writefn(cs, gf, arg1, len);
     case TARGET_SYS_READ:
         GET_ARG(0);
         GET_ARG(1);
@@ -811,22 +815,22 @@ target_ulong do_common_semihosting(CPUState *cs)
         gf = get_guestfd(arg0);
         if (!gf) {
             errno = EBADF;
-            return set_swi_errno(env, -1);
+            return set_swi_errno(cs, -1);
         }
 
-        return guestfd_fns[gf->type].readfn(cpu, gf, arg1, len);
+        return guestfd_fns[gf->type].readfn(cs, gf, arg1, len);
     case TARGET_SYS_READC:
-        return qemu_semihosting_console_inc(env);
+        return qemu_semihosting_console_inc(cs->env_ptr);
     case TARGET_SYS_ISTTY:
         GET_ARG(0);
 
         gf = get_guestfd(arg0);
         if (!gf) {
             errno = EBADF;
-            return set_swi_errno(env, -1);
+            return set_swi_errno(cs, -1);
         }
 
-        return guestfd_fns[gf->type].isattyfn(cpu, gf);
+        return guestfd_fns[gf->type].isattyfn(cs, gf);
     case TARGET_SYS_SEEK:
         GET_ARG(0);
         GET_ARG(1);
@@ -834,20 +838,20 @@ target_ulong do_common_semihosting(CPUState *cs)
         gf = get_guestfd(arg0);
         if (!gf) {
             errno = EBADF;
-            return set_swi_errno(env, -1);
+            return set_swi_errno(cs, -1);
         }
 
-        return guestfd_fns[gf->type].seekfn(cpu, gf, arg1);
+        return guestfd_fns[gf->type].seekfn(cs, gf, arg1);
     case TARGET_SYS_FLEN:
         GET_ARG(0);
 
         gf = get_guestfd(arg0);
         if (!gf) {
             errno = EBADF;
-            return set_swi_errno(env, -1);
+            return set_swi_errno(cs, -1);
         }
 
-        return guestfd_fns[gf->type].flenfn(cpu, gf);
+        return guestfd_fns[gf->type].flenfn(cs, gf);
     case TARGET_SYS_TMPNAM:
         qemu_log_mask(LOG_UNIMP, "%s: SYS_TMPNAM not implemented", __func__);
         return -1;
@@ -855,15 +859,15 @@ target_ulong do_common_semihosting(CPUState *cs)
         GET_ARG(0);
         GET_ARG(1);
         if (use_gdb_syscalls()) {
-            ret = arm_gdb_syscall(cpu, arm_semi_cb, "unlink,%s",
-                                  arg0, (int)arg1+1);
+            ret = common_semi_gdb_syscall(cs, common_semi_cb, "unlink,%s",
+                                          arg0, (int)arg1+1);
         } else {
             s = lock_user_string(arg0);
             if (!s) {
                 errno = EFAULT;
-                return set_swi_errno(env, -1);
+                return set_swi_errno(cs, -1);
             }
-            ret =  set_swi_errno(env, remove(s));
+            ret =  set_swi_errno(cs, remove(s));
             unlock_user(s, arg0, 0);
         }
         return ret;
@@ -873,17 +877,17 @@ target_ulong do_common_semihosting(CPUState *cs)
         GET_ARG(2);
         GET_ARG(3);
         if (use_gdb_syscalls()) {
-            return arm_gdb_syscall(cpu, arm_semi_cb, "rename,%s,%s",
-                                   arg0, (int)arg1+1, arg2, (int)arg3+1);
+            return common_semi_gdb_syscall(cs, common_semi_cb, "rename,%s,%s",
+                                           arg0, (int)arg1+1, arg2, (int)arg3+1);
         } else {
             char *s2;
             s = lock_user_string(arg0);
             s2 = lock_user_string(arg2);
             if (!s || !s2) {
                 errno = EFAULT;
-                ret = set_swi_errno(env, -1);
+                ret = set_swi_errno(cs, -1);
             } else {
-                ret = set_swi_errno(env, rename(s, s2));
+                ret = set_swi_errno(cs, rename(s, s2));
             }
             if (s2)
                 unlock_user(s2, arg2, 0);
@@ -894,25 +898,25 @@ target_ulong do_common_semihosting(CPUState *cs)
     case TARGET_SYS_CLOCK:
         return clock() / (CLOCKS_PER_SEC / 100);
     case TARGET_SYS_TIME:
-        return set_swi_errno(env, time(NULL));
+        return set_swi_errno(cs, time(NULL));
     case TARGET_SYS_SYSTEM:
         GET_ARG(0);
         GET_ARG(1);
         if (use_gdb_syscalls()) {
-            return arm_gdb_syscall(cpu, arm_semi_cb, "system,%s",
-                                   arg0, (int)arg1+1);
+            return common_semi_gdb_syscall(cs, common_semi_cb, "system,%s",
+                                           arg0, (int)arg1+1);
         } else {
             s = lock_user_string(arg0);
             if (!s) {
                 errno = EFAULT;
-                return set_swi_errno(env, -1);
+                return set_swi_errno(cs, -1);
             }
-            ret = set_swi_errno(env, system(s));
+            ret = set_swi_errno(cs, system(s));
             unlock_user(s, arg0, 0);
             return ret;
         }
     case TARGET_SYS_ERRNO:
-        return get_swi_errno(env);
+        return get_swi_errno(cs);
     case TARGET_SYS_GET_CMDLINE:
         {
             /* Build a command-line from the original argv.
@@ -964,21 +968,21 @@ target_ulong do_common_semihosting(CPUState *cs)
             if (output_size > input_size) {
                 /* Not enough space to store command-line arguments.  */
                 errno = E2BIG;
-                return set_swi_errno(env, -1);
+                return set_swi_errno(cs, -1);
             }
 
             /* Adjust the command-line length.  */
             if (SET_ARG(1, output_size - 1)) {
                 /* Couldn't write back to argument block */
                 errno = EFAULT;
-                return set_swi_errno(env, -1);
+                return set_swi_errno(cs, -1);
             }
 
             /* Lock the buffer on the ARM side.  */
             output_buffer = lock_user(VERIFY_WRITE, arg0, output_size, 0);
             if (!output_buffer) {
                 errno = EFAULT;
-                return set_swi_errno(env, -1);
+                return set_swi_errno(cs, -1);
             }
 
             /* Copy the command-line arguments.  */
@@ -994,7 +998,7 @@ target_ulong do_common_semihosting(CPUState *cs)
             if (copy_from_user(output_buffer, ts->info->arg_start,
                                output_size)) {
                 errno = EFAULT;
-                status = set_swi_errno(env, -1);
+                status = set_swi_errno(cs, -1);
                 goto out;
             }
 
@@ -1031,7 +1035,7 @@ target_ulong do_common_semihosting(CPUState *cs)
                 abi_ulong ret;
 
                 ts->heap_base = do_brk(0);
-                limit = ts->heap_base + ARM_ANGEL_HEAP_SIZE;
+                limit = ts->heap_base + COMMON_SEMI_HEAP_SIZE;
                 /* Try a big heap, and reduce the size if that fails.  */
                 for (;;) {
                     ret = do_brk(limit);
@@ -1059,23 +1063,19 @@ target_ulong do_common_semihosting(CPUState *cs)
             for (i = 0; i < ARRAY_SIZE(retvals); i++) {
                 bool fail;
 
-                if (is_a64(env)) {
-                    fail = put_user_u64(retvals[i], arg0 + i * 8);
-                } else {
-                    fail = put_user_u32(retvals[i], arg0 + i * 4);
-                }
+                fail = SET_ARG(i, retvals[i]);
 
                 if (fail) {
                     /* Couldn't write back to argument block */
                     errno = EFAULT;
-                    return set_swi_errno(env, -1);
+                    return set_swi_errno(cs, -1);
                 }
             }
             return 0;
         }
     case TARGET_SYS_EXIT:
     case TARGET_SYS_EXIT_EXTENDED:
-        if (nr == TARGET_SYS_EXIT_EXTENDED || is_a64(env)) {
+        if (common_semi_sys_exit_extended(cs, nr)) {
             /*
              * The A64 version of SYS_EXIT takes a parameter block,
              * so the application-exit type can return a subcode which
@@ -1100,7 +1100,7 @@ target_ulong do_common_semihosting(CPUState *cs)
              */
             ret = (args == ADP_Stopped_ApplicationExit) ? 0 : 1;
         }
-        gdb_exit(env, ret);
+        gdb_exit(cs->env_ptr, ret);
         exit(ret);
     case TARGET_SYS_SYNCCACHE:
         /*
@@ -1108,9 +1108,11 @@ target_ulong do_common_semihosting(CPUState *cs)
          * virtual address range. This is a nop for us since we don't
          * implement caches. This is only present on A64.
          */
-        if (is_a64(env)) {
+#ifdef TARGET_ARM
+        if (is_a64(cs->env_ptr)) {
             return 0;
         }
+#endif
         /* fall through -- invalid for A32/T32 */
     default:
         fprintf(stderr, "qemu: Unsupported SemiHosting SWI 0x%02x\n", nr);
-- 
2.28.0



^ permalink raw reply related	[flat|nested] 32+ messages in thread

* [PATCH 3/4] semihosting: Change internal common-semi interfaces to use CPUState *
@ 2020-10-28 18:57   ` Keith Packard
  0 siblings, 0 replies; 32+ messages in thread
From: Keith Packard @ 2020-10-28 18:57 UTC (permalink / raw)
  To: qemu-devel
  Cc: Alex Bennée, Laurent Vivier, Peter Maydell, qemu-arm,
	Palmer Dabbelt, Alistair Francis, Sagar Karandikar,
	Bastian Koppelmann, qemu-riscv, Keith Packard

This makes all of the internal interfaces architecture-independent and
renames the internal functions to use the 'common_semi' prefix instead
of 'arm' or 'arm_semi'.

To do this, some new architecture-specific internal helper functions
were created:

    static inline target_ulong
    common_semi_arg(CPUState *cs, int argno)

	Returns the argno'th semihosting argument, where argno can be
	either 0 or 1.

    static inline void
    common_semi_set_ret(CPUState *cs, target_ulong ret)

	Sets the semihosting return value.

    static inline bool
    common_semi_sys_exit_extended(CPUState *cs, int nr)

	This detects whether the specified semihosting call, which
	is either TARGET_SYS_EXIT or TARGET_SYS_EXIT_EXTENDED should
	be executed using the TARGET_SYS_EXIT_EXTENDED semantics.

In addition, several existing functions have been changed to flag
areas of code which are architecture specific:

    static target_ulong
    common_semi_flen_buf(CPUState *cs)

	Returns the current stack pointer minus 64, which is
	where a stat structure will be placed on the stack

    #define GET_ARG(n)

	This fetches arguments from the semihosting command's argument
	block. The address of this is available implicitly through the
	local 'args' variable. This is *mostly* architecture
	independent, but does depend on the current ABI's notion of
	the size of a 'long' parameter, which may need run-time checks
	(as it does on AARCH64)

    #define SET_ARG(n, val)

	This mirrors GET_ARG and stores data back into the argument
	block.

Signed-off-by: Keith Packard <keithp@keithp.com>
---
 hw/semihosting/common-semi.c | 326 ++++++++++++++++++-----------------
 1 file changed, 164 insertions(+), 162 deletions(-)

diff --git a/hw/semihosting/common-semi.c b/hw/semihosting/common-semi.c
index e0c59bc599..c77fb21bec 100644
--- a/hw/semihosting/common-semi.c
+++ b/hw/semihosting/common-semi.c
@@ -32,11 +32,12 @@
 #include "cpu.h"
 #include "hw/semihosting/semihost.h"
 #include "hw/semihosting/console.h"
+#include "hw/semihosting/common-semi.h"
 #include "qemu/log.h"
 #ifdef CONFIG_USER_ONLY
 #include "qemu.h"
 
-#define ARM_ANGEL_HEAP_SIZE (128 * 1024 * 1024)
+#define COMMON_SEMI_HEAP_SIZE (128 * 1024 * 1024)
 #else
 #include "exec/gdbstub.h"
 #include "qemu/cutils.h"
@@ -132,6 +133,36 @@ typedef struct GuestFD {
 
 static GArray *guestfd_array;
 
+#ifdef TARGET_ARM
+static inline target_ulong
+common_semi_arg(CPUState *cs, int argno)
+{
+    ARMCPU *cpu = ARM_CPU(cs);
+    CPUARMState *env = &cpu->env;
+    if (is_a64(env))
+        return env->xregs[argno];
+    else
+        return env->regs[argno];
+}
+
+static inline void
+common_semi_set_ret(CPUState *cs, target_ulong ret)
+{
+    ARMCPU *cpu = ARM_CPU(cs);
+    CPUARMState *env = &cpu->env;
+    if (is_a64(env))
+        env->xregs[0] = ret;
+    else
+        env->regs[0] = ret;
+}
+
+static inline bool
+common_semi_sys_exit_extended(CPUState *cs, int nr)
+{
+    return (nr == TARGET_SYS_EXIT_EXTENDED || is_a64(cs->env_ptr));
+}
+#endif /* TARGET_ARM */
+
 /*
  * Allocate a new guest file descriptor and return it; if we
  * couldn't allocate a new fd then return -1.
@@ -237,11 +268,10 @@ static target_ulong syscall_err;
 #include "exec/softmmu-semi.h"
 #endif
 
-static inline uint32_t set_swi_errno(CPUARMState *env, uint32_t code)
+static inline uint32_t set_swi_errno(CPUState *cs, uint32_t code)
 {
     if (code == (uint32_t)-1) {
 #ifdef CONFIG_USER_ONLY
-        CPUState *cs = env_cpu(env);
         TaskState *ts = cs->opaque;
 
         ts->swi_errno = errno;
@@ -252,10 +282,9 @@ static inline uint32_t set_swi_errno(CPUARMState *env, uint32_t code)
     return code;
 }
 
-static inline uint32_t get_swi_errno(CPUARMState *env)
+static inline uint32_t get_swi_errno(CPUState *cs)
 {
 #ifdef CONFIG_USER_ONLY
-    CPUState *cs = env_cpu(env);
     TaskState *ts = cs->opaque;
 
     return ts->swi_errno;
@@ -264,24 +293,22 @@ static inline uint32_t get_swi_errno(CPUARMState *env)
 #endif
 }
 
-static target_ulong arm_semi_syscall_len;
+static target_ulong common_semi_syscall_len;
 
-static void arm_semi_cb(CPUState *cs, target_ulong ret, target_ulong err)
+static void common_semi_cb(CPUState *cs, target_ulong ret, target_ulong err)
 {
-    ARMCPU *cpu = ARM_CPU(cs);
-    CPUARMState *env = &cpu->env;
-    target_ulong reg0 = is_a64(env) ? env->xregs[0] : env->regs[0];
+    target_ulong reg0 = common_semi_arg(cs, 0);
 
     if (ret == (target_ulong)-1) {
         errno = err;
-        set_swi_errno(env, -1);
+        set_swi_errno(cs, -1);
         reg0 = ret;
     } else {
         /* Fixup syscalls that use nonstardard return conventions.  */
         switch (reg0) {
         case TARGET_SYS_WRITE:
         case TARGET_SYS_READ:
-            reg0 = arm_semi_syscall_len - ret;
+            reg0 = common_semi_syscall_len - ret;
             break;
         case TARGET_SYS_SEEK:
             reg0 = 0;
@@ -291,77 +318,62 @@ static void arm_semi_cb(CPUState *cs, target_ulong ret, target_ulong err)
             break;
         }
     }
-    if (is_a64(env)) {
-        env->xregs[0] = reg0;
-    } else {
-        env->regs[0] = reg0;
-    }
+    common_semi_set_ret(cs, reg0);
 }
 
-static target_ulong arm_flen_buf(ARMCPU *cpu)
+static target_ulong common_semi_flen_buf(CPUState *cs)
 {
+    target_ulong sp;
+#ifdef TARGET_ARM
     /* 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.
      */
+    ARMCPU *cpu = ARM_CPU(cs);
     CPUARMState *env = &cpu->env;
-    target_ulong sp;
 
     if (is_a64(env)) {
         sp = env->xregs[31];
     } else {
         sp = env->regs[13];
     }
+#endif
 
     return sp - 64;
 }
 
-static void arm_semi_flen_cb(CPUState *cs, target_ulong ret, target_ulong err)
+static void common_semi_flen_cb(CPUState *cs, target_ulong ret, target_ulong err)
 {
-    ARMCPU *cpu = ARM_CPU(cs);
-    CPUARMState *env = &cpu->env;
     /* 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, arm_flen_buf(cpu) + 32, (uint8_t *)&size, 4, 0);
+    cpu_memory_rw_debug(cs, common_semi_flen_buf(cs) + 32, (uint8_t *)&size, 4, 0);
     size = be32_to_cpu(size);
-    if (is_a64(env)) {
-        env->xregs[0] = size;
-    } else {
-        env->regs[0] = size;
-    }
+    common_semi_set_ret(cs, size);
     errno = err;
-    set_swi_errno(env, -1);
+    set_swi_errno(cs, -1);
 }
 
-static int arm_semi_open_guestfd;
+static int common_semi_open_guestfd;
 
-static void arm_semi_open_cb(CPUState *cs, target_ulong ret, target_ulong err)
+static void common_semi_open_cb(CPUState *cs, target_ulong ret, target_ulong err)
 {
-    ARMCPU *cpu = ARM_CPU(cs);
-    CPUARMState *env = &cpu->env;
     if (ret == (target_ulong)-1) {
         errno = err;
-        set_swi_errno(env, -1);
-        dealloc_guestfd(arm_semi_open_guestfd);
-    } else {
-        associate_guestfd(arm_semi_open_guestfd, ret);
-        ret = arm_semi_open_guestfd;
-    }
-
-    if (is_a64(env)) {
-        env->xregs[0] = ret;
+        set_swi_errno(cs, -1);
+        dealloc_guestfd(common_semi_open_guestfd);
     } else {
-        env->regs[0] = ret;
+        associate_guestfd(common_semi_open_guestfd, ret);
+        ret = common_semi_open_guestfd;
     }
+    common_semi_set_ret(cs, ret);
 }
 
-static target_ulong arm_gdb_syscall(ARMCPU *cpu, gdb_syscall_complete_cb cb,
-                                    const char *fmt, ...)
+static target_ulong common_semi_gdb_syscall(CPUState *cs, gdb_syscall_complete_cb cb,
+                                            const char *fmt, ...)
 {
     va_list va;
-    CPUARMState *env = &cpu->env;
 
     va_start(va, fmt);
     gdb_do_syscallv(cb, fmt, va);
@@ -384,7 +396,7 @@ static target_ulong arm_gdb_syscall(ARMCPU *cpu, gdb_syscall_complete_cb cb,
      * doing something with the return value is not possible to make.
      */
 
-    return is_a64(env) ? env->xregs[0] : env->regs[0];
+    return common_semi_arg(cs, 0);
 }
 
 /*
@@ -393,20 +405,18 @@ static target_ulong arm_gdb_syscall(ARMCPU *cpu, gdb_syscall_complete_cb cb,
  * do the work and return the required return value for the guest,
  * setting the guest errno if appropriate.
  */
-typedef uint32_t sys_closefn(ARMCPU *cpu, GuestFD *gf);
-typedef uint32_t sys_writefn(ARMCPU *cpu, GuestFD *gf,
+typedef uint32_t sys_closefn(CPUState *cs, GuestFD *gf);
+typedef uint32_t sys_writefn(CPUState *cs, GuestFD *gf,
                              target_ulong buf, uint32_t len);
-typedef uint32_t sys_readfn(ARMCPU *cpu, GuestFD *gf,
+typedef uint32_t sys_readfn(CPUState *cs, GuestFD *gf,
                             target_ulong buf, uint32_t len);
-typedef uint32_t sys_isattyfn(ARMCPU *cpu, GuestFD *gf);
-typedef uint32_t sys_seekfn(ARMCPU *cpu, GuestFD *gf,
+typedef uint32_t sys_isattyfn(CPUState *cs, GuestFD *gf);
+typedef uint32_t sys_seekfn(CPUState *cs, GuestFD *gf,
                             target_ulong offset);
-typedef uint32_t sys_flenfn(ARMCPU *cpu, GuestFD *gf);
+typedef uint32_t sys_flenfn(CPUState *cs, GuestFD *gf);
 
-static uint32_t host_closefn(ARMCPU *cpu, GuestFD *gf)
+static uint32_t host_closefn(CPUState *cs, GuestFD *gf)
 {
-    CPUARMState *env = &cpu->env;
-
     /*
      * Only close the underlying host fd if it's one we opened on behalf
      * of the guest in SYS_OPEN.
@@ -416,20 +426,21 @@ static uint32_t host_closefn(ARMCPU *cpu, GuestFD *gf)
         gf->hostfd == STDERR_FILENO) {
         return 0;
     }
-    return set_swi_errno(env, close(gf->hostfd));
+    return set_swi_errno(cs, close(gf->hostfd));
 }
 
-static uint32_t host_writefn(ARMCPU *cpu, GuestFD *gf,
+static uint32_t host_writefn(CPUState *cs, GuestFD *gf,
                              target_ulong buf, uint32_t len)
 {
+    CPUArchState *env = cs->env_ptr;
     uint32_t ret;
-    CPUARMState *env = &cpu->env;
     char *s = lock_user(VERIFY_READ, buf, len, 1);
+    (void) env; /* Used in arm softmmu lock_user implicitly */
     if (!s) {
         /* Return bytes not written on error */
         return len;
     }
-    ret = set_swi_errno(env, write(gf->hostfd, s, len));
+    ret = set_swi_errno(cs, write(gf->hostfd, s, len));
     unlock_user(s, buf, 0);
     if (ret == (uint32_t)-1) {
         ret = 0;
@@ -438,18 +449,19 @@ static uint32_t host_writefn(ARMCPU *cpu, GuestFD *gf,
     return len - ret;
 }
 
-static uint32_t host_readfn(ARMCPU *cpu, GuestFD *gf,
+static uint32_t host_readfn(CPUState *cs, GuestFD *gf,
                             target_ulong buf, uint32_t len)
 {
+    CPUArchState *env = cs->env_ptr;
     uint32_t ret;
-    CPUARMState *env = &cpu->env;
     char *s = lock_user(VERIFY_WRITE, buf, len, 0);
+    (void) env; /* Used in arm softmmu lock_user implicitly */
     if (!s) {
         /* return bytes not read */
         return len;
     }
     do {
-        ret = set_swi_errno(env, read(gf->hostfd, s, len));
+        ret = set_swi_errno(cs, read(gf->hostfd, s, len));
     } while (ret == -1 && errno == EINTR);
     unlock_user(s, buf, len);
     if (ret == (uint32_t)-1) {
@@ -459,68 +471,66 @@ static uint32_t host_readfn(ARMCPU *cpu, GuestFD *gf,
     return len - ret;
 }
 
-static uint32_t host_isattyfn(ARMCPU *cpu, GuestFD *gf)
+static uint32_t host_isattyfn(CPUState *cs, GuestFD *gf)
 {
     return isatty(gf->hostfd);
 }
 
-static uint32_t host_seekfn(ARMCPU *cpu, GuestFD *gf, target_ulong offset)
+static uint32_t host_seekfn(CPUState *cs, GuestFD *gf, target_ulong offset)
 {
-    CPUARMState *env = &cpu->env;
-    uint32_t ret = set_swi_errno(env, lseek(gf->hostfd, offset, SEEK_SET));
+    uint32_t ret = set_swi_errno(cs, lseek(gf->hostfd, offset, SEEK_SET));
     if (ret == (uint32_t)-1) {
         return -1;
     }
     return 0;
 }
 
-static uint32_t host_flenfn(ARMCPU *cpu, GuestFD *gf)
+static uint32_t host_flenfn(CPUState *cs, GuestFD *gf)
 {
-    CPUARMState *env = &cpu->env;
     struct stat buf;
-    uint32_t ret = set_swi_errno(env, fstat(gf->hostfd, &buf));
+    uint32_t ret = set_swi_errno(cs, fstat(gf->hostfd, &buf));
     if (ret == (uint32_t)-1) {
         return -1;
     }
     return buf.st_size;
 }
 
-static uint32_t gdb_closefn(ARMCPU *cpu, GuestFD *gf)
+static uint32_t gdb_closefn(CPUState *cs, GuestFD *gf)
 {
-    return arm_gdb_syscall(cpu, arm_semi_cb, "close,%x", gf->hostfd);
+    return common_semi_gdb_syscall(cs, common_semi_cb, "close,%x", gf->hostfd);
 }
 
-static uint32_t gdb_writefn(ARMCPU *cpu, GuestFD *gf,
+static uint32_t gdb_writefn(CPUState *cs, GuestFD *gf,
                             target_ulong buf, uint32_t len)
 {
-    arm_semi_syscall_len = len;
-    return arm_gdb_syscall(cpu, arm_semi_cb, "write,%x,%x,%x",
-                           gf->hostfd, buf, len);
+    common_semi_syscall_len = len;
+    return common_semi_gdb_syscall(cs, common_semi_cb, "write,%x,%x,%x",
+                                   gf->hostfd, buf, len);
 }
 
-static uint32_t gdb_readfn(ARMCPU *cpu, GuestFD *gf,
+static uint32_t gdb_readfn(CPUState *cs, GuestFD *gf,
                            target_ulong buf, uint32_t len)
 {
-    arm_semi_syscall_len = len;
-    return arm_gdb_syscall(cpu, arm_semi_cb, "read,%x,%x,%x",
-                           gf->hostfd, buf, len);
+    common_semi_syscall_len = len;
+    return common_semi_gdb_syscall(cs, common_semi_cb, "read,%x,%x,%x",
+                                   gf->hostfd, buf, len);
 }
 
-static uint32_t gdb_isattyfn(ARMCPU *cpu, GuestFD *gf)
+static uint32_t gdb_isattyfn(CPUState *cs, GuestFD *gf)
 {
-    return arm_gdb_syscall(cpu, arm_semi_cb, "isatty,%x", gf->hostfd);
+    return common_semi_gdb_syscall(cs, common_semi_cb, "isatty,%x", gf->hostfd);
 }
 
-static uint32_t gdb_seekfn(ARMCPU *cpu, GuestFD *gf, target_ulong offset)
+static uint32_t gdb_seekfn(CPUState *cs, GuestFD *gf, target_ulong offset)
 {
-    return arm_gdb_syscall(cpu, arm_semi_cb, "lseek,%x,%x,0",
-                           gf->hostfd, offset);
+    return common_semi_gdb_syscall(cs, common_semi_cb, "lseek,%x,%x,0",
+                                   gf->hostfd, offset);
 }
 
-static uint32_t gdb_flenfn(ARMCPU *cpu, GuestFD *gf)
+static uint32_t gdb_flenfn(CPUState *cs, GuestFD *gf)
 {
-    return arm_gdb_syscall(cpu, arm_semi_flen_cb, "fstat,%x,%x",
-                           gf->hostfd, arm_flen_buf(cpu));
+    return common_semi_gdb_syscall(cs, common_semi_flen_cb, "fstat,%x,%x",
+                                   gf->hostfd, common_semi_flen_buf(cs));
 }
 
 #define SHFB_MAGIC_0 0x53
@@ -549,31 +559,29 @@ static void init_featurefile_guestfd(int guestfd)
     gf->featurefile_offset = 0;
 }
 
-static uint32_t featurefile_closefn(ARMCPU *cpu, GuestFD *gf)
+static uint32_t featurefile_closefn(CPUState *cs, GuestFD *gf)
 {
     /* Nothing to do */
     return 0;
 }
 
-static uint32_t featurefile_writefn(ARMCPU *cpu, GuestFD *gf,
+static uint32_t featurefile_writefn(CPUState *cs, GuestFD *gf,
                                     target_ulong buf, uint32_t len)
 {
     /* This fd can never be open for writing */
-    CPUARMState *env = &cpu->env;
 
     errno = EBADF;
-    return set_swi_errno(env, -1);
+    return set_swi_errno(cs, -1);
 }
 
-static uint32_t featurefile_readfn(ARMCPU *cpu, GuestFD *gf,
+static uint32_t featurefile_readfn(CPUState *cs, GuestFD *gf,
                                    target_ulong buf, uint32_t len)
 {
+    CPUArchState *env = cs->env_ptr;
     uint32_t i;
-#ifndef CONFIG_USER_ONLY
-    CPUARMState *env = &cpu->env;
-#endif
     char *s;
 
+    (void) env; /* Used in arm softmmu lock_user implicitly */
     s = lock_user(VERIFY_WRITE, buf, len, 0);
     if (!s) {
         return len;
@@ -593,19 +601,19 @@ static uint32_t featurefile_readfn(ARMCPU *cpu, GuestFD *gf,
     return len - i;
 }
 
-static uint32_t featurefile_isattyfn(ARMCPU *cpu, GuestFD *gf)
+static uint32_t featurefile_isattyfn(CPUState *cs, GuestFD *gf)
 {
     return 0;
 }
 
-static uint32_t featurefile_seekfn(ARMCPU *cpu, GuestFD *gf,
+static uint32_t featurefile_seekfn(CPUState *cs, GuestFD *gf,
                                    target_ulong offset)
 {
     gf->featurefile_offset = offset;
     return 0;
 }
 
-static uint32_t featurefile_flenfn(ARMCPU *cpu, GuestFD *gf)
+static uint32_t featurefile_flenfn(CPUState *cs, GuestFD *gf)
 {
     return sizeof(featurefile_data);
 }
@@ -649,16 +657,17 @@ static const GuestFDFunctions guestfd_fns[] = {
 /* Read the input value from the argument block; fail the semihosting
  * call if the memory read fails.
  */
+#ifdef TARGET_ARM
 #define GET_ARG(n) do {                                 \
     if (is_a64(env)) {                                  \
         if (get_user_u64(arg ## n, args + (n) * 8)) {   \
             errno = EFAULT;                             \
-            return set_swi_errno(env, -1);              \
+            return set_swi_errno(cs, -1);              \
         }                                               \
     } else {                                            \
         if (get_user_u32(arg ## n, args + (n) * 4)) {   \
             errno = EFAULT;                             \
-            return set_swi_errno(env, -1);              \
+            return set_swi_errno(cs, -1);              \
         }                                               \
     }                                                   \
 } while (0)
@@ -667,6 +676,7 @@ static const GuestFDFunctions guestfd_fns[] = {
     (is_a64(env) ?                                      \
      put_user_u64(val, args + (n) * 8) :                \
      put_user_u32(val, args + (n) * 4))
+#endif
 
 /*
  * Do a semihosting call.
@@ -679,8 +689,7 @@ static const GuestFDFunctions guestfd_fns[] = {
  */
 target_ulong do_common_semihosting(CPUState *cs)
 {
-    ARMCPU *cpu = ARM_CPU(cs);
-    CPUARMState *env = &cpu->env;
+    CPUArchState *env = cs->env_ptr;
     target_ulong args;
     target_ulong arg0, arg1, arg2, arg3;
     char * s;
@@ -689,14 +698,9 @@ target_ulong do_common_semihosting(CPUState *cs)
     uint32_t len;
     GuestFD *gf;
 
-    if (is_a64(env)) {
-        /* 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];
-    }
+    (void) env; /* Used implicitly by arm lock_user macro */
+    nr = common_semi_arg(cs, 0) & 0xffffffffU;
+    args = common_semi_arg(cs, 1);
 
     switch (nr) {
     case TARGET_SYS_OPEN:
@@ -709,19 +713,19 @@ target_ulong do_common_semihosting(CPUState *cs)
         s = lock_user_string(arg0);
         if (!s) {
             errno = EFAULT;
-            return set_swi_errno(env, -1);
+            return set_swi_errno(cs, -1);
         }
         if (arg1 >= 12) {
             unlock_user(s, arg0, 0);
             errno = EINVAL;
-            return set_swi_errno(env, -1);
+            return set_swi_errno(cs, -1);
         }
 
         guestfd = alloc_guestfd();
         if (guestfd < 0) {
             unlock_user(s, arg0, 0);
             errno = EMFILE;
-            return set_swi_errno(env, -1);
+            return set_swi_errno(cs, -1);
         }
 
         if (strcmp(s, ":tt") == 0) {
@@ -750,18 +754,18 @@ target_ulong do_common_semihosting(CPUState *cs)
             if (arg1 != 0 && arg1 != 1) {
                 dealloc_guestfd(guestfd);
                 errno = EACCES;
-                return set_swi_errno(env, -1);
+                return set_swi_errno(cs, -1);
             }
             init_featurefile_guestfd(guestfd);
             return guestfd;
         }
 
         if (use_gdb_syscalls()) {
-            arm_semi_open_guestfd = guestfd;
-            ret = arm_gdb_syscall(cpu, arm_semi_open_cb, "open,%s,%x,1a4", arg0,
-                                  (int)arg2+1, gdb_open_modeflags[arg1]);
+            common_semi_open_guestfd = guestfd;
+            ret = common_semi_gdb_syscall(cs, common_semi_open_cb, "open,%s,%x,1a4", arg0,
+                                          (int)arg2+1, gdb_open_modeflags[arg1]);
         } else {
-            ret = set_swi_errno(env, open(s, open_modeflags[arg1], 0644));
+            ret = set_swi_errno(cs, open(s, open_modeflags[arg1], 0644));
             if (ret == (uint32_t)-1) {
                 dealloc_guestfd(guestfd);
             } else {
@@ -778,17 +782,17 @@ target_ulong do_common_semihosting(CPUState *cs)
         gf = get_guestfd(arg0);
         if (!gf) {
             errno = EBADF;
-            return set_swi_errno(env, -1);
+            return set_swi_errno(cs, -1);
         }
 
-        ret = guestfd_fns[gf->type].closefn(cpu, gf);
+        ret = guestfd_fns[gf->type].closefn(cs, gf);
         dealloc_guestfd(arg0);
         return ret;
     case TARGET_SYS_WRITEC:
-        qemu_semihosting_console_outc(env, args);
+        qemu_semihosting_console_outc(cs->env_ptr, args);
         return 0xdeadbeef;
     case TARGET_SYS_WRITE0:
-        return qemu_semihosting_console_outs(env, args);
+        return qemu_semihosting_console_outs(cs->env_ptr, args);
     case TARGET_SYS_WRITE:
         GET_ARG(0);
         GET_ARG(1);
@@ -798,10 +802,10 @@ target_ulong do_common_semihosting(CPUState *cs)
         gf = get_guestfd(arg0);
         if (!gf) {
             errno = EBADF;
-            return set_swi_errno(env, -1);
+            return set_swi_errno(cs, -1);
         }
 
-        return guestfd_fns[gf->type].writefn(cpu, gf, arg1, len);
+        return guestfd_fns[gf->type].writefn(cs, gf, arg1, len);
     case TARGET_SYS_READ:
         GET_ARG(0);
         GET_ARG(1);
@@ -811,22 +815,22 @@ target_ulong do_common_semihosting(CPUState *cs)
         gf = get_guestfd(arg0);
         if (!gf) {
             errno = EBADF;
-            return set_swi_errno(env, -1);
+            return set_swi_errno(cs, -1);
         }
 
-        return guestfd_fns[gf->type].readfn(cpu, gf, arg1, len);
+        return guestfd_fns[gf->type].readfn(cs, gf, arg1, len);
     case TARGET_SYS_READC:
-        return qemu_semihosting_console_inc(env);
+        return qemu_semihosting_console_inc(cs->env_ptr);
     case TARGET_SYS_ISTTY:
         GET_ARG(0);
 
         gf = get_guestfd(arg0);
         if (!gf) {
             errno = EBADF;
-            return set_swi_errno(env, -1);
+            return set_swi_errno(cs, -1);
         }
 
-        return guestfd_fns[gf->type].isattyfn(cpu, gf);
+        return guestfd_fns[gf->type].isattyfn(cs, gf);
     case TARGET_SYS_SEEK:
         GET_ARG(0);
         GET_ARG(1);
@@ -834,20 +838,20 @@ target_ulong do_common_semihosting(CPUState *cs)
         gf = get_guestfd(arg0);
         if (!gf) {
             errno = EBADF;
-            return set_swi_errno(env, -1);
+            return set_swi_errno(cs, -1);
         }
 
-        return guestfd_fns[gf->type].seekfn(cpu, gf, arg1);
+        return guestfd_fns[gf->type].seekfn(cs, gf, arg1);
     case TARGET_SYS_FLEN:
         GET_ARG(0);
 
         gf = get_guestfd(arg0);
         if (!gf) {
             errno = EBADF;
-            return set_swi_errno(env, -1);
+            return set_swi_errno(cs, -1);
         }
 
-        return guestfd_fns[gf->type].flenfn(cpu, gf);
+        return guestfd_fns[gf->type].flenfn(cs, gf);
     case TARGET_SYS_TMPNAM:
         qemu_log_mask(LOG_UNIMP, "%s: SYS_TMPNAM not implemented", __func__);
         return -1;
@@ -855,15 +859,15 @@ target_ulong do_common_semihosting(CPUState *cs)
         GET_ARG(0);
         GET_ARG(1);
         if (use_gdb_syscalls()) {
-            ret = arm_gdb_syscall(cpu, arm_semi_cb, "unlink,%s",
-                                  arg0, (int)arg1+1);
+            ret = common_semi_gdb_syscall(cs, common_semi_cb, "unlink,%s",
+                                          arg0, (int)arg1+1);
         } else {
             s = lock_user_string(arg0);
             if (!s) {
                 errno = EFAULT;
-                return set_swi_errno(env, -1);
+                return set_swi_errno(cs, -1);
             }
-            ret =  set_swi_errno(env, remove(s));
+            ret =  set_swi_errno(cs, remove(s));
             unlock_user(s, arg0, 0);
         }
         return ret;
@@ -873,17 +877,17 @@ target_ulong do_common_semihosting(CPUState *cs)
         GET_ARG(2);
         GET_ARG(3);
         if (use_gdb_syscalls()) {
-            return arm_gdb_syscall(cpu, arm_semi_cb, "rename,%s,%s",
-                                   arg0, (int)arg1+1, arg2, (int)arg3+1);
+            return common_semi_gdb_syscall(cs, common_semi_cb, "rename,%s,%s",
+                                           arg0, (int)arg1+1, arg2, (int)arg3+1);
         } else {
             char *s2;
             s = lock_user_string(arg0);
             s2 = lock_user_string(arg2);
             if (!s || !s2) {
                 errno = EFAULT;
-                ret = set_swi_errno(env, -1);
+                ret = set_swi_errno(cs, -1);
             } else {
-                ret = set_swi_errno(env, rename(s, s2));
+                ret = set_swi_errno(cs, rename(s, s2));
             }
             if (s2)
                 unlock_user(s2, arg2, 0);
@@ -894,25 +898,25 @@ target_ulong do_common_semihosting(CPUState *cs)
     case TARGET_SYS_CLOCK:
         return clock() / (CLOCKS_PER_SEC / 100);
     case TARGET_SYS_TIME:
-        return set_swi_errno(env, time(NULL));
+        return set_swi_errno(cs, time(NULL));
     case TARGET_SYS_SYSTEM:
         GET_ARG(0);
         GET_ARG(1);
         if (use_gdb_syscalls()) {
-            return arm_gdb_syscall(cpu, arm_semi_cb, "system,%s",
-                                   arg0, (int)arg1+1);
+            return common_semi_gdb_syscall(cs, common_semi_cb, "system,%s",
+                                           arg0, (int)arg1+1);
         } else {
             s = lock_user_string(arg0);
             if (!s) {
                 errno = EFAULT;
-                return set_swi_errno(env, -1);
+                return set_swi_errno(cs, -1);
             }
-            ret = set_swi_errno(env, system(s));
+            ret = set_swi_errno(cs, system(s));
             unlock_user(s, arg0, 0);
             return ret;
         }
     case TARGET_SYS_ERRNO:
-        return get_swi_errno(env);
+        return get_swi_errno(cs);
     case TARGET_SYS_GET_CMDLINE:
         {
             /* Build a command-line from the original argv.
@@ -964,21 +968,21 @@ target_ulong do_common_semihosting(CPUState *cs)
             if (output_size > input_size) {
                 /* Not enough space to store command-line arguments.  */
                 errno = E2BIG;
-                return set_swi_errno(env, -1);
+                return set_swi_errno(cs, -1);
             }
 
             /* Adjust the command-line length.  */
             if (SET_ARG(1, output_size - 1)) {
                 /* Couldn't write back to argument block */
                 errno = EFAULT;
-                return set_swi_errno(env, -1);
+                return set_swi_errno(cs, -1);
             }
 
             /* Lock the buffer on the ARM side.  */
             output_buffer = lock_user(VERIFY_WRITE, arg0, output_size, 0);
             if (!output_buffer) {
                 errno = EFAULT;
-                return set_swi_errno(env, -1);
+                return set_swi_errno(cs, -1);
             }
 
             /* Copy the command-line arguments.  */
@@ -994,7 +998,7 @@ target_ulong do_common_semihosting(CPUState *cs)
             if (copy_from_user(output_buffer, ts->info->arg_start,
                                output_size)) {
                 errno = EFAULT;
-                status = set_swi_errno(env, -1);
+                status = set_swi_errno(cs, -1);
                 goto out;
             }
 
@@ -1031,7 +1035,7 @@ target_ulong do_common_semihosting(CPUState *cs)
                 abi_ulong ret;
 
                 ts->heap_base = do_brk(0);
-                limit = ts->heap_base + ARM_ANGEL_HEAP_SIZE;
+                limit = ts->heap_base + COMMON_SEMI_HEAP_SIZE;
                 /* Try a big heap, and reduce the size if that fails.  */
                 for (;;) {
                     ret = do_brk(limit);
@@ -1059,23 +1063,19 @@ target_ulong do_common_semihosting(CPUState *cs)
             for (i = 0; i < ARRAY_SIZE(retvals); i++) {
                 bool fail;
 
-                if (is_a64(env)) {
-                    fail = put_user_u64(retvals[i], arg0 + i * 8);
-                } else {
-                    fail = put_user_u32(retvals[i], arg0 + i * 4);
-                }
+                fail = SET_ARG(i, retvals[i]);
 
                 if (fail) {
                     /* Couldn't write back to argument block */
                     errno = EFAULT;
-                    return set_swi_errno(env, -1);
+                    return set_swi_errno(cs, -1);
                 }
             }
             return 0;
         }
     case TARGET_SYS_EXIT:
     case TARGET_SYS_EXIT_EXTENDED:
-        if (nr == TARGET_SYS_EXIT_EXTENDED || is_a64(env)) {
+        if (common_semi_sys_exit_extended(cs, nr)) {
             /*
              * The A64 version of SYS_EXIT takes a parameter block,
              * so the application-exit type can return a subcode which
@@ -1100,7 +1100,7 @@ target_ulong do_common_semihosting(CPUState *cs)
              */
             ret = (args == ADP_Stopped_ApplicationExit) ? 0 : 1;
         }
-        gdb_exit(env, ret);
+        gdb_exit(cs->env_ptr, ret);
         exit(ret);
     case TARGET_SYS_SYNCCACHE:
         /*
@@ -1108,9 +1108,11 @@ target_ulong do_common_semihosting(CPUState *cs)
          * virtual address range. This is a nop for us since we don't
          * implement caches. This is only present on A64.
          */
-        if (is_a64(env)) {
+#ifdef TARGET_ARM
+        if (is_a64(cs->env_ptr)) {
             return 0;
         }
+#endif
         /* fall through -- invalid for A32/T32 */
     default:
         fprintf(stderr, "qemu: Unsupported SemiHosting SWI 0x%02x\n", nr);
-- 
2.28.0



^ permalink raw reply related	[flat|nested] 32+ messages in thread

end of thread, other threads:[~2020-11-11 22:56 UTC | newest]

Thread overview: 32+ messages (download: mbox.gz / follow: Atom feed)
-- links below jump to the message on this page --
2020-10-26 21:28 [PATCH 0/4] riscv: Add semihosting support [v10] Keith Packard via
2020-10-26 21:28 ` Keith Packard
2020-10-26 21:28 ` [PATCH 1/4] semihosting: Move ARM semihosting code to shared directories Keith Packard via
2020-10-26 21:28   ` Keith Packard
2020-10-27 20:32   ` Alistair Francis
2020-10-27 20:32     ` Alistair Francis
2020-10-27 21:20   ` Peter Maydell
2020-10-27 21:20     ` Peter Maydell
2020-10-27 21:56     ` Keith Packard via
2020-10-27 21:56       ` Keith Packard
2020-10-27 23:38       ` Peter Maydell
2020-10-27 23:38         ` Peter Maydell
2020-10-28  1:33         ` Keith Packard via
2020-10-28  1:33           ` Keith Packard
     [not found]           ` <87lffqmwi6.fsf@linaro.org>
2020-10-28 15:37             ` Keith Packard via
2020-10-28 15:37               ` Keith Packard
2020-10-28 19:14             ` Keith Packard via
2020-10-28 19:14               ` Keith Packard
2020-10-26 21:28 ` [PATCH 2/4] semihosting: Change common-semi API to be architecture-independent Keith Packard via
2020-10-26 21:28   ` Keith Packard
2020-10-26 21:28 ` [PATCH 3/4] semihosting: Change internal common-semi interfaces to use CPUState * Keith Packard via
2020-10-26 21:28   ` Keith Packard
2020-10-26 21:28 ` [PATCH 4/4] riscv: Add semihosting support [v10] Keith Packard via
2020-10-26 21:28   ` Keith Packard
2020-10-26 21:42 ` [PATCH 0/4] " no-reply
2020-10-26 21:42   ` no-reply
2020-10-28 18:57 [PATCH 0/4] Add RISC-V semihosting support Keith Packard via
2020-10-28 18:57 ` [PATCH 3/4] semihosting: Change internal common-semi interfaces to use CPUState * Keith Packard via
2020-10-28 18:57   ` Keith Packard
2020-11-11 22:29   ` Alistair Francis
2020-11-11 22:29     ` Alistair Francis
2020-11-11 22:55     ` Keith Packard via
2020-11-11 22:55       ` Keith Packard

This is an external index of several public inboxes,
see mirroring instructions on how to clone and mirror
all data and code used by this external index.