mirror of https://github.com/xqemu/xqemu.git
semihosting: create SemihostingConfig structure and semihost.h
Remove semihosting_enabled and semihosting_target and replace them with SemihostingConfig structure containing equivalent fields. The structure is defined in vl.c where it is actually set. Also introduce separate header file include/exec/semihost.h allowing to access semihosting config related stuff from target specific semihosting code. Signed-off-by: Leon Alrae <leon.alrae@imgtec.com> Reviewed-by: Peter Maydell <peter.maydell@linaro.org> Message-id: 1434643256-16858-2-git-send-email-leon.alrae@imgtec.com Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
parent
b58850e79d
commit
cfe67cef48
|
@ -40,6 +40,7 @@
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "qemu/sockets.h"
|
#include "qemu/sockets.h"
|
||||||
#include "sysemu/kvm.h"
|
#include "sysemu/kvm.h"
|
||||||
|
#include "exec/semihost.h"
|
||||||
|
|
||||||
#ifdef CONFIG_USER_ONLY
|
#ifdef CONFIG_USER_ONLY
|
||||||
#define GDB_ATTACHED "0"
|
#define GDB_ATTACHED "0"
|
||||||
|
@ -323,8 +324,6 @@ static GDBState *gdbserver_state;
|
||||||
|
|
||||||
bool gdb_has_xml;
|
bool gdb_has_xml;
|
||||||
|
|
||||||
int semihosting_target = SEMIHOSTING_TARGET_AUTO;
|
|
||||||
|
|
||||||
#ifdef CONFIG_USER_ONLY
|
#ifdef CONFIG_USER_ONLY
|
||||||
/* XXX: This is not thread safe. Do we care? */
|
/* XXX: This is not thread safe. Do we care? */
|
||||||
static int gdbserver_fd = -1;
|
static int gdbserver_fd = -1;
|
||||||
|
@ -362,10 +361,11 @@ static enum {
|
||||||
/* Decide if either remote gdb syscalls or native file IO should be used. */
|
/* Decide if either remote gdb syscalls or native file IO should be used. */
|
||||||
int use_gdb_syscalls(void)
|
int use_gdb_syscalls(void)
|
||||||
{
|
{
|
||||||
if (semihosting_target == SEMIHOSTING_TARGET_NATIVE) {
|
SemihostingTarget target = semihosting_get_target();
|
||||||
|
if (target == SEMIHOSTING_TARGET_NATIVE) {
|
||||||
/* -semihosting-config target=native */
|
/* -semihosting-config target=native */
|
||||||
return false;
|
return false;
|
||||||
} else if (semihosting_target == SEMIHOSTING_TARGET_GDB) {
|
} else if (target == SEMIHOSTING_TARGET_GDB) {
|
||||||
/* -semihosting-config target=gdb */
|
/* -semihosting-config target=gdb */
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
|
@ -95,10 +95,4 @@ extern bool gdb_has_xml;
|
||||||
/* in gdbstub-xml.c, generated by scripts/feature_to_c.sh */
|
/* in gdbstub-xml.c, generated by scripts/feature_to_c.sh */
|
||||||
extern const char *const xml_builtin[][2];
|
extern const char *const xml_builtin[][2];
|
||||||
|
|
||||||
/* Command line option defining whether semihosting should go via gdb or not */
|
|
||||||
extern int semihosting_target;
|
|
||||||
#define SEMIHOSTING_TARGET_AUTO 0
|
|
||||||
#define SEMIHOSTING_TARGET_NATIVE 1
|
|
||||||
#define SEMIHOSTING_TARGET_GDB 2
|
|
||||||
|
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -0,0 +1,44 @@
|
||||||
|
/*
|
||||||
|
* Semihosting support
|
||||||
|
*
|
||||||
|
* Copyright (c) 2015 Imagination Technologies
|
||||||
|
*
|
||||||
|
* This library is free software; you can redistribute it and/or
|
||||||
|
* modify it under the terms of the GNU Lesser General Public
|
||||||
|
* License as published by the Free Software Foundation; either
|
||||||
|
* version 2 of the License, or (at your option) any later version.
|
||||||
|
*
|
||||||
|
* This library 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
|
||||||
|
* Lesser General Public License for more details.
|
||||||
|
*
|
||||||
|
* You should have received a copy of the GNU Lesser General Public
|
||||||
|
* License along with this library; if not, see <http://www.gnu.org/licenses/>.
|
||||||
|
*/
|
||||||
|
|
||||||
|
#ifndef SEMIHOST_H
|
||||||
|
#define SEMIHOST_H
|
||||||
|
|
||||||
|
typedef enum SemihostingTarget {
|
||||||
|
SEMIHOSTING_TARGET_AUTO = 0,
|
||||||
|
SEMIHOSTING_TARGET_NATIVE,
|
||||||
|
SEMIHOSTING_TARGET_GDB
|
||||||
|
} SemihostingTarget;
|
||||||
|
|
||||||
|
#ifdef CONFIG_USER_ONLY
|
||||||
|
static inline bool semihosting_enabled(void)
|
||||||
|
{
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline SemihostingTarget semihosting_get_target(void)
|
||||||
|
{
|
||||||
|
return SEMIHOSTING_TARGET_AUTO;
|
||||||
|
}
|
||||||
|
#else
|
||||||
|
bool semihosting_enabled(void);
|
||||||
|
SemihostingTarget semihosting_get_target(void);
|
||||||
|
#endif
|
||||||
|
|
||||||
|
#endif
|
|
@ -126,7 +126,6 @@ extern int cursor_hide;
|
||||||
extern int graphic_rotate;
|
extern int graphic_rotate;
|
||||||
extern int no_quit;
|
extern int no_quit;
|
||||||
extern int no_shutdown;
|
extern int no_shutdown;
|
||||||
extern int semihosting_enabled;
|
|
||||||
extern int old_param;
|
extern int old_param;
|
||||||
extern int boot_menu;
|
extern int boot_menu;
|
||||||
extern bool boot_strict;
|
extern bool boot_strict;
|
||||||
|
|
|
@ -10,6 +10,7 @@
|
||||||
#include "exec/cpu_ldst.h"
|
#include "exec/cpu_ldst.h"
|
||||||
#include "arm_ldst.h"
|
#include "arm_ldst.h"
|
||||||
#include <zlib.h> /* For crc32 */
|
#include <zlib.h> /* For crc32 */
|
||||||
|
#include "exec/semihost.h"
|
||||||
|
|
||||||
#ifndef CONFIG_USER_ONLY
|
#ifndef CONFIG_USER_ONLY
|
||||||
static inline bool get_phys_addr(CPUARMState *env, target_ulong address,
|
static inline bool get_phys_addr(CPUARMState *env, target_ulong address,
|
||||||
|
@ -4554,7 +4555,7 @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
|
||||||
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_MEM);
|
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_MEM);
|
||||||
return;
|
return;
|
||||||
case EXCP_BKPT:
|
case EXCP_BKPT:
|
||||||
if (semihosting_enabled) {
|
if (semihosting_enabled()) {
|
||||||
int nr;
|
int nr;
|
||||||
nr = arm_lduw_code(env, env->regs[15], env->bswap_code) & 0xff;
|
nr = arm_lduw_code(env, env->regs[15], env->bswap_code) & 0xff;
|
||||||
if (nr == 0xab) {
|
if (nr == 0xab) {
|
||||||
|
@ -4866,7 +4867,7 @@ void arm_cpu_do_interrupt(CPUState *cs)
|
||||||
offset = 4;
|
offset = 4;
|
||||||
break;
|
break;
|
||||||
case EXCP_SWI:
|
case EXCP_SWI:
|
||||||
if (semihosting_enabled) {
|
if (semihosting_enabled()) {
|
||||||
/* Check for semihosting interrupt. */
|
/* Check for semihosting interrupt. */
|
||||||
if (env->thumb) {
|
if (env->thumb) {
|
||||||
mask = arm_lduw_code(env, env->regs[15] - 2, env->bswap_code)
|
mask = arm_lduw_code(env, env->regs[15] - 2, env->bswap_code)
|
||||||
|
@ -4893,7 +4894,7 @@ void arm_cpu_do_interrupt(CPUState *cs)
|
||||||
break;
|
break;
|
||||||
case EXCP_BKPT:
|
case EXCP_BKPT:
|
||||||
/* See if this is a semihosting syscall. */
|
/* See if this is a semihosting syscall. */
|
||||||
if (env->thumb && semihosting_enabled) {
|
if (env->thumb && semihosting_enabled()) {
|
||||||
mask = arm_lduw_code(env, env->regs[15], env->bswap_code) & 0xff;
|
mask = arm_lduw_code(env, env->regs[15], env->bswap_code) & 0xff;
|
||||||
if (mask == 0xab
|
if (mask == 0xab
|
||||||
&& (env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR) {
|
&& (env->uncached_cpsr & CPSR_M) != ARM_CPU_MODE_USR) {
|
||||||
|
|
|
@ -20,6 +20,7 @@
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "qemu/host-utils.h"
|
#include "qemu/host-utils.h"
|
||||||
#include "sysemu/sysemu.h"
|
#include "sysemu/sysemu.h"
|
||||||
|
#include "exec/semihost.h"
|
||||||
|
|
||||||
int lm32_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int rw,
|
int lm32_cpu_handle_mmu_fault(CPUState *cs, vaddr address, int rw,
|
||||||
int mmu_idx)
|
int mmu_idx)
|
||||||
|
@ -162,7 +163,7 @@ void lm32_cpu_do_interrupt(CPUState *cs)
|
||||||
|
|
||||||
switch (cs->exception_index) {
|
switch (cs->exception_index) {
|
||||||
case EXCP_SYSTEMCALL:
|
case EXCP_SYSTEMCALL:
|
||||||
if (unlikely(semihosting_enabled)) {
|
if (unlikely(semihosting_enabled())) {
|
||||||
/* do_semicall() returns true if call was handled. Otherwise
|
/* do_semicall() returns true if call was handled. Otherwise
|
||||||
* do the normal exception handling. */
|
* do the normal exception handling. */
|
||||||
if (lm32_cpu_do_semihosting(cs)) {
|
if (lm32_cpu_do_semihosting(cs)) {
|
||||||
|
|
|
@ -19,6 +19,7 @@
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "exec/helper-proto.h"
|
#include "exec/helper-proto.h"
|
||||||
#include "exec/cpu_ldst.h"
|
#include "exec/cpu_ldst.h"
|
||||||
|
#include "exec/semihost.h"
|
||||||
|
|
||||||
#if defined(CONFIG_USER_ONLY)
|
#if defined(CONFIG_USER_ONLY)
|
||||||
|
|
||||||
|
@ -33,8 +34,6 @@ static inline void do_interrupt_m68k_hardirq(CPUM68KState *env)
|
||||||
|
|
||||||
#else
|
#else
|
||||||
|
|
||||||
extern int semihosting_enabled;
|
|
||||||
|
|
||||||
/* Try to fill the TLB and return an exception if error. If retaddr is
|
/* Try to fill the TLB and return an exception if error. If retaddr is
|
||||||
NULL, it means that the function was called in C code (i.e. not
|
NULL, it means that the function was called in C code (i.e. not
|
||||||
from generated code or from helper.c) */
|
from generated code or from helper.c) */
|
||||||
|
@ -85,7 +84,7 @@ static void do_interrupt_all(CPUM68KState *env, int is_hw)
|
||||||
do_rte(env);
|
do_rte(env);
|
||||||
return;
|
return;
|
||||||
case EXCP_HALT_INSN:
|
case EXCP_HALT_INSN:
|
||||||
if (semihosting_enabled
|
if (semihosting_enabled()
|
||||||
&& (env->sr & SR_S) != 0
|
&& (env->sr & SR_S) != 0
|
||||||
&& (env->pc & 3) == 0
|
&& (env->pc & 3) == 0
|
||||||
&& cpu_lduw_code(env, env->pc - 4) == 0x4e71
|
&& cpu_lduw_code(env, env->pc - 4) == 0x4e71
|
||||||
|
|
|
@ -37,6 +37,7 @@
|
||||||
#include "qemu/log.h"
|
#include "qemu/log.h"
|
||||||
#include "sysemu/sysemu.h"
|
#include "sysemu/sysemu.h"
|
||||||
#include "exec/cpu_ldst.h"
|
#include "exec/cpu_ldst.h"
|
||||||
|
#include "exec/semihost.h"
|
||||||
|
|
||||||
#include "exec/helper-proto.h"
|
#include "exec/helper-proto.h"
|
||||||
#include "exec/helper-gen.h"
|
#include "exec/helper-gen.h"
|
||||||
|
@ -1216,7 +1217,7 @@ static void disas_xtensa_insn(CPUXtensaState *env, DisasContext *dc)
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case 1: /*SIMCALL*/
|
case 1: /*SIMCALL*/
|
||||||
if (semihosting_enabled) {
|
if (semihosting_enabled()) {
|
||||||
if (gen_check_privilege(dc)) {
|
if (gen_check_privilege(dc)) {
|
||||||
gen_helper_simcall(cpu_env);
|
gen_helper_simcall(cpu_env);
|
||||||
}
|
}
|
||||||
|
|
38
vl.c
38
vl.c
|
@ -119,6 +119,7 @@ int main(int argc, char **argv)
|
||||||
#include "qapi/opts-visitor.h"
|
#include "qapi/opts-visitor.h"
|
||||||
#include "qom/object_interfaces.h"
|
#include "qom/object_interfaces.h"
|
||||||
#include "qapi-event.h"
|
#include "qapi-event.h"
|
||||||
|
#include "exec/semihost.h"
|
||||||
|
|
||||||
#define MAX_VIRTIO_CONSOLES 1
|
#define MAX_VIRTIO_CONSOLES 1
|
||||||
#define MAX_SCLP_CONSOLES 1
|
#define MAX_SCLP_CONSOLES 1
|
||||||
|
@ -169,7 +170,6 @@ int graphic_rotate = 0;
|
||||||
const char *watchdog;
|
const char *watchdog;
|
||||||
QEMUOptionRom option_rom[MAX_OPTION_ROMS];
|
QEMUOptionRom option_rom[MAX_OPTION_ROMS];
|
||||||
int nb_option_roms;
|
int nb_option_roms;
|
||||||
int semihosting_enabled = 0;
|
|
||||||
int old_param = 0;
|
int old_param = 0;
|
||||||
const char *qemu_name;
|
const char *qemu_name;
|
||||||
int alt_grab = 0;
|
int alt_grab = 0;
|
||||||
|
@ -1245,6 +1245,26 @@ static void configure_msg(QemuOpts *opts)
|
||||||
enable_timestamp_msg = qemu_opt_get_bool(opts, "timestamp", true);
|
enable_timestamp_msg = qemu_opt_get_bool(opts, "timestamp", true);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/***********************************************************/
|
||||||
|
/* Semihosting */
|
||||||
|
|
||||||
|
typedef struct SemihostingConfig {
|
||||||
|
bool enabled;
|
||||||
|
SemihostingTarget target;
|
||||||
|
} SemihostingConfig;
|
||||||
|
|
||||||
|
static SemihostingConfig semihosting;
|
||||||
|
|
||||||
|
bool semihosting_enabled(void)
|
||||||
|
{
|
||||||
|
return semihosting.enabled;
|
||||||
|
}
|
||||||
|
|
||||||
|
SemihostingTarget semihosting_get_target(void)
|
||||||
|
{
|
||||||
|
return semihosting.target;
|
||||||
|
}
|
||||||
|
|
||||||
/***********************************************************/
|
/***********************************************************/
|
||||||
/* USB devices */
|
/* USB devices */
|
||||||
|
|
||||||
|
@ -3622,24 +3642,24 @@ int main(int argc, char **argv, char **envp)
|
||||||
nb_option_roms++;
|
nb_option_roms++;
|
||||||
break;
|
break;
|
||||||
case QEMU_OPTION_semihosting:
|
case QEMU_OPTION_semihosting:
|
||||||
semihosting_enabled = 1;
|
semihosting.enabled = true;
|
||||||
semihosting_target = SEMIHOSTING_TARGET_AUTO;
|
semihosting.target = SEMIHOSTING_TARGET_AUTO;
|
||||||
break;
|
break;
|
||||||
case QEMU_OPTION_semihosting_config:
|
case QEMU_OPTION_semihosting_config:
|
||||||
semihosting_enabled = 1;
|
semihosting.enabled = true;
|
||||||
opts = qemu_opts_parse(qemu_find_opts("semihosting-config"),
|
opts = qemu_opts_parse(qemu_find_opts("semihosting-config"),
|
||||||
optarg, 0);
|
optarg, 0);
|
||||||
if (opts != NULL) {
|
if (opts != NULL) {
|
||||||
semihosting_enabled = qemu_opt_get_bool(opts, "enable",
|
semihosting.enabled = qemu_opt_get_bool(opts, "enable",
|
||||||
true);
|
true);
|
||||||
const char *target = qemu_opt_get(opts, "target");
|
const char *target = qemu_opt_get(opts, "target");
|
||||||
if (target != NULL) {
|
if (target != NULL) {
|
||||||
if (strcmp("native", target) == 0) {
|
if (strcmp("native", target) == 0) {
|
||||||
semihosting_target = SEMIHOSTING_TARGET_NATIVE;
|
semihosting.target = SEMIHOSTING_TARGET_NATIVE;
|
||||||
} else if (strcmp("gdb", target) == 0) {
|
} else if (strcmp("gdb", target) == 0) {
|
||||||
semihosting_target = SEMIHOSTING_TARGET_GDB;
|
semihosting.target = SEMIHOSTING_TARGET_GDB;
|
||||||
} else if (strcmp("auto", target) == 0) {
|
} else if (strcmp("auto", target) == 0) {
|
||||||
semihosting_target = SEMIHOSTING_TARGET_AUTO;
|
semihosting.target = SEMIHOSTING_TARGET_AUTO;
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "Unsupported semihosting-config"
|
fprintf(stderr, "Unsupported semihosting-config"
|
||||||
" %s\n",
|
" %s\n",
|
||||||
|
@ -3647,7 +3667,7 @@ int main(int argc, char **argv, char **envp)
|
||||||
exit(1);
|
exit(1);
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
semihosting_target = SEMIHOSTING_TARGET_AUTO;
|
semihosting.target = SEMIHOSTING_TARGET_AUTO;
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
fprintf(stderr, "Unsupported semihosting-config %s\n",
|
fprintf(stderr, "Unsupported semihosting-config %s\n",
|
||||||
|
|
Loading…
Reference in New Issue