For OpenRISC we currently only use semihosting for system exit and reset. This patch implements that.
The implementation uses a helper to delegate to the semihosting facility. The helper is marked as having side effects but currently does not have any. I have defined it like this as our other unimplemented semihosting calls will have side effects and return results in register r11. Signed-off-by: Stafford Horne <sho...@gmail.com> --- configs/devices/or1k-softmmu/default.mak | 2 + qemu-options.hx | 16 ++++--- target/openrisc/cpu.h | 2 + target/openrisc/helper.h | 1 + target/openrisc/meson.build | 1 + target/openrisc/openrisc-semi.c | 54 ++++++++++++++++++++++++ target/openrisc/sys_helper.c | 5 +++ target/openrisc/translate.c | 6 +++ 8 files changed, 82 insertions(+), 5 deletions(-) create mode 100644 target/openrisc/openrisc-semi.c diff --git a/configs/devices/or1k-softmmu/default.mak b/configs/devices/or1k-softmmu/default.mak index 168101c39a..5b3ac89491 100644 --- a/configs/devices/or1k-softmmu/default.mak +++ b/configs/devices/or1k-softmmu/default.mak @@ -1,5 +1,7 @@ # Default configuration for or1k-softmmu +CONFIG_SEMIHOSTING=y + # Boards: # CONFIG_OR1K_SIM=y diff --git a/qemu-options.hx b/qemu-options.hx index b484640067..312c68b065 100644 --- a/qemu-options.hx +++ b/qemu-options.hx @@ -4566,10 +4566,12 @@ 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_MIPS | QEMU_ARCH_NIOS2 | QEMU_ARCH_RISCV | + QEMU_ARCH_OPENRISC) 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, + OpenRISC only). Note that this allows guest direct access to the host filesystem, so should only be used with a trusted guest OS. @@ -4581,11 +4583,12 @@ 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_MIPS | QEMU_ARCH_NIOS2 | QEMU_ARCH_RISCV | +QEMU_ARCH_OPENRISC) 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, + OpenRISC only). Note that this allows guest direct access to the host filesystem, so should only be used with a trusted guest OS. @@ -4601,6 +4604,9 @@ SRST On RISC-V this implements the standard semihosting API, version 0.2. + On OpenRISC this only supports providing simulation exit and reset + facilities. + ``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/openrisc/cpu.h b/target/openrisc/cpu.h index b9584f10d4..4617f1272b 100644 --- a/target/openrisc/cpu.h +++ b/target/openrisc/cpu.h @@ -407,4 +407,6 @@ void cpu_set_fpcsr(CPUOpenRISCState *env, uint32_t val); #define CPU_INTERRUPT_TIMER CPU_INTERRUPT_TGT_INT_0 +void do_or1k_semihosting(CPUOpenRISCState *env, uint32_t k); + #endif /* OPENRISC_CPU_H */ diff --git a/target/openrisc/helper.h b/target/openrisc/helper.h index d847814a28..2fe3e4e4ca 100644 --- a/target/openrisc/helper.h +++ b/target/openrisc/helper.h @@ -64,3 +64,4 @@ DEF_HELPER_FLAGS_1(rfe, 0, void, env) /* sys */ DEF_HELPER_FLAGS_3(mtspr, 0, void, env, tl, tl) DEF_HELPER_FLAGS_3(mfspr, TCG_CALL_NO_WG, tl, env, tl, tl) +DEF_HELPER_FLAGS_2(nop, 0, void, env, i32) diff --git a/target/openrisc/meson.build b/target/openrisc/meson.build index 84322086ec..1c1758b846 100644 --- a/target/openrisc/meson.build +++ b/target/openrisc/meson.build @@ -10,6 +10,7 @@ openrisc_ss.add(files( 'fpu_helper.c', 'gdbstub.c', 'interrupt_helper.c', + 'openrisc-semi.c', 'sys_helper.c', 'translate.c', )) diff --git a/target/openrisc/openrisc-semi.c b/target/openrisc/openrisc-semi.c new file mode 100644 index 0000000000..97d6aaacdb --- /dev/null +++ b/target/openrisc/openrisc-semi.c @@ -0,0 +1,54 @@ +/* + * OpenRISC Semihosting syscall interface. + * + * Copyright (c) 2022 Stafford Horne + * + * 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/>. + */ + +#include "qemu/osdep.h" + +#include "cpu.h" +#include "exec/gdbstub.h" +#include "sysemu/runstate.h" +#include "qemu/log.h" + +#define HOSTED_EXIT 1 +#define HOSTED_RESET 13 + +static void or1k_semi_return_u32(CPUOpenRISCState *env, uint32_t ret) +{ + cpu_set_gpr(env, 11, ret); +} + +void do_or1k_semihosting(CPUOpenRISCState *env, uint32_t k) +{ + uint32_t result; + + switch (k) { + case HOSTED_EXIT: + gdb_exit(cpu_get_gpr(env, 3)); + exit(cpu_get_gpr(env, 3)); + case HOSTED_RESET: +#ifndef CONFIG_USER_ONLY + qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET); + return; +#endif + default: + qemu_log_mask(LOG_GUEST_ERROR, "or1k-semihosting: unsupported " + "semihosting syscall %d\n", k); + result = 0; + } + or1k_semi_return_u32(env, result); +} diff --git a/target/openrisc/sys_helper.c b/target/openrisc/sys_helper.c index 48674231e7..eb698a527e 100644 --- a/target/openrisc/sys_helper.c +++ b/target/openrisc/sys_helper.c @@ -314,3 +314,8 @@ target_ulong HELPER(mfspr)(CPUOpenRISCState *env, target_ulong rd, /* for rd is passed in, if rd unchanged, just keep it back. */ return rd; } + +void HELPER(nop)(CPUOpenRISCState *env, target_ulong k) +{ + do_or1k_semihosting(env, k); +} diff --git a/target/openrisc/translate.c b/target/openrisc/translate.c index 7b8ad43d5f..ec7b3b46ad 100644 --- a/target/openrisc/translate.c +++ b/target/openrisc/translate.c @@ -28,6 +28,7 @@ #include "qemu/qemu-print.h" #include "exec/cpu_ldst.h" #include "exec/translator.h" +#include "semihosting/semihost.h" #include "exec/helper-proto.h" #include "exec/helper-gen.h" @@ -780,6 +781,11 @@ static bool trans_l_sh(DisasContext *dc, arg_store *a) static bool trans_l_nop(DisasContext *dc, arg_l_nop *a) { + if (semihosting_enabled() && + a->k != 0) { + gen_helper_nop(cpu_env, tcg_constant_i32(a->k)); + } + return true; } -- 2.31.1