Fifth RISC-V PR for QEMU 7.1
* Fix register zero guarding for auipc and lui * Ensure bins (mtval) is set correctly * Minimize the calls to decode_save_opc * Guard against PMP ranges with a negative size * Implement mcountinhibit CSR * Add support for hpmcounters/hpmevents * Improve PMU implenentation * Support mcycle/minstret write operation * Fixup MSECCFG minimum priv check * Ibex (OpenTitan) fixup priv version * Fix bug resulting in always using latest priv spec * Reduce FDT address alignment constraints * Set minumum priv spec version for mcountinhibit * AIA update to v0.3 of the spec -----BEGIN PGP SIGNATURE----- iQEzBAABCAAdFiEE9sSsRtSTSGjTuM6PIeENKd+XcFQFAmLA3r8ACgkQIeENKd+X cFQdFQf6A63mocJxSc0vqMTBNULwgcUKbRbnkazbFS4vtbo/YXioCGaHA8c8trKj HbZfJv64phOThj7Y8ifLozENjnHX7dHbspPOcWIK9yalvKLA4EB4+OI7LisoL1vg H4E+9nXSzskaCmJgwSM6WlS0Vf89VxL0CoBb3XqJocSaajstg1XpqrR9anTZlUhl N712cLze+bOxBHTdjtC5Kxuxj+zmNvcMmuhldIJRdPCW8P5v2yccNVc6+hrE3WUX 9jHGMthS4qC5oVhok14/tPoyL0QTZpU2DXrJPFGUigOvUHoMBfQ3Qhulx3/rGLZv 4SdTD9ASrNWJfa+eyHAPNw//5NxTYA== =N7VN -----END PGP SIGNATURE----- Merge tag 'pull-riscv-to-apply-20220703-1' of github.com:alistair23/qemu into staging Fifth RISC-V PR for QEMU 7.1 * Fix register zero guarding for auipc and lui * Ensure bins (mtval) is set correctly * Minimize the calls to decode_save_opc * Guard against PMP ranges with a negative size * Implement mcountinhibit CSR * Add support for hpmcounters/hpmevents * Improve PMU implenentation * Support mcycle/minstret write operation * Fixup MSECCFG minimum priv check * Ibex (OpenTitan) fixup priv version * Fix bug resulting in always using latest priv spec * Reduce FDT address alignment constraints * Set minumum priv spec version for mcountinhibit * AIA update to v0.3 of the spec # -----BEGIN PGP SIGNATURE----- # # iQEzBAABCAAdFiEE9sSsRtSTSGjTuM6PIeENKd+XcFQFAmLA3r8ACgkQIeENKd+X # cFQdFQf6A63mocJxSc0vqMTBNULwgcUKbRbnkazbFS4vtbo/YXioCGaHA8c8trKj # HbZfJv64phOThj7Y8ifLozENjnHX7dHbspPOcWIK9yalvKLA4EB4+OI7LisoL1vg # H4E+9nXSzskaCmJgwSM6WlS0Vf89VxL0CoBb3XqJocSaajstg1XpqrR9anTZlUhl # N712cLze+bOxBHTdjtC5Kxuxj+zmNvcMmuhldIJRdPCW8P5v2yccNVc6+hrE3WUX # 9jHGMthS4qC5oVhok14/tPoyL0QTZpU2DXrJPFGUigOvUHoMBfQ3Qhulx3/rGLZv # 4SdTD9ASrNWJfa+eyHAPNw//5NxTYA== # =N7VN # -----END PGP SIGNATURE----- # gpg: Signature made Sun 03 Jul 2022 05:41:43 AM +0530 # gpg: using RSA key F6C4AC46D4934868D3B8CE8F21E10D29DF977054 # gpg: Good signature from "Alistair Francis <alistair@alistair23.me>" [undefined] # gpg: WARNING: This key is not certified with a trusted signature! # gpg: There is no indication that the signature belongs to the owner. # Primary key fingerprint: F6C4 AC46 D493 4868 D3B8 CE8F 21E1 0D29 DF97 7054 * tag 'pull-riscv-to-apply-20220703-1' of github.com:alistair23/qemu: target/riscv: Update default priority table for local interrupts target/riscv: Remove CSRs that set/clear an IMSIC interrupt file bits target/riscv: Set minumum priv spec version for mcountinhibit hw/riscv: boot: Reduce FDT address alignment constraints target/riscv: Don't force update priv spec version to latest target/riscv: Ibex: Support priv version 1.11 target/riscv: Fixup MSECCFG minimum priv check target/riscv: Support mcycle/minstret write operation target/riscv: Add support for hpmcounters/hpmevents target/riscv: Implement mcountinhibit CSR target/riscv: pmu: Make number of counters configurable target/riscv: pmu: Rename the counters extension to pmu target/riscv: Implement PMU CSR predicate function for S-mode target/riscv: Fix PMU CSR predicate function target/riscv/pmp: guard against PMP ranges with a negative size target/riscv: Minimize the calls to decode_save_opc target/riscv: Remove generate_exception_mtval target/riscv: Set env->bins in gen_exception_illegal target/riscv: Remove condition guarding register zero for auipc and lui Signed-off-by: Richard Henderson <richard.henderson@linaro.org>
This commit is contained in:
commit
e8e86b484e
@ -227,11 +227,11 @@ uint64_t riscv_load_fdt(hwaddr dram_base, uint64_t mem_size, void *fdt)
|
||||
/*
|
||||
* We should put fdt as far as possible to avoid kernel/initrd overwriting
|
||||
* its content. But it should be addressable by 32 bit system as well.
|
||||
* Thus, put it at an 16MB aligned address that less than fdt size from the
|
||||
* Thus, put it at an 2MB aligned address that less than fdt size from the
|
||||
* end of dram or 3GB whichever is lesser.
|
||||
*/
|
||||
temp = (dram_base < 3072 * MiB) ? MIN(dram_end, 3072 * MiB) : dram_end;
|
||||
fdt_addr = QEMU_ALIGN_DOWN(temp - fdtsize, 16 * MiB);
|
||||
fdt_addr = QEMU_ALIGN_DOWN(temp - fdtsize, 2 * MiB);
|
||||
|
||||
ret = fdt_pack(fdt);
|
||||
/* Should only fail if we've built a corrupted tree */
|
||||
|
@ -173,6 +173,8 @@ static void rv64_base_cpu_init(Object *obj)
|
||||
/* We set this in the realise function */
|
||||
set_misa(env, MXL_RV64, 0);
|
||||
register_cpu_props(DEVICE(obj));
|
||||
/* Set latest version of privileged specification */
|
||||
set_priv_version(env, PRIV_VERSION_1_12_0);
|
||||
}
|
||||
|
||||
static void rv64_sifive_u_cpu_init(Object *obj)
|
||||
@ -204,6 +206,8 @@ static void rv128_base_cpu_init(Object *obj)
|
||||
/* We set this in the realise function */
|
||||
set_misa(env, MXL_RV128, 0);
|
||||
register_cpu_props(DEVICE(obj));
|
||||
/* Set latest version of privileged specification */
|
||||
set_priv_version(env, PRIV_VERSION_1_12_0);
|
||||
}
|
||||
#else
|
||||
static void rv32_base_cpu_init(Object *obj)
|
||||
@ -212,6 +216,8 @@ static void rv32_base_cpu_init(Object *obj)
|
||||
/* We set this in the realise function */
|
||||
set_misa(env, MXL_RV32, 0);
|
||||
register_cpu_props(DEVICE(obj));
|
||||
/* Set latest version of privileged specification */
|
||||
set_priv_version(env, PRIV_VERSION_1_12_0);
|
||||
}
|
||||
|
||||
static void rv32_sifive_u_cpu_init(Object *obj)
|
||||
@ -237,7 +243,7 @@ static void rv32_ibex_cpu_init(Object *obj)
|
||||
RISCVCPU *cpu = RISCV_CPU(obj);
|
||||
|
||||
set_misa(env, MXL_RV32, RVI | RVM | RVC | RVU);
|
||||
set_priv_version(env, PRIV_VERSION_1_10_0);
|
||||
set_priv_version(env, PRIV_VERSION_1_11_0);
|
||||
cpu->cfg.mmu = false;
|
||||
cpu->cfg.epmp = true;
|
||||
}
|
||||
@ -524,7 +530,7 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
|
||||
CPURISCVState *env = &cpu->env;
|
||||
RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(dev);
|
||||
CPUClass *cc = CPU_CLASS(mcc);
|
||||
int priv_version = 0;
|
||||
int priv_version = -1;
|
||||
Error *local_err = NULL;
|
||||
|
||||
cpu_exec_realizefn(cs, &local_err);
|
||||
@ -548,10 +554,8 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp)
|
||||
}
|
||||
}
|
||||
|
||||
if (priv_version) {
|
||||
if (priv_version >= PRIV_VERSION_1_10_0) {
|
||||
set_priv_version(env, priv_version);
|
||||
} else if (!env->priv_ver) {
|
||||
set_priv_version(env, PRIV_VERSION_1_12_0);
|
||||
}
|
||||
|
||||
if (cpu->cfg.mmu) {
|
||||
@ -851,7 +855,6 @@ static void riscv_cpu_init(Object *obj)
|
||||
{
|
||||
RISCVCPU *cpu = RISCV_CPU(obj);
|
||||
|
||||
cpu->cfg.ext_counters = true;
|
||||
cpu->cfg.ext_ifencei = true;
|
||||
cpu->cfg.ext_icsr = true;
|
||||
cpu->cfg.mmu = true;
|
||||
@ -879,7 +882,7 @@ static Property riscv_cpu_extensions[] = {
|
||||
DEFINE_PROP_BOOL("u", RISCVCPU, cfg.ext_u, true),
|
||||
DEFINE_PROP_BOOL("v", RISCVCPU, cfg.ext_v, false),
|
||||
DEFINE_PROP_BOOL("h", RISCVCPU, cfg.ext_h, true),
|
||||
DEFINE_PROP_BOOL("Counters", RISCVCPU, cfg.ext_counters, true),
|
||||
DEFINE_PROP_UINT8("pmu-num", RISCVCPU, cfg.pmu_num, 16),
|
||||
DEFINE_PROP_BOOL("Zifencei", RISCVCPU, cfg.ext_ifencei, true),
|
||||
DEFINE_PROP_BOOL("Zicsr", RISCVCPU, cfg.ext_icsr, true),
|
||||
DEFINE_PROP_BOOL("Zfh", RISCVCPU, cfg.ext_zfh, false),
|
||||
|
@ -117,6 +117,8 @@ typedef struct CPUArchState CPURISCVState;
|
||||
#endif
|
||||
|
||||
#define RV_VLEN_MAX 1024
|
||||
#define RV_MAX_MHPMEVENTS 32
|
||||
#define RV_MAX_MHPMCOUNTERS 32
|
||||
|
||||
FIELD(VTYPE, VLMUL, 0, 3)
|
||||
FIELD(VTYPE, VSEW, 3, 3)
|
||||
@ -125,6 +127,18 @@ FIELD(VTYPE, VMA, 7, 1)
|
||||
FIELD(VTYPE, VEDIV, 8, 2)
|
||||
FIELD(VTYPE, RESERVED, 10, sizeof(target_ulong) * 8 - 11)
|
||||
|
||||
typedef struct PMUCTRState {
|
||||
/* Current value of a counter */
|
||||
target_ulong mhpmcounter_val;
|
||||
/* Current value of a counter in RV32*/
|
||||
target_ulong mhpmcounterh_val;
|
||||
/* Snapshot values of counter */
|
||||
target_ulong mhpmcounter_prev;
|
||||
/* Snapshort value of a counter in RV32 */
|
||||
target_ulong mhpmcounterh_prev;
|
||||
bool started;
|
||||
} PMUCTRState;
|
||||
|
||||
struct CPUArchState {
|
||||
target_ulong gpr[32];
|
||||
target_ulong gprh[32]; /* 64 top bits of the 128-bit registers */
|
||||
@ -275,6 +289,14 @@ struct CPUArchState {
|
||||
target_ulong scounteren;
|
||||
target_ulong mcounteren;
|
||||
|
||||
target_ulong mcountinhibit;
|
||||
|
||||
/* PMU counter state */
|
||||
PMUCTRState pmu_ctrs[RV_MAX_MHPMCOUNTERS];
|
||||
|
||||
/* PMU event selector configured values. First three are unused*/
|
||||
target_ulong mhpmevent_val[RV_MAX_MHPMEVENTS];
|
||||
|
||||
target_ulong sscratch;
|
||||
target_ulong mscratch;
|
||||
|
||||
@ -397,7 +419,6 @@ struct RISCVCPUConfig {
|
||||
bool ext_zksed;
|
||||
bool ext_zksh;
|
||||
bool ext_zkt;
|
||||
bool ext_counters;
|
||||
bool ext_ifencei;
|
||||
bool ext_icsr;
|
||||
bool ext_svinval;
|
||||
@ -421,6 +442,7 @@ struct RISCVCPUConfig {
|
||||
/* Vendor-specific custom extensions */
|
||||
bool ext_XVentanaCondOps;
|
||||
|
||||
uint8_t pmu_num;
|
||||
char *priv_spec;
|
||||
char *user_spec;
|
||||
char *bext_spec;
|
||||
|
@ -174,14 +174,8 @@
|
||||
#define CSR_MIREG 0x351
|
||||
|
||||
/* Machine-Level Interrupts (AIA) */
|
||||
#define CSR_MTOPI 0xfb0
|
||||
|
||||
/* Machine-Level IMSIC Interface (AIA) */
|
||||
#define CSR_MSETEIPNUM 0x358
|
||||
#define CSR_MCLREIPNUM 0x359
|
||||
#define CSR_MSETEIENUM 0x35a
|
||||
#define CSR_MCLREIENUM 0x35b
|
||||
#define CSR_MTOPEI 0x35c
|
||||
#define CSR_MTOPI 0xfb0
|
||||
|
||||
/* Virtual Interrupts for Supervisor Level (AIA) */
|
||||
#define CSR_MVIEN 0x308
|
||||
@ -221,14 +215,8 @@
|
||||
#define CSR_SIREG 0x151
|
||||
|
||||
/* Supervisor-Level Interrupts (AIA) */
|
||||
#define CSR_STOPI 0xdb0
|
||||
|
||||
/* Supervisor-Level IMSIC Interface (AIA) */
|
||||
#define CSR_SSETEIPNUM 0x158
|
||||
#define CSR_SCLREIPNUM 0x159
|
||||
#define CSR_SSETEIENUM 0x15a
|
||||
#define CSR_SCLREIENUM 0x15b
|
||||
#define CSR_STOPEI 0x15c
|
||||
#define CSR_STOPI 0xdb0
|
||||
|
||||
/* Supervisor-Level High-Half CSRs (AIA) */
|
||||
#define CSR_SIEH 0x114
|
||||
@ -279,14 +267,8 @@
|
||||
#define CSR_VSIREG 0x251
|
||||
|
||||
/* VS-Level Interrupts (H-extension with AIA) */
|
||||
#define CSR_VSTOPI 0xeb0
|
||||
|
||||
/* VS-Level IMSIC Interface (H-extension with AIA) */
|
||||
#define CSR_VSSETEIPNUM 0x258
|
||||
#define CSR_VSCLREIPNUM 0x259
|
||||
#define CSR_VSSETEIENUM 0x25a
|
||||
#define CSR_VSCLREIENUM 0x25b
|
||||
#define CSR_VSTOPEI 0x25c
|
||||
#define CSR_VSTOPI 0xeb0
|
||||
|
||||
/* Hypervisor and VS-Level High-Half CSRs (H-extension with AIA) */
|
||||
#define CSR_HIDELEGH 0x613
|
||||
@ -367,6 +349,10 @@
|
||||
#define CSR_MHPMCOUNTER29 0xb1d
|
||||
#define CSR_MHPMCOUNTER30 0xb1e
|
||||
#define CSR_MHPMCOUNTER31 0xb1f
|
||||
|
||||
/* Machine counter-inhibit register */
|
||||
#define CSR_MCOUNTINHIBIT 0x320
|
||||
|
||||
#define CSR_MHPMEVENT3 0x323
|
||||
#define CSR_MHPMEVENT4 0x324
|
||||
#define CSR_MHPMEVENT5 0x325
|
||||
@ -788,7 +774,7 @@ typedef enum RISCVException {
|
||||
#define IPRIO_IRQ_BITS 8
|
||||
#define IPRIO_MMAXIPRIO 255
|
||||
#define IPRIO_DEFAULT_UPPER 4
|
||||
#define IPRIO_DEFAULT_MIDDLE (IPRIO_DEFAULT_UPPER + 24)
|
||||
#define IPRIO_DEFAULT_MIDDLE (IPRIO_DEFAULT_UPPER + 12)
|
||||
#define IPRIO_DEFAULT_M IPRIO_DEFAULT_MIDDLE
|
||||
#define IPRIO_DEFAULT_S (IPRIO_DEFAULT_M + 3)
|
||||
#define IPRIO_DEFAULT_SGEXT (IPRIO_DEFAULT_S + 3)
|
||||
|
@ -168,17 +168,17 @@ void riscv_cpu_update_mask(CPURISCVState *env)
|
||||
* 14 "
|
||||
* 15 "
|
||||
* 16 "
|
||||
* 18 Debug/trace interrupt
|
||||
* 20 (Reserved interrupt)
|
||||
* 17 "
|
||||
* 18 "
|
||||
* 19 "
|
||||
* 20 "
|
||||
* 21 "
|
||||
* 22 "
|
||||
* 24 "
|
||||
* 26 "
|
||||
* 28 "
|
||||
* 30 (Reserved for standard reporting of bus or system errors)
|
||||
* 23 "
|
||||
*/
|
||||
|
||||
static const int hviprio_index2irq[] = {
|
||||
0, 1, 4, 5, 8, 13, 14, 15, 16, 18, 20, 22, 24, 26, 28, 30 };
|
||||
0, 1, 4, 5, 8, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23 };
|
||||
static const int hviprio_index2rdzero[] = {
|
||||
1, 0, 1, 0, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 };
|
||||
|
||||
@ -207,50 +207,60 @@ int riscv_cpu_hviprio_index2irq(int index, int *out_irq, int *out_rdzero)
|
||||
* Default |
|
||||
* Priority | Major Interrupt Numbers
|
||||
* ----------------------------------------------------------------
|
||||
* Highest | 63 (3f), 62 (3e), 31 (1f), 30 (1e), 61 (3d), 60 (3c),
|
||||
* | 59 (3b), 58 (3a), 29 (1d), 28 (1c), 57 (39), 56 (38),
|
||||
* | 55 (37), 54 (36), 27 (1b), 26 (1a), 53 (35), 52 (34),
|
||||
* | 51 (33), 50 (32), 25 (19), 24 (18), 49 (31), 48 (30)
|
||||
* Highest | 47, 23, 46, 45, 22, 44,
|
||||
* | 43, 21, 42, 41, 20, 40
|
||||
* |
|
||||
* | 11 (0b), 3 (03), 7 (07)
|
||||
* | 9 (09), 1 (01), 5 (05)
|
||||
* | 12 (0c)
|
||||
* | 10 (0a), 2 (02), 6 (06)
|
||||
* |
|
||||
* | 47 (2f), 46 (2e), 23 (17), 22 (16), 45 (2d), 44 (2c),
|
||||
* | 43 (2b), 42 (2a), 21 (15), 20 (14), 41 (29), 40 (28),
|
||||
* | 39 (27), 38 (26), 19 (13), 18 (12), 37 (25), 36 (24),
|
||||
* Lowest | 35 (23), 34 (22), 17 (11), 16 (10), 33 (21), 32 (20)
|
||||
* | 39, 19, 38, 37, 18, 36,
|
||||
* Lowest | 35, 17, 34, 33, 16, 32
|
||||
* ----------------------------------------------------------------
|
||||
*/
|
||||
static const uint8_t default_iprio[64] = {
|
||||
[63] = IPRIO_DEFAULT_UPPER,
|
||||
[62] = IPRIO_DEFAULT_UPPER + 1,
|
||||
[31] = IPRIO_DEFAULT_UPPER + 2,
|
||||
[30] = IPRIO_DEFAULT_UPPER + 3,
|
||||
[61] = IPRIO_DEFAULT_UPPER + 4,
|
||||
[60] = IPRIO_DEFAULT_UPPER + 5,
|
||||
/* Custom interrupts 48 to 63 */
|
||||
[63] = IPRIO_MMAXIPRIO,
|
||||
[62] = IPRIO_MMAXIPRIO,
|
||||
[61] = IPRIO_MMAXIPRIO,
|
||||
[60] = IPRIO_MMAXIPRIO,
|
||||
[59] = IPRIO_MMAXIPRIO,
|
||||
[58] = IPRIO_MMAXIPRIO,
|
||||
[57] = IPRIO_MMAXIPRIO,
|
||||
[56] = IPRIO_MMAXIPRIO,
|
||||
[55] = IPRIO_MMAXIPRIO,
|
||||
[54] = IPRIO_MMAXIPRIO,
|
||||
[53] = IPRIO_MMAXIPRIO,
|
||||
[52] = IPRIO_MMAXIPRIO,
|
||||
[51] = IPRIO_MMAXIPRIO,
|
||||
[50] = IPRIO_MMAXIPRIO,
|
||||
[49] = IPRIO_MMAXIPRIO,
|
||||
[48] = IPRIO_MMAXIPRIO,
|
||||
|
||||
[59] = IPRIO_DEFAULT_UPPER + 6,
|
||||
[58] = IPRIO_DEFAULT_UPPER + 7,
|
||||
[29] = IPRIO_DEFAULT_UPPER + 8,
|
||||
[28] = IPRIO_DEFAULT_UPPER + 9,
|
||||
[57] = IPRIO_DEFAULT_UPPER + 10,
|
||||
[56] = IPRIO_DEFAULT_UPPER + 11,
|
||||
/* Custom interrupts 24 to 31 */
|
||||
[31] = IPRIO_MMAXIPRIO,
|
||||
[30] = IPRIO_MMAXIPRIO,
|
||||
[29] = IPRIO_MMAXIPRIO,
|
||||
[28] = IPRIO_MMAXIPRIO,
|
||||
[27] = IPRIO_MMAXIPRIO,
|
||||
[26] = IPRIO_MMAXIPRIO,
|
||||
[25] = IPRIO_MMAXIPRIO,
|
||||
[24] = IPRIO_MMAXIPRIO,
|
||||
|
||||
[55] = IPRIO_DEFAULT_UPPER + 12,
|
||||
[54] = IPRIO_DEFAULT_UPPER + 13,
|
||||
[27] = IPRIO_DEFAULT_UPPER + 14,
|
||||
[26] = IPRIO_DEFAULT_UPPER + 15,
|
||||
[53] = IPRIO_DEFAULT_UPPER + 16,
|
||||
[52] = IPRIO_DEFAULT_UPPER + 17,
|
||||
[47] = IPRIO_DEFAULT_UPPER,
|
||||
[23] = IPRIO_DEFAULT_UPPER + 1,
|
||||
[46] = IPRIO_DEFAULT_UPPER + 2,
|
||||
[45] = IPRIO_DEFAULT_UPPER + 3,
|
||||
[22] = IPRIO_DEFAULT_UPPER + 4,
|
||||
[44] = IPRIO_DEFAULT_UPPER + 5,
|
||||
|
||||
[51] = IPRIO_DEFAULT_UPPER + 18,
|
||||
[50] = IPRIO_DEFAULT_UPPER + 19,
|
||||
[25] = IPRIO_DEFAULT_UPPER + 20,
|
||||
[24] = IPRIO_DEFAULT_UPPER + 21,
|
||||
[49] = IPRIO_DEFAULT_UPPER + 22,
|
||||
[48] = IPRIO_DEFAULT_UPPER + 23,
|
||||
[43] = IPRIO_DEFAULT_UPPER + 6,
|
||||
[21] = IPRIO_DEFAULT_UPPER + 7,
|
||||
[42] = IPRIO_DEFAULT_UPPER + 8,
|
||||
[41] = IPRIO_DEFAULT_UPPER + 9,
|
||||
[20] = IPRIO_DEFAULT_UPPER + 10,
|
||||
[40] = IPRIO_DEFAULT_UPPER + 11,
|
||||
|
||||
[11] = IPRIO_DEFAULT_M,
|
||||
[3] = IPRIO_DEFAULT_M + 1,
|
||||
@ -266,33 +276,19 @@ static const uint8_t default_iprio[64] = {
|
||||
[2] = IPRIO_DEFAULT_VS + 1,
|
||||
[6] = IPRIO_DEFAULT_VS + 2,
|
||||
|
||||
[47] = IPRIO_DEFAULT_LOWER,
|
||||
[46] = IPRIO_DEFAULT_LOWER + 1,
|
||||
[23] = IPRIO_DEFAULT_LOWER + 2,
|
||||
[22] = IPRIO_DEFAULT_LOWER + 3,
|
||||
[45] = IPRIO_DEFAULT_LOWER + 4,
|
||||
[44] = IPRIO_DEFAULT_LOWER + 5,
|
||||
[39] = IPRIO_DEFAULT_LOWER,
|
||||
[19] = IPRIO_DEFAULT_LOWER + 1,
|
||||
[38] = IPRIO_DEFAULT_LOWER + 2,
|
||||
[37] = IPRIO_DEFAULT_LOWER + 3,
|
||||
[18] = IPRIO_DEFAULT_LOWER + 4,
|
||||
[36] = IPRIO_DEFAULT_LOWER + 5,
|
||||
|
||||
[43] = IPRIO_DEFAULT_LOWER + 6,
|
||||
[42] = IPRIO_DEFAULT_LOWER + 7,
|
||||
[21] = IPRIO_DEFAULT_LOWER + 8,
|
||||
[20] = IPRIO_DEFAULT_LOWER + 9,
|
||||
[41] = IPRIO_DEFAULT_LOWER + 10,
|
||||
[40] = IPRIO_DEFAULT_LOWER + 11,
|
||||
|
||||
[39] = IPRIO_DEFAULT_LOWER + 12,
|
||||
[38] = IPRIO_DEFAULT_LOWER + 13,
|
||||
[19] = IPRIO_DEFAULT_LOWER + 14,
|
||||
[18] = IPRIO_DEFAULT_LOWER + 15,
|
||||
[37] = IPRIO_DEFAULT_LOWER + 16,
|
||||
[36] = IPRIO_DEFAULT_LOWER + 17,
|
||||
|
||||
[35] = IPRIO_DEFAULT_LOWER + 18,
|
||||
[34] = IPRIO_DEFAULT_LOWER + 19,
|
||||
[17] = IPRIO_DEFAULT_LOWER + 20,
|
||||
[16] = IPRIO_DEFAULT_LOWER + 21,
|
||||
[33] = IPRIO_DEFAULT_LOWER + 22,
|
||||
[32] = IPRIO_DEFAULT_LOWER + 23,
|
||||
[35] = IPRIO_DEFAULT_LOWER + 6,
|
||||
[17] = IPRIO_DEFAULT_LOWER + 7,
|
||||
[34] = IPRIO_DEFAULT_LOWER + 8,
|
||||
[33] = IPRIO_DEFAULT_LOWER + 9,
|
||||
[16] = IPRIO_DEFAULT_LOWER + 10,
|
||||
[32] = IPRIO_DEFAULT_LOWER + 11,
|
||||
};
|
||||
|
||||
uint8_t riscv_cpu_default_priority(int irq)
|
||||
|
@ -21,6 +21,7 @@
|
||||
#include "qemu/log.h"
|
||||
#include "qemu/timer.h"
|
||||
#include "cpu.h"
|
||||
#include "pmu.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "exec/exec-all.h"
|
||||
#include "sysemu/cpu-timers.h"
|
||||
@ -72,12 +73,72 @@ static RISCVException ctr(CPURISCVState *env, int csrno)
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
CPUState *cs = env_cpu(env);
|
||||
RISCVCPU *cpu = RISCV_CPU(cs);
|
||||
int ctr_index;
|
||||
int base_csrno = CSR_HPMCOUNTER3;
|
||||
bool rv32 = riscv_cpu_mxl(env) == MXL_RV32 ? true : false;
|
||||
|
||||
if (!cpu->cfg.ext_counters) {
|
||||
/* The Counters extensions is not enabled */
|
||||
if (rv32 && csrno >= CSR_CYCLEH) {
|
||||
/* Offset for RV32 hpmcounternh counters */
|
||||
base_csrno += 0x80;
|
||||
}
|
||||
ctr_index = csrno - base_csrno;
|
||||
|
||||
if (!cpu->cfg.pmu_num || ctr_index >= (cpu->cfg.pmu_num)) {
|
||||
/* No counter is enabled in PMU or the counter is out of range */
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
|
||||
if (env->priv == PRV_S) {
|
||||
switch (csrno) {
|
||||
case CSR_CYCLE:
|
||||
if (!get_field(env->mcounteren, COUNTEREN_CY)) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
break;
|
||||
case CSR_TIME:
|
||||
if (!get_field(env->mcounteren, COUNTEREN_TM)) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
break;
|
||||
case CSR_INSTRET:
|
||||
if (!get_field(env->mcounteren, COUNTEREN_IR)) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
break;
|
||||
case CSR_HPMCOUNTER3...CSR_HPMCOUNTER31:
|
||||
ctr_index = csrno - CSR_CYCLE;
|
||||
if (!get_field(env->mcounteren, 1 << ctr_index)) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (rv32) {
|
||||
switch (csrno) {
|
||||
case CSR_CYCLEH:
|
||||
if (!get_field(env->mcounteren, COUNTEREN_CY)) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
break;
|
||||
case CSR_TIMEH:
|
||||
if (!get_field(env->mcounteren, COUNTEREN_TM)) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
break;
|
||||
case CSR_INSTRETH:
|
||||
if (!get_field(env->mcounteren, COUNTEREN_IR)) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
break;
|
||||
case CSR_HPMCOUNTER3H...CSR_HPMCOUNTER31H:
|
||||
ctr_index = csrno - CSR_CYCLEH;
|
||||
if (!get_field(env->mcounteren, 1 << ctr_index)) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if (riscv_cpu_virt_enabled(env)) {
|
||||
switch (csrno) {
|
||||
case CSR_CYCLE:
|
||||
@ -99,13 +160,14 @@ static RISCVException ctr(CPURISCVState *env, int csrno)
|
||||
}
|
||||
break;
|
||||
case CSR_HPMCOUNTER3...CSR_HPMCOUNTER31:
|
||||
if (!get_field(env->hcounteren, 1 << (csrno - CSR_HPMCOUNTER3)) &&
|
||||
get_field(env->mcounteren, 1 << (csrno - CSR_HPMCOUNTER3))) {
|
||||
ctr_index = csrno - CSR_CYCLE;
|
||||
if (!get_field(env->hcounteren, 1 << ctr_index) &&
|
||||
get_field(env->mcounteren, 1 << ctr_index)) {
|
||||
return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
|
||||
}
|
||||
break;
|
||||
}
|
||||
if (riscv_cpu_mxl(env) == MXL_RV32) {
|
||||
if (rv32) {
|
||||
switch (csrno) {
|
||||
case CSR_CYCLEH:
|
||||
if (!get_field(env->hcounteren, COUNTEREN_CY) &&
|
||||
@ -126,8 +188,9 @@ static RISCVException ctr(CPURISCVState *env, int csrno)
|
||||
}
|
||||
break;
|
||||
case CSR_HPMCOUNTER3H...CSR_HPMCOUNTER31H:
|
||||
if (!get_field(env->hcounteren, 1 << (csrno - CSR_HPMCOUNTER3H)) &&
|
||||
get_field(env->mcounteren, 1 << (csrno - CSR_HPMCOUNTER3H))) {
|
||||
ctr_index = csrno - CSR_CYCLEH;
|
||||
if (!get_field(env->hcounteren, 1 << ctr_index) &&
|
||||
get_field(env->mcounteren, 1 << ctr_index)) {
|
||||
return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
|
||||
}
|
||||
break;
|
||||
@ -148,6 +211,35 @@ static RISCVException ctr32(CPURISCVState *env, int csrno)
|
||||
}
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
static RISCVException mctr(CPURISCVState *env, int csrno)
|
||||
{
|
||||
CPUState *cs = env_cpu(env);
|
||||
RISCVCPU *cpu = RISCV_CPU(cs);
|
||||
int ctr_index;
|
||||
int base_csrno = CSR_MHPMCOUNTER3;
|
||||
|
||||
if ((riscv_cpu_mxl(env) == MXL_RV32) && csrno >= CSR_MCYCLEH) {
|
||||
/* Offset for RV32 mhpmcounternh counters */
|
||||
base_csrno += 0x80;
|
||||
}
|
||||
ctr_index = csrno - base_csrno;
|
||||
if (!cpu->cfg.pmu_num || ctr_index >= cpu->cfg.pmu_num) {
|
||||
/* The PMU is not enabled or counter is out of range*/
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
static RISCVException mctr32(CPURISCVState *env, int csrno)
|
||||
{
|
||||
if (riscv_cpu_mxl(env) != MXL_RV32) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
|
||||
return mctr(env, csrno);
|
||||
}
|
||||
|
||||
static RISCVException any(CPURISCVState *env, int csrno)
|
||||
{
|
||||
return RISCV_EXCP_NONE;
|
||||
@ -506,34 +598,28 @@ static int write_vcsr(CPURISCVState *env, int csrno, target_ulong val)
|
||||
}
|
||||
|
||||
/* User Timers and Counters */
|
||||
static RISCVException read_instret(CPURISCVState *env, int csrno,
|
||||
target_ulong *val)
|
||||
static target_ulong get_ticks(bool shift)
|
||||
{
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
if (icount_enabled()) {
|
||||
*val = icount_get();
|
||||
} else {
|
||||
*val = cpu_get_host_ticks();
|
||||
}
|
||||
#else
|
||||
*val = cpu_get_host_ticks();
|
||||
#endif
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
int64_t val;
|
||||
target_ulong result;
|
||||
|
||||
static RISCVException read_instreth(CPURISCVState *env, int csrno,
|
||||
target_ulong *val)
|
||||
{
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
if (icount_enabled()) {
|
||||
*val = icount_get() >> 32;
|
||||
val = icount_get();
|
||||
} else {
|
||||
*val = cpu_get_host_ticks() >> 32;
|
||||
val = cpu_get_host_ticks();
|
||||
}
|
||||
#else
|
||||
*val = cpu_get_host_ticks() >> 32;
|
||||
val = cpu_get_host_ticks();
|
||||
#endif
|
||||
return RISCV_EXCP_NONE;
|
||||
|
||||
if (shift) {
|
||||
result = val >> 32;
|
||||
} else {
|
||||
result = val;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
#if defined(CONFIG_USER_ONLY)
|
||||
@ -551,8 +637,139 @@ static RISCVException read_timeh(CPURISCVState *env, int csrno,
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
static int read_hpmcounter(CPURISCVState *env, int csrno, target_ulong *val)
|
||||
{
|
||||
*val = get_ticks(false);
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
static int read_hpmcounterh(CPURISCVState *env, int csrno, target_ulong *val)
|
||||
{
|
||||
*val = get_ticks(true);
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
#else /* CONFIG_USER_ONLY */
|
||||
|
||||
static int read_mhpmevent(CPURISCVState *env, int csrno, target_ulong *val)
|
||||
{
|
||||
int evt_index = csrno - CSR_MCOUNTINHIBIT;
|
||||
|
||||
*val = env->mhpmevent_val[evt_index];
|
||||
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
static int write_mhpmevent(CPURISCVState *env, int csrno, target_ulong val)
|
||||
{
|
||||
int evt_index = csrno - CSR_MCOUNTINHIBIT;
|
||||
|
||||
env->mhpmevent_val[evt_index] = val;
|
||||
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
static int write_mhpmcounter(CPURISCVState *env, int csrno, target_ulong val)
|
||||
{
|
||||
int ctr_idx = csrno - CSR_MCYCLE;
|
||||
PMUCTRState *counter = &env->pmu_ctrs[ctr_idx];
|
||||
|
||||
counter->mhpmcounter_val = val;
|
||||
if (riscv_pmu_ctr_monitor_cycles(env, ctr_idx) ||
|
||||
riscv_pmu_ctr_monitor_instructions(env, ctr_idx)) {
|
||||
counter->mhpmcounter_prev = get_ticks(false);
|
||||
} else {
|
||||
/* Other counters can keep incrementing from the given value */
|
||||
counter->mhpmcounter_prev = val;
|
||||
}
|
||||
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
static int write_mhpmcounterh(CPURISCVState *env, int csrno, target_ulong val)
|
||||
{
|
||||
int ctr_idx = csrno - CSR_MCYCLEH;
|
||||
PMUCTRState *counter = &env->pmu_ctrs[ctr_idx];
|
||||
|
||||
counter->mhpmcounterh_val = val;
|
||||
if (riscv_pmu_ctr_monitor_cycles(env, ctr_idx) ||
|
||||
riscv_pmu_ctr_monitor_instructions(env, ctr_idx)) {
|
||||
counter->mhpmcounterh_prev = get_ticks(true);
|
||||
} else {
|
||||
counter->mhpmcounterh_prev = val;
|
||||
}
|
||||
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
static RISCVException riscv_pmu_read_ctr(CPURISCVState *env, target_ulong *val,
|
||||
bool upper_half, uint32_t ctr_idx)
|
||||
{
|
||||
PMUCTRState counter = env->pmu_ctrs[ctr_idx];
|
||||
target_ulong ctr_prev = upper_half ? counter.mhpmcounterh_prev :
|
||||
counter.mhpmcounter_prev;
|
||||
target_ulong ctr_val = upper_half ? counter.mhpmcounterh_val :
|
||||
counter.mhpmcounter_val;
|
||||
|
||||
if (get_field(env->mcountinhibit, BIT(ctr_idx))) {
|
||||
/**
|
||||
* Counter should not increment if inhibit bit is set. We can't really
|
||||
* stop the icount counting. Just return the counter value written by
|
||||
* the supervisor to indicate that counter was not incremented.
|
||||
*/
|
||||
if (!counter.started) {
|
||||
*val = ctr_val;
|
||||
return RISCV_EXCP_NONE;
|
||||
} else {
|
||||
/* Mark that the counter has been stopped */
|
||||
counter.started = false;
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* The kernel computes the perf delta by subtracting the current value from
|
||||
* the value it initialized previously (ctr_val).
|
||||
*/
|
||||
if (riscv_pmu_ctr_monitor_cycles(env, ctr_idx) ||
|
||||
riscv_pmu_ctr_monitor_instructions(env, ctr_idx)) {
|
||||
*val = get_ticks(upper_half) - ctr_prev + ctr_val;
|
||||
} else {
|
||||
*val = ctr_val;
|
||||
}
|
||||
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
static int read_hpmcounter(CPURISCVState *env, int csrno, target_ulong *val)
|
||||
{
|
||||
uint16_t ctr_index;
|
||||
|
||||
if (csrno >= CSR_MCYCLE && csrno <= CSR_MHPMCOUNTER31) {
|
||||
ctr_index = csrno - CSR_MCYCLE;
|
||||
} else if (csrno >= CSR_CYCLE && csrno <= CSR_HPMCOUNTER31) {
|
||||
ctr_index = csrno - CSR_CYCLE;
|
||||
} else {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
|
||||
return riscv_pmu_read_ctr(env, val, false, ctr_index);
|
||||
}
|
||||
|
||||
static int read_hpmcounterh(CPURISCVState *env, int csrno, target_ulong *val)
|
||||
{
|
||||
uint16_t ctr_index;
|
||||
|
||||
if (csrno >= CSR_MCYCLEH && csrno <= CSR_MHPMCOUNTER31H) {
|
||||
ctr_index = csrno - CSR_MCYCLEH;
|
||||
} else if (csrno >= CSR_CYCLEH && csrno <= CSR_HPMCOUNTER31H) {
|
||||
ctr_index = csrno - CSR_CYCLEH;
|
||||
} else {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
|
||||
return riscv_pmu_read_ctr(env, val, true, ctr_index);
|
||||
}
|
||||
|
||||
static RISCVException read_time(CPURISCVState *env, int csrno,
|
||||
target_ulong *val)
|
||||
{
|
||||
@ -1040,14 +1257,6 @@ static int aia_xlate_vs_csrno(CPURISCVState *env, int csrno)
|
||||
return CSR_VSISELECT;
|
||||
case CSR_SIREG:
|
||||
return CSR_VSIREG;
|
||||
case CSR_SSETEIPNUM:
|
||||
return CSR_VSSETEIPNUM;
|
||||
case CSR_SCLREIPNUM:
|
||||
return CSR_VSCLREIPNUM;
|
||||
case CSR_SSETEIENUM:
|
||||
return CSR_VSSETEIENUM;
|
||||
case CSR_SCLREIENUM:
|
||||
return CSR_VSCLREIENUM;
|
||||
case CSR_STOPEI:
|
||||
return CSR_VSTOPEI;
|
||||
default:
|
||||
@ -1202,124 +1411,6 @@ done:
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
static int rmw_xsetclreinum(CPURISCVState *env, int csrno, target_ulong *val,
|
||||
target_ulong new_val, target_ulong wr_mask)
|
||||
{
|
||||
int ret = -EINVAL;
|
||||
bool set, pend, virt;
|
||||
target_ulong priv, isel, vgein, xlen, nval, wmask;
|
||||
|
||||
/* Translate CSR number for VS-mode */
|
||||
csrno = aia_xlate_vs_csrno(env, csrno);
|
||||
|
||||
/* Decode register details from CSR number */
|
||||
virt = set = pend = false;
|
||||
switch (csrno) {
|
||||
case CSR_MSETEIPNUM:
|
||||
priv = PRV_M;
|
||||
set = true;
|
||||
pend = true;
|
||||
break;
|
||||
case CSR_MCLREIPNUM:
|
||||
priv = PRV_M;
|
||||
pend = true;
|
||||
break;
|
||||
case CSR_MSETEIENUM:
|
||||
priv = PRV_M;
|
||||
set = true;
|
||||
break;
|
||||
case CSR_MCLREIENUM:
|
||||
priv = PRV_M;
|
||||
break;
|
||||
case CSR_SSETEIPNUM:
|
||||
priv = PRV_S;
|
||||
set = true;
|
||||
pend = true;
|
||||
break;
|
||||
case CSR_SCLREIPNUM:
|
||||
priv = PRV_S;
|
||||
pend = true;
|
||||
break;
|
||||
case CSR_SSETEIENUM:
|
||||
priv = PRV_S;
|
||||
set = true;
|
||||
break;
|
||||
case CSR_SCLREIENUM:
|
||||
priv = PRV_S;
|
||||
break;
|
||||
case CSR_VSSETEIPNUM:
|
||||
priv = PRV_S;
|
||||
virt = true;
|
||||
set = true;
|
||||
pend = true;
|
||||
break;
|
||||
case CSR_VSCLREIPNUM:
|
||||
priv = PRV_S;
|
||||
virt = true;
|
||||
pend = true;
|
||||
break;
|
||||
case CSR_VSSETEIENUM:
|
||||
priv = PRV_S;
|
||||
virt = true;
|
||||
set = true;
|
||||
break;
|
||||
case CSR_VSCLREIENUM:
|
||||
priv = PRV_S;
|
||||
virt = true;
|
||||
break;
|
||||
default:
|
||||
goto done;
|
||||
};
|
||||
|
||||
/* IMSIC CSRs only available when machine implements IMSIC. */
|
||||
if (!env->aia_ireg_rmw_fn[priv]) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Find the selected guest interrupt file */
|
||||
vgein = (virt) ? get_field(env->hstatus, HSTATUS_VGEIN) : 0;
|
||||
|
||||
/* Selected guest interrupt file should be valid */
|
||||
if (virt && (!vgein || env->geilen < vgein)) {
|
||||
goto done;
|
||||
}
|
||||
|
||||
/* Set/Clear CSRs always read zero */
|
||||
if (val) {
|
||||
*val = 0;
|
||||
}
|
||||
|
||||
if (wr_mask) {
|
||||
/* Get interrupt number */
|
||||
new_val &= wr_mask;
|
||||
|
||||
/* Find target interrupt pending/enable register */
|
||||
xlen = riscv_cpu_mxl_bits(env);
|
||||
isel = (new_val / xlen);
|
||||
isel *= (xlen / IMSIC_EIPx_BITS);
|
||||
isel += (pend) ? ISELECT_IMSIC_EIP0 : ISELECT_IMSIC_EIE0;
|
||||
|
||||
/* Find the interrupt bit to be set/clear */
|
||||
wmask = ((target_ulong)1) << (new_val % xlen);
|
||||
nval = (set) ? wmask : 0;
|
||||
|
||||
/* Call machine specific IMSIC register emulation */
|
||||
ret = env->aia_ireg_rmw_fn[priv](env->aia_ireg_rmw_fn_arg[priv],
|
||||
AIA_MAKE_IREG(isel, priv, virt,
|
||||
vgein, xlen),
|
||||
NULL, nval, wmask);
|
||||
} else {
|
||||
ret = 0;
|
||||
}
|
||||
|
||||
done:
|
||||
if (ret) {
|
||||
return (riscv_cpu_virt_enabled(env) && virt) ?
|
||||
RISCV_EXCP_VIRT_INSTRUCTION_FAULT : RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
static int rmw_xtopei(CPURISCVState *env, int csrno, target_ulong *val,
|
||||
target_ulong new_val, target_ulong wr_mask)
|
||||
{
|
||||
@ -1393,6 +1484,40 @@ static RISCVException write_mtvec(CPURISCVState *env, int csrno,
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
static RISCVException read_mcountinhibit(CPURISCVState *env, int csrno,
|
||||
target_ulong *val)
|
||||
{
|
||||
if (env->priv_ver < PRIV_VERSION_1_11_0) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
|
||||
*val = env->mcountinhibit;
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
static RISCVException write_mcountinhibit(CPURISCVState *env, int csrno,
|
||||
target_ulong val)
|
||||
{
|
||||
int cidx;
|
||||
PMUCTRState *counter;
|
||||
|
||||
if (env->priv_ver < PRIV_VERSION_1_11_0) {
|
||||
return RISCV_EXCP_ILLEGAL_INST;
|
||||
}
|
||||
|
||||
env->mcountinhibit = val;
|
||||
|
||||
/* Check if any other counter is also monitoring cycles/instructions */
|
||||
for (cidx = 0; cidx < RV_MAX_MHPMCOUNTERS; cidx++) {
|
||||
if (!get_field(env->mcountinhibit, BIT(cidx))) {
|
||||
counter = &env->pmu_ctrs[cidx];
|
||||
counter->started = true;
|
||||
}
|
||||
}
|
||||
|
||||
return RISCV_EXCP_NONE;
|
||||
}
|
||||
|
||||
static RISCVException read_mcounteren(CPURISCVState *env, int csrno,
|
||||
target_ulong *val)
|
||||
{
|
||||
@ -3351,10 +3476,10 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
|
||||
[CSR_VLENB] = { "vlenb", vs, read_vlenb,
|
||||
.min_priv_ver = PRIV_VERSION_1_12_0 },
|
||||
/* User Timers and Counters */
|
||||
[CSR_CYCLE] = { "cycle", ctr, read_instret },
|
||||
[CSR_INSTRET] = { "instret", ctr, read_instret },
|
||||
[CSR_CYCLEH] = { "cycleh", ctr32, read_instreth },
|
||||
[CSR_INSTRETH] = { "instreth", ctr32, read_instreth },
|
||||
[CSR_CYCLE] = { "cycle", ctr, read_hpmcounter },
|
||||
[CSR_INSTRET] = { "instret", ctr, read_hpmcounter },
|
||||
[CSR_CYCLEH] = { "cycleh", ctr32, read_hpmcounterh },
|
||||
[CSR_INSTRETH] = { "instreth", ctr32, read_hpmcounterh },
|
||||
|
||||
/*
|
||||
* In privileged mode, the monitor will have to emulate TIME CSRs only if
|
||||
@ -3368,10 +3493,10 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
|
||||
|
||||
#if !defined(CONFIG_USER_ONLY)
|
||||
/* Machine Timers and Counters */
|
||||
[CSR_MCYCLE] = { "mcycle", any, read_instret },
|
||||
[CSR_MINSTRET] = { "minstret", any, read_instret },
|
||||
[CSR_MCYCLEH] = { "mcycleh", any32, read_instreth },
|
||||
[CSR_MINSTRETH] = { "minstreth", any32, read_instreth },
|
||||
[CSR_MCYCLE] = { "mcycle", any, read_hpmcounter, write_mhpmcounter},
|
||||
[CSR_MINSTRET] = { "minstret", any, read_hpmcounter, write_mhpmcounter},
|
||||
[CSR_MCYCLEH] = { "mcycleh", any32, read_hpmcounterh, write_mhpmcounterh},
|
||||
[CSR_MINSTRETH] = { "minstreth", any32, read_hpmcounterh, write_mhpmcounterh},
|
||||
|
||||
/* Machine Information Registers */
|
||||
[CSR_MVENDORID] = { "mvendorid", any, read_mvendorid },
|
||||
@ -3407,14 +3532,8 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
|
||||
[CSR_MIREG] = { "mireg", aia_any, NULL, NULL, rmw_xireg },
|
||||
|
||||
/* Machine-Level Interrupts (AIA) */
|
||||
[CSR_MTOPI] = { "mtopi", aia_any, read_mtopi },
|
||||
|
||||
/* Machine-Level IMSIC Interface (AIA) */
|
||||
[CSR_MSETEIPNUM] = { "mseteipnum", aia_any, NULL, NULL, rmw_xsetclreinum },
|
||||
[CSR_MCLREIPNUM] = { "mclreipnum", aia_any, NULL, NULL, rmw_xsetclreinum },
|
||||
[CSR_MSETEIENUM] = { "mseteienum", aia_any, NULL, NULL, rmw_xsetclreinum },
|
||||
[CSR_MCLREIENUM] = { "mclreienum", aia_any, NULL, NULL, rmw_xsetclreinum },
|
||||
[CSR_MTOPEI] = { "mtopei", aia_any, NULL, NULL, rmw_xtopei },
|
||||
[CSR_MTOPI] = { "mtopi", aia_any, read_mtopi },
|
||||
|
||||
/* Virtual Interrupts for Supervisor Level (AIA) */
|
||||
[CSR_MVIEN] = { "mvien", aia_any, read_zero, write_ignore },
|
||||
@ -3462,14 +3581,8 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
|
||||
[CSR_SIREG] = { "sireg", aia_smode, NULL, NULL, rmw_xireg },
|
||||
|
||||
/* Supervisor-Level Interrupts (AIA) */
|
||||
[CSR_STOPI] = { "stopi", aia_smode, read_stopi },
|
||||
|
||||
/* Supervisor-Level IMSIC Interface (AIA) */
|
||||
[CSR_SSETEIPNUM] = { "sseteipnum", aia_smode, NULL, NULL, rmw_xsetclreinum },
|
||||
[CSR_SCLREIPNUM] = { "sclreipnum", aia_smode, NULL, NULL, rmw_xsetclreinum },
|
||||
[CSR_SSETEIENUM] = { "sseteienum", aia_smode, NULL, NULL, rmw_xsetclreinum },
|
||||
[CSR_SCLREIENUM] = { "sclreienum", aia_smode, NULL, NULL, rmw_xsetclreinum },
|
||||
[CSR_STOPEI] = { "stopei", aia_smode, NULL, NULL, rmw_xtopei },
|
||||
[CSR_STOPI] = { "stopi", aia_smode, read_stopi },
|
||||
|
||||
/* Supervisor-Level High-Half CSRs (AIA) */
|
||||
[CSR_SIEH] = { "sieh", aia_smode32, NULL, NULL, rmw_sieh },
|
||||
@ -3541,14 +3654,8 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
|
||||
[CSR_VSIREG] = { "vsireg", aia_hmode, NULL, NULL, rmw_xireg },
|
||||
|
||||
/* VS-Level Interrupts (H-extension with AIA) */
|
||||
[CSR_VSTOPI] = { "vstopi", aia_hmode, read_vstopi },
|
||||
|
||||
/* VS-Level IMSIC Interface (H-extension with AIA) */
|
||||
[CSR_VSSETEIPNUM] = { "vsseteipnum", aia_hmode, NULL, NULL, rmw_xsetclreinum },
|
||||
[CSR_VSCLREIPNUM] = { "vsclreipnum", aia_hmode, NULL, NULL, rmw_xsetclreinum },
|
||||
[CSR_VSSETEIENUM] = { "vsseteienum", aia_hmode, NULL, NULL, rmw_xsetclreinum },
|
||||
[CSR_VSCLREIENUM] = { "vsclreienum", aia_hmode, NULL, NULL, rmw_xsetclreinum },
|
||||
[CSR_VSTOPEI] = { "vstopei", aia_hmode, NULL, NULL, rmw_xtopei },
|
||||
[CSR_VSTOPI] = { "vstopi", aia_hmode, read_vstopi },
|
||||
|
||||
/* Hypervisor and VS-Level High-Half CSRs (H-extension with AIA) */
|
||||
[CSR_HIDELEGH] = { "hidelegh", aia_hmode32, NULL, NULL, rmw_hidelegh },
|
||||
@ -3561,7 +3668,7 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
|
||||
|
||||
/* Physical Memory Protection */
|
||||
[CSR_MSECCFG] = { "mseccfg", epmp, read_mseccfg, write_mseccfg,
|
||||
.min_priv_ver = PRIV_VERSION_1_12_0 },
|
||||
.min_priv_ver = PRIV_VERSION_1_11_0 },
|
||||
[CSR_PMPCFG0] = { "pmpcfg0", pmp, read_pmpcfg, write_pmpcfg },
|
||||
[CSR_PMPCFG1] = { "pmpcfg1", pmp, read_pmpcfg, write_pmpcfg },
|
||||
[CSR_PMPCFG2] = { "pmpcfg2", pmp, read_pmpcfg, write_pmpcfg },
|
||||
@ -3603,154 +3710,244 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
|
||||
[CSR_SPMBASE] = { "spmbase", pointer_masking, read_spmbase, write_spmbase },
|
||||
|
||||
/* Performance Counters */
|
||||
[CSR_HPMCOUNTER3] = { "hpmcounter3", ctr, read_zero },
|
||||
[CSR_HPMCOUNTER4] = { "hpmcounter4", ctr, read_zero },
|
||||
[CSR_HPMCOUNTER5] = { "hpmcounter5", ctr, read_zero },
|
||||
[CSR_HPMCOUNTER6] = { "hpmcounter6", ctr, read_zero },
|
||||
[CSR_HPMCOUNTER7] = { "hpmcounter7", ctr, read_zero },
|
||||
[CSR_HPMCOUNTER8] = { "hpmcounter8", ctr, read_zero },
|
||||
[CSR_HPMCOUNTER9] = { "hpmcounter9", ctr, read_zero },
|
||||
[CSR_HPMCOUNTER10] = { "hpmcounter10", ctr, read_zero },
|
||||
[CSR_HPMCOUNTER11] = { "hpmcounter11", ctr, read_zero },
|
||||
[CSR_HPMCOUNTER12] = { "hpmcounter12", ctr, read_zero },
|
||||
[CSR_HPMCOUNTER13] = { "hpmcounter13", ctr, read_zero },
|
||||
[CSR_HPMCOUNTER14] = { "hpmcounter14", ctr, read_zero },
|
||||
[CSR_HPMCOUNTER15] = { "hpmcounter15", ctr, read_zero },
|
||||
[CSR_HPMCOUNTER16] = { "hpmcounter16", ctr, read_zero },
|
||||
[CSR_HPMCOUNTER17] = { "hpmcounter17", ctr, read_zero },
|
||||
[CSR_HPMCOUNTER18] = { "hpmcounter18", ctr, read_zero },
|
||||
[CSR_HPMCOUNTER19] = { "hpmcounter19", ctr, read_zero },
|
||||
[CSR_HPMCOUNTER20] = { "hpmcounter20", ctr, read_zero },
|
||||
[CSR_HPMCOUNTER21] = { "hpmcounter21", ctr, read_zero },
|
||||
[CSR_HPMCOUNTER22] = { "hpmcounter22", ctr, read_zero },
|
||||
[CSR_HPMCOUNTER23] = { "hpmcounter23", ctr, read_zero },
|
||||
[CSR_HPMCOUNTER24] = { "hpmcounter24", ctr, read_zero },
|
||||
[CSR_HPMCOUNTER25] = { "hpmcounter25", ctr, read_zero },
|
||||
[CSR_HPMCOUNTER26] = { "hpmcounter26", ctr, read_zero },
|
||||
[CSR_HPMCOUNTER27] = { "hpmcounter27", ctr, read_zero },
|
||||
[CSR_HPMCOUNTER28] = { "hpmcounter28", ctr, read_zero },
|
||||
[CSR_HPMCOUNTER29] = { "hpmcounter29", ctr, read_zero },
|
||||
[CSR_HPMCOUNTER30] = { "hpmcounter30", ctr, read_zero },
|
||||
[CSR_HPMCOUNTER31] = { "hpmcounter31", ctr, read_zero },
|
||||
[CSR_HPMCOUNTER3] = { "hpmcounter3", ctr, read_hpmcounter },
|
||||
[CSR_HPMCOUNTER4] = { "hpmcounter4", ctr, read_hpmcounter },
|
||||
[CSR_HPMCOUNTER5] = { "hpmcounter5", ctr, read_hpmcounter },
|
||||
[CSR_HPMCOUNTER6] = { "hpmcounter6", ctr, read_hpmcounter },
|
||||
[CSR_HPMCOUNTER7] = { "hpmcounter7", ctr, read_hpmcounter },
|
||||
[CSR_HPMCOUNTER8] = { "hpmcounter8", ctr, read_hpmcounter },
|
||||
[CSR_HPMCOUNTER9] = { "hpmcounter9", ctr, read_hpmcounter },
|
||||
[CSR_HPMCOUNTER10] = { "hpmcounter10", ctr, read_hpmcounter },
|
||||
[CSR_HPMCOUNTER11] = { "hpmcounter11", ctr, read_hpmcounter },
|
||||
[CSR_HPMCOUNTER12] = { "hpmcounter12", ctr, read_hpmcounter },
|
||||
[CSR_HPMCOUNTER13] = { "hpmcounter13", ctr, read_hpmcounter },
|
||||
[CSR_HPMCOUNTER14] = { "hpmcounter14", ctr, read_hpmcounter },
|
||||
[CSR_HPMCOUNTER15] = { "hpmcounter15", ctr, read_hpmcounter },
|
||||
[CSR_HPMCOUNTER16] = { "hpmcounter16", ctr, read_hpmcounter },
|
||||
[CSR_HPMCOUNTER17] = { "hpmcounter17", ctr, read_hpmcounter },
|
||||
[CSR_HPMCOUNTER18] = { "hpmcounter18", ctr, read_hpmcounter },
|
||||
[CSR_HPMCOUNTER19] = { "hpmcounter19", ctr, read_hpmcounter },
|
||||
[CSR_HPMCOUNTER20] = { "hpmcounter20", ctr, read_hpmcounter },
|
||||
[CSR_HPMCOUNTER21] = { "hpmcounter21", ctr, read_hpmcounter },
|
||||
[CSR_HPMCOUNTER22] = { "hpmcounter22", ctr, read_hpmcounter },
|
||||
[CSR_HPMCOUNTER23] = { "hpmcounter23", ctr, read_hpmcounter },
|
||||
[CSR_HPMCOUNTER24] = { "hpmcounter24", ctr, read_hpmcounter },
|
||||
[CSR_HPMCOUNTER25] = { "hpmcounter25", ctr, read_hpmcounter },
|
||||
[CSR_HPMCOUNTER26] = { "hpmcounter26", ctr, read_hpmcounter },
|
||||
[CSR_HPMCOUNTER27] = { "hpmcounter27", ctr, read_hpmcounter },
|
||||
[CSR_HPMCOUNTER28] = { "hpmcounter28", ctr, read_hpmcounter },
|
||||
[CSR_HPMCOUNTER29] = { "hpmcounter29", ctr, read_hpmcounter },
|
||||
[CSR_HPMCOUNTER30] = { "hpmcounter30", ctr, read_hpmcounter },
|
||||
[CSR_HPMCOUNTER31] = { "hpmcounter31", ctr, read_hpmcounter },
|
||||
|
||||
[CSR_MHPMCOUNTER3] = { "mhpmcounter3", any, read_zero },
|
||||
[CSR_MHPMCOUNTER4] = { "mhpmcounter4", any, read_zero },
|
||||
[CSR_MHPMCOUNTER5] = { "mhpmcounter5", any, read_zero },
|
||||
[CSR_MHPMCOUNTER6] = { "mhpmcounter6", any, read_zero },
|
||||
[CSR_MHPMCOUNTER7] = { "mhpmcounter7", any, read_zero },
|
||||
[CSR_MHPMCOUNTER8] = { "mhpmcounter8", any, read_zero },
|
||||
[CSR_MHPMCOUNTER9] = { "mhpmcounter9", any, read_zero },
|
||||
[CSR_MHPMCOUNTER10] = { "mhpmcounter10", any, read_zero },
|
||||
[CSR_MHPMCOUNTER11] = { "mhpmcounter11", any, read_zero },
|
||||
[CSR_MHPMCOUNTER12] = { "mhpmcounter12", any, read_zero },
|
||||
[CSR_MHPMCOUNTER13] = { "mhpmcounter13", any, read_zero },
|
||||
[CSR_MHPMCOUNTER14] = { "mhpmcounter14", any, read_zero },
|
||||
[CSR_MHPMCOUNTER15] = { "mhpmcounter15", any, read_zero },
|
||||
[CSR_MHPMCOUNTER16] = { "mhpmcounter16", any, read_zero },
|
||||
[CSR_MHPMCOUNTER17] = { "mhpmcounter17", any, read_zero },
|
||||
[CSR_MHPMCOUNTER18] = { "mhpmcounter18", any, read_zero },
|
||||
[CSR_MHPMCOUNTER19] = { "mhpmcounter19", any, read_zero },
|
||||
[CSR_MHPMCOUNTER20] = { "mhpmcounter20", any, read_zero },
|
||||
[CSR_MHPMCOUNTER21] = { "mhpmcounter21", any, read_zero },
|
||||
[CSR_MHPMCOUNTER22] = { "mhpmcounter22", any, read_zero },
|
||||
[CSR_MHPMCOUNTER23] = { "mhpmcounter23", any, read_zero },
|
||||
[CSR_MHPMCOUNTER24] = { "mhpmcounter24", any, read_zero },
|
||||
[CSR_MHPMCOUNTER25] = { "mhpmcounter25", any, read_zero },
|
||||
[CSR_MHPMCOUNTER26] = { "mhpmcounter26", any, read_zero },
|
||||
[CSR_MHPMCOUNTER27] = { "mhpmcounter27", any, read_zero },
|
||||
[CSR_MHPMCOUNTER28] = { "mhpmcounter28", any, read_zero },
|
||||
[CSR_MHPMCOUNTER29] = { "mhpmcounter29", any, read_zero },
|
||||
[CSR_MHPMCOUNTER30] = { "mhpmcounter30", any, read_zero },
|
||||
[CSR_MHPMCOUNTER31] = { "mhpmcounter31", any, read_zero },
|
||||
[CSR_MHPMCOUNTER3] = { "mhpmcounter3", mctr, read_hpmcounter,
|
||||
write_mhpmcounter },
|
||||
[CSR_MHPMCOUNTER4] = { "mhpmcounter4", mctr, read_hpmcounter,
|
||||
write_mhpmcounter },
|
||||
[CSR_MHPMCOUNTER5] = { "mhpmcounter5", mctr, read_hpmcounter,
|
||||
write_mhpmcounter },
|
||||
[CSR_MHPMCOUNTER6] = { "mhpmcounter6", mctr, read_hpmcounter,
|
||||
write_mhpmcounter },
|
||||
[CSR_MHPMCOUNTER7] = { "mhpmcounter7", mctr, read_hpmcounter,
|
||||
write_mhpmcounter },
|
||||
[CSR_MHPMCOUNTER8] = { "mhpmcounter8", mctr, read_hpmcounter,
|
||||
write_mhpmcounter },
|
||||
[CSR_MHPMCOUNTER9] = { "mhpmcounter9", mctr, read_hpmcounter,
|
||||
write_mhpmcounter },
|
||||
[CSR_MHPMCOUNTER10] = { "mhpmcounter10", mctr, read_hpmcounter,
|
||||
write_mhpmcounter },
|
||||
[CSR_MHPMCOUNTER11] = { "mhpmcounter11", mctr, read_hpmcounter,
|
||||
write_mhpmcounter },
|
||||
[CSR_MHPMCOUNTER12] = { "mhpmcounter12", mctr, read_hpmcounter,
|
||||
write_mhpmcounter },
|
||||
[CSR_MHPMCOUNTER13] = { "mhpmcounter13", mctr, read_hpmcounter,
|
||||
write_mhpmcounter },
|
||||
[CSR_MHPMCOUNTER14] = { "mhpmcounter14", mctr, read_hpmcounter,
|
||||
write_mhpmcounter },
|
||||
[CSR_MHPMCOUNTER15] = { "mhpmcounter15", mctr, read_hpmcounter,
|
||||
write_mhpmcounter },
|
||||
[CSR_MHPMCOUNTER16] = { "mhpmcounter16", mctr, read_hpmcounter,
|
||||
write_mhpmcounter },
|
||||
[CSR_MHPMCOUNTER17] = { "mhpmcounter17", mctr, read_hpmcounter,
|
||||
write_mhpmcounter },
|
||||
[CSR_MHPMCOUNTER18] = { "mhpmcounter18", mctr, read_hpmcounter,
|
||||
write_mhpmcounter },
|
||||
[CSR_MHPMCOUNTER19] = { "mhpmcounter19", mctr, read_hpmcounter,
|
||||
write_mhpmcounter },
|
||||
[CSR_MHPMCOUNTER20] = { "mhpmcounter20", mctr, read_hpmcounter,
|
||||
write_mhpmcounter },
|
||||
[CSR_MHPMCOUNTER21] = { "mhpmcounter21", mctr, read_hpmcounter,
|
||||
write_mhpmcounter },
|
||||
[CSR_MHPMCOUNTER22] = { "mhpmcounter22", mctr, read_hpmcounter,
|
||||
write_mhpmcounter },
|
||||
[CSR_MHPMCOUNTER23] = { "mhpmcounter23", mctr, read_hpmcounter,
|
||||
write_mhpmcounter },
|
||||
[CSR_MHPMCOUNTER24] = { "mhpmcounter24", mctr, read_hpmcounter,
|
||||
write_mhpmcounter },
|
||||
[CSR_MHPMCOUNTER25] = { "mhpmcounter25", mctr, read_hpmcounter,
|
||||
write_mhpmcounter },
|
||||
[CSR_MHPMCOUNTER26] = { "mhpmcounter26", mctr, read_hpmcounter,
|
||||
write_mhpmcounter },
|
||||
[CSR_MHPMCOUNTER27] = { "mhpmcounter27", mctr, read_hpmcounter,
|
||||
write_mhpmcounter },
|
||||
[CSR_MHPMCOUNTER28] = { "mhpmcounter28", mctr, read_hpmcounter,
|
||||
write_mhpmcounter },
|
||||
[CSR_MHPMCOUNTER29] = { "mhpmcounter29", mctr, read_hpmcounter,
|
||||
write_mhpmcounter },
|
||||
[CSR_MHPMCOUNTER30] = { "mhpmcounter30", mctr, read_hpmcounter,
|
||||
write_mhpmcounter },
|
||||
[CSR_MHPMCOUNTER31] = { "mhpmcounter31", mctr, read_hpmcounter,
|
||||
write_mhpmcounter },
|
||||
|
||||
[CSR_MHPMEVENT3] = { "mhpmevent3", any, read_zero },
|
||||
[CSR_MHPMEVENT4] = { "mhpmevent4", any, read_zero },
|
||||
[CSR_MHPMEVENT5] = { "mhpmevent5", any, read_zero },
|
||||
[CSR_MHPMEVENT6] = { "mhpmevent6", any, read_zero },
|
||||
[CSR_MHPMEVENT7] = { "mhpmevent7", any, read_zero },
|
||||
[CSR_MHPMEVENT8] = { "mhpmevent8", any, read_zero },
|
||||
[CSR_MHPMEVENT9] = { "mhpmevent9", any, read_zero },
|
||||
[CSR_MHPMEVENT10] = { "mhpmevent10", any, read_zero },
|
||||
[CSR_MHPMEVENT11] = { "mhpmevent11", any, read_zero },
|
||||
[CSR_MHPMEVENT12] = { "mhpmevent12", any, read_zero },
|
||||
[CSR_MHPMEVENT13] = { "mhpmevent13", any, read_zero },
|
||||
[CSR_MHPMEVENT14] = { "mhpmevent14", any, read_zero },
|
||||
[CSR_MHPMEVENT15] = { "mhpmevent15", any, read_zero },
|
||||
[CSR_MHPMEVENT16] = { "mhpmevent16", any, read_zero },
|
||||
[CSR_MHPMEVENT17] = { "mhpmevent17", any, read_zero },
|
||||
[CSR_MHPMEVENT18] = { "mhpmevent18", any, read_zero },
|
||||
[CSR_MHPMEVENT19] = { "mhpmevent19", any, read_zero },
|
||||
[CSR_MHPMEVENT20] = { "mhpmevent20", any, read_zero },
|
||||
[CSR_MHPMEVENT21] = { "mhpmevent21", any, read_zero },
|
||||
[CSR_MHPMEVENT22] = { "mhpmevent22", any, read_zero },
|
||||
[CSR_MHPMEVENT23] = { "mhpmevent23", any, read_zero },
|
||||
[CSR_MHPMEVENT24] = { "mhpmevent24", any, read_zero },
|
||||
[CSR_MHPMEVENT25] = { "mhpmevent25", any, read_zero },
|
||||
[CSR_MHPMEVENT26] = { "mhpmevent26", any, read_zero },
|
||||
[CSR_MHPMEVENT27] = { "mhpmevent27", any, read_zero },
|
||||
[CSR_MHPMEVENT28] = { "mhpmevent28", any, read_zero },
|
||||
[CSR_MHPMEVENT29] = { "mhpmevent29", any, read_zero },
|
||||
[CSR_MHPMEVENT30] = { "mhpmevent30", any, read_zero },
|
||||
[CSR_MHPMEVENT31] = { "mhpmevent31", any, read_zero },
|
||||
[CSR_MCOUNTINHIBIT] = { "mcountinhibit", any, read_mcountinhibit,
|
||||
write_mcountinhibit, .min_priv_ver = PRIV_VERSION_1_11_0 },
|
||||
|
||||
[CSR_HPMCOUNTER3H] = { "hpmcounter3h", ctr32, read_zero },
|
||||
[CSR_HPMCOUNTER4H] = { "hpmcounter4h", ctr32, read_zero },
|
||||
[CSR_HPMCOUNTER5H] = { "hpmcounter5h", ctr32, read_zero },
|
||||
[CSR_HPMCOUNTER6H] = { "hpmcounter6h", ctr32, read_zero },
|
||||
[CSR_HPMCOUNTER7H] = { "hpmcounter7h", ctr32, read_zero },
|
||||
[CSR_HPMCOUNTER8H] = { "hpmcounter8h", ctr32, read_zero },
|
||||
[CSR_HPMCOUNTER9H] = { "hpmcounter9h", ctr32, read_zero },
|
||||
[CSR_HPMCOUNTER10H] = { "hpmcounter10h", ctr32, read_zero },
|
||||
[CSR_HPMCOUNTER11H] = { "hpmcounter11h", ctr32, read_zero },
|
||||
[CSR_HPMCOUNTER12H] = { "hpmcounter12h", ctr32, read_zero },
|
||||
[CSR_HPMCOUNTER13H] = { "hpmcounter13h", ctr32, read_zero },
|
||||
[CSR_HPMCOUNTER14H] = { "hpmcounter14h", ctr32, read_zero },
|
||||
[CSR_HPMCOUNTER15H] = { "hpmcounter15h", ctr32, read_zero },
|
||||
[CSR_HPMCOUNTER16H] = { "hpmcounter16h", ctr32, read_zero },
|
||||
[CSR_HPMCOUNTER17H] = { "hpmcounter17h", ctr32, read_zero },
|
||||
[CSR_HPMCOUNTER18H] = { "hpmcounter18h", ctr32, read_zero },
|
||||
[CSR_HPMCOUNTER19H] = { "hpmcounter19h", ctr32, read_zero },
|
||||
[CSR_HPMCOUNTER20H] = { "hpmcounter20h", ctr32, read_zero },
|
||||
[CSR_HPMCOUNTER21H] = { "hpmcounter21h", ctr32, read_zero },
|
||||
[CSR_HPMCOUNTER22H] = { "hpmcounter22h", ctr32, read_zero },
|
||||
[CSR_HPMCOUNTER23H] = { "hpmcounter23h", ctr32, read_zero },
|
||||
[CSR_HPMCOUNTER24H] = { "hpmcounter24h", ctr32, read_zero },
|
||||
[CSR_HPMCOUNTER25H] = { "hpmcounter25h", ctr32, read_zero },
|
||||
[CSR_HPMCOUNTER26H] = { "hpmcounter26h", ctr32, read_zero },
|
||||
[CSR_HPMCOUNTER27H] = { "hpmcounter27h", ctr32, read_zero },
|
||||
[CSR_HPMCOUNTER28H] = { "hpmcounter28h", ctr32, read_zero },
|
||||
[CSR_HPMCOUNTER29H] = { "hpmcounter29h", ctr32, read_zero },
|
||||
[CSR_HPMCOUNTER30H] = { "hpmcounter30h", ctr32, read_zero },
|
||||
[CSR_HPMCOUNTER31H] = { "hpmcounter31h", ctr32, read_zero },
|
||||
[CSR_MHPMEVENT3] = { "mhpmevent3", any, read_mhpmevent,
|
||||
write_mhpmevent },
|
||||
[CSR_MHPMEVENT4] = { "mhpmevent4", any, read_mhpmevent,
|
||||
write_mhpmevent },
|
||||
[CSR_MHPMEVENT5] = { "mhpmevent5", any, read_mhpmevent,
|
||||
write_mhpmevent },
|
||||
[CSR_MHPMEVENT6] = { "mhpmevent6", any, read_mhpmevent,
|
||||
write_mhpmevent },
|
||||
[CSR_MHPMEVENT7] = { "mhpmevent7", any, read_mhpmevent,
|
||||
write_mhpmevent },
|
||||
[CSR_MHPMEVENT8] = { "mhpmevent8", any, read_mhpmevent,
|
||||
write_mhpmevent },
|
||||
[CSR_MHPMEVENT9] = { "mhpmevent9", any, read_mhpmevent,
|
||||
write_mhpmevent },
|
||||
[CSR_MHPMEVENT10] = { "mhpmevent10", any, read_mhpmevent,
|
||||
write_mhpmevent },
|
||||
[CSR_MHPMEVENT11] = { "mhpmevent11", any, read_mhpmevent,
|
||||
write_mhpmevent },
|
||||
[CSR_MHPMEVENT12] = { "mhpmevent12", any, read_mhpmevent,
|
||||
write_mhpmevent },
|
||||
[CSR_MHPMEVENT13] = { "mhpmevent13", any, read_mhpmevent,
|
||||
write_mhpmevent },
|
||||
[CSR_MHPMEVENT14] = { "mhpmevent14", any, read_mhpmevent,
|
||||
write_mhpmevent },
|
||||
[CSR_MHPMEVENT15] = { "mhpmevent15", any, read_mhpmevent,
|
||||
write_mhpmevent },
|
||||
[CSR_MHPMEVENT16] = { "mhpmevent16", any, read_mhpmevent,
|
||||
write_mhpmevent },
|
||||
[CSR_MHPMEVENT17] = { "mhpmevent17", any, read_mhpmevent,
|
||||
write_mhpmevent },
|
||||
[CSR_MHPMEVENT18] = { "mhpmevent18", any, read_mhpmevent,
|
||||
write_mhpmevent },
|
||||
[CSR_MHPMEVENT19] = { "mhpmevent19", any, read_mhpmevent,
|
||||
write_mhpmevent },
|
||||
[CSR_MHPMEVENT20] = { "mhpmevent20", any, read_mhpmevent,
|
||||
write_mhpmevent },
|
||||
[CSR_MHPMEVENT21] = { "mhpmevent21", any, read_mhpmevent,
|
||||
write_mhpmevent },
|
||||
[CSR_MHPMEVENT22] = { "mhpmevent22", any, read_mhpmevent,
|
||||
write_mhpmevent },
|
||||
[CSR_MHPMEVENT23] = { "mhpmevent23", any, read_mhpmevent,
|
||||
write_mhpmevent },
|
||||
[CSR_MHPMEVENT24] = { "mhpmevent24", any, read_mhpmevent,
|
||||
write_mhpmevent },
|
||||
[CSR_MHPMEVENT25] = { "mhpmevent25", any, read_mhpmevent,
|
||||
write_mhpmevent },
|
||||
[CSR_MHPMEVENT26] = { "mhpmevent26", any, read_mhpmevent,
|
||||
write_mhpmevent },
|
||||
[CSR_MHPMEVENT27] = { "mhpmevent27", any, read_mhpmevent,
|
||||
write_mhpmevent },
|
||||
[CSR_MHPMEVENT28] = { "mhpmevent28", any, read_mhpmevent,
|
||||
write_mhpmevent },
|
||||
[CSR_MHPMEVENT29] = { "mhpmevent29", any, read_mhpmevent,
|
||||
write_mhpmevent },
|
||||
[CSR_MHPMEVENT30] = { "mhpmevent30", any, read_mhpmevent,
|
||||
write_mhpmevent },
|
||||
[CSR_MHPMEVENT31] = { "mhpmevent31", any, read_mhpmevent,
|
||||
write_mhpmevent },
|
||||
|
||||
[CSR_MHPMCOUNTER3H] = { "mhpmcounter3h", any32, read_zero },
|
||||
[CSR_MHPMCOUNTER4H] = { "mhpmcounter4h", any32, read_zero },
|
||||
[CSR_MHPMCOUNTER5H] = { "mhpmcounter5h", any32, read_zero },
|
||||
[CSR_MHPMCOUNTER6H] = { "mhpmcounter6h", any32, read_zero },
|
||||
[CSR_MHPMCOUNTER7H] = { "mhpmcounter7h", any32, read_zero },
|
||||
[CSR_MHPMCOUNTER8H] = { "mhpmcounter8h", any32, read_zero },
|
||||
[CSR_MHPMCOUNTER9H] = { "mhpmcounter9h", any32, read_zero },
|
||||
[CSR_MHPMCOUNTER10H] = { "mhpmcounter10h", any32, read_zero },
|
||||
[CSR_MHPMCOUNTER11H] = { "mhpmcounter11h", any32, read_zero },
|
||||
[CSR_MHPMCOUNTER12H] = { "mhpmcounter12h", any32, read_zero },
|
||||
[CSR_MHPMCOUNTER13H] = { "mhpmcounter13h", any32, read_zero },
|
||||
[CSR_MHPMCOUNTER14H] = { "mhpmcounter14h", any32, read_zero },
|
||||
[CSR_MHPMCOUNTER15H] = { "mhpmcounter15h", any32, read_zero },
|
||||
[CSR_MHPMCOUNTER16H] = { "mhpmcounter16h", any32, read_zero },
|
||||
[CSR_MHPMCOUNTER17H] = { "mhpmcounter17h", any32, read_zero },
|
||||
[CSR_MHPMCOUNTER18H] = { "mhpmcounter18h", any32, read_zero },
|
||||
[CSR_MHPMCOUNTER19H] = { "mhpmcounter19h", any32, read_zero },
|
||||
[CSR_MHPMCOUNTER20H] = { "mhpmcounter20h", any32, read_zero },
|
||||
[CSR_MHPMCOUNTER21H] = { "mhpmcounter21h", any32, read_zero },
|
||||
[CSR_MHPMCOUNTER22H] = { "mhpmcounter22h", any32, read_zero },
|
||||
[CSR_MHPMCOUNTER23H] = { "mhpmcounter23h", any32, read_zero },
|
||||
[CSR_MHPMCOUNTER24H] = { "mhpmcounter24h", any32, read_zero },
|
||||
[CSR_MHPMCOUNTER25H] = { "mhpmcounter25h", any32, read_zero },
|
||||
[CSR_MHPMCOUNTER26H] = { "mhpmcounter26h", any32, read_zero },
|
||||
[CSR_MHPMCOUNTER27H] = { "mhpmcounter27h", any32, read_zero },
|
||||
[CSR_MHPMCOUNTER28H] = { "mhpmcounter28h", any32, read_zero },
|
||||
[CSR_MHPMCOUNTER29H] = { "mhpmcounter29h", any32, read_zero },
|
||||
[CSR_MHPMCOUNTER30H] = { "mhpmcounter30h", any32, read_zero },
|
||||
[CSR_MHPMCOUNTER31H] = { "mhpmcounter31h", any32, read_zero },
|
||||
[CSR_HPMCOUNTER3H] = { "hpmcounter3h", ctr32, read_hpmcounterh },
|
||||
[CSR_HPMCOUNTER4H] = { "hpmcounter4h", ctr32, read_hpmcounterh },
|
||||
[CSR_HPMCOUNTER5H] = { "hpmcounter5h", ctr32, read_hpmcounterh },
|
||||
[CSR_HPMCOUNTER6H] = { "hpmcounter6h", ctr32, read_hpmcounterh },
|
||||
[CSR_HPMCOUNTER7H] = { "hpmcounter7h", ctr32, read_hpmcounterh },
|
||||
[CSR_HPMCOUNTER8H] = { "hpmcounter8h", ctr32, read_hpmcounterh },
|
||||
[CSR_HPMCOUNTER9H] = { "hpmcounter9h", ctr32, read_hpmcounterh },
|
||||
[CSR_HPMCOUNTER10H] = { "hpmcounter10h", ctr32, read_hpmcounterh },
|
||||
[CSR_HPMCOUNTER11H] = { "hpmcounter11h", ctr32, read_hpmcounterh },
|
||||
[CSR_HPMCOUNTER12H] = { "hpmcounter12h", ctr32, read_hpmcounterh },
|
||||
[CSR_HPMCOUNTER13H] = { "hpmcounter13h", ctr32, read_hpmcounterh },
|
||||
[CSR_HPMCOUNTER14H] = { "hpmcounter14h", ctr32, read_hpmcounterh },
|
||||
[CSR_HPMCOUNTER15H] = { "hpmcounter15h", ctr32, read_hpmcounterh },
|
||||
[CSR_HPMCOUNTER16H] = { "hpmcounter16h", ctr32, read_hpmcounterh },
|
||||
[CSR_HPMCOUNTER17H] = { "hpmcounter17h", ctr32, read_hpmcounterh },
|
||||
[CSR_HPMCOUNTER18H] = { "hpmcounter18h", ctr32, read_hpmcounterh },
|
||||
[CSR_HPMCOUNTER19H] = { "hpmcounter19h", ctr32, read_hpmcounterh },
|
||||
[CSR_HPMCOUNTER20H] = { "hpmcounter20h", ctr32, read_hpmcounterh },
|
||||
[CSR_HPMCOUNTER21H] = { "hpmcounter21h", ctr32, read_hpmcounterh },
|
||||
[CSR_HPMCOUNTER22H] = { "hpmcounter22h", ctr32, read_hpmcounterh },
|
||||
[CSR_HPMCOUNTER23H] = { "hpmcounter23h", ctr32, read_hpmcounterh },
|
||||
[CSR_HPMCOUNTER24H] = { "hpmcounter24h", ctr32, read_hpmcounterh },
|
||||
[CSR_HPMCOUNTER25H] = { "hpmcounter25h", ctr32, read_hpmcounterh },
|
||||
[CSR_HPMCOUNTER26H] = { "hpmcounter26h", ctr32, read_hpmcounterh },
|
||||
[CSR_HPMCOUNTER27H] = { "hpmcounter27h", ctr32, read_hpmcounterh },
|
||||
[CSR_HPMCOUNTER28H] = { "hpmcounter28h", ctr32, read_hpmcounterh },
|
||||
[CSR_HPMCOUNTER29H] = { "hpmcounter29h", ctr32, read_hpmcounterh },
|
||||
[CSR_HPMCOUNTER30H] = { "hpmcounter30h", ctr32, read_hpmcounterh },
|
||||
[CSR_HPMCOUNTER31H] = { "hpmcounter31h", ctr32, read_hpmcounterh },
|
||||
|
||||
[CSR_MHPMCOUNTER3H] = { "mhpmcounter3h", mctr32, read_hpmcounterh,
|
||||
write_mhpmcounterh },
|
||||
[CSR_MHPMCOUNTER4H] = { "mhpmcounter4h", mctr32, read_hpmcounterh,
|
||||
write_mhpmcounterh },
|
||||
[CSR_MHPMCOUNTER5H] = { "mhpmcounter5h", mctr32, read_hpmcounterh,
|
||||
write_mhpmcounterh },
|
||||
[CSR_MHPMCOUNTER6H] = { "mhpmcounter6h", mctr32, read_hpmcounterh,
|
||||
write_mhpmcounterh },
|
||||
[CSR_MHPMCOUNTER7H] = { "mhpmcounter7h", mctr32, read_hpmcounterh,
|
||||
write_mhpmcounterh },
|
||||
[CSR_MHPMCOUNTER8H] = { "mhpmcounter8h", mctr32, read_hpmcounterh,
|
||||
write_mhpmcounterh },
|
||||
[CSR_MHPMCOUNTER9H] = { "mhpmcounter9h", mctr32, read_hpmcounterh,
|
||||
write_mhpmcounterh },
|
||||
[CSR_MHPMCOUNTER10H] = { "mhpmcounter10h", mctr32, read_hpmcounterh,
|
||||
write_mhpmcounterh },
|
||||
[CSR_MHPMCOUNTER11H] = { "mhpmcounter11h", mctr32, read_hpmcounterh,
|
||||
write_mhpmcounterh },
|
||||
[CSR_MHPMCOUNTER12H] = { "mhpmcounter12h", mctr32, read_hpmcounterh,
|
||||
write_mhpmcounterh },
|
||||
[CSR_MHPMCOUNTER13H] = { "mhpmcounter13h", mctr32, read_hpmcounterh,
|
||||
write_mhpmcounterh },
|
||||
[CSR_MHPMCOUNTER14H] = { "mhpmcounter14h", mctr32, read_hpmcounterh,
|
||||
write_mhpmcounterh },
|
||||
[CSR_MHPMCOUNTER15H] = { "mhpmcounter15h", mctr32, read_hpmcounterh,
|
||||
write_mhpmcounterh },
|
||||
[CSR_MHPMCOUNTER16H] = { "mhpmcounter16h", mctr32, read_hpmcounterh,
|
||||
write_mhpmcounterh },
|
||||
[CSR_MHPMCOUNTER17H] = { "mhpmcounter17h", mctr32, read_hpmcounterh,
|
||||
write_mhpmcounterh },
|
||||
[CSR_MHPMCOUNTER18H] = { "mhpmcounter18h", mctr32, read_hpmcounterh,
|
||||
write_mhpmcounterh },
|
||||
[CSR_MHPMCOUNTER19H] = { "mhpmcounter19h", mctr32, read_hpmcounterh,
|
||||
write_mhpmcounterh },
|
||||
[CSR_MHPMCOUNTER20H] = { "mhpmcounter20h", mctr32, read_hpmcounterh,
|
||||
write_mhpmcounterh },
|
||||
[CSR_MHPMCOUNTER21H] = { "mhpmcounter21h", mctr32, read_hpmcounterh,
|
||||
write_mhpmcounterh },
|
||||
[CSR_MHPMCOUNTER22H] = { "mhpmcounter22h", mctr32, read_hpmcounterh,
|
||||
write_mhpmcounterh },
|
||||
[CSR_MHPMCOUNTER23H] = { "mhpmcounter23h", mctr32, read_hpmcounterh,
|
||||
write_mhpmcounterh },
|
||||
[CSR_MHPMCOUNTER24H] = { "mhpmcounter24h", mctr32, read_hpmcounterh,
|
||||
write_mhpmcounterh },
|
||||
[CSR_MHPMCOUNTER25H] = { "mhpmcounter25h", mctr32, read_hpmcounterh,
|
||||
write_mhpmcounterh },
|
||||
[CSR_MHPMCOUNTER26H] = { "mhpmcounter26h", mctr32, read_hpmcounterh,
|
||||
write_mhpmcounterh },
|
||||
[CSR_MHPMCOUNTER27H] = { "mhpmcounter27h", mctr32, read_hpmcounterh,
|
||||
write_mhpmcounterh },
|
||||
[CSR_MHPMCOUNTER28H] = { "mhpmcounter28h", mctr32, read_hpmcounterh,
|
||||
write_mhpmcounterh },
|
||||
[CSR_MHPMCOUNTER29H] = { "mhpmcounter29h", mctr32, read_hpmcounterh,
|
||||
write_mhpmcounterh },
|
||||
[CSR_MHPMCOUNTER30H] = { "mhpmcounter30h", mctr32, read_hpmcounterh,
|
||||
write_mhpmcounterh },
|
||||
[CSR_MHPMCOUNTER31H] = { "mhpmcounter31h", mctr32, read_hpmcounterh,
|
||||
write_mhpmcounterh },
|
||||
#endif /* !CONFIG_USER_ONLY */
|
||||
};
|
||||
|
@ -75,6 +75,7 @@ static bool trans_sret(DisasContext *ctx, arg_sret *a)
|
||||
{
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
if (has_ext(ctx, RVS)) {
|
||||
decode_save_opc(ctx);
|
||||
gen_helper_sret(cpu_pc, cpu_env);
|
||||
tcg_gen_exit_tb(NULL, 0); /* no chaining */
|
||||
ctx->base.is_jmp = DISAS_NORETURN;
|
||||
@ -90,6 +91,7 @@ static bool trans_sret(DisasContext *ctx, arg_sret *a)
|
||||
static bool trans_mret(DisasContext *ctx, arg_mret *a)
|
||||
{
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
decode_save_opc(ctx);
|
||||
gen_helper_mret(cpu_pc, cpu_env);
|
||||
tcg_gen_exit_tb(NULL, 0); /* no chaining */
|
||||
ctx->base.is_jmp = DISAS_NORETURN;
|
||||
@ -102,6 +104,7 @@ static bool trans_mret(DisasContext *ctx, arg_mret *a)
|
||||
static bool trans_wfi(DisasContext *ctx, arg_wfi *a)
|
||||
{
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
decode_save_opc(ctx);
|
||||
gen_set_pc_imm(ctx, ctx->pc_succ_insn);
|
||||
gen_helper_wfi(cpu_env);
|
||||
return true;
|
||||
@ -113,6 +116,7 @@ static bool trans_wfi(DisasContext *ctx, arg_wfi *a)
|
||||
static bool trans_sfence_vma(DisasContext *ctx, arg_sfence_vma *a)
|
||||
{
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
decode_save_opc(ctx);
|
||||
gen_helper_tlb_flush(cpu_env);
|
||||
return true;
|
||||
#endif
|
||||
|
@ -169,6 +169,7 @@ static bool trans_hfence_gvma(DisasContext *ctx, arg_sfence_vma *a)
|
||||
{
|
||||
REQUIRE_EXT(ctx, RVH);
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
decode_save_opc(ctx);
|
||||
gen_helper_hyp_gvma_tlb_flush(cpu_env);
|
||||
return true;
|
||||
#endif
|
||||
@ -179,6 +180,7 @@ static bool trans_hfence_vvma(DisasContext *ctx, arg_sfence_vma *a)
|
||||
{
|
||||
REQUIRE_EXT(ctx, RVH);
|
||||
#ifndef CONFIG_USER_ONLY
|
||||
decode_save_opc(ctx);
|
||||
gen_helper_hyp_tlb_flush(cpu_env);
|
||||
return true;
|
||||
#endif
|
||||
|
@ -32,17 +32,13 @@ static bool trans_c64_illegal(DisasContext *ctx, arg_empty *a)
|
||||
|
||||
static bool trans_lui(DisasContext *ctx, arg_lui *a)
|
||||
{
|
||||
if (a->rd != 0) {
|
||||
gen_set_gpri(ctx, a->rd, a->imm);
|
||||
}
|
||||
gen_set_gpri(ctx, a->rd, a->imm);
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool trans_auipc(DisasContext *ctx, arg_auipc *a)
|
||||
{
|
||||
if (a->rd != 0) {
|
||||
gen_set_gpri(ctx, a->rd, a->imm + ctx->base.pc_next);
|
||||
}
|
||||
gen_set_gpri(ctx, a->rd, a->imm + ctx->base.pc_next);
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -822,6 +818,8 @@ static bool trans_fence_i(DisasContext *ctx, arg_fence_i *a)
|
||||
|
||||
static bool do_csr_post(DisasContext *ctx)
|
||||
{
|
||||
/* The helper may raise ILLEGAL_INSN -- record binv for unwind. */
|
||||
decode_save_opc(ctx);
|
||||
/* We may have changed important cpu state -- exit to main loop. */
|
||||
gen_set_pc_imm(ctx, ctx->pc_succ_insn);
|
||||
tcg_gen_exit_tb(NULL, 0);
|
||||
|
@ -279,7 +279,28 @@ static const VMStateDescription vmstate_envcfg = {
|
||||
VMSTATE_UINT64(env.menvcfg, RISCVCPU),
|
||||
VMSTATE_UINTTL(env.senvcfg, RISCVCPU),
|
||||
VMSTATE_UINT64(env.henvcfg, RISCVCPU),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
|
||||
static bool pmu_needed(void *opaque)
|
||||
{
|
||||
RISCVCPU *cpu = opaque;
|
||||
|
||||
return cpu->cfg.pmu_num;
|
||||
}
|
||||
|
||||
static const VMStateDescription vmstate_pmu_ctr_state = {
|
||||
.name = "cpu/pmu",
|
||||
.version_id = 1,
|
||||
.minimum_version_id = 1,
|
||||
.needed = pmu_needed,
|
||||
.fields = (VMStateField[]) {
|
||||
VMSTATE_UINTTL(mhpmcounter_val, PMUCTRState),
|
||||
VMSTATE_UINTTL(mhpmcounterh_val, PMUCTRState),
|
||||
VMSTATE_UINTTL(mhpmcounter_prev, PMUCTRState),
|
||||
VMSTATE_UINTTL(mhpmcounterh_prev, PMUCTRState),
|
||||
VMSTATE_BOOL(started, PMUCTRState),
|
||||
VMSTATE_END_OF_LIST()
|
||||
}
|
||||
};
|
||||
@ -330,6 +351,10 @@ const VMStateDescription vmstate_riscv_cpu = {
|
||||
VMSTATE_UINTTL(env.siselect, RISCVCPU),
|
||||
VMSTATE_UINTTL(env.scounteren, RISCVCPU),
|
||||
VMSTATE_UINTTL(env.mcounteren, RISCVCPU),
|
||||
VMSTATE_UINTTL(env.mcountinhibit, RISCVCPU),
|
||||
VMSTATE_STRUCT_ARRAY(env.pmu_ctrs, RISCVCPU, RV_MAX_MHPMCOUNTERS, 0,
|
||||
vmstate_pmu_ctr_state, PMUCTRState),
|
||||
VMSTATE_UINTTL_ARRAY(env.mhpmevent_val, RISCVCPU, RV_MAX_MHPMEVENTS),
|
||||
VMSTATE_UINTTL(env.sscratch, RISCVCPU),
|
||||
VMSTATE_UINTTL(env.mscratch, RISCVCPU),
|
||||
VMSTATE_UINT64(env.mfromhost, RISCVCPU),
|
||||
|
@ -30,7 +30,8 @@ riscv_softmmu_ss.add(files(
|
||||
'pmp.c',
|
||||
'debug.c',
|
||||
'monitor.c',
|
||||
'machine.c'
|
||||
'machine.c',
|
||||
'pmu.c'
|
||||
))
|
||||
|
||||
target_arch += {'riscv': riscv_ss}
|
||||
|
@ -167,6 +167,9 @@ void pmp_update_rule_addr(CPURISCVState *env, uint32_t pmp_index)
|
||||
case PMP_AMATCH_TOR:
|
||||
sa = prev_addr << 2; /* shift up from [xx:0] to [xx+2:2] */
|
||||
ea = (this_addr << 2) - 1u;
|
||||
if (sa > ea) {
|
||||
sa = ea = 0u;
|
||||
}
|
||||
break;
|
||||
|
||||
case PMP_AMATCH_NA4:
|
||||
|
32
target/riscv/pmu.c
Normal file
32
target/riscv/pmu.c
Normal file
@ -0,0 +1,32 @@
|
||||
/*
|
||||
* RISC-V PMU file.
|
||||
*
|
||||
* Copyright (c) 2021 Western Digital Corporation or its affiliates.
|
||||
*
|
||||
* 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"
|
||||
#include "cpu.h"
|
||||
#include "pmu.h"
|
||||
|
||||
bool riscv_pmu_ctr_monitor_instructions(CPURISCVState *env,
|
||||
uint32_t target_ctr)
|
||||
{
|
||||
return (target_ctr == 0) ? true : false;
|
||||
}
|
||||
|
||||
bool riscv_pmu_ctr_monitor_cycles(CPURISCVState *env, uint32_t target_ctr)
|
||||
{
|
||||
return (target_ctr == 2) ? true : false;
|
||||
}
|
28
target/riscv/pmu.h
Normal file
28
target/riscv/pmu.h
Normal file
@ -0,0 +1,28 @@
|
||||
/*
|
||||
* RISC-V PMU header file.
|
||||
*
|
||||
* Copyright (c) 2021 Western Digital Corporation or its affiliates.
|
||||
*
|
||||
* 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"
|
||||
#include "qemu/log.h"
|
||||
#include "cpu.h"
|
||||
#include "qemu/main-loop.h"
|
||||
#include "exec/exec-all.h"
|
||||
|
||||
bool riscv_pmu_ctr_monitor_instructions(CPURISCVState *env,
|
||||
uint32_t target_ctr);
|
||||
bool riscv_pmu_ctr_monitor_cycles(CPURISCVState *env,
|
||||
uint32_t target_ctr);
|
@ -206,6 +206,13 @@ static void gen_check_nanbox_s(TCGv_i64 out, TCGv_i64 in)
|
||||
tcg_gen_movcond_i64(TCG_COND_GEU, out, in, t_max, in, t_nan);
|
||||
}
|
||||
|
||||
static void decode_save_opc(DisasContext *ctx)
|
||||
{
|
||||
assert(ctx->insn_start != NULL);
|
||||
tcg_set_insn_start_param(ctx->insn_start, 1, ctx->opcode);
|
||||
ctx->insn_start = NULL;
|
||||
}
|
||||
|
||||
static void gen_set_pc_imm(DisasContext *ctx, target_ulong dest)
|
||||
{
|
||||
if (get_xl(ctx) == MXL_RV32) {
|
||||
@ -230,22 +237,17 @@ static void generate_exception(DisasContext *ctx, int excp)
|
||||
ctx->base.is_jmp = DISAS_NORETURN;
|
||||
}
|
||||
|
||||
static void generate_exception_mtval(DisasContext *ctx, int excp)
|
||||
{
|
||||
gen_set_pc_imm(ctx, ctx->base.pc_next);
|
||||
tcg_gen_st_tl(cpu_pc, cpu_env, offsetof(CPURISCVState, badaddr));
|
||||
gen_helper_raise_exception(cpu_env, tcg_constant_i32(excp));
|
||||
ctx->base.is_jmp = DISAS_NORETURN;
|
||||
}
|
||||
|
||||
static void gen_exception_illegal(DisasContext *ctx)
|
||||
{
|
||||
tcg_gen_st_i32(tcg_constant_i32(ctx->opcode), cpu_env,
|
||||
offsetof(CPURISCVState, bins));
|
||||
generate_exception(ctx, RISCV_EXCP_ILLEGAL_INST);
|
||||
}
|
||||
|
||||
static void gen_exception_inst_addr_mis(DisasContext *ctx)
|
||||
{
|
||||
generate_exception_mtval(ctx, RISCV_EXCP_INST_ADDR_MIS);
|
||||
tcg_gen_st_tl(cpu_pc, cpu_env, offsetof(CPURISCVState, badaddr));
|
||||
generate_exception(ctx, RISCV_EXCP_INST_ADDR_MIS);
|
||||
}
|
||||
|
||||
static void gen_goto_tb(DisasContext *ctx, int n, target_ulong dest)
|
||||
@ -640,6 +642,8 @@ static void gen_set_rm(DisasContext *ctx, int rm)
|
||||
return;
|
||||
}
|
||||
|
||||
/* The helper may raise ILLEGAL_INSN -- record binv for unwind. */
|
||||
decode_save_opc(ctx);
|
||||
gen_helper_set_rounding_mode(cpu_env, tcg_constant_i32(rm));
|
||||
}
|
||||
|
||||
@ -1018,13 +1022,6 @@ static uint32_t opcode_at(DisasContextBase *dcbase, target_ulong pc)
|
||||
/* Include decoders for factored-out extensions */
|
||||
#include "decode-XVentanaCondOps.c.inc"
|
||||
|
||||
static inline void decode_save_opc(DisasContext *ctx, target_ulong opc)
|
||||
{
|
||||
assert(ctx->insn_start != NULL);
|
||||
tcg_set_insn_start_param(ctx->insn_start, 1, opc);
|
||||
ctx->insn_start = NULL;
|
||||
}
|
||||
|
||||
static void decode_opc(CPURISCVState *env, DisasContext *ctx, uint16_t opcode)
|
||||
{
|
||||
/*
|
||||
@ -1041,7 +1038,6 @@ static void decode_opc(CPURISCVState *env, DisasContext *ctx, uint16_t opcode)
|
||||
|
||||
/* Check for compressed insn */
|
||||
if (extract16(opcode, 0, 2) != 3) {
|
||||
decode_save_opc(ctx, opcode);
|
||||
if (!has_ext(ctx, RVC)) {
|
||||
gen_exception_illegal(ctx);
|
||||
} else {
|
||||
@ -1056,7 +1052,6 @@ static void decode_opc(CPURISCVState *env, DisasContext *ctx, uint16_t opcode)
|
||||
opcode32 = deposit32(opcode32, 16, 16,
|
||||
translator_lduw(env, &ctx->base,
|
||||
ctx->base.pc_next + 2));
|
||||
decode_save_opc(ctx, opcode32);
|
||||
ctx->opcode = opcode32;
|
||||
ctx->pc_succ_insn = ctx->base.pc_next + 4;
|
||||
|
||||
|
21
tests/tcg/riscv64/Makefile.softmmu-target
Normal file
21
tests/tcg/riscv64/Makefile.softmmu-target
Normal file
@ -0,0 +1,21 @@
|
||||
#
|
||||
# RISC-V system tests
|
||||
#
|
||||
|
||||
TEST_SRC = $(SRC_PATH)/tests/tcg/riscv64
|
||||
VPATH += $(TEST_SRC)
|
||||
|
||||
LINK_SCRIPT = $(TEST_SRC)/semihost.ld
|
||||
LDFLAGS = -T $(LINK_SCRIPT)
|
||||
CFLAGS += -g -Og
|
||||
|
||||
%.o: %.S
|
||||
$(CC) $(CFLAGS) $< -c -o $@
|
||||
%: %.o $(LINK_SCRIPT)
|
||||
$(LD) $(LDFLAGS) $< -o $@
|
||||
|
||||
QEMU_OPTS += -M virt -display none -semihosting -device loader,file=
|
||||
|
||||
EXTRA_RUNS += run-issue1060
|
||||
run-issue1060: issue1060
|
||||
$(call run-test, $<, $(QEMU) $(QEMU_OPTS)$<)
|
53
tests/tcg/riscv64/issue1060.S
Normal file
53
tests/tcg/riscv64/issue1060.S
Normal file
@ -0,0 +1,53 @@
|
||||
.option norvc
|
||||
|
||||
.text
|
||||
.global _start
|
||||
_start:
|
||||
lla t0, trap
|
||||
csrw mtvec, t0
|
||||
|
||||
# These are all illegal instructions
|
||||
csrw time, x0
|
||||
.insn i CUSTOM_0, 0, x0, x0, 0x321
|
||||
csrw time, x0
|
||||
.insn i CUSTOM_0, 0, x0, x0, 0x123
|
||||
csrw cycle, x0
|
||||
|
||||
# Success!
|
||||
li a0, 0
|
||||
j _exit
|
||||
|
||||
trap:
|
||||
# When an instruction traps, compare it to the insn in memory.
|
||||
csrr t0, mepc
|
||||
csrr t1, mtval
|
||||
lwu t2, 0(t0)
|
||||
bne t1, t2, fail
|
||||
|
||||
# Skip the insn and continue.
|
||||
addi t0, t0, 4
|
||||
csrw mepc, t0
|
||||
mret
|
||||
|
||||
fail:
|
||||
li a0, 1
|
||||
|
||||
# Exit code in a0
|
||||
_exit:
|
||||
lla a1, semiargs
|
||||
li t0, 0x20026 # ADP_Stopped_ApplicationExit
|
||||
sd t0, 0(a1)
|
||||
sd a0, 8(a1)
|
||||
li a0, 0x20 # TARGET_SYS_EXIT_EXTENDED
|
||||
|
||||
# Semihosting call sequence
|
||||
.balign 16
|
||||
slli zero, zero, 0x1f
|
||||
ebreak
|
||||
srai zero, zero, 0x7
|
||||
j .
|
||||
|
||||
.data
|
||||
.balign 16
|
||||
semiargs:
|
||||
.space 16
|
21
tests/tcg/riscv64/semihost.ld
Normal file
21
tests/tcg/riscv64/semihost.ld
Normal file
@ -0,0 +1,21 @@
|
||||
ENTRY(_start)
|
||||
|
||||
SECTIONS
|
||||
{
|
||||
/* virt machine, RAM starts at 2gb */
|
||||
. = 0x80000000;
|
||||
.text : {
|
||||
*(.text)
|
||||
}
|
||||
.rodata : {
|
||||
*(.rodata)
|
||||
}
|
||||
/* align r/w section to next 2mb */
|
||||
. = ALIGN(1 << 21);
|
||||
.data : {
|
||||
*(.data)
|
||||
}
|
||||
.bss : {
|
||||
*(.bss)
|
||||
}
|
||||
}
|
Loading…
Reference in New Issue
Block a user