All of lore.kernel.org
 help / color / mirror / Atom feed
From: Brian Cain <brian.cain@oss.qualcomm.com>
To: Matheus Tavares Bernardino <matheus.bernardino@oss.qualcomm.com>,
	qemu-devel@nongnu.org
Cc: pierrick.bouvier@oss.qualcomm.com, marco.liebel@oss.qualcomm.com,
	philmd@oss.qualcomm.com, ale@rev.ng, anjo@rev.ng,
	Paolo Bonzini <pbonzini@redhat.com>
Subject: Re: [PATCH v3 07/13] target/hexagon: add semihosting support
Date: Sun, 16 Aug 2026 23:11:05 -0500	[thread overview]
Message-ID: <dd38b8ea-7af6-499c-93cb-9f93c1c03e4b@oss.qualcomm.com> (raw)
In-Reply-To: <0c46c3d9cf8215dc9249a8a583bad3eacad47639.1784568922.git.matheus.bernardino@oss.qualcomm.com>


On 7/20/2026 12:41 PM, Matheus Tavares Bernardino wrote:
> Baremetal Hexagon programs use trap0 #0 to invoke
> semihosting calls for I/O and process control.  Wire up the
> arm-compatible semihosting framework for softmmu by enabling
> CONFIG_ARM_COMPATIBLE_SEMIHOSTING and routing trap0 to the
> semihosting handler.
>
> Signed-off-by: Brian Cain <brian.cain@oss.qualcomm.com>
> Reviewed-by: Pierrick Bouvier <pierrick.bouvier@oss.qualcomm.com>
> Signed-off-by: Matheus Tavares Bernardino <matheus.bernardino@oss.qualcomm.com>
> ---

Reviewed-by: Brian Cain <brian.cain@oss.qualcomm.com>

>   docs/system/target-hexagon.rst      |   8 +-
>   configs/targets/hexagon-softmmu.mak |   2 +
>   hw/hexagon/hexagon_dsp.c            |   2 +
>   target/hexagon/common-semi-target.c |  51 +++++++++
>   target/hexagon/hexswi.c             | 167 +++++++++++++++++++++++++++-
>   hw/hexagon/Kconfig                  |   1 +
>   qemu-options.hx                     |   8 +-
>   target/hexagon/meson.build          |   3 +
>   8 files changed, 232 insertions(+), 10 deletions(-)
>   create mode 100644 target/hexagon/common-semi-target.c
>
> diff --git a/docs/system/target-hexagon.rst b/docs/system/target-hexagon.rst
> index 416b8f7be76..a9f8c29810e 100644
> --- a/docs/system/target-hexagon.rst
> +++ b/docs/system/target-hexagon.rst
> @@ -91,9 +91,11 @@ Semihosting
>   -----------
>   Hexagon supports a semihosting interface similar to other architectures'.
>   The ``trap0`` instruction can activate these semihosting calls so that the
> -guest software can access the host console and filesystem.  Semihosting
> -is not yet implemented in QEMU hexagon.
> -
> +guest software can access the host console and filesystem. Read the
> +`Hexagon Semihosting Specification
> +<https://docs.qualcomm.com/doc/80-N2040-101_102648/topic/semihosting-specification.html>`__
> +for details. Semihosting is enabled by default on hexagon-sim-compatible
> +machines. This can be further configured through ``-semihosting-config``.
>   
>   Hexagon Features
>   ================
> diff --git a/configs/targets/hexagon-softmmu.mak b/configs/targets/hexagon-softmmu.mak
> index a77c100f0c5..6cbdc64be56 100644
> --- a/configs/targets/hexagon-softmmu.mak
> +++ b/configs/targets/hexagon-softmmu.mak
> @@ -6,3 +6,5 @@ TARGET_LONG_BITS=32
>   TARGET_NOT_USING_LEGACY_LDST_PHYS_API=y
>   TARGET_NOT_USING_LEGACY_NATIVE_ENDIAN_API=y
>   TARGET_NEED_FDT=y
> +CONFIG_SEMIHOSTING=y
> +CONFIG_ARM_COMPATIBLE_SEMIHOSTING=y
> diff --git a/hw/hexagon/hexagon_dsp.c b/hw/hexagon/hexagon_dsp.c
> index aa493993229..315733cded3 100644
> --- a/hw/hexagon/hexagon_dsp.c
> +++ b/hw/hexagon/hexagon_dsp.c
> @@ -27,6 +27,7 @@
>   #include "target/hexagon/internal.h"
>   #include "system/physmem.h"
>   #include "system/reset.h"
> +#include "semihosting/semihost.h"
>   
>   #include "machine_cfg_v66g_1024.h.inc"
>   
> @@ -178,6 +179,7 @@ static void init_mc(MachineClass *mc)
>       mc->no_serial = 1;
>       mc->is_default = false;
>       mc->max_cpus = 8;
> +    qemu_semihosting_enable();
>   }
>   
>   /* ----------------------------------------------------------------- */
> diff --git a/target/hexagon/common-semi-target.c b/target/hexagon/common-semi-target.c
> new file mode 100644
> index 00000000000..9a7720514bb
> --- /dev/null
> +++ b/target/hexagon/common-semi-target.c
> @@ -0,0 +1,51 @@
> +/*
> + * Target-specific parts of semihosting/arm-compat-semi.c.
> + *
> + * Copyright (c) Qualcomm Technologies, Inc. and/or its subsidiaries.
> + *
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + */
> +
> +#include "qemu/osdep.h"
> +#include "cpu.h"
> +#include "cpu_helper.h"
> +#include "semihosting/common-semi.h"
> +
> +uint64_t common_semi_arg(CPUState *cs, int argno)
> +{
> +    CPUHexagonState *env = cpu_env(cs);
> +    return arch_get_thread_reg(env, HEX_REG_R00 + argno);
> +}
> +
> +void common_semi_set_ret(CPUState *cs, uint64_t ret)
> +{
> +    CPUHexagonState *env = cpu_env(cs);
> +    arch_set_thread_reg(env, HEX_REG_R00, ret);
> +}
> +
> +void common_semi_set_err(CPUState *cs, int err)
> +{
> +    CPUHexagonState *env = cpu_env(cs);
> +    arch_set_thread_reg(env, HEX_REG_R01, err);
> +}
> +
> +bool common_semi_sys_exit_is_extended(CPUState *cs)
> +{
> +    return false;
> +}
> +
> +bool is_64bit_semihosting(CPUArchState *env)
> +{
> +    return false;
> +}
> +
> +uint64_t common_semi_stack_bottom(CPUState *cs)
> +{
> +    CPUHexagonState *env = cpu_env(cs);
> +    return arch_get_thread_reg(env, HEX_REG_SP);
> +}
> +
> +bool common_semi_has_synccache(CPUArchState *env)
> +{
> +    return false;
> +}
> diff --git a/target/hexagon/hexswi.c b/target/hexagon/hexswi.c
> index 43c373ea2ee..2aedd8368e2 100644
> --- a/target/hexagon/hexswi.c
> +++ b/target/hexagon/hexswi.c
> @@ -24,9 +24,171 @@
>   #error "This file is only used in system emulation"
>   #endif
>   
> +#include "semihosting/common-semi.h"
> +#include "semihosting/console.h"
> +#include "semihosting/syscalls.h"
> +#include "semihosting/guestfd.h"
> +#include "system/runstate.h"
> +
> +/* non-arm-compatible semihosting calls */
> +#define HEXAGON_SPECIFIC_SWI_FLAGS \
> +    DEF_SWI_FLAG(OPEN,             0x01) \
> +    DEF_SWI_FLAG(ISTTY,            0x09) \
> +    DEF_SWI_FLAG(HEAPINFO,         0x16) \
> +    DEF_SWI_FLAG(EXCEPTION,        0x18) \
> +    DEF_SWI_FLAG(SEEK,             0x0A) \
> +    DEF_SWI_FLAG(READ_CYCLES,      0x40) \
> +    DEF_SWI_FLAG(PROF_ON,          0x41) \
> +    DEF_SWI_FLAG(PROF_OFF,         0x42) \
> +    DEF_SWI_FLAG(WRITECREG,        0x43) \
> +    DEF_SWI_FLAG(READ_TCYCLES,     0x44) \
> +    DEF_SWI_FLAG(LOG_EVENT,        0x45) \
> +    DEF_SWI_FLAG(REDRAW,           0x46) \
> +    DEF_SWI_FLAG(READ_ICOUNT,      0x47) \
> +    DEF_SWI_FLAG(PROF_STATSRESET,  0x48) \
> +    DEF_SWI_FLAG(DUMP_PMU_STATS,   0x4a) \
> +    DEF_SWI_FLAG(READ_PCYCLES,     0x52) \
> +    DEF_SWI_FLAG(COREDUMP,         0xCD) \
> +    DEF_SWI_FLAG(FTELL,            0x100) \
> +    DEF_SWI_FLAG(FSTAT,            0x101) \
> +    DEF_SWI_FLAG(STAT,             0x103) \
> +    DEF_SWI_FLAG(GETCWD,           0x104) \
> +    DEF_SWI_FLAG(ACCESS,           0x105) \
> +    DEF_SWI_FLAG(OPENDIR,          0x180) \
> +    DEF_SWI_FLAG(CLOSEDIR,         0x181) \
> +    DEF_SWI_FLAG(READDIR,          0x182) \
> +    DEF_SWI_FLAG(EXEC,             0x185) \
> +    DEF_SWI_FLAG(FTRUNC,           0x186)
> +
> +/*
> + * We use the arm-compatible semihosting routines for these ones, but we do
> + * need some hexagon-specific preprocessing.
> + */
> +#define HEX_SYS_WRITE       0x05
> +#define HEX_SYS_READ        0x06
> +#define HEX_SYS_READC       0x07
> +
> +#define DEF_SWI_FLAG(name, val) HEX_SYS_ ##name = val,
> +enum hex_swi_flag {
> +    HEXAGON_SPECIFIC_SWI_FLAGS
> +};
> +#undef DEF_SWI_FLAG
> +
> +#define DEF_SWI_FLAG(_, val) case val:
> +static inline bool is_hexagon_specific_swi_flag(enum hex_swi_flag what_swi)
> +{
> +    switch (what_swi) {
> +    HEXAGON_SPECIFIC_SWI_FLAGS
> +        return true;
> +    }
> +    return false;
> +}
> +#undef DEF_SWI_FLAG
> +
> +static void init_semihosting_guestfds(void)
> +{
> +    static gsize initialized;
> +
> +    if (g_once_init_enter(&initialized)) {
> +        if (qemu_semihosting_console_has_chardev()) {
> +            alloc_guestfd();
> +            console_guestfd(0);
> +            alloc_guestfd();
> +            console_guestfd(1);
> +            alloc_guestfd();
> +            console_guestfd(2);
> +        } else {
> +            alloc_guestfd();
> +            associate_guestfd(0, 0);
> +            alloc_guestfd();
> +            associate_guestfd(1, 1);
> +            alloc_guestfd();
> +            associate_guestfd(2, 2);
> +        }
> +        g_once_init_leave(&initialized, 1);
> +    }
> +}
> +
> +static void do_preload(CPUHexagonState *env, target_ulong swi_info, bool load)
> +{
> +    uint32_t addr, count;
> +    uintptr_t retaddr = 0;
> +
> +    hexagon_read_memory(env, swi_info + 4, 4, &addr, retaddr);
> +    hexagon_read_memory(env, swi_info + 8, 4, &count, retaddr);
> +    hexagon_peek_memory_range(env, addr, count, retaddr);
> +}
> +
> +static void sim_handle_trap0(CPUHexagonState *env)
> +{
> +    target_ulong what_swi, swi_info;
> +    CPUState *cs = env_cpu(env);
> +
> +    g_assert(bql_locked());
> +    init_semihosting_guestfds();
> +
> +    what_swi = arch_get_thread_reg(env, HEX_REG_R00);
> +    swi_info = arch_get_thread_reg(env, HEX_REG_R01);
> +
> +    qemu_log_mask(CPU_LOG_INT,
> +                  "sim_handle_trap0: swi=0x%" PRIx32
> +                  " info=0x%" PRIx32 " PC=0x%" PRIx32
> +                  " thread=%" PRId32 "\n",
> +                  (uint32_t)what_swi, (uint32_t)swi_info,
> +                  (uint32_t)arch_get_thread_reg(env, HEX_REG_PC),
> +                  (uint32_t)env->threadId);
> +
> +    if (!is_hexagon_specific_swi_flag(what_swi)) {
> +        if (what_swi == HEX_SYS_READ || what_swi == HEX_SYS_READC ||
> +            what_swi == HEX_SYS_WRITE) {
> +            /*
> +             * Avoid page faults if the buffer is not in memory yet.
> +             * NOTE: Counterintuitive, but a WRITE must be able to LOAD from
> +             * the input address. The contents of that buffer will be
> +             * directed to the SWI interface.
> +             */
> +            do_preload(env, swi_info, (what_swi == HEX_SYS_WRITE));
> +        }
> +        /*
> +         * ARM-compat semihosting SWI numbers are all <= 0x31.
> +         * If R0 holds a value outside that range (e.g. guest code
> +         * executing trap0(#0) with an arbitrary R0), treat it as an
> +         * unrecognized request rather than forwarding to
> +         * do_common_semihosting() which would abort.
> +         */
> +        if (what_swi > 0x31) {
> +            qemu_log_mask(LOG_UNIMP,
> +                          "trap0(#0): unrecognized request in r0: "
> +                          "0x" TARGET_FMT_lx "\n", what_swi);
> +            return;
> +        }
> +        do_common_semihosting(cs);
> +        return;
> +    }
> +
> +    switch (what_swi) {
> +
> +    case HEX_SYS_EXCEPTION:
> +    {
> +        uint32_t ret = arch_get_thread_reg(env, HEX_REG_R02);
> +        arch_set_system_reg(env, HEX_SREG_MODECTL, 0);
> +        gdb_exit(ret);
> +        exit(ret);
> +    }
> +    break;
> +
> +    /* TODO: implement other hexagon-specific semihosting calls */
> +
> +    default:
> +        qemu_log_mask(LOG_GUEST_ERROR,
> +                      "unknown swi request: 0x%" PRIx32 "\n",
> +                      (uint32_t)what_swi);
> +        common_semi_cb(cs, -1, ENOSYS);
> +    }
> +}
> +
>   static void set_addresses(CPUHexagonState *env, uint32_t pc_offset,
>                             uint32_t exception_index)
> -
>   {
>       HexagonCPU *cpu = env_archcpu(env);
>       uint32_t evb = cpu->globalregs ?
> @@ -95,8 +257,7 @@ void hexagon_cpu_do_interrupt(CPUState *cs)
>       switch (cs->exception_index) {
>       case HEX_EVENT_TRAP0:
>           if (env->cause_code == 0) {
> -            qemu_log_mask(LOG_UNIMP,
> -                          "trap0 is unhandled, no semihosting available\n");
> +            sim_handle_trap0(env);
>           }
>   
>           hexagon_ssr_set_cause(env, env->cause_code);
> diff --git a/hw/hexagon/Kconfig b/hw/hexagon/Kconfig
> index 52065ab3b22..3a8ff17812b 100644
> --- a/hw/hexagon/Kconfig
> +++ b/hw/hexagon/Kconfig
> @@ -2,6 +2,7 @@ config HEX_DSP
>       bool
>       default y
>       depends on HEXAGON
> +    select ARM_COMPATIBLE_SEMIHOSTING
>   
>   config HEX_VIRT
>       bool
> diff --git a/qemu-options.hx b/qemu-options.hx
> index 34970fffc94..56f42b02c8a 100644
> --- a/qemu-options.hx
> +++ b/qemu-options.hx
> @@ -5507,7 +5507,7 @@ 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_RISCV)
> +    QEMU_ARCH_MIPS | QEMU_ARCH_RISCV | QEMU_ARCH_HEXAGON)
>   SRST
>   ``-semihosting``
>       Enable :ref:`Semihosting` mode (ARM, M68K, Xtensa, MIPS, RISC-V only).
> @@ -5523,11 +5523,11 @@ DEF("semihosting-config", HAS_ARG, QEMU_OPTION_semihosting_config,
>       "-semihosting-config [enable=on|off][,target=native|gdb|auto][,chardev=id][,userspace=on|off][,arg=str[,...]]\n" \
>       "                semihosting configuration\n",
>   QEMU_ARCH_ARM | QEMU_ARCH_M68K | QEMU_ARCH_XTENSA |
> -QEMU_ARCH_MIPS | QEMU_ARCH_RISCV)
> +QEMU_ARCH_MIPS | QEMU_ARCH_RISCV | QEMU_ARCH_HEXAGON)
>   SRST
>   ``-semihosting-config [enable=on|off][,target=native|gdb|auto][,chardev=id][,userspace=on|off][,arg=str[,...]]``
> -    Enable and configure :ref:`Semihosting` (ARM, M68K, Xtensa, MIPS, RISC-V
> -    only).
> +    Enable and configure :ref:`Semihosting` (ARM, M68K, Xtensa, MIPS, RISC-V,
> +    Hexagon only).
>   
>       .. warning::
>         Note that this allows guest direct access to the host filesystem, so
> diff --git a/target/hexagon/meson.build b/target/hexagon/meson.build
> index 59cb09c1070..69f01bd2f70 100644
> --- a/target/hexagon/meson.build
> +++ b/target/hexagon/meson.build
> @@ -262,6 +262,9 @@ hexagon_softmmu_ss.add(files(
>       'machine.c',
>   ))
>   
> +hexagon_softmmu_ss.add(when: 'CONFIG_ARM_COMPATIBLE_SEMIHOSTING',
> +                       if_true: files('common-semi-target.c'))
> +
>   #
>   # Step 4.5
>   # We use flex/bison based idef-parser to generate TCG code for a lot


  reply	other threads:[~2026-08-17  4:11 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-07-20 17:40 [PATCH v3 00/13] hexagon: add semihosting support Matheus Tavares Bernardino
2026-07-20 17:40 ` [PATCH v3 01/13] target/hexagon: fix improper assign of cause code to exception index Matheus Tavares Bernardino
2026-07-20 17:40 ` [PATCH v3 02/13] target/hexagon: fix PC advancement for non-COF TB terminators Matheus Tavares Bernardino
2026-07-20 17:40 ` [PATCH v3 03/13] target/hexagon: add aux functions for guest mem load/store Matheus Tavares Bernardino
2026-07-20 17:41 ` [PATCH v3 04/13] hexagon: cpu_helper: add reg reading/writing helpers Matheus Tavares Bernardino
2026-08-10  3:48   ` Brian Cain
2026-07-20 17:41 ` [PATCH v3 05/13] semihosting: add APIs for chardev-aware guest fd routing Matheus Tavares Bernardino
2026-07-20 17:41 ` [PATCH v3 06/13] semihosting: add callback to set error Matheus Tavares Bernardino
2026-07-20 17:41 ` [PATCH v3 07/13] target/hexagon: add semihosting support Matheus Tavares Bernardino
2026-08-17  4:11   ` Brian Cain [this message]
2026-08-17  4:23   ` Philippe Mathieu-Daudé
2026-08-17 18:50     ` Matheus Tavares Bernardino
2026-07-20 17:41 ` [PATCH v3 08/13] semihosting: add ftruncate helper (to be used for hexagon) Matheus Tavares Bernardino
2026-07-20 17:41 ` [PATCH v3 09/13] target/hexagon: add main arch-specific semihosting operations Matheus Tavares Bernardino
2026-08-17  4:10   ` Brian Cain
2026-08-17  4:29   ` Philippe Mathieu-Daudé
2026-08-18 14:06     ` Matheus Tavares Bernardino
2026-07-20 17:41 ` [PATCH v3 10/13] target/hexagon: add COREDUMP semihosting operation Matheus Tavares Bernardino
2026-08-17  4:34   ` Philippe Mathieu-Daudé
2026-08-17 19:55     ` Matheus Tavares Bernardino
2026-07-20 17:41 ` [PATCH v3 11/13] target/hexagon: Add an errno mapping Matheus Tavares Bernardino
2026-08-17  4:41   ` Philippe Mathieu-Daudé
2026-08-17 20:09     ` Matheus Tavares Bernardino
2026-07-20 17:41 ` [PATCH v3 12/13] python/machine: support routing semihosting output to the test console Matheus Tavares Bernardino
2026-07-20 17:41 ` [PATCH v3 13/13] tests/functional: Add hexagon semihosting systests Matheus Tavares Bernardino
2026-08-17  4:47   ` Philippe Mathieu-Daudé
2026-08-19 20:25     ` Matheus Tavares Bernardino

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=dd38b8ea-7af6-499c-93cb-9f93c1c03e4b@oss.qualcomm.com \
    --to=brian.cain@oss.qualcomm.com \
    --cc=ale@rev.ng \
    --cc=anjo@rev.ng \
    --cc=marco.liebel@oss.qualcomm.com \
    --cc=matheus.bernardino@oss.qualcomm.com \
    --cc=pbonzini@redhat.com \
    --cc=philmd@oss.qualcomm.com \
    --cc=pierrick.bouvier@oss.qualcomm.com \
    --cc=qemu-devel@nongnu.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
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.