#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
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)
#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
--- /dev/null
+common-obj-$(CONFIG_SOFTMMU) += config.o
--- /dev/null
+/*
+ * 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;
+}
+
+++ /dev/null
-/*
- * 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;
-}
-
-static inline const char *semihosting_get_arg(int i)
-{
- return NULL;
-}
-
-static inline int semihosting_get_argc(void)
-{
- return 0;
-}
-
-static inline const char *semihosting_get_cmdline(void)
-{
- return NULL;
-}
-#else
-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
-
-#endif
--- /dev/null
+/*
+ * 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;
+}
+
+static inline const char *semihosting_get_arg(int i)
+{
+ return NULL;
+}
+
+static inline int semihosting_get_argc(void)
+{
+ return 0;
+}
+
+static inline const char *semihosting_get_cmdline(void)
+{
+ return NULL;
+}
+#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);
+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 /* SEMIHOST_H */
extern QemuOptsList qemu_net_opts;
extern QemuOptsList qemu_global_opts;
extern QemuOptsList qemu_mon_opts;
+extern QemuOptsList qemu_semihosting_config_opts;
#endif
#include "qemu/osdep.h"
#include "cpu.h"
-#include "exec/semihost.h"
+#include "hw/semihosting/semihost.h"
#ifdef CONFIG_USER_ONLY
#include "qemu.h"
#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"
#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"
#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"
#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,
#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)
#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,
#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"
#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)
#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"
#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"
#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"
},
};
-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",
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;
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;