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
|
- sparse
|
||||||
- uuid-dev
|
- uuid-dev
|
||||||
- gcovr
|
- gcovr
|
||||||
homebrew:
|
|
||||||
packages:
|
|
||||||
- ccache
|
|
||||||
- glib
|
|
||||||
- pixman
|
|
||||||
- gnu-sed
|
|
||||||
update: true
|
|
||||||
|
|
||||||
|
|
||||||
# The channel name "irc.oftc.net#qemu" is encrypted against qemu/qemu
|
# The channel name "irc.oftc.net#qemu" is encrypted against qemu/qemu
|
||||||
|
@ -89,12 +82,12 @@ git:
|
||||||
|
|
||||||
|
|
||||||
before_script:
|
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
|
- if command -v ccache ; then ccache --zero-stats ; fi
|
||||||
- mkdir -p ${BUILD_DIR} && cd ${BUILD_DIR}
|
- mkdir -p ${BUILD_DIR} && cd ${BUILD_DIR}
|
||||||
- ${SRC_DIR}/configure ${BASE_CONFIG} ${CONFIG} || { cat config.log && exit 1; }
|
- ${SRC_DIR}/configure ${BASE_CONFIG} ${CONFIG} || { cat config.log && exit 1; }
|
||||||
script:
|
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:
|
after_script:
|
||||||
- if command -v ccache ; then ccache --show-stats ; fi
|
- if command -v ccache ; then ccache --show-stats ; fi
|
||||||
|
|
||||||
|
@ -239,6 +232,21 @@ matrix:
|
||||||
os: osx
|
os: osx
|
||||||
osx_image: xcode10.3
|
osx_image: xcode10.3
|
||||||
compiler: clang
|
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
|
# Python builds
|
||||||
|
@ -262,8 +270,8 @@ matrix:
|
||||||
- env:
|
- 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"
|
- 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"
|
- TEST_CMD="make check-acceptance"
|
||||||
after_failure:
|
after_script:
|
||||||
- cat tests/results/latest/job.log
|
- 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:
|
addons:
|
||||||
apt:
|
apt:
|
||||||
packages:
|
packages:
|
||||||
|
|
|
@ -32,3 +32,12 @@ X86IOMMUState *x86_iommu_get_default(void)
|
||||||
return NULL;
|
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/semihost.h"
|
||||||
#include "hw/semihosting/console.h"
|
#include "hw/semihosting/console.h"
|
||||||
#include "exec/gdbstub.h"
|
#include "exec/gdbstub.h"
|
||||||
|
#include "exec/exec-all.h"
|
||||||
#include "qemu/log.h"
|
#include "qemu/log.h"
|
||||||
#include "chardev/char.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)
|
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);
|
__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);
|
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:
|
* qemu_semihosting_log_out:
|
||||||
* @s: pointer to string
|
* @s: pointer to string
|
||||||
|
|
|
@ -56,6 +56,9 @@ static inline Chardev *semihosting_get_chardev(void)
|
||||||
{
|
{
|
||||||
return NULL;
|
return NULL;
|
||||||
}
|
}
|
||||||
|
static inline void qemu_semihosting_console_init(void)
|
||||||
|
{
|
||||||
|
}
|
||||||
#else /* !CONFIG_USER_ONLY */
|
#else /* !CONFIG_USER_ONLY */
|
||||||
bool semihosting_enabled(void);
|
bool semihosting_enabled(void);
|
||||||
SemihostingTarget semihosting_get_target(void);
|
SemihostingTarget semihosting_get_target(void);
|
||||||
|
@ -68,6 +71,7 @@ Chardev *semihosting_get_chardev(void);
|
||||||
void qemu_semihosting_enable(void);
|
void qemu_semihosting_enable(void);
|
||||||
int qemu_semihosting_config_options(const char *opt);
|
int qemu_semihosting_config_options(const char *opt);
|
||||||
void qemu_semihosting_connect_chardevs(void);
|
void qemu_semihosting_connect_chardevs(void);
|
||||||
|
void qemu_semihosting_console_init(void);
|
||||||
#endif /* CONFIG_USER_ONLY */
|
#endif /* CONFIG_USER_ONLY */
|
||||||
|
|
||||||
#endif /* SEMIHOST_H */
|
#endif /* SEMIHOST_H */
|
||||||
|
|
|
@ -130,6 +130,7 @@ void cpu_loop(CPUARMState *env)
|
||||||
break;
|
break;
|
||||||
case EXCP_SEMIHOST:
|
case EXCP_SEMIHOST:
|
||||||
env->xregs[0] = do_arm_semihosting(env);
|
env->xregs[0] = do_arm_semihosting(env);
|
||||||
|
env->pc += 4;
|
||||||
break;
|
break;
|
||||||
case EXCP_YIELD:
|
case EXCP_YIELD:
|
||||||
/* nothing to do here for user-mode, just resume guest code */
|
/* nothing to do here for user-mode, just resume guest code */
|
||||||
|
|
|
@ -377,6 +377,7 @@ void cpu_loop(CPUARMState *env)
|
||||||
break;
|
break;
|
||||||
case EXCP_SEMIHOST:
|
case EXCP_SEMIHOST:
|
||||||
env->regs[0] = do_arm_semihosting(env);
|
env->regs[0] = do_arm_semihosting(env);
|
||||||
|
env->regs[15] += env->thumb ? 2 : 4;
|
||||||
break;
|
break;
|
||||||
case EXCP_INTERRUPT:
|
case EXCP_INTERRUPT:
|
||||||
/* just indicate that signals should be handled asap */
|
/* just indicate that signals should be handled asap */
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include "cpu.h"
|
#include "cpu.h"
|
||||||
#include "hw/semihosting/console.h"
|
#include "hw/semihosting/console.h"
|
||||||
#include "qemu.h"
|
#include "qemu.h"
|
||||||
|
#include <termios.h>
|
||||||
|
|
||||||
int qemu_semihosting_console_outs(CPUArchState *env, target_ulong addr)
|
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_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);
|
return guestfd_fns[gf->type].readfn(cpu, gf, arg1, len);
|
||||||
case TARGET_SYS_READC:
|
case TARGET_SYS_READC:
|
||||||
qemu_log_mask(LOG_UNIMP, "%s: SYS_READC not implemented", __func__);
|
return qemu_semihosting_console_inc(env);
|
||||||
return 0;
|
|
||||||
case TARGET_SYS_ISTTY:
|
case TARGET_SYS_ISTTY:
|
||||||
GET_ARG(0);
|
GET_ARG(0);
|
||||||
|
|
||||||
|
|
|
@ -8566,12 +8566,6 @@ static void arm_cpu_do_interrupt_aarch64(CPUState *cs)
|
||||||
case EXCP_VFIQ:
|
case EXCP_VFIQ:
|
||||||
addr += 0x100;
|
addr += 0x100;
|
||||||
break;
|
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:
|
default:
|
||||||
cpu_abort(cs, "Unhandled exception 0x%x\n", cs->exception_index);
|
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",
|
"...handling as semihosting call 0x%" PRIx64 "\n",
|
||||||
env->xregs[0]);
|
env->xregs[0]);
|
||||||
env->xregs[0] = do_arm_semihosting(env);
|
env->xregs[0] = do_arm_semihosting(env);
|
||||||
|
env->pc += 4;
|
||||||
} else {
|
} else {
|
||||||
qemu_log_mask(CPU_LOG_INT,
|
qemu_log_mask(CPU_LOG_INT,
|
||||||
"...handling as semihosting call 0x%x\n",
|
"...handling as semihosting call 0x%x\n",
|
||||||
env->regs[0]);
|
env->regs[0]);
|
||||||
env->regs[0] = do_arm_semihosting(env);
|
env->regs[0] = do_arm_semihosting(env);
|
||||||
|
env->regs[15] += env->thumb ? 2 : 4;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
|
|
|
@ -2185,6 +2185,7 @@ void arm_v7m_cpu_do_interrupt(CPUState *cs)
|
||||||
"...handling as semihosting call 0x%x\n",
|
"...handling as semihosting call 0x%x\n",
|
||||||
env->regs[0]);
|
env->regs[0]);
|
||||||
env->regs[0] = do_arm_semihosting(env);
|
env->regs[0] = do_arm_semihosting(env);
|
||||||
|
env->regs[15] += env->thumb ? 2 : 4;
|
||||||
return;
|
return;
|
||||||
case EXCP_BKPT:
|
case EXCP_BKPT:
|
||||||
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_DEBUG, false);
|
armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_DEBUG, false);
|
||||||
|
|
|
@ -1937,7 +1937,7 @@ static void disas_exc(DisasContext *s, uint32_t insn)
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
#endif
|
#endif
|
||||||
gen_exception_internal_insn(s, s->base.pc_next, EXCP_SEMIHOST);
|
gen_exception_internal_insn(s, s->pc_curr, EXCP_SEMIHOST);
|
||||||
} else {
|
} else {
|
||||||
unsupported_encoding(s, insn);
|
unsupported_encoding(s, insn);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1124,7 +1124,7 @@ static inline void gen_hlt(DisasContext *s, int imm)
|
||||||
s->current_el != 0 &&
|
s->current_el != 0 &&
|
||||||
#endif
|
#endif
|
||||||
(imm == (s->thumb ? 0x3c : 0xf000))) {
|
(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;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -8457,7 +8457,7 @@ static bool trans_BKPT(DisasContext *s, arg_BKPT *a)
|
||||||
!IS_USER(s) &&
|
!IS_USER(s) &&
|
||||||
#endif
|
#endif
|
||||||
(a->imm == 0xab)) {
|
(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 {
|
} else {
|
||||||
gen_exception_bkpt_insn(s, syn_aa32_bkpt(a->imm, false));
|
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) &&
|
!IS_USER(s) &&
|
||||||
#endif
|
#endif
|
||||||
(a->imm == semihost_imm)) {
|
(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 {
|
} else {
|
||||||
gen_set_pc_im(s, s->base.pc_next);
|
gen_set_pc_im(s, s->base.pc_next);
|
||||||
s->svc_imm = a->imm;
|
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
|
# the build dir is created by configure
|
||||||
.PHONY: $(FP_TEST_BIN)
|
.PHONY: $(FP_TEST_BIN)
|
||||||
$(FP_TEST_BIN):
|
$(FP_TEST_BIN): config-host.h $(test-util-obj-y)
|
||||||
$(call quiet-command, \
|
$(call quiet-command, \
|
||||||
$(MAKE) $(SUBDIR_MAKEFLAGS) -C $(dir $@) V="$(V)" $(notdir $@), \
|
$(MAKE) $(SUBDIR_MAKEFLAGS) -C $(dir $@) V="$(V)" $(notdir $@), \
|
||||||
"BUILD", "$(notdir $@)")
|
"BUILD", "$(notdir $@)")
|
||||||
|
|
|
@ -554,15 +554,13 @@ TF_OBJS_LIB += $(TF_OBJS_TEST)
|
||||||
|
|
||||||
BINARIES := fp-test$(EXESUF) fp-bench$(EXESUF)
|
BINARIES := fp-test$(EXESUF) fp-bench$(EXESUF)
|
||||||
|
|
||||||
# everything depends on config-host.h because platform.h includes it
|
# We require artefacts from the main build including config-host.h
|
||||||
all: $(BUILD_DIR)/config-host.h
|
# because platform.h includes it. Rather than re-invoking the main
|
||||||
$(MAKE) $(BINARIES)
|
# build we just error out if things aren't there.
|
||||||
|
$(LIBQEMUUTIL) $(BUILD_DIR)/config-host.h:
|
||||||
|
$(error $@ missing, re-run parent build)
|
||||||
|
|
||||||
$(LIBQEMUUTIL):
|
all: $(BUILD_DIR)/config-host.h $(BINARIES)
|
||||||
$(MAKE) -C $(BUILD_DIR) libqemuutil.a
|
|
||||||
|
|
||||||
$(BUILD_DIR)/config-host.h:
|
|
||||||
$(MAKE) -C $(BUILD_DIR) config-host.h
|
|
||||||
|
|
||||||
# libtestfloat.a depends on libsoftfloat.a, so specify it first
|
# libtestfloat.a depends on libsoftfloat.a, so specify it first
|
||||||
FP_TEST_LIBS := libtestfloat.a libsoftfloat.a $(LIBQEMUUTIL)
|
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
|
memory: CFLAGS+=-DCHECK_UNALIGNED=1
|
||||||
|
|
||||||
# Running
|
# 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
|
# Simple Record/Replay Test
|
||||||
.PHONY: memory-record
|
.PHONY: memory-record
|
||||||
|
|
|
@ -32,4 +32,11 @@ run-plugin-semihosting-with-%:
|
||||||
$(call strip-plugin,$<) 2> $<.err, \
|
$(call strip-plugin,$<) 2> $<.err, \
|
||||||
"$< on $(TARGET_NAME) with $*")
|
"$< 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)
|
TESTS += $(AARCH64_TESTS)
|
||||||
|
|
|
@ -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
|
# Semihosting smoke test for linux-user
|
||||||
ARM_TESTS += semihosting
|
ARM_TESTS += semihosting
|
||||||
|
semihosting: CFLAGS += -mthumb
|
||||||
run-semihosting: semihosting
|
run-semihosting: semihosting
|
||||||
$(call run-test,$<,$(QEMU) $< 2> $<.err, "$< on $(TARGET_NAME)")
|
$(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-%:
|
run-plugin-semihosting-with-%:
|
||||||
$(call run-test, $@, $(QEMU) $(QEMU_OPTS) \
|
$(call run-test, $@, $(QEMU) $(QEMU_OPTS) \
|
||||||
-plugin $(PLUGIN_DIR)/$(call extract-plugin,$@) \
|
-plugin $(PLUGIN_DIR)/$(call extract-plugin,$@) \
|
||||||
$(call strip-plugin,$<) 2> $<.err, \
|
$(call strip-plugin,$<) 2> $<.err, \
|
||||||
"$< on $(TARGET_NAME) with $*")
|
"$< 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)
|
TESTS += $(ARM_TESTS)
|
||||||
|
|
||||||
# On ARM Linux only supports 4k pages
|
# On ARM Linux only supports 4k pages
|
||||||
|
|
|
@ -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;
|
||||||
|
}
|
|
@ -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>
|
#include <stdint.h>
|
||||||
|
#include "semicall.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
|
|
||||||
}
|
|
||||||
|
|
||||||
int main(int argc, char *argv[argc])
|
int main(int argc, char *argv[argc])
|
||||||
{
|
{
|
||||||
|
|
|
@ -32,6 +32,7 @@ class FreeBSDVM(basevm.BaseVM):
|
||||||
"git",
|
"git",
|
||||||
"pkgconf",
|
"pkgconf",
|
||||||
"bzip2",
|
"bzip2",
|
||||||
|
"python37",
|
||||||
|
|
||||||
# gnu tools
|
# gnu tools
|
||||||
"bash",
|
"bash",
|
||||||
|
@ -63,7 +64,7 @@ class FreeBSDVM(basevm.BaseVM):
|
||||||
mkdir src build; cd src;
|
mkdir src build; cd src;
|
||||||
tar -xf /dev/vtbd1;
|
tar -xf /dev/vtbd1;
|
||||||
cd ../build
|
cd ../build
|
||||||
../src/configure --python=python3.6 {configure_opts};
|
../src/configure --python=python3.7 {configure_opts};
|
||||||
gmake --output-sync -j{jobs} {target} {verbose};
|
gmake --output-sync -j{jobs} {target} {verbose};
|
||||||
"""
|
"""
|
||||||
|
|
||||||
|
|
|
@ -22,8 +22,8 @@ class OpenBSDVM(basevm.BaseVM):
|
||||||
name = "openbsd"
|
name = "openbsd"
|
||||||
arch = "x86_64"
|
arch = "x86_64"
|
||||||
|
|
||||||
link = "https://cdn.openbsd.org/pub/OpenBSD/6.5/amd64/install65.iso"
|
link = "https://cdn.openbsd.org/pub/OpenBSD/6.6/amd64/install66.iso"
|
||||||
csum = "38d1f8cadd502f1c27bf05c5abde6cc505dd28f3f34f8a941048ff9a54f9f608"
|
csum = "b22e63df56e6266de6bbeed8e9be0fbe9ee2291551c5bc03f3cc2e4ab9436ee3"
|
||||||
size = "20G"
|
size = "20G"
|
||||||
pkgs = [
|
pkgs = [
|
||||||
# tools
|
# 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"),
|
qemu_opts_foreach(qemu_find_opts("mon"),
|
||||||
mon_init_func, NULL, &error_fatal);
|
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)
|
if (foreach_device_config(DEV_SERIAL, serial_parse) < 0)
|
||||||
exit(1);
|
exit(1);
|
||||||
if (foreach_device_config(DEV_PARALLEL, parallel_parse) < 0)
|
if (foreach_device_config(DEV_PARALLEL, parallel_parse) < 0)
|
||||||
|
|
Loading…
Reference in New Issue