aboutsummaryrefslogtreecommitdiff
path: root/target/riscv
diff options
context:
space:
mode:
authorPeter Maydell <peter.maydell@linaro.org>2021-01-18 12:09:21 +0000
committerPeter Maydell <peter.maydell@linaro.org>2021-01-18 12:10:20 +0000
commit8814b1327c0070d440ec1480888b77eb27af43f8 (patch)
treeffce6d3e1dedb1ed10f08f70a4b17a3271171a30 /target/riscv
parent20b8016ed847ac751e508c38aa27a9f8ecb93ac8 (diff)
parent767ba049b8f8f8ebfebe90ecaf1b5a9cf8c865ff (diff)
downloadqemu-8814b1327c0070d440ec1480888b77eb27af43f8.zip
qemu-8814b1327c0070d440ec1480888b77eb27af43f8.tar.gz
qemu-8814b1327c0070d440ec1480888b77eb27af43f8.tar.bz2
Merge remote-tracking branch 'remotes/stsquad/tags/pull-testing-and-misc-180121-2' into staging
Testing, gdbstub and semihosting patches: - clean-ups to docker images - drop duplicate jobs from shippable - prettier tag generation (+gtags) - generate browsable source tree - more Travis->GitLab migrations - fix checkpatch to deal with commits - gate gdbstub tests on 8.3.1, expand tests - support Xfer:auxv:read gdb packet - better gdbstub cleanup - use GDB's SVE register layout - make arm-compat-semihosting common - add riscv semihosting support - add HEAPINFO, ELAPSED, TICKFREQ, TMPNAM and ISERROR to semihosting # gpg: Signature made Mon 18 Jan 2021 10:09:11 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-misc-180121-2: (30 commits) semihosting: Implement SYS_ISERROR semihosting: Implement SYS_TMPNAM semihosting: Implement SYS_ELAPSED and SYS_TICKFREQ riscv: Add semihosting support for user mode riscv: Add semihosting support semihosting: Support SYS_HEAPINFO when env->boot_info is not set semihosting: Change internal common-semi interfaces to use CPUState * semihosting: Change common-semi API to be architecture-independent semihosting: Move ARM semihosting code to shared directories target/arm: use official org.gnu.gdb.aarch64.sve layout for registers gdbstub: ensure we clean-up when terminated gdbstub: drop gdbserver_cleanup in favour of gdb_exit gdbstub: drop CPUEnv from gdb_exit() gdbstub: add support to Xfer:auxv:read: packet gdbstub: implement a softmmu based test Revert "tests/tcg/multiarch/Makefile.target: Disable run-gdbstub-sha1 test" configure: gate our use of GDB to 8.3.1 or above test/guest-debug: echo QEMU command as well scripts/checkpatch.pl: fix git-show invocation to include diffstat gitlab: migrate the minimal tools and unit tests from Travis ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org> # Conflicts: # default-configs/targets/riscv32-linux-user.mak # default-configs/targets/riscv64-linux-user.mak
Diffstat (limited to 'target/riscv')
-rw-r--r--target/riscv/cpu_bits.h1
-rw-r--r--target/riscv/cpu_helper.c10
-rw-r--r--target/riscv/insn_trans/trans_privileged.c.inc37
-rw-r--r--target/riscv/translate.c11
4 files changed, 58 insertions, 1 deletions
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index b41e883..4196ef8 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -542,6 +542,7 @@
#define RISCV_EXCP_INST_PAGE_FAULT 0xc /* since: priv-1.10.0 */
#define RISCV_EXCP_LOAD_PAGE_FAULT 0xd /* since: priv-1.10.0 */
#define RISCV_EXCP_STORE_PAGE_FAULT 0xf /* since: priv-1.10.0 */
+#define RISCV_EXCP_SEMIHOST 0x10
#define RISCV_EXCP_INST_GUEST_PAGE_FAULT 0x14
#define RISCV_EXCP_LOAD_GUEST_ACCESS_FAULT 0x15
#define RISCV_EXCP_VIRT_INSTRUCTION_FAULT 0x16
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index a2afb95..f8350f5 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -24,6 +24,7 @@
#include "exec/exec-all.h"
#include "tcg/tcg-op.h"
#include "trace.h"
+#include "hw/semihosting/common-semi.h"
int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch)
{
@@ -847,6 +848,15 @@ void riscv_cpu_do_interrupt(CPUState *cs)
target_ulong htval = 0;
target_ulong mtval2 = 0;
+ if (cause == RISCV_EXCP_SEMIHOST) {
+ if (env->priv >= PRV_S) {
+ env->gpr[xA0] = do_common_semihosting(cs);
+ env->pc += 4;
+ return;
+ }
+ cause = RISCV_EXCP_BREAKPOINT;
+ }
+
if (!async) {
/* set tval to badaddr for traps with address information */
switch (cause) {
diff --git a/target/riscv/insn_trans/trans_privileged.c.inc b/target/riscv/insn_trans/trans_privileged.c.inc
index 2a61a85..32312be 100644
--- a/target/riscv/insn_trans/trans_privileged.c.inc
+++ b/target/riscv/insn_trans/trans_privileged.c.inc
@@ -29,7 +29,42 @@ static bool trans_ecall(DisasContext *ctx, arg_ecall *a)
static bool trans_ebreak(DisasContext *ctx, arg_ebreak *a)
{
- generate_exception(ctx, RISCV_EXCP_BREAKPOINT);
+ target_ulong ebreak_addr = ctx->base.pc_next;
+ target_ulong pre_addr = ebreak_addr - 4;
+ target_ulong post_addr = ebreak_addr + 4;
+ uint32_t pre = 0;
+ uint32_t ebreak = 0;
+ uint32_t post = 0;
+
+ /*
+ * The RISC-V semihosting spec specifies the following
+ * three-instruction sequence to flag a semihosting call:
+ *
+ * slli zero, zero, 0x1f 0x01f01013
+ * ebreak 0x00100073
+ * srai zero, zero, 0x7 0x40705013
+ *
+ * The two shift operations on the zero register are no-ops, used
+ * here to signify a semihosting exception, rather than a breakpoint.
+ *
+ * Uncompressed instructions are required so that the sequence is easy
+ * to validate.
+ *
+ * The three instructions are required to lie in the same page so
+ * that no exception will be raised when fetching them.
+ */
+
+ if ((pre_addr & TARGET_PAGE_MASK) == (post_addr & TARGET_PAGE_MASK)) {
+ pre = opcode_at(&ctx->base, pre_addr);
+ ebreak = opcode_at(&ctx->base, ebreak_addr);
+ post = opcode_at(&ctx->base, post_addr);
+ }
+
+ if (pre == 0x01f01013 && ebreak == 0x00100073 && post == 0x40705013) {
+ generate_exception(ctx, RISCV_EXCP_SEMIHOST);
+ } else {
+ generate_exception(ctx, RISCV_EXCP_BREAKPOINT);
+ }
exit_tb(ctx); /* no chaining */
ctx->base.is_jmp = DISAS_NORETURN;
return true;
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 554d52a..0f28b5f 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -64,6 +64,7 @@ typedef struct DisasContext {
uint16_t vlen;
uint16_t mlen;
bool vl_eq_vlmax;
+ CPUState *cs;
} DisasContext;
#ifdef TARGET_RISCV64
@@ -747,6 +748,15 @@ static bool gen_shift(DisasContext *ctx, arg_r *a,
return true;
}
+static uint32_t opcode_at(DisasContextBase *dcbase, target_ulong pc)
+{
+ DisasContext *ctx = container_of(dcbase, DisasContext, base);
+ CPUState *cpu = ctx->cs;
+ CPURISCVState *env = cpu->env_ptr;
+
+ return cpu_ldl_code(env, pc);
+}
+
/* Include insn module translation function */
#include "insn_trans/trans_rvi.c.inc"
#include "insn_trans/trans_rvm.c.inc"
@@ -814,6 +824,7 @@ static void riscv_tr_init_disas_context(DisasContextBase *dcbase, CPUState *cs)
ctx->lmul = FIELD_EX32(tb_flags, TB_FLAGS, LMUL);
ctx->mlen = 1 << (ctx->sew + 3 - ctx->lmul);
ctx->vl_eq_vlmax = FIELD_EX32(tb_flags, TB_FLAGS, VL_EQ_VLMAX);
+ ctx->cs = cs;
}
static void riscv_tr_tb_start(DisasContextBase *db, CPUState *cpu)