qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[RFC PATCH v3 1/5] ppc64: Add semihosting support


From: Leandro Lupori
Subject: [RFC PATCH v3 1/5] ppc64: Add semihosting support
Date: Mon, 18 Apr 2022 16:10:56 -0300

Add semihosting support for PPC64. This implementation is
based on the standard for ARM semihosting version 2.0, as
implemented by QEMU and documented in

    https://github.com/ARM-software/abi-aa/releases

The PPC64 specific differences are the following:

Semihosting Trap Instruction: sc 7
Operation Number Register: r3
Parameter Register: r4
Return Register: r3
Data block field size: 64 bits

Signed-off-by: Leandro Lupori <leandro.lupori@eldorado.org.br>
---
 configs/devices/ppc64-softmmu/default.mak |  3 +++
 qemu-options.hx                           | 18 ++++++++-----
 semihosting/arm-compat-semi.c             | 33 +++++++++++++++++++++++
 target/ppc/cpu.h                          |  3 ++-
 target/ppc/excp_helper.c                  |  9 +++++++
 target/ppc/translate.c                    | 14 ++++++++++
 6 files changed, 72 insertions(+), 8 deletions(-)

diff --git a/configs/devices/ppc64-softmmu/default.mak 
b/configs/devices/ppc64-softmmu/default.mak
index b90e5bf455..43b618fa32 100644
--- a/configs/devices/ppc64-softmmu/default.mak
+++ b/configs/devices/ppc64-softmmu/default.mak
@@ -8,3 +8,6 @@ CONFIG_POWERNV=y
 
 # For pSeries
 CONFIG_PSERIES=y
+
+CONFIG_SEMIHOSTING=y
+CONFIG_ARM_COMPATIBLE_SEMIHOSTING=y
diff --git a/qemu-options.hx b/qemu-options.hx
index 34e9b32a5c..6e76f7de96 100644
--- a/qemu-options.hx
+++ b/qemu-options.hx
@@ -4527,11 +4527,12 @@ SRST
 ERST
 DEF("semihosting", 0, QEMU_OPTION_semihosting,
     "-semihosting    semihosting mode\n",
-    QEMU_ARCH_ARM | QEMU_ARCH_M68K | QEMU_ARCH_XTENSA |
-    QEMU_ARCH_MIPS | QEMU_ARCH_NIOS2 | QEMU_ARCH_RISCV)
+    QEMU_ARCH_ARM | QEMU_ARCH_M68K | QEMU_ARCH_XTENSA | QEMU_ARCH_MIPS |
+    QEMU_ARCH_NIOS2 | QEMU_ARCH_RISCV | QEMU_ARCH_PPC)
 SRST
 ``-semihosting``
-    Enable semihosting mode (ARM, M68K, Xtensa, MIPS, Nios II, RISC-V only).
+    Enable semihosting mode (ARM, M68K, Xtensa, MIPS, Nios II, RISC-V and
+    PPC only).
 
     Note that this allows guest direct access to the host filesystem, so
     should only be used with a trusted guest OS.
@@ -4542,12 +4543,12 @@ ERST
 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_MIPS | QEMU_ARCH_NIOS2 | QEMU_ARCH_RISCV)
+QEMU_ARCH_ARM | QEMU_ARCH_M68K | QEMU_ARCH_XTENSA | QEMU_ARCH_MIPS |
+QEMU_ARCH_NIOS2 | QEMU_ARCH_RISCV | QEMU_ARCH_PPC)
 SRST
 ``-semihosting-config 
[enable=on|off][,target=native|gdb|auto][,chardev=id][,arg=str[,...]]``
-    Enable and configure semihosting (ARM, M68K, Xtensa, MIPS, Nios II, RISC-V
-    only).
+    Enable and configure semihosting (ARM, M68K, Xtensa, MIPS, Nios II,
+    RISC-V, PPC only).
 
     Note that this allows guest direct access to the host filesystem, so
     should only be used with a trusted guest OS.
@@ -4563,6 +4564,9 @@ SRST
 
     On RISC-V this implements the standard semihosting API, version 0.2.
 
+    On PPC this implements the standard Arm semihosting API, version 2.0,
+    with only the trap instruction and register definitions changed.
+
     ``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/semihosting/arm-compat-semi.c b/semihosting/arm-compat-semi.c
index 7a51fd0737..e1279c316c 100644
--- a/semihosting/arm-compat-semi.c
+++ b/semihosting/arm-compat-semi.c
@@ -268,6 +268,31 @@ common_semi_sys_exit_extended(CPUState *cs, int nr)
 
 #endif
 
+#ifdef TARGET_PPC64
+static inline target_ulong
+common_semi_arg(CPUState *cs, int argno)
+{
+    PowerPCCPU *cpu = POWERPC_CPU(cs);
+    CPUPPCState *env = &cpu->env;
+    return env->gpr[3 + argno];
+}
+
+static inline void
+common_semi_set_ret(CPUState *cs, target_ulong ret)
+{
+    PowerPCCPU *cpu = POWERPC_CPU(cs);
+    CPUPPCState *env = &cpu->env;
+    env->gpr[3] = ret;
+}
+
+static inline bool
+common_semi_sys_exit_extended(CPUState *cs, int nr)
+{
+    return (nr == TARGET_SYS_EXIT_EXTENDED || sizeof(target_ulong) == 8);
+}
+
+#endif
+
 /*
  * Allocate a new guest file descriptor and return it; if we
  * couldn't allocate a new fd then return -1.
@@ -450,6 +475,12 @@ static target_ulong common_semi_flen_buf(CPUState *cs)
 
     sp = env->gpr[xSP];
 #endif
+#ifdef TARGET_PPC64
+    PowerPCCPU *cpu = POWERPC_CPU(cs);
+    CPUPPCState *env = &cpu->env;
+
+    sp = env->gpr[1];
+#endif
 
     return sp - 64;
 }
@@ -780,6 +811,8 @@ static inline bool is_64bit_semihosting(CPUArchState *env)
     return is_a64(env);
 #elif defined(TARGET_RISCV)
     return riscv_cpu_mxl(env) != MXL_RV32;
+#elif defined(TARGET_PPC64)
+    return true;
 #else
 #error un-handled architecture
 #endif
diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index 047b24ba50..349104ad79 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -129,8 +129,9 @@ enum {
     POWERPC_EXCP_SYSCALL_VECTORED = 102, /* scv exception                     
*/
     POWERPC_EXCP_PERFM_EBB = 103,    /* Performance Monitor EBB Exception    */
     POWERPC_EXCP_EXTERNAL_EBB = 104, /* External EBB Exception               */
+    POWERPC_EXCP_SEMIHOST = 105,     /* Semihosting Exception                */
     /* EOL                                                                   */
-    POWERPC_EXCP_NB       = 105,
+    POWERPC_EXCP_NB       = 106,
     /* QEMU exceptions: special cases we want to stop translation            */
     POWERPC_EXCP_SYSCALL_USER = 0x203, /* System call in user mode only      */
 };
diff --git a/target/ppc/excp_helper.c b/target/ppc/excp_helper.c
index d3e2cfcd71..af34a57082 100644
--- a/target/ppc/excp_helper.c
+++ b/target/ppc/excp_helper.c
@@ -25,6 +25,7 @@
 #include "helper_regs.h"
 
 #include "trace.h"
+#include "semihosting/common-semi.h"
 
 #ifdef CONFIG_TCG
 #include "exec/helper-proto.h"
@@ -100,6 +101,7 @@ static const char *powerpc_excp_name(int excp)
     case POWERPC_EXCP_SDOOR_HV: return "SDOOR_HV";
     case POWERPC_EXCP_HVIRT:    return "HVIRT";
     case POWERPC_EXCP_SYSCALL_VECTORED: return "SYSCALL_VECTORED";
+    case POWERPC_EXCP_SEMIHOST: return "SEMIHOST";
     default:
         g_assert_not_reached();
     }
@@ -1327,6 +1329,13 @@ static void powerpc_excp_books(PowerPCCPU *cpu, int excp)
     target_ulong msr, new_msr, vector;
     int srr0, srr1, lev = -1;
 
+    /* Handle semihost exceptions first */
+    if (excp == POWERPC_EXCP_SEMIHOST) {
+        env->gpr[3] = do_common_semihosting(cs);
+        env->nip += 4;
+        return;
+    }
+
     /* new srr1 value excluding must-be-zero bits */
     msr = env->msr & ~0x783f0000ULL;
 
diff --git a/target/ppc/translate.c b/target/ppc/translate.c
index 408ae26173..c013889a84 100644
--- a/target/ppc/translate.c
+++ b/target/ppc/translate.c
@@ -4520,6 +4520,20 @@ static void gen_sc(DisasContext *ctx)
     uint32_t lev;
 
     lev = (ctx->opcode >> 5) & 0x7F;
+
+#if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY)
+    /*
+     * PowerPC semihosting uses the following
+     * instruction to flag a semihosting call:
+     *
+     *      sc 7            0x440000e2
+     */
+    if (lev == 7) {
+        gen_exception(ctx, POWERPC_EXCP_SEMIHOST);
+        return;
+    }
+#endif
+
     gen_exception_err(ctx, POWERPC_SYSCALL, lev);
 }
 
-- 
2.25.1




reply via email to

[Prev in Thread] Current Thread [Next in Thread]