aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.travis.yml30
-rw-r--r--hw/i386/x86-iommu-stub.c9
-rw-r--r--hw/semihosting/console.c79
-rw-r--r--include/hw/semihosting/console.h16
-rw-r--r--include/hw/semihosting/semihost.h4
-rw-r--r--linux-user/aarch64/cpu_loop.c1
-rw-r--r--linux-user/arm/cpu_loop.c1
-rw-r--r--linux-user/arm/semihost.c27
-rw-r--r--stubs/semihost.c4
-rw-r--r--target/arm/arm-semi.c3
-rw-r--r--target/arm/helper.c8
-rw-r--r--target/arm/m_helper.c1
-rw-r--r--target/arm/translate-a64.c2
-rw-r--r--target/arm/translate.c6
-rw-r--r--tests/Makefile.include2
-rw-r--r--tests/fp/Makefile14
-rw-r--r--tests/tcg/aarch64/Makefile.softmmu-target11
-rw-r--r--tests/tcg/aarch64/Makefile.target7
-rw-r--r--tests/tcg/aarch64/system/semiconsole.c38
-rw-r--r--tests/tcg/arm/Makefile.target28
-rw-r--r--tests/tcg/arm/semicall.h35
-rw-r--r--tests/tcg/arm/semiconsole.c27
-rw-r--r--tests/tcg/arm/semihosting.c21
-rwxr-xr-xtests/vm/freebsd3
-rwxr-xr-xtests/vm/openbsd4
-rw-r--r--vl.c3
26 files changed, 328 insertions, 56 deletions
diff --git a/.travis.yml b/.travis.yml
index 638fba4..6c1038a 100644
--- a/.travis.yml
+++ b/.travis.yml
@@ -51,13 +51,6 @@ addons:
- sparse
- uuid-dev
- gcovr
- homebrew:
- packages:
- - ccache
- - glib
- - pixman
- - gnu-sed
- update: true
# The channel name "irc.oftc.net#qemu" is encrypted against qemu/qemu
@@ -89,12 +82,12 @@ git:
before_script:
- - if [ "$TRAVIS_OS_NAME" == "osx" ] ; then export PATH="/usr/local/opt/ccache/libexec:$PATH" ; fi
- if command -v ccache ; then ccache --zero-stats ; fi
- mkdir -p ${BUILD_DIR} && cd ${BUILD_DIR}
- ${SRC_DIR}/configure ${BASE_CONFIG} ${CONFIG} || { cat config.log && exit 1; }
script:
- - make -j3 && travis_retry ${TEST_CMD}
+ - BUILD_RC=0 && make -j3 || BUILD_RC=$?
+ - if [ "$BUILD_RC" -eq 0 ] ; then travis_retry ${TEST_CMD} ; else $(exit $BUILD_RC); fi
after_script:
- if command -v ccache ; then ccache --show-stats ; fi
@@ -239,6 +232,21 @@ matrix:
os: osx
osx_image: xcode10.3
compiler: clang
+ addons:
+ homebrew:
+ packages:
+ - ccache
+ - glib
+ - pixman
+ - gnu-sed
+ - python
+ update: true
+ before_script:
+ - brew link --overwrite python
+ - export PATH="/usr/local/opt/ccache/libexec:$PATH"
+ - if command -v ccache ; then ccache --zero-stats ; fi
+ - mkdir -p ${BUILD_DIR} && cd ${BUILD_DIR}
+ - ${SRC_DIR}/configure ${BASE_CONFIG} ${CONFIG} || { cat config.log && exit 1; }
# Python builds
@@ -262,8 +270,8 @@ matrix:
- env:
- CONFIG="--python=/usr/bin/python3 --target-list=x86_64-softmmu,mips-softmmu,mips64el-softmmu,aarch64-softmmu,arm-softmmu,s390x-softmmu,alpha-softmmu,ppc-softmmu,ppc64-softmmu,m68k-softmmu,sparc-softmmu"
- TEST_CMD="make check-acceptance"
- after_failure:
- - cat tests/results/latest/job.log
+ after_script:
+ - python3 -c 'import json; r = json.load(open("tests/results/latest/results.json")); [print(t["logfile"]) for t in r["tests"] if t["status"] not in ("PASS", "SKIP")]' | xargs cat
addons:
apt:
packages:
diff --git a/hw/i386/x86-iommu-stub.c b/hw/i386/x86-iommu-stub.c
index 03576cd..c5ba077 100644
--- a/hw/i386/x86-iommu-stub.c
+++ b/hw/i386/x86-iommu-stub.c
@@ -32,3 +32,12 @@ X86IOMMUState *x86_iommu_get_default(void)
return NULL;
}
+bool x86_iommu_ir_supported(X86IOMMUState *s)
+{
+ return false;
+}
+
+IommuType x86_iommu_get_type(void)
+{
+ abort();
+}
diff --git a/hw/semihosting/console.c b/hw/semihosting/console.c
index b4b17c8..6346bd7 100644
--- a/hw/semihosting/console.c
+++ b/hw/semihosting/console.c
@@ -20,8 +20,15 @@
#include "hw/semihosting/semihost.h"
#include "hw/semihosting/console.h"
#include "exec/gdbstub.h"
+#include "exec/exec-all.h"
#include "qemu/log.h"
#include "chardev/char.h"
+#include <pthread.h>
+#include "chardev/char-fe.h"
+#include "sysemu/sysemu.h"
+#include "qemu/main-loop.h"
+#include "qapi/error.h"
+#include "qemu/fifo8.h"
int qemu_semihosting_log_out(const char *s, int len)
{
@@ -98,3 +105,75 @@ void qemu_semihosting_console_outc(CPUArchState *env, target_ulong addr)
__func__, addr);
}
}
+
+#define FIFO_SIZE 1024
+
+/* Access to this structure is protected by the BQL */
+typedef struct SemihostingConsole {
+ CharBackend backend;
+ GSList *sleeping_cpus;
+ bool got;
+ Fifo8 fifo;
+} SemihostingConsole;
+
+static SemihostingConsole console;
+
+static int console_can_read(void *opaque)
+{
+ SemihostingConsole *c = opaque;
+ int ret;
+ g_assert(qemu_mutex_iothread_locked());
+ ret = (int) fifo8_num_free(&c->fifo);
+ return ret;
+}
+
+static void console_wake_up(gpointer data, gpointer user_data)
+{
+ CPUState *cs = (CPUState *) data;
+ /* cpu_handle_halt won't know we have work so just unbung here */
+ cs->halted = 0;
+ qemu_cpu_kick(cs);
+}
+
+static void console_read(void *opaque, const uint8_t *buf, int size)
+{
+ SemihostingConsole *c = opaque;
+ g_assert(qemu_mutex_iothread_locked());
+ while (size-- && !fifo8_is_full(&c->fifo)) {
+ fifo8_push(&c->fifo, *buf++);
+ }
+ g_slist_foreach(c->sleeping_cpus, console_wake_up, NULL);
+ c->sleeping_cpus = NULL;
+}
+
+target_ulong qemu_semihosting_console_inc(CPUArchState *env)
+{
+ uint8_t ch;
+ SemihostingConsole *c = &console;
+ g_assert(qemu_mutex_iothread_locked());
+ g_assert(current_cpu);
+ if (fifo8_is_empty(&c->fifo)) {
+ c->sleeping_cpus = g_slist_prepend(c->sleeping_cpus, current_cpu);
+ current_cpu->halted = 1;
+ current_cpu->exception_index = EXCP_HALTED;
+ cpu_loop_exit(current_cpu);
+ /* never returns */
+ }
+ ch = fifo8_pop(&c->fifo);
+ return (target_ulong) ch;
+}
+
+void qemu_semihosting_console_init(void)
+{
+ Chardev *chr = semihosting_get_chardev();
+
+ if (chr) {
+ fifo8_create(&console.fifo, FIFO_SIZE);
+ qemu_chr_fe_init(&console.backend, chr, &error_abort);
+ qemu_chr_fe_set_handlers(&console.backend,
+ console_can_read,
+ console_read,
+ NULL, NULL, &console,
+ NULL, true);
+ }
+}
diff --git a/include/hw/semihosting/console.h b/include/hw/semihosting/console.h
index 9be9754..0238f54 100644
--- a/include/hw/semihosting/console.h
+++ b/include/hw/semihosting/console.h
@@ -38,6 +38,22 @@ int qemu_semihosting_console_outs(CPUArchState *env, target_ulong s);
void qemu_semihosting_console_outc(CPUArchState *env, target_ulong c);
/**
+ * qemu_semihosting_console_inc:
+ * @env: CPUArchState
+ *
+ * Receive single character from debug console. This may be the remote
+ * gdb session if a softmmu guest is currently being debugged. As this
+ * call may block if no data is available we suspend the CPU and will
+ * re-execute the instruction when data is there. Therefore two
+ * conditions must be met:
+ * - CPUState is synchronized before calling this function
+ * - pc is only updated once the character is successfully returned
+ *
+ * Returns: character read OR cpu_loop_exit!
+ */
+target_ulong qemu_semihosting_console_inc(CPUArchState *env);
+
+/**
* qemu_semihosting_log_out:
* @s: pointer to string
* @len: length of string
diff --git a/include/hw/semihosting/semihost.h b/include/hw/semihosting/semihost.h
index 60fc42d..b8ce511 100644
--- a/include/hw/semihosting/semihost.h
+++ b/include/hw/semihosting/semihost.h
@@ -56,6 +56,9 @@ static inline Chardev *semihosting_get_chardev(void)
{
return NULL;
}
+static inline void qemu_semihosting_console_init(void)
+{
+}
#else /* !CONFIG_USER_ONLY */
bool semihosting_enabled(void);
SemihostingTarget semihosting_get_target(void);
@@ -68,6 +71,7 @@ Chardev *semihosting_get_chardev(void);
void qemu_semihosting_enable(void);
int qemu_semihosting_config_options(const char *opt);
void qemu_semihosting_connect_chardevs(void);
+void qemu_semihosting_console_init(void);
#endif /* CONFIG_USER_ONLY */
#endif /* SEMIHOST_H */
diff --git a/linux-user/aarch64/cpu_loop.c b/linux-user/aarch64/cpu_loop.c
index 31c845a..bbe9fef 100644
--- a/linux-user/aarch64/cpu_loop.c
+++ b/linux-user/aarch64/cpu_loop.c
@@ -130,6 +130,7 @@ void cpu_loop(CPUARMState *env)
break;
case EXCP_SEMIHOST:
env->xregs[0] = do_arm_semihosting(env);
+ env->pc += 4;
break;
case EXCP_YIELD:
/* nothing to do here for user-mode, just resume guest code */
diff --git a/linux-user/arm/cpu_loop.c b/linux-user/arm/cpu_loop.c
index 7be4071..1fae90c 100644
--- a/linux-user/arm/cpu_loop.c
+++ b/linux-user/arm/cpu_loop.c
@@ -377,6 +377,7 @@ void cpu_loop(CPUARMState *env)
break;
case EXCP_SEMIHOST:
env->regs[0] = do_arm_semihosting(env);
+ env->regs[15] += env->thumb ? 2 : 4;
break;
case EXCP_INTERRUPT:
/* just indicate that signals should be handled asap */
diff --git a/linux-user/arm/semihost.c b/linux-user/arm/semihost.c
index a16b525..a1f0f60 100644
--- a/linux-user/arm/semihost.c
+++ b/linux-user/arm/semihost.c
@@ -14,6 +14,7 @@
#include "cpu.h"
#include "hw/semihosting/console.h"
#include "qemu.h"
+#include <termios.h>
int qemu_semihosting_console_outs(CPUArchState *env, target_ulong addr)
{
@@ -47,3 +48,29 @@ void qemu_semihosting_console_outc(CPUArchState *env, target_ulong addr)
}
}
}
+
+/*
+ * For linux-user we can safely block. However as we want to return as
+ * soon as a character is read we need to tweak the termio to disable
+ * line buffering. We restore the old mode afterwards in case the
+ * program is expecting more normal behaviour. This is slow but
+ * nothing using semihosting console reading is expecting to be fast.
+ */
+target_ulong qemu_semihosting_console_inc(CPUArchState *env)
+{
+ uint8_t c;
+ struct termios old_tio, new_tio;
+
+ /* Disable line-buffering and echo */
+ tcgetattr(STDIN_FILENO, &old_tio);
+ new_tio = old_tio;
+ new_tio.c_lflag &= (~ICANON & ~ECHO);
+ tcsetattr(STDIN_FILENO, TCSANOW, &new_tio);
+
+ c = getchar();
+
+ /* restore config */
+ tcsetattr(STDIN_FILENO, TCSANOW, &old_tio);
+
+ return (target_ulong) c;
+}
diff --git a/stubs/semihost.c b/stubs/semihost.c
index f905892..1d8b37f 100644
--- a/stubs/semihost.c
+++ b/stubs/semihost.c
@@ -69,3 +69,7 @@ void semihosting_arg_fallback(const char *file, const char *cmd)
void qemu_semihosting_connect_chardevs(void)
{
}
+
+void qemu_semihosting_console_init(void)
+{
+}
diff --git a/target/arm/arm-semi.c b/target/arm/arm-semi.c
index 6f7b6d8..47d61f6 100644
--- a/target/arm/arm-semi.c
+++ b/target/arm/arm-semi.c
@@ -802,8 +802,7 @@ target_ulong do_arm_semihosting(CPUARMState *env)
return guestfd_fns[gf->type].readfn(cpu, gf, arg1, len);
case TARGET_SYS_READC:
- qemu_log_mask(LOG_UNIMP, "%s: SYS_READC not implemented", __func__);
- return 0;
+ return qemu_semihosting_console_inc(env);
case TARGET_SYS_ISTTY:
GET_ARG(0);
diff --git a/target/arm/helper.c b/target/arm/helper.c
index b6bec42..19a57a1 100644
--- a/target/arm/helper.c
+++ b/target/arm/helper.c
@@ -8566,12 +8566,6 @@ static void arm_cpu_do_interrupt_aarch64(CPUState *cs)
case EXCP_VFIQ:
addr += 0x100;
break;
- case EXCP_SEMIHOST:
- qemu_log_mask(CPU_LOG_INT,
- "...handling as semihosting call 0x%" PRIx64 "\n",
- env->xregs[0]);
- env->xregs[0] = do_arm_semihosting(env);
- return;
default:
cpu_abort(cs, "Unhandled exception 0x%x\n", cs->exception_index);
}
@@ -8620,11 +8614,13 @@ static void handle_semihosting(CPUState *cs)
"...handling as semihosting call 0x%" PRIx64 "\n",
env->xregs[0]);
env->xregs[0] = do_arm_semihosting(env);
+ env->pc += 4;
} else {
qemu_log_mask(CPU_LOG_INT,
"...handling as semihosting call 0x%x\n",
env->regs[0]);
env->regs[0] = do_arm_semihosting(env);
+ env->regs[15] += env->thumb ? 2 : 4;
}
}
#endif
diff --git a/target/arm/m_helper.c b/target/arm/m_helper.c
index 76de317..33d414a 100644
--- a/target/arm/m_helper.c
+++ b/target/arm/m_helper.c
@@ -2185,6 +2185,7 @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
"...handling as semihosting call 0x%x\n",
env->regs[0]);
env->regs[0] = do_arm_semihosting(env);
+ env->regs[15] += env->thumb ? 2 : 4;
return;
case EXCP_BKPT:
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_DEBUG, false);
diff --git a/target/arm/translate-a64.c b/target/arm/translate-a64.c
index d4bebbe..972c28c 100644
--- a/target/arm/translate-a64.c
+++ b/target/arm/translate-a64.c
@@ -1937,7 +1937,7 @@ static void disas_exc(DisasContext *s, uint32_t insn)
break;
}
#endif
- gen_exception_internal_insn(s, s->base.pc_next, EXCP_SEMIHOST);
+ gen_exception_internal_insn(s, s->pc_curr, EXCP_SEMIHOST);
} else {
unsupported_encoding(s, insn);
}
diff --git a/target/arm/translate.c b/target/arm/translate.c
index 2b6c1f9..5185e08 100644
--- a/target/arm/translate.c
+++ b/target/arm/translate.c
@@ -1124,7 +1124,7 @@ static inline void gen_hlt(DisasContext *s, int imm)
s->current_el != 0 &&
#endif
(imm == (s->thumb ? 0x3c : 0xf000))) {
- gen_exception_internal_insn(s, s->base.pc_next, EXCP_SEMIHOST);
+ gen_exception_internal_insn(s, s->pc_curr, EXCP_SEMIHOST);
return;
}
@@ -8457,7 +8457,7 @@ static bool trans_BKPT(DisasContext *s, arg_BKPT *a)
!IS_USER(s) &&
#endif
(a->imm == 0xab)) {
- gen_exception_internal_insn(s, s->base.pc_next, EXCP_SEMIHOST);
+ gen_exception_internal_insn(s, s->pc_curr, EXCP_SEMIHOST);
} else {
gen_exception_bkpt_insn(s, syn_aa32_bkpt(a->imm, false));
}
@@ -10266,7 +10266,7 @@ static bool trans_SVC(DisasContext *s, arg_SVC *a)
!IS_USER(s) &&
#endif
(a->imm == semihost_imm)) {
- gen_exception_internal_insn(s, s->base.pc_next, EXCP_SEMIHOST);
+ gen_exception_internal_insn(s, s->pc_curr, EXCP_SEMIHOST);
} else {
gen_set_pc_im(s, s->base.pc_next);
s->svc_imm = a->imm;
diff --git a/tests/Makefile.include b/tests/Makefile.include
index 49e3b0d..7a767bf 100644
--- a/tests/Makefile.include
+++ b/tests/Makefile.include
@@ -969,7 +969,7 @@ FP_TEST_BIN=$(BUILD_DIR)/tests/fp/fp-test
# the build dir is created by configure
.PHONY: $(FP_TEST_BIN)
-$(FP_TEST_BIN):
+$(FP_TEST_BIN): config-host.h $(test-util-obj-y)
$(call quiet-command, \
$(MAKE) $(SUBDIR_MAKEFLAGS) -C $(dir $@) V="$(V)" $(notdir $@), \
"BUILD", "$(notdir $@)")
diff --git a/tests/fp/Makefile b/tests/fp/Makefile
index 5a35e7c2..56768ec 100644
--- a/tests/fp/Makefile
+++ b/tests/fp/Makefile
@@ -554,15 +554,13 @@ TF_OBJS_LIB += $(TF_OBJS_TEST)
BINARIES := fp-test$(EXESUF) fp-bench$(EXESUF)
-# everything depends on config-host.h because platform.h includes it
-all: $(BUILD_DIR)/config-host.h
- $(MAKE) $(BINARIES)
+# We require artefacts from the main build including config-host.h
+# because platform.h includes it. Rather than re-invoking the main
+# build we just error out if things aren't there.
+$(LIBQEMUUTIL) $(BUILD_DIR)/config-host.h:
+ $(error $@ missing, re-run parent build)
-$(LIBQEMUUTIL):
- $(MAKE) -C $(BUILD_DIR) libqemuutil.a
-
-$(BUILD_DIR)/config-host.h:
- $(MAKE) -C $(BUILD_DIR) config-host.h
+all: $(BUILD_DIR)/config-host.h $(BINARIES)
# libtestfloat.a depends on libsoftfloat.a, so specify it first
FP_TEST_LIBS := libtestfloat.a libsoftfloat.a $(LIBQEMUUTIL)
diff --git a/tests/tcg/aarch64/Makefile.softmmu-target b/tests/tcg/aarch64/Makefile.softmmu-target
index 950dbb4..7b4eede 100644
--- a/tests/tcg/aarch64/Makefile.softmmu-target
+++ b/tests/tcg/aarch64/Makefile.softmmu-target
@@ -31,7 +31,16 @@ LDFLAGS+=-static -nostdlib $(CRT_OBJS) $(MINILIB_OBJS) -lgcc
memory: CFLAGS+=-DCHECK_UNALIGNED=1
# Running
-QEMU_OPTS+=-M virt -cpu max -display none -semihosting-config enable=on,target=native,chardev=output -kernel
+QEMU_BASE_MACHINE=-M virt -cpu max -display none
+QEMU_OPTS+=$(QEMU_BASE_MACHINE) -semihosting-config enable=on,target=native,chardev=output -kernel
+
+# console test is manual only
+QEMU_SEMIHOST=-chardev stdio,mux=on,id=stdio0 -semihosting-config enable=on,chardev=stdio0 -mon chardev=stdio0,mode=readline
+run-semiconsole: QEMU_OPTS=$(QEMU_BASE_MACHINE) $(QEMU_SEMIHOST) -kernel
+run-semiconsole: semiconsole
+ $(call skip-test, $<, "MANUAL ONLY")
+run-plugin-semiconsole-with-%: semiconsole
+ $(call skip-test, $<, "MANUAL ONLY")
# Simple Record/Replay Test
.PHONY: memory-record
diff --git a/tests/tcg/aarch64/Makefile.target b/tests/tcg/aarch64/Makefile.target
index 96d2321..df3fe80 100644
--- a/tests/tcg/aarch64/Makefile.target
+++ b/tests/tcg/aarch64/Makefile.target
@@ -32,4 +32,11 @@ run-plugin-semihosting-with-%:
$(call strip-plugin,$<) 2> $<.err, \
"$< on $(TARGET_NAME) with $*")
+AARCH64_TESTS += semiconsole
+run-semiconsole: semiconsole
+ $(call skip-test, $<, "MANUAL ONLY")
+
+run-plugin-semiconsole-with-%:
+ $(call skip-test, $<, "MANUAL ONLY")
+
TESTS += $(AARCH64_TESTS)
diff --git a/tests/tcg/aarch64/system/semiconsole.c b/tests/tcg/aarch64/system/semiconsole.c
new file mode 100644
index 0000000..bfe7c9e
--- /dev/null
+++ b/tests/tcg/aarch64/system/semiconsole.c
@@ -0,0 +1,38 @@
+/*
+ * Semihosting Console Test
+ *
+ * Copyright (c) 2019 Linaro Ltd
+ *
+ * SPDX-License-Identifier: GPL-2.0-or-later
+ */
+
+#include <inttypes.h>
+#include <minilib.h>
+
+#define SYS_READC 0x7
+
+uintptr_t __semi_call(uintptr_t type, uintptr_t arg0)
+{
+ register uintptr_t t asm("x0") = type;
+ register uintptr_t a0 asm("x1") = arg0;
+ asm("hlt 0xf000"
+ : "=r" (t)
+ : "r" (t), "r" (a0));
+
+ return t;
+}
+
+int main(void)
+{
+ char c;
+
+ ml_printf("Semihosting Console Test\n");
+ ml_printf("hit X to exit:");
+
+ do {
+ c = __semi_call(SYS_READC, 0);
+ __sys_outc(c);
+ } while (c != 'X');
+
+ return 0;
+}
diff --git a/tests/tcg/arm/Makefile.target b/tests/tcg/arm/Makefile.target
index 0765f37..11c39c6 100644
--- a/tests/tcg/arm/Makefile.target
+++ b/tests/tcg/arm/Makefile.target
@@ -31,15 +31,43 @@ run-fcvt: fcvt
# Semihosting smoke test for linux-user
ARM_TESTS += semihosting
+semihosting: CFLAGS += -mthumb
run-semihosting: semihosting
$(call run-test,$<,$(QEMU) $< 2> $<.err, "$< on $(TARGET_NAME)")
+ARM_TESTS += semihosting-arm
+semihosting-arm: CFLAGS += -marm
+semihosting-arm: semihosting.c
+ $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $< -o $@ $(LDFLAGS)
+
+run-semihosting-arm: semihosting-arm
+ $(call run-test,$<,$(QEMU) $< 2> $<.err, "$< on $(TARGET_NAME)")
+
run-plugin-semihosting-with-%:
$(call run-test, $@, $(QEMU) $(QEMU_OPTS) \
-plugin $(PLUGIN_DIR)/$(call extract-plugin,$@) \
$(call strip-plugin,$<) 2> $<.err, \
"$< on $(TARGET_NAME) with $*")
+ARM_TESTS += semiconsole semiconsole-arm
+
+semiconsole: CFLAGS += -mthumb
+run-semiconsole: semiconsole
+ $(call skip-test, $<, "MANUAL ONLY")
+
+run-plugin-semiconsole-with-%:
+ $(call skip-test, $<, "MANUAL ONLY")
+
+semiconsole-arm: CFLAGS += -marm
+semiconsole-arm: semiconsole.c
+ $(CC) $(CFLAGS) $(EXTRA_CFLAGS) $< -o $@ $(LDFLAGS)
+
+run-semiconsole-arm: semiconsole-arm
+ $(call skip-test, $<, "MANUAL ONLY")
+
+run-plugin-semiconsole-arm-with-%:
+ $(call skip-test, $<, "MANUAL ONLY")
+
TESTS += $(ARM_TESTS)
# On ARM Linux only supports 4k pages
diff --git a/tests/tcg/arm/semicall.h b/tests/tcg/arm/semicall.h
new file mode 100644
index 0000000..d4f6818
--- /dev/null
+++ b/tests/tcg/arm/semicall.h
@@ -0,0 +1,35 @@
+/*
+ * Semihosting Tests
+ *
+ * Copyright (c) 2019
+ * Written by Alex Bennée <alex.bennee@linaro.org>
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#define SYS_WRITE0 0x04
+#define SYS_READC 0x07
+#define SYS_REPORTEXC 0x18
+
+uintptr_t __semi_call(uintptr_t type, uintptr_t arg0)
+{
+#if defined(__arm__)
+ register uintptr_t t asm("r0") = type;
+ register uintptr_t a0 asm("r1") = arg0;
+#ifdef __thumb__
+# define SVC "svc 0xab"
+#else
+# define SVC "svc 0x123456"
+#endif
+ asm(SVC : "=r" (t)
+ : "r" (t), "r" (a0));
+#else
+ register uintptr_t t asm("x0") = type;
+ register uintptr_t a0 asm("x1") = arg0;
+ asm("hlt 0xf000"
+ : "=r" (t)
+ : "r" (t), "r" (a0));
+#endif
+
+ return t;
+}
diff --git a/tests/tcg/arm/semiconsole.c b/tests/tcg/arm/semiconsole.c
new file mode 100644
index 0000000..6ef0bd2
--- /dev/null
+++ b/tests/tcg/arm/semiconsole.c
@@ -0,0 +1,27 @@
+/*
+ * linux-user semihosting console
+ *
+ * Copyright (c) 2019
+ * Written by Alex Bennée <alex.bennee@linaro.org>
+ *
+ * SPDX-License-Identifier: GPL-3.0-or-later
+ */
+
+#include <stdio.h>
+#include <stdint.h>
+#include "semicall.h"
+
+int main(void)
+{
+ char c;
+
+ printf("Semihosting Console Test\n");
+ printf("hit X to exit:");
+
+ do {
+ c = __semi_call(SYS_READC, 0);
+ printf("got '%c'\n", c);
+ } while (c != 'X');
+
+ return 0;
+}
diff --git a/tests/tcg/arm/semihosting.c b/tests/tcg/arm/semihosting.c
index 09c89cb..33faac9 100644
--- a/tests/tcg/arm/semihosting.c
+++ b/tests/tcg/arm/semihosting.c
@@ -8,26 +8,7 @@
*/
#include <stdint.h>
-
-#define SYS_WRITE0 0x04
-#define SYS_REPORTEXC 0x18
-
-void __semi_call(uintptr_t type, uintptr_t arg0)
-{
-#if defined(__arm__)
- register uintptr_t t asm("r0") = type;
- register uintptr_t a0 asm("r1") = arg0;
- asm("svc 0xab"
- : /* no return */
- : "r" (t), "r" (a0));
-#else
- register uintptr_t t asm("x0") = type;
- register uintptr_t a0 asm("x1") = arg0;
- asm("hlt 0xf000"
- : /* no return */
- : "r" (t), "r" (a0));
-#endif
-}
+#include "semicall.h"
int main(int argc, char *argv[argc])
{
diff --git a/tests/vm/freebsd b/tests/vm/freebsd
index 1825cc5..33a7362 100755
--- a/tests/vm/freebsd
+++ b/tests/vm/freebsd
@@ -32,6 +32,7 @@ class FreeBSDVM(basevm.BaseVM):
"git",
"pkgconf",
"bzip2",
+ "python37",
# gnu tools
"bash",
@@ -63,7 +64,7 @@ class FreeBSDVM(basevm.BaseVM):
mkdir src build; cd src;
tar -xf /dev/vtbd1;
cd ../build
- ../src/configure --python=python3.6 {configure_opts};
+ ../src/configure --python=python3.7 {configure_opts};
gmake --output-sync -j{jobs} {target} {verbose};
"""
diff --git a/tests/vm/openbsd b/tests/vm/openbsd
index 6df5162..d617350 100755
--- a/tests/vm/openbsd
+++ b/tests/vm/openbsd
@@ -22,8 +22,8 @@ class OpenBSDVM(basevm.BaseVM):
name = "openbsd"
arch = "x86_64"
- link = "https://cdn.openbsd.org/pub/OpenBSD/6.5/amd64/install65.iso"
- csum = "38d1f8cadd502f1c27bf05c5abde6cc505dd28f3f34f8a941048ff9a54f9f608"
+ link = "https://cdn.openbsd.org/pub/OpenBSD/6.6/amd64/install66.iso"
+ csum = "b22e63df56e6266de6bbeed8e9be0fbe9ee2291551c5bc03f3cc2e4ab9436ee3"
size = "20G"
pkgs = [
# tools
diff --git a/vl.c b/vl.c
index 86474a5..b211921 100644
--- a/vl.c
+++ b/vl.c
@@ -4238,6 +4238,9 @@ int main(int argc, char **argv, char **envp)
qemu_opts_foreach(qemu_find_opts("mon"),
mon_init_func, NULL, &error_fatal);
+ /* connect semihosting console input if requested */
+ qemu_semihosting_console_init();
+
if (foreach_device_config(DEV_SERIAL, serial_parse) < 0)
exit(1);
if (foreach_device_config(DEV_PARALLEL, parallel_parse) < 0)