Browse Source
* Add a property to set vl to ceil(AVL/2) * Enable numamem testing for RISC-V * Consider MISA bit choice in implied rule * Fix the za64rs priv spec requirements * Enable Bit Manip for OpenTitan Ibex CPU * Fix the group bit setting of AIA with KVM * Stop timer with infinite timecmp * Add 'fcsr' register to QEMU log as a part of F extension * Fix riscv64 build on musl libc * Add preliminary textra trigger CSR functions * RISC-V bsd-user support * Respect firmware ELF entry point * Add Svvptc extension support * Fix masking of rv32 physical address * Fix linking problem with semihosting disabled * Fix IMSIC interrupt state updates -----BEGIN PGP SIGNATURE----- iQIzBAABCAAdFiEEaukCtqfKh31tZZKWr3yVEwxTgBMFAmb83lYACgkQr3yVEwxT gBNndBAAmh66yWt9TeTHlQ/rgBhx2nUMBbfICBWQyNGvPlslffwrNoLkh8jpkuiP PD0RQArAAGeM09cgCZCu14JzIBmmNiGgUxsUnqOZvUw18uIlLFlpt/tiT7iGw/Xb pfI7waF66/FPXBErY2yiw9/RGQLlkiGNBC9FNYrD/kCahf9MSIobv85tOgSQ2qjH nOJ+UBN0TQ1x0Z5lJMj9Pzl1WDvelRnCkYI5nXg1heKG73Hm7GmHt99QpTV2Okqn T3jFzEfMTQeHO4nC/X2pbaesE62K+mTg/FZpId2iV8lMCSm1zKof+xJ4boKM9RB2 0HjXAT+MveLuLUNtgfbV9C+VgU25M+wnfy5tH0l801Y/Gez8Q1fbK2uykuiyiUSy MNNk/KzmOYuffwItuyeL3mmWHXsN+izUIeMmMxfL9X9nssZXRsrDXc+MByS7w0fk QOeZmXHTxXwxFymr0t0DLK2eKEG6cqQty1KWp6iLx3uwnMTGo+576P41Q+boj64s VllWzmuR0Ta0xuSR4sDvEFCO7OCFEgVdn1j0FvhRFskPEDrbQgXRLq8i3awtU6z1 NIh+A30XeK+EZLv0sEje6gav5lZHWMfAeCOKJstVzOl8+NQibuKTUrsqLgTrBK6K plw8qwvZYjSnYErzHfywlq9ArufIvOHYcx9Nb76tLNy9E+y01yo= =15Hm -----END PGP SIGNATURE----- Merge tag 'pull-riscv-to-apply-20241002' of https://github.com/alistair23/qemu into staging RISC-V PR for 9.2 * Add a property to set vl to ceil(AVL/2) * Enable numamem testing for RISC-V * Consider MISA bit choice in implied rule * Fix the za64rs priv spec requirements * Enable Bit Manip for OpenTitan Ibex CPU * Fix the group bit setting of AIA with KVM * Stop timer with infinite timecmp * Add 'fcsr' register to QEMU log as a part of F extension * Fix riscv64 build on musl libc * Add preliminary textra trigger CSR functions * RISC-V bsd-user support * Respect firmware ELF entry point * Add Svvptc extension support * Fix masking of rv32 physical address * Fix linking problem with semihosting disabled * Fix IMSIC interrupt state updates # -----BEGIN PGP SIGNATURE----- # # iQIzBAABCAAdFiEEaukCtqfKh31tZZKWr3yVEwxTgBMFAmb83lYACgkQr3yVEwxT # gBNndBAAmh66yWt9TeTHlQ/rgBhx2nUMBbfICBWQyNGvPlslffwrNoLkh8jpkuiP # PD0RQArAAGeM09cgCZCu14JzIBmmNiGgUxsUnqOZvUw18uIlLFlpt/tiT7iGw/Xb # pfI7waF66/FPXBErY2yiw9/RGQLlkiGNBC9FNYrD/kCahf9MSIobv85tOgSQ2qjH # nOJ+UBN0TQ1x0Z5lJMj9Pzl1WDvelRnCkYI5nXg1heKG73Hm7GmHt99QpTV2Okqn # T3jFzEfMTQeHO4nC/X2pbaesE62K+mTg/FZpId2iV8lMCSm1zKof+xJ4boKM9RB2 # 0HjXAT+MveLuLUNtgfbV9C+VgU25M+wnfy5tH0l801Y/Gez8Q1fbK2uykuiyiUSy # MNNk/KzmOYuffwItuyeL3mmWHXsN+izUIeMmMxfL9X9nssZXRsrDXc+MByS7w0fk # QOeZmXHTxXwxFymr0t0DLK2eKEG6cqQty1KWp6iLx3uwnMTGo+576P41Q+boj64s # VllWzmuR0Ta0xuSR4sDvEFCO7OCFEgVdn1j0FvhRFskPEDrbQgXRLq8i3awtU6z1 # NIh+A30XeK+EZLv0sEje6gav5lZHWMfAeCOKJstVzOl8+NQibuKTUrsqLgTrBK6K # plw8qwvZYjSnYErzHfywlq9ArufIvOHYcx9Nb76tLNy9E+y01yo= # =15Hm # -----END PGP SIGNATURE----- # gpg: Signature made Wed 02 Oct 2024 06:47:02 BST # gpg: using RSA key 6AE902B6A7CA877D6D659296AF7C95130C538013 # gpg: Good signature from "Alistair Francis <alistair@alistair23.me>" [unknown] # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: 6AE9 02B6 A7CA 877D 6D65 9296 AF7C 9513 0C53 8013 * tag 'pull-riscv-to-apply-20241002' of https://github.com/alistair23/qemu: (35 commits) bsd-user: Add RISC-V 64-bit Target Configuration and Debug XML Files bsd-user: Implement set_mcontext and get_ucontext_sigreturn for RISCV bsd-user: Implement 'get_mcontext' for RISC-V bsd-user: Implement RISC-V signal trampoline setup functions bsd-user: Define RISC-V signal handling structures and constants bsd-user: Add generic RISC-V64 target definitions bsd-user: Define RISC-V system call structures and constants bsd-user: Define RISC-V VM parameters and helper functions bsd-user: Add RISC-V thread setup and initialization support bsd-user: Implement RISC-V sysarch system call emulation bsd-user: Add RISC-V signal trampoline setup function bsd-user: Define RISC-V register structures and register copying bsd-user: Add RISC-V ELF definitions and hardware capability detection bsd-user: Implement RISC-V TLS register setup bsd-user: Implement RISC-V CPU register cloning and reset functions bsd-user: Add RISC-V CPU execution loop and syscall handling bsd-user: Implement RISC-V CPU initialization and main loop hw/intc: riscv-imsic: Fix interrupt state updates. target/riscv/cpu_helper: Fix linking problem with semihosting disabled target/riscv32: Fix masking of physical address ... Signed-off-by: Peter Maydell <peter.maydell@linaro.org>pull/271/head
37 changed files with 1068 additions and 57 deletions
@ -0,0 +1,170 @@ |
|||
/*
|
|||
* RISC-V signal definitions |
|||
* |
|||
* Copyright (c) 2019 Mark Corbin |
|||
* |
|||
* This program is free software; you can redistribute it and/or modify |
|||
* it under the terms of the GNU General Public License as published by |
|||
* the Free Software Foundation; either version 2 of the License, or |
|||
* (at your option) any later version. |
|||
* |
|||
* This program 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 General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
#include "qemu/osdep.h" |
|||
|
|||
#include "qemu.h" |
|||
|
|||
/*
|
|||
* Compare with sendsig() in riscv/riscv/exec_machdep.c |
|||
* Assumes that target stack frame memory is locked. |
|||
*/ |
|||
abi_long |
|||
set_sigtramp_args(CPURISCVState *regs, int sig, struct target_sigframe *frame, |
|||
abi_ulong frame_addr, struct target_sigaction *ka) |
|||
{ |
|||
/*
|
|||
* Arguments to signal handler: |
|||
* a0 (10) = signal number |
|||
* a1 (11) = siginfo pointer |
|||
* a2 (12) = ucontext pointer |
|||
* pc = signal pointer handler |
|||
* sp (2) = sigframe pointer |
|||
* ra (1) = sigtramp at base of user stack |
|||
*/ |
|||
|
|||
regs->gpr[xA0] = sig; |
|||
regs->gpr[xA1] = frame_addr + |
|||
offsetof(struct target_sigframe, sf_si); |
|||
regs->gpr[xA2] = frame_addr + |
|||
offsetof(struct target_sigframe, sf_uc); |
|||
regs->pc = ka->_sa_handler; |
|||
regs->gpr[xSP] = frame_addr; |
|||
regs->gpr[xRA] = TARGET_PS_STRINGS - TARGET_SZSIGCODE; |
|||
return 0; |
|||
} |
|||
|
|||
/*
|
|||
* Compare to riscv/riscv/exec_machdep.c sendsig() |
|||
* Assumes that the memory is locked if frame points to user memory. |
|||
*/ |
|||
abi_long setup_sigframe_arch(CPURISCVState *env, abi_ulong frame_addr, |
|||
struct target_sigframe *frame, int flags) |
|||
{ |
|||
target_mcontext_t *mcp = &frame->sf_uc.uc_mcontext; |
|||
|
|||
get_mcontext(env, mcp, flags); |
|||
return 0; |
|||
} |
|||
|
|||
/*
|
|||
* Compare with get_mcontext() in riscv/riscv/machdep.c |
|||
* Assumes that the memory is locked if mcp points to user memory. |
|||
*/ |
|||
abi_long get_mcontext(CPURISCVState *regs, target_mcontext_t *mcp, |
|||
int flags) |
|||
{ |
|||
|
|||
mcp->mc_gpregs.gp_t[0] = tswap64(regs->gpr[5]); |
|||
mcp->mc_gpregs.gp_t[1] = tswap64(regs->gpr[6]); |
|||
mcp->mc_gpregs.gp_t[2] = tswap64(regs->gpr[7]); |
|||
mcp->mc_gpregs.gp_t[3] = tswap64(regs->gpr[28]); |
|||
mcp->mc_gpregs.gp_t[4] = tswap64(regs->gpr[29]); |
|||
mcp->mc_gpregs.gp_t[5] = tswap64(regs->gpr[30]); |
|||
mcp->mc_gpregs.gp_t[6] = tswap64(regs->gpr[31]); |
|||
|
|||
mcp->mc_gpregs.gp_s[0] = tswap64(regs->gpr[8]); |
|||
mcp->mc_gpregs.gp_s[1] = tswap64(regs->gpr[9]); |
|||
mcp->mc_gpregs.gp_s[2] = tswap64(regs->gpr[18]); |
|||
mcp->mc_gpregs.gp_s[3] = tswap64(regs->gpr[19]); |
|||
mcp->mc_gpregs.gp_s[4] = tswap64(regs->gpr[20]); |
|||
mcp->mc_gpregs.gp_s[5] = tswap64(regs->gpr[21]); |
|||
mcp->mc_gpregs.gp_s[6] = tswap64(regs->gpr[22]); |
|||
mcp->mc_gpregs.gp_s[7] = tswap64(regs->gpr[23]); |
|||
mcp->mc_gpregs.gp_s[8] = tswap64(regs->gpr[24]); |
|||
mcp->mc_gpregs.gp_s[9] = tswap64(regs->gpr[25]); |
|||
mcp->mc_gpregs.gp_s[10] = tswap64(regs->gpr[26]); |
|||
mcp->mc_gpregs.gp_s[11] = tswap64(regs->gpr[27]); |
|||
|
|||
mcp->mc_gpregs.gp_a[0] = tswap64(regs->gpr[10]); |
|||
mcp->mc_gpregs.gp_a[1] = tswap64(regs->gpr[11]); |
|||
mcp->mc_gpregs.gp_a[2] = tswap64(regs->gpr[12]); |
|||
mcp->mc_gpregs.gp_a[3] = tswap64(regs->gpr[13]); |
|||
mcp->mc_gpregs.gp_a[4] = tswap64(regs->gpr[14]); |
|||
mcp->mc_gpregs.gp_a[5] = tswap64(regs->gpr[15]); |
|||
mcp->mc_gpregs.gp_a[6] = tswap64(regs->gpr[16]); |
|||
mcp->mc_gpregs.gp_a[7] = tswap64(regs->gpr[17]); |
|||
|
|||
if (flags & TARGET_MC_GET_CLEAR_RET) { |
|||
mcp->mc_gpregs.gp_a[0] = 0; /* a0 */ |
|||
mcp->mc_gpregs.gp_a[1] = 0; /* a1 */ |
|||
mcp->mc_gpregs.gp_t[0] = 0; /* clear syscall error */ |
|||
} |
|||
|
|||
mcp->mc_gpregs.gp_ra = tswap64(regs->gpr[1]); |
|||
mcp->mc_gpregs.gp_sp = tswap64(regs->gpr[2]); |
|||
mcp->mc_gpregs.gp_gp = tswap64(regs->gpr[3]); |
|||
mcp->mc_gpregs.gp_tp = tswap64(regs->gpr[4]); |
|||
mcp->mc_gpregs.gp_sepc = tswap64(regs->pc); |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
/* Compare with set_mcontext() in riscv/riscv/exec_machdep.c */ |
|||
abi_long set_mcontext(CPURISCVState *regs, target_mcontext_t *mcp, |
|||
int srflag) |
|||
{ |
|||
|
|||
regs->gpr[5] = tswap64(mcp->mc_gpregs.gp_t[0]); |
|||
regs->gpr[6] = tswap64(mcp->mc_gpregs.gp_t[1]); |
|||
regs->gpr[7] = tswap64(mcp->mc_gpregs.gp_t[2]); |
|||
regs->gpr[28] = tswap64(mcp->mc_gpregs.gp_t[3]); |
|||
regs->gpr[29] = tswap64(mcp->mc_gpregs.gp_t[4]); |
|||
regs->gpr[30] = tswap64(mcp->mc_gpregs.gp_t[5]); |
|||
regs->gpr[31] = tswap64(mcp->mc_gpregs.gp_t[6]); |
|||
|
|||
regs->gpr[8] = tswap64(mcp->mc_gpregs.gp_s[0]); |
|||
regs->gpr[9] = tswap64(mcp->mc_gpregs.gp_s[1]); |
|||
regs->gpr[18] = tswap64(mcp->mc_gpregs.gp_s[2]); |
|||
regs->gpr[19] = tswap64(mcp->mc_gpregs.gp_s[3]); |
|||
regs->gpr[20] = tswap64(mcp->mc_gpregs.gp_s[4]); |
|||
regs->gpr[21] = tswap64(mcp->mc_gpregs.gp_s[5]); |
|||
regs->gpr[22] = tswap64(mcp->mc_gpregs.gp_s[6]); |
|||
regs->gpr[23] = tswap64(mcp->mc_gpregs.gp_s[7]); |
|||
regs->gpr[24] = tswap64(mcp->mc_gpregs.gp_s[8]); |
|||
regs->gpr[25] = tswap64(mcp->mc_gpregs.gp_s[9]); |
|||
regs->gpr[26] = tswap64(mcp->mc_gpregs.gp_s[10]); |
|||
regs->gpr[27] = tswap64(mcp->mc_gpregs.gp_s[11]); |
|||
|
|||
regs->gpr[10] = tswap64(mcp->mc_gpregs.gp_a[0]); |
|||
regs->gpr[11] = tswap64(mcp->mc_gpregs.gp_a[1]); |
|||
regs->gpr[12] = tswap64(mcp->mc_gpregs.gp_a[2]); |
|||
regs->gpr[13] = tswap64(mcp->mc_gpregs.gp_a[3]); |
|||
regs->gpr[14] = tswap64(mcp->mc_gpregs.gp_a[4]); |
|||
regs->gpr[15] = tswap64(mcp->mc_gpregs.gp_a[5]); |
|||
regs->gpr[16] = tswap64(mcp->mc_gpregs.gp_a[6]); |
|||
regs->gpr[17] = tswap64(mcp->mc_gpregs.gp_a[7]); |
|||
|
|||
|
|||
regs->gpr[1] = tswap64(mcp->mc_gpregs.gp_ra); |
|||
regs->gpr[2] = tswap64(mcp->mc_gpregs.gp_sp); |
|||
regs->gpr[3] = tswap64(mcp->mc_gpregs.gp_gp); |
|||
regs->gpr[4] = tswap64(mcp->mc_gpregs.gp_tp); |
|||
regs->pc = tswap64(mcp->mc_gpregs.gp_sepc); |
|||
|
|||
return 0; |
|||
} |
|||
|
|||
/* Compare with sys_sigreturn() in riscv/riscv/machdep.c */ |
|||
abi_long get_ucontext_sigreturn(CPURISCVState *regs, |
|||
abi_ulong target_sf, abi_ulong *target_uc) |
|||
{ |
|||
|
|||
*target_uc = target_sf; |
|||
return 0; |
|||
} |
|||
@ -0,0 +1,20 @@ |
|||
/*
|
|||
* Riscv64 general target stuff that's common to all aarch details |
|||
* |
|||
* Copyright (c) 2022 M. Warner Losh <imp@bsdimp.com> |
|||
* |
|||
* SPDX-License-Identifier: GPL-2.0-or-later |
|||
*/ |
|||
|
|||
#ifndef TARGET_H |
|||
#define TARGET_H |
|||
|
|||
/*
|
|||
* riscv64 ABI does not 'lump' the registers for 64-bit args. |
|||
*/ |
|||
static inline bool regpairs_aligned(void *cpu_env) |
|||
{ |
|||
return false; |
|||
} |
|||
|
|||
#endif /* TARGET_H */ |
|||
@ -0,0 +1,27 @@ |
|||
/*
|
|||
* RISC-V specific prototypes |
|||
* |
|||
* Copyright (c) 2019 Mark Corbin <mark.corbin@embecsom.com> |
|||
* |
|||
* 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 TARGET_ARCH_H |
|||
#define TARGET_ARCH_H |
|||
|
|||
#include "qemu.h" |
|||
|
|||
void target_cpu_set_tls(CPURISCVState *env, target_ulong newtls); |
|||
|
|||
#endif /* TARGET_ARCH_H */ |
|||
@ -0,0 +1,29 @@ |
|||
/*
|
|||
* RISC-V CPU related code |
|||
* |
|||
* Copyright (c) 2019 Mark Corbin |
|||
* |
|||
* This program is free software; you can redistribute it and/or modify |
|||
* it under the terms of the GNU General Public License as published by |
|||
* the Free Software Foundation; either version 2 of the License, or |
|||
* (at your option) any later version. |
|||
* |
|||
* This program 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 General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
#include "qemu/osdep.h" |
|||
|
|||
#include "target_arch.h" |
|||
|
|||
#define TP_OFFSET 16 |
|||
|
|||
/* Compare with cpu_set_user_tls() in riscv/riscv/vm_machdep.c */ |
|||
void target_cpu_set_tls(CPURISCVState *env, target_ulong newtls) |
|||
{ |
|||
env->gpr[xTP] = newtls + TP_OFFSET; |
|||
} |
|||
@ -0,0 +1,148 @@ |
|||
/*
|
|||
* RISC-V CPU init and loop |
|||
* |
|||
* Copyright (c) 2019 Mark Corbin |
|||
* |
|||
* This program is free software; you can redistribute it and/or modify |
|||
* it under the terms of the GNU General Public License as published by |
|||
* the Free Software Foundation; either version 2 of the License, or |
|||
* (at your option) any later version. |
|||
* |
|||
* This program 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 General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
|
|||
#ifndef TARGET_ARCH_CPU_H |
|||
#define TARGET_ARCH_CPU_H |
|||
|
|||
#include "target_arch.h" |
|||
#include "signal-common.h" |
|||
|
|||
#define TARGET_DEFAULT_CPU_MODEL "max" |
|||
|
|||
static inline void target_cpu_init(CPURISCVState *env, |
|||
struct target_pt_regs *regs) |
|||
{ |
|||
int i; |
|||
|
|||
for (i = 1; i < 32; i++) { |
|||
env->gpr[i] = regs->regs[i]; |
|||
} |
|||
|
|||
env->pc = regs->sepc; |
|||
} |
|||
|
|||
static inline void target_cpu_loop(CPURISCVState *env) |
|||
{ |
|||
CPUState *cs = env_cpu(env); |
|||
int trapnr; |
|||
abi_long ret; |
|||
unsigned int syscall_num; |
|||
int32_t signo, code; |
|||
|
|||
for (;;) { |
|||
cpu_exec_start(cs); |
|||
trapnr = cpu_exec(cs); |
|||
cpu_exec_end(cs); |
|||
process_queued_cpu_work(cs); |
|||
|
|||
signo = 0; |
|||
|
|||
switch (trapnr) { |
|||
case EXCP_INTERRUPT: |
|||
/* just indicate that signals should be handled asap */ |
|||
break; |
|||
case EXCP_ATOMIC: |
|||
cpu_exec_step_atomic(cs); |
|||
break; |
|||
case RISCV_EXCP_U_ECALL: |
|||
syscall_num = env->gpr[xT0]; |
|||
env->pc += TARGET_INSN_SIZE; |
|||
/* Compare to cpu_fetch_syscall_args() in riscv/riscv/trap.c */ |
|||
if (TARGET_FREEBSD_NR___syscall == syscall_num || |
|||
TARGET_FREEBSD_NR_syscall == syscall_num) { |
|||
ret = do_freebsd_syscall(env, |
|||
env->gpr[xA0], |
|||
env->gpr[xA1], |
|||
env->gpr[xA2], |
|||
env->gpr[xA3], |
|||
env->gpr[xA4], |
|||
env->gpr[xA5], |
|||
env->gpr[xA6], |
|||
env->gpr[xA7], |
|||
0); |
|||
} else { |
|||
ret = do_freebsd_syscall(env, |
|||
syscall_num, |
|||
env->gpr[xA0], |
|||
env->gpr[xA1], |
|||
env->gpr[xA2], |
|||
env->gpr[xA3], |
|||
env->gpr[xA4], |
|||
env->gpr[xA5], |
|||
env->gpr[xA6], |
|||
env->gpr[xA7] |
|||
); |
|||
} |
|||
|
|||
/*
|
|||
* Compare to cpu_set_syscall_retval() in |
|||
* riscv/riscv/vm_machdep.c |
|||
*/ |
|||
if (ret >= 0) { |
|||
env->gpr[xA0] = ret; |
|||
env->gpr[xT0] = 0; |
|||
} else if (ret == -TARGET_ERESTART) { |
|||
env->pc -= TARGET_INSN_SIZE; |
|||
} else if (ret != -TARGET_EJUSTRETURN) { |
|||
env->gpr[xA0] = -ret; |
|||
env->gpr[xT0] = 1; |
|||
} |
|||
break; |
|||
case RISCV_EXCP_ILLEGAL_INST: |
|||
signo = TARGET_SIGILL; |
|||
code = TARGET_ILL_ILLOPC; |
|||
break; |
|||
case RISCV_EXCP_BREAKPOINT: |
|||
signo = TARGET_SIGTRAP; |
|||
code = TARGET_TRAP_BRKPT; |
|||
break; |
|||
case EXCP_DEBUG: |
|||
signo = TARGET_SIGTRAP; |
|||
code = TARGET_TRAP_BRKPT; |
|||
break; |
|||
default: |
|||
fprintf(stderr, "qemu: unhandled CPU exception " |
|||
"0x%x - aborting\n", trapnr); |
|||
cpu_dump_state(cs, stderr, 0); |
|||
abort(); |
|||
} |
|||
|
|||
if (signo) { |
|||
force_sig_fault(signo, code, env->pc); |
|||
} |
|||
|
|||
process_pending_signals(env); |
|||
} |
|||
} |
|||
|
|||
static inline void target_cpu_clone_regs(CPURISCVState *env, target_ulong newsp) |
|||
{ |
|||
if (newsp) { |
|||
env->gpr[xSP] = newsp; |
|||
} |
|||
|
|||
env->gpr[xA0] = 0; |
|||
env->gpr[xT0] = 0; |
|||
} |
|||
|
|||
static inline void target_cpu_reset(CPUArchState *env) |
|||
{ |
|||
} |
|||
|
|||
#endif /* TARGET_ARCH_CPU_H */ |
|||
@ -0,0 +1,42 @@ |
|||
/*
|
|||
* RISC-V ELF definitions |
|||
* |
|||
* Copyright (c) 2019 Mark Corbin |
|||
* |
|||
* This program is free software; you can redistribute it and/or modify |
|||
* it under the terms of the GNU General Public License as published by |
|||
* the Free Software Foundation; either version 2 of the License, or |
|||
* (at your option) any later version. |
|||
* |
|||
* This program 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 General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
|
|||
#ifndef TARGET_ARCH_ELF_H |
|||
#define TARGET_ARCH_ELF_H |
|||
|
|||
#define elf_check_arch(x) ((x) == EM_RISCV) |
|||
#define ELF_START_MMAP 0x80000000 |
|||
#define ELF_ET_DYN_LOAD_ADDR 0x100000 |
|||
#define ELF_CLASS ELFCLASS64 |
|||
|
|||
#define ELF_DATA ELFDATA2LSB |
|||
#define ELF_ARCH EM_RISCV |
|||
|
|||
#define ELF_HWCAP get_elf_hwcap() |
|||
static uint32_t get_elf_hwcap(void) |
|||
{ |
|||
RISCVCPU *cpu = RISCV_CPU(thread_cpu); |
|||
|
|||
return cpu->env.misa_ext_mask; |
|||
} |
|||
|
|||
#define USE_ELF_CORE_DUMP |
|||
#define ELF_EXEC_PAGESIZE 4096 |
|||
|
|||
#endif /* TARGET_ARCH_ELF_H */ |
|||
@ -0,0 +1,88 @@ |
|||
/*
|
|||
* RISC-V register structures |
|||
* |
|||
* Copyright (c) 2019 Mark Corbin |
|||
* |
|||
* This program is free software; you can redistribute it and/or modify |
|||
* it under the terms of the GNU General Public License as published by |
|||
* the Free Software Foundation; either version 2 of the License, or |
|||
* (at your option) any later version. |
|||
* |
|||
* This program 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 General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
|
|||
#ifndef TARGET_ARCH_REG_H |
|||
#define TARGET_ARCH_REG_H |
|||
|
|||
/* Compare with riscv/include/reg.h */ |
|||
typedef struct target_reg { |
|||
uint64_t ra; /* return address */ |
|||
uint64_t sp; /* stack pointer */ |
|||
uint64_t gp; /* global pointer */ |
|||
uint64_t tp; /* thread pointer */ |
|||
uint64_t t[7]; /* temporaries */ |
|||
uint64_t s[12]; /* saved registers */ |
|||
uint64_t a[8]; /* function arguments */ |
|||
uint64_t sepc; /* exception program counter */ |
|||
uint64_t sstatus; /* status register */ |
|||
} target_reg_t; |
|||
|
|||
typedef struct target_fpreg { |
|||
uint64_t fp_x[32][2]; /* Floating point registers */ |
|||
uint64_t fp_fcsr; /* Floating point control reg */ |
|||
} target_fpreg_t; |
|||
|
|||
#define tswapreg(ptr) tswapal(ptr) |
|||
|
|||
/* Compare with struct trapframe in riscv/include/frame.h */ |
|||
static inline void target_copy_regs(target_reg_t *regs, |
|||
const CPURISCVState *env) |
|||
{ |
|||
|
|||
regs->ra = tswapreg(env->gpr[1]); |
|||
regs->sp = tswapreg(env->gpr[2]); |
|||
regs->gp = tswapreg(env->gpr[3]); |
|||
regs->tp = tswapreg(env->gpr[4]); |
|||
|
|||
regs->t[0] = tswapreg(env->gpr[5]); |
|||
regs->t[1] = tswapreg(env->gpr[6]); |
|||
regs->t[2] = tswapreg(env->gpr[7]); |
|||
regs->t[3] = tswapreg(env->gpr[28]); |
|||
regs->t[4] = tswapreg(env->gpr[29]); |
|||
regs->t[5] = tswapreg(env->gpr[30]); |
|||
regs->t[6] = tswapreg(env->gpr[31]); |
|||
|
|||
regs->s[0] = tswapreg(env->gpr[8]); |
|||
regs->s[1] = tswapreg(env->gpr[9]); |
|||
regs->s[2] = tswapreg(env->gpr[18]); |
|||
regs->s[3] = tswapreg(env->gpr[19]); |
|||
regs->s[4] = tswapreg(env->gpr[20]); |
|||
regs->s[5] = tswapreg(env->gpr[21]); |
|||
regs->s[6] = tswapreg(env->gpr[22]); |
|||
regs->s[7] = tswapreg(env->gpr[23]); |
|||
regs->s[8] = tswapreg(env->gpr[24]); |
|||
regs->s[9] = tswapreg(env->gpr[25]); |
|||
regs->s[10] = tswapreg(env->gpr[26]); |
|||
regs->s[11] = tswapreg(env->gpr[27]); |
|||
|
|||
regs->a[0] = tswapreg(env->gpr[10]); |
|||
regs->a[1] = tswapreg(env->gpr[11]); |
|||
regs->a[2] = tswapreg(env->gpr[12]); |
|||
regs->a[3] = tswapreg(env->gpr[13]); |
|||
regs->a[4] = tswapreg(env->gpr[14]); |
|||
regs->a[5] = tswapreg(env->gpr[15]); |
|||
regs->a[6] = tswapreg(env->gpr[16]); |
|||
regs->a[7] = tswapreg(env->gpr[17]); |
|||
|
|||
regs->sepc = tswapreg(env->pc); |
|||
} |
|||
|
|||
#undef tswapreg |
|||
|
|||
#endif /* TARGET_ARCH_REG_H */ |
|||
@ -0,0 +1,75 @@ |
|||
/*
|
|||
* RISC-V signal definitions |
|||
* |
|||
* Copyright (c) 2019 Mark Corbin |
|||
* |
|||
* This program is free software; you can redistribute it and/or modify |
|||
* it under the terms of the GNU General Public License as published by |
|||
* the Free Software Foundation; either version 2 of the License, or |
|||
* (at your option) any later version. |
|||
* |
|||
* This program 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 General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
|
|||
#ifndef TARGET_ARCH_SIGNAL_H |
|||
#define TARGET_ARCH_SIGNAL_H |
|||
|
|||
#include "cpu.h" |
|||
|
|||
|
|||
#define TARGET_INSN_SIZE 4 /* riscv instruction size */ |
|||
|
|||
/* Size of the signal trampoline code placed on the stack. */ |
|||
#define TARGET_SZSIGCODE ((abi_ulong)(7 * TARGET_INSN_SIZE)) |
|||
|
|||
/* Compare with riscv/include/_limits.h */ |
|||
#define TARGET_MINSIGSTKSZ (1024 * 4) |
|||
#define TARGET_SIGSTKSZ (TARGET_MINSIGSTKSZ + 32768) |
|||
|
|||
struct target_gpregs { |
|||
uint64_t gp_ra; |
|||
uint64_t gp_sp; |
|||
uint64_t gp_gp; |
|||
uint64_t gp_tp; |
|||
uint64_t gp_t[7]; |
|||
uint64_t gp_s[12]; |
|||
uint64_t gp_a[8]; |
|||
uint64_t gp_sepc; |
|||
uint64_t gp_sstatus; |
|||
}; |
|||
|
|||
struct target_fpregs { |
|||
uint64_t fp_x[32][2]; |
|||
uint64_t fp_fcsr; |
|||
uint32_t fp_flags; |
|||
uint32_t pad; |
|||
}; |
|||
|
|||
typedef struct target_mcontext { |
|||
struct target_gpregs mc_gpregs; |
|||
struct target_fpregs mc_fpregs; |
|||
uint32_t mc_flags; |
|||
#define TARGET_MC_FP_VALID 0x01 |
|||
uint32_t mc_pad; |
|||
uint64_t mc_spare[8]; |
|||
} target_mcontext_t; |
|||
|
|||
#define TARGET_MCONTEXT_SIZE 864 |
|||
#define TARGET_UCONTEXT_SIZE 936 |
|||
|
|||
#include "target_os_ucontext.h" |
|||
|
|||
struct target_sigframe { |
|||
target_ucontext_t sf_uc; /* = *sf_uncontext */ |
|||
target_siginfo_t sf_si; /* = *sf_siginfo (SA_SIGINFO case)*/ |
|||
}; |
|||
|
|||
#define TARGET_SIGSTACK_ALIGN 16 |
|||
|
|||
#endif /* TARGET_ARCH_SIGNAL_H */ |
|||
@ -0,0 +1,41 @@ |
|||
/*
|
|||
* RISC-V sigcode |
|||
* |
|||
* Copyright (c) 2019 Mark Corbin |
|||
* |
|||
* 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 TARGET_ARCH_SIGTRAMP_H |
|||
#define TARGET_ARCH_SIGTRAMP_H |
|||
|
|||
/* Compare with sigcode() in riscv/riscv/locore.S */ |
|||
static inline abi_long setup_sigtramp(abi_ulong offset, unsigned sigf_uc, |
|||
unsigned sys_sigreturn) |
|||
{ |
|||
uint32_t sys_exit = TARGET_FREEBSD_NR_exit; |
|||
|
|||
uint32_t sigtramp_code[] = { |
|||
/*1*/ const_le32(0x00010513), /*mv a0, sp*/ |
|||
/*2*/ const_le32(0x00050513 + (sigf_uc << 20)), /*addi a0,a0,sigf_uc*/ |
|||
/*3*/ const_le32(0x00000293 + (sys_sigreturn << 20)),/*li t0,sys_sigreturn*/ |
|||
/*4*/ const_le32(0x00000073), /*ecall*/ |
|||
/*5*/ const_le32(0x00000293 + (sys_exit << 20)), /*li t0,sys_exit*/ |
|||
/*6*/ const_le32(0x00000073), /*ecall*/ |
|||
/*7*/ const_le32(0xFF1FF06F) /*b -16*/ |
|||
}; |
|||
|
|||
return memcpy_to_target(offset, sigtramp_code, TARGET_SZSIGCODE); |
|||
} |
|||
#endif /* TARGET_ARCH_SIGTRAMP_H */ |
|||
@ -0,0 +1,41 @@ |
|||
/*
|
|||
* RISC-V sysarch() system call emulation |
|||
* |
|||
* Copyright (c) 2019 Mark Corbin |
|||
* |
|||
* This program is free software; you can redistribute it and/or modify |
|||
* it under the terms of the GNU General Public License as published by |
|||
* the Free Software Foundation; either version 2 of the License, or |
|||
* (at your option) any later version. |
|||
* |
|||
* This program 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 General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
|
|||
#ifndef TARGET_ARCH_SYSARCH_H |
|||
#define TARGET_ARCH_SYSARCH_H |
|||
|
|||
#include "target_syscall.h" |
|||
#include "target_arch.h" |
|||
|
|||
static inline abi_long do_freebsd_arch_sysarch(CPURISCVState *env, int op, |
|||
abi_ulong parms) |
|||
{ |
|||
|
|||
return -TARGET_EOPNOTSUPP; |
|||
} |
|||
|
|||
static inline void do_freebsd_arch_print_sysarch( |
|||
const struct syscallname *name, abi_long arg1, abi_long arg2, |
|||
abi_long arg3, abi_long arg4, abi_long arg5, abi_long arg6) |
|||
{ |
|||
|
|||
gemu_log("UNKNOWN OP: %d, " TARGET_ABI_FMT_lx ")", (int)arg1, arg2); |
|||
} |
|||
|
|||
#endif /* TARGET_ARCH_SYSARCH_H */ |
|||
@ -0,0 +1,47 @@ |
|||
/*
|
|||
* RISC-V thread support |
|||
* |
|||
* Copyright (c) 2019 Mark Corbin |
|||
* |
|||
* This program is free software; you can redistribute it and/or modify |
|||
* it under the terms of the GNU General Public License as published by |
|||
* the Free Software Foundation; either version 2 of the License, or |
|||
* (at your option) any later version. |
|||
* |
|||
* This program 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 General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
|
|||
#ifndef TARGET_ARCH_THREAD_H |
|||
#define TARGET_ARCH_THREAD_H |
|||
|
|||
/* Compare with cpu_set_upcall() in riscv/riscv/vm_machdep.c */ |
|||
static inline void target_thread_set_upcall(CPURISCVState *regs, |
|||
abi_ulong entry, abi_ulong arg, abi_ulong stack_base, |
|||
abi_ulong stack_size) |
|||
{ |
|||
abi_ulong sp; |
|||
|
|||
sp = ROUND_DOWN(stack_base + stack_size, 16); |
|||
|
|||
regs->gpr[xSP] = sp; |
|||
regs->pc = entry; |
|||
regs->gpr[xA0] = arg; |
|||
} |
|||
|
|||
/* Compare with exec_setregs() in riscv/riscv/machdep.c */ |
|||
static inline void target_thread_init(struct target_pt_regs *regs, |
|||
struct image_info *infop) |
|||
{ |
|||
regs->sepc = infop->entry; |
|||
regs->regs[xRA] = infop->entry; |
|||
regs->regs[xA0] = infop->start_stack; |
|||
regs->regs[xSP] = ROUND_DOWN(infop->start_stack, 16); |
|||
} |
|||
|
|||
#endif /* TARGET_ARCH_THREAD_H */ |
|||
@ -0,0 +1,53 @@ |
|||
/*
|
|||
* RISC-V VM parameters definitions |
|||
* |
|||
* Copyright (c) 2019 Mark Corbin |
|||
* |
|||
* This program is free software; you can redistribute it and/or modify |
|||
* it under the terms of the GNU General Public License as published by |
|||
* the Free Software Foundation; either version 2 of the License, or |
|||
* (at your option) any later version. |
|||
* |
|||
* This program 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 General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
|
|||
#ifndef TARGET_ARCH_VMPARAM_H |
|||
#define TARGET_ARCH_VMPARAM_H |
|||
|
|||
#include "cpu.h" |
|||
|
|||
/* Compare with riscv/include/vmparam.h */ |
|||
#define TARGET_MAXTSIZ (1 * GiB) /* max text size */ |
|||
#define TARGET_DFLDSIZ (128 * MiB) /* initial data size limit */ |
|||
#define TARGET_MAXDSIZ (1 * GiB) /* max data size */ |
|||
#define TARGET_DFLSSIZ (128 * MiB) /* initial stack size limit */ |
|||
#define TARGET_MAXSSIZ (1 * GiB) /* max stack size */ |
|||
#define TARGET_SGROWSIZ (128 * KiB) /* amount to grow stack */ |
|||
|
|||
#define TARGET_VM_MINUSER_ADDRESS (0x0000000000000000UL) |
|||
#define TARGET_VM_MAXUSER_ADDRESS (0x0000004000000000UL) |
|||
|
|||
#define TARGET_USRSTACK (TARGET_VM_MAXUSER_ADDRESS - TARGET_PAGE_SIZE) |
|||
|
|||
static inline abi_ulong get_sp_from_cpustate(CPURISCVState *state) |
|||
{ |
|||
return state->gpr[xSP]; |
|||
} |
|||
|
|||
static inline void set_second_rval(CPURISCVState *state, abi_ulong retval2) |
|||
{ |
|||
state->gpr[xA1] = retval2; |
|||
} |
|||
|
|||
static inline abi_ulong get_second_rval(CPURISCVState *state) |
|||
{ |
|||
return state->gpr[xA1]; |
|||
} |
|||
|
|||
#endif /* TARGET_ARCH_VMPARAM_H */ |
|||
@ -0,0 +1,38 @@ |
|||
/*
|
|||
* RISC-V system call definitions |
|||
* |
|||
* Copyright (c) Mark Corbin |
|||
* |
|||
* This program is free software; you can redistribute it and/or modify |
|||
* it under the terms of the GNU General Public License as published by |
|||
* the Free Software Foundation; either version 2 of the License, or |
|||
* (at your option) any later version. |
|||
* |
|||
* This program 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 General Public License for more details. |
|||
* |
|||
* You should have received a copy of the GNU General Public License |
|||
* along with this program; if not, see <http://www.gnu.org/licenses/>.
|
|||
*/ |
|||
|
|||
#ifndef BSD_USER_RISCV_TARGET_SYSCALL_H |
|||
#define BSD_USER_RISCV_TARGET_SYSCALL_H |
|||
|
|||
/*
|
|||
* struct target_pt_regs defines the way the registers are stored on the stack |
|||
* during a system call. |
|||
*/ |
|||
|
|||
struct target_pt_regs { |
|||
abi_ulong regs[32]; |
|||
abi_ulong sepc; |
|||
}; |
|||
|
|||
#define UNAME_MACHINE "riscv64" |
|||
|
|||
#define TARGET_HW_MACHINE "riscv" |
|||
#define TARGET_HW_MACHINE_ARCH UNAME_MACHINE |
|||
|
|||
#endif /* BSD_USER_RISCV_TARGET_SYSCALL_H */ |
|||
@ -0,0 +1,4 @@ |
|||
TARGET_ARCH=riscv64 |
|||
TARGET_BASE_ARCH=riscv |
|||
TARGET_ABI_DIR=riscv |
|||
TARGET_XML_FILES= gdb-xml/riscv-64bit-cpu.xml gdb-xml/riscv-32bit-fpu.xml gdb-xml/riscv-64bit-fpu.xml gdb-xml/riscv-64bit-virtual.xml |
|||
@ -1,9 +1,9 @@ |
|||
config RISCV32 |
|||
bool |
|||
imply ARM_COMPATIBLE_SEMIHOSTING if TCG |
|||
select ARM_COMPATIBLE_SEMIHOSTING if TCG |
|||
select DEVICE_TREE # needed by boot.c |
|||
|
|||
config RISCV64 |
|||
bool |
|||
imply ARM_COMPATIBLE_SEMIHOSTING if TCG |
|||
select ARM_COMPATIBLE_SEMIHOSTING if TCG |
|||
select DEVICE_TREE # needed by boot.c |
|||
|
|||
Binary file not shown.
Loading…
Reference in new issue