2018-03-02 15:31:10 +03:00
|
|
|
/*
|
|
|
|
* QEMU RISC-V CPU
|
|
|
|
*
|
|
|
|
* Copyright (c) 2016-2017 Sagar Karandikar, sagark@eecs.berkeley.edu
|
|
|
|
* Copyright (c) 2017-2018 SiFive, Inc.
|
|
|
|
*
|
|
|
|
* This program is free software; you can redistribute it and/or modify it
|
|
|
|
* under the terms and conditions of the GNU General Public License,
|
|
|
|
* version 2 or later, as published by the Free Software Foundation.
|
|
|
|
*
|
|
|
|
* This program is distributed in the hope 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"
|
2019-04-17 22:17:57 +03:00
|
|
|
#include "qemu/qemu-print.h"
|
2019-05-23 17:35:06 +03:00
|
|
|
#include "qemu/ctype.h"
|
2018-03-02 15:31:10 +03:00
|
|
|
#include "qemu/log.h"
|
|
|
|
#include "cpu.h"
|
2023-01-31 23:20:11 +03:00
|
|
|
#include "cpu_vendorid.h"
|
2022-08-25 01:16:57 +03:00
|
|
|
#include "pmu.h"
|
2020-10-26 14:55:26 +03:00
|
|
|
#include "internals.h"
|
2022-08-25 01:13:56 +03:00
|
|
|
#include "time_helper.h"
|
2018-03-02 15:31:10 +03:00
|
|
|
#include "exec/exec-all.h"
|
|
|
|
#include "qapi/error.h"
|
riscv: Allow user to set the satp mode
RISC-V specifies multiple sizes for addressable memory and Linux probes for
the machine's support at startup via the satp CSR register (done in
csr.c:validate_vm).
As per the specification, sv64 must support sv57, which in turn must
support sv48...etc. So we can restrict machine support by simply setting the
"highest" supported mode and the bare mode is always supported.
You can set the satp mode using the new properties "sv32", "sv39", "sv48",
"sv57" and "sv64" as follows:
-cpu rv64,sv57=on # Linux will boot using sv57 scheme
-cpu rv64,sv39=on # Linux will boot using sv39 scheme
-cpu rv64,sv57=off # Linux will boot using sv48 scheme
-cpu rv64 # Linux will boot using sv57 scheme by default
We take the highest level set by the user:
-cpu rv64,sv48=on,sv57=on # Linux will boot using sv57 scheme
We make sure that invalid configurations are rejected:
-cpu rv64,sv39=off,sv48=on # sv39 must be supported if higher modes are
# enabled
We accept "redundant" configurations:
-cpu rv64,sv48=on,sv57=off # Linux will boot using sv48 scheme
And contradictory configurations:
-cpu rv64,sv48=on,sv48=off # Linux will boot using sv39 scheme
Co-Developed-by: Ludovic Henry <ludovic@rivosinc.com>
Signed-off-by: Ludovic Henry <ludovic@rivosinc.com>
Signed-off-by: Alexandre Ghiti <alexghiti@rivosinc.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
Reviewed-by: Bin Meng <bmeng@tinylab.org>
Acked-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Frank Chang <frank.chang@sifive.com>
Message-ID: <20230303131252.892893-4-alexghiti@rivosinc.com>
Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
2023-03-03 16:12:50 +03:00
|
|
|
#include "qapi/visitor.h"
|
2019-05-07 01:49:53 +03:00
|
|
|
#include "qemu/error-report.h"
|
2019-04-20 05:24:01 +03:00
|
|
|
#include "hw/qdev-properties.h"
|
2018-03-02 15:31:10 +03:00
|
|
|
#include "migration/vmstate.h"
|
2019-08-08 19:29:41 +03:00
|
|
|
#include "fpu/softfloat-helpers.h"
|
2022-01-12 11:13:22 +03:00
|
|
|
#include "sysemu/kvm.h"
|
|
|
|
#include "kvm_riscv.h"
|
2023-02-27 16:51:52 +03:00
|
|
|
#include "tcg/tcg.h"
|
2018-03-02 15:31:10 +03:00
|
|
|
|
|
|
|
/* RISC-V CPU definitions */
|
|
|
|
|
2022-04-22 07:04:34 +03:00
|
|
|
#define RISCV_CPU_MARCHID ((QEMU_VERSION_MAJOR << 16) | \
|
|
|
|
(QEMU_VERSION_MINOR << 8) | \
|
|
|
|
(QEMU_VERSION_MICRO))
|
2022-05-23 18:31:46 +03:00
|
|
|
#define RISCV_CPU_MIMPID RISCV_CPU_MARCHID
|
2022-04-22 07:04:34 +03:00
|
|
|
|
2022-03-28 16:11:23 +03:00
|
|
|
static const char riscv_single_letter_exts[] = "IEMAFDQCPVH";
|
2018-03-02 15:31:10 +03:00
|
|
|
|
2022-03-29 22:56:57 +03:00
|
|
|
struct isa_ext_data {
|
|
|
|
const char *name;
|
2022-06-30 09:11:50 +03:00
|
|
|
bool multi_letter;
|
|
|
|
int min_version;
|
|
|
|
int ext_enable_offset;
|
2022-03-29 22:56:57 +03:00
|
|
|
};
|
|
|
|
|
2022-06-30 09:11:50 +03:00
|
|
|
#define ISA_EXT_DATA_ENTRY(_name, _m_letter, _min_ver, _prop) \
|
|
|
|
{#_name, _m_letter, _min_ver, offsetof(struct RISCVCPUConfig, _prop)}
|
|
|
|
|
|
|
|
/**
|
|
|
|
* Here are the ordering rules of extension naming defined by RISC-V
|
|
|
|
* specification :
|
|
|
|
* 1. All extensions should be separated from other multi-letter extensions
|
|
|
|
* by an underscore.
|
|
|
|
* 2. The first letter following the 'Z' conventionally indicates the most
|
|
|
|
* closely related alphabetical extension category, IMAFDQLCBKJTPVH.
|
|
|
|
* If multiple 'Z' extensions are named, they should be ordered first
|
|
|
|
* by category, then alphabetically within a category.
|
|
|
|
* 3. Standard supervisor-level extensions (starts with 'S') should be
|
|
|
|
* listed after standard unprivileged extensions. If multiple
|
|
|
|
* supervisor-level extensions are listed, they should be ordered
|
|
|
|
* alphabetically.
|
|
|
|
* 4. Non-standard extensions (starts with 'X') must be listed after all
|
|
|
|
* standard extensions. They must be separated from other multi-letter
|
|
|
|
* extensions by an underscore.
|
|
|
|
*/
|
|
|
|
static const struct isa_ext_data isa_edata_arr[] = {
|
|
|
|
ISA_EXT_DATA_ENTRY(h, false, PRIV_VERSION_1_12_0, ext_h),
|
2023-02-08 09:32:08 +03:00
|
|
|
ISA_EXT_DATA_ENTRY(v, false, PRIV_VERSION_1_10_0, ext_v),
|
2023-02-24 16:25:35 +03:00
|
|
|
ISA_EXT_DATA_ENTRY(zicbom, true, PRIV_VERSION_1_12_0, ext_icbom),
|
2023-02-24 16:25:34 +03:00
|
|
|
ISA_EXT_DATA_ENTRY(zicboz, true, PRIV_VERSION_1_12_0, ext_icboz),
|
2023-02-21 12:10:09 +03:00
|
|
|
ISA_EXT_DATA_ENTRY(zicond, true, PRIV_VERSION_1_12_0, ext_zicond),
|
2022-06-30 09:11:50 +03:00
|
|
|
ISA_EXT_DATA_ENTRY(zicsr, true, PRIV_VERSION_1_10_0, ext_icsr),
|
|
|
|
ISA_EXT_DATA_ENTRY(zifencei, true, PRIV_VERSION_1_10_0, ext_ifencei),
|
2022-07-25 06:47:28 +03:00
|
|
|
ISA_EXT_DATA_ENTRY(zihintpause, true, PRIV_VERSION_1_10_0, ext_zihintpause),
|
2022-10-05 17:49:48 +03:00
|
|
|
ISA_EXT_DATA_ENTRY(zawrs, true, PRIV_VERSION_1_12_0, ext_zawrs),
|
2023-01-31 23:20:10 +03:00
|
|
|
ISA_EXT_DATA_ENTRY(zfh, true, PRIV_VERSION_1_11_0, ext_zfh),
|
2022-06-30 09:11:50 +03:00
|
|
|
ISA_EXT_DATA_ENTRY(zfhmin, true, PRIV_VERSION_1_12_0, ext_zfhmin),
|
|
|
|
ISA_EXT_DATA_ENTRY(zfinx, true, PRIV_VERSION_1_12_0, ext_zfinx),
|
|
|
|
ISA_EXT_DATA_ENTRY(zdinx, true, PRIV_VERSION_1_12_0, ext_zdinx),
|
|
|
|
ISA_EXT_DATA_ENTRY(zba, true, PRIV_VERSION_1_12_0, ext_zba),
|
|
|
|
ISA_EXT_DATA_ENTRY(zbb, true, PRIV_VERSION_1_12_0, ext_zbb),
|
|
|
|
ISA_EXT_DATA_ENTRY(zbc, true, PRIV_VERSION_1_12_0, ext_zbc),
|
|
|
|
ISA_EXT_DATA_ENTRY(zbkb, true, PRIV_VERSION_1_12_0, ext_zbkb),
|
|
|
|
ISA_EXT_DATA_ENTRY(zbkc, true, PRIV_VERSION_1_12_0, ext_zbkc),
|
|
|
|
ISA_EXT_DATA_ENTRY(zbkx, true, PRIV_VERSION_1_12_0, ext_zbkx),
|
|
|
|
ISA_EXT_DATA_ENTRY(zbs, true, PRIV_VERSION_1_12_0, ext_zbs),
|
|
|
|
ISA_EXT_DATA_ENTRY(zk, true, PRIV_VERSION_1_12_0, ext_zk),
|
|
|
|
ISA_EXT_DATA_ENTRY(zkn, true, PRIV_VERSION_1_12_0, ext_zkn),
|
|
|
|
ISA_EXT_DATA_ENTRY(zknd, true, PRIV_VERSION_1_12_0, ext_zknd),
|
|
|
|
ISA_EXT_DATA_ENTRY(zkne, true, PRIV_VERSION_1_12_0, ext_zkne),
|
|
|
|
ISA_EXT_DATA_ENTRY(zknh, true, PRIV_VERSION_1_12_0, ext_zknh),
|
|
|
|
ISA_EXT_DATA_ENTRY(zkr, true, PRIV_VERSION_1_12_0, ext_zkr),
|
|
|
|
ISA_EXT_DATA_ENTRY(zks, true, PRIV_VERSION_1_12_0, ext_zks),
|
|
|
|
ISA_EXT_DATA_ENTRY(zksed, true, PRIV_VERSION_1_12_0, ext_zksed),
|
|
|
|
ISA_EXT_DATA_ENTRY(zksh, true, PRIV_VERSION_1_12_0, ext_zksh),
|
|
|
|
ISA_EXT_DATA_ENTRY(zkt, true, PRIV_VERSION_1_12_0, ext_zkt),
|
|
|
|
ISA_EXT_DATA_ENTRY(zve32f, true, PRIV_VERSION_1_12_0, ext_zve32f),
|
|
|
|
ISA_EXT_DATA_ENTRY(zve64f, true, PRIV_VERSION_1_12_0, ext_zve64f),
|
2023-02-15 05:05:39 +03:00
|
|
|
ISA_EXT_DATA_ENTRY(zve64d, true, PRIV_VERSION_1_12_0, ext_zve64d),
|
|
|
|
ISA_EXT_DATA_ENTRY(zvfh, true, PRIV_VERSION_1_12_0, ext_zvfh),
|
|
|
|
ISA_EXT_DATA_ENTRY(zvfhmin, true, PRIV_VERSION_1_12_0, ext_zvfhmin),
|
2022-06-30 09:11:50 +03:00
|
|
|
ISA_EXT_DATA_ENTRY(zhinx, true, PRIV_VERSION_1_12_0, ext_zhinx),
|
|
|
|
ISA_EXT_DATA_ENTRY(zhinxmin, true, PRIV_VERSION_1_12_0, ext_zhinxmin),
|
2022-08-20 07:29:58 +03:00
|
|
|
ISA_EXT_DATA_ENTRY(smaia, true, PRIV_VERSION_1_12_0, ext_smaia),
|
|
|
|
ISA_EXT_DATA_ENTRY(ssaia, true, PRIV_VERSION_1_12_0, ext_ssaia),
|
2022-08-25 01:16:57 +03:00
|
|
|
ISA_EXT_DATA_ENTRY(sscofpmf, true, PRIV_VERSION_1_12_0, ext_sscofpmf),
|
2022-08-25 01:13:56 +03:00
|
|
|
ISA_EXT_DATA_ENTRY(sstc, true, PRIV_VERSION_1_12_0, ext_sstc),
|
2023-02-24 07:08:52 +03:00
|
|
|
ISA_EXT_DATA_ENTRY(svadu, true, PRIV_VERSION_1_12_0, ext_svadu),
|
2022-06-30 09:11:50 +03:00
|
|
|
ISA_EXT_DATA_ENTRY(svinval, true, PRIV_VERSION_1_12_0, ext_svinval),
|
|
|
|
ISA_EXT_DATA_ENTRY(svnapot, true, PRIV_VERSION_1_12_0, ext_svnapot),
|
|
|
|
ISA_EXT_DATA_ENTRY(svpbmt, true, PRIV_VERSION_1_12_0, ext_svpbmt),
|
2023-01-31 23:20:02 +03:00
|
|
|
ISA_EXT_DATA_ENTRY(xtheadba, true, PRIV_VERSION_1_11_0, ext_xtheadba),
|
2023-01-31 23:20:03 +03:00
|
|
|
ISA_EXT_DATA_ENTRY(xtheadbb, true, PRIV_VERSION_1_11_0, ext_xtheadbb),
|
2023-01-31 23:20:04 +03:00
|
|
|
ISA_EXT_DATA_ENTRY(xtheadbs, true, PRIV_VERSION_1_11_0, ext_xtheadbs),
|
2023-01-31 23:20:00 +03:00
|
|
|
ISA_EXT_DATA_ENTRY(xtheadcmo, true, PRIV_VERSION_1_11_0, ext_xtheadcmo),
|
2023-01-31 23:20:05 +03:00
|
|
|
ISA_EXT_DATA_ENTRY(xtheadcondmov, true, PRIV_VERSION_1_11_0, ext_xtheadcondmov),
|
2023-01-31 23:20:09 +03:00
|
|
|
ISA_EXT_DATA_ENTRY(xtheadfmemidx, true, PRIV_VERSION_1_11_0, ext_xtheadfmemidx),
|
2023-01-31 23:20:12 +03:00
|
|
|
ISA_EXT_DATA_ENTRY(xtheadfmv, true, PRIV_VERSION_1_11_0, ext_xtheadfmv),
|
2023-01-31 23:20:06 +03:00
|
|
|
ISA_EXT_DATA_ENTRY(xtheadmac, true, PRIV_VERSION_1_11_0, ext_xtheadmac),
|
2023-01-31 23:20:08 +03:00
|
|
|
ISA_EXT_DATA_ENTRY(xtheadmemidx, true, PRIV_VERSION_1_11_0, ext_xtheadmemidx),
|
2023-01-31 23:20:07 +03:00
|
|
|
ISA_EXT_DATA_ENTRY(xtheadmempair, true, PRIV_VERSION_1_11_0, ext_xtheadmempair),
|
2023-01-31 23:20:01 +03:00
|
|
|
ISA_EXT_DATA_ENTRY(xtheadsync, true, PRIV_VERSION_1_11_0, ext_xtheadsync),
|
2022-08-16 07:54:08 +03:00
|
|
|
ISA_EXT_DATA_ENTRY(xventanacondops, true, PRIV_VERSION_1_12_0, ext_XVentanaCondOps),
|
2022-06-30 09:11:50 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
static bool isa_ext_is_enabled(RISCVCPU *cpu,
|
|
|
|
const struct isa_ext_data *edata)
|
|
|
|
{
|
|
|
|
bool *ext_enabled = (void *)&cpu->cfg + edata->ext_enable_offset;
|
|
|
|
|
|
|
|
return *ext_enabled;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void isa_ext_update_enabled(RISCVCPU *cpu,
|
|
|
|
const struct isa_ext_data *edata, bool en)
|
|
|
|
{
|
|
|
|
bool *ext_enabled = (void *)&cpu->cfg + edata->ext_enable_offset;
|
|
|
|
|
|
|
|
*ext_enabled = en;
|
|
|
|
}
|
|
|
|
|
2018-03-02 15:31:10 +03:00
|
|
|
const char * const riscv_int_regnames[] = {
|
2019-08-23 18:21:19 +03:00
|
|
|
"x0/zero", "x1/ra", "x2/sp", "x3/gp", "x4/tp", "x5/t0", "x6/t1",
|
|
|
|
"x7/t2", "x8/s0", "x9/s1", "x10/a0", "x11/a1", "x12/a2", "x13/a3",
|
|
|
|
"x14/a4", "x15/a5", "x16/a6", "x17/a7", "x18/s2", "x19/s3", "x20/s4",
|
|
|
|
"x21/s5", "x22/s6", "x23/s7", "x24/s8", "x25/s9", "x26/s10", "x27/s11",
|
|
|
|
"x28/t3", "x29/t4", "x30/t5", "x31/t6"
|
2018-03-02 15:31:10 +03:00
|
|
|
};
|
|
|
|
|
2022-01-07 00:00:56 +03:00
|
|
|
const char * const riscv_int_regnamesh[] = {
|
|
|
|
"x0h/zeroh", "x1h/rah", "x2h/sph", "x3h/gph", "x4h/tph", "x5h/t0h",
|
|
|
|
"x6h/t1h", "x7h/t2h", "x8h/s0h", "x9h/s1h", "x10h/a0h", "x11h/a1h",
|
|
|
|
"x12h/a2h", "x13h/a3h", "x14h/a4h", "x15h/a5h", "x16h/a6h", "x17h/a7h",
|
|
|
|
"x18h/s2h", "x19h/s3h", "x20h/s4h", "x21h/s5h", "x22h/s6h", "x23h/s7h",
|
|
|
|
"x24h/s8h", "x25h/s9h", "x26h/s10h", "x27h/s11h", "x28h/t3h", "x29h/t4h",
|
|
|
|
"x30h/t5h", "x31h/t6h"
|
|
|
|
};
|
|
|
|
|
2018-03-02 15:31:10 +03:00
|
|
|
const char * const riscv_fpr_regnames[] = {
|
2019-08-23 18:21:19 +03:00
|
|
|
"f0/ft0", "f1/ft1", "f2/ft2", "f3/ft3", "f4/ft4", "f5/ft5",
|
|
|
|
"f6/ft6", "f7/ft7", "f8/fs0", "f9/fs1", "f10/fa0", "f11/fa1",
|
|
|
|
"f12/fa2", "f13/fa3", "f14/fa4", "f15/fa5", "f16/fa6", "f17/fa7",
|
|
|
|
"f18/fs2", "f19/fs3", "f20/fs4", "f21/fs5", "f22/fs6", "f23/fs7",
|
|
|
|
"f24/fs8", "f25/fs9", "f26/fs10", "f27/fs11", "f28/ft8", "f29/ft9",
|
|
|
|
"f30/ft10", "f31/ft11"
|
2018-03-02 15:31:10 +03:00
|
|
|
};
|
|
|
|
|
2021-05-14 08:24:35 +03:00
|
|
|
static const char * const riscv_excp_names[] = {
|
2018-03-02 15:31:10 +03:00
|
|
|
"misaligned_fetch",
|
|
|
|
"fault_fetch",
|
|
|
|
"illegal_instruction",
|
|
|
|
"breakpoint",
|
|
|
|
"misaligned_load",
|
|
|
|
"fault_load",
|
|
|
|
"misaligned_store",
|
|
|
|
"fault_store",
|
|
|
|
"user_ecall",
|
|
|
|
"supervisor_ecall",
|
|
|
|
"hypervisor_ecall",
|
|
|
|
"machine_ecall",
|
|
|
|
"exec_page_fault",
|
|
|
|
"load_page_fault",
|
|
|
|
"reserved",
|
2020-03-05 19:46:20 +03:00
|
|
|
"store_page_fault",
|
2020-02-01 04:01:46 +03:00
|
|
|
"reserved",
|
|
|
|
"reserved",
|
|
|
|
"reserved",
|
|
|
|
"reserved",
|
|
|
|
"guest_exec_page_fault",
|
|
|
|
"guest_load_page_fault",
|
|
|
|
"reserved",
|
2020-03-05 19:46:20 +03:00
|
|
|
"guest_store_page_fault",
|
2018-03-02 15:31:10 +03:00
|
|
|
};
|
|
|
|
|
2021-05-14 08:24:35 +03:00
|
|
|
static const char * const riscv_intr_names[] = {
|
2018-03-02 15:31:10 +03:00
|
|
|
"u_software",
|
|
|
|
"s_software",
|
2020-02-01 04:01:49 +03:00
|
|
|
"vs_software",
|
2018-03-02 15:31:10 +03:00
|
|
|
"m_software",
|
|
|
|
"u_timer",
|
|
|
|
"s_timer",
|
2020-02-01 04:01:49 +03:00
|
|
|
"vs_timer",
|
2018-03-02 15:31:10 +03:00
|
|
|
"m_timer",
|
|
|
|
"u_external",
|
2021-04-21 16:32:36 +03:00
|
|
|
"s_external",
|
2020-02-01 04:01:49 +03:00
|
|
|
"vs_external",
|
2018-03-02 15:31:10 +03:00
|
|
|
"m_external",
|
2018-03-06 00:51:53 +03:00
|
|
|
"reserved",
|
|
|
|
"reserved",
|
|
|
|
"reserved",
|
|
|
|
"reserved"
|
2018-03-02 15:31:10 +03:00
|
|
|
};
|
|
|
|
|
2023-03-03 16:12:48 +03:00
|
|
|
static void register_cpu_props(Object *obj);
|
2022-06-08 09:14:37 +03:00
|
|
|
|
2020-08-14 06:58:19 +03:00
|
|
|
const char *riscv_cpu_get_trap_name(target_ulong cause, bool async)
|
|
|
|
{
|
|
|
|
if (async) {
|
|
|
|
return (cause < ARRAY_SIZE(riscv_intr_names)) ?
|
|
|
|
riscv_intr_names[cause] : "(unknown)";
|
|
|
|
} else {
|
|
|
|
return (cause < ARRAY_SIZE(riscv_excp_names)) ?
|
|
|
|
riscv_excp_names[cause] : "(unknown)";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-10-20 06:16:57 +03:00
|
|
|
static void set_misa(CPURISCVState *env, RISCVMXL mxl, uint32_t ext)
|
2018-03-02 15:31:10 +03:00
|
|
|
{
|
2021-10-20 06:16:57 +03:00
|
|
|
env->misa_mxl_max = env->misa_mxl = mxl;
|
|
|
|
env->misa_ext_mask = env->misa_ext = ext;
|
2018-03-02 15:31:10 +03:00
|
|
|
}
|
|
|
|
|
2019-06-18 04:31:19 +03:00
|
|
|
static void set_priv_version(CPURISCVState *env, int priv_ver)
|
2018-03-02 15:31:10 +03:00
|
|
|
{
|
|
|
|
env->priv_ver = priv_ver;
|
|
|
|
}
|
|
|
|
|
2020-07-01 18:24:50 +03:00
|
|
|
static void set_vext_version(CPURISCVState *env, int vext_ver)
|
|
|
|
{
|
|
|
|
env->vext_ver = vext_ver;
|
|
|
|
}
|
|
|
|
|
riscv: Allow user to set the satp mode
RISC-V specifies multiple sizes for addressable memory and Linux probes for
the machine's support at startup via the satp CSR register (done in
csr.c:validate_vm).
As per the specification, sv64 must support sv57, which in turn must
support sv48...etc. So we can restrict machine support by simply setting the
"highest" supported mode and the bare mode is always supported.
You can set the satp mode using the new properties "sv32", "sv39", "sv48",
"sv57" and "sv64" as follows:
-cpu rv64,sv57=on # Linux will boot using sv57 scheme
-cpu rv64,sv39=on # Linux will boot using sv39 scheme
-cpu rv64,sv57=off # Linux will boot using sv48 scheme
-cpu rv64 # Linux will boot using sv57 scheme by default
We take the highest level set by the user:
-cpu rv64,sv48=on,sv57=on # Linux will boot using sv57 scheme
We make sure that invalid configurations are rejected:
-cpu rv64,sv39=off,sv48=on # sv39 must be supported if higher modes are
# enabled
We accept "redundant" configurations:
-cpu rv64,sv48=on,sv57=off # Linux will boot using sv48 scheme
And contradictory configurations:
-cpu rv64,sv48=on,sv48=off # Linux will boot using sv39 scheme
Co-Developed-by: Ludovic Henry <ludovic@rivosinc.com>
Signed-off-by: Ludovic Henry <ludovic@rivosinc.com>
Signed-off-by: Alexandre Ghiti <alexghiti@rivosinc.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
Reviewed-by: Bin Meng <bmeng@tinylab.org>
Acked-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Frank Chang <frank.chang@sifive.com>
Message-ID: <20230303131252.892893-4-alexghiti@rivosinc.com>
Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
2023-03-03 16:12:50 +03:00
|
|
|
#ifndef CONFIG_USER_ONLY
|
|
|
|
static uint8_t satp_mode_from_str(const char *satp_mode_str)
|
|
|
|
{
|
|
|
|
if (!strncmp(satp_mode_str, "mbare", 5)) {
|
|
|
|
return VM_1_10_MBARE;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!strncmp(satp_mode_str, "sv32", 4)) {
|
|
|
|
return VM_1_10_SV32;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!strncmp(satp_mode_str, "sv39", 4)) {
|
|
|
|
return VM_1_10_SV39;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!strncmp(satp_mode_str, "sv48", 4)) {
|
|
|
|
return VM_1_10_SV48;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!strncmp(satp_mode_str, "sv57", 4)) {
|
|
|
|
return VM_1_10_SV57;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!strncmp(satp_mode_str, "sv64", 4)) {
|
|
|
|
return VM_1_10_SV64;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_assert_not_reached();
|
|
|
|
}
|
|
|
|
|
|
|
|
uint8_t satp_mode_max_from_map(uint32_t map)
|
|
|
|
{
|
|
|
|
/* map here has at least one bit set, so no problem with clz */
|
|
|
|
return 31 - __builtin_clz(map);
|
|
|
|
}
|
|
|
|
|
|
|
|
const char *satp_mode_str(uint8_t satp_mode, bool is_32_bit)
|
|
|
|
{
|
|
|
|
if (is_32_bit) {
|
|
|
|
switch (satp_mode) {
|
|
|
|
case VM_1_10_SV32:
|
|
|
|
return "sv32";
|
|
|
|
case VM_1_10_MBARE:
|
|
|
|
return "none";
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
switch (satp_mode) {
|
|
|
|
case VM_1_10_SV64:
|
|
|
|
return "sv64";
|
|
|
|
case VM_1_10_SV57:
|
|
|
|
return "sv57";
|
|
|
|
case VM_1_10_SV48:
|
|
|
|
return "sv48";
|
|
|
|
case VM_1_10_SV39:
|
|
|
|
return "sv39";
|
|
|
|
case VM_1_10_MBARE:
|
|
|
|
return "none";
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
g_assert_not_reached();
|
|
|
|
}
|
|
|
|
|
2023-03-03 16:12:51 +03:00
|
|
|
static void set_satp_mode_max_supported(RISCVCPU *cpu,
|
|
|
|
uint8_t satp_mode)
|
riscv: Allow user to set the satp mode
RISC-V specifies multiple sizes for addressable memory and Linux probes for
the machine's support at startup via the satp CSR register (done in
csr.c:validate_vm).
As per the specification, sv64 must support sv57, which in turn must
support sv48...etc. So we can restrict machine support by simply setting the
"highest" supported mode and the bare mode is always supported.
You can set the satp mode using the new properties "sv32", "sv39", "sv48",
"sv57" and "sv64" as follows:
-cpu rv64,sv57=on # Linux will boot using sv57 scheme
-cpu rv64,sv39=on # Linux will boot using sv39 scheme
-cpu rv64,sv57=off # Linux will boot using sv48 scheme
-cpu rv64 # Linux will boot using sv57 scheme by default
We take the highest level set by the user:
-cpu rv64,sv48=on,sv57=on # Linux will boot using sv57 scheme
We make sure that invalid configurations are rejected:
-cpu rv64,sv39=off,sv48=on # sv39 must be supported if higher modes are
# enabled
We accept "redundant" configurations:
-cpu rv64,sv48=on,sv57=off # Linux will boot using sv48 scheme
And contradictory configurations:
-cpu rv64,sv48=on,sv48=off # Linux will boot using sv39 scheme
Co-Developed-by: Ludovic Henry <ludovic@rivosinc.com>
Signed-off-by: Ludovic Henry <ludovic@rivosinc.com>
Signed-off-by: Alexandre Ghiti <alexghiti@rivosinc.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
Reviewed-by: Bin Meng <bmeng@tinylab.org>
Acked-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Frank Chang <frank.chang@sifive.com>
Message-ID: <20230303131252.892893-4-alexghiti@rivosinc.com>
Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
2023-03-03 16:12:50 +03:00
|
|
|
{
|
|
|
|
bool rv32 = riscv_cpu_mxl(&cpu->env) == MXL_RV32;
|
2023-03-03 16:12:51 +03:00
|
|
|
const bool *valid_vm = rv32 ? valid_vm_1_10_32 : valid_vm_1_10_64;
|
riscv: Allow user to set the satp mode
RISC-V specifies multiple sizes for addressable memory and Linux probes for
the machine's support at startup via the satp CSR register (done in
csr.c:validate_vm).
As per the specification, sv64 must support sv57, which in turn must
support sv48...etc. So we can restrict machine support by simply setting the
"highest" supported mode and the bare mode is always supported.
You can set the satp mode using the new properties "sv32", "sv39", "sv48",
"sv57" and "sv64" as follows:
-cpu rv64,sv57=on # Linux will boot using sv57 scheme
-cpu rv64,sv39=on # Linux will boot using sv39 scheme
-cpu rv64,sv57=off # Linux will boot using sv48 scheme
-cpu rv64 # Linux will boot using sv57 scheme by default
We take the highest level set by the user:
-cpu rv64,sv48=on,sv57=on # Linux will boot using sv57 scheme
We make sure that invalid configurations are rejected:
-cpu rv64,sv39=off,sv48=on # sv39 must be supported if higher modes are
# enabled
We accept "redundant" configurations:
-cpu rv64,sv48=on,sv57=off # Linux will boot using sv48 scheme
And contradictory configurations:
-cpu rv64,sv48=on,sv48=off # Linux will boot using sv39 scheme
Co-Developed-by: Ludovic Henry <ludovic@rivosinc.com>
Signed-off-by: Ludovic Henry <ludovic@rivosinc.com>
Signed-off-by: Alexandre Ghiti <alexghiti@rivosinc.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
Reviewed-by: Bin Meng <bmeng@tinylab.org>
Acked-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Frank Chang <frank.chang@sifive.com>
Message-ID: <20230303131252.892893-4-alexghiti@rivosinc.com>
Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
2023-03-03 16:12:50 +03:00
|
|
|
|
2023-03-03 16:12:51 +03:00
|
|
|
for (int i = 0; i <= satp_mode; ++i) {
|
|
|
|
if (valid_vm[i]) {
|
|
|
|
cpu->cfg.satp_mode.supported |= (1 << i);
|
|
|
|
}
|
riscv: Allow user to set the satp mode
RISC-V specifies multiple sizes for addressable memory and Linux probes for
the machine's support at startup via the satp CSR register (done in
csr.c:validate_vm).
As per the specification, sv64 must support sv57, which in turn must
support sv48...etc. So we can restrict machine support by simply setting the
"highest" supported mode and the bare mode is always supported.
You can set the satp mode using the new properties "sv32", "sv39", "sv48",
"sv57" and "sv64" as follows:
-cpu rv64,sv57=on # Linux will boot using sv57 scheme
-cpu rv64,sv39=on # Linux will boot using sv39 scheme
-cpu rv64,sv57=off # Linux will boot using sv48 scheme
-cpu rv64 # Linux will boot using sv57 scheme by default
We take the highest level set by the user:
-cpu rv64,sv48=on,sv57=on # Linux will boot using sv57 scheme
We make sure that invalid configurations are rejected:
-cpu rv64,sv39=off,sv48=on # sv39 must be supported if higher modes are
# enabled
We accept "redundant" configurations:
-cpu rv64,sv48=on,sv57=off # Linux will boot using sv48 scheme
And contradictory configurations:
-cpu rv64,sv48=on,sv48=off # Linux will boot using sv39 scheme
Co-Developed-by: Ludovic Henry <ludovic@rivosinc.com>
Signed-off-by: Ludovic Henry <ludovic@rivosinc.com>
Signed-off-by: Alexandre Ghiti <alexghiti@rivosinc.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
Reviewed-by: Bin Meng <bmeng@tinylab.org>
Acked-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Frank Chang <frank.chang@sifive.com>
Message-ID: <20230303131252.892893-4-alexghiti@rivosinc.com>
Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
2023-03-03 16:12:50 +03:00
|
|
|
}
|
|
|
|
}
|
2023-03-03 16:12:51 +03:00
|
|
|
|
|
|
|
/* Set the satp mode to the max supported */
|
|
|
|
static void set_satp_mode_default_map(RISCVCPU *cpu)
|
|
|
|
{
|
|
|
|
cpu->cfg.satp_mode.map = cpu->cfg.satp_mode.supported;
|
|
|
|
}
|
riscv: Allow user to set the satp mode
RISC-V specifies multiple sizes for addressable memory and Linux probes for
the machine's support at startup via the satp CSR register (done in
csr.c:validate_vm).
As per the specification, sv64 must support sv57, which in turn must
support sv48...etc. So we can restrict machine support by simply setting the
"highest" supported mode and the bare mode is always supported.
You can set the satp mode using the new properties "sv32", "sv39", "sv48",
"sv57" and "sv64" as follows:
-cpu rv64,sv57=on # Linux will boot using sv57 scheme
-cpu rv64,sv39=on # Linux will boot using sv39 scheme
-cpu rv64,sv57=off # Linux will boot using sv48 scheme
-cpu rv64 # Linux will boot using sv57 scheme by default
We take the highest level set by the user:
-cpu rv64,sv48=on,sv57=on # Linux will boot using sv57 scheme
We make sure that invalid configurations are rejected:
-cpu rv64,sv39=off,sv48=on # sv39 must be supported if higher modes are
# enabled
We accept "redundant" configurations:
-cpu rv64,sv48=on,sv57=off # Linux will boot using sv48 scheme
And contradictory configurations:
-cpu rv64,sv48=on,sv48=off # Linux will boot using sv39 scheme
Co-Developed-by: Ludovic Henry <ludovic@rivosinc.com>
Signed-off-by: Ludovic Henry <ludovic@rivosinc.com>
Signed-off-by: Alexandre Ghiti <alexghiti@rivosinc.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
Reviewed-by: Bin Meng <bmeng@tinylab.org>
Acked-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Frank Chang <frank.chang@sifive.com>
Message-ID: <20230303131252.892893-4-alexghiti@rivosinc.com>
Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
2023-03-03 16:12:50 +03:00
|
|
|
#endif
|
|
|
|
|
2018-03-02 15:31:10 +03:00
|
|
|
static void riscv_any_cpu_init(Object *obj)
|
|
|
|
{
|
|
|
|
CPURISCVState *env = &RISCV_CPU(obj)->env;
|
2021-04-24 06:28:33 +03:00
|
|
|
#if defined(TARGET_RISCV32)
|
2021-10-20 06:16:57 +03:00
|
|
|
set_misa(env, MXL_RV32, RVI | RVM | RVA | RVF | RVD | RVC | RVU);
|
2021-04-24 06:28:33 +03:00
|
|
|
#elif defined(TARGET_RISCV64)
|
2021-10-20 06:16:57 +03:00
|
|
|
set_misa(env, MXL_RV64, RVI | RVM | RVA | RVF | RVD | RVC | RVU);
|
2021-04-24 06:28:33 +03:00
|
|
|
#endif
|
2023-03-03 16:12:51 +03:00
|
|
|
|
|
|
|
#ifndef CONFIG_USER_ONLY
|
|
|
|
set_satp_mode_max_supported(RISCV_CPU(obj),
|
|
|
|
riscv_cpu_mxl(&RISCV_CPU(obj)->env) == MXL_RV32 ?
|
|
|
|
VM_1_10_SV32 : VM_1_10_SV57);
|
|
|
|
#endif
|
|
|
|
|
2022-03-03 21:54:40 +03:00
|
|
|
set_priv_version(env, PRIV_VERSION_1_12_0);
|
2023-03-03 16:12:48 +03:00
|
|
|
register_cpu_props(obj);
|
2018-03-02 15:31:10 +03:00
|
|
|
}
|
|
|
|
|
2020-12-16 21:23:05 +03:00
|
|
|
#if defined(TARGET_RISCV64)
|
|
|
|
static void rv64_base_cpu_init(Object *obj)
|
2019-04-20 05:24:09 +03:00
|
|
|
{
|
|
|
|
CPURISCVState *env = &RISCV_CPU(obj)->env;
|
2019-05-07 01:49:53 +03:00
|
|
|
/* We set this in the realise function */
|
2021-10-20 06:16:57 +03:00
|
|
|
set_misa(env, MXL_RV64, 0);
|
2023-03-03 16:12:48 +03:00
|
|
|
register_cpu_props(obj);
|
2022-06-11 11:01:04 +03:00
|
|
|
/* Set latest version of privileged specification */
|
|
|
|
set_priv_version(env, PRIV_VERSION_1_12_0);
|
2023-03-03 16:12:51 +03:00
|
|
|
#ifndef CONFIG_USER_ONLY
|
|
|
|
set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV57);
|
|
|
|
#endif
|
2019-04-20 05:24:09 +03:00
|
|
|
}
|
|
|
|
|
2020-12-16 21:22:54 +03:00
|
|
|
static void rv64_sifive_u_cpu_init(Object *obj)
|
2018-03-02 15:31:10 +03:00
|
|
|
{
|
|
|
|
CPURISCVState *env = &RISCV_CPU(obj)->env;
|
2021-10-20 06:16:57 +03:00
|
|
|
set_misa(env, MXL_RV64, RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU);
|
2023-03-03 16:12:48 +03:00
|
|
|
register_cpu_props(obj);
|
2019-06-18 04:31:19 +03:00
|
|
|
set_priv_version(env, PRIV_VERSION_1_10_0);
|
2023-03-03 16:12:51 +03:00
|
|
|
#ifndef CONFIG_USER_ONLY
|
|
|
|
set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV39);
|
|
|
|
#endif
|
2018-03-02 15:31:10 +03:00
|
|
|
}
|
|
|
|
|
2020-12-16 21:22:54 +03:00
|
|
|
static void rv64_sifive_e_cpu_init(Object *obj)
|
2020-04-23 20:50:09 +03:00
|
|
|
{
|
|
|
|
CPURISCVState *env = &RISCV_CPU(obj)->env;
|
2022-06-08 09:14:37 +03:00
|
|
|
RISCVCPU *cpu = RISCV_CPU(obj);
|
|
|
|
|
2021-10-20 06:16:57 +03:00
|
|
|
set_misa(env, MXL_RV64, RVI | RVM | RVA | RVC | RVU);
|
2023-03-03 16:12:48 +03:00
|
|
|
register_cpu_props(obj);
|
2020-04-23 20:50:09 +03:00
|
|
|
set_priv_version(env, PRIV_VERSION_1_10_0);
|
2022-06-08 09:14:37 +03:00
|
|
|
cpu->cfg.mmu = false;
|
2023-03-03 16:12:51 +03:00
|
|
|
#ifndef CONFIG_USER_ONLY
|
|
|
|
set_satp_mode_max_supported(cpu, VM_1_10_MBARE);
|
|
|
|
#endif
|
2020-04-23 20:50:09 +03:00
|
|
|
}
|
2022-01-07 00:00:57 +03:00
|
|
|
|
2023-01-31 23:20:11 +03:00
|
|
|
static void rv64_thead_c906_cpu_init(Object *obj)
|
|
|
|
{
|
|
|
|
CPURISCVState *env = &RISCV_CPU(obj)->env;
|
|
|
|
RISCVCPU *cpu = RISCV_CPU(obj);
|
|
|
|
|
|
|
|
set_misa(env, MXL_RV64, RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU);
|
|
|
|
set_priv_version(env, PRIV_VERSION_1_11_0);
|
|
|
|
|
|
|
|
cpu->cfg.ext_g = true;
|
|
|
|
cpu->cfg.ext_c = true;
|
|
|
|
cpu->cfg.ext_u = true;
|
|
|
|
cpu->cfg.ext_s = true;
|
|
|
|
cpu->cfg.ext_icsr = true;
|
|
|
|
cpu->cfg.ext_zfh = true;
|
|
|
|
cpu->cfg.mmu = true;
|
|
|
|
cpu->cfg.ext_xtheadba = true;
|
|
|
|
cpu->cfg.ext_xtheadbb = true;
|
|
|
|
cpu->cfg.ext_xtheadbs = true;
|
|
|
|
cpu->cfg.ext_xtheadcmo = true;
|
|
|
|
cpu->cfg.ext_xtheadcondmov = true;
|
|
|
|
cpu->cfg.ext_xtheadfmemidx = true;
|
|
|
|
cpu->cfg.ext_xtheadmac = true;
|
|
|
|
cpu->cfg.ext_xtheadmemidx = true;
|
|
|
|
cpu->cfg.ext_xtheadmempair = true;
|
|
|
|
cpu->cfg.ext_xtheadsync = true;
|
|
|
|
|
|
|
|
cpu->cfg.mvendorid = THEAD_VENDOR_ID;
|
2023-03-03 16:12:51 +03:00
|
|
|
#ifndef CONFIG_USER_ONLY
|
|
|
|
set_satp_mode_max_supported(cpu, VM_1_10_SV39);
|
|
|
|
#endif
|
2023-01-31 23:20:11 +03:00
|
|
|
}
|
|
|
|
|
2022-01-07 00:00:57 +03:00
|
|
|
static void rv128_base_cpu_init(Object *obj)
|
|
|
|
{
|
|
|
|
if (qemu_tcg_mttcg_enabled()) {
|
|
|
|
/* Missing 128-bit aligned atomics */
|
|
|
|
error_report("128-bit RISC-V currently does not work with Multi "
|
|
|
|
"Threaded TCG. Please use: -accel tcg,thread=single");
|
|
|
|
exit(EXIT_FAILURE);
|
|
|
|
}
|
|
|
|
CPURISCVState *env = &RISCV_CPU(obj)->env;
|
|
|
|
/* We set this in the realise function */
|
|
|
|
set_misa(env, MXL_RV128, 0);
|
2023-03-03 16:12:48 +03:00
|
|
|
register_cpu_props(obj);
|
2022-06-11 11:01:04 +03:00
|
|
|
/* Set latest version of privileged specification */
|
|
|
|
set_priv_version(env, PRIV_VERSION_1_12_0);
|
2023-03-03 16:12:51 +03:00
|
|
|
#ifndef CONFIG_USER_ONLY
|
|
|
|
set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV57);
|
|
|
|
#endif
|
2022-01-07 00:00:57 +03:00
|
|
|
}
|
2020-12-16 21:22:54 +03:00
|
|
|
#else
|
2020-12-16 21:23:05 +03:00
|
|
|
static void rv32_base_cpu_init(Object *obj)
|
|
|
|
{
|
|
|
|
CPURISCVState *env = &RISCV_CPU(obj)->env;
|
|
|
|
/* We set this in the realise function */
|
2021-10-20 06:16:57 +03:00
|
|
|
set_misa(env, MXL_RV32, 0);
|
2023-03-03 16:12:48 +03:00
|
|
|
register_cpu_props(obj);
|
2022-06-11 11:01:04 +03:00
|
|
|
/* Set latest version of privileged specification */
|
|
|
|
set_priv_version(env, PRIV_VERSION_1_12_0);
|
2023-03-03 16:12:51 +03:00
|
|
|
#ifndef CONFIG_USER_ONLY
|
|
|
|
set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV32);
|
|
|
|
#endif
|
2020-12-16 21:23:05 +03:00
|
|
|
}
|
|
|
|
|
2020-12-16 21:22:54 +03:00
|
|
|
static void rv32_sifive_u_cpu_init(Object *obj)
|
|
|
|
{
|
|
|
|
CPURISCVState *env = &RISCV_CPU(obj)->env;
|
2021-10-20 06:16:57 +03:00
|
|
|
set_misa(env, MXL_RV32, RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU);
|
2023-03-03 16:12:48 +03:00
|
|
|
register_cpu_props(obj);
|
2020-12-16 21:22:54 +03:00
|
|
|
set_priv_version(env, PRIV_VERSION_1_10_0);
|
2023-03-03 16:12:51 +03:00
|
|
|
#ifndef CONFIG_USER_ONLY
|
|
|
|
set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV32);
|
|
|
|
#endif
|
2020-12-16 21:22:54 +03:00
|
|
|
}
|
2020-04-23 20:50:09 +03:00
|
|
|
|
2020-12-16 21:22:54 +03:00
|
|
|
static void rv32_sifive_e_cpu_init(Object *obj)
|
|
|
|
{
|
|
|
|
CPURISCVState *env = &RISCV_CPU(obj)->env;
|
2022-06-08 09:14:37 +03:00
|
|
|
RISCVCPU *cpu = RISCV_CPU(obj);
|
|
|
|
|
2021-10-20 06:16:57 +03:00
|
|
|
set_misa(env, MXL_RV32, RVI | RVM | RVA | RVC | RVU);
|
2023-03-03 16:12:48 +03:00
|
|
|
register_cpu_props(obj);
|
2020-12-16 21:22:54 +03:00
|
|
|
set_priv_version(env, PRIV_VERSION_1_10_0);
|
2022-06-08 09:14:37 +03:00
|
|
|
cpu->cfg.mmu = false;
|
2023-03-03 16:12:51 +03:00
|
|
|
#ifndef CONFIG_USER_ONLY
|
|
|
|
set_satp_mode_max_supported(cpu, VM_1_10_MBARE);
|
|
|
|
#endif
|
2020-12-16 21:22:54 +03:00
|
|
|
}
|
2020-06-11 04:08:48 +03:00
|
|
|
|
2020-06-16 03:50:37 +03:00
|
|
|
static void rv32_ibex_cpu_init(Object *obj)
|
2018-03-02 15:31:10 +03:00
|
|
|
{
|
|
|
|
CPURISCVState *env = &RISCV_CPU(obj)->env;
|
2022-06-08 09:14:37 +03:00
|
|
|
RISCVCPU *cpu = RISCV_CPU(obj);
|
|
|
|
|
2021-10-20 06:16:57 +03:00
|
|
|
set_misa(env, MXL_RV32, RVI | RVM | RVC | RVU);
|
2023-03-03 16:12:48 +03:00
|
|
|
register_cpu_props(obj);
|
2022-06-30 02:31:02 +03:00
|
|
|
set_priv_version(env, PRIV_VERSION_1_11_0);
|
2022-06-08 09:14:37 +03:00
|
|
|
cpu->cfg.mmu = false;
|
2023-03-03 16:12:51 +03:00
|
|
|
#ifndef CONFIG_USER_ONLY
|
|
|
|
set_satp_mode_max_supported(cpu, VM_1_10_MBARE);
|
|
|
|
#endif
|
2022-06-08 09:14:37 +03:00
|
|
|
cpu->cfg.epmp = true;
|
2018-03-02 15:31:10 +03:00
|
|
|
}
|
|
|
|
|
2020-06-11 04:08:49 +03:00
|
|
|
static void rv32_imafcu_nommu_cpu_init(Object *obj)
|
2020-03-13 22:34:29 +03:00
|
|
|
{
|
|
|
|
CPURISCVState *env = &RISCV_CPU(obj)->env;
|
2022-06-08 09:14:37 +03:00
|
|
|
RISCVCPU *cpu = RISCV_CPU(obj);
|
|
|
|
|
2021-10-20 06:16:57 +03:00
|
|
|
set_misa(env, MXL_RV32, RVI | RVM | RVA | RVF | RVC | RVU);
|
2023-03-03 16:12:48 +03:00
|
|
|
register_cpu_props(obj);
|
2020-03-13 22:34:29 +03:00
|
|
|
set_priv_version(env, PRIV_VERSION_1_10_0);
|
2022-06-08 09:14:37 +03:00
|
|
|
cpu->cfg.mmu = false;
|
2023-03-03 16:12:51 +03:00
|
|
|
#ifndef CONFIG_USER_ONLY
|
|
|
|
set_satp_mode_max_supported(cpu, VM_1_10_MBARE);
|
|
|
|
#endif
|
2020-03-13 22:34:29 +03:00
|
|
|
}
|
2018-03-09 01:12:31 +03:00
|
|
|
#endif
|
2018-03-02 15:31:10 +03:00
|
|
|
|
2022-01-12 11:13:25 +03:00
|
|
|
#if defined(CONFIG_KVM)
|
|
|
|
static void riscv_host_cpu_init(Object *obj)
|
|
|
|
{
|
|
|
|
CPURISCVState *env = &RISCV_CPU(obj)->env;
|
|
|
|
#if defined(TARGET_RISCV32)
|
|
|
|
set_misa(env, MXL_RV32, 0);
|
|
|
|
#elif defined(TARGET_RISCV64)
|
|
|
|
set_misa(env, MXL_RV64, 0);
|
|
|
|
#endif
|
2023-03-03 16:12:48 +03:00
|
|
|
register_cpu_props(obj);
|
2022-01-12 11:13:25 +03:00
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
2018-03-02 15:31:10 +03:00
|
|
|
static ObjectClass *riscv_cpu_class_by_name(const char *cpu_model)
|
|
|
|
{
|
|
|
|
ObjectClass *oc;
|
|
|
|
char *typename;
|
|
|
|
char **cpuname;
|
|
|
|
|
|
|
|
cpuname = g_strsplit(cpu_model, ",", 1);
|
|
|
|
typename = g_strdup_printf(RISCV_CPU_TYPE_NAME("%s"), cpuname[0]);
|
|
|
|
oc = object_class_by_name(typename);
|
|
|
|
g_strfreev(cpuname);
|
|
|
|
g_free(typename);
|
|
|
|
if (!oc || !object_class_dynamic_cast(oc, TYPE_RISCV_CPU) ||
|
|
|
|
object_class_is_abstract(oc)) {
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
return oc;
|
|
|
|
}
|
|
|
|
|
2019-04-17 22:18:02 +03:00
|
|
|
static void riscv_cpu_dump_state(CPUState *cs, FILE *f, int flags)
|
2018-03-02 15:31:10 +03:00
|
|
|
{
|
|
|
|
RISCVCPU *cpu = RISCV_CPU(cs);
|
|
|
|
CPURISCVState *env = &cpu->env;
|
|
|
|
int i;
|
|
|
|
|
2020-02-01 04:02:02 +03:00
|
|
|
#if !defined(CONFIG_USER_ONLY)
|
|
|
|
if (riscv_has_ext(env, RVH)) {
|
|
|
|
qemu_fprintf(f, " %s %d\n", "V = ", riscv_cpu_virt_enabled(env));
|
|
|
|
}
|
|
|
|
#endif
|
2019-04-17 22:18:02 +03:00
|
|
|
qemu_fprintf(f, " %s " TARGET_FMT_lx "\n", "pc ", env->pc);
|
2018-03-02 15:31:10 +03:00
|
|
|
#ifndef CONFIG_USER_ONLY
|
2021-10-20 06:17:08 +03:00
|
|
|
{
|
|
|
|
static const int dump_csrs[] = {
|
|
|
|
CSR_MHARTID,
|
|
|
|
CSR_MSTATUS,
|
|
|
|
CSR_MSTATUSH,
|
2022-11-25 08:03:54 +03:00
|
|
|
/*
|
|
|
|
* CSR_SSTATUS is intentionally omitted here as its value
|
|
|
|
* can be figured out by looking at CSR_MSTATUS
|
|
|
|
*/
|
2021-10-20 06:17:08 +03:00
|
|
|
CSR_HSTATUS,
|
|
|
|
CSR_VSSTATUS,
|
|
|
|
CSR_MIP,
|
|
|
|
CSR_MIE,
|
|
|
|
CSR_MIDELEG,
|
|
|
|
CSR_HIDELEG,
|
|
|
|
CSR_MEDELEG,
|
|
|
|
CSR_HEDELEG,
|
|
|
|
CSR_MTVEC,
|
|
|
|
CSR_STVEC,
|
|
|
|
CSR_VSTVEC,
|
|
|
|
CSR_MEPC,
|
|
|
|
CSR_SEPC,
|
|
|
|
CSR_VSEPC,
|
|
|
|
CSR_MCAUSE,
|
|
|
|
CSR_SCAUSE,
|
|
|
|
CSR_VSCAUSE,
|
|
|
|
CSR_MTVAL,
|
|
|
|
CSR_STVAL,
|
|
|
|
CSR_HTVAL,
|
|
|
|
CSR_MTVAL2,
|
|
|
|
CSR_MSCRATCH,
|
|
|
|
CSR_SSCRATCH,
|
|
|
|
CSR_SATP,
|
2021-10-25 20:36:06 +03:00
|
|
|
CSR_MMTE,
|
|
|
|
CSR_UPMBASE,
|
|
|
|
CSR_UPMMASK,
|
|
|
|
CSR_SPMBASE,
|
|
|
|
CSR_SPMMASK,
|
|
|
|
CSR_MPMBASE,
|
|
|
|
CSR_MPMMASK,
|
2021-10-20 06:17:08 +03:00
|
|
|
};
|
|
|
|
|
|
|
|
for (int i = 0; i < ARRAY_SIZE(dump_csrs); ++i) {
|
|
|
|
int csrno = dump_csrs[i];
|
|
|
|
target_ulong val = 0;
|
|
|
|
RISCVException res = riscv_csrrw_debug(env, csrno, &val, 0, 0);
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Rely on the smode, hmode, etc, predicates within csr.c
|
|
|
|
* to do the filtering of the registers that are present.
|
|
|
|
*/
|
|
|
|
if (res == RISCV_EXCP_NONE) {
|
|
|
|
qemu_fprintf(f, " %-8s " TARGET_FMT_lx "\n",
|
|
|
|
csr_ops[csrno].name, val);
|
|
|
|
}
|
|
|
|
}
|
2020-02-01 04:02:02 +03:00
|
|
|
}
|
2018-03-02 15:31:10 +03:00
|
|
|
#endif
|
|
|
|
|
|
|
|
for (i = 0; i < 32; i++) {
|
2021-10-09 08:50:19 +03:00
|
|
|
qemu_fprintf(f, " %-8s " TARGET_FMT_lx,
|
2019-04-17 22:18:02 +03:00
|
|
|
riscv_int_regnames[i], env->gpr[i]);
|
2018-03-02 15:31:10 +03:00
|
|
|
if ((i & 3) == 3) {
|
2019-04-17 22:18:02 +03:00
|
|
|
qemu_fprintf(f, "\n");
|
2018-03-02 15:31:10 +03:00
|
|
|
}
|
|
|
|
}
|
2018-05-11 06:31:33 +03:00
|
|
|
if (flags & CPU_DUMP_FPU) {
|
|
|
|
for (i = 0; i < 32; i++) {
|
2021-10-09 08:50:19 +03:00
|
|
|
qemu_fprintf(f, " %-8s %016" PRIx64,
|
2019-04-17 22:18:02 +03:00
|
|
|
riscv_fpr_regnames[i], env->fpr[i]);
|
2018-05-11 06:31:33 +03:00
|
|
|
if ((i & 3) == 3) {
|
2019-04-17 22:18:02 +03:00
|
|
|
qemu_fprintf(f, "\n");
|
2018-05-11 06:31:33 +03:00
|
|
|
}
|
2018-03-02 15:31:10 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
static void riscv_cpu_set_pc(CPUState *cs, vaddr value)
|
|
|
|
{
|
|
|
|
RISCVCPU *cpu = RISCV_CPU(cs);
|
|
|
|
CPURISCVState *env = &cpu->env;
|
2022-01-20 15:20:34 +03:00
|
|
|
|
|
|
|
if (env->xl == MXL_RV32) {
|
|
|
|
env->pc = (int32_t)value;
|
|
|
|
} else {
|
|
|
|
env->pc = value;
|
|
|
|
}
|
2018-03-02 15:31:10 +03:00
|
|
|
}
|
|
|
|
|
2022-09-30 20:31:21 +03:00
|
|
|
static vaddr riscv_cpu_get_pc(CPUState *cs)
|
|
|
|
{
|
|
|
|
RISCVCPU *cpu = RISCV_CPU(cs);
|
|
|
|
CPURISCVState *env = &cpu->env;
|
|
|
|
|
|
|
|
/* Match cpu_get_tb_cpu_state. */
|
|
|
|
if (env->xl == MXL_RV32) {
|
|
|
|
return env->pc & UINT32_MAX;
|
|
|
|
}
|
|
|
|
return env->pc;
|
|
|
|
}
|
|
|
|
|
2020-10-29 22:30:01 +03:00
|
|
|
static void riscv_cpu_synchronize_from_tb(CPUState *cs,
|
|
|
|
const TranslationBlock *tb)
|
2018-03-02 15:31:10 +03:00
|
|
|
{
|
|
|
|
RISCVCPU *cpu = RISCV_CPU(cs);
|
|
|
|
CPURISCVState *env = &cpu->env;
|
2022-01-20 15:20:34 +03:00
|
|
|
RISCVMXL xl = FIELD_EX32(tb->flags, TB_FLAGS, XL);
|
|
|
|
|
2023-02-27 16:51:52 +03:00
|
|
|
tcg_debug_assert(!(cs->tcg_cflags & CF_PCREL));
|
|
|
|
|
2022-01-20 15:20:34 +03:00
|
|
|
if (xl == MXL_RV32) {
|
2023-02-27 16:51:52 +03:00
|
|
|
env->pc = (int32_t) tb->pc;
|
2022-01-20 15:20:34 +03:00
|
|
|
} else {
|
2023-02-27 16:51:52 +03:00
|
|
|
env->pc = tb->pc;
|
2022-01-20 15:20:34 +03:00
|
|
|
}
|
2018-03-02 15:31:10 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static bool riscv_cpu_has_work(CPUState *cs)
|
|
|
|
{
|
|
|
|
#ifndef CONFIG_USER_ONLY
|
|
|
|
RISCVCPU *cpu = RISCV_CPU(cs);
|
|
|
|
CPURISCVState *env = &cpu->env;
|
|
|
|
/*
|
|
|
|
* Definition of the WFI instruction requires it to ignore the privilege
|
|
|
|
* mode and delegation registers, but respect individual enables
|
|
|
|
*/
|
2022-06-01 00:05:44 +03:00
|
|
|
return riscv_cpu_all_pending(env) != 0;
|
2018-03-02 15:31:10 +03:00
|
|
|
#else
|
|
|
|
return true;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2022-10-24 13:49:27 +03:00
|
|
|
static void riscv_restore_state_to_opc(CPUState *cs,
|
|
|
|
const TranslationBlock *tb,
|
|
|
|
const uint64_t *data)
|
2018-03-02 15:31:10 +03:00
|
|
|
{
|
2022-10-24 13:49:27 +03:00
|
|
|
RISCVCPU *cpu = RISCV_CPU(cs);
|
|
|
|
CPURISCVState *env = &cpu->env;
|
2022-01-20 15:20:34 +03:00
|
|
|
RISCVMXL xl = FIELD_EX32(tb->flags, TB_FLAGS, XL);
|
2022-10-24 13:49:27 +03:00
|
|
|
|
2022-01-20 15:20:34 +03:00
|
|
|
if (xl == MXL_RV32) {
|
|
|
|
env->pc = (int32_t)data[0];
|
|
|
|
} else {
|
|
|
|
env->pc = data[0];
|
|
|
|
}
|
2022-05-11 17:45:23 +03:00
|
|
|
env->bins = data[1];
|
2018-03-02 15:31:10 +03:00
|
|
|
}
|
|
|
|
|
2022-11-24 14:50:17 +03:00
|
|
|
static void riscv_cpu_reset_hold(Object *obj)
|
2018-03-02 15:31:10 +03:00
|
|
|
{
|
2022-02-04 20:46:45 +03:00
|
|
|
#ifndef CONFIG_USER_ONLY
|
|
|
|
uint8_t iprio;
|
|
|
|
int i, irq, rdzero;
|
|
|
|
#endif
|
2022-11-24 14:50:17 +03:00
|
|
|
CPUState *cs = CPU(obj);
|
2018-03-02 15:31:10 +03:00
|
|
|
RISCVCPU *cpu = RISCV_CPU(cs);
|
|
|
|
RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(cpu);
|
|
|
|
CPURISCVState *env = &cpu->env;
|
|
|
|
|
2022-11-24 14:50:17 +03:00
|
|
|
if (mcc->parent_phases.hold) {
|
|
|
|
mcc->parent_phases.hold(obj);
|
|
|
|
}
|
2018-03-02 15:31:10 +03:00
|
|
|
#ifndef CONFIG_USER_ONLY
|
2021-10-20 06:16:57 +03:00
|
|
|
env->misa_mxl = env->misa_mxl_max;
|
2018-03-02 15:31:10 +03:00
|
|
|
env->priv = PRV_M;
|
|
|
|
env->mstatus &= ~(MSTATUS_MIE | MSTATUS_MPRV);
|
2021-10-20 06:16:59 +03:00
|
|
|
if (env->misa_mxl > MXL_RV32) {
|
|
|
|
/*
|
|
|
|
* The reset status of SXL/UXL is undefined, but mstatus is WARL
|
|
|
|
* and we must ensure that the value after init is valid for read.
|
|
|
|
*/
|
|
|
|
env->mstatus = set_field(env->mstatus, MSTATUS64_SXL, env->misa_mxl);
|
|
|
|
env->mstatus = set_field(env->mstatus, MSTATUS64_UXL, env->misa_mxl);
|
2022-01-20 15:20:48 +03:00
|
|
|
if (riscv_has_ext(env, RVH)) {
|
|
|
|
env->vsstatus = set_field(env->vsstatus,
|
|
|
|
MSTATUS64_SXL, env->misa_mxl);
|
|
|
|
env->vsstatus = set_field(env->vsstatus,
|
|
|
|
MSTATUS64_UXL, env->misa_mxl);
|
|
|
|
env->mstatus_hs = set_field(env->mstatus_hs,
|
|
|
|
MSTATUS64_SXL, env->misa_mxl);
|
|
|
|
env->mstatus_hs = set_field(env->mstatus_hs,
|
|
|
|
MSTATUS64_UXL, env->misa_mxl);
|
|
|
|
}
|
2021-10-20 06:16:59 +03:00
|
|
|
}
|
2018-03-02 15:31:10 +03:00
|
|
|
env->mcause = 0;
|
2022-02-04 20:46:38 +03:00
|
|
|
env->miclaim = MIP_SGEIP;
|
2018-03-02 15:31:10 +03:00
|
|
|
env->pc = env->resetvec;
|
2022-05-11 17:45:23 +03:00
|
|
|
env->bins = 0;
|
2021-03-19 17:14:59 +03:00
|
|
|
env->two_stage_lookup = false;
|
2022-02-04 20:46:45 +03:00
|
|
|
|
2023-02-24 07:08:51 +03:00
|
|
|
env->menvcfg = (cpu->cfg.ext_svpbmt ? MENVCFG_PBMTE : 0) |
|
|
|
|
(cpu->cfg.ext_svadu ? MENVCFG_HADE : 0);
|
|
|
|
env->henvcfg = (cpu->cfg.ext_svpbmt ? HENVCFG_PBMTE : 0) |
|
|
|
|
(cpu->cfg.ext_svadu ? HENVCFG_HADE : 0);
|
2023-02-24 07:08:50 +03:00
|
|
|
|
2022-02-04 20:46:45 +03:00
|
|
|
/* Initialized default priorities of local interrupts. */
|
|
|
|
for (i = 0; i < ARRAY_SIZE(env->miprio); i++) {
|
|
|
|
iprio = riscv_cpu_default_priority(i);
|
|
|
|
env->miprio[i] = (i == IRQ_M_EXT) ? 0 : iprio;
|
|
|
|
env->siprio[i] = (i == IRQ_S_EXT) ? 0 : iprio;
|
|
|
|
env->hviprio[i] = 0;
|
|
|
|
}
|
|
|
|
i = 0;
|
|
|
|
while (!riscv_cpu_hviprio_index2irq(i, &irq, &rdzero)) {
|
|
|
|
if (!rdzero) {
|
|
|
|
env->hviprio[irq] = env->miprio[irq];
|
|
|
|
}
|
|
|
|
i++;
|
|
|
|
}
|
2021-10-25 20:36:04 +03:00
|
|
|
/* mmte is supposed to have pm.current hardwired to 1 */
|
|
|
|
env->mmte |= (PM_EXT_INITIAL | MMTE_M_PM_CURRENT);
|
2018-03-02 15:31:10 +03:00
|
|
|
#endif
|
2022-01-20 15:20:32 +03:00
|
|
|
env->xl = riscv_cpu_mxl(env);
|
2022-01-20 15:20:38 +03:00
|
|
|
riscv_cpu_update_mask(env);
|
2021-04-01 18:17:29 +03:00
|
|
|
cs->exception_index = RISCV_EXCP_NONE;
|
2019-06-24 21:08:38 +03:00
|
|
|
env->load_res = -1;
|
2018-03-02 15:31:10 +03:00
|
|
|
set_default_nan_mode(1, &env->fp_status);
|
2022-01-12 11:13:22 +03:00
|
|
|
|
|
|
|
#ifndef CONFIG_USER_ONLY
|
2023-02-22 21:51:59 +03:00
|
|
|
if (cpu->cfg.debug) {
|
2022-04-21 03:33:21 +03:00
|
|
|
riscv_trigger_init(env);
|
|
|
|
}
|
|
|
|
|
2022-01-12 11:13:22 +03:00
|
|
|
if (kvm_enabled()) {
|
|
|
|
kvm_riscv_reset_vcpu(cpu);
|
|
|
|
}
|
|
|
|
#endif
|
2018-03-02 15:31:10 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static void riscv_cpu_disas_set_info(CPUState *s, disassemble_info *info)
|
|
|
|
{
|
2020-12-16 21:22:56 +03:00
|
|
|
RISCVCPU *cpu = RISCV_CPU(s);
|
2021-10-20 06:16:58 +03:00
|
|
|
|
|
|
|
switch (riscv_cpu_mxl(&cpu->env)) {
|
|
|
|
case MXL_RV32:
|
2020-12-16 21:22:56 +03:00
|
|
|
info->print_insn = print_insn_riscv32;
|
2021-10-20 06:16:58 +03:00
|
|
|
break;
|
|
|
|
case MXL_RV64:
|
2020-12-16 21:22:56 +03:00
|
|
|
info->print_insn = print_insn_riscv64;
|
2021-10-20 06:16:58 +03:00
|
|
|
break;
|
2022-01-07 00:00:57 +03:00
|
|
|
case MXL_RV128:
|
|
|
|
info->print_insn = print_insn_riscv128;
|
|
|
|
break;
|
2021-10-20 06:16:58 +03:00
|
|
|
default:
|
|
|
|
g_assert_not_reached();
|
2020-12-16 21:22:56 +03:00
|
|
|
}
|
2018-03-02 15:31:10 +03:00
|
|
|
}
|
|
|
|
|
2023-01-13 20:52:30 +03:00
|
|
|
/*
|
|
|
|
* Check consistency between chosen extensions while setting
|
|
|
|
* cpu->cfg accordingly, doing a set_misa() in the end.
|
|
|
|
*/
|
|
|
|
static void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp)
|
|
|
|
{
|
|
|
|
CPURISCVState *env = &cpu->env;
|
|
|
|
uint32_t ext = 0;
|
|
|
|
|
|
|
|
/* Do some ISA extension error checking */
|
|
|
|
if (cpu->cfg.ext_g && !(cpu->cfg.ext_i && cpu->cfg.ext_m &&
|
|
|
|
cpu->cfg.ext_a && cpu->cfg.ext_f &&
|
|
|
|
cpu->cfg.ext_d &&
|
|
|
|
cpu->cfg.ext_icsr && cpu->cfg.ext_ifencei)) {
|
|
|
|
warn_report("Setting G will also set IMAFD_Zicsr_Zifencei");
|
|
|
|
cpu->cfg.ext_i = true;
|
|
|
|
cpu->cfg.ext_m = true;
|
|
|
|
cpu->cfg.ext_a = true;
|
|
|
|
cpu->cfg.ext_f = true;
|
|
|
|
cpu->cfg.ext_d = true;
|
|
|
|
cpu->cfg.ext_icsr = true;
|
|
|
|
cpu->cfg.ext_ifencei = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cpu->cfg.ext_i && cpu->cfg.ext_e) {
|
|
|
|
error_setg(errp,
|
|
|
|
"I and E extensions are incompatible");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (!cpu->cfg.ext_i && !cpu->cfg.ext_e) {
|
|
|
|
error_setg(errp,
|
|
|
|
"Either I or E extension must be set");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cpu->cfg.ext_s && !cpu->cfg.ext_u) {
|
|
|
|
error_setg(errp,
|
|
|
|
"Setting S extension without U extension is illegal");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cpu->cfg.ext_h && !cpu->cfg.ext_i) {
|
|
|
|
error_setg(errp,
|
|
|
|
"H depends on an I base integer ISA with 32 x registers");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cpu->cfg.ext_h && !cpu->cfg.ext_s) {
|
|
|
|
error_setg(errp, "H extension implicitly requires S-mode");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cpu->cfg.ext_f && !cpu->cfg.ext_icsr) {
|
|
|
|
error_setg(errp, "F extension requires Zicsr");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if ((cpu->cfg.ext_zawrs) && !cpu->cfg.ext_a) {
|
|
|
|
error_setg(errp, "Zawrs extension requires A extension");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-02-15 05:05:26 +03:00
|
|
|
if (cpu->cfg.ext_zfh) {
|
|
|
|
cpu->cfg.ext_zfhmin = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cpu->cfg.ext_zfhmin && !cpu->cfg.ext_f) {
|
2023-01-13 20:52:30 +03:00
|
|
|
error_setg(errp, "Zfh/Zfhmin extensions require F extension");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cpu->cfg.ext_d && !cpu->cfg.ext_f) {
|
|
|
|
error_setg(errp, "D extension requires F extension");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-02-15 05:05:30 +03:00
|
|
|
/* The V vector extension depends on the Zve64d extension */
|
|
|
|
if (cpu->cfg.ext_v) {
|
|
|
|
cpu->cfg.ext_zve64d = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* The Zve64d extension depends on the Zve64f extension */
|
|
|
|
if (cpu->cfg.ext_zve64d) {
|
|
|
|
cpu->cfg.ext_zve64f = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* The Zve64f extension depends on the Zve32f extension */
|
|
|
|
if (cpu->cfg.ext_zve64f) {
|
|
|
|
cpu->cfg.ext_zve32f = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cpu->cfg.ext_zve64d && !cpu->cfg.ext_d) {
|
|
|
|
error_setg(errp, "Zve64d/V extensions require D extension");
|
2023-01-13 20:52:30 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-02-15 05:05:30 +03:00
|
|
|
if (cpu->cfg.ext_zve32f && !cpu->cfg.ext_f) {
|
2023-01-13 20:52:30 +03:00
|
|
|
error_setg(errp, "Zve32f/Zve64f extensions require F extension");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-02-15 05:05:31 +03:00
|
|
|
if (cpu->cfg.ext_zvfh) {
|
|
|
|
cpu->cfg.ext_zvfhmin = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cpu->cfg.ext_zvfhmin && !cpu->cfg.ext_zve32f) {
|
|
|
|
error_setg(errp, "Zvfh/Zvfhmin extensions require Zve32f extension");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cpu->cfg.ext_zvfh && !cpu->cfg.ext_zfhmin) {
|
|
|
|
error_setg(errp, "Zvfh extensions requires Zfhmin extension");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2023-01-13 20:52:30 +03:00
|
|
|
/* Set the ISA extensions, checks should have happened above */
|
2023-02-15 05:05:27 +03:00
|
|
|
if (cpu->cfg.ext_zhinx) {
|
|
|
|
cpu->cfg.ext_zhinxmin = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cpu->cfg.ext_zdinx || cpu->cfg.ext_zhinxmin) {
|
2023-01-13 20:52:30 +03:00
|
|
|
cpu->cfg.ext_zfinx = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cpu->cfg.ext_zfinx) {
|
|
|
|
if (!cpu->cfg.ext_icsr) {
|
|
|
|
error_setg(errp, "Zfinx extension requires Zicsr");
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (cpu->cfg.ext_f) {
|
|
|
|
error_setg(errp,
|
2023-02-15 05:05:32 +03:00
|
|
|
"Zfinx cannot be supported together with F extension");
|
2023-01-13 20:52:30 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cpu->cfg.ext_zk) {
|
|
|
|
cpu->cfg.ext_zkn = true;
|
|
|
|
cpu->cfg.ext_zkr = true;
|
|
|
|
cpu->cfg.ext_zkt = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cpu->cfg.ext_zkn) {
|
|
|
|
cpu->cfg.ext_zbkb = true;
|
|
|
|
cpu->cfg.ext_zbkc = true;
|
|
|
|
cpu->cfg.ext_zbkx = true;
|
|
|
|
cpu->cfg.ext_zkne = true;
|
|
|
|
cpu->cfg.ext_zknd = true;
|
|
|
|
cpu->cfg.ext_zknh = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cpu->cfg.ext_zks) {
|
|
|
|
cpu->cfg.ext_zbkb = true;
|
|
|
|
cpu->cfg.ext_zbkc = true;
|
|
|
|
cpu->cfg.ext_zbkx = true;
|
|
|
|
cpu->cfg.ext_zksed = true;
|
|
|
|
cpu->cfg.ext_zksh = true;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (cpu->cfg.ext_i) {
|
|
|
|
ext |= RVI;
|
|
|
|
}
|
|
|
|
if (cpu->cfg.ext_e) {
|
|
|
|
ext |= RVE;
|
|
|
|
}
|
|
|
|
if (cpu->cfg.ext_m) {
|
|
|
|
ext |= RVM;
|
|
|
|
}
|
|
|
|
if (cpu->cfg.ext_a) {
|
|
|
|
ext |= RVA;
|
|
|
|
}
|
|
|
|
if (cpu->cfg.ext_f) {
|
|
|
|
ext |= RVF;
|
|
|
|
}
|
|
|
|
if (cpu->cfg.ext_d) {
|
|
|
|
ext |= RVD;
|
|
|
|
}
|
|
|
|
if (cpu->cfg.ext_c) {
|
|
|
|
ext |= RVC;
|
|
|
|
}
|
|
|
|
if (cpu->cfg.ext_s) {
|
|
|
|
ext |= RVS;
|
|
|
|
}
|
|
|
|
if (cpu->cfg.ext_u) {
|
|
|
|
ext |= RVU;
|
|
|
|
}
|
|
|
|
if (cpu->cfg.ext_h) {
|
|
|
|
ext |= RVH;
|
|
|
|
}
|
|
|
|
if (cpu->cfg.ext_v) {
|
|
|
|
int vext_version = VEXT_VERSION_1_00_0;
|
|
|
|
ext |= RVV;
|
|
|
|
if (!is_power_of_2(cpu->cfg.vlen)) {
|
|
|
|
error_setg(errp,
|
2023-02-15 05:05:32 +03:00
|
|
|
"Vector extension VLEN must be power of 2");
|
2023-01-13 20:52:30 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (cpu->cfg.vlen > RV_VLEN_MAX || cpu->cfg.vlen < 128) {
|
|
|
|
error_setg(errp,
|
2023-02-15 05:05:32 +03:00
|
|
|
"Vector extension implementation only supports VLEN "
|
|
|
|
"in the range [128, %d]", RV_VLEN_MAX);
|
2023-01-13 20:52:30 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
if (!is_power_of_2(cpu->cfg.elen)) {
|
|
|
|
error_setg(errp,
|
2023-02-15 05:05:32 +03:00
|
|
|
"Vector extension ELEN must be power of 2");
|
2023-01-13 20:52:30 +03:00
|
|
|
return;
|
|
|
|
}
|
2023-02-15 05:05:32 +03:00
|
|
|
if (cpu->cfg.elen > 64 || cpu->cfg.elen < 8) {
|
2023-01-13 20:52:30 +03:00
|
|
|
error_setg(errp,
|
2023-02-15 05:05:32 +03:00
|
|
|
"Vector extension implementation only supports ELEN "
|
|
|
|
"in the range [8, 64]");
|
2023-01-13 20:52:30 +03:00
|
|
|
return;
|
|
|
|
}
|
2023-02-15 05:05:32 +03:00
|
|
|
if (cpu->cfg.vext_spec) {
|
|
|
|
if (!g_strcmp0(cpu->cfg.vext_spec, "v1.0")) {
|
|
|
|
vext_version = VEXT_VERSION_1_00_0;
|
|
|
|
} else {
|
|
|
|
error_setg(errp,
|
|
|
|
"Unsupported vector spec version '%s'",
|
|
|
|
cpu->cfg.vext_spec);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
} else {
|
|
|
|
qemu_log("vector version is not specified, "
|
|
|
|
"use the default value v1.0\n");
|
|
|
|
}
|
|
|
|
set_vext_version(env, vext_version);
|
2023-01-13 20:52:30 +03:00
|
|
|
}
|
|
|
|
if (cpu->cfg.ext_j) {
|
|
|
|
ext |= RVJ;
|
|
|
|
}
|
|
|
|
|
|
|
|
set_misa(env, env->misa_mxl, ext);
|
|
|
|
}
|
|
|
|
|
riscv: Allow user to set the satp mode
RISC-V specifies multiple sizes for addressable memory and Linux probes for
the machine's support at startup via the satp CSR register (done in
csr.c:validate_vm).
As per the specification, sv64 must support sv57, which in turn must
support sv48...etc. So we can restrict machine support by simply setting the
"highest" supported mode and the bare mode is always supported.
You can set the satp mode using the new properties "sv32", "sv39", "sv48",
"sv57" and "sv64" as follows:
-cpu rv64,sv57=on # Linux will boot using sv57 scheme
-cpu rv64,sv39=on # Linux will boot using sv39 scheme
-cpu rv64,sv57=off # Linux will boot using sv48 scheme
-cpu rv64 # Linux will boot using sv57 scheme by default
We take the highest level set by the user:
-cpu rv64,sv48=on,sv57=on # Linux will boot using sv57 scheme
We make sure that invalid configurations are rejected:
-cpu rv64,sv39=off,sv48=on # sv39 must be supported if higher modes are
# enabled
We accept "redundant" configurations:
-cpu rv64,sv48=on,sv57=off # Linux will boot using sv48 scheme
And contradictory configurations:
-cpu rv64,sv48=on,sv48=off # Linux will boot using sv39 scheme
Co-Developed-by: Ludovic Henry <ludovic@rivosinc.com>
Signed-off-by: Ludovic Henry <ludovic@rivosinc.com>
Signed-off-by: Alexandre Ghiti <alexghiti@rivosinc.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
Reviewed-by: Bin Meng <bmeng@tinylab.org>
Acked-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Frank Chang <frank.chang@sifive.com>
Message-ID: <20230303131252.892893-4-alexghiti@rivosinc.com>
Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
2023-03-03 16:12:50 +03:00
|
|
|
#ifndef CONFIG_USER_ONLY
|
|
|
|
static void riscv_cpu_satp_mode_finalize(RISCVCPU *cpu, Error **errp)
|
|
|
|
{
|
|
|
|
bool rv32 = riscv_cpu_mxl(&cpu->env) == MXL_RV32;
|
2023-03-03 16:12:51 +03:00
|
|
|
uint8_t satp_mode_map_max;
|
|
|
|
uint8_t satp_mode_supported_max =
|
|
|
|
satp_mode_max_from_map(cpu->cfg.satp_mode.supported);
|
riscv: Allow user to set the satp mode
RISC-V specifies multiple sizes for addressable memory and Linux probes for
the machine's support at startup via the satp CSR register (done in
csr.c:validate_vm).
As per the specification, sv64 must support sv57, which in turn must
support sv48...etc. So we can restrict machine support by simply setting the
"highest" supported mode and the bare mode is always supported.
You can set the satp mode using the new properties "sv32", "sv39", "sv48",
"sv57" and "sv64" as follows:
-cpu rv64,sv57=on # Linux will boot using sv57 scheme
-cpu rv64,sv39=on # Linux will boot using sv39 scheme
-cpu rv64,sv57=off # Linux will boot using sv48 scheme
-cpu rv64 # Linux will boot using sv57 scheme by default
We take the highest level set by the user:
-cpu rv64,sv48=on,sv57=on # Linux will boot using sv57 scheme
We make sure that invalid configurations are rejected:
-cpu rv64,sv39=off,sv48=on # sv39 must be supported if higher modes are
# enabled
We accept "redundant" configurations:
-cpu rv64,sv48=on,sv57=off # Linux will boot using sv48 scheme
And contradictory configurations:
-cpu rv64,sv48=on,sv48=off # Linux will boot using sv39 scheme
Co-Developed-by: Ludovic Henry <ludovic@rivosinc.com>
Signed-off-by: Ludovic Henry <ludovic@rivosinc.com>
Signed-off-by: Alexandre Ghiti <alexghiti@rivosinc.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
Reviewed-by: Bin Meng <bmeng@tinylab.org>
Acked-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Frank Chang <frank.chang@sifive.com>
Message-ID: <20230303131252.892893-4-alexghiti@rivosinc.com>
Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
2023-03-03 16:12:50 +03:00
|
|
|
|
|
|
|
if (cpu->cfg.satp_mode.map == 0) {
|
|
|
|
if (cpu->cfg.satp_mode.init == 0) {
|
|
|
|
/* If unset by the user, we fallback to the default satp mode. */
|
|
|
|
set_satp_mode_default_map(cpu);
|
|
|
|
} else {
|
|
|
|
/*
|
|
|
|
* Find the lowest level that was disabled and then enable the
|
|
|
|
* first valid level below which can be found in
|
|
|
|
* valid_vm_1_10_32/64.
|
|
|
|
*/
|
|
|
|
for (int i = 1; i < 16; ++i) {
|
2023-03-03 16:12:51 +03:00
|
|
|
if ((cpu->cfg.satp_mode.init & (1 << i)) &&
|
|
|
|
(cpu->cfg.satp_mode.supported & (1 << i))) {
|
riscv: Allow user to set the satp mode
RISC-V specifies multiple sizes for addressable memory and Linux probes for
the machine's support at startup via the satp CSR register (done in
csr.c:validate_vm).
As per the specification, sv64 must support sv57, which in turn must
support sv48...etc. So we can restrict machine support by simply setting the
"highest" supported mode and the bare mode is always supported.
You can set the satp mode using the new properties "sv32", "sv39", "sv48",
"sv57" and "sv64" as follows:
-cpu rv64,sv57=on # Linux will boot using sv57 scheme
-cpu rv64,sv39=on # Linux will boot using sv39 scheme
-cpu rv64,sv57=off # Linux will boot using sv48 scheme
-cpu rv64 # Linux will boot using sv57 scheme by default
We take the highest level set by the user:
-cpu rv64,sv48=on,sv57=on # Linux will boot using sv57 scheme
We make sure that invalid configurations are rejected:
-cpu rv64,sv39=off,sv48=on # sv39 must be supported if higher modes are
# enabled
We accept "redundant" configurations:
-cpu rv64,sv48=on,sv57=off # Linux will boot using sv48 scheme
And contradictory configurations:
-cpu rv64,sv48=on,sv48=off # Linux will boot using sv39 scheme
Co-Developed-by: Ludovic Henry <ludovic@rivosinc.com>
Signed-off-by: Ludovic Henry <ludovic@rivosinc.com>
Signed-off-by: Alexandre Ghiti <alexghiti@rivosinc.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
Reviewed-by: Bin Meng <bmeng@tinylab.org>
Acked-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Frank Chang <frank.chang@sifive.com>
Message-ID: <20230303131252.892893-4-alexghiti@rivosinc.com>
Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
2023-03-03 16:12:50 +03:00
|
|
|
for (int j = i - 1; j >= 0; --j) {
|
2023-03-03 16:12:51 +03:00
|
|
|
if (cpu->cfg.satp_mode.supported & (1 << j)) {
|
riscv: Allow user to set the satp mode
RISC-V specifies multiple sizes for addressable memory and Linux probes for
the machine's support at startup via the satp CSR register (done in
csr.c:validate_vm).
As per the specification, sv64 must support sv57, which in turn must
support sv48...etc. So we can restrict machine support by simply setting the
"highest" supported mode and the bare mode is always supported.
You can set the satp mode using the new properties "sv32", "sv39", "sv48",
"sv57" and "sv64" as follows:
-cpu rv64,sv57=on # Linux will boot using sv57 scheme
-cpu rv64,sv39=on # Linux will boot using sv39 scheme
-cpu rv64,sv57=off # Linux will boot using sv48 scheme
-cpu rv64 # Linux will boot using sv57 scheme by default
We take the highest level set by the user:
-cpu rv64,sv48=on,sv57=on # Linux will boot using sv57 scheme
We make sure that invalid configurations are rejected:
-cpu rv64,sv39=off,sv48=on # sv39 must be supported if higher modes are
# enabled
We accept "redundant" configurations:
-cpu rv64,sv48=on,sv57=off # Linux will boot using sv48 scheme
And contradictory configurations:
-cpu rv64,sv48=on,sv48=off # Linux will boot using sv39 scheme
Co-Developed-by: Ludovic Henry <ludovic@rivosinc.com>
Signed-off-by: Ludovic Henry <ludovic@rivosinc.com>
Signed-off-by: Alexandre Ghiti <alexghiti@rivosinc.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
Reviewed-by: Bin Meng <bmeng@tinylab.org>
Acked-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Frank Chang <frank.chang@sifive.com>
Message-ID: <20230303131252.892893-4-alexghiti@rivosinc.com>
Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
2023-03-03 16:12:50 +03:00
|
|
|
cpu->cfg.satp_mode.map |= (1 << j);
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
break;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-03-03 16:12:51 +03:00
|
|
|
satp_mode_map_max = satp_mode_max_from_map(cpu->cfg.satp_mode.map);
|
|
|
|
|
|
|
|
/* Make sure the user asked for a supported configuration (HW and qemu) */
|
|
|
|
if (satp_mode_map_max > satp_mode_supported_max) {
|
|
|
|
error_setg(errp, "satp_mode %s is higher than hw max capability %s",
|
|
|
|
satp_mode_str(satp_mode_map_max, rv32),
|
|
|
|
satp_mode_str(satp_mode_supported_max, rv32));
|
|
|
|
return;
|
riscv: Allow user to set the satp mode
RISC-V specifies multiple sizes for addressable memory and Linux probes for
the machine's support at startup via the satp CSR register (done in
csr.c:validate_vm).
As per the specification, sv64 must support sv57, which in turn must
support sv48...etc. So we can restrict machine support by simply setting the
"highest" supported mode and the bare mode is always supported.
You can set the satp mode using the new properties "sv32", "sv39", "sv48",
"sv57" and "sv64" as follows:
-cpu rv64,sv57=on # Linux will boot using sv57 scheme
-cpu rv64,sv39=on # Linux will boot using sv39 scheme
-cpu rv64,sv57=off # Linux will boot using sv48 scheme
-cpu rv64 # Linux will boot using sv57 scheme by default
We take the highest level set by the user:
-cpu rv64,sv48=on,sv57=on # Linux will boot using sv57 scheme
We make sure that invalid configurations are rejected:
-cpu rv64,sv39=off,sv48=on # sv39 must be supported if higher modes are
# enabled
We accept "redundant" configurations:
-cpu rv64,sv48=on,sv57=off # Linux will boot using sv48 scheme
And contradictory configurations:
-cpu rv64,sv48=on,sv48=off # Linux will boot using sv39 scheme
Co-Developed-by: Ludovic Henry <ludovic@rivosinc.com>
Signed-off-by: Ludovic Henry <ludovic@rivosinc.com>
Signed-off-by: Alexandre Ghiti <alexghiti@rivosinc.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
Reviewed-by: Bin Meng <bmeng@tinylab.org>
Acked-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Frank Chang <frank.chang@sifive.com>
Message-ID: <20230303131252.892893-4-alexghiti@rivosinc.com>
Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
2023-03-03 16:12:50 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
/*
|
|
|
|
* Make sure the user did not ask for an invalid configuration as per
|
|
|
|
* the specification.
|
|
|
|
*/
|
|
|
|
if (!rv32) {
|
2023-03-03 16:12:51 +03:00
|
|
|
for (int i = satp_mode_map_max - 1; i >= 0; --i) {
|
riscv: Allow user to set the satp mode
RISC-V specifies multiple sizes for addressable memory and Linux probes for
the machine's support at startup via the satp CSR register (done in
csr.c:validate_vm).
As per the specification, sv64 must support sv57, which in turn must
support sv48...etc. So we can restrict machine support by simply setting the
"highest" supported mode and the bare mode is always supported.
You can set the satp mode using the new properties "sv32", "sv39", "sv48",
"sv57" and "sv64" as follows:
-cpu rv64,sv57=on # Linux will boot using sv57 scheme
-cpu rv64,sv39=on # Linux will boot using sv39 scheme
-cpu rv64,sv57=off # Linux will boot using sv48 scheme
-cpu rv64 # Linux will boot using sv57 scheme by default
We take the highest level set by the user:
-cpu rv64,sv48=on,sv57=on # Linux will boot using sv57 scheme
We make sure that invalid configurations are rejected:
-cpu rv64,sv39=off,sv48=on # sv39 must be supported if higher modes are
# enabled
We accept "redundant" configurations:
-cpu rv64,sv48=on,sv57=off # Linux will boot using sv48 scheme
And contradictory configurations:
-cpu rv64,sv48=on,sv48=off # Linux will boot using sv39 scheme
Co-Developed-by: Ludovic Henry <ludovic@rivosinc.com>
Signed-off-by: Ludovic Henry <ludovic@rivosinc.com>
Signed-off-by: Alexandre Ghiti <alexghiti@rivosinc.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
Reviewed-by: Bin Meng <bmeng@tinylab.org>
Acked-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Frank Chang <frank.chang@sifive.com>
Message-ID: <20230303131252.892893-4-alexghiti@rivosinc.com>
Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
2023-03-03 16:12:50 +03:00
|
|
|
if (!(cpu->cfg.satp_mode.map & (1 << i)) &&
|
|
|
|
(cpu->cfg.satp_mode.init & (1 << i)) &&
|
2023-03-03 16:12:51 +03:00
|
|
|
(cpu->cfg.satp_mode.supported & (1 << i))) {
|
riscv: Allow user to set the satp mode
RISC-V specifies multiple sizes for addressable memory and Linux probes for
the machine's support at startup via the satp CSR register (done in
csr.c:validate_vm).
As per the specification, sv64 must support sv57, which in turn must
support sv48...etc. So we can restrict machine support by simply setting the
"highest" supported mode and the bare mode is always supported.
You can set the satp mode using the new properties "sv32", "sv39", "sv48",
"sv57" and "sv64" as follows:
-cpu rv64,sv57=on # Linux will boot using sv57 scheme
-cpu rv64,sv39=on # Linux will boot using sv39 scheme
-cpu rv64,sv57=off # Linux will boot using sv48 scheme
-cpu rv64 # Linux will boot using sv57 scheme by default
We take the highest level set by the user:
-cpu rv64,sv48=on,sv57=on # Linux will boot using sv57 scheme
We make sure that invalid configurations are rejected:
-cpu rv64,sv39=off,sv48=on # sv39 must be supported if higher modes are
# enabled
We accept "redundant" configurations:
-cpu rv64,sv48=on,sv57=off # Linux will boot using sv48 scheme
And contradictory configurations:
-cpu rv64,sv48=on,sv48=off # Linux will boot using sv39 scheme
Co-Developed-by: Ludovic Henry <ludovic@rivosinc.com>
Signed-off-by: Ludovic Henry <ludovic@rivosinc.com>
Signed-off-by: Alexandre Ghiti <alexghiti@rivosinc.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
Reviewed-by: Bin Meng <bmeng@tinylab.org>
Acked-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Frank Chang <frank.chang@sifive.com>
Message-ID: <20230303131252.892893-4-alexghiti@rivosinc.com>
Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
2023-03-03 16:12:50 +03:00
|
|
|
error_setg(errp, "cannot disable %s satp mode if %s "
|
|
|
|
"is enabled", satp_mode_str(i, false),
|
2023-03-03 16:12:51 +03:00
|
|
|
satp_mode_str(satp_mode_map_max, false));
|
riscv: Allow user to set the satp mode
RISC-V specifies multiple sizes for addressable memory and Linux probes for
the machine's support at startup via the satp CSR register (done in
csr.c:validate_vm).
As per the specification, sv64 must support sv57, which in turn must
support sv48...etc. So we can restrict machine support by simply setting the
"highest" supported mode and the bare mode is always supported.
You can set the satp mode using the new properties "sv32", "sv39", "sv48",
"sv57" and "sv64" as follows:
-cpu rv64,sv57=on # Linux will boot using sv57 scheme
-cpu rv64,sv39=on # Linux will boot using sv39 scheme
-cpu rv64,sv57=off # Linux will boot using sv48 scheme
-cpu rv64 # Linux will boot using sv57 scheme by default
We take the highest level set by the user:
-cpu rv64,sv48=on,sv57=on # Linux will boot using sv57 scheme
We make sure that invalid configurations are rejected:
-cpu rv64,sv39=off,sv48=on # sv39 must be supported if higher modes are
# enabled
We accept "redundant" configurations:
-cpu rv64,sv48=on,sv57=off # Linux will boot using sv48 scheme
And contradictory configurations:
-cpu rv64,sv48=on,sv48=off # Linux will boot using sv39 scheme
Co-Developed-by: Ludovic Henry <ludovic@rivosinc.com>
Signed-off-by: Ludovic Henry <ludovic@rivosinc.com>
Signed-off-by: Alexandre Ghiti <alexghiti@rivosinc.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
Reviewed-by: Bin Meng <bmeng@tinylab.org>
Acked-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Frank Chang <frank.chang@sifive.com>
Message-ID: <20230303131252.892893-4-alexghiti@rivosinc.com>
Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
2023-03-03 16:12:50 +03:00
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Finally expand the map so that all valid modes are set */
|
2023-03-03 16:12:51 +03:00
|
|
|
for (int i = satp_mode_map_max - 1; i >= 0; --i) {
|
|
|
|
if (cpu->cfg.satp_mode.supported & (1 << i)) {
|
riscv: Allow user to set the satp mode
RISC-V specifies multiple sizes for addressable memory and Linux probes for
the machine's support at startup via the satp CSR register (done in
csr.c:validate_vm).
As per the specification, sv64 must support sv57, which in turn must
support sv48...etc. So we can restrict machine support by simply setting the
"highest" supported mode and the bare mode is always supported.
You can set the satp mode using the new properties "sv32", "sv39", "sv48",
"sv57" and "sv64" as follows:
-cpu rv64,sv57=on # Linux will boot using sv57 scheme
-cpu rv64,sv39=on # Linux will boot using sv39 scheme
-cpu rv64,sv57=off # Linux will boot using sv48 scheme
-cpu rv64 # Linux will boot using sv57 scheme by default
We take the highest level set by the user:
-cpu rv64,sv48=on,sv57=on # Linux will boot using sv57 scheme
We make sure that invalid configurations are rejected:
-cpu rv64,sv39=off,sv48=on # sv39 must be supported if higher modes are
# enabled
We accept "redundant" configurations:
-cpu rv64,sv48=on,sv57=off # Linux will boot using sv48 scheme
And contradictory configurations:
-cpu rv64,sv48=on,sv48=off # Linux will boot using sv39 scheme
Co-Developed-by: Ludovic Henry <ludovic@rivosinc.com>
Signed-off-by: Ludovic Henry <ludovic@rivosinc.com>
Signed-off-by: Alexandre Ghiti <alexghiti@rivosinc.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
Reviewed-by: Bin Meng <bmeng@tinylab.org>
Acked-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Frank Chang <frank.chang@sifive.com>
Message-ID: <20230303131252.892893-4-alexghiti@rivosinc.com>
Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
2023-03-03 16:12:50 +03:00
|
|
|
cpu->cfg.satp_mode.map |= (1 << i);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
static void riscv_cpu_finalize_features(RISCVCPU *cpu, Error **errp)
|
|
|
|
{
|
|
|
|
#ifndef CONFIG_USER_ONLY
|
|
|
|
Error *local_err = NULL;
|
|
|
|
|
|
|
|
riscv_cpu_satp_mode_finalize(cpu, &local_err);
|
|
|
|
if (local_err != NULL) {
|
|
|
|
error_propagate(errp, local_err);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
2018-03-02 15:31:10 +03:00
|
|
|
static void riscv_cpu_realize(DeviceState *dev, Error **errp)
|
|
|
|
{
|
|
|
|
CPUState *cs = CPU(dev);
|
2019-04-20 05:24:01 +03:00
|
|
|
RISCVCPU *cpu = RISCV_CPU(dev);
|
|
|
|
CPURISCVState *env = &cpu->env;
|
2018-03-02 15:31:10 +03:00
|
|
|
RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(dev);
|
2022-01-20 15:20:35 +03:00
|
|
|
CPUClass *cc = CPU_CLASS(mcc);
|
2022-06-30 09:11:50 +03:00
|
|
|
int i, priv_version = -1;
|
2018-03-02 15:31:10 +03:00
|
|
|
Error *local_err = NULL;
|
|
|
|
|
|
|
|
cpu_exec_realizefn(cs, &local_err);
|
|
|
|
if (local_err != NULL) {
|
|
|
|
error_propagate(errp, local_err);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-04-20 05:24:01 +03:00
|
|
|
if (cpu->cfg.priv_spec) {
|
2022-03-03 21:54:40 +03:00
|
|
|
if (!g_strcmp0(cpu->cfg.priv_spec, "v1.12.0")) {
|
|
|
|
priv_version = PRIV_VERSION_1_12_0;
|
|
|
|
} else if (!g_strcmp0(cpu->cfg.priv_spec, "v1.11.0")) {
|
2019-06-18 04:31:11 +03:00
|
|
|
priv_version = PRIV_VERSION_1_11_0;
|
|
|
|
} else if (!g_strcmp0(cpu->cfg.priv_spec, "v1.10.0")) {
|
2019-04-20 05:24:01 +03:00
|
|
|
priv_version = PRIV_VERSION_1_10_0;
|
|
|
|
} else {
|
|
|
|
error_setg(errp,
|
|
|
|
"Unsupported privilege spec version '%s'",
|
|
|
|
cpu->cfg.priv_spec);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2022-06-11 11:01:04 +03:00
|
|
|
if (priv_version >= PRIV_VERSION_1_10_0) {
|
2021-08-11 17:46:12 +03:00
|
|
|
set_priv_version(env, priv_version);
|
|
|
|
}
|
2019-04-20 05:24:01 +03:00
|
|
|
|
2022-06-30 09:11:50 +03:00
|
|
|
/* Force disable extensions if priv spec version does not match */
|
|
|
|
for (i = 0; i < ARRAY_SIZE(isa_edata_arr); i++) {
|
|
|
|
if (isa_ext_is_enabled(cpu, &isa_edata_arr[i]) &&
|
|
|
|
(env->priv_ver < isa_edata_arr[i].min_version)) {
|
|
|
|
isa_ext_update_enabled(cpu, &isa_edata_arr[i], false);
|
|
|
|
#ifndef CONFIG_USER_ONLY
|
2023-01-09 18:26:55 +03:00
|
|
|
warn_report("disabling %s extension for hart 0x" TARGET_FMT_lx
|
|
|
|
" because privilege spec version does not match",
|
|
|
|
isa_edata_arr[i].name, env->mhartid);
|
2022-06-30 09:11:50 +03:00
|
|
|
#else
|
|
|
|
warn_report("disabling %s extension because "
|
|
|
|
"privilege spec version does not match",
|
|
|
|
isa_edata_arr[i].name);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2023-02-22 21:52:01 +03:00
|
|
|
if (cpu->cfg.epmp && !cpu->cfg.pmp) {
|
2021-04-19 09:17:25 +03:00
|
|
|
/*
|
|
|
|
* Enhanced PMP should only be available
|
|
|
|
* on harts with PMP support
|
|
|
|
*/
|
2023-02-22 21:52:01 +03:00
|
|
|
error_setg(errp, "Invalid configuration: EPMP requires PMP support");
|
|
|
|
return;
|
2022-04-21 03:33:20 +03:00
|
|
|
}
|
|
|
|
|
2020-09-01 04:38:58 +03:00
|
|
|
|
2022-08-25 01:13:56 +03:00
|
|
|
#ifndef CONFIG_USER_ONLY
|
|
|
|
if (cpu->cfg.ext_sstc) {
|
|
|
|
riscv_timer_init(cpu);
|
|
|
|
}
|
|
|
|
#endif /* CONFIG_USER_ONLY */
|
|
|
|
|
2021-10-20 06:16:57 +03:00
|
|
|
/* Validate that MISA_MXL is set properly. */
|
|
|
|
switch (env->misa_mxl_max) {
|
|
|
|
#ifdef TARGET_RISCV64
|
|
|
|
case MXL_RV64:
|
2022-01-07 00:00:57 +03:00
|
|
|
case MXL_RV128:
|
2022-01-24 23:24:56 +03:00
|
|
|
cc->gdb_core_xml_file = "riscv-64bit-cpu.xml";
|
2022-01-07 00:00:57 +03:00
|
|
|
break;
|
2021-10-20 06:16:57 +03:00
|
|
|
#endif
|
|
|
|
case MXL_RV32:
|
2022-01-20 15:20:35 +03:00
|
|
|
cc->gdb_core_xml_file = "riscv-32bit-cpu.xml";
|
2021-10-20 06:16:57 +03:00
|
|
|
break;
|
|
|
|
default:
|
|
|
|
g_assert_not_reached();
|
|
|
|
}
|
|
|
|
assert(env->misa_mxl_max == env->misa_mxl);
|
|
|
|
|
2023-01-13 20:52:30 +03:00
|
|
|
riscv_cpu_validate_set_extensions(cpu, &local_err);
|
|
|
|
if (local_err != NULL) {
|
|
|
|
error_propagate(errp, local_err);
|
|
|
|
return;
|
2019-05-07 01:49:53 +03:00
|
|
|
}
|
|
|
|
|
2022-08-25 01:16:57 +03:00
|
|
|
#ifndef CONFIG_USER_ONLY
|
|
|
|
if (cpu->cfg.pmu_num) {
|
|
|
|
if (!riscv_pmu_init(cpu, cpu->cfg.pmu_num) && cpu->cfg.ext_sscofpmf) {
|
|
|
|
cpu->pmu_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL,
|
|
|
|
riscv_pmu_timer_cb, cpu);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
riscv: Allow user to set the satp mode
RISC-V specifies multiple sizes for addressable memory and Linux probes for
the machine's support at startup via the satp CSR register (done in
csr.c:validate_vm).
As per the specification, sv64 must support sv57, which in turn must
support sv48...etc. So we can restrict machine support by simply setting the
"highest" supported mode and the bare mode is always supported.
You can set the satp mode using the new properties "sv32", "sv39", "sv48",
"sv57" and "sv64" as follows:
-cpu rv64,sv57=on # Linux will boot using sv57 scheme
-cpu rv64,sv39=on # Linux will boot using sv39 scheme
-cpu rv64,sv57=off # Linux will boot using sv48 scheme
-cpu rv64 # Linux will boot using sv57 scheme by default
We take the highest level set by the user:
-cpu rv64,sv48=on,sv57=on # Linux will boot using sv57 scheme
We make sure that invalid configurations are rejected:
-cpu rv64,sv39=off,sv48=on # sv39 must be supported if higher modes are
# enabled
We accept "redundant" configurations:
-cpu rv64,sv48=on,sv57=off # Linux will boot using sv48 scheme
And contradictory configurations:
-cpu rv64,sv48=on,sv48=off # Linux will boot using sv39 scheme
Co-Developed-by: Ludovic Henry <ludovic@rivosinc.com>
Signed-off-by: Ludovic Henry <ludovic@rivosinc.com>
Signed-off-by: Alexandre Ghiti <alexghiti@rivosinc.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
Reviewed-by: Bin Meng <bmeng@tinylab.org>
Acked-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Frank Chang <frank.chang@sifive.com>
Message-ID: <20230303131252.892893-4-alexghiti@rivosinc.com>
Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
2023-03-03 16:12:50 +03:00
|
|
|
riscv_cpu_finalize_features(cpu, &local_err);
|
|
|
|
if (local_err != NULL) {
|
|
|
|
error_propagate(errp, local_err);
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2019-03-15 13:26:59 +03:00
|
|
|
riscv_cpu_register_gdb_regs_for_features(cs);
|
|
|
|
|
2018-03-02 15:31:10 +03:00
|
|
|
qemu_init_vcpu(cs);
|
|
|
|
cpu_reset(cs);
|
|
|
|
|
|
|
|
mcc->parent_realize(dev, errp);
|
|
|
|
}
|
|
|
|
|
2021-08-30 08:34:20 +03:00
|
|
|
#ifndef CONFIG_USER_ONLY
|
riscv: Allow user to set the satp mode
RISC-V specifies multiple sizes for addressable memory and Linux probes for
the machine's support at startup via the satp CSR register (done in
csr.c:validate_vm).
As per the specification, sv64 must support sv57, which in turn must
support sv48...etc. So we can restrict machine support by simply setting the
"highest" supported mode and the bare mode is always supported.
You can set the satp mode using the new properties "sv32", "sv39", "sv48",
"sv57" and "sv64" as follows:
-cpu rv64,sv57=on # Linux will boot using sv57 scheme
-cpu rv64,sv39=on # Linux will boot using sv39 scheme
-cpu rv64,sv57=off # Linux will boot using sv48 scheme
-cpu rv64 # Linux will boot using sv57 scheme by default
We take the highest level set by the user:
-cpu rv64,sv48=on,sv57=on # Linux will boot using sv57 scheme
We make sure that invalid configurations are rejected:
-cpu rv64,sv39=off,sv48=on # sv39 must be supported if higher modes are
# enabled
We accept "redundant" configurations:
-cpu rv64,sv48=on,sv57=off # Linux will boot using sv48 scheme
And contradictory configurations:
-cpu rv64,sv48=on,sv48=off # Linux will boot using sv39 scheme
Co-Developed-by: Ludovic Henry <ludovic@rivosinc.com>
Signed-off-by: Ludovic Henry <ludovic@rivosinc.com>
Signed-off-by: Alexandre Ghiti <alexghiti@rivosinc.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
Reviewed-by: Bin Meng <bmeng@tinylab.org>
Acked-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Frank Chang <frank.chang@sifive.com>
Message-ID: <20230303131252.892893-4-alexghiti@rivosinc.com>
Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
2023-03-03 16:12:50 +03:00
|
|
|
static void cpu_riscv_get_satp(Object *obj, Visitor *v, const char *name,
|
|
|
|
void *opaque, Error **errp)
|
|
|
|
{
|
|
|
|
RISCVSATPMap *satp_map = opaque;
|
|
|
|
uint8_t satp = satp_mode_from_str(name);
|
|
|
|
bool value;
|
|
|
|
|
|
|
|
value = satp_map->map & (1 << satp);
|
|
|
|
|
|
|
|
visit_type_bool(v, name, &value, errp);
|
|
|
|
}
|
|
|
|
|
|
|
|
static void cpu_riscv_set_satp(Object *obj, Visitor *v, const char *name,
|
|
|
|
void *opaque, Error **errp)
|
|
|
|
{
|
|
|
|
RISCVSATPMap *satp_map = opaque;
|
|
|
|
uint8_t satp = satp_mode_from_str(name);
|
|
|
|
bool value;
|
|
|
|
|
|
|
|
if (!visit_type_bool(v, name, &value, errp)) {
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
|
|
|
satp_map->map = deposit32(satp_map->map, satp, 1, value);
|
|
|
|
satp_map->init |= 1 << satp;
|
|
|
|
}
|
|
|
|
|
|
|
|
static void riscv_add_satp_mode_properties(Object *obj)
|
|
|
|
{
|
|
|
|
RISCVCPU *cpu = RISCV_CPU(obj);
|
|
|
|
|
|
|
|
if (cpu->env.misa_mxl == MXL_RV32) {
|
|
|
|
object_property_add(obj, "sv32", "bool", cpu_riscv_get_satp,
|
|
|
|
cpu_riscv_set_satp, NULL, &cpu->cfg.satp_mode);
|
|
|
|
} else {
|
|
|
|
object_property_add(obj, "sv39", "bool", cpu_riscv_get_satp,
|
|
|
|
cpu_riscv_set_satp, NULL, &cpu->cfg.satp_mode);
|
|
|
|
object_property_add(obj, "sv48", "bool", cpu_riscv_get_satp,
|
|
|
|
cpu_riscv_set_satp, NULL, &cpu->cfg.satp_mode);
|
|
|
|
object_property_add(obj, "sv57", "bool", cpu_riscv_get_satp,
|
|
|
|
cpu_riscv_set_satp, NULL, &cpu->cfg.satp_mode);
|
|
|
|
object_property_add(obj, "sv64", "bool", cpu_riscv_get_satp,
|
|
|
|
cpu_riscv_set_satp, NULL, &cpu->cfg.satp_mode);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-08-30 08:34:20 +03:00
|
|
|
static void riscv_cpu_set_irq(void *opaque, int irq, int level)
|
|
|
|
{
|
|
|
|
RISCVCPU *cpu = RISCV_CPU(opaque);
|
2022-02-04 20:46:39 +03:00
|
|
|
CPURISCVState *env = &cpu->env;
|
2021-08-30 08:34:20 +03:00
|
|
|
|
2022-02-04 20:46:39 +03:00
|
|
|
if (irq < IRQ_LOCAL_MAX) {
|
|
|
|
switch (irq) {
|
|
|
|
case IRQ_U_SOFT:
|
|
|
|
case IRQ_S_SOFT:
|
|
|
|
case IRQ_VS_SOFT:
|
|
|
|
case IRQ_M_SOFT:
|
|
|
|
case IRQ_U_TIMER:
|
|
|
|
case IRQ_S_TIMER:
|
|
|
|
case IRQ_VS_TIMER:
|
|
|
|
case IRQ_M_TIMER:
|
|
|
|
case IRQ_U_EXT:
|
|
|
|
case IRQ_VS_EXT:
|
|
|
|
case IRQ_M_EXT:
|
2022-03-17 09:18:16 +03:00
|
|
|
if (kvm_enabled()) {
|
2022-02-04 20:46:39 +03:00
|
|
|
kvm_riscv_set_irq(cpu, irq, level);
|
2022-03-17 09:18:16 +03:00
|
|
|
} else {
|
2022-02-04 20:46:39 +03:00
|
|
|
riscv_cpu_update_mip(cpu, 1 << irq, BOOL_TO_MASK(level));
|
2022-03-17 09:18:16 +03:00
|
|
|
}
|
2022-02-04 20:46:39 +03:00
|
|
|
break;
|
2022-03-17 09:18:17 +03:00
|
|
|
case IRQ_S_EXT:
|
|
|
|
if (kvm_enabled()) {
|
|
|
|
kvm_riscv_set_irq(cpu, irq, level);
|
|
|
|
} else {
|
|
|
|
env->external_seip = level;
|
|
|
|
riscv_cpu_update_mip(cpu, 1 << irq,
|
|
|
|
BOOL_TO_MASK(level | env->software_seip));
|
|
|
|
}
|
|
|
|
break;
|
2022-02-04 20:46:39 +03:00
|
|
|
default:
|
|
|
|
g_assert_not_reached();
|
2022-01-12 11:13:23 +03:00
|
|
|
}
|
2022-02-04 20:46:39 +03:00
|
|
|
} else if (irq < (IRQ_LOCAL_MAX + IRQ_LOCAL_GUEST_MAX)) {
|
|
|
|
/* Require H-extension for handling guest local interrupts */
|
|
|
|
if (!riscv_has_ext(env, RVH)) {
|
|
|
|
g_assert_not_reached();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Compute bit position in HGEIP CSR */
|
|
|
|
irq = irq - IRQ_LOCAL_MAX + 1;
|
|
|
|
if (env->geilen < irq) {
|
|
|
|
g_assert_not_reached();
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Update HGEIP CSR */
|
|
|
|
env->hgeip &= ~((target_ulong)1 << irq);
|
|
|
|
if (level) {
|
|
|
|
env->hgeip |= (target_ulong)1 << irq;
|
|
|
|
}
|
|
|
|
|
|
|
|
/* Update mip.SGEIP bit */
|
|
|
|
riscv_cpu_update_mip(cpu, MIP_SGEIP,
|
|
|
|
BOOL_TO_MASK(!!(env->hgeie & env->hgeip)));
|
|
|
|
} else {
|
2021-08-30 08:34:20 +03:00
|
|
|
g_assert_not_reached();
|
|
|
|
}
|
|
|
|
}
|
|
|
|
#endif /* CONFIG_USER_ONLY */
|
|
|
|
|
2018-03-02 15:31:10 +03:00
|
|
|
static void riscv_cpu_init(Object *obj)
|
|
|
|
{
|
|
|
|
RISCVCPU *cpu = RISCV_CPU(obj);
|
|
|
|
|
2022-06-08 09:14:37 +03:00
|
|
|
cpu->cfg.ext_ifencei = true;
|
|
|
|
cpu->cfg.ext_icsr = true;
|
|
|
|
cpu->cfg.mmu = true;
|
|
|
|
cpu->cfg.pmp = true;
|
|
|
|
|
2019-03-29 00:26:22 +03:00
|
|
|
cpu_set_cpustate_pointers(cpu);
|
2021-08-30 08:34:20 +03:00
|
|
|
|
|
|
|
#ifndef CONFIG_USER_ONLY
|
2022-02-04 20:46:39 +03:00
|
|
|
qdev_init_gpio_in(DEVICE(cpu), riscv_cpu_set_irq,
|
|
|
|
IRQ_LOCAL_MAX + IRQ_LOCAL_GUEST_MAX);
|
2021-08-30 08:34:20 +03:00
|
|
|
#endif /* CONFIG_USER_ONLY */
|
2018-03-02 15:31:10 +03:00
|
|
|
}
|
|
|
|
|
2022-06-08 09:14:37 +03:00
|
|
|
static Property riscv_cpu_extensions[] = {
|
2021-10-18 07:32:15 +03:00
|
|
|
/* Defaults for standard extensions */
|
2019-05-07 01:49:53 +03:00
|
|
|
DEFINE_PROP_BOOL("i", RISCVCPU, cfg.ext_i, true),
|
|
|
|
DEFINE_PROP_BOOL("e", RISCVCPU, cfg.ext_e, false),
|
2022-05-15 05:56:08 +03:00
|
|
|
DEFINE_PROP_BOOL("g", RISCVCPU, cfg.ext_g, false),
|
2019-05-07 01:49:53 +03:00
|
|
|
DEFINE_PROP_BOOL("m", RISCVCPU, cfg.ext_m, true),
|
|
|
|
DEFINE_PROP_BOOL("a", RISCVCPU, cfg.ext_a, true),
|
|
|
|
DEFINE_PROP_BOOL("f", RISCVCPU, cfg.ext_f, true),
|
|
|
|
DEFINE_PROP_BOOL("d", RISCVCPU, cfg.ext_d, true),
|
|
|
|
DEFINE_PROP_BOOL("c", RISCVCPU, cfg.ext_c, true),
|
|
|
|
DEFINE_PROP_BOOL("s", RISCVCPU, cfg.ext_s, true),
|
|
|
|
DEFINE_PROP_BOOL("u", RISCVCPU, cfg.ext_u, true),
|
2021-12-10 10:55:47 +03:00
|
|
|
DEFINE_PROP_BOOL("v", RISCVCPU, cfg.ext_v, false),
|
2022-01-06 00:39:35 +03:00
|
|
|
DEFINE_PROP_BOOL("h", RISCVCPU, cfg.ext_h, true),
|
2022-06-21 02:15:54 +03:00
|
|
|
DEFINE_PROP_UINT8("pmu-num", RISCVCPU, cfg.pmu_num, 16),
|
2022-08-25 01:16:57 +03:00
|
|
|
DEFINE_PROP_BOOL("sscofpmf", RISCVCPU, cfg.ext_sscofpmf, false),
|
2021-10-18 07:32:15 +03:00
|
|
|
DEFINE_PROP_BOOL("Zifencei", RISCVCPU, cfg.ext_ifencei, true),
|
|
|
|
DEFINE_PROP_BOOL("Zicsr", RISCVCPU, cfg.ext_icsr, true),
|
2022-07-25 06:47:28 +03:00
|
|
|
DEFINE_PROP_BOOL("Zihintpause", RISCVCPU, cfg.ext_zihintpause, true),
|
2022-10-05 17:49:48 +03:00
|
|
|
DEFINE_PROP_BOOL("Zawrs", RISCVCPU, cfg.ext_zawrs, true),
|
2021-12-10 10:43:25 +03:00
|
|
|
DEFINE_PROP_BOOL("Zfh", RISCVCPU, cfg.ext_zfh, false),
|
2021-12-10 10:43:27 +03:00
|
|
|
DEFINE_PROP_BOOL("Zfhmin", RISCVCPU, cfg.ext_zfhmin, false),
|
2022-01-18 04:45:20 +03:00
|
|
|
DEFINE_PROP_BOOL("Zve32f", RISCVCPU, cfg.ext_zve32f, false),
|
2022-01-18 04:45:13 +03:00
|
|
|
DEFINE_PROP_BOOL("Zve64f", RISCVCPU, cfg.ext_zve64f, false),
|
2023-02-15 05:05:39 +03:00
|
|
|
DEFINE_PROP_BOOL("Zve64d", RISCVCPU, cfg.ext_zve64d, false),
|
2021-10-18 07:32:15 +03:00
|
|
|
DEFINE_PROP_BOOL("mmu", RISCVCPU, cfg.mmu, true),
|
|
|
|
DEFINE_PROP_BOOL("pmp", RISCVCPU, cfg.pmp, true),
|
2022-08-25 01:13:56 +03:00
|
|
|
DEFINE_PROP_BOOL("sstc", RISCVCPU, cfg.ext_sstc, true),
|
2021-10-18 07:32:15 +03:00
|
|
|
|
|
|
|
DEFINE_PROP_STRING("priv_spec", RISCVCPU, cfg.priv_spec),
|
2021-12-10 10:55:47 +03:00
|
|
|
DEFINE_PROP_STRING("vext_spec", RISCVCPU, cfg.vext_spec),
|
|
|
|
DEFINE_PROP_UINT16("vlen", RISCVCPU, cfg.vlen, 128),
|
|
|
|
DEFINE_PROP_UINT16("elen", RISCVCPU, cfg.elen, 64),
|
2021-10-18 07:32:15 +03:00
|
|
|
|
2023-02-24 07:08:52 +03:00
|
|
|
DEFINE_PROP_BOOL("svadu", RISCVCPU, cfg.ext_svadu, true),
|
|
|
|
|
2022-02-04 05:26:57 +03:00
|
|
|
DEFINE_PROP_BOOL("svinval", RISCVCPU, cfg.ext_svinval, false),
|
2022-02-04 05:26:56 +03:00
|
|
|
DEFINE_PROP_BOOL("svnapot", RISCVCPU, cfg.ext_svnapot, false),
|
2022-02-04 05:26:58 +03:00
|
|
|
DEFINE_PROP_BOOL("svpbmt", RISCVCPU, cfg.ext_svpbmt, false),
|
2022-02-04 05:26:56 +03:00
|
|
|
|
2021-12-16 08:18:44 +03:00
|
|
|
DEFINE_PROP_BOOL("zba", RISCVCPU, cfg.ext_zba, true),
|
|
|
|
DEFINE_PROP_BOOL("zbb", RISCVCPU, cfg.ext_zbb, true),
|
|
|
|
DEFINE_PROP_BOOL("zbc", RISCVCPU, cfg.ext_zbc, true),
|
2022-04-23 05:35:10 +03:00
|
|
|
DEFINE_PROP_BOOL("zbkb", RISCVCPU, cfg.ext_zbkb, false),
|
|
|
|
DEFINE_PROP_BOOL("zbkc", RISCVCPU, cfg.ext_zbkc, false),
|
|
|
|
DEFINE_PROP_BOOL("zbkx", RISCVCPU, cfg.ext_zbkx, false),
|
2021-12-16 08:18:44 +03:00
|
|
|
DEFINE_PROP_BOOL("zbs", RISCVCPU, cfg.ext_zbs, true),
|
2022-04-23 05:35:10 +03:00
|
|
|
DEFINE_PROP_BOOL("zk", RISCVCPU, cfg.ext_zk, false),
|
|
|
|
DEFINE_PROP_BOOL("zkn", RISCVCPU, cfg.ext_zkn, false),
|
|
|
|
DEFINE_PROP_BOOL("zknd", RISCVCPU, cfg.ext_zknd, false),
|
|
|
|
DEFINE_PROP_BOOL("zkne", RISCVCPU, cfg.ext_zkne, false),
|
|
|
|
DEFINE_PROP_BOOL("zknh", RISCVCPU, cfg.ext_zknh, false),
|
|
|
|
DEFINE_PROP_BOOL("zkr", RISCVCPU, cfg.ext_zkr, false),
|
|
|
|
DEFINE_PROP_BOOL("zks", RISCVCPU, cfg.ext_zks, false),
|
|
|
|
DEFINE_PROP_BOOL("zksed", RISCVCPU, cfg.ext_zksed, false),
|
|
|
|
DEFINE_PROP_BOOL("zksh", RISCVCPU, cfg.ext_zksh, false),
|
|
|
|
DEFINE_PROP_BOOL("zkt", RISCVCPU, cfg.ext_zkt, false),
|
2022-01-06 16:40:20 +03:00
|
|
|
|
2022-02-11 07:39:20 +03:00
|
|
|
DEFINE_PROP_BOOL("zdinx", RISCVCPU, cfg.ext_zdinx, false),
|
|
|
|
DEFINE_PROP_BOOL("zfinx", RISCVCPU, cfg.ext_zfinx, false),
|
|
|
|
DEFINE_PROP_BOOL("zhinx", RISCVCPU, cfg.ext_zhinx, false),
|
|
|
|
DEFINE_PROP_BOOL("zhinxmin", RISCVCPU, cfg.ext_zhinxmin, false),
|
|
|
|
|
2023-02-24 16:25:35 +03:00
|
|
|
DEFINE_PROP_BOOL("zicbom", RISCVCPU, cfg.ext_icbom, true),
|
|
|
|
DEFINE_PROP_UINT16("cbom_blocksize", RISCVCPU, cfg.cbom_blocksize, 64),
|
2023-02-24 16:25:34 +03:00
|
|
|
DEFINE_PROP_BOOL("zicboz", RISCVCPU, cfg.ext_icboz, true),
|
|
|
|
DEFINE_PROP_UINT16("cboz_blocksize", RISCVCPU, cfg.cboz_blocksize, 64),
|
|
|
|
|
2022-07-10 13:15:46 +03:00
|
|
|
DEFINE_PROP_BOOL("zmmul", RISCVCPU, cfg.ext_zmmul, false),
|
|
|
|
|
2022-02-02 03:52:48 +03:00
|
|
|
/* Vendor-specific custom extensions */
|
2023-01-31 23:20:02 +03:00
|
|
|
DEFINE_PROP_BOOL("xtheadba", RISCVCPU, cfg.ext_xtheadba, false),
|
2023-01-31 23:20:03 +03:00
|
|
|
DEFINE_PROP_BOOL("xtheadbb", RISCVCPU, cfg.ext_xtheadbb, false),
|
2023-01-31 23:20:04 +03:00
|
|
|
DEFINE_PROP_BOOL("xtheadbs", RISCVCPU, cfg.ext_xtheadbs, false),
|
2023-01-31 23:20:00 +03:00
|
|
|
DEFINE_PROP_BOOL("xtheadcmo", RISCVCPU, cfg.ext_xtheadcmo, false),
|
2023-01-31 23:20:05 +03:00
|
|
|
DEFINE_PROP_BOOL("xtheadcondmov", RISCVCPU, cfg.ext_xtheadcondmov, false),
|
2023-01-31 23:20:09 +03:00
|
|
|
DEFINE_PROP_BOOL("xtheadfmemidx", RISCVCPU, cfg.ext_xtheadfmemidx, false),
|
2023-01-31 23:20:12 +03:00
|
|
|
DEFINE_PROP_BOOL("xtheadfmv", RISCVCPU, cfg.ext_xtheadfmv, false),
|
2023-01-31 23:20:06 +03:00
|
|
|
DEFINE_PROP_BOOL("xtheadmac", RISCVCPU, cfg.ext_xtheadmac, false),
|
2023-01-31 23:20:08 +03:00
|
|
|
DEFINE_PROP_BOOL("xtheadmemidx", RISCVCPU, cfg.ext_xtheadmemidx, false),
|
2023-01-31 23:20:07 +03:00
|
|
|
DEFINE_PROP_BOOL("xtheadmempair", RISCVCPU, cfg.ext_xtheadmempair, false),
|
2023-01-31 23:20:01 +03:00
|
|
|
DEFINE_PROP_BOOL("xtheadsync", RISCVCPU, cfg.ext_xtheadsync, false),
|
2022-02-02 03:52:48 +03:00
|
|
|
DEFINE_PROP_BOOL("xventanacondops", RISCVCPU, cfg.ext_XVentanaCondOps, false),
|
|
|
|
|
2022-01-06 16:40:20 +03:00
|
|
|
/* These are experimental so mark with 'x-' */
|
2023-02-21 12:10:09 +03:00
|
|
|
DEFINE_PROP_BOOL("x-zicond", RISCVCPU, cfg.ext_zicond, false),
|
2021-10-25 20:36:09 +03:00
|
|
|
DEFINE_PROP_BOOL("x-j", RISCVCPU, cfg.ext_j, false),
|
2021-09-02 03:40:10 +03:00
|
|
|
/* ePMP 0.9.3 */
|
2021-04-19 09:17:25 +03:00
|
|
|
DEFINE_PROP_BOOL("x-epmp", RISCVCPU, cfg.epmp, false),
|
2022-08-20 07:29:58 +03:00
|
|
|
DEFINE_PROP_BOOL("x-smaia", RISCVCPU, cfg.ext_smaia, false),
|
|
|
|
DEFINE_PROP_BOOL("x-ssaia", RISCVCPU, cfg.ext_ssaia, false),
|
2021-04-19 09:17:25 +03:00
|
|
|
|
2023-02-15 05:05:39 +03:00
|
|
|
DEFINE_PROP_BOOL("x-zvfh", RISCVCPU, cfg.ext_zvfh, false),
|
|
|
|
DEFINE_PROP_BOOL("x-zvfhmin", RISCVCPU, cfg.ext_zvfhmin, false),
|
|
|
|
|
2022-06-08 09:14:37 +03:00
|
|
|
DEFINE_PROP_END_OF_LIST(),
|
|
|
|
};
|
|
|
|
|
target/riscv/cpu: set cpu->cfg in register_cpu_props()
There is an informal contract between the cpu_init() functions and
riscv_cpu_realize(): if cpu->env.misa_ext is zero, assume that the
default settings were loaded via register_cpu_props() and do validations
to set env.misa_ext. If it's not zero, skip this whole process and
assume that the board somehow did everything.
At this moment, all SiFive CPUs are setting a non-zero misa_ext during
their cpu_init() and skipping a good chunk of riscv_cpu_realize(). This
causes problems when the code being skipped in riscv_cpu_realize()
contains fixes or assumptions that affects all CPUs, meaning that SiFive
CPUs are missing out.
To allow this code to not be skipped anymore, all the cpu->cfg.ext_*
attributes needs to be set during cpu_init() time. At this moment this
is being done in register_cpu_props(). The SiFive boards are setting
their own extensions during cpu_init() though, meaning that they don't
want all the defaults from register_cpu_props().
Let's move the contract between *_cpu_init() and riscv_cpu_realize() to
register_cpu_props(). Inside this function we'll check if
cpu->env.misa_ext was set and, if that's the case, set all relevant
cpu->cfg.ext_* attributes, and only that. Leave the 'misa_ext' = 0 case
as is today, i.e. loading all the defaults from riscv_cpu_extensions[].
register_cpu_props() can then be called by all the cpu_init() functions,
including the SiFive ones. This will make all CPUs behave more in line
with what riscv_cpu_realize() expects.
This will also make the cpu_init() functions even more alike, but at this
moment we would need some design changes in how we're initializing
extensions/attributes (e.g. some CPUs are setting cfg options after
register_cpu_props(), so we can't simply add the function to a common
post_init() hook) to make a common cpu_init() code across all CPUs.
Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Message-Id: <20230113175230.473975-2-dbarboza@ventanamicro.com>
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
2023-01-13 20:52:29 +03:00
|
|
|
/*
|
|
|
|
* Register CPU props based on env.misa_ext. If a non-zero
|
|
|
|
* value was set, register only the required cpu->cfg.ext_*
|
|
|
|
* properties and leave. env.misa_ext = 0 means that we want
|
|
|
|
* all the default properties to be registered.
|
|
|
|
*/
|
2023-03-03 16:12:48 +03:00
|
|
|
static void register_cpu_props(Object *obj)
|
2022-06-08 09:14:37 +03:00
|
|
|
{
|
2023-03-03 16:12:48 +03:00
|
|
|
RISCVCPU *cpu = RISCV_CPU(obj);
|
target/riscv/cpu: set cpu->cfg in register_cpu_props()
There is an informal contract between the cpu_init() functions and
riscv_cpu_realize(): if cpu->env.misa_ext is zero, assume that the
default settings were loaded via register_cpu_props() and do validations
to set env.misa_ext. If it's not zero, skip this whole process and
assume that the board somehow did everything.
At this moment, all SiFive CPUs are setting a non-zero misa_ext during
their cpu_init() and skipping a good chunk of riscv_cpu_realize(). This
causes problems when the code being skipped in riscv_cpu_realize()
contains fixes or assumptions that affects all CPUs, meaning that SiFive
CPUs are missing out.
To allow this code to not be skipped anymore, all the cpu->cfg.ext_*
attributes needs to be set during cpu_init() time. At this moment this
is being done in register_cpu_props(). The SiFive boards are setting
their own extensions during cpu_init() though, meaning that they don't
want all the defaults from register_cpu_props().
Let's move the contract between *_cpu_init() and riscv_cpu_realize() to
register_cpu_props(). Inside this function we'll check if
cpu->env.misa_ext was set and, if that's the case, set all relevant
cpu->cfg.ext_* attributes, and only that. Leave the 'misa_ext' = 0 case
as is today, i.e. loading all the defaults from riscv_cpu_extensions[].
register_cpu_props() can then be called by all the cpu_init() functions,
including the SiFive ones. This will make all CPUs behave more in line
with what riscv_cpu_realize() expects.
This will also make the cpu_init() functions even more alike, but at this
moment we would need some design changes in how we're initializing
extensions/attributes (e.g. some CPUs are setting cfg options after
register_cpu_props(), so we can't simply add the function to a common
post_init() hook) to make a common cpu_init() code across all CPUs.
Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Message-Id: <20230113175230.473975-2-dbarboza@ventanamicro.com>
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
2023-01-13 20:52:29 +03:00
|
|
|
uint32_t misa_ext = cpu->env.misa_ext;
|
2022-06-08 09:14:37 +03:00
|
|
|
Property *prop;
|
2023-03-03 16:12:48 +03:00
|
|
|
DeviceState *dev = DEVICE(obj);
|
2022-06-08 09:14:37 +03:00
|
|
|
|
target/riscv/cpu: set cpu->cfg in register_cpu_props()
There is an informal contract between the cpu_init() functions and
riscv_cpu_realize(): if cpu->env.misa_ext is zero, assume that the
default settings were loaded via register_cpu_props() and do validations
to set env.misa_ext. If it's not zero, skip this whole process and
assume that the board somehow did everything.
At this moment, all SiFive CPUs are setting a non-zero misa_ext during
their cpu_init() and skipping a good chunk of riscv_cpu_realize(). This
causes problems when the code being skipped in riscv_cpu_realize()
contains fixes or assumptions that affects all CPUs, meaning that SiFive
CPUs are missing out.
To allow this code to not be skipped anymore, all the cpu->cfg.ext_*
attributes needs to be set during cpu_init() time. At this moment this
is being done in register_cpu_props(). The SiFive boards are setting
their own extensions during cpu_init() though, meaning that they don't
want all the defaults from register_cpu_props().
Let's move the contract between *_cpu_init() and riscv_cpu_realize() to
register_cpu_props(). Inside this function we'll check if
cpu->env.misa_ext was set and, if that's the case, set all relevant
cpu->cfg.ext_* attributes, and only that. Leave the 'misa_ext' = 0 case
as is today, i.e. loading all the defaults from riscv_cpu_extensions[].
register_cpu_props() can then be called by all the cpu_init() functions,
including the SiFive ones. This will make all CPUs behave more in line
with what riscv_cpu_realize() expects.
This will also make the cpu_init() functions even more alike, but at this
moment we would need some design changes in how we're initializing
extensions/attributes (e.g. some CPUs are setting cfg options after
register_cpu_props(), so we can't simply add the function to a common
post_init() hook) to make a common cpu_init() code across all CPUs.
Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Reviewed-by: Alistair Francis <alistair.francis@wdc.com>
Message-Id: <20230113175230.473975-2-dbarboza@ventanamicro.com>
Signed-off-by: Alistair Francis <alistair.francis@wdc.com>
2023-01-13 20:52:29 +03:00
|
|
|
/*
|
|
|
|
* If misa_ext is not zero, set cfg properties now to
|
|
|
|
* allow them to be read during riscv_cpu_realize()
|
|
|
|
* later on.
|
|
|
|
*/
|
|
|
|
if (cpu->env.misa_ext != 0) {
|
|
|
|
cpu->cfg.ext_i = misa_ext & RVI;
|
|
|
|
cpu->cfg.ext_e = misa_ext & RVE;
|
|
|
|
cpu->cfg.ext_m = misa_ext & RVM;
|
|
|
|
cpu->cfg.ext_a = misa_ext & RVA;
|
|
|
|
cpu->cfg.ext_f = misa_ext & RVF;
|
|
|
|
cpu->cfg.ext_d = misa_ext & RVD;
|
|
|
|
cpu->cfg.ext_v = misa_ext & RVV;
|
|
|
|
cpu->cfg.ext_c = misa_ext & RVC;
|
|
|
|
cpu->cfg.ext_s = misa_ext & RVS;
|
|
|
|
cpu->cfg.ext_u = misa_ext & RVU;
|
|
|
|
cpu->cfg.ext_h = misa_ext & RVH;
|
|
|
|
cpu->cfg.ext_j = misa_ext & RVJ;
|
|
|
|
|
|
|
|
/*
|
|
|
|
* We don't want to set the default riscv_cpu_extensions
|
|
|
|
* in this case.
|
|
|
|
*/
|
|
|
|
return;
|
|
|
|
}
|
|
|
|
|
2022-06-08 09:14:37 +03:00
|
|
|
for (prop = riscv_cpu_extensions; prop && prop->name; prop++) {
|
|
|
|
qdev_property_add_static(dev, prop);
|
|
|
|
}
|
riscv: Allow user to set the satp mode
RISC-V specifies multiple sizes for addressable memory and Linux probes for
the machine's support at startup via the satp CSR register (done in
csr.c:validate_vm).
As per the specification, sv64 must support sv57, which in turn must
support sv48...etc. So we can restrict machine support by simply setting the
"highest" supported mode and the bare mode is always supported.
You can set the satp mode using the new properties "sv32", "sv39", "sv48",
"sv57" and "sv64" as follows:
-cpu rv64,sv57=on # Linux will boot using sv57 scheme
-cpu rv64,sv39=on # Linux will boot using sv39 scheme
-cpu rv64,sv57=off # Linux will boot using sv48 scheme
-cpu rv64 # Linux will boot using sv57 scheme by default
We take the highest level set by the user:
-cpu rv64,sv48=on,sv57=on # Linux will boot using sv57 scheme
We make sure that invalid configurations are rejected:
-cpu rv64,sv39=off,sv48=on # sv39 must be supported if higher modes are
# enabled
We accept "redundant" configurations:
-cpu rv64,sv48=on,sv57=off # Linux will boot using sv48 scheme
And contradictory configurations:
-cpu rv64,sv48=on,sv48=off # Linux will boot using sv39 scheme
Co-Developed-by: Ludovic Henry <ludovic@rivosinc.com>
Signed-off-by: Ludovic Henry <ludovic@rivosinc.com>
Signed-off-by: Alexandre Ghiti <alexghiti@rivosinc.com>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
Reviewed-by: Bin Meng <bmeng@tinylab.org>
Acked-by: Alistair Francis <alistair.francis@wdc.com>
Reviewed-by: Frank Chang <frank.chang@sifive.com>
Message-ID: <20230303131252.892893-4-alexghiti@rivosinc.com>
Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
2023-03-03 16:12:50 +03:00
|
|
|
|
|
|
|
#ifndef CONFIG_USER_ONLY
|
|
|
|
riscv_add_satp_mode_properties(obj);
|
|
|
|
#endif
|
2022-06-08 09:14:37 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
static Property riscv_cpu_properties[] = {
|
|
|
|
DEFINE_PROP_BOOL("debug", RISCVCPU, cfg.debug, true),
|
|
|
|
|
|
|
|
DEFINE_PROP_UINT32("mvendorid", RISCVCPU, cfg.mvendorid, 0),
|
|
|
|
DEFINE_PROP_UINT64("marchid", RISCVCPU, cfg.marchid, RISCV_CPU_MARCHID),
|
|
|
|
DEFINE_PROP_UINT64("mimpid", RISCVCPU, cfg.mimpid, RISCV_CPU_MIMPID),
|
|
|
|
|
2022-09-14 13:11:06 +03:00
|
|
|
#ifndef CONFIG_USER_ONLY
|
|
|
|
DEFINE_PROP_UINT64("resetvec", RISCVCPU, env.resetvec, DEFAULT_RSTVEC),
|
|
|
|
#endif
|
2022-05-10 14:29:08 +03:00
|
|
|
|
|
|
|
DEFINE_PROP_BOOL("short-isa-string", RISCVCPU, cfg.short_isa_string, false),
|
2022-06-06 09:16:56 +03:00
|
|
|
|
|
|
|
DEFINE_PROP_BOOL("rvv_ta_all_1s", RISCVCPU, cfg.rvv_ta_all_1s, false),
|
2022-06-20 09:51:11 +03:00
|
|
|
DEFINE_PROP_BOOL("rvv_ma_all_1s", RISCVCPU, cfg.rvv_ma_all_1s, false),
|
target/riscv: allow MISA writes as experimental
At this moment, and apparently since ever, we have no way of enabling
RISCV_FEATURE_MISA. This means that all the code from write_misa(), all
the nuts and bolts that handles how to properly write this CSR, has
always been a no-op as well because write_misa() will always exit
earlier.
This seems to be benign in the majority of cases. Booting an Ubuntu
'virt' guest and logging all the calls to 'write_misa' shows that no
writes to MISA CSR was attempted. Writing MISA, i.e. enabling/disabling
RISC-V extensions after the machine is powered on, seems to be a niche
use.
After discussions in the mailing list, most notably in [1], we reached
the consensus that this code is not suited to be exposed to users
because it's not well tested, but at the same time removing it is a bit
extreme because we would like to fix it, and it's easier to do so with
the code available to use instead of fetching it from git log.
The approach taken here is to get rid of RISCV_FEATURE_MISA altogether
and use a new experimental flag called x-misa-w. The default value is
false, meaning that we're keeping the existing behavior of doing nothing
if a write_misa() is attempted. As with any existing experimental flag,
x-misa-w is also a temporary flag that we need to remove once we fix
write_misa().
[1] https://lists.gnu.org/archive/html/qemu-devel/2023-02/msg05092.html
Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Reviewed-by: Weiwei Li <liweiwei@iscas.ac.cn>
Reviewed-by: Andrew Jones <ajones@ventanamicro.com>
Reviewed-by: Bin Meng <bmeng@tinylab.org>
Reviewed-by: Weiwei Li<liweiwei@iscas.ac.cn>
Reviewed-by: LIU Zhiwei <zhiwei_liu@linux.alibaba.com>
Message-ID: <20230222185205.355361-4-dbarboza@ventanamicro.com>
Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
2023-02-22 21:51:58 +03:00
|
|
|
|
|
|
|
/*
|
|
|
|
* write_misa() is marked as experimental for now so mark
|
|
|
|
* it with -x and default to 'false'.
|
|
|
|
*/
|
|
|
|
DEFINE_PROP_BOOL("x-misa-w", RISCVCPU, cfg.misa_w, false),
|
2019-04-20 05:24:01 +03:00
|
|
|
DEFINE_PROP_END_OF_LIST(),
|
|
|
|
};
|
|
|
|
|
2021-01-06 23:41:41 +03:00
|
|
|
static gchar *riscv_gdb_arch_name(CPUState *cs)
|
|
|
|
{
|
|
|
|
RISCVCPU *cpu = RISCV_CPU(cs);
|
|
|
|
CPURISCVState *env = &cpu->env;
|
|
|
|
|
2021-10-20 06:16:58 +03:00
|
|
|
switch (riscv_cpu_mxl(env)) {
|
|
|
|
case MXL_RV32:
|
2021-01-06 23:41:41 +03:00
|
|
|
return g_strdup("riscv:rv32");
|
2021-10-20 06:16:58 +03:00
|
|
|
case MXL_RV64:
|
2022-01-07 00:00:57 +03:00
|
|
|
case MXL_RV128:
|
2021-01-06 23:41:41 +03:00
|
|
|
return g_strdup("riscv:rv64");
|
2021-10-20 06:16:58 +03:00
|
|
|
default:
|
|
|
|
g_assert_not_reached();
|
2021-01-06 23:41:41 +03:00
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2021-01-16 08:41:22 +03:00
|
|
|
static const char *riscv_gdb_get_dynamic_xml(CPUState *cs, const char *xmlname)
|
|
|
|
{
|
|
|
|
RISCVCPU *cpu = RISCV_CPU(cs);
|
|
|
|
|
|
|
|
if (strcmp(xmlname, "riscv-csr.xml") == 0) {
|
|
|
|
return cpu->dyn_csr_xml;
|
2021-12-10 10:56:54 +03:00
|
|
|
} else if (strcmp(xmlname, "riscv-vector.xml") == 0) {
|
|
|
|
return cpu->dyn_vreg_xml;
|
2021-01-16 08:41:22 +03:00
|
|
|
}
|
|
|
|
|
|
|
|
return NULL;
|
|
|
|
}
|
|
|
|
|
2021-05-17 13:51:31 +03:00
|
|
|
#ifndef CONFIG_USER_ONLY
|
2023-03-03 09:50:54 +03:00
|
|
|
static int64_t riscv_get_arch_id(CPUState *cs)
|
|
|
|
{
|
|
|
|
RISCVCPU *cpu = RISCV_CPU(cs);
|
|
|
|
|
|
|
|
return cpu->env.mhartid;
|
|
|
|
}
|
|
|
|
|
2021-05-17 13:51:31 +03:00
|
|
|
#include "hw/core/sysemu-cpu-ops.h"
|
|
|
|
|
|
|
|
static const struct SysemuCPUOps riscv_sysemu_ops = {
|
2021-05-17 13:51:37 +03:00
|
|
|
.get_phys_page_debug = riscv_cpu_get_phys_page_debug,
|
2021-05-17 13:51:35 +03:00
|
|
|
.write_elf64_note = riscv_cpu_write_elf64_note,
|
|
|
|
.write_elf32_note = riscv_cpu_write_elf32_note,
|
2021-05-17 13:51:32 +03:00
|
|
|
.legacy_vmsd = &vmstate_riscv_cpu,
|
2021-05-17 13:51:31 +03:00
|
|
|
};
|
|
|
|
#endif
|
|
|
|
|
2021-02-04 19:39:23 +03:00
|
|
|
#include "hw/core/tcg-cpu-ops.h"
|
|
|
|
|
2021-02-28 02:21:17 +03:00
|
|
|
static const struct TCGCPUOps riscv_tcg_ops = {
|
2021-02-04 19:39:23 +03:00
|
|
|
.initialize = riscv_translate_init,
|
|
|
|
.synchronize_from_tb = riscv_cpu_synchronize_from_tb,
|
2022-10-24 13:49:27 +03:00
|
|
|
.restore_state_to_opc = riscv_restore_state_to_opc,
|
2021-02-04 19:39:23 +03:00
|
|
|
|
|
|
|
#ifndef CONFIG_USER_ONLY
|
2021-09-15 06:46:38 +03:00
|
|
|
.tlb_fill = riscv_cpu_tlb_fill,
|
2021-09-11 19:54:28 +03:00
|
|
|
.cpu_exec_interrupt = riscv_cpu_exec_interrupt,
|
2021-02-04 19:39:23 +03:00
|
|
|
.do_interrupt = riscv_cpu_do_interrupt,
|
|
|
|
.do_transaction_failed = riscv_cpu_do_transaction_failed,
|
|
|
|
.do_unaligned_access = riscv_cpu_do_unaligned_access,
|
2022-04-21 03:33:19 +03:00
|
|
|
.debug_excp_handler = riscv_cpu_debug_excp_handler,
|
|
|
|
.debug_check_breakpoint = riscv_cpu_debug_check_breakpoint,
|
|
|
|
.debug_check_watchpoint = riscv_cpu_debug_check_watchpoint,
|
2021-02-04 19:39:23 +03:00
|
|
|
#endif /* !CONFIG_USER_ONLY */
|
|
|
|
};
|
|
|
|
|
2018-03-02 15:31:10 +03:00
|
|
|
static void riscv_cpu_class_init(ObjectClass *c, void *data)
|
|
|
|
{
|
|
|
|
RISCVCPUClass *mcc = RISCV_CPU_CLASS(c);
|
|
|
|
CPUClass *cc = CPU_CLASS(c);
|
|
|
|
DeviceClass *dc = DEVICE_CLASS(c);
|
2022-11-24 14:50:17 +03:00
|
|
|
ResettableClass *rc = RESETTABLE_CLASS(c);
|
2018-03-02 15:31:10 +03:00
|
|
|
|
2018-11-26 06:20:38 +03:00
|
|
|
device_class_set_parent_realize(dc, riscv_cpu_realize,
|
|
|
|
&mcc->parent_realize);
|
2018-03-02 15:31:10 +03:00
|
|
|
|
2022-11-24 14:50:17 +03:00
|
|
|
resettable_class_set_parent_phases(rc, NULL, riscv_cpu_reset_hold, NULL,
|
|
|
|
&mcc->parent_phases);
|
2018-03-02 15:31:10 +03:00
|
|
|
|
|
|
|
cc->class_by_name = riscv_cpu_class_by_name;
|
|
|
|
cc->has_work = riscv_cpu_has_work;
|
|
|
|
cc->dump_state = riscv_cpu_dump_state;
|
|
|
|
cc->set_pc = riscv_cpu_set_pc;
|
2022-09-30 20:31:21 +03:00
|
|
|
cc->get_pc = riscv_cpu_get_pc;
|
2018-03-02 15:31:10 +03:00
|
|
|
cc->gdb_read_register = riscv_cpu_gdb_read_register;
|
|
|
|
cc->gdb_write_register = riscv_cpu_gdb_write_register;
|
2019-03-15 13:26:59 +03:00
|
|
|
cc->gdb_num_core_regs = 33;
|
2018-03-02 15:31:10 +03:00
|
|
|
cc->gdb_stop_before_watchpoint = true;
|
|
|
|
cc->disas_set_info = riscv_cpu_disas_set_info;
|
2019-04-02 13:12:38 +03:00
|
|
|
#ifndef CONFIG_USER_ONLY
|
2021-05-17 13:51:31 +03:00
|
|
|
cc->sysemu_ops = &riscv_sysemu_ops;
|
2023-03-03 09:50:54 +03:00
|
|
|
cc->get_arch_id = riscv_get_arch_id;
|
2018-03-02 15:31:10 +03:00
|
|
|
#endif
|
2021-01-06 23:41:41 +03:00
|
|
|
cc->gdb_arch_name = riscv_gdb_arch_name;
|
2021-01-16 08:41:22 +03:00
|
|
|
cc->gdb_get_dynamic_xml = riscv_gdb_get_dynamic_xml;
|
2021-02-04 19:39:23 +03:00
|
|
|
cc->tcg_ops = &riscv_tcg_ops;
|
2021-02-04 19:39:10 +03:00
|
|
|
|
2020-01-10 18:30:32 +03:00
|
|
|
device_class_set_props(dc, riscv_cpu_properties);
|
2018-03-02 15:31:10 +03:00
|
|
|
}
|
|
|
|
|
2022-03-29 22:56:57 +03:00
|
|
|
static void riscv_isa_string_ext(RISCVCPU *cpu, char **isa_str, int max_str_len)
|
|
|
|
{
|
|
|
|
char *old = *isa_str;
|
|
|
|
char *new = *isa_str;
|
|
|
|
int i;
|
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE(isa_edata_arr); i++) {
|
2022-06-30 09:11:50 +03:00
|
|
|
if (isa_edata_arr[i].multi_letter &&
|
|
|
|
isa_ext_is_enabled(cpu, &isa_edata_arr[i])) {
|
2022-03-29 22:56:57 +03:00
|
|
|
new = g_strconcat(old, "_", isa_edata_arr[i].name, NULL);
|
|
|
|
g_free(old);
|
|
|
|
old = new;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
*isa_str = new;
|
|
|
|
}
|
|
|
|
|
2018-03-02 15:31:10 +03:00
|
|
|
char *riscv_isa_string(RISCVCPU *cpu)
|
|
|
|
{
|
|
|
|
int i;
|
2022-03-28 16:11:23 +03:00
|
|
|
const size_t maxlen = sizeof("rv128") + sizeof(riscv_single_letter_exts);
|
2018-03-20 00:18:49 +03:00
|
|
|
char *isa_str = g_new(char, maxlen);
|
|
|
|
char *p = isa_str + snprintf(isa_str, maxlen, "rv%d", TARGET_LONG_BITS);
|
2022-03-28 16:11:23 +03:00
|
|
|
for (i = 0; i < sizeof(riscv_single_letter_exts) - 1; i++) {
|
|
|
|
if (cpu->env.misa_ext & RV(riscv_single_letter_exts[i])) {
|
|
|
|
*p++ = qemu_tolower(riscv_single_letter_exts[i]);
|
2018-03-02 15:31:10 +03:00
|
|
|
}
|
|
|
|
}
|
2018-03-20 00:18:49 +03:00
|
|
|
*p = '\0';
|
2022-05-10 14:29:08 +03:00
|
|
|
if (!cpu->cfg.short_isa_string) {
|
|
|
|
riscv_isa_string_ext(cpu, &isa_str, maxlen);
|
|
|
|
}
|
2018-03-20 00:18:49 +03:00
|
|
|
return isa_str;
|
2018-03-02 15:31:10 +03:00
|
|
|
}
|
|
|
|
|
2018-03-09 01:12:31 +03:00
|
|
|
static gint riscv_cpu_list_compare(gconstpointer a, gconstpointer b)
|
2018-03-02 15:31:10 +03:00
|
|
|
{
|
2018-03-09 01:12:31 +03:00
|
|
|
ObjectClass *class_a = (ObjectClass *)a;
|
|
|
|
ObjectClass *class_b = (ObjectClass *)b;
|
|
|
|
const char *name_a, *name_b;
|
2018-03-02 15:31:10 +03:00
|
|
|
|
2018-03-09 01:12:31 +03:00
|
|
|
name_a = object_class_get_name(class_a);
|
|
|
|
name_b = object_class_get_name(class_b);
|
|
|
|
return strcmp(name_a, name_b);
|
2018-03-02 15:31:10 +03:00
|
|
|
}
|
|
|
|
|
2018-03-09 01:12:31 +03:00
|
|
|
static void riscv_cpu_list_entry(gpointer data, gpointer user_data)
|
2018-03-02 15:31:10 +03:00
|
|
|
{
|
2018-03-09 01:12:31 +03:00
|
|
|
const char *typename = object_class_get_name(OBJECT_CLASS(data));
|
|
|
|
int len = strlen(typename) - strlen(RISCV_CPU_TYPE_SUFFIX);
|
2018-03-02 15:31:10 +03:00
|
|
|
|
2019-04-17 22:17:57 +03:00
|
|
|
qemu_printf("%.*s\n", len, typename);
|
2018-03-09 01:12:31 +03:00
|
|
|
}
|
2018-03-02 15:31:10 +03:00
|
|
|
|
2019-04-17 22:17:57 +03:00
|
|
|
void riscv_cpu_list(void)
|
2018-03-09 01:12:31 +03:00
|
|
|
{
|
|
|
|
GSList *list;
|
|
|
|
|
|
|
|
list = object_class_get_list(TYPE_RISCV_CPU, false);
|
|
|
|
list = g_slist_sort(list, riscv_cpu_list_compare);
|
2019-04-17 22:17:57 +03:00
|
|
|
g_slist_foreach(list, riscv_cpu_list_entry, NULL);
|
2018-03-09 01:12:31 +03:00
|
|
|
g_slist_free(list);
|
2018-03-02 15:31:10 +03:00
|
|
|
}
|
|
|
|
|
2018-03-09 01:12:31 +03:00
|
|
|
#define DEFINE_CPU(type_name, initfn) \
|
|
|
|
{ \
|
|
|
|
.name = type_name, \
|
|
|
|
.parent = TYPE_RISCV_CPU, \
|
|
|
|
.instance_init = initfn \
|
|
|
|
}
|
|
|
|
|
|
|
|
static const TypeInfo riscv_cpu_type_infos[] = {
|
|
|
|
{
|
|
|
|
.name = TYPE_RISCV_CPU,
|
|
|
|
.parent = TYPE_CPU,
|
|
|
|
.instance_size = sizeof(RISCVCPU),
|
2020-09-16 03:46:37 +03:00
|
|
|
.instance_align = __alignof__(RISCVCPU),
|
2018-03-09 01:12:31 +03:00
|
|
|
.instance_init = riscv_cpu_init,
|
|
|
|
.abstract = true,
|
|
|
|
.class_size = sizeof(RISCVCPUClass),
|
|
|
|
.class_init = riscv_cpu_class_init,
|
|
|
|
},
|
|
|
|
DEFINE_CPU(TYPE_RISCV_CPU_ANY, riscv_any_cpu_init),
|
2022-01-12 11:13:25 +03:00
|
|
|
#if defined(CONFIG_KVM)
|
|
|
|
DEFINE_CPU(TYPE_RISCV_CPU_HOST, riscv_host_cpu_init),
|
|
|
|
#endif
|
2018-03-09 01:12:31 +03:00
|
|
|
#if defined(TARGET_RISCV32)
|
2020-12-16 21:23:05 +03:00
|
|
|
DEFINE_CPU(TYPE_RISCV_CPU_BASE32, rv32_base_cpu_init),
|
2020-06-16 03:50:37 +03:00
|
|
|
DEFINE_CPU(TYPE_RISCV_CPU_IBEX, rv32_ibex_cpu_init),
|
2020-12-16 21:22:54 +03:00
|
|
|
DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E31, rv32_sifive_e_cpu_init),
|
2020-06-11 04:08:49 +03:00
|
|
|
DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E34, rv32_imafcu_nommu_cpu_init),
|
2020-12-16 21:22:54 +03:00
|
|
|
DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_U34, rv32_sifive_u_cpu_init),
|
2018-03-09 01:12:31 +03:00
|
|
|
#elif defined(TARGET_RISCV64)
|
2020-12-16 21:23:05 +03:00
|
|
|
DEFINE_CPU(TYPE_RISCV_CPU_BASE64, rv64_base_cpu_init),
|
2020-12-16 21:22:54 +03:00
|
|
|
DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_E51, rv64_sifive_e_cpu_init),
|
|
|
|
DEFINE_CPU(TYPE_RISCV_CPU_SIFIVE_U54, rv64_sifive_u_cpu_init),
|
2021-04-01 21:14:54 +03:00
|
|
|
DEFINE_CPU(TYPE_RISCV_CPU_SHAKTI_C, rv64_sifive_u_cpu_init),
|
2023-01-31 23:20:11 +03:00
|
|
|
DEFINE_CPU(TYPE_RISCV_CPU_THEAD_C906, rv64_thead_c906_cpu_init),
|
2022-01-07 00:00:57 +03:00
|
|
|
DEFINE_CPU(TYPE_RISCV_CPU_BASE128, rv128_base_cpu_init),
|
2018-03-09 01:12:31 +03:00
|
|
|
#endif
|
|
|
|
};
|
|
|
|
|
|
|
|
DEFINE_TYPES(riscv_cpu_type_infos)
|