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)) ?
|
||||||
imsic->eithreshold[page] : imsic->num_irqs;
|
imsic->eithreshold[page] : imsic->num_irqs;
|
||||||
for (i = 1; i < max_irq; i++) {
|
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) {
|
IMSIC_EISTATE_ENPEND) {
|
||||||
return (i << IMSIC_TOPEI_IID_SHIFT) | i;
|
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)
|
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)) {
|
if (imsic->eidelivery[page] && riscv_imsic_topei(imsic, page)) {
|
||||||
qemu_irq_raise(imsic->external_irqs[page]);
|
qemu_irq_raise(imsic->external_irqs[page]);
|
||||||
} else {
|
qatomic_or(&imsic->eistate[base], IMSIC_EISTATE_ENPEND);
|
||||||
qemu_irq_lower(imsic->external_irqs[page]);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -125,12 +139,11 @@ static int riscv_imsic_topei_rmw(RISCVIMSICState *imsic, uint32_t page,
|
|||||||
topei >>= IMSIC_TOPEI_IID_SHIFT;
|
topei >>= IMSIC_TOPEI_IID_SHIFT;
|
||||||
base = page * imsic->num_irqs;
|
base = page * imsic->num_irqs;
|
||||||
if (topei) {
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -139,7 +152,7 @@ static int riscv_imsic_eix_rmw(RISCVIMSICState *imsic,
|
|||||||
uint32_t num, bool pend, target_ulong *val,
|
uint32_t num, bool pend, target_ulong *val,
|
||||||
target_ulong new_val, target_ulong wr_mask)
|
target_ulong new_val, target_ulong wr_mask)
|
||||||
{
|
{
|
||||||
uint32_t i, base;
|
uint32_t i, base, prev;
|
||||||
target_ulong mask;
|
target_ulong mask;
|
||||||
uint32_t state = (pend) ? IMSIC_EISTATE_PENDING : IMSIC_EISTATE_ENABLED;
|
uint32_t state = (pend) ? IMSIC_EISTATE_PENDING : IMSIC_EISTATE_ENABLED;
|
||||||
|
|
||||||
@ -157,10 +170,6 @@ static int riscv_imsic_eix_rmw(RISCVIMSICState *imsic,
|
|||||||
|
|
||||||
if (val) {
|
if (val) {
|
||||||
*val = 0;
|
*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++) {
|
for (i = 0; i < xlen; i++) {
|
||||||
@ -172,10 +181,15 @@ static int riscv_imsic_eix_rmw(RISCVIMSICState *imsic,
|
|||||||
mask = (target_ulong)1 << i;
|
mask = (target_ulong)1 << i;
|
||||||
if (wr_mask & mask) {
|
if (wr_mask & mask) {
|
||||||
if (new_val & mask) {
|
if (new_val & mask) {
|
||||||
imsic->eistate[base + i] |= state;
|
prev = qatomic_fetch_or(&imsic->eistate[base + i], state);
|
||||||
} else {
|
} 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;
|
page = addr >> IMSIC_MMIO_PAGE_SHIFT;
|
||||||
if ((addr & (IMSIC_MMIO_PAGE_SZ - 1)) == IMSIC_MMIO_PAGE_LE) {
|
if ((addr & (IMSIC_MMIO_PAGE_SZ - 1)) == IMSIC_MMIO_PAGE_LE) {
|
||||||
if (value && (value < imsic->num_irqs)) {
|
if (value && (value < imsic->num_irqs)) {
|
||||||
imsic->eistate[(page * imsic->num_irqs) + value] |=
|
qatomic_or(&imsic->eistate[(page * imsic->num_irqs) + value],
|
||||||
IMSIC_EISTATE_PENDING;
|
IMSIC_EISTATE_PENDING);
|
||||||
|
|
||||||
|
/* Update CPU external interrupt status */
|
||||||
|
riscv_imsic_update(imsic, page);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/* Update CPU external interrupt status */
|
|
||||||
riscv_imsic_update(imsic, page);
|
|
||||||
|
|
||||||
return;
|
return;
|
||||||
|
|
||||||
err:
|
err:
|
||||||
|
@ -128,11 +128,11 @@ char *riscv_find_firmware(const char *firmware_filename,
|
|||||||
|
|
||||||
target_ulong riscv_find_and_load_firmware(MachineState *machine,
|
target_ulong riscv_find_and_load_firmware(MachineState *machine,
|
||||||
const char *default_machine_firmware,
|
const char *default_machine_firmware,
|
||||||
hwaddr firmware_load_addr,
|
hwaddr *firmware_load_addr,
|
||||||
symbol_fn_t sym_cb)
|
symbol_fn_t sym_cb)
|
||||||
{
|
{
|
||||||
char *firmware_filename;
|
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,
|
firmware_filename = riscv_find_firmware(machine->firmware,
|
||||||
default_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,
|
target_ulong riscv_load_firmware(const char *firmware_filename,
|
||||||
hwaddr firmware_load_addr,
|
hwaddr *firmware_load_addr,
|
||||||
symbol_fn_t sym_cb)
|
symbol_fn_t sym_cb)
|
||||||
{
|
{
|
||||||
uint64_t firmware_entry, firmware_end;
|
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,
|
if (load_elf_ram_sym(firmware_filename, NULL, NULL, NULL,
|
||||||
&firmware_entry, NULL, &firmware_end, NULL,
|
&firmware_entry, NULL, &firmware_end, NULL,
|
||||||
0, EM_RISCV, 1, 0, NULL, true, sym_cb) > 0) {
|
0, EM_RISCV, 1, 0, NULL, true, sym_cb) > 0) {
|
||||||
|
*firmware_load_addr = firmware_entry;
|
||||||
return firmware_end;
|
return firmware_end;
|
||||||
}
|
}
|
||||||
|
|
||||||
firmware_size = load_image_targphys_as(firmware_filename,
|
firmware_size = load_image_targphys_as(firmware_filename,
|
||||||
firmware_load_addr,
|
*firmware_load_addr,
|
||||||
current_machine->ram_size, NULL);
|
current_machine->ram_size, NULL);
|
||||||
|
|
||||||
if (firmware_size > 0) {
|
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);
|
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 */
|
/* Load the firmware */
|
||||||
firmware_end_addr = riscv_find_and_load_firmware(machine, firmware_name,
|
firmware_end_addr = riscv_find_and_load_firmware(machine, firmware_name,
|
||||||
firmware_load_addr, NULL);
|
&firmware_load_addr, NULL);
|
||||||
|
|
||||||
if (kernel_as_payload) {
|
if (kernel_as_payload) {
|
||||||
kernel_start_addr = riscv_calc_kernel_start_addr(&s->soc.u_cpus,
|
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);
|
memmap[IBEX_DEV_RAM].base, machine->ram);
|
||||||
|
|
||||||
if (machine->firmware) {
|
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) {
|
if (machine->kernel_filename) {
|
||||||
|
@ -45,6 +45,7 @@ static void shakti_c_machine_state_init(MachineState *mstate)
|
|||||||
{
|
{
|
||||||
ShaktiCMachineState *sms = RISCV_SHAKTI_MACHINE(mstate);
|
ShaktiCMachineState *sms = RISCV_SHAKTI_MACHINE(mstate);
|
||||||
MemoryRegion *system_memory = get_system_memory();
|
MemoryRegion *system_memory = get_system_memory();
|
||||||
|
hwaddr firmware_load_addr = shakti_c_memmap[SHAKTI_C_RAM].base;
|
||||||
|
|
||||||
/* Initialize SoC */
|
/* Initialize SoC */
|
||||||
object_initialize_child(OBJECT(mstate), "soc", &sms->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,
|
shakti_c_memmap[SHAKTI_C_RAM].base,
|
||||||
mstate->ram);
|
mstate->ram);
|
||||||
|
|
||||||
|
if (mstate->firmware) {
|
||||||
|
riscv_load_firmware(mstate->firmware, &firmware_load_addr, NULL);
|
||||||
|
}
|
||||||
|
|
||||||
/* ROM reset vector */
|
/* ROM reset vector */
|
||||||
riscv_setup_rom_reset_vec(mstate, &sms->soc.cpus,
|
riscv_setup_rom_reset_vec(mstate, &sms->soc.cpus, firmware_load_addr,
|
||||||
shakti_c_memmap[SHAKTI_C_RAM].base,
|
|
||||||
shakti_c_memmap[SHAKTI_C_ROM].base,
|
shakti_c_memmap[SHAKTI_C_ROM].base,
|
||||||
shakti_c_memmap[SHAKTI_C_ROM].size, 0, 0);
|
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)
|
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);
|
SiFiveUState *s = RISCV_U_MACHINE(machine);
|
||||||
MemoryRegion *system_memory = get_system_memory();
|
MemoryRegion *system_memory = get_system_memory();
|
||||||
MemoryRegion *flash0 = g_new(MemoryRegion, 1);
|
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;
|
target_ulong firmware_end_addr, kernel_start_addr;
|
||||||
const char *firmware_name;
|
const char *firmware_name;
|
||||||
uint32_t start_addr_hi32 = 0x00000000;
|
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_name = riscv_default_firmware_name(&s->soc.u_cpus);
|
||||||
firmware_end_addr = riscv_find_and_load_firmware(machine, firmware_name,
|
firmware_end_addr = riscv_find_and_load_firmware(machine, firmware_name,
|
||||||
start_addr, NULL);
|
&start_addr, NULL);
|
||||||
|
|
||||||
if (machine->kernel_filename) {
|
if (machine->kernel_filename) {
|
||||||
kernel_start_addr = riscv_calc_kernel_start_addr(&s->soc.u_cpus,
|
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 *system_memory = get_system_memory();
|
||||||
MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
|
MemoryRegion *mask_rom = g_new(MemoryRegion, 1);
|
||||||
target_ulong firmware_end_addr = memmap[SPIKE_DRAM].base;
|
target_ulong firmware_end_addr = memmap[SPIKE_DRAM].base;
|
||||||
|
hwaddr firmware_load_addr = memmap[SPIKE_DRAM].base;
|
||||||
target_ulong kernel_start_addr;
|
target_ulong kernel_start_addr;
|
||||||
char *firmware_name;
|
char *firmware_name;
|
||||||
uint32_t fdt_load_addr;
|
uint32_t fdt_load_addr;
|
||||||
@ -290,7 +291,7 @@ static void spike_board_init(MachineState *machine)
|
|||||||
/* Load firmware */
|
/* Load firmware */
|
||||||
if (firmware_name) {
|
if (firmware_name) {
|
||||||
firmware_end_addr = riscv_load_firmware(firmware_name,
|
firmware_end_addr = riscv_load_firmware(firmware_name,
|
||||||
memmap[SPIKE_DRAM].base,
|
&firmware_load_addr,
|
||||||
htif_symbol_callback);
|
htif_symbol_callback);
|
||||||
g_free(firmware_name);
|
g_free(firmware_name);
|
||||||
}
|
}
|
||||||
@ -320,7 +321,7 @@ static void spike_board_init(MachineState *machine)
|
|||||||
riscv_load_fdt(fdt_load_addr, machine->fdt);
|
riscv_load_fdt(fdt_load_addr, machine->fdt);
|
||||||
|
|
||||||
/* load the reset vector */
|
/* 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].base,
|
||||||
memmap[SPIKE_MROM].size, kernel_entry,
|
memmap[SPIKE_MROM].size, kernel_entry,
|
||||||
fdt_load_addr);
|
fdt_load_addr);
|
||||||
|
@ -1335,7 +1335,7 @@ static void virt_machine_done(Notifier *notifier, void *data)
|
|||||||
machine_done);
|
machine_done);
|
||||||
const MemMapEntry *memmap = virt_memmap;
|
const MemMapEntry *memmap = virt_memmap;
|
||||||
MachineState *machine = MACHINE(s);
|
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;
|
target_ulong firmware_end_addr, kernel_start_addr;
|
||||||
const char *firmware_name = riscv_default_firmware_name(&s->soc[0]);
|
const char *firmware_name = riscv_default_firmware_name(&s->soc[0]);
|
||||||
uint64_t fdt_load_addr;
|
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,
|
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]);
|
pflash_blk0 = pflash_cfi01_get_blk(s->flash[0]);
|
||||||
if (pflash_blk0) {
|
if (pflash_blk0) {
|
||||||
|
@ -35,13 +35,13 @@ target_ulong riscv_calc_kernel_start_addr(RISCVHartArrayState *harts,
|
|||||||
target_ulong firmware_end_addr);
|
target_ulong firmware_end_addr);
|
||||||
target_ulong riscv_find_and_load_firmware(MachineState *machine,
|
target_ulong riscv_find_and_load_firmware(MachineState *machine,
|
||||||
const char *default_machine_firmware,
|
const char *default_machine_firmware,
|
||||||
hwaddr firmware_load_addr,
|
hwaddr *firmware_load_addr,
|
||||||
symbol_fn_t sym_cb);
|
symbol_fn_t sym_cb);
|
||||||
const char *riscv_default_firmware_name(RISCVHartArrayState *harts);
|
const char *riscv_default_firmware_name(RISCVHartArrayState *harts);
|
||||||
char *riscv_find_firmware(const char *firmware_filename,
|
char *riscv_find_firmware(const char *firmware_filename,
|
||||||
const char *default_machine_firmware);
|
const char *default_machine_firmware);
|
||||||
target_ulong riscv_load_firmware(const char *firmware_filename,
|
target_ulong riscv_load_firmware(const char *firmware_filename,
|
||||||
hwaddr firmware_load_addr,
|
hwaddr *firmware_load_addr,
|
||||||
symbol_fn_t sym_cb);
|
symbol_fn_t sym_cb);
|
||||||
target_ulong riscv_load_kernel(MachineState *machine,
|
target_ulong riscv_load_kernel(MachineState *machine,
|
||||||
RISCVHartArrayState *harts,
|
RISCVHartArrayState *harts,
|
||||||
|
@ -1,9 +1,9 @@
|
|||||||
config RISCV32
|
config RISCV32
|
||||||
bool
|
bool
|
||||||
imply ARM_COMPATIBLE_SEMIHOSTING if TCG
|
select ARM_COMPATIBLE_SEMIHOSTING if TCG
|
||||||
select DEVICE_TREE # needed by boot.c
|
select DEVICE_TREE # needed by boot.c
|
||||||
|
|
||||||
config RISCV64
|
config RISCV64
|
||||||
bool
|
bool
|
||||||
imply ARM_COMPATIBLE_SEMIHOSTING if TCG
|
select ARM_COMPATIBLE_SEMIHOSTING if TCG
|
||||||
select DEVICE_TREE # needed by boot.c
|
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(zihpm, PRIV_VERSION_1_12_0, ext_zihpm),
|
||||||
ISA_EXT_DATA_ENTRY(zimop, PRIV_VERSION_1_13_0, ext_zimop),
|
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(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(zaamo, PRIV_VERSION_1_12_0, ext_zaamo),
|
||||||
ISA_EXT_DATA_ENTRY(zabha, PRIV_VERSION_1_13_0, ext_zabha),
|
ISA_EXT_DATA_ENTRY(zabha, PRIV_VERSION_1_13_0, ext_zabha),
|
||||||
ISA_EXT_DATA_ENTRY(zacas, PRIV_VERSION_1_12_0, ext_zacas),
|
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(svinval, PRIV_VERSION_1_12_0, ext_svinval),
|
||||||
ISA_EXT_DATA_ENTRY(svnapot, PRIV_VERSION_1_12_0, ext_svnapot),
|
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(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(xtheadba, PRIV_VERSION_1_11_0, ext_xtheadba),
|
||||||
ISA_EXT_DATA_ENTRY(xtheadbb, PRIV_VERSION_1_11_0, ext_xtheadbb),
|
ISA_EXT_DATA_ENTRY(xtheadbb, PRIV_VERSION_1_11_0, ext_xtheadbb),
|
||||||
ISA_EXT_DATA_ENTRY(xtheadbs, PRIV_VERSION_1_11_0, ext_xtheadbs),
|
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.ext_zicsr = true;
|
||||||
cpu->cfg.pmp = true;
|
cpu->cfg.pmp = true;
|
||||||
cpu->cfg.ext_smepmp = 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)
|
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) {
|
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++) {
|
for (i = 0; i < 32; i++) {
|
||||||
qemu_fprintf(f, " %-8s %016" PRIx64,
|
qemu_fprintf(f, " %-8s %016" PRIx64,
|
||||||
riscv_fpr_regnames[i], env->fpr[i]);
|
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("svinval", ext_svinval, false),
|
||||||
MULTI_EXT_CFG_BOOL("svnapot", ext_svnapot, false),
|
MULTI_EXT_CFG_BOOL("svnapot", ext_svnapot, false),
|
||||||
MULTI_EXT_CFG_BOOL("svpbmt", ext_svpbmt, 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("zicntr", ext_zicntr, true),
|
||||||
MULTI_EXT_CFG_BOOL("zihpm", ext_zihpm, 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_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_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
|
* write_misa() is marked as experimental for now so mark
|
||||||
|
@ -947,6 +947,16 @@ typedef enum RISCVException {
|
|||||||
#define JVT_BASE (~0x3F)
|
#define JVT_BASE (~0x3F)
|
||||||
|
|
||||||
/* Debug Sdtrig CSR masks */
|
/* 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 MCONTEXT32 0x0000003F
|
||||||
#define MCONTEXT64 0x0000000000001FFFULL
|
#define MCONTEXT64 0x0000000000001FFFULL
|
||||||
#define MCONTEXT32_HCONTEXT 0x0000007F
|
#define MCONTEXT32_HCONTEXT 0x0000007F
|
||||||
|
@ -81,6 +81,7 @@ struct RISCVCPUConfig {
|
|||||||
bool ext_svinval;
|
bool ext_svinval;
|
||||||
bool ext_svnapot;
|
bool ext_svnapot;
|
||||||
bool ext_svpbmt;
|
bool ext_svpbmt;
|
||||||
|
bool ext_svvptc;
|
||||||
bool ext_zdinx;
|
bool ext_zdinx;
|
||||||
bool ext_zaamo;
|
bool ext_zaamo;
|
||||||
bool ext_zacas;
|
bool ext_zacas;
|
||||||
@ -127,6 +128,7 @@ struct RISCVCPUConfig {
|
|||||||
bool ext_smepmp;
|
bool ext_smepmp;
|
||||||
bool rvv_ta_all_1s;
|
bool rvv_ta_all_1s;
|
||||||
bool rvv_ma_all_1s;
|
bool rvv_ma_all_1s;
|
||||||
|
bool rvv_vl_half_avl;
|
||||||
|
|
||||||
uint32_t mvendorid;
|
uint32_t mvendorid;
|
||||||
uint64_t marchid;
|
uint64_t marchid;
|
||||||
|
@ -1323,7 +1323,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
|
|||||||
int ret = TRANSLATE_FAIL;
|
int ret = TRANSLATE_FAIL;
|
||||||
int mode = mmuidx_priv(mmu_idx);
|
int mode = mmuidx_priv(mmu_idx);
|
||||||
/* default TLB page size */
|
/* default TLB page size */
|
||||||
target_ulong tlb_size = TARGET_PAGE_SIZE;
|
hwaddr tlb_size = TARGET_PAGE_SIZE;
|
||||||
|
|
||||||
env->guest_phys_fault_addr = 0;
|
env->guest_phys_fault_addr = 0;
|
||||||
|
|
||||||
@ -1375,7 +1375,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
|
|||||||
|
|
||||||
qemu_log_mask(CPU_LOG_MMU,
|
qemu_log_mask(CPU_LOG_MMU,
|
||||||
"%s PMP address=" HWADDR_FMT_plx " ret %d prot"
|
"%s PMP address=" HWADDR_FMT_plx " ret %d prot"
|
||||||
" %d tlb_size " TARGET_FMT_lu "\n",
|
" %d tlb_size %" HWADDR_PRIu "\n",
|
||||||
__func__, pa, ret, prot_pmp, tlb_size);
|
__func__, pa, ret, prot_pmp, tlb_size);
|
||||||
|
|
||||||
prot &= prot_pmp;
|
prot &= prot_pmp;
|
||||||
@ -1409,7 +1409,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
|
|||||||
|
|
||||||
qemu_log_mask(CPU_LOG_MMU,
|
qemu_log_mask(CPU_LOG_MMU,
|
||||||
"%s PMP address=" HWADDR_FMT_plx " ret %d prot"
|
"%s PMP address=" HWADDR_FMT_plx " ret %d prot"
|
||||||
" %d tlb_size " TARGET_FMT_lu "\n",
|
" %d tlb_size %" HWADDR_PRIu "\n",
|
||||||
__func__, pa, ret, prot_pmp, tlb_size);
|
__func__, pa, ret, prot_pmp, tlb_size);
|
||||||
|
|
||||||
prot &= prot_pmp;
|
prot &= prot_pmp;
|
||||||
@ -1674,10 +1674,12 @@ void riscv_cpu_do_interrupt(CPUState *cs)
|
|||||||
if (!async) {
|
if (!async) {
|
||||||
/* set tval to badaddr for traps with address information */
|
/* set tval to badaddr for traps with address information */
|
||||||
switch (cause) {
|
switch (cause) {
|
||||||
|
#ifdef CONFIG_TCG
|
||||||
case RISCV_EXCP_SEMIHOST:
|
case RISCV_EXCP_SEMIHOST:
|
||||||
do_common_semihosting(cs);
|
do_common_semihosting(cs);
|
||||||
env->pc += 4;
|
env->pc += 4;
|
||||||
return;
|
return;
|
||||||
|
#endif
|
||||||
case RISCV_EXCP_LOAD_GUEST_ACCESS_FAULT:
|
case RISCV_EXCP_LOAD_GUEST_ACCESS_FAULT:
|
||||||
case RISCV_EXCP_STORE_GUEST_AMO_ACCESS_FAULT:
|
case RISCV_EXCP_STORE_GUEST_AMO_ACCESS_FAULT:
|
||||||
case RISCV_EXCP_LOAD_ADDR_MIS:
|
case RISCV_EXCP_LOAD_ADDR_MIS:
|
||||||
|
@ -217,6 +217,66 @@ static inline void warn_always_zero_bit(target_ulong val, target_ulong mask,
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static target_ulong textra_validate(CPURISCVState *env, target_ulong tdata3)
|
||||||
|
{
|
||||||
|
target_ulong mhvalue, mhselect;
|
||||||
|
target_ulong mhselect_new;
|
||||||
|
target_ulong textra;
|
||||||
|
const uint32_t mhselect_no_rvh[8] = { 0, 0, 0, 0, 4, 4, 4, 4 };
|
||||||
|
|
||||||
|
switch (riscv_cpu_mxl(env)) {
|
||||||
|
case MXL_RV32:
|
||||||
|
mhvalue = get_field(tdata3, TEXTRA32_MHVALUE);
|
||||||
|
mhselect = get_field(tdata3, TEXTRA32_MHSELECT);
|
||||||
|
/* Validate unimplemented (always zero) bits */
|
||||||
|
warn_always_zero_bit(tdata3, (target_ulong)TEXTRA32_SBYTEMASK,
|
||||||
|
"sbytemask");
|
||||||
|
warn_always_zero_bit(tdata3, (target_ulong)TEXTRA32_SVALUE,
|
||||||
|
"svalue");
|
||||||
|
warn_always_zero_bit(tdata3, (target_ulong)TEXTRA32_SSELECT,
|
||||||
|
"sselect");
|
||||||
|
break;
|
||||||
|
case MXL_RV64:
|
||||||
|
case MXL_RV128:
|
||||||
|
mhvalue = get_field(tdata3, TEXTRA64_MHVALUE);
|
||||||
|
mhselect = get_field(tdata3, TEXTRA64_MHSELECT);
|
||||||
|
/* Validate unimplemented (always zero) bits */
|
||||||
|
warn_always_zero_bit(tdata3, (target_ulong)TEXTRA64_SBYTEMASK,
|
||||||
|
"sbytemask");
|
||||||
|
warn_always_zero_bit(tdata3, (target_ulong)TEXTRA64_SVALUE,
|
||||||
|
"svalue");
|
||||||
|
warn_always_zero_bit(tdata3, (target_ulong)TEXTRA64_SSELECT,
|
||||||
|
"sselect");
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Validate mhselect. */
|
||||||
|
mhselect_new = mhselect_no_rvh[mhselect];
|
||||||
|
if (mhselect != mhselect_new) {
|
||||||
|
qemu_log_mask(LOG_UNIMP, "mhselect only supports 0 or 4 for now\n");
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Write legal values into textra */
|
||||||
|
textra = 0;
|
||||||
|
switch (riscv_cpu_mxl(env)) {
|
||||||
|
case MXL_RV32:
|
||||||
|
textra = set_field(textra, TEXTRA32_MHVALUE, mhvalue);
|
||||||
|
textra = set_field(textra, TEXTRA32_MHSELECT, mhselect_new);
|
||||||
|
break;
|
||||||
|
case MXL_RV64:
|
||||||
|
case MXL_RV128:
|
||||||
|
textra = set_field(textra, TEXTRA64_MHVALUE, mhvalue);
|
||||||
|
textra = set_field(textra, TEXTRA64_MHSELECT, mhselect_new);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
|
||||||
|
return textra;
|
||||||
|
}
|
||||||
|
|
||||||
static void do_trigger_action(CPURISCVState *env, target_ulong trigger_index)
|
static void do_trigger_action(CPURISCVState *env, target_ulong trigger_index)
|
||||||
{
|
{
|
||||||
trigger_action_t action = get_trigger_action(env, trigger_index);
|
trigger_action_t action = get_trigger_action(env, trigger_index);
|
||||||
@ -304,11 +364,54 @@ static bool trigger_priv_match(CPURISCVState *env, trigger_type_t type,
|
|||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static bool trigger_textra_match(CPURISCVState *env, trigger_type_t type,
|
||||||
|
int trigger_index)
|
||||||
|
{
|
||||||
|
target_ulong textra = env->tdata3[trigger_index];
|
||||||
|
target_ulong mhvalue, mhselect;
|
||||||
|
|
||||||
|
if (type < TRIGGER_TYPE_AD_MATCH || type > TRIGGER_TYPE_AD_MATCH6) {
|
||||||
|
/* textra checking is only applicable when type is 2, 3, 4, 5, or 6 */
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
|
switch (riscv_cpu_mxl(env)) {
|
||||||
|
case MXL_RV32:
|
||||||
|
mhvalue = get_field(textra, TEXTRA32_MHVALUE);
|
||||||
|
mhselect = get_field(textra, TEXTRA32_MHSELECT);
|
||||||
|
break;
|
||||||
|
case MXL_RV64:
|
||||||
|
case MXL_RV128:
|
||||||
|
mhvalue = get_field(textra, TEXTRA64_MHVALUE);
|
||||||
|
mhselect = get_field(textra, TEXTRA64_MHSELECT);
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
g_assert_not_reached();
|
||||||
|
}
|
||||||
|
|
||||||
|
/* Check mhvalue and mhselect. */
|
||||||
|
switch (mhselect) {
|
||||||
|
case MHSELECT_IGNORE:
|
||||||
|
break;
|
||||||
|
case MHSELECT_MCONTEXT:
|
||||||
|
/* Match if the low bits of mcontext/hcontext equal mhvalue. */
|
||||||
|
if (mhvalue != env->mcontext) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
default:
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
||||||
/* Common matching conditions for all types of the triggers. */
|
/* Common matching conditions for all types of the triggers. */
|
||||||
static bool trigger_common_match(CPURISCVState *env, trigger_type_t type,
|
static bool trigger_common_match(CPURISCVState *env, trigger_type_t type,
|
||||||
int trigger_index)
|
int trigger_index)
|
||||||
{
|
{
|
||||||
return trigger_priv_match(env, type, trigger_index);
|
return trigger_priv_match(env, type, trigger_index) &&
|
||||||
|
trigger_textra_match(env, type, trigger_index);
|
||||||
}
|
}
|
||||||
|
|
||||||
/* type 2 trigger */
|
/* type 2 trigger */
|
||||||
@ -441,8 +544,7 @@ static void type2_reg_write(CPURISCVState *env, target_ulong index,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TDATA3:
|
case TDATA3:
|
||||||
qemu_log_mask(LOG_UNIMP,
|
env->tdata3[index] = textra_validate(env, val);
|
||||||
"tdata3 is not supported for type 2 trigger\n");
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
g_assert_not_reached();
|
g_assert_not_reached();
|
||||||
@ -558,8 +660,7 @@ static void type6_reg_write(CPURISCVState *env, target_ulong index,
|
|||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case TDATA3:
|
case TDATA3:
|
||||||
qemu_log_mask(LOG_UNIMP,
|
env->tdata3[index] = textra_validate(env, val);
|
||||||
"tdata3 is not supported for type 6 trigger\n");
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
g_assert_not_reached();
|
g_assert_not_reached();
|
||||||
@ -741,8 +842,7 @@ static void itrigger_reg_write(CPURISCVState *env, target_ulong index,
|
|||||||
"tdata2 is not supported for icount trigger\n");
|
"tdata2 is not supported for icount trigger\n");
|
||||||
break;
|
break;
|
||||||
case TDATA3:
|
case TDATA3:
|
||||||
qemu_log_mask(LOG_UNIMP,
|
env->tdata3[index] = textra_validate(env, val);
|
||||||
"tdata3 is not supported for icount trigger\n");
|
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
g_assert_not_reached();
|
g_assert_not_reached();
|
||||||
|
@ -131,6 +131,9 @@ enum {
|
|||||||
#define ITRIGGER_VU BIT(25)
|
#define ITRIGGER_VU BIT(25)
|
||||||
#define ITRIGGER_VS BIT(26)
|
#define ITRIGGER_VS BIT(26)
|
||||||
|
|
||||||
|
#define MHSELECT_IGNORE 0
|
||||||
|
#define MHSELECT_MCONTEXT 4
|
||||||
|
|
||||||
bool tdata_available(CPURISCVState *env, int tdata_index);
|
bool tdata_available(CPURISCVState *env, int tdata_index);
|
||||||
|
|
||||||
target_ulong tselect_csr_read(CPURISCVState *env);
|
target_ulong tselect_csr_read(CPURISCVState *env);
|
||||||
|
@ -1695,6 +1695,7 @@ void kvm_riscv_aia_create(MachineState *machine, uint64_t group_shift,
|
|||||||
uint64_t max_hart_per_socket = 0;
|
uint64_t max_hart_per_socket = 0;
|
||||||
uint64_t socket, base_hart, hart_count, socket_imsic_base, imsic_addr;
|
uint64_t socket, base_hart, hart_count, socket_imsic_base, imsic_addr;
|
||||||
uint64_t socket_bits, hart_bits, guest_bits;
|
uint64_t socket_bits, hart_bits, guest_bits;
|
||||||
|
uint64_t max_group_id;
|
||||||
|
|
||||||
aia_fd = kvm_create_device(kvm_state, KVM_DEV_TYPE_RISCV_AIA, false);
|
aia_fd = kvm_create_device(kvm_state, KVM_DEV_TYPE_RISCV_AIA, false);
|
||||||
|
|
||||||
@ -1742,7 +1743,8 @@ void kvm_riscv_aia_create(MachineState *machine, uint64_t group_shift,
|
|||||||
|
|
||||||
|
|
||||||
if (socket_count > 1) {
|
if (socket_count > 1) {
|
||||||
socket_bits = find_last_bit(&socket_count, BITS_PER_LONG) + 1;
|
max_group_id = socket_count - 1;
|
||||||
|
socket_bits = find_last_bit(&max_group_id, BITS_PER_LONG) + 1;
|
||||||
ret = kvm_device_access(aia_fd, KVM_DEV_RISCV_AIA_GRP_CONFIG,
|
ret = kvm_device_access(aia_fd, KVM_DEV_RISCV_AIA_GRP_CONFIG,
|
||||||
KVM_DEV_RISCV_AIA_CONFIG_GROUP_BITS,
|
KVM_DEV_RISCV_AIA_CONFIG_GROUP_BITS,
|
||||||
&socket_bits, true, NULL);
|
&socket_bits, true, NULL);
|
||||||
|
@ -778,11 +778,18 @@ static void cpu_enable_implied_rule(RISCVCPU *cpu,
|
|||||||
if (!enabled) {
|
if (!enabled) {
|
||||||
/* Enable the implied MISAs. */
|
/* Enable the implied MISAs. */
|
||||||
if (rule->implied_misa_exts) {
|
if (rule->implied_misa_exts) {
|
||||||
riscv_cpu_set_misa_ext(env,
|
|
||||||
env->misa_ext | rule->implied_misa_exts);
|
|
||||||
|
|
||||||
for (i = 0; misa_bits[i] != 0; i++) {
|
for (i = 0; misa_bits[i] != 0; i++) {
|
||||||
if (rule->implied_misa_exts & misa_bits[i]) {
|
if (rule->implied_misa_exts & misa_bits[i]) {
|
||||||
|
/*
|
||||||
|
* If the user disabled the misa_bit do not re-enable it
|
||||||
|
* and do not apply any implied rules related to it.
|
||||||
|
*/
|
||||||
|
if (cpu_misa_ext_is_user_set(misa_bits[i]) &&
|
||||||
|
!(env->misa_ext & misa_bits[i])) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
riscv_cpu_set_misa_ext(env, env->misa_ext | misa_bits[i]);
|
||||||
ir = g_hash_table_lookup(misa_ext_implied_rules,
|
ir = g_hash_table_lookup(misa_ext_implied_rules,
|
||||||
GUINT_TO_POINTER(misa_bits[i]));
|
GUINT_TO_POINTER(misa_bits[i]));
|
||||||
|
|
||||||
|
@ -92,6 +92,7 @@ void riscv_timer_write_timecmp(CPURISCVState *env, QEMUTimer *timer,
|
|||||||
* equals UINT64_MAX.
|
* equals UINT64_MAX.
|
||||||
*/
|
*/
|
||||||
if (timecmp == UINT64_MAX) {
|
if (timecmp == UINT64_MAX) {
|
||||||
|
timer_del(timer);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -75,6 +75,8 @@ target_ulong HELPER(vsetvl)(CPURISCVState *env, target_ulong s1,
|
|||||||
vlmax = vext_get_vlmax(cpu->cfg.vlenb, vsew, lmul);
|
vlmax = vext_get_vlmax(cpu->cfg.vlenb, vsew, lmul);
|
||||||
if (s1 <= vlmax) {
|
if (s1 <= vlmax) {
|
||||||
vl = s1;
|
vl = s1;
|
||||||
|
} else if (s1 < 2 * vlmax && cpu->cfg.rvv_vl_half_avl) {
|
||||||
|
vl = (s1 + 1) >> 1;
|
||||||
} else {
|
} else {
|
||||||
vl = vlmax;
|
vl = vlmax;
|
||||||
}
|
}
|
||||||
|
BIN
tests/data/acpi/riscv64/virt/SRAT.numamem
Normal file
BIN
tests/data/acpi/riscv64/virt/SRAT.numamem
Normal file
Binary file not shown.
@ -1706,6 +1706,32 @@ static void test_acpi_microvm_ioapic2_tcg(void)
|
|||||||
free_test_data(&data);
|
free_test_data(&data);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static void test_acpi_riscv64_virt_tcg_numamem(void)
|
||||||
|
{
|
||||||
|
test_data data = {
|
||||||
|
.machine = "virt",
|
||||||
|
.arch = "riscv64",
|
||||||
|
.tcg_only = true,
|
||||||
|
.uefi_fl1 = "pc-bios/edk2-riscv-code.fd",
|
||||||
|
.uefi_fl2 = "pc-bios/edk2-riscv-vars.fd",
|
||||||
|
.cd = "tests/data/uefi-boot-images/bios-tables-test.riscv64.iso.qcow2",
|
||||||
|
.ram_start = 0x80000000ULL,
|
||||||
|
.scan_len = 128ULL * 1024 * 1024,
|
||||||
|
};
|
||||||
|
|
||||||
|
data.variant = ".numamem";
|
||||||
|
/*
|
||||||
|
* RHCT will have ISA string encoded. To reduce the effort
|
||||||
|
* of updating expected AML file for any new default ISA extension,
|
||||||
|
* use the profile rva22s64.
|
||||||
|
*/
|
||||||
|
test_acpi_one(" -cpu rva22s64"
|
||||||
|
" -object memory-backend-ram,id=ram0,size=128M"
|
||||||
|
" -numa node,memdev=ram0",
|
||||||
|
&data);
|
||||||
|
free_test_data(&data);
|
||||||
|
}
|
||||||
|
|
||||||
static void test_acpi_aarch64_virt_tcg_numamem(void)
|
static void test_acpi_aarch64_virt_tcg_numamem(void)
|
||||||
{
|
{
|
||||||
test_data data = {
|
test_data data = {
|
||||||
@ -2466,6 +2492,8 @@ int main(int argc, char *argv[])
|
|||||||
} else if (strcmp(arch, "riscv64") == 0) {
|
} else if (strcmp(arch, "riscv64") == 0) {
|
||||||
if (has_tcg && qtest_has_device("virtio-blk-pci")) {
|
if (has_tcg && qtest_has_device("virtio-blk-pci")) {
|
||||||
qtest_add_func("acpi/virt", test_acpi_riscv64_virt_tcg);
|
qtest_add_func("acpi/virt", test_acpi_riscv64_virt_tcg);
|
||||||
|
qtest_add_func("acpi/virt/numamem",
|
||||||
|
test_acpi_riscv64_virt_tcg_numamem);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
ret = g_test_run();
|
ret = g_test_run();
|
||||||
|
@ -9,6 +9,7 @@
|
|||||||
#ifdef CONFIG_ASM_HWPROBE_H
|
#ifdef CONFIG_ASM_HWPROBE_H
|
||||||
#include <asm/hwprobe.h>
|
#include <asm/hwprobe.h>
|
||||||
#include <sys/syscall.h>
|
#include <sys/syscall.h>
|
||||||
|
#include <asm/unistd.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
unsigned cpuinfo;
|
unsigned cpuinfo;
|
||||||
|
Loading…
Reference in New Issue
Block a user