semihosting: move semihosting configuration into its own directory
In preparation for having some more common semihosting code let's excise the current config magic from vl.c into its own file. We shall later add more conditionals to the build configurations so we can avoid building this if we don't need it. Signed-off-by: Alex Bennée <alex.bennee@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <philmd@redhat.com> Tested-by: Philippe Mathieu-Daudé <philmd@redhat.com> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
parent
a7b21f6762
commit
f1672e6f2b
@ -37,7 +37,7 @@
|
||||
#include "qemu/sockets.h"
|
||||
#include "sysemu/hw_accel.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "exec/semihost.h"
|
||||
#include "hw/semihosting/semihost.h"
|
||||
#include "exec/exec-all.h"
|
||||
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
|
@ -36,6 +36,7 @@ devices-dirs-$(CONFIG_SOFTMMU) += watchdog/
|
||||
devices-dirs-$(CONFIG_SOFTMMU) += xen/
|
||||
devices-dirs-$(CONFIG_MEM_DEVICE) += mem/
|
||||
devices-dirs-$(CONFIG_SOFTMMU) += smbios/
|
||||
devices-dirs-y += semihosting/
|
||||
devices-dirs-y += core/
|
||||
common-obj-y += $(devices-dirs-y)
|
||||
obj-y += $(devices-dirs-y)
|
||||
|
@ -55,7 +55,7 @@
|
||||
#include "qemu/error-report.h"
|
||||
#include "hw/empty_slot.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "exec/semihost.h"
|
||||
#include "hw/semihosting/semihost.h"
|
||||
#include "hw/mips/cps.h"
|
||||
|
||||
#define ENVP_ADDR 0x80002000l
|
||||
|
1
hw/semihosting/Makefile.objs
Normal file
1
hw/semihosting/Makefile.objs
Normal file
@ -0,0 +1 @@
|
||||
common-obj-$(CONFIG_SOFTMMU) += config.o
|
160
hw/semihosting/config.c
Normal file
160
hw/semihosting/config.c
Normal file
@ -0,0 +1,160 @@
|
||||
/*
|
||||
* Semihosting configuration
|
||||
*
|
||||
* Copyright (c) 2015 Imagination Technologies
|
||||
* Copyright (c) 2019 Linaro Ltd
|
||||
*
|
||||
* This controls the configuration of semihosting for all guest
|
||||
* targets that support it. Architecture specific handling is handled
|
||||
* in target/HW/HW-semi.c
|
||||
*
|
||||
* Semihosting is sightly strange in that it is also supported by some
|
||||
* linux-user targets. However in that use case no configuration of
|
||||
* the outputs and command lines is supported.
|
||||
*
|
||||
* The config module is common to all softmmu targets however as vl.c
|
||||
* needs to link against the helpers.
|
||||
*
|
||||
* SPDX-License-Identifier: GPL-2.0-or-later
|
||||
*/
|
||||
|
||||
#include "qemu/osdep.h"
|
||||
#include "qemu/option.h"
|
||||
#include "qemu/config-file.h"
|
||||
#include "qemu/error-report.h"
|
||||
#include "hw/semihosting/semihost.h"
|
||||
|
||||
QemuOptsList qemu_semihosting_config_opts = {
|
||||
.name = "semihosting-config",
|
||||
.implied_opt_name = "enable",
|
||||
.head = QTAILQ_HEAD_INITIALIZER(qemu_semihosting_config_opts.head),
|
||||
.desc = {
|
||||
{
|
||||
.name = "enable",
|
||||
.type = QEMU_OPT_BOOL,
|
||||
}, {
|
||||
.name = "target",
|
||||
.type = QEMU_OPT_STRING,
|
||||
}, {
|
||||
.name = "arg",
|
||||
.type = QEMU_OPT_STRING,
|
||||
},
|
||||
{ /* end of list */ }
|
||||
},
|
||||
};
|
||||
|
||||
typedef struct SemihostingConfig {
|
||||
bool enabled;
|
||||
SemihostingTarget target;
|
||||
const char **argv;
|
||||
int argc;
|
||||
const char *cmdline; /* concatenated argv */
|
||||
} SemihostingConfig;
|
||||
|
||||
static SemihostingConfig semihosting;
|
||||
|
||||
bool semihosting_enabled(void)
|
||||
{
|
||||
return semihosting.enabled;
|
||||
}
|
||||
|
||||
SemihostingTarget semihosting_get_target(void)
|
||||
{
|
||||
return semihosting.target;
|
||||
}
|
||||
|
||||
const char *semihosting_get_arg(int i)
|
||||
{
|
||||
if (i >= semihosting.argc) {
|
||||
return NULL;
|
||||
}
|
||||
return semihosting.argv[i];
|
||||
}
|
||||
|
||||
int semihosting_get_argc(void)
|
||||
{
|
||||
return semihosting.argc;
|
||||
}
|
||||
|
||||
const char *semihosting_get_cmdline(void)
|
||||
{
|
||||
if (semihosting.cmdline == NULL && semihosting.argc > 0) {
|
||||
semihosting.cmdline = g_strjoinv(" ", (gchar **)semihosting.argv);
|
||||
}
|
||||
return semihosting.cmdline;
|
||||
}
|
||||
|
||||
static int add_semihosting_arg(void *opaque,
|
||||
const char *name, const char *val,
|
||||
Error **errp)
|
||||
{
|
||||
SemihostingConfig *s = opaque;
|
||||
if (strcmp(name, "arg") == 0) {
|
||||
s->argc++;
|
||||
/* one extra element as g_strjoinv() expects NULL-terminated array */
|
||||
s->argv = g_realloc(s->argv, (s->argc + 1) * sizeof(void *));
|
||||
s->argv[s->argc - 1] = val;
|
||||
s->argv[s->argc] = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Use strings passed via -kernel/-append to initialize semihosting.argv[] */
|
||||
void semihosting_arg_fallback(const char *file, const char *cmd)
|
||||
{
|
||||
char *cmd_token;
|
||||
|
||||
/* argv[0] */
|
||||
add_semihosting_arg(&semihosting, "arg", file, NULL);
|
||||
|
||||
/* split -append and initialize argv[1..n] */
|
||||
cmd_token = strtok(g_strdup(cmd), " ");
|
||||
while (cmd_token) {
|
||||
add_semihosting_arg(&semihosting, "arg", cmd_token, NULL);
|
||||
cmd_token = strtok(NULL, " ");
|
||||
}
|
||||
}
|
||||
|
||||
void qemu_semihosting_enable(void)
|
||||
{
|
||||
semihosting.enabled = true;
|
||||
semihosting.target = SEMIHOSTING_TARGET_AUTO;
|
||||
}
|
||||
|
||||
int qemu_semihosting_config_options(const char *optarg)
|
||||
{
|
||||
QemuOptsList *opt_list = qemu_find_opts("semihosting-config");
|
||||
QemuOpts *opts = qemu_opts_parse_noisily(opt_list, optarg, false);
|
||||
|
||||
semihosting.enabled = true;
|
||||
|
||||
if (opts != NULL) {
|
||||
semihosting.enabled = qemu_opt_get_bool(opts, "enable",
|
||||
true);
|
||||
const char *target = qemu_opt_get(opts, "target");
|
||||
if (target != NULL) {
|
||||
if (strcmp("native", target) == 0) {
|
||||
semihosting.target = SEMIHOSTING_TARGET_NATIVE;
|
||||
} else if (strcmp("gdb", target) == 0) {
|
||||
semihosting.target = SEMIHOSTING_TARGET_GDB;
|
||||
} else if (strcmp("auto", target) == 0) {
|
||||
semihosting.target = SEMIHOSTING_TARGET_AUTO;
|
||||
} else {
|
||||
error_report("unsupported semihosting-config %s",
|
||||
optarg);
|
||||
return 1;
|
||||
}
|
||||
} else {
|
||||
semihosting.target = SEMIHOSTING_TARGET_AUTO;
|
||||
}
|
||||
/* Set semihosting argument count and vector */
|
||||
qemu_opt_foreach(opts, add_semihosting_arg,
|
||||
&semihosting, NULL);
|
||||
} else {
|
||||
error_report("unsupported semihosting-config %s", optarg);
|
||||
return 1;
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -51,12 +51,16 @@ static inline const char *semihosting_get_cmdline(void)
|
||||
{
|
||||
return NULL;
|
||||
}
|
||||
#else
|
||||
#else /* !CONFIG_USER_ONLY */
|
||||
bool semihosting_enabled(void);
|
||||
SemihostingTarget semihosting_get_target(void);
|
||||
const char *semihosting_get_arg(int i);
|
||||
int semihosting_get_argc(void);
|
||||
const char *semihosting_get_cmdline(void);
|
||||
#endif
|
||||
void semihosting_arg_fallback(const char *file, const char *cmd);
|
||||
/* for vl.c hooks */
|
||||
void qemu_semihosting_enable(void);
|
||||
int qemu_semihosting_config_options(const char *opt);
|
||||
#endif /* CONFIG_USER_ONLY */
|
||||
|
||||
#endif
|
||||
#endif /* SEMIHOST_H */
|
@ -193,5 +193,6 @@ extern QemuOptsList qemu_nic_opts;
|
||||
extern QemuOptsList qemu_net_opts;
|
||||
extern QemuOptsList qemu_global_opts;
|
||||
extern QemuOptsList qemu_mon_opts;
|
||||
extern QemuOptsList qemu_semihosting_config_opts;
|
||||
|
||||
#endif
|
||||
|
@ -21,7 +21,7 @@
|
||||
#include "qemu/osdep.h"
|
||||
|
||||
#include "cpu.h"
|
||||
#include "exec/semihost.h"
|
||||
#include "hw/semihosting/semihost.h"
|
||||
#ifdef CONFIG_USER_ONLY
|
||||
#include "qemu.h"
|
||||
|
||||
|
@ -16,7 +16,7 @@
|
||||
#include "exec/cpu_ldst.h"
|
||||
#include "arm_ldst.h"
|
||||
#include <zlib.h> /* For crc32 */
|
||||
#include "exec/semihost.h"
|
||||
#include "hw/semihosting/semihost.h"
|
||||
#include "sysemu/cpus.h"
|
||||
#include "sysemu/kvm.h"
|
||||
#include "fpu/softfloat.h"
|
||||
|
@ -29,7 +29,7 @@
|
||||
#include "qemu/host-utils.h"
|
||||
#include "qemu/qemu-print.h"
|
||||
|
||||
#include "exec/semihost.h"
|
||||
#include "hw/semihosting/semihost.h"
|
||||
#include "exec/gen-icount.h"
|
||||
|
||||
#include "exec/helper-proto.h"
|
||||
|
@ -30,7 +30,7 @@
|
||||
#include "qemu/bitops.h"
|
||||
#include "qemu/qemu-print.h"
|
||||
#include "arm_ldst.h"
|
||||
#include "exec/semihost.h"
|
||||
#include "hw/semihosting/semihost.h"
|
||||
|
||||
#include "exec/helper-proto.h"
|
||||
#include "exec/helper-gen.h"
|
||||
|
@ -22,7 +22,7 @@
|
||||
#include "exec/exec-all.h"
|
||||
#include "qemu/host-utils.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "exec/semihost.h"
|
||||
#include "hw/semihosting/semihost.h"
|
||||
#include "exec/log.h"
|
||||
|
||||
bool lm32_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
|
||||
|
@ -21,7 +21,7 @@
|
||||
#include "exec/helper-proto.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "exec/cpu_ldst.h"
|
||||
#include "exec/semihost.h"
|
||||
#include "hw/semihosting/semihost.h"
|
||||
|
||||
#if defined(CONFIG_USER_ONLY)
|
||||
|
||||
|
@ -22,7 +22,7 @@
|
||||
#include "qemu/log.h"
|
||||
#include "exec/helper-proto.h"
|
||||
#include "exec/softmmu-semi.h"
|
||||
#include "exec/semihost.h"
|
||||
#include "hw/semihosting/semihost.h"
|
||||
|
||||
typedef enum UHIOp {
|
||||
UHI_exit = 1,
|
||||
|
@ -32,7 +32,7 @@
|
||||
|
||||
#include "exec/helper-proto.h"
|
||||
#include "exec/helper-gen.h"
|
||||
#include "exec/semihost.h"
|
||||
#include "hw/semihosting/semihost.h"
|
||||
|
||||
#include "target/mips/trace.h"
|
||||
#include "trace-tcg.h"
|
||||
|
@ -26,7 +26,7 @@
|
||||
#include "exec/cpu_ldst.h"
|
||||
#include "exec/log.h"
|
||||
#include "exec/helper-proto.h"
|
||||
#include "exec/semihost.h"
|
||||
#include "hw/semihosting/semihost.h"
|
||||
|
||||
#if defined(CONFIG_USER_ONLY)
|
||||
|
||||
|
@ -38,7 +38,7 @@
|
||||
#include "qemu/qemu-print.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
#include "exec/cpu_ldst.h"
|
||||
#include "exec/semihost.h"
|
||||
#include "hw/semihosting/semihost.h"
|
||||
#include "exec/translator.h"
|
||||
|
||||
#include "exec/helper-proto.h"
|
||||
|
@ -29,7 +29,7 @@
|
||||
#include "cpu.h"
|
||||
#include "chardev/char-fe.h"
|
||||
#include "exec/helper-proto.h"
|
||||
#include "exec/semihost.h"
|
||||
#include "hw/semihosting/semihost.h"
|
||||
#include "qapi/error.h"
|
||||
#include "qemu/log.h"
|
||||
#include "sysemu/sysemu.h"
|
||||
|
126
vl.c
126
vl.c
@ -116,7 +116,7 @@ int main(int argc, char **argv)
|
||||
#include "qapi/opts-visitor.h"
|
||||
#include "qapi/clone-visitor.h"
|
||||
#include "qom/object_interfaces.h"
|
||||
#include "exec/semihost.h"
|
||||
#include "hw/semihosting/semihost.h"
|
||||
#include "crypto/init.h"
|
||||
#include "sysemu/replay.h"
|
||||
#include "qapi/qapi-events-run-state.h"
|
||||
@ -501,25 +501,6 @@ static QemuOptsList qemu_icount_opts = {
|
||||
},
|
||||
};
|
||||
|
||||
static QemuOptsList qemu_semihosting_config_opts = {
|
||||
.name = "semihosting-config",
|
||||
.implied_opt_name = "enable",
|
||||
.head = QTAILQ_HEAD_INITIALIZER(qemu_semihosting_config_opts.head),
|
||||
.desc = {
|
||||
{
|
||||
.name = "enable",
|
||||
.type = QEMU_OPT_BOOL,
|
||||
}, {
|
||||
.name = "target",
|
||||
.type = QEMU_OPT_STRING,
|
||||
}, {
|
||||
.name = "arg",
|
||||
.type = QEMU_OPT_STRING,
|
||||
},
|
||||
{ /* end of list */ }
|
||||
},
|
||||
};
|
||||
|
||||
static QemuOptsList qemu_fw_cfg_opts = {
|
||||
.name = "fw_cfg",
|
||||
.implied_opt_name = "name",
|
||||
@ -1351,80 +1332,6 @@ static void configure_msg(QemuOpts *opts)
|
||||
enable_timestamp_msg = qemu_opt_get_bool(opts, "timestamp", true);
|
||||
}
|
||||
|
||||
/***********************************************************/
|
||||
/* Semihosting */
|
||||
|
||||
typedef struct SemihostingConfig {
|
||||
bool enabled;
|
||||
SemihostingTarget target;
|
||||
const char **argv;
|
||||
int argc;
|
||||
const char *cmdline; /* concatenated argv */
|
||||
} SemihostingConfig;
|
||||
|
||||
static SemihostingConfig semihosting;
|
||||
|
||||
bool semihosting_enabled(void)
|
||||
{
|
||||
return semihosting.enabled;
|
||||
}
|
||||
|
||||
SemihostingTarget semihosting_get_target(void)
|
||||
{
|
||||
return semihosting.target;
|
||||
}
|
||||
|
||||
const char *semihosting_get_arg(int i)
|
||||
{
|
||||
if (i >= semihosting.argc) {
|
||||
return NULL;
|
||||
}
|
||||
return semihosting.argv[i];
|
||||
}
|
||||
|
||||
int semihosting_get_argc(void)
|
||||
{
|
||||
return semihosting.argc;
|
||||
}
|
||||
|
||||
const char *semihosting_get_cmdline(void)
|
||||
{
|
||||
if (semihosting.cmdline == NULL && semihosting.argc > 0) {
|
||||
semihosting.cmdline = g_strjoinv(" ", (gchar **)semihosting.argv);
|
||||
}
|
||||
return semihosting.cmdline;
|
||||
}
|
||||
|
||||
static int add_semihosting_arg(void *opaque,
|
||||
const char *name, const char *val,
|
||||
Error **errp)
|
||||
{
|
||||
SemihostingConfig *s = opaque;
|
||||
if (strcmp(name, "arg") == 0) {
|
||||
s->argc++;
|
||||
/* one extra element as g_strjoinv() expects NULL-terminated array */
|
||||
s->argv = g_realloc(s->argv, (s->argc + 1) * sizeof(void *));
|
||||
s->argv[s->argc - 1] = val;
|
||||
s->argv[s->argc] = NULL;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
/* Use strings passed via -kernel/-append to initialize semihosting.argv[] */
|
||||
static inline void semihosting_arg_fallback(const char *file, const char *cmd)
|
||||
{
|
||||
char *cmd_token;
|
||||
|
||||
/* argv[0] */
|
||||
add_semihosting_arg(&semihosting, "arg", file, NULL);
|
||||
|
||||
/* split -append and initialize argv[1..n] */
|
||||
cmd_token = strtok(g_strdup(cmd), " ");
|
||||
while (cmd_token) {
|
||||
add_semihosting_arg(&semihosting, "arg", cmd_token, NULL);
|
||||
cmd_token = strtok(NULL, " ");
|
||||
}
|
||||
}
|
||||
|
||||
/* Now we still need this for compatibility with XEN. */
|
||||
bool has_igd_gfx_passthru;
|
||||
@ -3743,37 +3650,10 @@ int main(int argc, char **argv, char **envp)
|
||||
nb_option_roms++;
|
||||
break;
|
||||
case QEMU_OPTION_semihosting:
|
||||
semihosting.enabled = true;
|
||||
semihosting.target = SEMIHOSTING_TARGET_AUTO;
|
||||
qemu_semihosting_enable();
|
||||
break;
|
||||
case QEMU_OPTION_semihosting_config:
|
||||
semihosting.enabled = true;
|
||||
opts = qemu_opts_parse_noisily(qemu_find_opts("semihosting-config"),
|
||||
optarg, false);
|
||||
if (opts != NULL) {
|
||||
semihosting.enabled = qemu_opt_get_bool(opts, "enable",
|
||||
true);
|
||||
const char *target = qemu_opt_get(opts, "target");
|
||||
if (target != NULL) {
|
||||
if (strcmp("native", target) == 0) {
|
||||
semihosting.target = SEMIHOSTING_TARGET_NATIVE;
|
||||
} else if (strcmp("gdb", target) == 0) {
|
||||
semihosting.target = SEMIHOSTING_TARGET_GDB;
|
||||
} else if (strcmp("auto", target) == 0) {
|
||||
semihosting.target = SEMIHOSTING_TARGET_AUTO;
|
||||
} else {
|
||||
error_report("unsupported semihosting-config %s",
|
||||
optarg);
|
||||
exit(1);
|
||||
}
|
||||
} else {
|
||||
semihosting.target = SEMIHOSTING_TARGET_AUTO;
|
||||
}
|
||||
/* Set semihosting argument count and vector */
|
||||
qemu_opt_foreach(opts, add_semihosting_arg,
|
||||
&semihosting, NULL);
|
||||
} else {
|
||||
error_report("unsupported semihosting-config %s", optarg);
|
||||
if (qemu_semihosting_config_options(optarg) != 0) {
|
||||
exit(1);
|
||||
}
|
||||
break;
|
||||
|
Loading…
Reference in New Issue
Block a user