Testing fixes and semiconsole support:
- build fix (missing x86-iommu stubs) - python fixes for freebsd and OSX - nicer reporting of acceptance failures - fix build nesting of fp-test (breaks bsds) - semihosting clean-ups - support for blocking semihosting console -----BEGIN PGP SIGNATURE----- iQEzBAABCgAdFiEEZoWumedRZ7yvyN81+9DbCVqeKkQFAl4XEbsACgkQ+9DbCVqe KkRtOwgAkdw3Pwi6sSlKdouR0lcWsRRqY2T3nA+xM/JrS+W9+hJ3VsM7EcBCJZcJ juJkQs3kU7Gs3LAeKbjmNq9xj9eTElD20l23RufiNB2CgULwHJ2+skGCTCq+1T1P VBWWNky4RyGjgcKoQQ8cNUmFhntnemGjnxvz1G0dObPu6yl5jNXIk7qJFZkSsERy YptCN8AF2bLXekYiB9Zn0xRd+O5Q4u/RtOg62REZoZOTA11M2Zuy+fkRK4XSzM/I wVdRd0t0hKViktl3Z4iu3MsQqCxaHIirsfEMVkmbGWMmepq3db9Xs1k4Ss2I7Uo3 YRTxj1BCwynsGbDpWSI/XHOYgKp8rA== =lSAv -----END PGP SIGNATURE----- Merge remote-tracking branch 'remotes/stsquad/tags/pull-testing-and-semihosting-090120-2' into staging Testing fixes and semiconsole support: - build fix (missing x86-iommu stubs) - python fixes for freebsd and OSX - nicer reporting of acceptance failures - fix build nesting of fp-test (breaks bsds) - semihosting clean-ups - support for blocking semihosting console # gpg: Signature made Thu 09 Jan 2020 11:42:51 GMT # gpg: using RSA key 6685AE99E75167BCAFC8DF35FBD0DB095A9E2A44 # gpg: Good signature from "Alex Bennée (Master Work Key) <alex.bennee@linaro.org>" [full] # Primary key fingerprint: 6685 AE99 E751 67BC AFC8 DF35 FBD0 DB09 5A9E 2A44 * remotes/stsquad/tags/pull-testing-and-semihosting-090120-2: tests/tcg: add user version of dumb-as-bricks semiconsole test tests/tcg: extract __semi_call into a header and expand tests/tcg: add a dumb-as-bricks semihosting console test semihosting: add qemu_semihosting_console_inc for SYS_READC target/arm: only update pc after semihosting completes target/arm: remove unused EXCP_SEMIHOST leg testing: don't nest build for fp-test travis.yml: install homebrew python for OS X travis.yml: duplicate before_script for MacOSX travis.yml: Detach build and test steps travis.yml: avocado: Print logs of non-pass tests only freebsd: use python37 tests/vm: update openbsd to release 6.6 hw/i386/x86-iommu: Add missing stubs Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
commit
f38a71b01f
30
.travis.yml
30
.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:
|
||||
|
|
|
@ -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();
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -37,6 +37,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
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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 */
|
||||
|
|
|
@ -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;
|
||||
}
|
||||
|
|
|
@ -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)
|
||||
{
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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;
|
||||
|
|
|
@ -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 $@)")
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
38
tests/tcg/aarch64/system/semiconsole.c
Normal file
38
tests/tcg/aarch64/system/semiconsole.c
Normal file
|
@ -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;
|
||||
}
|
|
@ -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
|
||||
|
|
35
tests/tcg/arm/semicall.h
Normal file
35
tests/tcg/arm/semicall.h
Normal file
|
@ -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;
|
||||
}
|
27
tests/tcg/arm/semiconsole.c
Normal file
27
tests/tcg/arm/semiconsole.c
Normal file
|
@ -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;
|
||||
}
|
|
@ -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])
|
||||
{
|
||||
|
|
|
@ -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};
|
||||
"""
|
||||
|
||||
|
|
|
@ -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
|
||||
|
|
3
vl.c
3
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)
|
||||
|
|
Loading…
Reference in a new issue