mirror of
https://gitlab.com/qemu-project/qemu.git
synced 2024-11-05 05:52:15 +03:00
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----- 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>
This commit is contained in:
commit
35ba77d2fc
170
bsd-user/riscv/signal.c
Normal file
170
bsd-user/riscv/signal.c
Normal file
@ -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;
|
||||
}
|
20
bsd-user/riscv/target.h
Normal file
20
bsd-user/riscv/target.h
Normal file
@ -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 */
|
27
bsd-user/riscv/target_arch.h
Normal file
27
bsd-user/riscv/target_arch.h
Normal file
@ -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 */
|
29
bsd-user/riscv/target_arch_cpu.c
Normal file
29
bsd-user/riscv/target_arch_cpu.c
Normal file
@ -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;
|
||||
}
|
148
bsd-user/riscv/target_arch_cpu.h
Normal file
148
bsd-user/riscv/target_arch_cpu.h
Normal file
@ -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 */
|
42
bsd-user/riscv/target_arch_elf.h
Normal file
42
bsd-user/riscv/target_arch_elf.h
Normal file
@ -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 */
|
88
bsd-user/riscv/target_arch_reg.h
Normal file
88
bsd-user/riscv/target_arch_reg.h
Normal file
@ -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 */
|
75
bsd-user/riscv/target_arch_signal.h
Normal file
75
bsd-user/riscv/target_arch_signal.h
Normal file
@ -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 */
|
41
bsd-user/riscv/target_arch_sigtramp.h
Normal file
41
bsd-user/riscv/target_arch_sigtramp.h
Normal file
@ -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 */
|
41
bsd-user/riscv/target_arch_sysarch.h
Normal file
41
bsd-user/riscv/target_arch_sysarch.h
Normal file
@ -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 */
|
47
bsd-user/riscv/target_arch_thread.h
Normal file
47
bsd-user/riscv/target_arch_thread.h
Normal file
@ -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 */
|
53
bsd-user/riscv/target_arch_vmparam.h
Normal file
53
bsd-user/riscv/target_arch_vmparam.h
Normal file
@ -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 */
|
38
bsd-user/riscv/target_syscall.h
Normal file
38
bsd-user/riscv/target_syscall.h
Normal file
@ -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 */
|
4
configs/targets/riscv64-bsd-user.mak
Normal file
4
configs/targets/riscv64-bsd-user.mak
Normal file
@ -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
|
@ -55,7 +55,7 @@ static uint32_t riscv_imsic_topei(RISCVIMSICState *imsic, uint32_t page)
|
||||
(imsic->eithreshold[page] <= imsic->num_irqs)) ?
|
||||
imsic->eithreshold[page] : imsic->num_irqs;
|
||||
for (i = 1; i < max_irq; i++) {
|
||||
if ((imsic->eistate[base + i] & IMSIC_EISTATE_ENPEND) ==
|
||||
if ((qatomic_read(&imsic->eistate[base + i]) & IMSIC_EISTATE_ENPEND) ==
|
||||
IMSIC_EISTATE_ENPEND) {
|
||||
return (i << IMSIC_TOPEI_IID_SHIFT) | i;
|
||||
}
|
||||
@ -66,10 +66,24 @@ static uint32_t riscv_imsic_topei(RISCVIMSICState *imsic, uint32_t page)
|
||||
|
||||
static void riscv_imsic_update(RISCVIMSICState *imsic, uint32_t page)
|
||||
{
|
||||
uint32_t base = page * imsic->num_irqs;
|
||||
|
||||
/*
|
||||
* Lower the interrupt line if necessary, then evaluate the current
|
||||
* IMSIC state.
|
||||
* This sequence ensures that any race between evaluating the eistate and
|
||||
* updating the interrupt line will not result in an incorrectly
|
||||
* deactivated connected CPU IRQ line.
|
||||
* If multiple interrupts are pending, this sequence functions identically
|
||||
* to qemu_irq_pulse.
|
||||
*/
|
||||
|
||||
if (qatomic_fetch_and(&imsic->eistate[base], ~IMSIC_EISTATE_ENPEND)) {
|
||||
qemu_irq_lower(imsic->external_irqs[page]);
|
||||
}
|
||||
if (imsic->eidelivery[page] && riscv_imsic_topei(imsic, page)) {
|
||||
qemu_irq_raise(imsic->external_irqs[page]);
|
||||
} else {
|
||||
qemu_irq_lower(imsic->external_irqs[page]);
|
||||
qatomic_or(&imsic->eistate[base], IMSIC_EISTATE_ENPEND);
|
||||
}
|
||||
}
|
||||
|
||||
@ -125,12 +139,11 @@ static int riscv_imsic_topei_rmw(RISCVIMSICState *imsic, uint32_t page,
|
||||
topei >>= IMSIC_TOPEI_IID_SHIFT;
|
||||
base = page * imsic->num_irqs;
|
||||
if (topei) {
|
||||
imsic->eistate[base + topei] &= ~IMSIC_EISTATE_PENDING;
|
||||
qatomic_and(&imsic->eistate[base + topei], ~IMSIC_EISTATE_PENDING);
|
||||
}
|
||||
|
||||
riscv_imsic_update(imsic, page);
|
||||
}
|
||||
|
||||
riscv_imsic_update(imsic, page);
|
||||
return 0;
|
||||
}
|
||||
|
||||
@ -139,7 +152,7 @@ static int riscv_imsic_eix_rmw(RISCVIMSICState *imsic,
|
||||
uint32_t num, bool pend, target_ulong *val,
|
||||
target_ulong new_val, target_ulong wr_mask)
|
||||
{
|
||||
uint32_t i, base;
|
||||
uint32_t i, base, prev;
|
||||
target_ulong mask;
|
||||
uint32_t state = (pend) ? IMSIC_EISTATE_PENDING : IMSIC_EISTATE_ENABLED;
|
||||
|
||||
@ -157,10 +170,6 @@ static int riscv_imsic_eix_rmw(RISCVIMSICState *imsic,
|
||||
|
||||
if (val) {
|
||||
*val = 0;
|
||||
for (i = 0; i < xlen; i++) {
|
||||
mask = (target_ulong)1 << i;
|
||||
*val |= (imsic->eistate[base + i] & state) ? mask : 0;
|
||||
}
|
||||
}
|
||||
|
||||
for (i = 0; i < xlen; i++) {
|
||||
@ -172,10 +181,15 @@ static int riscv_imsic_eix_rmw(RISCVIMSICState *imsic,
|
||||
mask = (target_ulong)1 << i;
|
||||
if (wr_mask & mask) {
|
||||
if (new_val & mask) {
|
||||
imsic->eistate[base + i] |= state;
|
||||
prev = qatomic_fetch_or(&imsic->eistate[base + i], state);
|
||||
} else {
|
||||
imsic->eistate[base + i] &= ~state;
|
||||
prev = qatomic_fetch_and(&imsic->eistate[base + i], ~state);
|
||||
}
|
||||
} else {
|
||||
prev = qatomic_read(&imsic->eistate[base + i]);
|
||||
}
|
||||
if (val && (prev & state)) {
|
||||
*val |= mask;
|
||||
}
|
||||
}
|
||||
|
||||
@ -302,14 +316,14 @@ static void riscv_imsic_write(void *opaque, hwaddr addr, uint64_t value,
|
||||
page = addr >> IMSIC_MMIO_PAGE_SHIFT;
|
||||
if ((addr & (IMSIC_MMIO_PAGE_SZ - 1)) == IMSIC_MMIO_PAGE_LE) {
|
||||
if (value && (value < imsic->num_irqs)) {
|
||||
imsic->eistate[(page * imsic->num_irqs) + value] |=
|
||||
IMSIC_EISTATE_PENDING;
|
||||
qatomic_or(&imsic->eistate[(page * imsic->num_irqs) + value],
|
||||
IMSIC_EISTATE_PENDING);
|
||||
|
||||
/* Update CPU external interrupt status */
|
||||
riscv_imsic_update(imsic, page);
|
||||
}
|
||||
}
|
||||
|
||||
/* Update CPU external interrupt status */
|
||||
riscv_imsic_update(imsic, page);
|
||||
|
||||
return;
|
||||
|
||||
err:
|
||||
|
@ -128,11 +128,11 @@ char *riscv_find_firmware(const char *firmware_filename,
|
||||
|
||||
target_ulong riscv_find_and_load_firmware(MachineState *machine,
|
||||
const char *default_machine_firmware,
|
||||
hwaddr firmware_load_addr,
|
||||
hwaddr *firmware_load_addr,
|
||||
symbol_fn_t sym_cb)
|
||||
{
|
||||
char *firmware_filename;
|
||||
target_ulong firmware_end_addr = firmware_load_addr;
|
||||
target_ulong firmware_end_addr = *firmware_load_addr;
|
||||
|
||||
firmware_filename = riscv_find_firmware(machine->firmware,
|
||||
default_machine_firmware);
|
||||
@ -148,7 +148,7 @@ target_ulong riscv_find_and_load_firmware(MachineState *machine,
|
||||
}
|
||||
|
||||
target_ulong riscv_load_firmware(const char *firmware_filename,
|
||||
hwaddr firmware_load_addr,
|
||||
hwaddr *firmware_load_addr,
|
||||
symbol_fn_t sym_cb)
|
||||
{
|
||||
uint64_t firmware_entry, firmware_end;
|
||||
@ -159,15 +159,16 @@ target_ulong riscv_load_firmware(const char *firmware_filename,
|
||||
if (load_elf_ram_sym(firmware_filename, NULL, NULL, NULL,
|
||||
&firmware_entry, NULL, &firmware_end, NULL,
|
||||
0, EM_RISCV, 1, 0, NULL, true, sym_cb) > 0) {
|
||||
*firmware_load_addr = firmware_entry;
|
||||
return firmware_end;
|
||||
}
|
||||
|
||||
firmware_size = load_image_targphys_as(firmware_filename,
|
||||
firmware_load_addr,
|
||||
*firmware_load_addr,
|
||||
current_machine->ram_size, NULL);
|
||||
|
||||
if (firmware_size > 0) {
|
||||
return firmware_load_addr + firmware_size;
|
||||
return *firmware_load_addr + firmware_size;
|
||||
}
|
||||
|
||||
error_report("could not load firmware '%s'", firmware_filename);
|
||||
|
@ -613,7 +613,7 @@ static void microchip_icicle_kit_machine_init(MachineState *machine)
|
||||
|
||||
/* Load the firmware */
|
||||
firmware_end_addr = riscv_find_and_load_firmware(machine, firmware_name,
|
||||
firmware_load_addr, NULL);
|
||||
&firmware_load_addr, NULL);
|
||||
|
||||
if (kernel_as_payload) {
|
||||
kernel_start_addr = riscv_calc_kernel_start_addr(&s->soc.u_cpus,
|
||||
|
@ -98,7 +98,8 @@ static void opentitan_machine_init(MachineState *machine)
|
||||
memmap[IBEX_DEV_RAM].base, machine->ram);
|
||||
|
||||
if (machine->firmware) {
|
||||
riscv_load_firmware(machine->firmware, memmap[IBEX_DEV_RAM].base, NULL);
|
||||
hwaddr firmware_load_addr = memmap[IBEX_DEV_RAM].base;
|
||||
riscv_load_firmware(machine->firmware, &firmware_load_addr, NULL);
|
||||
}
|
||||
|
||||
if (machine->kernel_filename) {
|
||||
|
@ -45,6 +45,7 @@ static void shakti_c_machine_state_init(MachineState *mstate)
|
||||
{
|
||||
ShaktiCMachineState *sms = RISCV_SHAKTI_MACHINE(mstate);
|
||||
MemoryRegion *system_memory = get_system_memory();
|
||||
hwaddr firmware_load_addr = shakti_c_memmap[SHAKTI_C_RAM].base;
|
||||
|
||||
/* Initialize SoC */
|
||||
object_initialize_child(OBJECT(mstate), "soc", &sms->soc,
|
||||
@ -56,16 +57,14 @@ static void shakti_c_machine_state_init(MachineState *mstate)
|
||||
shakti_c_memmap[SHAKTI_C_RAM].base,
|
||||
mstate->ram);
|
||||
|
||||
if (mstate->firmware) {
|
||||
riscv_load_firmware(mstate->firmware, &firmware_load_addr, NULL);
|
||||
}
|
||||
|
||||
/* ROM reset vector */
|
||||
riscv_setup_rom_reset_vec(mstate, &sms->soc.cpus,
|
||||
shakti_c_memmap[SHAKTI_C_RAM].base,
|
||||
riscv_setup_rom_reset_vec(mstate, &sms->soc.cpus, firmware_load_addr,
|
||||
shakti_c_memmap[SHAKTI_C_ROM].base,
|
||||
shakti_c_memmap[SHAKTI_C_ROM].size, 0, 0);
|
||||
if (mstate->firmware) {
|
||||
riscv_load_firmware(mstate->firmware,
|
||||
shakti_c_memmap[SHAKTI_C_RAM].base,
|
||||
NULL);
|
||||
}
|
||||
}
|
||||
|
||||
static void shakti_c_machine_instance_init(Object *obj)
|
||||
|
@ -515,7 +515,7 @@ static void sifive_u_machine_init(MachineState *machine)
|
||||
SiFiveUState *s = RISCV_U_MACHINE(machine);
|
||||
MemoryRegion *system_memory = get_system_memory();
|
||||
MemoryRegion *flash0 = g_new(MemoryRegion, 1);
|
||||
target_ulong start_addr = memmap[SIFIVE_U_DEV_DRAM].base;
|
||||
hwaddr start_addr = memmap[SIFIVE_U_DEV_DRAM].base;
|
||||
target_ulong firmware_end_addr, kernel_start_addr;
|
||||
const char *firmware_name;
|
||||
uint32_t start_addr_hi32 = 0x00000000;
|
||||
@ -589,7 +589,7 @@ static void sifive_u_machine_init(MachineState *machine)
|
||||
|
||||
firmware_name = riscv_default_firmware_name(&s->soc.u_cpus);
|
||||
firmware_end_addr = riscv_find_and_load_firmware(machine, firmware_name,
|
||||
start_addr, NULL);
|
||||
&start_addr, NULL);
|
||||
|
||||
if (machine->kernel_filename) {
|
||||
kernel_start_addr = riscv_calc_kernel_start_addr(&s->soc.u_cpus,
|
||||
|
@ -198,6 +198,7 @@ static void spike_board_init(MachineState *machine)
|
||||
MemoryRegion *system_memory = get_system_memory();
|
||||
MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
|
||||
target_ulong firmware_end_addr = memmap[SPIKE_DRAM].base;
|
||||
hwaddr firmware_load_addr = memmap[SPIKE_DRAM].base;
|
||||
target_ulong kernel_start_addr;
|
||||
char *firmware_name;
|
||||
uint32_t fdt_load_addr;
|
||||
@ -290,7 +291,7 @@ static void spike_board_init(MachineState *machine)
|
||||
/* Load firmware */
|
||||
if (firmware_name) {
|
||||
firmware_end_addr = riscv_load_firmware(firmware_name,
|
||||
memmap[SPIKE_DRAM].base,
|
||||
&firmware_load_addr,
|
||||
htif_symbol_callback);
|
||||
g_free(firmware_name);
|
||||
}
|
||||
@ -320,7 +321,7 @@ static void spike_board_init(MachineState *machine)
|
||||
riscv_load_fdt(fdt_load_addr, machine->fdt);
|
||||
|
||||
/* load the reset vector */
|
||||
riscv_setup_rom_reset_vec(machine, &s->soc[0], memmap[SPIKE_DRAM].base,
|
||||
riscv_setup_rom_reset_vec(machine, &s->soc[0], firmware_load_addr,
|
||||
memmap[SPIKE_MROM].base,
|
||||
memmap[SPIKE_MROM].size, kernel_entry,
|
||||
fdt_load_addr);
|
||||
|
@ -1335,7 +1335,7 @@ static void virt_machine_done(Notifier *notifier, void *data)
|
||||
machine_done);
|
||||
const MemMapEntry *memmap = virt_memmap;
|
||||
MachineState *machine = MACHINE(s);
|
||||
target_ulong start_addr = memmap[VIRT_DRAM].base;
|
||||
hwaddr start_addr = memmap[VIRT_DRAM].base;
|
||||
target_ulong firmware_end_addr, kernel_start_addr;
|
||||
const char *firmware_name = riscv_default_firmware_name(&s->soc[0]);
|
||||
uint64_t fdt_load_addr;
|
||||
@ -1367,7 +1367,7 @@ static void virt_machine_done(Notifier *notifier, void *data)
|
||||
}
|
||||
|
||||
firmware_end_addr = riscv_find_and_load_firmware(machine, firmware_name,
|
||||
start_addr, NULL);
|
||||
&start_addr, NULL);
|
||||
|
||||
pflash_blk0 = pflash_cfi01_get_blk(s->flash[0]);
|
||||
if (pflash_blk0) {
|
||||
|
@ -35,13 +35,13 @@ target_ulong riscv_calc_kernel_start_addr(RISCVHartArrayState *harts,
|
||||
target_ulong firmware_end_addr);
|
||||
target_ulong riscv_find_and_load_firmware(MachineState *machine,
|
||||
const char *default_machine_firmware,
|
||||
hwaddr firmware_load_addr,
|
||||
hwaddr *firmware_load_addr,
|
||||
symbol_fn_t sym_cb);
|
||||
const char *riscv_default_firmware_name(RISCVHartArrayState *harts);
|
||||
char *riscv_find_firmware(const char *firmware_filename,
|
||||
const char *default_machine_firmware);
|
||||
target_ulong riscv_load_firmware(const char *firmware_filename,
|
||||
hwaddr firmware_load_addr,
|
||||
hwaddr *firmware_load_addr,
|
||||
symbol_fn_t sym_cb);
|
||||
target_ulong riscv_load_kernel(MachineState *machine,
|
||||
RISCVHartArrayState *harts,
|
||||
|
@ -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
|
||||
|
@ -115,7 +115,7 @@ const RISCVIsaExtData isa_edata_arr[] = {
|
||||
ISA_EXT_DATA_ENTRY(zihpm, PRIV_VERSION_1_12_0, ext_zihpm),
|
||||
ISA_EXT_DATA_ENTRY(zimop, PRIV_VERSION_1_13_0, ext_zimop),
|
||||
ISA_EXT_DATA_ENTRY(zmmul, PRIV_VERSION_1_12_0, ext_zmmul),
|
||||
ISA_EXT_DATA_ENTRY(za64rs, PRIV_VERSION_1_12_0, has_priv_1_11),
|
||||
ISA_EXT_DATA_ENTRY(za64rs, PRIV_VERSION_1_12_0, has_priv_1_12),
|
||||
ISA_EXT_DATA_ENTRY(zaamo, PRIV_VERSION_1_12_0, ext_zaamo),
|
||||
ISA_EXT_DATA_ENTRY(zabha, PRIV_VERSION_1_13_0, ext_zabha),
|
||||
ISA_EXT_DATA_ENTRY(zacas, PRIV_VERSION_1_12_0, ext_zacas),
|
||||
@ -197,6 +197,7 @@ const RISCVIsaExtData isa_edata_arr[] = {
|
||||
ISA_EXT_DATA_ENTRY(svinval, PRIV_VERSION_1_12_0, ext_svinval),
|
||||
ISA_EXT_DATA_ENTRY(svnapot, PRIV_VERSION_1_12_0, ext_svnapot),
|
||||
ISA_EXT_DATA_ENTRY(svpbmt, PRIV_VERSION_1_12_0, ext_svpbmt),
|
||||
ISA_EXT_DATA_ENTRY(svvptc, PRIV_VERSION_1_13_0, ext_svvptc),
|
||||
ISA_EXT_DATA_ENTRY(xtheadba, PRIV_VERSION_1_11_0, ext_xtheadba),
|
||||
ISA_EXT_DATA_ENTRY(xtheadbb, PRIV_VERSION_1_11_0, ext_xtheadbb),
|
||||
ISA_EXT_DATA_ENTRY(xtheadbs, PRIV_VERSION_1_11_0, ext_xtheadbs),
|
||||
@ -680,6 +681,11 @@ static void rv32_ibex_cpu_init(Object *obj)
|
||||
cpu->cfg.ext_zicsr = true;
|
||||
cpu->cfg.pmp = true;
|
||||
cpu->cfg.ext_smepmp = true;
|
||||
|
||||
cpu->cfg.ext_zba = true;
|
||||
cpu->cfg.ext_zbb = true;
|
||||
cpu->cfg.ext_zbc = true;
|
||||
cpu->cfg.ext_zbs = true;
|
||||
}
|
||||
|
||||
static void rv32_imafcu_nommu_cpu_init(Object *obj)
|
||||
@ -818,6 +824,12 @@ static void riscv_cpu_dump_state(CPUState *cs, FILE *f, int flags)
|
||||
}
|
||||
}
|
||||
if (flags & CPU_DUMP_FPU) {
|
||||
target_ulong val = 0;
|
||||
RISCVException res = riscv_csrrw_debug(env, CSR_FCSR, &val, 0, 0);
|
||||
if (res == RISCV_EXCP_NONE) {
|
||||
qemu_fprintf(f, " %-8s " TARGET_FMT_lx "\n",
|
||||
csr_ops[CSR_FCSR].name, val);
|
||||
}
|
||||
for (i = 0; i < 32; i++) {
|
||||
qemu_fprintf(f, " %-8s %016" PRIx64,
|
||||
riscv_fpr_regnames[i], env->fpr[i]);
|
||||
@ -1483,6 +1495,7 @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
|
||||
MULTI_EXT_CFG_BOOL("svinval", ext_svinval, false),
|
||||
MULTI_EXT_CFG_BOOL("svnapot", ext_svnapot, false),
|
||||
MULTI_EXT_CFG_BOOL("svpbmt", ext_svpbmt, false),
|
||||
MULTI_EXT_CFG_BOOL("svvptc", ext_svvptc, true),
|
||||
|
||||
MULTI_EXT_CFG_BOOL("zicntr", ext_zicntr, true),
|
||||
MULTI_EXT_CFG_BOOL("zihpm", ext_zihpm, true),
|
||||
@ -2661,6 +2674,7 @@ static Property riscv_cpu_properties[] = {
|
||||
|
||||
DEFINE_PROP_BOOL("rvv_ta_all_1s", RISCVCPU, cfg.rvv_ta_all_1s, false),
|
||||
DEFINE_PROP_BOOL("rvv_ma_all_1s", RISCVCPU, cfg.rvv_ma_all_1s, false),
|
||||
DEFINE_PROP_BOOL("rvv_vl_half_avl", RISCVCPU, cfg.rvv_vl_half_avl, false),
|
||||
|
||||
/*
|
||||
* write_misa() is marked as experimental for now so mark
|
||||
|
@ -947,6 +947,16 @@ typedef enum RISCVException {
|
||||
#define JVT_BASE (~0x3F)
|
||||
|
||||
/* Debug Sdtrig CSR masks */
|
||||
#define TEXTRA32_MHVALUE 0xFC000000
|
||||
#define TEXTRA32_MHSELECT 0x03800000
|
||||
#define TEXTRA32_SBYTEMASK 0x000C0000
|
||||
#define TEXTRA32_SVALUE 0x0003FFFC
|
||||
#define TEXTRA32_SSELECT 0x00000003
|
||||
#define TEXTRA64_MHVALUE 0xFFF8000000000000ULL
|
||||
#define TEXTRA64_MHSELECT 0x0007000000000000ULL
|
||||
#define TEXTRA64_SBYTEMASK 0x000000F000000000ULL
|
||||
#define TEXTRA64_SVALUE 0x00000003FFFFFFFCULL
|
||||
#define TEXTRA64_SSELECT 0x0000000000000003ULL
|
||||
#define MCONTEXT32 0x0000003F
|
||||
#define MCONTEXT64 0x0000000000001FFFULL
|
||||
#define MCONTEXT32_HCONTEXT 0x0000007F
|
||||
|
@ -81,6 +81,7 @@ struct RISCVCPUConfig {
|
||||
bool ext_svinval;
|
||||
bool ext_svnapot;
|
||||
bool ext_svpbmt;
|
||||
bool ext_svvptc;
|
||||
bool ext_zdinx;
|
||||
bool ext_zaamo;
|
||||
bool ext_zacas;
|
||||
@ -127,6 +128,7 @@ struct RISCVCPUConfig {
|
||||
bool ext_smepmp;
|
||||
bool rvv_ta_all_1s;
|
||||
bool rvv_ma_all_1s;
|
||||
bool rvv_vl_half_avl;
|
||||
|
||||
uint32_t mvendorid;
|
||||
uint64_t marchid;
|
||||
|
@ -1323,7 +1323,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
|
||||
int ret = TRANSLATE_FAIL;
|
||||
int mode = mmuidx_priv(mmu_idx);
|
||||
/* default TLB page size */
|
||||
target_ulong tlb_size = TARGET_PAGE_SIZE;
|
||||
hwaddr tlb_size = TARGET_PAGE_SIZE;
|
||||
|
||||
env->guest_phys_fault_addr = 0;
|
||||
|
||||
@ -1375,7 +1375,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
|
||||
|
||||
qemu_log_mask( |