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:
Peter Maydell 2024-10-02 16:30:06 +01:00
commit 35ba77d2fc
37 changed files with 1068 additions and 57 deletions

170
bsd-user/riscv/signal.c Normal file
View 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
View 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 */

View 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 */

View 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;
}

View 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 */

View 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 */

View 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 */

View 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 */

View 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 */

View 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 */

View 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 */

View 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 */

View 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 */

View 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

View File

@ -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:

View File

@ -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);

View File

@ -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,

View File

@ -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) {

View File

@ -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)

View File

@ -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,

View File

@ -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);

View File

@ -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) {

View File

@ -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,

View File

@ -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

View File

@ -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

View File

@ -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

View File

@ -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;

View File

@ -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(CPU_LOG_MMU,
"%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);
prot &= prot_pmp;
@ -1409,7 +1409,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
qemu_log_mask(CPU_LOG_MMU,
"%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);
prot &= prot_pmp;
@ -1674,10 +1674,12 @@ void riscv_cpu_do_interrupt(CPUState *cs)
if (!async) {
/* set tval to badaddr for traps with address information */
switch (cause) {
#ifdef CONFIG_TCG
case RISCV_EXCP_SEMIHOST:
do_common_semihosting(cs);
env->pc += 4;
return;
#endif
case RISCV_EXCP_LOAD_GUEST_ACCESS_FAULT:
case RISCV_EXCP_STORE_GUEST_AMO_ACCESS_FAULT:
case RISCV_EXCP_LOAD_ADDR_MIS:

View File

@ -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)
{
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;
}
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. */
static bool trigger_common_match(CPURISCVState *env, trigger_type_t type,
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 */
@ -441,8 +544,7 @@ static void type2_reg_write(CPURISCVState *env, target_ulong index,
}
break;
case TDATA3:
qemu_log_mask(LOG_UNIMP,
"tdata3 is not supported for type 2 trigger\n");
env->tdata3[index] = textra_validate(env, val);
break;
default:
g_assert_not_reached();
@ -558,8 +660,7 @@ static void type6_reg_write(CPURISCVState *env, target_ulong index,
}
break;
case TDATA3:
qemu_log_mask(LOG_UNIMP,
"tdata3 is not supported for type 6 trigger\n");
env->tdata3[index] = textra_validate(env, val);
break;
default:
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");
break;
case TDATA3:
qemu_log_mask(LOG_UNIMP,
"tdata3 is not supported for icount trigger\n");
env->tdata3[index] = textra_validate(env, val);
break;
default:
g_assert_not_reached();

View File

@ -131,6 +131,9 @@ enum {
#define ITRIGGER_VU BIT(25)
#define ITRIGGER_VS BIT(26)
#define MHSELECT_IGNORE 0
#define MHSELECT_MCONTEXT 4
bool tdata_available(CPURISCVState *env, int tdata_index);
target_ulong tselect_csr_read(CPURISCVState *env);

View File

@ -1695,6 +1695,7 @@ void kvm_riscv_aia_create(MachineState *machine, uint64_t group_shift,
uint64_t max_hart_per_socket = 0;
uint64_t socket, base_hart, hart_count, socket_imsic_base, imsic_addr;
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);
@ -1742,7 +1743,8 @@ void kvm_riscv_aia_create(MachineState *machine, uint64_t group_shift,
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,
KVM_DEV_RISCV_AIA_CONFIG_GROUP_BITS,
&socket_bits, true, NULL);

View File

@ -778,11 +778,18 @@ static void cpu_enable_implied_rule(RISCVCPU *cpu,
if (!enabled) {
/* Enable the implied MISAs. */
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++) {
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,
GUINT_TO_POINTER(misa_bits[i]));

View File

@ -92,6 +92,7 @@ void riscv_timer_write_timecmp(CPURISCVState *env, QEMUTimer *timer,
* equals UINT64_MAX.
*/
if (timecmp == UINT64_MAX) {
timer_del(timer);
return;
}

View File

@ -75,6 +75,8 @@ target_ulong HELPER(vsetvl)(CPURISCVState *env, target_ulong s1,
vlmax = vext_get_vlmax(cpu->cfg.vlenb, vsew, lmul);
if (s1 <= vlmax) {
vl = s1;
} else if (s1 < 2 * vlmax && cpu->cfg.rvv_vl_half_avl) {
vl = (s1 + 1) >> 1;
} else {
vl = vlmax;
}

Binary file not shown.

View File

@ -1706,6 +1706,32 @@ static void test_acpi_microvm_ioapic2_tcg(void)
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)
{
test_data data = {
@ -2466,6 +2492,8 @@ int main(int argc, char *argv[])
} else if (strcmp(arch, "riscv64") == 0) {
if (has_tcg && qtest_has_device("virtio-blk-pci")) {
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();

View File

@ -9,6 +9,7 @@
#ifdef CONFIG_ASM_HWPROBE_H
#include <asm/hwprobe.h>
#include <sys/syscall.h>
#include <asm/unistd.h>
#endif
unsigned cpuinfo;