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:
Alex Bennée 2019-05-13 14:43:57 +01:00
parent a7b21f6762
commit f1672e6f2b
19 changed files with 186 additions and 139 deletions

View File

@ -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

View File

@ -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)

View File

@ -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

View File

@ -0,0 +1 @@
common-obj-$(CONFIG_SOFTMMU) += config.o

160
hw/semihosting/config.c Normal file
View 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;
}

View File

@ -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 */

View File

@ -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

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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"

View File

@ -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,

View File

@ -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)

View File

@ -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,

View File

@ -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"

View File

@ -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)

View File

@ -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"

View File

@ -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
View File

@ -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;