From 6eab278d389bc3569135773265e0d481d89ef82e Mon Sep 17 00:00:00 2001 From: LIU Zhiwei Date: Tue, 9 Jul 2024 19:36:42 +0800 Subject: [PATCH 01/30] target/riscv: Add zimop extension Zimop extension defines an encoding space for 40 MOPs.The Zimop extension defines 32 MOP instructions named MOP.R.n, where n is an integer between 0 and 31, inclusive. The Zimop extension additionally defines 8 MOP instructions named MOP.RR.n, where n is an integer between 0 and 7. These 40 MOPs initially are defined to simply write zero to x[rd], but are designed to be redefined by later extensions to perform some other action. Signed-off-by: LIU Zhiwei Reviewed-by: Alistair Francis Reviewed-by: Deepak Gupta Message-ID: <20240709113652.1239-2-zhiwei_liu@linux.alibaba.com> Signed-off-by: Alistair Francis --- target/riscv/cpu.c | 2 ++ target/riscv/cpu_cfg.h | 1 + target/riscv/insn32.decode | 11 ++++++ target/riscv/insn_trans/trans_rvzimop.c.inc | 37 +++++++++++++++++++++ target/riscv/translate.c | 1 + 5 files changed, 52 insertions(+) create mode 100644 target/riscv/insn_trans/trans_rvzimop.c.inc diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index c53b0d5b40..ac503826ce 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -113,6 +113,7 @@ const RISCVIsaExtData isa_edata_arr[] = { ISA_EXT_DATA_ENTRY(zihintntl, PRIV_VERSION_1_10_0, ext_zihintntl), ISA_EXT_DATA_ENTRY(zihintpause, PRIV_VERSION_1_10_0, ext_zihintpause), ISA_EXT_DATA_ENTRY(zihpm, PRIV_VERSION_1_12_0, ext_zihpm), + ISA_EXT_DATA_ENTRY(zimop, PRIV_VERSION_1_13_0, ext_zimop), ISA_EXT_DATA_ENTRY(zmmul, PRIV_VERSION_1_12_0, ext_zmmul), ISA_EXT_DATA_ENTRY(za64rs, PRIV_VERSION_1_12_0, has_priv_1_11), ISA_EXT_DATA_ENTRY(zaamo, PRIV_VERSION_1_12_0, ext_zaamo), @@ -1471,6 +1472,7 @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = { MULTI_EXT_CFG_BOOL("zicsr", ext_zicsr, true), MULTI_EXT_CFG_BOOL("zihintntl", ext_zihintntl, true), MULTI_EXT_CFG_BOOL("zihintpause", ext_zihintpause, true), + MULTI_EXT_CFG_BOOL("zimop", ext_zimop, false), MULTI_EXT_CFG_BOOL("zacas", ext_zacas, false), MULTI_EXT_CFG_BOOL("zaamo", ext_zaamo, false), MULTI_EXT_CFG_BOOL("zalrsc", ext_zalrsc, false), diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h index fb7eebde52..9f53512053 100644 --- a/target/riscv/cpu_cfg.h +++ b/target/riscv/cpu_cfg.h @@ -71,6 +71,7 @@ struct RISCVCPUConfig { bool ext_zihintntl; bool ext_zihintpause; bool ext_zihpm; + bool ext_zimop; bool ext_ztso; bool ext_smstateen; bool ext_sstc; diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode index f22df04cfd..60da673153 100644 --- a/target/riscv/insn32.decode +++ b/target/riscv/insn32.decode @@ -38,6 +38,8 @@ %imm_bs 30:2 !function=ex_shift_3 %imm_rnum 20:4 %imm_z6 26:1 15:5 +%imm_mop5 30:1 26:2 20:2 +%imm_mop3 30:1 26:2 # Argument sets: &empty @@ -56,6 +58,8 @@ &r2nfvm vm rd rs1 nf &rnfvm vm rd rs1 rs2 nf &k_aes shamt rs2 rs1 rd +&mop5 imm rd rs1 +&mop3 imm rd rs1 rs2 # Formats 32: @r ....... ..... ..... ... ..... ....... &r %rs2 %rs1 %rd @@ -98,6 +102,9 @@ @k_aes .. ..... ..... ..... ... ..... ....... &k_aes shamt=%imm_bs %rs2 %rs1 %rd @i_aes .. ..... ..... ..... ... ..... ....... &i imm=%imm_rnum %rs1 %rd +@mop5 . . .. .. .... .. ..... ... ..... ....... &mop5 imm=%imm_mop5 %rd %rs1 +@mop3 . . .. .. . ..... ..... ... ..... ....... &mop3 imm=%imm_mop3 %rd %rs1 %rs2 + # Formats 64: @sh5 ....... ..... ..... ... ..... ....... &shift shamt=%sh5 %rs1 %rd @@ -1010,3 +1017,7 @@ amocas_w 00101 . . ..... ..... 010 ..... 0101111 @atom_st amocas_d 00101 . . ..... ..... 011 ..... 0101111 @atom_st # *** RV64 Zacas Standard Extension *** amocas_q 00101 . . ..... ..... 100 ..... 0101111 @atom_st + +# *** Zimop may-be-operation extension *** +mop_r_n 1 . 00 .. 0111 .. ..... 100 ..... 1110011 @mop5 +mop_rr_n 1 . 00 .. 1 ..... ..... 100 ..... 1110011 @mop3 diff --git a/target/riscv/insn_trans/trans_rvzimop.c.inc b/target/riscv/insn_trans/trans_rvzimop.c.inc new file mode 100644 index 0000000000..165aacd2b6 --- /dev/null +++ b/target/riscv/insn_trans/trans_rvzimop.c.inc @@ -0,0 +1,37 @@ +/* + * RISC-V translation routines for May-Be-Operation(zimop). + * + * Copyright (c) 2024 Alibaba Group. + * + * 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 . + */ + +#define REQUIRE_ZIMOP(ctx) do { \ + if (!ctx->cfg_ptr->ext_zimop) { \ + return false; \ + } \ +} while (0) + +static bool trans_mop_r_n(DisasContext *ctx, arg_mop_r_n *a) +{ + REQUIRE_ZIMOP(ctx); + gen_set_gpr(ctx, a->rd, ctx->zero); + return true; +} + +static bool trans_mop_rr_n(DisasContext *ctx, arg_mop_rr_n *a) +{ + REQUIRE_ZIMOP(ctx); + gen_set_gpr(ctx, a->rd, ctx->zero); + return true; +} diff --git a/target/riscv/translate.c b/target/riscv/translate.c index 0569224e53..379b68289f 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -1099,6 +1099,7 @@ static uint32_t opcode_at(DisasContextBase *dcbase, target_ulong pc) #include "insn_trans/trans_rvzacas.c.inc" #include "insn_trans/trans_rvzawrs.c.inc" #include "insn_trans/trans_rvzicbo.c.inc" +#include "insn_trans/trans_rvzimop.c.inc" #include "insn_trans/trans_rvzfa.c.inc" #include "insn_trans/trans_rvzfh.c.inc" #include "insn_trans/trans_rvk.c.inc" From d98883d127d0029532601e9ca6832dfcb3ee2ca0 Mon Sep 17 00:00:00 2001 From: LIU Zhiwei Date: Tue, 9 Jul 2024 19:36:43 +0800 Subject: [PATCH 02/30] disas/riscv: Support zimop disassemble Signed-off-by: LIU Zhiwei Acked-by: Alistair Francis Reviewed-by: Deepak Gupta Message-ID: <20240709113652.1239-3-zhiwei_liu@linux.alibaba.com> Signed-off-by: Alistair Francis --- disas/riscv.c | 98 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 98 insertions(+) diff --git a/disas/riscv.c b/disas/riscv.c index 90d6b26de9..0b82ab2322 100644 --- a/disas/riscv.c +++ b/disas/riscv.c @@ -906,6 +906,46 @@ typedef enum { rv_op_amocas_w = 875, rv_op_amocas_d = 876, rv_op_amocas_q = 877, + rv_mop_r_0 = 878, + rv_mop_r_1 = 879, + rv_mop_r_2 = 880, + rv_mop_r_3 = 881, + rv_mop_r_4 = 882, + rv_mop_r_5 = 883, + rv_mop_r_6 = 884, + rv_mop_r_7 = 885, + rv_mop_r_8 = 886, + rv_mop_r_9 = 887, + rv_mop_r_10 = 888, + rv_mop_r_11 = 889, + rv_mop_r_12 = 890, + rv_mop_r_13 = 891, + rv_mop_r_14 = 892, + rv_mop_r_15 = 893, + rv_mop_r_16 = 894, + rv_mop_r_17 = 895, + rv_mop_r_18 = 896, + rv_mop_r_19 = 897, + rv_mop_r_20 = 898, + rv_mop_r_21 = 899, + rv_mop_r_22 = 900, + rv_mop_r_23 = 901, + rv_mop_r_24 = 902, + rv_mop_r_25 = 903, + rv_mop_r_26 = 904, + rv_mop_r_27 = 905, + rv_mop_r_28 = 906, + rv_mop_r_29 = 907, + rv_mop_r_30 = 908, + rv_mop_r_31 = 909, + rv_mop_rr_0 = 910, + rv_mop_rr_1 = 911, + rv_mop_rr_2 = 912, + rv_mop_rr_3 = 913, + rv_mop_rr_4 = 914, + rv_mop_rr_5 = 915, + rv_mop_rr_6 = 916, + rv_mop_rr_7 = 917, } rv_op; /* register names */ @@ -2096,6 +2136,46 @@ const rv_opcode_data rvi_opcode_data[] = { { "amocas.w", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 }, { "amocas.d", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 }, { "amocas.q", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 }, + { "mop.r.0", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 }, + { "mop.r.1", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 }, + { "mop.r.2", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 }, + { "mop.r.3", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 }, + { "mop.r.4", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 }, + { "mop.r.5", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 }, + { "mop.r.6", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 }, + { "mop.r.7", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 }, + { "mop.r.8", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 }, + { "mop.r.9", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 }, + { "mop.r.10", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 }, + { "mop.r.11", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 }, + { "mop.r.12", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 }, + { "mop.r.13", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 }, + { "mop.r.14", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 }, + { "mop.r.15", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 }, + { "mop.r.16", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 }, + { "mop.r.17", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 }, + { "mop.r.18", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 }, + { "mop.r.19", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 }, + { "mop.r.20", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 }, + { "mop.r.21", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 }, + { "mop.r.22", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 }, + { "mop.r.23", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 }, + { "mop.r.24", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 }, + { "mop.r.25", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 }, + { "mop.r.26", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 }, + { "mop.r.27", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 }, + { "mop.r.28", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 }, + { "mop.r.29", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 }, + { "mop.r.30", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 }, + { "mop.r.31", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 }, + { "mop.rr.0", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, + { "mop.rr.1", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, + { "mop.rr.2", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, + { "mop.rr.3", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, + { "mop.rr.4", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, + { "mop.rr.5", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, + { "mop.rr.6", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, + { "mop.rr.7", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, }; /* CSR names */ @@ -3855,6 +3935,24 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa isa) case 1: op = rv_op_csrrw; break; case 2: op = rv_op_csrrs; break; case 3: op = rv_op_csrrc; break; + case 4: + if (dec->cfg->ext_zimop) { + int imm_mop5, imm_mop3; + if ((extract32(inst, 22, 10) & 0b1011001111) + == 0b1000000111) { + imm_mop5 = deposit32(deposit32(extract32(inst, 20, 2), + 2, 2, + extract32(inst, 26, 2)), + 4, 1, extract32(inst, 30, 1)); + op = rv_mop_r_0 + imm_mop5; + } else if ((extract32(inst, 25, 7) & 0b1011001) + == 0b1000001) { + imm_mop3 = deposit32(extract32(inst, 26, 2), + 2, 1, extract32(inst, 30, 1)); + op = rv_mop_rr_0 + imm_mop3; + } + } + break; case 5: op = rv_op_csrrwi; break; case 6: op = rv_op_csrrsi; break; case 7: op = rv_op_csrrci; break; From 197e4d29889453760c74763662e3812d0ec7a645 Mon Sep 17 00:00:00 2001 From: LIU Zhiwei Date: Tue, 9 Jul 2024 19:36:44 +0800 Subject: [PATCH 03/30] target/riscv: Add zcmop extension Zcmop defines eight 16-bit MOP instructions named C.MOP.n, where n is an odd integer between 1 and 15, inclusive. C.MOP.n is encoded in the reserved encoding space corresponding to C.LUI xn, 0. Unlike the MOPs defined in the Zimop extension, the C.MOP.n instructions are defined to not write any register. In current implementation, C.MOP.n only has an check function, without any other more behavior. Signed-off-by: LIU Zhiwei Reviewed-by: Alistair Francis Reviewed-by: Deepak Gupta Message-ID: <20240709113652.1239-4-zhiwei_liu@linux.alibaba.com> Signed-off-by: Alistair Francis --- target/riscv/cpu.c | 2 ++ target/riscv/cpu_cfg.h | 1 + target/riscv/insn16.decode | 1 + target/riscv/insn_trans/trans_rvzcmop.c.inc | 29 +++++++++++++++++++++ target/riscv/tcg/tcg-cpu.c | 5 ++++ target/riscv/translate.c | 1 + 6 files changed, 39 insertions(+) create mode 100644 target/riscv/insn_trans/trans_rvzcmop.c.inc diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index ac503826ce..f4f8287a6d 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -131,6 +131,7 @@ const RISCVIsaExtData isa_edata_arr[] = { ISA_EXT_DATA_ENTRY(zcf, PRIV_VERSION_1_12_0, ext_zcf), ISA_EXT_DATA_ENTRY(zcd, PRIV_VERSION_1_12_0, ext_zcd), ISA_EXT_DATA_ENTRY(zce, PRIV_VERSION_1_12_0, ext_zce), + ISA_EXT_DATA_ENTRY(zcmop, PRIV_VERSION_1_13_0, ext_zcmop), ISA_EXT_DATA_ENTRY(zcmp, PRIV_VERSION_1_12_0, ext_zcmp), ISA_EXT_DATA_ENTRY(zcmt, PRIV_VERSION_1_12_0, ext_zcmt), ISA_EXT_DATA_ENTRY(zba, PRIV_VERSION_1_12_0, ext_zba), @@ -1473,6 +1474,7 @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = { MULTI_EXT_CFG_BOOL("zihintntl", ext_zihintntl, true), MULTI_EXT_CFG_BOOL("zihintpause", ext_zihintpause, true), MULTI_EXT_CFG_BOOL("zimop", ext_zimop, false), + MULTI_EXT_CFG_BOOL("zcmop", ext_zcmop, false), MULTI_EXT_CFG_BOOL("zacas", ext_zacas, false), MULTI_EXT_CFG_BOOL("zaamo", ext_zaamo, false), MULTI_EXT_CFG_BOOL("zalrsc", ext_zalrsc, false), diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h index 9f53512053..d85e54b475 100644 --- a/target/riscv/cpu_cfg.h +++ b/target/riscv/cpu_cfg.h @@ -72,6 +72,7 @@ struct RISCVCPUConfig { bool ext_zihintpause; bool ext_zihpm; bool ext_zimop; + bool ext_zcmop; bool ext_ztso; bool ext_smstateen; bool ext_sstc; diff --git a/target/riscv/insn16.decode b/target/riscv/insn16.decode index b96c534e73..3953bcf82d 100644 --- a/target/riscv/insn16.decode +++ b/target/riscv/insn16.decode @@ -140,6 +140,7 @@ sw 110 ... ... .. ... 00 @cs_w addi 000 . ..... ..... 01 @ci addi 010 . ..... ..... 01 @c_li { + c_mop_n 011 0 0 n:3 1 00000 01 illegal 011 0 ----- 00000 01 # c.addi16sp and c.lui, RES nzimm=0 addi 011 . 00010 ..... 01 @c_addi16sp lui 011 . ..... ..... 01 @c_lui diff --git a/target/riscv/insn_trans/trans_rvzcmop.c.inc b/target/riscv/insn_trans/trans_rvzcmop.c.inc new file mode 100644 index 0000000000..7205586508 --- /dev/null +++ b/target/riscv/insn_trans/trans_rvzcmop.c.inc @@ -0,0 +1,29 @@ +/* + * RISC-V translation routines for compressed May-Be-Operation(zcmop). + * + * Copyright (c) 2024 Alibaba Group. + * + * 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 . + */ + +#define REQUIRE_ZCMOP(ctx) do { \ + if (!ctx->cfg_ptr->ext_zcmop) { \ + return false; \ + } \ +} while (0) + +static bool trans_c_mop_n(DisasContext *ctx, arg_c_mop_n *a) +{ + REQUIRE_ZCMOP(ctx); + return true; +} diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c index ecf366d6c7..b8814ab753 100644 --- a/target/riscv/tcg/tcg-cpu.c +++ b/target/riscv/tcg/tcg-cpu.c @@ -549,6 +549,11 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp) } } + if (cpu->cfg.ext_zcmop && !cpu->cfg.ext_zca) { + error_setg(errp, "Zcmop extensions require Zca"); + return; + } + if (mcc->misa_mxl_max != MXL_RV32 && cpu->cfg.ext_zcf) { error_setg(errp, "Zcf extension is only relevant to RV32"); return; diff --git a/target/riscv/translate.c b/target/riscv/translate.c index 379b68289f..8a546f4ece 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -1114,6 +1114,7 @@ static uint32_t opcode_at(DisasContextBase *dcbase, target_ulong pc) /* Include the auto-generated decoder for 16 bit insn */ #include "decode-insn16.c.inc" #include "insn_trans/trans_rvzce.c.inc" +#include "insn_trans/trans_rvzcmop.c.inc" /* Include decoders for factored-out extensions */ #include "decode-XVentanaCondOps.c.inc" From 67e98ebad063e8b028466a754578dd8386aaa5f6 Mon Sep 17 00:00:00 2001 From: LIU Zhiwei Date: Tue, 9 Jul 2024 19:36:45 +0800 Subject: [PATCH 04/30] disas/riscv: Support zcmop disassemble Although in QEMU disassemble, we usually lift compressed instruction to an normal format when display the instruction name. For C.MOP.n, it is more reasonable to directly display its compressed name, because its behavior can be redefined by later extension. Signed-off-by: LIU Zhiwei Acked-by: Alistair Francis Reviewed-by: Deepak Gupta Message-ID: <20240709113652.1239-5-zhiwei_liu@linux.alibaba.com> Signed-off-by: Alistair Francis --- disas/riscv.c | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/disas/riscv.c b/disas/riscv.c index 0b82ab2322..d29cb1ff7d 100644 --- a/disas/riscv.c +++ b/disas/riscv.c @@ -946,6 +946,14 @@ typedef enum { rv_mop_rr_5 = 915, rv_mop_rr_6 = 916, rv_mop_rr_7 = 917, + rv_c_mop_1 = 918, + rv_c_mop_3 = 919, + rv_c_mop_5 = 920, + rv_c_mop_7 = 921, + rv_c_mop_9 = 922, + rv_c_mop_11 = 923, + rv_c_mop_13 = 924, + rv_c_mop_15 = 925, } rv_op; /* register names */ @@ -2176,6 +2184,14 @@ const rv_opcode_data rvi_opcode_data[] = { { "mop.rr.5", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, { "mop.rr.6", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, { "mop.rr.7", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 }, + { "c.mop.1", rv_codec_ci_none, rv_fmt_none, NULL, 0, 0, 0 }, + { "c.mop.3", rv_codec_ci_none, rv_fmt_none, NULL, 0, 0, 0 }, + { "c.mop.5", rv_codec_ci_none, rv_fmt_none, NULL, 0, 0, 0 }, + { "c.mop.7", rv_codec_ci_none, rv_fmt_none, NULL, 0, 0, 0 }, + { "c.mop.9", rv_codec_ci_none, rv_fmt_none, NULL, 0, 0, 0 }, + { "c.mop.11", rv_codec_ci_none, rv_fmt_none, NULL, 0, 0, 0 }, + { "c.mop.13", rv_codec_ci_none, rv_fmt_none, NULL, 0, 0, 0 }, + { "c.mop.15", rv_codec_ci_none, rv_fmt_none, NULL, 0, 0, 0 }, }; /* CSR names */ @@ -2532,6 +2548,13 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa isa) break; case 2: op = rv_op_c_li; break; case 3: + if (dec->cfg->ext_zcmop) { + if ((((inst >> 2) & 0b111111) == 0b100000) && + (((inst >> 11) & 0b11) == 0b0)) { + op = rv_c_mop_1 + ((inst >> 8) & 0b111); + break; + } + } switch ((inst >> 7) & 0b11111) { case 2: op = rv_op_c_addi16sp; break; default: op = rv_op_c_lui; break; From a60ce58fd971bdcbec6ba96ce989fd399ca1f2d7 Mon Sep 17 00:00:00 2001 From: LIU Zhiwei Date: Tue, 9 Jul 2024 19:36:46 +0800 Subject: [PATCH 05/30] target/riscv: Support Zama16b extension MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit Zama16b is the property that misaligned load/stores/atomics within a naturally aligned 16-byte region are atomic. According to the specification, Zama16b applies only to AMOs, loads and stores defined in the base ISAs, and loads and stores of no more than XLEN bits defined in the F, D, and Q extensions. Thus it should not apply to zacas or RVC instructions. For an instruction in that set, if all accessed bytes lie within 16B granule, the instruction will not raise an exception for reasons of address alignment, and the instruction will give rise to only one memory operation for the purposes of RVWMO—i.e., it will execute atomically. Signed-off-by: LIU Zhiwei Reviewed-by: Alistair Francis Message-ID: <20240709113652.1239-6-zhiwei_liu@linux.alibaba.com> Signed-off-by: Alistair Francis --- target/riscv/cpu.c | 2 ++ target/riscv/cpu_cfg.h | 1 + target/riscv/insn_trans/trans_rva.c.inc | 42 ++++++++++++++----------- target/riscv/insn_trans/trans_rvd.c.inc | 14 +++++++-- target/riscv/insn_trans/trans_rvf.c.inc | 14 +++++++-- target/riscv/insn_trans/trans_rvi.c.inc | 6 ++++ 6 files changed, 57 insertions(+), 22 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index f4f8287a6d..de9c06904f 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -118,6 +118,7 @@ const RISCVIsaExtData isa_edata_arr[] = { ISA_EXT_DATA_ENTRY(za64rs, PRIV_VERSION_1_12_0, has_priv_1_11), ISA_EXT_DATA_ENTRY(zaamo, PRIV_VERSION_1_12_0, ext_zaamo), ISA_EXT_DATA_ENTRY(zacas, PRIV_VERSION_1_12_0, ext_zacas), + ISA_EXT_DATA_ENTRY(zama16b, PRIV_VERSION_1_13_0, ext_zama16b), ISA_EXT_DATA_ENTRY(zalrsc, PRIV_VERSION_1_12_0, ext_zalrsc), ISA_EXT_DATA_ENTRY(zawrs, PRIV_VERSION_1_12_0, ext_zawrs), ISA_EXT_DATA_ENTRY(zfa, PRIV_VERSION_1_12_0, ext_zfa), @@ -1476,6 +1477,7 @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = { MULTI_EXT_CFG_BOOL("zimop", ext_zimop, false), MULTI_EXT_CFG_BOOL("zcmop", ext_zcmop, false), MULTI_EXT_CFG_BOOL("zacas", ext_zacas, false), + MULTI_EXT_CFG_BOOL("zama16b", ext_zama16b, false), MULTI_EXT_CFG_BOOL("zaamo", ext_zaamo, false), MULTI_EXT_CFG_BOOL("zalrsc", ext_zalrsc, false), MULTI_EXT_CFG_BOOL("zawrs", ext_zawrs, true), diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h index d85e54b475..ddbfae37e5 100644 --- a/target/riscv/cpu_cfg.h +++ b/target/riscv/cpu_cfg.h @@ -83,6 +83,7 @@ struct RISCVCPUConfig { bool ext_zdinx; bool ext_zaamo; bool ext_zacas; + bool ext_zama16b; bool ext_zalrsc; bool ext_zawrs; bool ext_zfa; diff --git a/target/riscv/insn_trans/trans_rva.c.inc b/target/riscv/insn_trans/trans_rva.c.inc index 4a9e4591d1..eb080baddd 100644 --- a/target/riscv/insn_trans/trans_rva.c.inc +++ b/target/riscv/insn_trans/trans_rva.c.inc @@ -103,6 +103,12 @@ static bool gen_amo(DisasContext *ctx, arg_atomic *a, TCGv dest = dest_gpr(ctx, a->rd); TCGv src1, src2 = get_gpr(ctx, a->rs2, EXT_NONE); + if (ctx->cfg_ptr->ext_zama16b) { + mop |= MO_ATOM_WITHIN16; + } else { + mop |= MO_ALIGN; + } + decode_save_opc(ctx); src1 = get_address(ctx, a->rs1, 0); func(dest, src1, src2, ctx->mem_idx, mop); @@ -126,55 +132,55 @@ static bool trans_sc_w(DisasContext *ctx, arg_sc_w *a) static bool trans_amoswap_w(DisasContext *ctx, arg_amoswap_w *a) { REQUIRE_A_OR_ZAAMO(ctx); - return gen_amo(ctx, a, &tcg_gen_atomic_xchg_tl, (MO_ALIGN | MO_TESL)); + return gen_amo(ctx, a, &tcg_gen_atomic_xchg_tl, MO_TESL); } static bool trans_amoadd_w(DisasContext *ctx, arg_amoadd_w *a) { REQUIRE_A_OR_ZAAMO(ctx); - return gen_amo(ctx, a, &tcg_gen_atomic_fetch_add_tl, (MO_ALIGN | MO_TESL)); + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_add_tl, MO_TESL); } static bool trans_amoxor_w(DisasContext *ctx, arg_amoxor_w *a) { REQUIRE_A_OR_ZAAMO(ctx); - return gen_amo(ctx, a, &tcg_gen_atomic_fetch_xor_tl, (MO_ALIGN | MO_TESL)); + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_xor_tl, MO_TESL); } static bool trans_amoand_w(DisasContext *ctx, arg_amoand_w *a) { REQUIRE_A_OR_ZAAMO(ctx); - return gen_amo(ctx, a, &tcg_gen_atomic_fetch_and_tl, (MO_ALIGN | MO_TESL)); + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_and_tl, MO_TESL); } static bool trans_amoor_w(DisasContext *ctx, arg_amoor_w *a) { REQUIRE_A_OR_ZAAMO(ctx); - return gen_amo(ctx, a, &tcg_gen_atomic_fetch_or_tl, (MO_ALIGN | MO_TESL)); + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_or_tl, MO_TESL); } static bool trans_amomin_w(DisasContext *ctx, arg_amomin_w *a) { REQUIRE_A_OR_ZAAMO(ctx); - return gen_amo(ctx, a, &tcg_gen_atomic_fetch_smin_tl, (MO_ALIGN | MO_TESL)); + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_smin_tl, MO_TESL); } static bool trans_amomax_w(DisasContext *ctx, arg_amomax_w *a) { REQUIRE_A_OR_ZAAMO(ctx); - return gen_amo(ctx, a, &tcg_gen_atomic_fetch_smax_tl, (MO_ALIGN | MO_TESL)); + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_smax_tl, MO_TESL); } static bool trans_amominu_w(DisasContext *ctx, arg_amominu_w *a) { REQUIRE_A_OR_ZAAMO(ctx); - return gen_amo(ctx, a, &tcg_gen_atomic_fetch_umin_tl, (MO_ALIGN | MO_TESL)); + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_umin_tl, MO_TESL); } static bool trans_amomaxu_w(DisasContext *ctx, arg_amomaxu_w *a) { REQUIRE_A_OR_ZAAMO(ctx); - return gen_amo(ctx, a, &tcg_gen_atomic_fetch_umax_tl, (MO_ALIGN | MO_TESL)); + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_umax_tl, MO_TESL); } static bool trans_lr_d(DisasContext *ctx, arg_lr_d *a) @@ -195,61 +201,61 @@ static bool trans_amoswap_d(DisasContext *ctx, arg_amoswap_d *a) { REQUIRE_64BIT(ctx); REQUIRE_A_OR_ZAAMO(ctx); - return gen_amo(ctx, a, &tcg_gen_atomic_xchg_tl, (MO_ALIGN | MO_TEUQ)); + return gen_amo(ctx, a, &tcg_gen_atomic_xchg_tl, MO_TEUQ); } static bool trans_amoadd_d(DisasContext *ctx, arg_amoadd_d *a) { REQUIRE_64BIT(ctx); REQUIRE_A_OR_ZAAMO(ctx); - return gen_amo(ctx, a, &tcg_gen_atomic_fetch_add_tl, (MO_ALIGN | MO_TEUQ)); + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_add_tl, MO_TEUQ); } static bool trans_amoxor_d(DisasContext *ctx, arg_amoxor_d *a) { REQUIRE_64BIT(ctx); REQUIRE_A_OR_ZAAMO(ctx); - return gen_amo(ctx, a, &tcg_gen_atomic_fetch_xor_tl, (MO_ALIGN | MO_TEUQ)); + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_xor_tl, MO_TEUQ); } static bool trans_amoand_d(DisasContext *ctx, arg_amoand_d *a) { REQUIRE_64BIT(ctx); REQUIRE_A_OR_ZAAMO(ctx); - return gen_amo(ctx, a, &tcg_gen_atomic_fetch_and_tl, (MO_ALIGN | MO_TEUQ)); + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_and_tl, MO_TEUQ); } static bool trans_amoor_d(DisasContext *ctx, arg_amoor_d *a) { REQUIRE_64BIT(ctx); REQUIRE_A_OR_ZAAMO(ctx); - return gen_amo(ctx, a, &tcg_gen_atomic_fetch_or_tl, (MO_ALIGN | MO_TEUQ)); + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_or_tl, MO_TEUQ); } static bool trans_amomin_d(DisasContext *ctx, arg_amomin_d *a) { REQUIRE_64BIT(ctx); REQUIRE_A_OR_ZAAMO(ctx); - return gen_amo(ctx, a, &tcg_gen_atomic_fetch_smin_tl, (MO_ALIGN | MO_TEUQ)); + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_smin_tl, MO_TEUQ); } static bool trans_amomax_d(DisasContext *ctx, arg_amomax_d *a) { REQUIRE_64BIT(ctx); REQUIRE_A_OR_ZAAMO(ctx); - return gen_amo(ctx, a, &tcg_gen_atomic_fetch_smax_tl, (MO_ALIGN | MO_TEUQ)); + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_smax_tl, MO_TEUQ); } static bool trans_amominu_d(DisasContext *ctx, arg_amominu_d *a) { REQUIRE_64BIT(ctx); REQUIRE_A_OR_ZAAMO(ctx); - return gen_amo(ctx, a, &tcg_gen_atomic_fetch_umin_tl, (MO_ALIGN | MO_TEUQ)); + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_umin_tl, MO_TEUQ); } static bool trans_amomaxu_d(DisasContext *ctx, arg_amomaxu_d *a) { REQUIRE_64BIT(ctx); REQUIRE_A_OR_ZAAMO(ctx); - return gen_amo(ctx, a, &tcg_gen_atomic_fetch_umax_tl, (MO_ALIGN | MO_TEUQ)); + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_umax_tl, MO_TEUQ); } diff --git a/target/riscv/insn_trans/trans_rvd.c.inc b/target/riscv/insn_trans/trans_rvd.c.inc index d9ce9e407f..1f5fac65a2 100644 --- a/target/riscv/insn_trans/trans_rvd.c.inc +++ b/target/riscv/insn_trans/trans_rvd.c.inc @@ -42,13 +42,18 @@ static bool trans_fld(DisasContext *ctx, arg_fld *a) { TCGv addr; + MemOp memop = MO_TEUQ; REQUIRE_FPU; REQUIRE_EXT(ctx, RVD); + if (ctx->cfg_ptr->ext_zama16b && (ctx->cur_insn_len != 2)) { + memop |= MO_ATOM_WITHIN16; + } + decode_save_opc(ctx); addr = get_address(ctx, a->rs1, a->imm); - tcg_gen_qemu_ld_i64(cpu_fpr[a->rd], addr, ctx->mem_idx, MO_TEUQ); + tcg_gen_qemu_ld_i64(cpu_fpr[a->rd], addr, ctx->mem_idx, memop); mark_fs_dirty(ctx); return true; @@ -57,13 +62,18 @@ static bool trans_fld(DisasContext *ctx, arg_fld *a) static bool trans_fsd(DisasContext *ctx, arg_fsd *a) { TCGv addr; + MemOp memop = MO_TEUQ; REQUIRE_FPU; REQUIRE_EXT(ctx, RVD); + if (ctx->cfg_ptr->ext_zama16b && (ctx->cur_insn_len != 2)) { + memop |= MO_ATOM_WITHIN16; + } + decode_save_opc(ctx); addr = get_address(ctx, a->rs1, a->imm); - tcg_gen_qemu_st_i64(cpu_fpr[a->rs2], addr, ctx->mem_idx, MO_TEUQ); + tcg_gen_qemu_st_i64(cpu_fpr[a->rs2], addr, ctx->mem_idx, memop); return true; } diff --git a/target/riscv/insn_trans/trans_rvf.c.inc b/target/riscv/insn_trans/trans_rvf.c.inc index 97a368970b..f771aa1939 100644 --- a/target/riscv/insn_trans/trans_rvf.c.inc +++ b/target/riscv/insn_trans/trans_rvf.c.inc @@ -43,14 +43,19 @@ static bool trans_flw(DisasContext *ctx, arg_flw *a) { TCGv_i64 dest; TCGv addr; + MemOp memop = MO_TEUL; REQUIRE_FPU; REQUIRE_EXT(ctx, RVF); + if (ctx->cfg_ptr->ext_zama16b && (ctx->cur_insn_len != 2)) { + memop |= MO_ATOM_WITHIN16; + } + decode_save_opc(ctx); addr = get_address(ctx, a->rs1, a->imm); dest = cpu_fpr[a->rd]; - tcg_gen_qemu_ld_i64(dest, addr, ctx->mem_idx, MO_TEUL); + tcg_gen_qemu_ld_i64(dest, addr, ctx->mem_idx, memop); gen_nanbox_s(dest, dest); mark_fs_dirty(ctx); @@ -60,13 +65,18 @@ static bool trans_flw(DisasContext *ctx, arg_flw *a) static bool trans_fsw(DisasContext *ctx, arg_fsw *a) { TCGv addr; + MemOp memop = MO_TEUL; REQUIRE_FPU; REQUIRE_EXT(ctx, RVF); + if (ctx->cfg_ptr->ext_zama16b && (ctx->cur_insn_len != 2)) { + memop |= MO_ATOM_WITHIN16; + } + decode_save_opc(ctx); addr = get_address(ctx, a->rs1, a->imm); - tcg_gen_qemu_st_i64(cpu_fpr[a->rs2], addr, ctx->mem_idx, MO_TEUL); + tcg_gen_qemu_st_i64(cpu_fpr[a->rs2], addr, ctx->mem_idx, memop); return true; } diff --git a/target/riscv/insn_trans/trans_rvi.c.inc b/target/riscv/insn_trans/trans_rvi.c.inc index ad40d3e87f..98e3806d5e 100644 --- a/target/riscv/insn_trans/trans_rvi.c.inc +++ b/target/riscv/insn_trans/trans_rvi.c.inc @@ -268,6 +268,9 @@ static bool gen_load(DisasContext *ctx, arg_lb *a, MemOp memop) { bool out; + if (ctx->cfg_ptr->ext_zama16b && (ctx->cur_insn_len != 2)) { + memop |= MO_ATOM_WITHIN16; + } decode_save_opc(ctx); if (get_xl(ctx) == MXL_RV128) { out = gen_load_i128(ctx, a, memop); @@ -366,6 +369,9 @@ static bool gen_store_i128(DisasContext *ctx, arg_sb *a, MemOp memop) static bool gen_store(DisasContext *ctx, arg_sb *a, MemOp memop) { + if (ctx->cfg_ptr->ext_zama16b && (ctx->cur_insn_len != 2)) { + memop |= MO_ATOM_WITHIN16; + } decode_save_opc(ctx); if (get_xl(ctx) == MXL_RV128) { return gen_store_i128(ctx, a, memop); From 24da9cbacacadaf95fbddc11da81ff68d3b1e795 Mon Sep 17 00:00:00 2001 From: LIU Zhiwei Date: Tue, 9 Jul 2024 19:36:47 +0800 Subject: [PATCH 06/30] target/riscv: Move gen_amo before implement Zabha Signed-off-by: LIU Zhiwei Acked-by: Alistair Francis Message-ID: <20240709113652.1239-7-zhiwei_liu@linux.alibaba.com> Signed-off-by: Alistair Francis --- target/riscv/insn_trans/trans_rva.c.inc | 21 --------------------- target/riscv/translate.c | 21 +++++++++++++++++++++ 2 files changed, 21 insertions(+), 21 deletions(-) diff --git a/target/riscv/insn_trans/trans_rva.c.inc b/target/riscv/insn_trans/trans_rva.c.inc index eb080baddd..39bbf60f3c 100644 --- a/target/riscv/insn_trans/trans_rva.c.inc +++ b/target/riscv/insn_trans/trans_rva.c.inc @@ -96,27 +96,6 @@ static bool gen_sc(DisasContext *ctx, arg_atomic *a, MemOp mop) return true; } -static bool gen_amo(DisasContext *ctx, arg_atomic *a, - void(*func)(TCGv, TCGv, TCGv, TCGArg, MemOp), - MemOp mop) -{ - TCGv dest = dest_gpr(ctx, a->rd); - TCGv src1, src2 = get_gpr(ctx, a->rs2, EXT_NONE); - - if (ctx->cfg_ptr->ext_zama16b) { - mop |= MO_ATOM_WITHIN16; - } else { - mop |= MO_ALIGN; - } - - decode_save_opc(ctx); - src1 = get_address(ctx, a->rs1, 0); - func(dest, src1, src2, ctx->mem_idx, mop); - - gen_set_gpr(ctx, a->rd, dest); - return true; -} - static bool trans_lr_w(DisasContext *ctx, arg_lr_w *a) { REQUIRE_A_OR_ZALRSC(ctx); diff --git a/target/riscv/translate.c b/target/riscv/translate.c index 8a546f4ece..133550d6e2 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -1077,6 +1077,27 @@ static bool gen_unary_per_ol(DisasContext *ctx, arg_r2 *a, DisasExtend ext, return gen_unary(ctx, a, ext, f_tl); } +static bool gen_amo(DisasContext *ctx, arg_atomic *a, + void(*func)(TCGv, TCGv, TCGv, TCGArg, MemOp), + MemOp mop) +{ + TCGv dest = dest_gpr(ctx, a->rd); + TCGv src1, src2 = get_gpr(ctx, a->rs2, EXT_NONE); + + if (ctx->cfg_ptr->ext_zama16b) { + mop |= MO_ATOM_WITHIN16; + } else { + mop |= MO_ALIGN; + } + + decode_save_opc(ctx); + src1 = get_address(ctx, a->rs1, 0); + func(dest, src1, src2, ctx->mem_idx, mop); + + gen_set_gpr(ctx, a->rd, dest); + return true; +} + static uint32_t opcode_at(DisasContextBase *dcbase, target_ulong pc) { DisasContext *ctx = container_of(dcbase, DisasContext, base); From be4a8db7f304347395b081ae5848bad2f507d0c4 Mon Sep 17 00:00:00 2001 From: LIU Zhiwei Date: Tue, 9 Jul 2024 19:36:48 +0800 Subject: [PATCH 07/30] target/riscv: Add AMO instructions for Zabha Signed-off-by: LIU Zhiwei Acked-by: Alistair Francis Message-ID: <20240709113652.1239-8-zhiwei_liu@linux.alibaba.com> Signed-off-by: Alistair Francis --- target/riscv/cpu_cfg.h | 1 + target/riscv/insn32.decode | 20 +++ target/riscv/insn_trans/trans_rvzabha.c.inc | 131 ++++++++++++++++++++ target/riscv/translate.c | 4 +- 4 files changed, 155 insertions(+), 1 deletion(-) create mode 100644 target/riscv/insn_trans/trans_rvzabha.c.inc diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h index ddbfae37e5..120905a254 100644 --- a/target/riscv/cpu_cfg.h +++ b/target/riscv/cpu_cfg.h @@ -84,6 +84,7 @@ struct RISCVCPUConfig { bool ext_zaamo; bool ext_zacas; bool ext_zama16b; + bool ext_zabha; bool ext_zalrsc; bool ext_zawrs; bool ext_zfa; diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode index 60da673153..3bad6372f2 100644 --- a/target/riscv/insn32.decode +++ b/target/riscv/insn32.decode @@ -1021,3 +1021,23 @@ amocas_q 00101 . . ..... ..... 100 ..... 0101111 @atom_st # *** Zimop may-be-operation extension *** mop_r_n 1 . 00 .. 0111 .. ..... 100 ..... 1110011 @mop5 mop_rr_n 1 . 00 .. 1 ..... ..... 100 ..... 1110011 @mop3 + +# *** Zabhb Standard Extension *** +amoswap_b 00001 . . ..... ..... 000 ..... 0101111 @atom_st +amoadd_b 00000 . . ..... ..... 000 ..... 0101111 @atom_st +amoxor_b 00100 . . ..... ..... 000 ..... 0101111 @atom_st +amoand_b 01100 . . ..... ..... 000 ..... 0101111 @atom_st +amoor_b 01000 . . ..... ..... 000 ..... 0101111 @atom_st +amomin_b 10000 . . ..... ..... 000 ..... 0101111 @atom_st +amomax_b 10100 . . ..... ..... 000 ..... 0101111 @atom_st +amominu_b 11000 . . ..... ..... 000 ..... 0101111 @atom_st +amomaxu_b 11100 . . ..... ..... 000 ..... 0101111 @atom_st +amoswap_h 00001 . . ..... ..... 001 ..... 0101111 @atom_st +amoadd_h 00000 . . ..... ..... 001 ..... 0101111 @atom_st +amoxor_h 00100 . . ..... ..... 001 ..... 0101111 @atom_st +amoand_h 01100 . . ..... ..... 001 ..... 0101111 @atom_st +amoor_h 01000 . . ..... ..... 001 ..... 0101111 @atom_st +amomin_h 10000 . . ..... ..... 001 ..... 0101111 @atom_st +amomax_h 10100 . . ..... ..... 001 ..... 0101111 @atom_st +amominu_h 11000 . . ..... ..... 001 ..... 0101111 @atom_st +amomaxu_h 11100 . . ..... ..... 001 ..... 0101111 @atom_st diff --git a/target/riscv/insn_trans/trans_rvzabha.c.inc b/target/riscv/insn_trans/trans_rvzabha.c.inc new file mode 100644 index 0000000000..9093a1cfc1 --- /dev/null +++ b/target/riscv/insn_trans/trans_rvzabha.c.inc @@ -0,0 +1,131 @@ +/* + * RISC-V translation routines for the Zabha Standard Extension. + * + * Copyright (c) 2024 Alibaba Group + * + * 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 . + */ + +#define REQUIRE_ZABHA(ctx) do { \ + if (!ctx->cfg_ptr->ext_zabha) { \ + return false; \ + } \ +} while (0) + +static bool trans_amoswap_b(DisasContext *ctx, arg_amoswap_b *a) +{ + REQUIRE_ZABHA(ctx); + return gen_amo(ctx, a, &tcg_gen_atomic_xchg_tl, MO_SB); +} + +static bool trans_amoadd_b(DisasContext *ctx, arg_amoadd_b *a) +{ + REQUIRE_ZABHA(ctx); + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_add_tl, MO_SB); +} + +static bool trans_amoxor_b(DisasContext *ctx, arg_amoxor_b *a) +{ + REQUIRE_ZABHA(ctx); + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_xor_tl, MO_SB); +} + +static bool trans_amoand_b(DisasContext *ctx, arg_amoand_b *a) +{ + REQUIRE_ZABHA(ctx); + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_and_tl, MO_SB); +} + +static bool trans_amoor_b(DisasContext *ctx, arg_amoor_b *a) +{ + REQUIRE_ZABHA(ctx); + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_or_tl, MO_SB); +} + +static bool trans_amomin_b(DisasContext *ctx, arg_amomin_b *a) +{ + REQUIRE_ZABHA(ctx); + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_smin_tl, MO_SB); +} + +static bool trans_amomax_b(DisasContext *ctx, arg_amomax_b *a) +{ + REQUIRE_ZABHA(ctx); + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_smax_tl, MO_SB); +} + +static bool trans_amominu_b(DisasContext *ctx, arg_amominu_b *a) +{ + REQUIRE_ZABHA(ctx); + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_umin_tl, MO_SB); +} + +static bool trans_amomaxu_b(DisasContext *ctx, arg_amomaxu_b *a) +{ + REQUIRE_ZABHA(ctx); + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_umax_tl, MO_SB); +} + +static bool trans_amoswap_h(DisasContext *ctx, arg_amoswap_h *a) +{ + REQUIRE_ZABHA(ctx); + return gen_amo(ctx, a, &tcg_gen_atomic_xchg_tl, MO_TESW); +} + +static bool trans_amoadd_h(DisasContext *ctx, arg_amoadd_h *a) +{ + REQUIRE_ZABHA(ctx); + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_add_tl, MO_TESW); +} + +static bool trans_amoxor_h(DisasContext *ctx, arg_amoxor_h *a) +{ + REQUIRE_ZABHA(ctx); + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_xor_tl, MO_TESW); +} + +static bool trans_amoand_h(DisasContext *ctx, arg_amoand_h *a) +{ + REQUIRE_ZABHA(ctx); + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_and_tl, MO_TESW); +} + +static bool trans_amoor_h(DisasContext *ctx, arg_amoor_h *a) +{ + REQUIRE_ZABHA(ctx); + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_or_tl, MO_TESW); +} + +static bool trans_amomin_h(DisasContext *ctx, arg_amomin_h *a) +{ + REQUIRE_ZABHA(ctx); + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_smin_tl, MO_TESW); +} + +static bool trans_amomax_h(DisasContext *ctx, arg_amomax_h *a) +{ + REQUIRE_ZABHA(ctx); + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_smax_tl, MO_TESW); +} + +static bool trans_amominu_h(DisasContext *ctx, arg_amominu_h *a) +{ + REQUIRE_ZABHA(ctx); + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_umin_tl, MO_TESW); +} + +static bool trans_amomaxu_h(DisasContext *ctx, arg_amomaxu_h *a) +{ + REQUIRE_ZABHA(ctx); + return gen_amo(ctx, a, &tcg_gen_atomic_fetch_umax_tl, MO_TESW); +} diff --git a/target/riscv/translate.c b/target/riscv/translate.c index 133550d6e2..4a3e786560 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -1083,8 +1083,9 @@ static bool gen_amo(DisasContext *ctx, arg_atomic *a, { TCGv dest = dest_gpr(ctx, a->rd); TCGv src1, src2 = get_gpr(ctx, a->rs2, EXT_NONE); + MemOp size = mop & MO_SIZE; - if (ctx->cfg_ptr->ext_zama16b) { + if (ctx->cfg_ptr->ext_zama16b && size >= MO_32) { mop |= MO_ATOM_WITHIN16; } else { mop |= MO_ALIGN; @@ -1118,6 +1119,7 @@ static uint32_t opcode_at(DisasContextBase *dcbase, target_ulong pc) #include "insn_trans/trans_rvb.c.inc" #include "insn_trans/trans_rvzicond.c.inc" #include "insn_trans/trans_rvzacas.c.inc" +#include "insn_trans/trans_rvzabha.c.inc" #include "insn_trans/trans_rvzawrs.c.inc" #include "insn_trans/trans_rvzicbo.c.inc" #include "insn_trans/trans_rvzimop.c.inc" From 8d07887bcbf13749224bd10b0303f7a79a959edb Mon Sep 17 00:00:00 2001 From: LIU Zhiwei Date: Tue, 9 Jul 2024 19:36:49 +0800 Subject: [PATCH 08/30] target/riscv: Move gen_cmpxchg before adding amocas.[b|h] Signed-off-by: LIU Zhiwei Acked-by: Alistair Francis Message-ID: <20240709113652.1239-9-zhiwei_liu@linux.alibaba.com> Signed-off-by: Alistair Francis --- target/riscv/insn_trans/trans_rvzacas.c.inc | 13 ------------- target/riscv/translate.c | 13 +++++++++++++ 2 files changed, 13 insertions(+), 13 deletions(-) diff --git a/target/riscv/insn_trans/trans_rvzacas.c.inc b/target/riscv/insn_trans/trans_rvzacas.c.inc index 5d274d4c08..fcced99fc7 100644 --- a/target/riscv/insn_trans/trans_rvzacas.c.inc +++ b/target/riscv/insn_trans/trans_rvzacas.c.inc @@ -22,19 +22,6 @@ } \ } while (0) -static bool gen_cmpxchg(DisasContext *ctx, arg_atomic *a, MemOp mop) -{ - TCGv dest = get_gpr(ctx, a->rd, EXT_NONE); - TCGv src1 = get_address(ctx, a->rs1, 0); - TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE); - - decode_save_opc(ctx); - tcg_gen_atomic_cmpxchg_tl(dest, src1, dest, src2, ctx->mem_idx, mop); - - gen_set_gpr(ctx, a->rd, dest); - return true; -} - static bool trans_amocas_w(DisasContext *ctx, arg_amocas_w *a) { REQUIRE_ZACAS(ctx); diff --git a/target/riscv/translate.c b/target/riscv/translate.c index 4a3e786560..acba90f170 100644 --- a/target/riscv/translate.c +++ b/target/riscv/translate.c @@ -1099,6 +1099,19 @@ static bool gen_amo(DisasContext *ctx, arg_atomic *a, return true; } +static bool gen_cmpxchg(DisasContext *ctx, arg_atomic *a, MemOp mop) +{ + TCGv dest = get_gpr(ctx, a->rd, EXT_NONE); + TCGv src1 = get_address(ctx, a->rs1, 0); + TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE); + + decode_save_opc(ctx); + tcg_gen_atomic_cmpxchg_tl(dest, src1, dest, src2, ctx->mem_idx, mop); + + gen_set_gpr(ctx, a->rd, dest); + return true; +} + static uint32_t opcode_at(DisasContextBase *dcbase, target_ulong pc) { DisasContext *ctx = container_of(dcbase, DisasContext, base); From d34e4066025378dff8d444104100d3b07e127fe6 Mon Sep 17 00:00:00 2001 From: LIU Zhiwei Date: Tue, 9 Jul 2024 19:36:50 +0800 Subject: [PATCH 09/30] target/riscv: Add amocas.[b|h] for Zabha Signed-off-by: LIU Zhiwei Reviewed-by: Alistair Francis Message-ID: <20240709113652.1239-10-zhiwei_liu@linux.alibaba.com> Signed-off-by: Alistair Francis --- target/riscv/insn32.decode | 2 ++ target/riscv/insn_trans/trans_rvzabha.c.inc | 14 ++++++++++++++ 2 files changed, 16 insertions(+) diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode index 3bad6372f2..c45b8fa1d8 100644 --- a/target/riscv/insn32.decode +++ b/target/riscv/insn32.decode @@ -1041,3 +1041,5 @@ amomin_h 10000 . . ..... ..... 001 ..... 0101111 @atom_st amomax_h 10100 . . ..... ..... 001 ..... 0101111 @atom_st amominu_h 11000 . . ..... ..... 001 ..... 0101111 @atom_st amomaxu_h 11100 . . ..... ..... 001 ..... 0101111 @atom_st +amocas_b 00101 . . ..... ..... 000 ..... 0101111 @atom_st +amocas_h 00101 . . ..... ..... 001 ..... 0101111 @atom_st diff --git a/target/riscv/insn_trans/trans_rvzabha.c.inc b/target/riscv/insn_trans/trans_rvzabha.c.inc index 9093a1cfc1..ce8edcba62 100644 --- a/target/riscv/insn_trans/trans_rvzabha.c.inc +++ b/target/riscv/insn_trans/trans_rvzabha.c.inc @@ -129,3 +129,17 @@ static bool trans_amomaxu_h(DisasContext *ctx, arg_amomaxu_h *a) REQUIRE_ZABHA(ctx); return gen_amo(ctx, a, &tcg_gen_atomic_fetch_umax_tl, MO_TESW); } + +static bool trans_amocas_b(DisasContext *ctx, arg_amocas_b *a) +{ + REQUIRE_ZACAS(ctx); + REQUIRE_ZABHA(ctx); + return gen_cmpxchg(ctx, a, MO_SB); +} + +static bool trans_amocas_h(DisasContext *ctx, arg_amocas_h *a) +{ + REQUIRE_ZACAS(ctx); + REQUIRE_ZABHA(ctx); + return gen_cmpxchg(ctx, a, MO_ALIGN | MO_TESW); +} From 8aebaa2591320619cbd3e75f91f6e088f2c3dcfa Mon Sep 17 00:00:00 2001 From: LIU Zhiwei Date: Tue, 9 Jul 2024 19:36:51 +0800 Subject: [PATCH 10/30] target/riscv: Expose zabha extension as a cpu property Signed-off-by: LIU Zhiwei Reviewed-by: Alistair Francis Message-ID: <20240709113652.1239-11-zhiwei_liu@linux.alibaba.com> Signed-off-by: Alistair Francis --- target/riscv/cpu.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index de9c06904f..33ef4eb795 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -117,6 +117,7 @@ const RISCVIsaExtData isa_edata_arr[] = { ISA_EXT_DATA_ENTRY(zmmul, PRIV_VERSION_1_12_0, ext_zmmul), ISA_EXT_DATA_ENTRY(za64rs, PRIV_VERSION_1_12_0, has_priv_1_11), ISA_EXT_DATA_ENTRY(zaamo, PRIV_VERSION_1_12_0, ext_zaamo), + ISA_EXT_DATA_ENTRY(zabha, PRIV_VERSION_1_13_0, ext_zabha), ISA_EXT_DATA_ENTRY(zacas, PRIV_VERSION_1_12_0, ext_zacas), ISA_EXT_DATA_ENTRY(zama16b, PRIV_VERSION_1_13_0, ext_zama16b), ISA_EXT_DATA_ENTRY(zalrsc, PRIV_VERSION_1_12_0, ext_zalrsc), @@ -1478,6 +1479,7 @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = { MULTI_EXT_CFG_BOOL("zcmop", ext_zcmop, false), MULTI_EXT_CFG_BOOL("zacas", ext_zacas, false), MULTI_EXT_CFG_BOOL("zama16b", ext_zama16b, false), + MULTI_EXT_CFG_BOOL("zabha", ext_zabha, false), MULTI_EXT_CFG_BOOL("zaamo", ext_zaamo, false), MULTI_EXT_CFG_BOOL("zalrsc", ext_zalrsc, false), MULTI_EXT_CFG_BOOL("zawrs", ext_zawrs, true), From ae4bdcef6fd3166264a47ed6a17cb9870e32306e Mon Sep 17 00:00:00 2001 From: LIU Zhiwei Date: Tue, 9 Jul 2024 19:36:52 +0800 Subject: [PATCH 11/30] disas/riscv: Support zabha disassemble Signed-off-by: LIU Zhiwei Acked-by: Alistair Francis Message-ID: <20240709113652.1239-12-zhiwei_liu@linux.alibaba.com> Signed-off-by: Alistair Francis --- disas/riscv.c | 60 +++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 60 insertions(+) diff --git a/disas/riscv.c b/disas/riscv.c index d29cb1ff7d..c8364c2b07 100644 --- a/disas/riscv.c +++ b/disas/riscv.c @@ -954,6 +954,26 @@ typedef enum { rv_c_mop_11 = 923, rv_c_mop_13 = 924, rv_c_mop_15 = 925, + rv_op_amoswap_b = 926, + rv_op_amoadd_b = 927, + rv_op_amoxor_b = 928, + rv_op_amoor_b = 929, + rv_op_amoand_b = 930, + rv_op_amomin_b = 931, + rv_op_amomax_b = 932, + rv_op_amominu_b = 933, + rv_op_amomaxu_b = 934, + rv_op_amoswap_h = 935, + rv_op_amoadd_h = 936, + rv_op_amoxor_h = 937, + rv_op_amoor_h = 938, + rv_op_amoand_h = 939, + rv_op_amomin_h = 940, + rv_op_amomax_h = 941, + rv_op_amominu_h = 942, + rv_op_amomaxu_h = 943, + rv_op_amocas_b = 944, + rv_op_amocas_h = 945, } rv_op; /* register names */ @@ -2192,6 +2212,26 @@ const rv_opcode_data rvi_opcode_data[] = { { "c.mop.11", rv_codec_ci_none, rv_fmt_none, NULL, 0, 0, 0 }, { "c.mop.13", rv_codec_ci_none, rv_fmt_none, NULL, 0, 0, 0 }, { "c.mop.15", rv_codec_ci_none, rv_fmt_none, NULL, 0, 0, 0 }, + { "amoswap.b", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 }, + { "amoadd.b", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 }, + { "amoxor.b", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 }, + { "amoor.b", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 }, + { "amoand.b", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 }, + { "amomin.b", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 }, + { "amomax.b", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 }, + { "amominu.b", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 }, + { "amomaxu.b", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 }, + { "amoswap.h", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 }, + { "amoadd.h", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 }, + { "amoxor.h", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 }, + { "amoor.h", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 }, + { "amoand.h", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 }, + { "amomin.h", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 }, + { "amomax.h", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 }, + { "amominu.h", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 }, + { "amomaxu.h", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 }, + { "amocas.b", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 }, + { "amocas.h", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 }, }; /* CSR names */ @@ -2986,9 +3026,13 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa isa) case 11: switch (((inst >> 24) & 0b11111000) | ((inst >> 12) & 0b00000111)) { + case 0: op = rv_op_amoadd_b; break; + case 1: op = rv_op_amoadd_h; break; case 2: op = rv_op_amoadd_w; break; case 3: op = rv_op_amoadd_d; break; case 4: op = rv_op_amoadd_q; break; + case 8: op = rv_op_amoswap_b; break; + case 9: op = rv_op_amoswap_h; break; case 10: op = rv_op_amoswap_w; break; case 11: op = rv_op_amoswap_d; break; case 12: op = rv_op_amoswap_q; break; @@ -3010,27 +3054,43 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa isa) case 26: op = rv_op_sc_w; break; case 27: op = rv_op_sc_d; break; case 28: op = rv_op_sc_q; break; + case 32: op = rv_op_amoxor_b; break; + case 33: op = rv_op_amoxor_h; break; case 34: op = rv_op_amoxor_w; break; case 35: op = rv_op_amoxor_d; break; case 36: op = rv_op_amoxor_q; break; + case 40: op = rv_op_amocas_b; break; + case 41: op = rv_op_amocas_h; break; case 42: op = rv_op_amocas_w; break; case 43: op = rv_op_amocas_d; break; case 44: op = rv_op_amocas_q; break; + case 64: op = rv_op_amoor_b; break; + case 65: op = rv_op_amoor_h; break; case 66: op = rv_op_amoor_w; break; case 67: op = rv_op_amoor_d; break; case 68: op = rv_op_amoor_q; break; + case 96: op = rv_op_amoand_b; break; + case 97: op = rv_op_amoand_h; break; case 98: op = rv_op_amoand_w; break; case 99: op = rv_op_amoand_d; break; case 100: op = rv_op_amoand_q; break; + case 128: op = rv_op_amomin_b; break; + case 129: op = rv_op_amomin_h; break; case 130: op = rv_op_amomin_w; break; case 131: op = rv_op_amomin_d; break; case 132: op = rv_op_amomin_q; break; + case 160: op = rv_op_amomax_b; break; + case 161: op = rv_op_amomax_h; break; case 162: op = rv_op_amomax_w; break; case 163: op = rv_op_amomax_d; break; case 164: op = rv_op_amomax_q; break; + case 192: op = rv_op_amominu_b; break; + case 193: op = rv_op_amominu_h; break; case 194: op = rv_op_amominu_w; break; case 195: op = rv_op_amominu_d; break; case 196: op = rv_op_amominu_q; break; + case 224: op = rv_op_amomaxu_b; break; + case 225: op = rv_op_amomaxu_h; break; case 226: op = rv_op_amomaxu_w; break; case 227: op = rv_op_amomaxu_d; break; case 228: op = rv_op_amomaxu_q; break; From 910c18a91738f9b77c5faf66e3534bb10d6e306e Mon Sep 17 00:00:00 2001 From: Jiayi Li Date: Mon, 1 Jul 2024 10:25:53 +0800 Subject: [PATCH 12/30] target/riscv: Validate the mode in write_vstvec Base on the riscv-privileged spec, vstvec substitutes for the usual stvec. Therefore, the encoding of the MODE should also be restricted to 0 and 1. Signed-off-by: Jiayi Li Reviewed-by: Alistair Francis Reviewed-by: LIU Zhiwei Message-ID: <20240701022553.1982-1-lijiayi@eswincomputing.com> Signed-off-by: Alistair Francis --- target/riscv/csr.c | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 432c59dc66..f9229d92ab 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -3791,7 +3791,12 @@ static RISCVException read_vstvec(CPURISCVState *env, int csrno, static RISCVException write_vstvec(CPURISCVState *env, int csrno, target_ulong val) { - env->vstvec = val; + /* bits [1:0] encode mode; 0 = direct, 1 = vectored, 2 >= reserved */ + if ((val & 3) < 2) { + env->vstvec = val; + } else { + qemu_log_mask(LOG_UNIMP, "CSR_VSTVEC: reserved mode not supported\n"); + } return RISCV_EXCP_NONE; } From 4d46d84ea7fbb694125b95c88e788caf6cd039fa Mon Sep 17 00:00:00 2001 From: Balaji Ravikumar Date: Fri, 5 Jul 2024 17:53:16 +0100 Subject: [PATCH 13/30] disas/riscv: Add decode for Zawrs extension Add disassembly support for these instructions from Zawrs: * wrs.sto * wrs.nto Signed-off-by: Balaji Ravikumar Signed-off-by: Rob Bradford Acked-by: Alistair Francis Message-ID: <20240705165316.127494-1-rbradford@rivosinc.com> Signed-off-by: Alistair Francis --- disas/riscv.c | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/disas/riscv.c b/disas/riscv.c index c8364c2b07..5965574d87 100644 --- a/disas/riscv.c +++ b/disas/riscv.c @@ -974,6 +974,8 @@ typedef enum { rv_op_amomaxu_h = 943, rv_op_amocas_b = 944, rv_op_amocas_h = 945, + rv_op_wrs_sto = 946, + rv_op_wrs_nto = 947, } rv_op; /* register names */ @@ -2232,6 +2234,8 @@ const rv_opcode_data rvi_opcode_data[] = { { "amomaxu.h", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 }, { "amocas.b", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 }, { "amocas.h", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 }, + { "wrs.sto", rv_codec_none, rv_fmt_none, NULL, 0, 0, 0 }, + { "wrs.nto", rv_codec_none, rv_fmt_none, NULL, 0, 0, 0 }, }; /* CSR names */ @@ -3980,6 +3984,8 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa isa) case 0: op = rv_op_ecall; break; case 32: op = rv_op_ebreak; break; case 64: op = rv_op_uret; break; + case 416: op = rv_op_wrs_nto; break; + case 928: op = rv_op_wrs_sto; break; } break; case 256: From 3cb9f20499cd7da644387a17a79230f8ffd89993 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Tue, 9 Jul 2024 05:54:31 -0300 Subject: [PATCH 14/30] target/riscv/kvm: update KVM regs to Linux 6.10-rc5 Two new regs added: ztso and zacas. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Alistair Francis Message-ID: <20240709085431.455541-1-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis --- target/riscv/kvm/kvm-cpu.c | 2 ++ 1 file changed, 2 insertions(+) diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c index 1047961fed..f6e3156b8d 100644 --- a/target/riscv/kvm/kvm-cpu.c +++ b/target/riscv/kvm/kvm-cpu.c @@ -281,6 +281,7 @@ static KVMCPUConfig kvm_multi_ext_cfgs[] = { KVM_EXT_CFG("zihintntl", ext_zihintntl, KVM_RISCV_ISA_EXT_ZIHINTNTL), KVM_EXT_CFG("zihintpause", ext_zihintpause, KVM_RISCV_ISA_EXT_ZIHINTPAUSE), KVM_EXT_CFG("zihpm", ext_zihpm, KVM_RISCV_ISA_EXT_ZIHPM), + KVM_EXT_CFG("zacas", ext_zacas, KVM_RISCV_ISA_EXT_ZACAS), KVM_EXT_CFG("zfa", ext_zfa, KVM_RISCV_ISA_EXT_ZFA), KVM_EXT_CFG("zfh", ext_zfh, KVM_RISCV_ISA_EXT_ZFH), KVM_EXT_CFG("zfhmin", ext_zfhmin, KVM_RISCV_ISA_EXT_ZFHMIN), @@ -298,6 +299,7 @@ static KVMCPUConfig kvm_multi_ext_cfgs[] = { KVM_EXT_CFG("zksed", ext_zksed, KVM_RISCV_ISA_EXT_ZKSED), KVM_EXT_CFG("zksh", ext_zksh, KVM_RISCV_ISA_EXT_ZKSH), KVM_EXT_CFG("zkt", ext_zkt, KVM_RISCV_ISA_EXT_ZKT), + KVM_EXT_CFG("ztso", ext_ztso, KVM_RISCV_ISA_EXT_ZTSO), KVM_EXT_CFG("zvbb", ext_zvbb, KVM_RISCV_ISA_EXT_ZVBB), KVM_EXT_CFG("zvbc", ext_zvbc, KVM_RISCV_ISA_EXT_ZVBC), KVM_EXT_CFG("zvfh", ext_zvfh, KVM_RISCV_ISA_EXT_ZVFH), From 68c05fb53036f59a55a54c943b713e8ac78fc627 Mon Sep 17 00:00:00 2001 From: Rajnesh Kanwal Date: Thu, 11 Jul 2024 15:31:04 -0700 Subject: [PATCH 15/30] target/riscv: Combine set_mode and set_virt functions. Combining riscv_cpu_set_virt_enabled() and riscv_cpu_set_mode() functions. This is to make complete mode change information available through a single function. This allows to easily differentiate between HS->VS, VS->HS and VS->VS transitions when executing state update codes. For example: One use-case which inspired this change is to update mode-specific instruction and cycle counters which requires information of both prev mode and current mode. Signed-off-by: Rajnesh Kanwal Reviewed-by: Alistair Francis Reviewed-by: Daniel Henrique Barboza Message-ID: <20240711-smcntrpmf_v7-v8-1-b7c38ae7b263@rivosinc.com> Signed-off-by: Alistair Francis --- target/riscv/cpu.h | 2 +- target/riscv/cpu_helper.c | 57 +++++++++++++++++++-------------------- target/riscv/op_helper.c | 17 +++++------- 3 files changed, 35 insertions(+), 41 deletions(-) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 87742047ce..6520e0f5d5 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -567,7 +567,7 @@ void riscv_cpu_set_aia_ireg_rmw_fn(CPURISCVState *env, uint32_t priv, RISCVException smstateen_acc_ok(CPURISCVState *env, int index, uint64_t bit); #endif /* !CONFIG_USER_ONLY */ -void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv); +void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv, bool virt_en); void riscv_translate_init(void); G_NORETURN void riscv_raise_exception(CPURISCVState *env, diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index 6709622dd3..10d3fdaed3 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -619,30 +619,6 @@ void riscv_cpu_set_geilen(CPURISCVState *env, target_ulong geilen) env->geilen = geilen; } -/* This function can only be called to set virt when RVH is enabled */ -void riscv_cpu_set_virt_enabled(CPURISCVState *env, bool enable) -{ - /* Flush the TLB on all virt mode changes. */ - if (env->virt_enabled != enable) { - tlb_flush(env_cpu(env)); - } - - env->virt_enabled = enable; - - if (enable) { - /* - * The guest external interrupts from an interrupt controller are - * delivered only when the Guest/VM is running (i.e. V=1). This means - * any guest external interrupt which is triggered while the Guest/VM - * is not running (i.e. V=0) will be missed on QEMU resulting in guest - * with sluggish response to serial console input and other I/O events. - * - * To solve this, we check and inject interrupt after setting V=1. - */ - riscv_cpu_update_mip(env, 0, 0); - } -} - int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint64_t interrupts) { CPURISCVState *env = &cpu->env; @@ -715,7 +691,7 @@ void riscv_cpu_set_aia_ireg_rmw_fn(CPURISCVState *env, uint32_t priv, } } -void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv) +void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv, bool virt_en) { g_assert(newpriv <= PRV_M && newpriv != PRV_RESERVED); @@ -736,6 +712,28 @@ void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv) * preemptive context switch. As a result, do both. */ env->load_res = -1; + + if (riscv_has_ext(env, RVH)) { + /* Flush the TLB on all virt mode changes. */ + if (env->virt_enabled != virt_en) { + tlb_flush(env_cpu(env)); + } + + env->virt_enabled = virt_en; + if (virt_en) { + /* + * The guest external interrupts from an interrupt controller are + * delivered only when the Guest/VM is running (i.e. V=1). This + * means any guest external interrupt which is triggered while the + * Guest/VM is not running (i.e. V=0) will be missed on QEMU + * resulting in guest with sluggish response to serial console + * input and other I/O events. + * + * To solve this, we check and inject interrupt after setting V=1. + */ + riscv_cpu_update_mip(env, 0, 0); + } + } } /* @@ -1648,6 +1646,7 @@ void riscv_cpu_do_interrupt(CPUState *cs) { RISCVCPU *cpu = RISCV_CPU(cs); CPURISCVState *env = &cpu->env; + bool virt = env->virt_enabled; bool write_gva = false; uint64_t s; @@ -1778,7 +1777,7 @@ void riscv_cpu_do_interrupt(CPUState *cs) htval = env->guest_phys_fault_addr; - riscv_cpu_set_virt_enabled(env, 0); + virt = false; } else { /* Trap into HS mode */ env->hstatus = set_field(env->hstatus, HSTATUS_SPV, false); @@ -1799,7 +1798,7 @@ void riscv_cpu_do_interrupt(CPUState *cs) env->htinst = tinst; env->pc = (env->stvec >> 2 << 2) + ((async && (env->stvec & 3) == 1) ? cause * 4 : 0); - riscv_cpu_set_mode(env, PRV_S); + riscv_cpu_set_mode(env, PRV_S, virt); } else { /* handle the trap in M-mode */ if (riscv_has_ext(env, RVH)) { @@ -1815,7 +1814,7 @@ void riscv_cpu_do_interrupt(CPUState *cs) mtval2 = env->guest_phys_fault_addr; /* Trapping to M mode, virt is disabled */ - riscv_cpu_set_virt_enabled(env, 0); + virt = false; } s = env->mstatus; @@ -1830,7 +1829,7 @@ void riscv_cpu_do_interrupt(CPUState *cs) env->mtinst = tinst; env->pc = (env->mtvec >> 2 << 2) + ((async && (env->mtvec & 3) == 1) ? cause * 4 : 0); - riscv_cpu_set_mode(env, PRV_M); + riscv_cpu_set_mode(env, PRV_M, virt); } /* diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c index 2baf5bc3ca..ec1408ba0f 100644 --- a/target/riscv/op_helper.c +++ b/target/riscv/op_helper.c @@ -264,7 +264,7 @@ void helper_cbo_inval(CPURISCVState *env, target_ulong address) target_ulong helper_sret(CPURISCVState *env) { uint64_t mstatus; - target_ulong prev_priv, prev_virt; + target_ulong prev_priv, prev_virt = env->virt_enabled; if (!(env->priv >= PRV_S)) { riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, GETPC()); @@ -307,11 +307,9 @@ target_ulong helper_sret(CPURISCVState *env) if (prev_virt) { riscv_cpu_swap_hypervisor_regs(env); } - - riscv_cpu_set_virt_enabled(env, prev_virt); } - riscv_cpu_set_mode(env, prev_priv); + riscv_cpu_set_mode(env, prev_priv, prev_virt); return retpc; } @@ -347,16 +345,13 @@ target_ulong helper_mret(CPURISCVState *env) mstatus = set_field(mstatus, MSTATUS_MPRV, 0); } env->mstatus = mstatus; - riscv_cpu_set_mode(env, prev_priv); - if (riscv_has_ext(env, RVH)) { - if (prev_virt) { - riscv_cpu_swap_hypervisor_regs(env); - } - - riscv_cpu_set_virt_enabled(env, prev_virt); + if (riscv_has_ext(env, RVH) && prev_virt) { + riscv_cpu_swap_hypervisor_regs(env); } + riscv_cpu_set_mode(env, prev_priv, prev_virt); + return retpc; } From be470e597708451e6fecb0631728fa759164d03e Mon Sep 17 00:00:00 2001 From: Atish Patra Date: Thu, 11 Jul 2024 15:31:05 -0700 Subject: [PATCH 16/30] target/riscv: Fix the predicate functions for mhpmeventhX CSRs mhpmeventhX CSRs are available for RV32. The predicate function should check that first before checking sscofpmf extension. Fixes: 14664483457b ("target/riscv: Add sscofpmf extension support") Reviewed-by: Daniel Henrique Barboza Reviewed-by: Alistair Francis Signed-off-by: Atish Patra Message-ID: <20240711-smcntrpmf_v7-v8-2-b7c38ae7b263@rivosinc.com> Signed-off-by: Alistair Francis --- target/riscv/csr.c | 67 ++++++++++++++++++++++++++-------------------- 1 file changed, 38 insertions(+), 29 deletions(-) diff --git a/target/riscv/csr.c b/target/riscv/csr.c index f9229d92ab..1bcf75f91f 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -227,6 +227,15 @@ static RISCVException sscofpmf(CPURISCVState *env, int csrno) return RISCV_EXCP_NONE; } +static RISCVException sscofpmf_32(CPURISCVState *env, int csrno) +{ + if (riscv_cpu_mxl(env) != MXL_RV32) { + return RISCV_EXCP_ILLEGAL_INST; + } + + return sscofpmf(env, csrno); +} + static RISCVException any(CPURISCVState *env, int csrno) { return RISCV_EXCP_NONE; @@ -5106,91 +5115,91 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { [CSR_MHPMEVENT31] = { "mhpmevent31", any, read_mhpmevent, write_mhpmevent }, - [CSR_MHPMEVENT3H] = { "mhpmevent3h", sscofpmf, read_mhpmeventh, + [CSR_MHPMEVENT3H] = { "mhpmevent3h", sscofpmf_32, read_mhpmeventh, write_mhpmeventh, .min_priv_ver = PRIV_VERSION_1_12_0 }, - [CSR_MHPMEVENT4H] = { "mhpmevent4h", sscofpmf, read_mhpmeventh, + [CSR_MHPMEVENT4H] = { "mhpmevent4h", sscofpmf_32, read_mhpmeventh, write_mhpmeventh, .min_priv_ver = PRIV_VERSION_1_12_0 }, - [CSR_MHPMEVENT5H] = { "mhpmevent5h", sscofpmf, read_mhpmeventh, + [CSR_MHPMEVENT5H] = { "mhpmevent5h", sscofpmf_32, read_mhpmeventh, write_mhpmeventh, .min_priv_ver = PRIV_VERSION_1_12_0 }, - [CSR_MHPMEVENT6H] = { "mhpmevent6h", sscofpmf, read_mhpmeventh, + [CSR_MHPMEVENT6H] = { "mhpmevent6h", sscofpmf_32, read_mhpmeventh, write_mhpmeventh, .min_priv_ver = PRIV_VERSION_1_12_0 }, - [CSR_MHPMEVENT7H] = { "mhpmevent7h", sscofpmf, read_mhpmeventh, + [CSR_MHPMEVENT7H] = { "mhpmevent7h", sscofpmf_32, read_mhpmeventh, write_mhpmeventh, .min_priv_ver = PRIV_VERSION_1_12_0 }, - [CSR_MHPMEVENT8H] = { "mhpmevent8h", sscofpmf, read_mhpmeventh, + [CSR_MHPMEVENT8H] = { "mhpmevent8h", sscofpmf_32, read_mhpmeventh, write_mhpmeventh, .min_priv_ver = PRIV_VERSION_1_12_0 }, - [CSR_MHPMEVENT9H] = { "mhpmevent9h", sscofpmf, read_mhpmeventh, + [CSR_MHPMEVENT9H] = { "mhpmevent9h", sscofpmf_32, read_mhpmeventh, write_mhpmeventh, .min_priv_ver = PRIV_VERSION_1_12_0 }, - [CSR_MHPMEVENT10H] = { "mhpmevent10h", sscofpmf, read_mhpmeventh, + [CSR_MHPMEVENT10H] = { "mhpmevent10h", sscofpmf_32, read_mhpmeventh, write_mhpmeventh, .min_priv_ver = PRIV_VERSION_1_12_0 }, - [CSR_MHPMEVENT11H] = { "mhpmevent11h", sscofpmf, read_mhpmeventh, + [CSR_MHPMEVENT11H] = { "mhpmevent11h", sscofpmf_32, read_mhpmeventh, write_mhpmeventh, .min_priv_ver = PRIV_VERSION_1_12_0 }, - [CSR_MHPMEVENT12H] = { "mhpmevent12h", sscofpmf, read_mhpmeventh, + [CSR_MHPMEVENT12H] = { "mhpmevent12h", sscofpmf_32, read_mhpmeventh, write_mhpmeventh, .min_priv_ver = PRIV_VERSION_1_12_0 }, - [CSR_MHPMEVENT13H] = { "mhpmevent13h", sscofpmf, read_mhpmeventh, + [CSR_MHPMEVENT13H] = { "mhpmevent13h", sscofpmf_32, read_mhpmeventh, write_mhpmeventh, .min_priv_ver = PRIV_VERSION_1_12_0 }, - [CSR_MHPMEVENT14H] = { "mhpmevent14h", sscofpmf, read_mhpmeventh, + [CSR_MHPMEVENT14H] = { "mhpmevent14h", sscofpmf_32, read_mhpmeventh, write_mhpmeventh, .min_priv_ver = PRIV_VERSION_1_12_0 }, - [CSR_MHPMEVENT15H] = { "mhpmevent15h", sscofpmf, read_mhpmeventh, + [CSR_MHPMEVENT15H] = { "mhpmevent15h", sscofpmf_32, read_mhpmeventh, write_mhpmeventh, .min_priv_ver = PRIV_VERSION_1_12_0 }, - [CSR_MHPMEVENT16H] = { "mhpmevent16h", sscofpmf, read_mhpmeventh, + [CSR_MHPMEVENT16H] = { "mhpmevent16h", sscofpmf_32, read_mhpmeventh, write_mhpmeventh, .min_priv_ver = PRIV_VERSION_1_12_0 }, - [CSR_MHPMEVENT17H] = { "mhpmevent17h", sscofpmf, read_mhpmeventh, + [CSR_MHPMEVENT17H] = { "mhpmevent17h", sscofpmf_32, read_mhpmeventh, write_mhpmeventh, .min_priv_ver = PRIV_VERSION_1_12_0 }, - [CSR_MHPMEVENT18H] = { "mhpmevent18h", sscofpmf, read_mhpmeventh, + [CSR_MHPMEVENT18H] = { "mhpmevent18h", sscofpmf_32, read_mhpmeventh, write_mhpmeventh, .min_priv_ver = PRIV_VERSION_1_12_0 }, - [CSR_MHPMEVENT19H] = { "mhpmevent19h", sscofpmf, read_mhpmeventh, + [CSR_MHPMEVENT19H] = { "mhpmevent19h", sscofpmf_32, read_mhpmeventh, write_mhpmeventh, .min_priv_ver = PRIV_VERSION_1_12_0 }, - [CSR_MHPMEVENT20H] = { "mhpmevent20h", sscofpmf, read_mhpmeventh, + [CSR_MHPMEVENT20H] = { "mhpmevent20h", sscofpmf_32, read_mhpmeventh, write_mhpmeventh, .min_priv_ver = PRIV_VERSION_1_12_0 }, - [CSR_MHPMEVENT21H] = { "mhpmevent21h", sscofpmf, read_mhpmeventh, + [CSR_MHPMEVENT21H] = { "mhpmevent21h", sscofpmf_32, read_mhpmeventh, write_mhpmeventh, .min_priv_ver = PRIV_VERSION_1_12_0 }, - [CSR_MHPMEVENT22H] = { "mhpmevent22h", sscofpmf, read_mhpmeventh, + [CSR_MHPMEVENT22H] = { "mhpmevent22h", sscofpmf_32, read_mhpmeventh, write_mhpmeventh, .min_priv_ver = PRIV_VERSION_1_12_0 }, - [CSR_MHPMEVENT23H] = { "mhpmevent23h", sscofpmf, read_mhpmeventh, + [CSR_MHPMEVENT23H] = { "mhpmevent23h", sscofpmf_32, read_mhpmeventh, write_mhpmeventh, .min_priv_ver = PRIV_VERSION_1_12_0 }, - [CSR_MHPMEVENT24H] = { "mhpmevent24h", sscofpmf, read_mhpmeventh, + [CSR_MHPMEVENT24H] = { "mhpmevent24h", sscofpmf_32, read_mhpmeventh, write_mhpmeventh, .min_priv_ver = PRIV_VERSION_1_12_0 }, - [CSR_MHPMEVENT25H] = { "mhpmevent25h", sscofpmf, read_mhpmeventh, + [CSR_MHPMEVENT25H] = { "mhpmevent25h", sscofpmf_32, read_mhpmeventh, write_mhpmeventh, .min_priv_ver = PRIV_VERSION_1_12_0 }, - [CSR_MHPMEVENT26H] = { "mhpmevent26h", sscofpmf, read_mhpmeventh, + [CSR_MHPMEVENT26H] = { "mhpmevent26h", sscofpmf_32, read_mhpmeventh, write_mhpmeventh, .min_priv_ver = PRIV_VERSION_1_12_0 }, - [CSR_MHPMEVENT27H] = { "mhpmevent27h", sscofpmf, read_mhpmeventh, + [CSR_MHPMEVENT27H] = { "mhpmevent27h", sscofpmf_32, read_mhpmeventh, write_mhpmeventh, .min_priv_ver = PRIV_VERSION_1_12_0 }, - [CSR_MHPMEVENT28H] = { "mhpmevent28h", sscofpmf, read_mhpmeventh, + [CSR_MHPMEVENT28H] = { "mhpmevent28h", sscofpmf_32, read_mhpmeventh, write_mhpmeventh, .min_priv_ver = PRIV_VERSION_1_12_0 }, - [CSR_MHPMEVENT29H] = { "mhpmevent29h", sscofpmf, read_mhpmeventh, + [CSR_MHPMEVENT29H] = { "mhpmevent29h", sscofpmf_32, read_mhpmeventh, write_mhpmeventh, .min_priv_ver = PRIV_VERSION_1_12_0 }, - [CSR_MHPMEVENT30H] = { "mhpmevent30h", sscofpmf, read_mhpmeventh, + [CSR_MHPMEVENT30H] = { "mhpmevent30h", sscofpmf_32, read_mhpmeventh, write_mhpmeventh, .min_priv_ver = PRIV_VERSION_1_12_0 }, - [CSR_MHPMEVENT31H] = { "mhpmevent31h", sscofpmf, read_mhpmeventh, + [CSR_MHPMEVENT31H] = { "mhpmevent31h", sscofpmf_32, read_mhpmeventh, write_mhpmeventh, .min_priv_ver = PRIV_VERSION_1_12_0 }, From 251dccc09af363900436656461151681687e2470 Mon Sep 17 00:00:00 2001 From: Kaiwen Xue Date: Thu, 11 Jul 2024 15:31:06 -0700 Subject: [PATCH 17/30] target/riscv: Add cycle & instret privilege mode filtering properties This adds the properties for ISA extension smcntrpmf. Patches implementing it will follow. Signed-off-by: Kaiwen Xue Reviewed-by: Daniel Henrique Barboza Signed-off-by: Atish Patra Reviewed-by: Alistair Francis Message-ID: <20240711-smcntrpmf_v7-v8-3-b7c38ae7b263@rivosinc.com> Signed-off-by: Alistair Francis --- target/riscv/cpu.c | 1 + target/riscv/cpu_cfg.h | 1 + 2 files changed, 2 insertions(+) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 33ef4eb795..4efe7ee3b0 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -182,6 +182,7 @@ const RISCVIsaExtData isa_edata_arr[] = { ISA_EXT_DATA_ENTRY(zhinx, PRIV_VERSION_1_12_0, ext_zhinx), ISA_EXT_DATA_ENTRY(zhinxmin, PRIV_VERSION_1_12_0, ext_zhinxmin), ISA_EXT_DATA_ENTRY(smaia, PRIV_VERSION_1_12_0, ext_smaia), + ISA_EXT_DATA_ENTRY(smcntrpmf, PRIV_VERSION_1_12_0, ext_smcntrpmf), ISA_EXT_DATA_ENTRY(smepmp, PRIV_VERSION_1_12_0, ext_smepmp), ISA_EXT_DATA_ENTRY(smstateen, PRIV_VERSION_1_12_0, ext_smstateen), ISA_EXT_DATA_ENTRY(ssaia, PRIV_VERSION_1_12_0, ext_ssaia), diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h index 120905a254..8b272fb826 100644 --- a/target/riscv/cpu_cfg.h +++ b/target/riscv/cpu_cfg.h @@ -76,6 +76,7 @@ struct RISCVCPUConfig { bool ext_ztso; bool ext_smstateen; bool ext_sstc; + bool ext_smcntrpmf; bool ext_svadu; bool ext_svinval; bool ext_svnapot; From 6d1e3893cfaeedb47a16edbb766fcc0c7907ab94 Mon Sep 17 00:00:00 2001 From: Kaiwen Xue Date: Thu, 11 Jul 2024 15:31:07 -0700 Subject: [PATCH 18/30] target/riscv: Add cycle & instret privilege mode filtering definitions This adds the definitions for ISA extension smcntrpmf. Signed-off-by: Kaiwen Xue Reviewed-by: Daniel Henrique Barboza Reviewed-by: Alistair Francis Signed-off-by: Atish Patra Message-ID: <20240711-smcntrpmf_v7-v8-4-b7c38ae7b263@rivosinc.com> Signed-off-by: Alistair Francis --- target/riscv/cpu.h | 6 ++++++ target/riscv/cpu_bits.h | 29 +++++++++++++++++++++++++++++ 2 files changed, 35 insertions(+) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 6520e0f5d5..980e2154cd 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -362,6 +362,12 @@ struct CPUArchState { uint32_t mcountinhibit; + /* PMU cycle & instret privilege mode filtering */ + target_ulong mcyclecfg; + target_ulong mcyclecfgh; + target_ulong minstretcfg; + target_ulong minstretcfgh; + /* PMU counter state */ PMUCTRState pmu_ctrs[RV_MAX_MHPMCOUNTERS]; diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h index c257c5ed7d..5faa817453 100644 --- a/target/riscv/cpu_bits.h +++ b/target/riscv/cpu_bits.h @@ -397,6 +397,10 @@ /* Machine counter-inhibit register */ #define CSR_MCOUNTINHIBIT 0x320 +/* Machine counter configuration registers */ +#define CSR_MCYCLECFG 0x321 +#define CSR_MINSTRETCFG 0x322 + #define CSR_MHPMEVENT3 0x323 #define CSR_MHPMEVENT4 0x324 #define CSR_MHPMEVENT5 0x325 @@ -427,6 +431,9 @@ #define CSR_MHPMEVENT30 0x33e #define CSR_MHPMEVENT31 0x33f +#define CSR_MCYCLECFGH 0x721 +#define CSR_MINSTRETCFGH 0x722 + #define CSR_MHPMEVENT3H 0x723 #define CSR_MHPMEVENT4H 0x724 #define CSR_MHPMEVENT5H 0x725 @@ -884,6 +891,28 @@ typedef enum RISCVException { /* PMU related bits */ #define MIE_LCOFIE (1 << IRQ_PMU_OVF) +#define MCYCLECFG_BIT_MINH BIT_ULL(62) +#define MCYCLECFGH_BIT_MINH BIT(30) +#define MCYCLECFG_BIT_SINH BIT_ULL(61) +#define MCYCLECFGH_BIT_SINH BIT(29) +#define MCYCLECFG_BIT_UINH BIT_ULL(60) +#define MCYCLECFGH_BIT_UINH BIT(28) +#define MCYCLECFG_BIT_VSINH BIT_ULL(59) +#define MCYCLECFGH_BIT_VSINH BIT(27) +#define MCYCLECFG_BIT_VUINH BIT_ULL(58) +#define MCYCLECFGH_BIT_VUINH BIT(26) + +#define MINSTRETCFG_BIT_MINH BIT_ULL(62) +#define MINSTRETCFGH_BIT_MINH BIT(30) +#define MINSTRETCFG_BIT_SINH BIT_ULL(61) +#define MINSTRETCFGH_BIT_SINH BIT(29) +#define MINSTRETCFG_BIT_UINH BIT_ULL(60) +#define MINSTRETCFGH_BIT_UINH BIT(28) +#define MINSTRETCFG_BIT_VSINH BIT_ULL(59) +#define MINSTRETCFGH_BIT_VSINH BIT(27) +#define MINSTRETCFG_BIT_VUINH BIT_ULL(58) +#define MINSTRETCFGH_BIT_VUINH BIT(26) + #define MHPMEVENT_BIT_OF BIT_ULL(63) #define MHPMEVENTH_BIT_OF BIT(31) #define MHPMEVENT_BIT_MINH BIT_ULL(62) From b54a84c15e389a4795022cc7edfe3a7e32dc065d Mon Sep 17 00:00:00 2001 From: Kaiwen Xue Date: Thu, 11 Jul 2024 15:31:08 -0700 Subject: [PATCH 19/30] target/riscv: Add cycle & instret privilege mode filtering support QEMU only calculates dummy cycles and instructions, so there is no actual means to stop the icount in QEMU. Hence this patch merely adds the functionality of accessing the cfg registers, and cause no actual effects on the counting of cycle and instret counters. Signed-off-by: Atish Patra Reviewed-by: Daniel Henrique Barboza Signed-off-by: Kaiwen Xue Acked-by: Alistair Francis Message-ID: <20240711-smcntrpmf_v7-v8-5-b7c38ae7b263@rivosinc.com> Signed-off-by: Alistair Francis --- target/riscv/cpu_bits.h | 12 ++++ target/riscv/csr.c | 138 +++++++++++++++++++++++++++++++++++++++- 2 files changed, 149 insertions(+), 1 deletion(-) diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h index 5faa817453..32b068f18a 100644 --- a/target/riscv/cpu_bits.h +++ b/target/riscv/cpu_bits.h @@ -926,6 +926,18 @@ typedef enum RISCVException { #define MHPMEVENT_BIT_VUINH BIT_ULL(58) #define MHPMEVENTH_BIT_VUINH BIT(26) +#define MHPMEVENT_FILTER_MASK (MHPMEVENT_BIT_MINH | \ + MHPMEVENT_BIT_SINH | \ + MHPMEVENT_BIT_UINH | \ + MHPMEVENT_BIT_VSINH | \ + MHPMEVENT_BIT_VUINH) + +#define MHPMEVENTH_FILTER_MASK (MHPMEVENTH_BIT_MINH | \ + MHPMEVENTH_BIT_SINH | \ + MHPMEVENTH_BIT_UINH | \ + MHPMEVENTH_BIT_VSINH | \ + MHPMEVENTH_BIT_VUINH) + #define MHPMEVENT_SSCOF_MASK _ULL(0xFFFF000000000000) #define MHPMEVENT_IDX_MASK 0xFFFFF #define MHPMEVENT_SSCOF_RESVD 16 diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 1bcf75f91f..8831d4f5ec 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -30,7 +30,6 @@ #include "qemu/guest-random.h" #include "qapi/error.h" - /* CSR function table public API */ void riscv_get_csr_ops(int csrno, riscv_csr_operations *ops) { @@ -236,6 +235,24 @@ static RISCVException sscofpmf_32(CPURISCVState *env, int csrno) return sscofpmf(env, csrno); } +static RISCVException smcntrpmf(CPURISCVState *env, int csrno) +{ + if (!riscv_cpu_cfg(env)->ext_smcntrpmf) { + return RISCV_EXCP_ILLEGAL_INST; + } + + return RISCV_EXCP_NONE; +} + +static RISCVException smcntrpmf_32(CPURISCVState *env, int csrno) +{ + if (riscv_cpu_mxl(env) != MXL_RV32) { + return RISCV_EXCP_ILLEGAL_INST; + } + + return smcntrpmf(env, csrno); +} + static RISCVException any(CPURISCVState *env, int csrno) { return RISCV_EXCP_NONE; @@ -830,6 +847,111 @@ static RISCVException read_hpmcounterh(CPURISCVState *env, int csrno, #else /* CONFIG_USER_ONLY */ +static RISCVException read_mcyclecfg(CPURISCVState *env, int csrno, + target_ulong *val) +{ + *val = env->mcyclecfg; + return RISCV_EXCP_NONE; +} + +static RISCVException write_mcyclecfg(CPURISCVState *env, int csrno, + target_ulong val) +{ + uint64_t inh_avail_mask; + + if (riscv_cpu_mxl(env) == MXL_RV32) { + env->mcyclecfg = val; + } else { + /* Set xINH fields if priv mode supported */ + inh_avail_mask = ~MHPMEVENT_FILTER_MASK | MCYCLECFG_BIT_MINH; + inh_avail_mask |= riscv_has_ext(env, RVU) ? MCYCLECFG_BIT_UINH : 0; + inh_avail_mask |= riscv_has_ext(env, RVS) ? MCYCLECFG_BIT_SINH : 0; + inh_avail_mask |= (riscv_has_ext(env, RVH) && + riscv_has_ext(env, RVU)) ? MCYCLECFG_BIT_VUINH : 0; + inh_avail_mask |= (riscv_has_ext(env, RVH) && + riscv_has_ext(env, RVS)) ? MCYCLECFG_BIT_VSINH : 0; + env->mcyclecfg = val & inh_avail_mask; + } + + return RISCV_EXCP_NONE; +} + +static RISCVException read_mcyclecfgh(CPURISCVState *env, int csrno, + target_ulong *val) +{ + *val = env->mcyclecfgh; + return RISCV_EXCP_NONE; +} + +static RISCVException write_mcyclecfgh(CPURISCVState *env, int csrno, + target_ulong val) +{ + target_ulong inh_avail_mask = (target_ulong)(~MHPMEVENTH_FILTER_MASK | + MCYCLECFGH_BIT_MINH); + + /* Set xINH fields if priv mode supported */ + inh_avail_mask |= riscv_has_ext(env, RVU) ? MCYCLECFGH_BIT_UINH : 0; + inh_avail_mask |= riscv_has_ext(env, RVS) ? MCYCLECFGH_BIT_SINH : 0; + inh_avail_mask |= (riscv_has_ext(env, RVH) && + riscv_has_ext(env, RVU)) ? MCYCLECFGH_BIT_VUINH : 0; + inh_avail_mask |= (riscv_has_ext(env, RVH) && + riscv_has_ext(env, RVS)) ? MCYCLECFGH_BIT_VSINH : 0; + + env->mcyclecfgh = val & inh_avail_mask; + return RISCV_EXCP_NONE; +} + +static RISCVException read_minstretcfg(CPURISCVState *env, int csrno, + target_ulong *val) +{ + *val = env->minstretcfg; + return RISCV_EXCP_NONE; +} + +static RISCVException write_minstretcfg(CPURISCVState *env, int csrno, + target_ulong val) +{ + uint64_t inh_avail_mask; + + if (riscv_cpu_mxl(env) == MXL_RV32) { + env->minstretcfg = val; + } else { + inh_avail_mask = ~MHPMEVENT_FILTER_MASK | MINSTRETCFG_BIT_MINH; + inh_avail_mask |= riscv_has_ext(env, RVU) ? MINSTRETCFG_BIT_UINH : 0; + inh_avail_mask |= riscv_has_ext(env, RVS) ? MINSTRETCFG_BIT_SINH : 0; + inh_avail_mask |= (riscv_has_ext(env, RVH) && + riscv_has_ext(env, RVU)) ? MINSTRETCFG_BIT_VUINH : 0; + inh_avail_mask |= (riscv_has_ext(env, RVH) && + riscv_has_ext(env, RVS)) ? MINSTRETCFG_BIT_VSINH : 0; + env->minstretcfg = val & inh_avail_mask; + } + return RISCV_EXCP_NONE; +} + +static RISCVException read_minstretcfgh(CPURISCVState *env, int csrno, + target_ulong *val) +{ + *val = env->minstretcfgh; + return RISCV_EXCP_NONE; +} + +static RISCVException write_minstretcfgh(CPURISCVState *env, int csrno, + target_ulong val) +{ + target_ulong inh_avail_mask = (target_ulong)(~MHPMEVENTH_FILTER_MASK | + MINSTRETCFGH_BIT_MINH); + + inh_avail_mask |= riscv_has_ext(env, RVU) ? MINSTRETCFGH_BIT_UINH : 0; + inh_avail_mask |= riscv_has_ext(env, RVS) ? MINSTRETCFGH_BIT_SINH : 0; + inh_avail_mask |= (riscv_has_ext(env, RVH) && + riscv_has_ext(env, RVU)) ? MINSTRETCFGH_BIT_VUINH : 0; + inh_avail_mask |= (riscv_has_ext(env, RVH) && + riscv_has_ext(env, RVS)) ? MINSTRETCFGH_BIT_VSINH : 0; + + env->minstretcfgh = val & inh_avail_mask; + return RISCV_EXCP_NONE; +} + static RISCVException read_mhpmevent(CPURISCVState *env, int csrno, target_ulong *val) { @@ -5056,6 +5178,13 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { write_mcountinhibit, .min_priv_ver = PRIV_VERSION_1_11_0 }, + [CSR_MCYCLECFG] = { "mcyclecfg", smcntrpmf, read_mcyclecfg, + write_mcyclecfg, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_MINSTRETCFG] = { "minstretcfg", smcntrpmf, read_minstretcfg, + write_minstretcfg, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_MHPMEVENT3] = { "mhpmevent3", any, read_mhpmevent, write_mhpmevent }, [CSR_MHPMEVENT4] = { "mhpmevent4", any, read_mhpmevent, @@ -5115,6 +5244,13 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = { [CSR_MHPMEVENT31] = { "mhpmevent31", any, read_mhpmevent, write_mhpmevent }, + [CSR_MCYCLECFGH] = { "mcyclecfgh", smcntrpmf_32, read_mcyclecfgh, + write_mcyclecfgh, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_MINSTRETCFGH] = { "minstretcfgh", smcntrpmf_32, read_minstretcfgh, + write_minstretcfgh, + .min_priv_ver = PRIV_VERSION_1_12_0 }, + [CSR_MHPMEVENT3H] = { "mhpmevent3h", sscofpmf_32, read_mhpmeventh, write_mhpmeventh, .min_priv_ver = PRIV_VERSION_1_12_0 }, From 3b31b7baff02b357a6c921b26ae953e04d0cfdbb Mon Sep 17 00:00:00 2001 From: Atish Patra Date: Thu, 11 Jul 2024 15:31:09 -0700 Subject: [PATCH 20/30] target/riscv: Only set INH fields if priv mode is available Currently, the INH fields are set in mhpmevent uncoditionally without checking if a particular priv mode is supported or not. Suggested-by: Alistair Francis Signed-off-by: Atish Patra Acked-by: Alistair Francis Message-ID: <20240711-smcntrpmf_v7-v8-6-b7c38ae7b263@rivosinc.com> Signed-off-by: Alistair Francis --- target/riscv/csr.c | 29 +++++++++++++++++++++++++---- 1 file changed, 25 insertions(+), 4 deletions(-) diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 8831d4f5ec..364583dc03 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -967,13 +967,24 @@ static RISCVException write_mhpmevent(CPURISCVState *env, int csrno, { int evt_index = csrno - CSR_MCOUNTINHIBIT; uint64_t mhpmevt_val = val; - - env->mhpmevent_val[evt_index] = val; + uint64_t inh_avail_mask; if (riscv_cpu_mxl(env) == MXL_RV32) { + env->mhpmevent_val[evt_index] = val; mhpmevt_val = mhpmevt_val | ((uint64_t)env->mhpmeventh_val[evt_index] << 32); + } else { + inh_avail_mask = ~MHPMEVENT_FILTER_MASK | MHPMEVENT_BIT_MINH; + inh_avail_mask |= riscv_has_ext(env, RVU) ? MHPMEVENT_BIT_UINH : 0; + inh_avail_mask |= riscv_has_ext(env, RVS) ? MHPMEVENT_BIT_SINH : 0; + inh_avail_mask |= (riscv_has_ext(env, RVH) && + riscv_has_ext(env, RVU)) ? MHPMEVENT_BIT_VUINH : 0; + inh_avail_mask |= (riscv_has_ext(env, RVH) && + riscv_has_ext(env, RVS)) ? MHPMEVENT_BIT_VSINH : 0; + mhpmevt_val = val & inh_avail_mask; + env->mhpmevent_val[evt_index] = mhpmevt_val; } + riscv_pmu_update_event_map(env, mhpmevt_val, evt_index); return RISCV_EXCP_NONE; @@ -993,11 +1004,21 @@ static RISCVException write_mhpmeventh(CPURISCVState *env, int csrno, target_ulong val) { int evt_index = csrno - CSR_MHPMEVENT3H + 3; - uint64_t mhpmevth_val = val; + uint64_t mhpmevth_val; uint64_t mhpmevt_val = env->mhpmevent_val[evt_index]; + target_ulong inh_avail_mask = (target_ulong)(~MHPMEVENTH_FILTER_MASK | + MHPMEVENTH_BIT_MINH); + inh_avail_mask |= riscv_has_ext(env, RVU) ? MHPMEVENTH_BIT_UINH : 0; + inh_avail_mask |= riscv_has_ext(env, RVS) ? MHPMEVENTH_BIT_SINH : 0; + inh_avail_mask |= (riscv_has_ext(env, RVH) && + riscv_has_ext(env, RVU)) ? MHPMEVENTH_BIT_VUINH : 0; + inh_avail_mask |= (riscv_has_ext(env, RVH) && + riscv_has_ext(env, RVS)) ? MHPMEVENTH_BIT_VSINH : 0; + + mhpmevth_val = val & inh_avail_mask; mhpmevt_val = mhpmevt_val | (mhpmevth_val << 32); - env->mhpmeventh_val[evt_index] = val; + env->mhpmeventh_val[evt_index] = mhpmevth_val; riscv_pmu_update_event_map(env, mhpmevt_val, evt_index); From b2d7a7c7e4e30fb5341d38deac968de675f9419c Mon Sep 17 00:00:00 2001 From: Atish Patra Date: Thu, 11 Jul 2024 15:31:10 -0700 Subject: [PATCH 21/30] target/riscv: Implement privilege mode filtering for cycle/instret Privilege mode filtering can also be emulated for cycle/instret by tracking host_ticks/icount during each privilege mode switch. This patch implements that for both cycle/instret and mhpmcounters. The first one requires Smcntrpmf while the other one requires Sscofpmf to be enabled. The cycle/instret are still computed using host ticks when icount is not enabled. Otherwise, they are computed using raw icount which is more accurate in icount mode. Co-Developed-by: Rajnesh Kanwal Signed-off-by: Rajnesh Kanwal Reviewed-by: Daniel Henrique Barboza Acked-by: Alistair Francis Signed-off-by: Atish Patra Message-ID: <20240711-smcntrpmf_v7-v8-7-b7c38ae7b263@rivosinc.com> Signed-off-by: Alistair Francis --- target/riscv/cpu.h | 11 ++++ target/riscv/cpu_helper.c | 9 ++- target/riscv/csr.c | 117 ++++++++++++++++++++++++++------------ target/riscv/pmu.c | 92 ++++++++++++++++++++++++++++++ target/riscv/pmu.h | 2 + 5 files changed, 194 insertions(+), 37 deletions(-) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 980e2154cd..f515ad072b 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -181,6 +181,15 @@ typedef struct PMUCTRState { target_ulong irq_overflow_left; } PMUCTRState; +typedef struct PMUFixedCtrState { + /* Track cycle and icount for each privilege mode */ + uint64_t counter[4]; + uint64_t counter_prev[4]; + /* Track cycle and icount for each privilege mode when V = 1*/ + uint64_t counter_virt[2]; + uint64_t counter_virt_prev[2]; +} PMUFixedCtrState; + struct CPUArchState { target_ulong gpr[32]; target_ulong gprh[32]; /* 64 top bits of the 128-bit registers */ @@ -377,6 +386,8 @@ struct CPUArchState { /* PMU event selector configured values for RV32 */ target_ulong mhpmeventh_val[RV_MAX_MHPMEVENTS]; + PMUFixedCtrState pmu_fixed_ctrs[2]; + target_ulong sscratch; target_ulong mscratch; diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index 10d3fdaed3..395a1d9140 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -695,9 +695,14 @@ void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv, bool virt_en) { g_assert(newpriv <= PRV_M && newpriv != PRV_RESERVED); - if (icount_enabled() && newpriv != env->priv) { - riscv_itrigger_update_priv(env); + if (newpriv != env->priv || env->virt_enabled != virt_en) { + if (icount_enabled()) { + riscv_itrigger_update_priv(env); + } + + riscv_pmu_update_fixed_ctrs(env, newpriv, virt_en); } + /* tlb_flush is unnecessary as mode is contained in mmu_idx */ env->priv = newpriv; env->xl = cpu_recompute_xl(env); diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 364583dc03..85d3f0aa3f 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -787,36 +787,16 @@ static RISCVException write_vcsr(CPURISCVState *env, int csrno, return RISCV_EXCP_NONE; } +#if defined(CONFIG_USER_ONLY) /* User Timers and Counters */ -static target_ulong get_ticks(bool shift, bool instructions) +static target_ulong get_ticks(bool shift) { - int64_t val; - target_ulong result; - -#if !defined(CONFIG_USER_ONLY) - if (icount_enabled()) { - if (instructions) { - val = icount_get_raw(); - } else { - val = icount_get(); - } - } else { - val = cpu_get_host_ticks(); - } -#else - val = cpu_get_host_ticks(); -#endif - - if (shift) { - result = val >> 32; - } else { - result = val; - } + int64_t val = cpu_get_host_ticks(); + target_ulong result = shift ? val >> 32 : val; return result; } -#if defined(CONFIG_USER_ONLY) static RISCVException read_time(CPURISCVState *env, int csrno, target_ulong *val) { @@ -834,14 +814,14 @@ static RISCVException read_timeh(CPURISCVState *env, int csrno, static RISCVException read_hpmcounter(CPURISCVState *env, int csrno, target_ulong *val) { - *val = get_ticks(false, (csrno == CSR_INSTRET)); + *val = get_ticks(false); return RISCV_EXCP_NONE; } static RISCVException read_hpmcounterh(CPURISCVState *env, int csrno, target_ulong *val) { - *val = get_ticks(true, (csrno == CSR_INSTRETH)); + *val = get_ticks(true); return RISCV_EXCP_NONE; } @@ -1025,17 +1005,82 @@ static RISCVException write_mhpmeventh(CPURISCVState *env, int csrno, return RISCV_EXCP_NONE; } +static target_ulong riscv_pmu_ctr_get_fixed_counters_val(CPURISCVState *env, + int counter_idx, + bool upper_half) +{ + int inst = riscv_pmu_ctr_monitor_instructions(env, counter_idx); + uint64_t *counter_arr_virt = env->pmu_fixed_ctrs[inst].counter_virt; + uint64_t *counter_arr = env->pmu_fixed_ctrs[inst].counter; + target_ulong result = 0; + uint64_t curr_val = 0; + uint64_t cfg_val = 0; + + if (counter_idx == 0) { + cfg_val = upper_half ? ((uint64_t)env->mcyclecfgh << 32) : + env->mcyclecfg; + } else if (counter_idx == 2) { + cfg_val = upper_half ? ((uint64_t)env->minstretcfgh << 32) : + env->minstretcfg; + } else { + cfg_val = upper_half ? + ((uint64_t)env->mhpmeventh_val[counter_idx] << 32) : + env->mhpmevent_val[counter_idx]; + cfg_val &= MHPMEVENT_FILTER_MASK; + } + + if (!cfg_val) { + if (icount_enabled()) { + curr_val = inst ? icount_get_raw() : icount_get(); + } else { + curr_val = cpu_get_host_ticks(); + } + + goto done; + } + + if (!(cfg_val & MCYCLECFG_BIT_MINH)) { + curr_val += counter_arr[PRV_M]; + } + + if (!(cfg_val & MCYCLECFG_BIT_SINH)) { + curr_val += counter_arr[PRV_S]; + } + + if (!(cfg_val & MCYCLECFG_BIT_UINH)) { + curr_val += counter_arr[PRV_U]; + } + + if (!(cfg_val & MCYCLECFG_BIT_VSINH)) { + curr_val += counter_arr_virt[PRV_S]; + } + + if (!(cfg_val & MCYCLECFG_BIT_VUINH)) { + curr_val += counter_arr_virt[PRV_U]; + } + +done: + if (riscv_cpu_mxl(env) == MXL_RV32) { + result = upper_half ? curr_val >> 32 : curr_val; + } else { + result = curr_val; + } + + return result; +} + static RISCVException write_mhpmcounter(CPURISCVState *env, int csrno, target_ulong val) { int ctr_idx = csrno - CSR_MCYCLE; PMUCTRState *counter = &env->pmu_ctrs[ctr_idx]; uint64_t mhpmctr_val = val; - bool instr = riscv_pmu_ctr_monitor_instructions(env, ctr_idx); counter->mhpmcounter_val = val; - if (riscv_pmu_ctr_monitor_cycles(env, ctr_idx) || instr) { - counter->mhpmcounter_prev = get_ticks(false, instr); + if (riscv_pmu_ctr_monitor_cycles(env, ctr_idx) || + riscv_pmu_ctr_monitor_instructions(env, ctr_idx)) { + counter->mhpmcounter_prev = riscv_pmu_ctr_get_fixed_counters_val(env, + ctr_idx, false); if (ctr_idx > 2) { if (riscv_cpu_mxl(env) == MXL_RV32) { mhpmctr_val = mhpmctr_val | @@ -1058,12 +1103,13 @@ static RISCVException write_mhpmcounterh(CPURISCVState *env, int csrno, PMUCTRState *counter = &env->pmu_ctrs[ctr_idx]; uint64_t mhpmctr_val = counter->mhpmcounter_val; uint64_t mhpmctrh_val = val; - bool instr = riscv_pmu_ctr_monitor_instructions(env, ctr_idx); counter->mhpmcounterh_val = val; mhpmctr_val = mhpmctr_val | (mhpmctrh_val << 32); - if (riscv_pmu_ctr_monitor_cycles(env, ctr_idx) || instr) { - counter->mhpmcounterh_prev = get_ticks(true, instr); + if (riscv_pmu_ctr_monitor_cycles(env, ctr_idx) || + riscv_pmu_ctr_monitor_instructions(env, ctr_idx)) { + counter->mhpmcounterh_prev = riscv_pmu_ctr_get_fixed_counters_val(env, + ctr_idx, true); if (ctr_idx > 2) { riscv_pmu_setup_timer(env, mhpmctr_val, ctr_idx); } @@ -1082,7 +1128,6 @@ static RISCVException riscv_pmu_read_ctr(CPURISCVState *env, target_ulong *val, counter->mhpmcounter_prev; target_ulong ctr_val = upper_half ? counter->mhpmcounterh_val : counter->mhpmcounter_val; - bool instr = riscv_pmu_ctr_monitor_instructions(env, ctr_idx); if (get_field(env->mcountinhibit, BIT(ctr_idx))) { /* @@ -1103,8 +1148,10 @@ static RISCVException riscv_pmu_read_ctr(CPURISCVState *env, target_ulong *val, * 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) || instr) { - *val = get_ticks(upper_half, instr) - ctr_prev + ctr_val; + if (riscv_pmu_ctr_monitor_cycles(env, ctr_idx) || + riscv_pmu_ctr_monitor_instructions(env, ctr_idx)) { + *val = riscv_pmu_ctr_get_fixed_counters_val(env, ctr_idx, upper_half) - + ctr_prev + ctr_val; } else { *val = ctr_val; } diff --git a/target/riscv/pmu.c b/target/riscv/pmu.c index 0e7d58b8a5..ac648cff8d 100644 --- a/target/riscv/pmu.c +++ b/target/riscv/pmu.c @@ -19,6 +19,7 @@ #include "qemu/osdep.h" #include "qemu/log.h" #include "qemu/error-report.h" +#include "qemu/timer.h" #include "cpu.h" #include "pmu.h" #include "sysemu/cpu-timers.h" @@ -176,6 +177,97 @@ static int riscv_pmu_incr_ctr_rv64(RISCVCPU *cpu, uint32_t ctr_idx) return 0; } +/* + * Information needed to update counters: + * new_priv, new_virt: To correctly save starting snapshot for the newly + * started mode. Look at array being indexed with newprv. + * old_priv, old_virt: To correctly select previous snapshot for old priv + * and compute delta. Also to select correct counter + * to inc. Look at arrays being indexed with env->priv. + * + * To avoid the complexity of calling this function, we assume that + * env->priv and env->virt_enabled contain old priv and old virt and + * new priv and new virt values are passed in as arguments. + */ +static void riscv_pmu_icount_update_priv(CPURISCVState *env, + target_ulong newpriv, bool new_virt) +{ + uint64_t *snapshot_prev, *snapshot_new; + uint64_t current_icount; + uint64_t *counter_arr; + uint64_t delta; + + if (icount_enabled()) { + current_icount = icount_get_raw(); + } else { + current_icount = cpu_get_host_ticks(); + } + + if (env->virt_enabled) { + counter_arr = env->pmu_fixed_ctrs[1].counter_virt; + snapshot_prev = env->pmu_fixed_ctrs[1].counter_virt_prev; + } else { + counter_arr = env->pmu_fixed_ctrs[1].counter; + snapshot_prev = env->pmu_fixed_ctrs[1].counter_prev; + } + + if (new_virt) { + snapshot_new = env->pmu_fixed_ctrs[1].counter_virt_prev; + } else { + snapshot_new = env->pmu_fixed_ctrs[1].counter_prev; + } + + /* + * new_priv can be same as env->priv. So we need to calculate + * delta first before updating snapshot_new[new_priv]. + */ + delta = current_icount - snapshot_prev[env->priv]; + snapshot_new[newpriv] = current_icount; + + counter_arr[env->priv] += delta; +} + +static void riscv_pmu_cycle_update_priv(CPURISCVState *env, + target_ulong newpriv, bool new_virt) +{ + uint64_t *snapshot_prev, *snapshot_new; + uint64_t current_ticks; + uint64_t *counter_arr; + uint64_t delta; + + if (icount_enabled()) { + current_ticks = icount_get(); + } else { + current_ticks = cpu_get_host_ticks(); + } + + if (env->virt_enabled) { + counter_arr = env->pmu_fixed_ctrs[0].counter_virt; + snapshot_prev = env->pmu_fixed_ctrs[0].counter_virt_prev; + } else { + counter_arr = env->pmu_fixed_ctrs[0].counter; + snapshot_prev = env->pmu_fixed_ctrs[0].counter_prev; + } + + if (new_virt) { + snapshot_new = env->pmu_fixed_ctrs[0].counter_virt_prev; + } else { + snapshot_new = env->pmu_fixed_ctrs[0].counter_prev; + } + + delta = current_ticks - snapshot_prev[env->priv]; + snapshot_new[newpriv] = current_ticks; + + counter_arr[env->priv] += delta; +} + +void riscv_pmu_update_fixed_ctrs(CPURISCVState *env, target_ulong newpriv, + bool new_virt) +{ + riscv_pmu_cycle_update_priv(env, newpriv, new_virt); + riscv_pmu_icount_update_priv(env, newpriv, new_virt); +} + int riscv_pmu_incr_ctr(RISCVCPU *cpu, enum riscv_pmu_event_idx event_idx) { uint32_t ctr_idx; diff --git a/target/riscv/pmu.h b/target/riscv/pmu.h index 7c0ad661e0..ca40cfeed6 100644 --- a/target/riscv/pmu.h +++ b/target/riscv/pmu.h @@ -34,5 +34,7 @@ int riscv_pmu_incr_ctr(RISCVCPU *cpu, enum riscv_pmu_event_idx event_idx); void riscv_pmu_generate_fdt_node(void *fdt, uint32_t cmask, char *pmu_name); int riscv_pmu_setup_timer(CPURISCVState *env, uint64_t value, uint32_t ctr_idx); +void riscv_pmu_update_fixed_ctrs(CPURISCVState *env, target_ulong newpriv, + bool new_virt); #endif /* RISCV_PMU_H */ From 46023470e014234f3e15ec4497e003550bd7da0d Mon Sep 17 00:00:00 2001 From: Atish Patra Date: Thu, 11 Jul 2024 15:31:11 -0700 Subject: [PATCH 22/30] target/riscv: Save counter values during countinhibit update Currently, if a counter monitoring cycle/instret is stopped via mcountinhibit we just update the state while the value is saved during the next read. This is not accurate as the read may happen many cycles after the counter is stopped. Ideally, the read should return the value saved when the counter is stopped. Thus, save the value of the counter during the inhibit update operation and return that value during the read if corresponding bit in mcountihibit is set. Acked-by: Alistair Francis Reviewed-by: Daniel Henrique Barboza Signed-off-by: Atish Patra Message-ID: <20240711-smcntrpmf_v7-v8-8-b7c38ae7b263@rivosinc.com> Signed-off-by: Alistair Francis --- target/riscv/cpu.h | 1 - target/riscv/csr.c | 34 ++++++++++++++++++++++------------ target/riscv/machine.c | 5 ++--- 3 files changed, 24 insertions(+), 16 deletions(-) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index f515ad072b..093c86b8b9 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -176,7 +176,6 @@ typedef struct PMUCTRState { target_ulong mhpmcounter_prev; /* Snapshort value of a counter in RV32 */ target_ulong mhpmcounterh_prev; - bool started; /* Value beyond UINT32_MAX/UINT64_MAX before overflow interrupt trigger */ target_ulong irq_overflow_left; } PMUCTRState; diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 85d3f0aa3f..b7a24f9c60 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -1131,17 +1131,11 @@ static RISCVException riscv_pmu_read_ctr(CPURISCVState *env, target_ulong *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. + * Counter should not increment if inhibit bit is set. Just return the + * current counter value. */ - if (!counter->started) { - *val = ctr_val; - return RISCV_EXCP_NONE; - } else { - /* Mark that the counter has been stopped */ - counter->started = false; - } + *val = ctr_val; + return RISCV_EXCP_NONE; } /* @@ -2183,9 +2177,25 @@ static RISCVException write_mcountinhibit(CPURISCVState *env, int csrno, /* 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; + if (get_field(env->mcountinhibit, BIT(cidx)) && (val & BIT(cidx))) { + /* + * Update the counter value for cycle/instret as we can't stop the + * host ticks. But we should show the current value at this moment. + */ + if (riscv_pmu_ctr_monitor_cycles(env, cidx) || + riscv_pmu_ctr_monitor_instructions(env, cidx)) { + counter->mhpmcounter_val = + riscv_pmu_ctr_get_fixed_counters_val(env, cidx, false) - + counter->mhpmcounter_prev + + counter->mhpmcounter_val; + if (riscv_cpu_mxl(env) == MXL_RV32) { + counter->mhpmcounterh_val = + riscv_pmu_ctr_get_fixed_counters_val(env, cidx, true) - + counter->mhpmcounterh_prev + + counter->mhpmcounterh_val; + } + } } } diff --git a/target/riscv/machine.c b/target/riscv/machine.c index 76f2150f78..492c2c6d9d 100644 --- a/target/riscv/machine.c +++ b/target/riscv/machine.c @@ -320,15 +320,14 @@ static bool pmu_needed(void *opaque) static const VMStateDescription vmstate_pmu_ctr_state = { .name = "cpu/pmu", - .version_id = 1, - .minimum_version_id = 1, + .version_id = 2, + .minimum_version_id = 2, .needed = pmu_needed, .fields = (const 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() } }; From 8cff74c26dbdfc746d8f0165c233be3d396d4572 Mon Sep 17 00:00:00 2001 From: Atish Patra Date: Thu, 11 Jul 2024 15:31:12 -0700 Subject: [PATCH 23/30] target/riscv: Enforce WARL behavior for scounteren/hcounteren scounteren/hcountern are also WARL registers similar to mcountern. Only set the bits for the available counters during the write to preserve the WARL behavior. Signed-off-by: Atish Patra Reviewed-by: Daniel Henrique Barboza Reviewed-by: Alistair Francis Message-ID: <20240711-smcntrpmf_v7-v8-9-b7c38ae7b263@rivosinc.com> Signed-off-by: Alistair Francis --- target/riscv/csr.c | 12 ++++++++++-- 1 file changed, 10 insertions(+), 2 deletions(-) diff --git a/target/riscv/csr.c b/target/riscv/csr.c index b7a24f9c60..d6c5b73afd 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -3063,7 +3063,11 @@ static RISCVException read_scounteren(CPURISCVState *env, int csrno, static RISCVException write_scounteren(CPURISCVState *env, int csrno, target_ulong val) { - env->scounteren = val; + RISCVCPU *cpu = env_archcpu(env); + + /* WARL register - disable unavailable counters */ + env->scounteren = val & (cpu->pmu_avail_ctrs | COUNTEREN_CY | COUNTEREN_TM | + COUNTEREN_IR); return RISCV_EXCP_NONE; } @@ -3722,7 +3726,11 @@ static RISCVException read_hcounteren(CPURISCVState *env, int csrno, static RISCVException write_hcounteren(CPURISCVState *env, int csrno, target_ulong val) { - env->hcounteren = val; + RISCVCPU *cpu = env_archcpu(env); + + /* WARL register - disable unavailable counters */ + env->hcounteren = val & (cpu->pmu_avail_ctrs | COUNTEREN_CY | COUNTEREN_TM | + COUNTEREN_IR); return RISCV_EXCP_NONE; } From 22c721c34c1609b5ac53dfc0d34125ec479205a0 Mon Sep 17 00:00:00 2001 From: Rajnesh Kanwal Date: Thu, 11 Jul 2024 15:31:13 -0700 Subject: [PATCH 24/30] target/riscv: Start counters from both mhpmcounter and mcountinhibit Currently we start timer counter from write_mhpmcounter path only without checking for mcountinhibit bit. This changes adds mcountinhibit check and also programs the counter from write_mcountinhibit as well. When a counter is stopped using mcountinhibit we simply update the value of the counter based on current host ticks and save it for future reads. We don't need to disable running timer as pmu_timer_trigger_irq will discard the interrupt if the counter has been inhibited. Signed-off-by: Rajnesh Kanwal Reviewed-by: Daniel Henrique Barboza Message-ID: <20240711-smcntrpmf_v7-v8-10-b7c38ae7b263@rivosinc.com> Signed-off-by: Alistair Francis --- target/riscv/csr.c | 75 ++++++++++++++++++++++++++++++++-------------- target/riscv/pmu.c | 3 +- 2 files changed, 54 insertions(+), 24 deletions(-) diff --git a/target/riscv/csr.c b/target/riscv/csr.c index d6c5b73afd..bb6ac33ac2 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -1077,8 +1077,9 @@ static RISCVException write_mhpmcounter(CPURISCVState *env, int csrno, uint64_t mhpmctr_val = val; counter->mhpmcounter_val = val; - if (riscv_pmu_ctr_monitor_cycles(env, ctr_idx) || - riscv_pmu_ctr_monitor_instructions(env, ctr_idx)) { + if (!get_field(env->mcountinhibit, BIT(ctr_idx)) && + (riscv_pmu_ctr_monitor_cycles(env, ctr_idx) || + riscv_pmu_ctr_monitor_instructions(env, ctr_idx))) { counter->mhpmcounter_prev = riscv_pmu_ctr_get_fixed_counters_val(env, ctr_idx, false); if (ctr_idx > 2) { @@ -1106,8 +1107,9 @@ static RISCVException write_mhpmcounterh(CPURISCVState *env, int csrno, counter->mhpmcounterh_val = val; mhpmctr_val = mhpmctr_val | (mhpmctrh_val << 32); - if (riscv_pmu_ctr_monitor_cycles(env, ctr_idx) || - riscv_pmu_ctr_monitor_instructions(env, ctr_idx)) { + if (!get_field(env->mcountinhibit, BIT(ctr_idx)) && + (riscv_pmu_ctr_monitor_cycles(env, ctr_idx) || + riscv_pmu_ctr_monitor_instructions(env, ctr_idx))) { counter->mhpmcounterh_prev = riscv_pmu_ctr_get_fixed_counters_val(env, ctr_idx, true); if (ctr_idx > 2) { @@ -2170,31 +2172,60 @@ static RISCVException write_mcountinhibit(CPURISCVState *env, int csrno, int cidx; PMUCTRState *counter; RISCVCPU *cpu = env_archcpu(env); + uint32_t present_ctrs = cpu->pmu_avail_ctrs | COUNTEREN_CY | COUNTEREN_IR; + target_ulong updated_ctrs = (env->mcountinhibit ^ val) & present_ctrs; + uint64_t mhpmctr_val, prev_count, curr_count; /* WARL register - disable unavailable counters; TM bit is always 0 */ - env->mcountinhibit = - val & (cpu->pmu_avail_ctrs | COUNTEREN_CY | COUNTEREN_IR); + env->mcountinhibit = val & present_ctrs; /* Check if any other counter is also monitoring cycles/instructions */ for (cidx = 0; cidx < RV_MAX_MHPMCOUNTERS; cidx++) { - counter = &env->pmu_ctrs[cidx]; - if (get_field(env->mcountinhibit, BIT(cidx)) && (val & BIT(cidx))) { - /* - * Update the counter value for cycle/instret as we can't stop the - * host ticks. But we should show the current value at this moment. - */ - if (riscv_pmu_ctr_monitor_cycles(env, cidx) || - riscv_pmu_ctr_monitor_instructions(env, cidx)) { - counter->mhpmcounter_val = - riscv_pmu_ctr_get_fixed_counters_val(env, cidx, false) - - counter->mhpmcounter_prev + - counter->mhpmcounter_val; + if (!(updated_ctrs & BIT(cidx)) || + (!riscv_pmu_ctr_monitor_cycles(env, cidx) && + !riscv_pmu_ctr_monitor_instructions(env, cidx))) { + continue; + } + + counter = &env->pmu_ctrs[cidx]; + + if (!get_field(env->mcountinhibit, BIT(cidx))) { + counter->mhpmcounter_prev = + riscv_pmu_ctr_get_fixed_counters_val(env, cidx, false); + if (riscv_cpu_mxl(env) == MXL_RV32) { + counter->mhpmcounterh_prev = + riscv_pmu_ctr_get_fixed_counters_val(env, cidx, true); + } + + if (cidx > 2) { + mhpmctr_val = counter->mhpmcounter_val; if (riscv_cpu_mxl(env) == MXL_RV32) { - counter->mhpmcounterh_val = - riscv_pmu_ctr_get_fixed_counters_val(env, cidx, true) - - counter->mhpmcounterh_prev + - counter->mhpmcounterh_val; + mhpmctr_val = mhpmctr_val | + ((uint64_t)counter->mhpmcounterh_val << 32); } + riscv_pmu_setup_timer(env, mhpmctr_val, cidx); + } + } else { + curr_count = riscv_pmu_ctr_get_fixed_counters_val(env, cidx, false); + + mhpmctr_val = counter->mhpmcounter_val; + prev_count = counter->mhpmcounter_prev; + if (riscv_cpu_mxl(env) == MXL_RV32) { + uint64_t tmp = + riscv_pmu_ctr_get_fixed_counters_val(env, cidx, true); + + curr_count = curr_count | (tmp << 32); + mhpmctr_val = mhpmctr_val | + ((uint64_t)counter->mhpmcounterh_val << 32); + prev_count = prev_count | + ((uint64_t)counter->mhpmcounterh_prev << 32); + } + + /* Adjust the counter for later reads. */ + mhpmctr_val = curr_count - prev_count + mhpmctr_val; + counter->mhpmcounter_val = mhpmctr_val; + if (riscv_cpu_mxl(env) == MXL_RV32) { + counter->mhpmcounterh_val = mhpmctr_val >> 32; } } } diff --git a/target/riscv/pmu.c b/target/riscv/pmu.c index ac648cff8d..63420d9f36 100644 --- a/target/riscv/pmu.c +++ b/target/riscv/pmu.c @@ -285,8 +285,7 @@ int riscv_pmu_incr_ctr(RISCVCPU *cpu, enum riscv_pmu_event_idx event_idx) } ctr_idx = GPOINTER_TO_UINT(value); - if (!riscv_pmu_counter_enabled(cpu, ctr_idx) || - get_field(env->mcountinhibit, BIT(ctr_idx))) { + if (!riscv_pmu_counter_enabled(cpu, ctr_idx)) { return -1; } From 74112400df659b0edb1da35db5c948313ffeffd0 Mon Sep 17 00:00:00 2001 From: Rajnesh Kanwal Date: Thu, 11 Jul 2024 15:31:14 -0700 Subject: [PATCH 25/30] target/riscv: More accurately model priv mode filtering. In case of programmable counters configured to count inst/cycles we often end-up with counter not incrementing at all from kernel's perspective. For example: - Kernel configures hpm3 to count instructions and sets hpmcounter to -10000 and all modes except U mode are inhibited. - In QEMU we configure a timer to expire after ~10000 instructions. - Problem is, it's often the case that kernel might not even schedule Umode task and we hit the timer callback in QEMU. - In the timer callback we inject the interrupt into kernel, kernel runs the handler and reads hpmcounter3 value. - Given QEMU maintains individual counters to count for each privilege mode, and given umode never ran, the umode counter didn't increment and QEMU returns same value as was programmed by the kernel when starting the counter. - Kernel checks for overflow using previous and current value of the counter and reprograms the counter given there wasn't an overflow as per the counter value. (Which itself is a problem. We have QEMU telling kernel that counter3 overflowed but the counter value returned by QEMU doesn't seem to reflect that.). This change makes sure that timer is reprogrammed from the handler if the counter didn't overflow based on the counter value. Second, this change makes sure that whenever the counter is read, it's value is updated to reflect the latest count. Signed-off-by: Rajnesh Kanwal Reviewed-by: Daniel Henrique Barboza Message-ID: <20240711-smcntrpmf_v7-v8-11-b7c38ae7b263@rivosinc.com> Signed-off-by: Alistair Francis --- target/riscv/csr.c | 5 ++++- target/riscv/pmu.c | 30 +++++++++++++++++++++++++++--- target/riscv/pmu.h | 2 ++ 3 files changed, 33 insertions(+), 4 deletions(-) diff --git a/target/riscv/csr.c b/target/riscv/csr.c index bb6ac33ac2..781ef27eba 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -1039,6 +1039,9 @@ static target_ulong riscv_pmu_ctr_get_fixed_counters_val(CPURISCVState *env, goto done; } + /* Update counter before reading. */ + riscv_pmu_update_fixed_ctrs(env, env->priv, env->virt_enabled); + if (!(cfg_val & MCYCLECFG_BIT_MINH)) { curr_val += counter_arr[PRV_M]; } @@ -1122,7 +1125,7 @@ static RISCVException write_mhpmcounterh(CPURISCVState *env, int csrno, return RISCV_EXCP_NONE; } -static RISCVException riscv_pmu_read_ctr(CPURISCVState *env, target_ulong *val, +RISCVException riscv_pmu_read_ctr(CPURISCVState *env, target_ulong *val, bool upper_half, uint32_t ctr_idx) { PMUCTRState *counter = &env->pmu_ctrs[ctr_idx]; diff --git a/target/riscv/pmu.c b/target/riscv/pmu.c index 63420d9f36..a4729f6c53 100644 --- a/target/riscv/pmu.c +++ b/target/riscv/pmu.c @@ -425,6 +425,8 @@ static void pmu_timer_trigger_irq(RISCVCPU *cpu, target_ulong *mhpmevent_val; uint64_t of_bit_mask; int64_t irq_trigger_at; + uint64_t curr_ctr_val, curr_ctrh_val; + uint64_t ctr_val; if (evt_idx != RISCV_PMU_EVENT_HW_CPU_CYCLES && evt_idx != RISCV_PMU_EVENT_HW_INSTRUCTIONS) { @@ -454,6 +456,26 @@ static void pmu_timer_trigger_irq(RISCVCPU *cpu, return; } + riscv_pmu_read_ctr(env, (target_ulong *)&curr_ctr_val, false, ctr_idx); + ctr_val = counter->mhpmcounter_val; + if (riscv_cpu_mxl(env) == MXL_RV32) { + riscv_pmu_read_ctr(env, (target_ulong *)&curr_ctrh_val, true, ctr_idx); + curr_ctr_val = curr_ctr_val | (curr_ctrh_val << 32); + ctr_val = ctr_val | + ((uint64_t)counter->mhpmcounterh_val << 32); + } + + /* + * We can not accommodate for inhibited modes when setting up timer. Check + * if the counter has actually overflowed or not by comparing current + * counter value (accommodated for inhibited modes) with software written + * counter value. + */ + if (curr_ctr_val >= ctr_val) { + riscv_pmu_setup_timer(env, curr_ctr_val, ctr_idx); + return; + } + if (cpu->pmu_avail_ctrs & BIT(ctr_idx)) { /* Generate interrupt only if OF bit is clear */ if (!(*mhpmevent_val & of_bit_mask)) { @@ -475,7 +497,7 @@ void riscv_pmu_timer_cb(void *priv) int riscv_pmu_setup_timer(CPURISCVState *env, uint64_t value, uint32_t ctr_idx) { - uint64_t overflow_delta, overflow_at; + uint64_t overflow_delta, overflow_at, curr_ns; int64_t overflow_ns, overflow_left = 0; RISCVCPU *cpu = env_archcpu(env); PMUCTRState *counter = &env->pmu_ctrs[ctr_idx]; @@ -506,8 +528,10 @@ int riscv_pmu_setup_timer(CPURISCVState *env, uint64_t value, uint32_t ctr_idx) } else { return -1; } - overflow_at = (uint64_t)qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + - overflow_ns; + curr_ns = (uint64_t)qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL); + overflow_at = curr_ns + overflow_ns; + if (overflow_at <= curr_ns) + overflow_at = UINT64_MAX; if (overflow_at > INT64_MAX) { overflow_left += overflow_at - INT64_MAX; diff --git a/target/riscv/pmu.h b/target/riscv/pmu.h index ca40cfeed6..3853d0e262 100644 --- a/target/riscv/pmu.h +++ b/target/riscv/pmu.h @@ -36,5 +36,7 @@ int riscv_pmu_setup_timer(CPURISCVState *env, uint64_t value, uint32_t ctr_idx); void riscv_pmu_update_fixed_ctrs(CPURISCVState *env, target_ulong newpriv, bool new_virt); +RISCVException riscv_pmu_read_ctr(CPURISCVState *env, target_ulong *val, + bool upper_half, uint32_t ctr_idx); #endif /* RISCV_PMU_H */ From dd4c123636dbdabd7dcc4f76c97af90271cd5fb6 Mon Sep 17 00:00:00 2001 From: Atish Patra Date: Thu, 11 Jul 2024 15:31:15 -0700 Subject: [PATCH 26/30] target/riscv: Do not setup pmu timer if OF is disabled The timer is setup function is invoked in both hpmcounter write and mcountinhibit write path. If the OF bit set, the LCOFI interrupt is disabled. There is no benefitting in setting up the qemu timer until LCOFI is cleared to indicate that interrupts can be fired again. Reviewed-by: Daniel Henrique Barboza Signed-off-by: Atish Patra Message-ID: <20240711-smcntrpmf_v7-v8-12-b7c38ae7b263@rivosinc.com> Signed-off-by: Alistair Francis --- target/riscv/pmu.c | 56 ++++++++++++++++++++++++++++++++++++---------- 1 file changed, 44 insertions(+), 12 deletions(-) diff --git a/target/riscv/pmu.c b/target/riscv/pmu.c index a4729f6c53..3cc0b3648c 100644 --- a/target/riscv/pmu.c +++ b/target/riscv/pmu.c @@ -416,14 +416,49 @@ int riscv_pmu_update_event_map(CPURISCVState *env, uint64_t value, return 0; } +static bool pmu_hpmevent_is_of_set(CPURISCVState *env, uint32_t ctr_idx) +{ + target_ulong mhpmevent_val; + uint64_t of_bit_mask; + + if (riscv_cpu_mxl(env) == MXL_RV32) { + mhpmevent_val = env->mhpmeventh_val[ctr_idx]; + of_bit_mask = MHPMEVENTH_BIT_OF; + } else { + mhpmevent_val = env->mhpmevent_val[ctr_idx]; + of_bit_mask = MHPMEVENT_BIT_OF; + } + + return get_field(mhpmevent_val, of_bit_mask); +} + +static bool pmu_hpmevent_set_of_if_clear(CPURISCVState *env, uint32_t ctr_idx) +{ + target_ulong *mhpmevent_val; + uint64_t of_bit_mask; + + if (riscv_cpu_mxl(env) == MXL_RV32) { + mhpmevent_val = &env->mhpmeventh_val[ctr_idx]; + of_bit_mask = MHPMEVENTH_BIT_OF; + } else { + mhpmevent_val = &env->mhpmevent_val[ctr_idx]; + of_bit_mask = MHPMEVENT_BIT_OF; + } + + if (!get_field(*mhpmevent_val, of_bit_mask)) { + *mhpmevent_val |= of_bit_mask; + return true; + } + + return false; +} + static void pmu_timer_trigger_irq(RISCVCPU *cpu, enum riscv_pmu_event_idx evt_idx) { uint32_t ctr_idx; CPURISCVState *env = &cpu->env; PMUCTRState *counter; - target_ulong *mhpmevent_val; - uint64_t of_bit_mask; int64_t irq_trigger_at; uint64_t curr_ctr_val, curr_ctrh_val; uint64_t ctr_val; @@ -439,12 +474,9 @@ static void pmu_timer_trigger_irq(RISCVCPU *cpu, return; } - if (riscv_cpu_mxl(env) == MXL_RV32) { - mhpmevent_val = &env->mhpmeventh_val[ctr_idx]; - of_bit_mask = MHPMEVENTH_BIT_OF; - } else { - mhpmevent_val = &env->mhpmevent_val[ctr_idx]; - of_bit_mask = MHPMEVENT_BIT_OF; + /* Generate interrupt only if OF bit is clear */ + if (pmu_hpmevent_is_of_set(env, ctr_idx)) { + return; } counter = &env->pmu_ctrs[ctr_idx]; @@ -477,9 +509,7 @@ static void pmu_timer_trigger_irq(RISCVCPU *cpu, } if (cpu->pmu_avail_ctrs & BIT(ctr_idx)) { - /* Generate interrupt only if OF bit is clear */ - if (!(*mhpmevent_val & of_bit_mask)) { - *mhpmevent_val |= of_bit_mask; + if (pmu_hpmevent_set_of_if_clear(env, ctr_idx)) { riscv_cpu_update_mip(env, MIP_LCOFIP, BOOL_TO_MASK(1)); } } @@ -502,7 +532,9 @@ int riscv_pmu_setup_timer(CPURISCVState *env, uint64_t value, uint32_t ctr_idx) RISCVCPU *cpu = env_archcpu(env); PMUCTRState *counter = &env->pmu_ctrs[ctr_idx]; - if (!riscv_pmu_counter_valid(cpu, ctr_idx) || !cpu->cfg.ext_sscofpmf) { + /* No need to setup a timer if LCOFI is disabled when OF is set */ + if (!riscv_pmu_counter_valid(cpu, ctr_idx) || !cpu->cfg.ext_sscofpmf || + pmu_hpmevent_is_of_set(env, ctr_idx)) { return -1; } From 6f6592d62ebaffff353bdd27ec4480972695d24b Mon Sep 17 00:00:00 2001 From: Atish Patra Date: Thu, 11 Jul 2024 15:31:16 -0700 Subject: [PATCH 27/30] target/riscv: Expose the Smcntrpmf config Create a new config for Smcntrpmf extension so that it can be enabled/ disabled from the qemu commandline. Signed-off-by: Atish Patra Acked-by: Alistair Francis Message-ID: <20240711-smcntrpmf_v7-v8-13-b7c38ae7b263@rivosinc.com> Signed-off-by: Alistair Francis --- target/riscv/cpu.c | 1 + 1 file changed, 1 insertion(+) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 4efe7ee3b0..a90808a3ba 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -1472,6 +1472,7 @@ const char *riscv_get_misa_ext_description(uint32_t bit) const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = { /* Defaults for standard extensions */ MULTI_EXT_CFG_BOOL("sscofpmf", ext_sscofpmf, false), + MULTI_EXT_CFG_BOOL("smcntrpmf", ext_smcntrpmf, false), MULTI_EXT_CFG_BOOL("zifencei", ext_zifencei, true), MULTI_EXT_CFG_BOOL("zicsr", ext_zicsr, true), MULTI_EXT_CFG_BOOL("zihintntl", ext_zihintntl, true), From 38c83e8d3a333b8b377367756a2b6c700c7d0084 Mon Sep 17 00:00:00 2001 From: Yu-Ming Chang Date: Fri, 8 Mar 2024 15:48:03 +0800 Subject: [PATCH 28/30] target/riscv: raise an exception when CSRRS/CSRRC writes a read-only CSR Both CSRRS and CSRRC always read the addressed CSR and cause any read side effects regardless of rs1 and rd fields. Note that if rs1 specifies a register holding a zero value other than x0, the instruction will still attempt to write the unmodified value back to the CSR and will cause any attendant side effects. So if CSRRS or CSRRC tries to write a read-only CSR with rs1 which specifies a register holding a zero value, an illegal instruction exception should be raised. Signed-off-by: Yu-Ming Chang Signed-off-by: Alvin Chang Reviewed-by: Alistair Francis Message-ID: <172100444279.18077.6893072378718059541-0@git.sr.ht> Signed-off-by: Alistair Francis --- target/riscv/cpu.h | 4 +++ target/riscv/csr.c | 57 ++++++++++++++++++++++++++++++++++++---- target/riscv/op_helper.c | 6 ++--- 3 files changed, 58 insertions(+), 9 deletions(-) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 093c86b8b9..1619c3acb6 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -751,6 +751,8 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, vaddr *pc, void riscv_cpu_update_mask(CPURISCVState *env); bool riscv_cpu_is_32bit(RISCVCPU *cpu); +RISCVException riscv_csrr(CPURISCVState *env, int csrno, + target_ulong *ret_value); RISCVException riscv_csrrw(CPURISCVState *env, int csrno, target_ulong *ret_value, target_ulong new_value, target_ulong write_mask); @@ -783,6 +785,8 @@ typedef RISCVException (*riscv_csr_op_fn)(CPURISCVState *env, int csrno, target_ulong new_value, target_ulong write_mask); +RISCVException riscv_csrr_i128(CPURISCVState *env, int csrno, + Int128 *ret_value); RISCVException riscv_csrrw_i128(CPURISCVState *env, int csrno, Int128 *ret_value, Int128 new_value, Int128 write_mask); diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 781ef27eba..ea3560342c 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -4624,7 +4624,7 @@ static RISCVException rmw_seed(CPURISCVState *env, int csrno, static inline RISCVException riscv_csrrw_check(CPURISCVState *env, int csrno, - bool write_mask) + bool write) { /* check privileges and return RISCV_EXCP_ILLEGAL_INST if check fails */ bool read_only = get_field(csrno, 0xC00) == 3; @@ -4646,7 +4646,7 @@ static inline RISCVException riscv_csrrw_check(CPURISCVState *env, } /* read / write check */ - if (write_mask && read_only) { + if (write && read_only) { return RISCV_EXCP_ILLEGAL_INST; } @@ -4733,11 +4733,22 @@ static RISCVException riscv_csrrw_do64(CPURISCVState *env, int csrno, return RISCV_EXCP_NONE; } +RISCVException riscv_csrr(CPURISCVState *env, int csrno, + target_ulong *ret_value) +{ + RISCVException ret = riscv_csrrw_check(env, csrno, false); + if (ret != RISCV_EXCP_NONE) { + return ret; + } + + return riscv_csrrw_do64(env, csrno, ret_value, 0, 0); +} + RISCVException riscv_csrrw(CPURISCVState *env, int csrno, target_ulong *ret_value, target_ulong new_value, target_ulong write_mask) { - RISCVException ret = riscv_csrrw_check(env, csrno, write_mask); + RISCVException ret = riscv_csrrw_check(env, csrno, true); if (ret != RISCV_EXCP_NONE) { return ret; } @@ -4785,13 +4796,45 @@ static RISCVException riscv_csrrw_do128(CPURISCVState *env, int csrno, return RISCV_EXCP_NONE; } +RISCVException riscv_csrr_i128(CPURISCVState *env, int csrno, + Int128 *ret_value) +{ + RISCVException ret; + + ret = riscv_csrrw_check(env, csrno, false); + if (ret != RISCV_EXCP_NONE) { + return ret; + } + + if (csr_ops[csrno].read128) { + return riscv_csrrw_do128(env, csrno, ret_value, + int128_zero(), int128_zero()); + } + + /* + * Fall back to 64-bit version for now, if the 128-bit alternative isn't + * at all defined. + * Note, some CSRs don't need to extend to MXLEN (64 upper bits non + * significant), for those, this fallback is correctly handling the + * accesses + */ + target_ulong old_value; + ret = riscv_csrrw_do64(env, csrno, &old_value, + (target_ulong)0, + (target_ulong)0); + if (ret == RISCV_EXCP_NONE && ret_value) { + *ret_value = int128_make64(old_value); + } + return ret; +} + RISCVException riscv_csrrw_i128(CPURISCVState *env, int csrno, Int128 *ret_value, Int128 new_value, Int128 write_mask) { RISCVException ret; - ret = riscv_csrrw_check(env, csrno, int128_nz(write_mask)); + ret = riscv_csrrw_check(env, csrno, true); if (ret != RISCV_EXCP_NONE) { return ret; } @@ -4830,7 +4873,11 @@ RISCVException riscv_csrrw_debug(CPURISCVState *env, int csrno, #if !defined(CONFIG_USER_ONLY) env->debugger = true; #endif - ret = riscv_csrrw(env, csrno, ret_value, new_value, write_mask); + if (!write_mask) { + ret = riscv_csrr(env, csrno, ret_value); + } else { + ret = riscv_csrrw(env, csrno, ret_value, new_value, write_mask); + } #if !defined(CONFIG_USER_ONLY) env->debugger = false; #endif diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c index ec1408ba0f..25a5263573 100644 --- a/target/riscv/op_helper.c +++ b/target/riscv/op_helper.c @@ -51,7 +51,7 @@ target_ulong helper_csrr(CPURISCVState *env, int csr) } target_ulong val = 0; - RISCVException ret = riscv_csrrw(env, csr, &val, 0, 0); + RISCVException ret = riscv_csrr(env, csr, &val); if (ret != RISCV_EXCP_NONE) { riscv_raise_exception(env, ret, GETPC()); @@ -84,9 +84,7 @@ target_ulong helper_csrrw(CPURISCVState *env, int csr, target_ulong helper_csrr_i128(CPURISCVState *env, int csr) { Int128 rv = int128_zero(); - RISCVException ret = riscv_csrrw_i128(env, csr, &rv, - int128_zero(), - int128_zero()); + RISCVException ret = riscv_csrr_i128(env, csr, &rv); if (ret != RISCV_EXCP_NONE) { riscv_raise_exception(env, ret, GETPC()); From 38facfa84328e4ee5a80f7082a01e10c768ee50a Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Mon, 15 Jul 2024 06:04:55 -0300 Subject: [PATCH 29/30] hw/riscv/virt.c: re-insert and deprecate 'riscv,delegate' Commit b1f1e9dcfa renamed 'riscv,delegate' to 'riscv,delegation' since it is the correct name as per dt-bindings, and the absence of the correct name will result in validation fails when dumping the dtb and using dt-validate. But this change has a side-effect: every other firmware available that is AIA capable is using 'riscv,delegate', and it will fault/misbehave if this property isn't present. The property was added back in QEMU 7.0, meaning we have 2 years of firmware development using the wrong property. Re-introducing 'riscv,delegate' while keeping 'riscv,delegation' allows older firmwares to keep booting with the 'virt' machine. 'riscv,delegate' is then marked for future deprecation with its use being discouraged from now on. Cc: Conor Dooley Cc: Anup Patel Fixes: b1f1e9dcfa ("hw/riscv/virt.c: aplic DT: rename prop to 'riscv, delegation'") Signed-off-by: Daniel Henrique Barboza Reviewed-by: Alistair Francis Message-ID: <20240715090455.145888-1-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis --- docs/about/deprecated.rst | 11 +++++++++++ hw/riscv/virt.c | 9 +++++++++ 2 files changed, 20 insertions(+) diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst index 20b7a17cf0..88f0f03786 100644 --- a/docs/about/deprecated.rst +++ b/docs/about/deprecated.rst @@ -479,6 +479,17 @@ versions, aliases will point to newer CPU model versions depending on the machine type, so management software must resolve CPU model aliases before starting a virtual machine. +RISC-V "virt" board "riscv,delegate" DT property (since 9.1) +'''''''''''''''''''''''''''''''''''''''''''''''''''''''''''' + +The "riscv,delegate" DT property was added in QEMU 7.0 as part of +the AIA APLIC support. The property changed name during the review +process in Linux and the correct name ended up being +"riscv,delegation". Changing the DT property name will break all +available firmwares that are using the current (wrong) name. The +property is kept as is in 9.1, together with "riscv,delegation", to +give more time for firmware developers to change their code. + Migration --------- diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c index bc0893e087..9981e0f6c9 100644 --- a/hw/riscv/virt.c +++ b/hw/riscv/virt.c @@ -651,6 +651,15 @@ static void create_fdt_one_aplic(RISCVVirtState *s, int socket, qemu_fdt_setprop_cells(ms->fdt, aplic_name, "riscv,delegation", aplic_child_phandle, 0x1, VIRT_IRQCHIP_NUM_SOURCES); + /* + * DEPRECATED_9.1: Compat property kept temporarily + * to allow old firmwares to work with AIA. Do *not* + * use 'riscv,delegate' in new code: use + * 'riscv,delegation' instead. + */ + qemu_fdt_setprop_cells(ms->fdt, aplic_name, "riscv,delegate", + aplic_child_phandle, 0x1, + VIRT_IRQCHIP_NUM_SOURCES); } riscv_socket_fdt_write_id(ms, aplic_name, socket); From daff9f7f7a457f78ce455e6abf19c2a37dfe7630 Mon Sep 17 00:00:00 2001 From: Daniel Henrique Barboza Date: Mon, 15 Jul 2024 14:15:21 -0300 Subject: [PATCH 30/30] roms/opensbi: Update to v1.5 Update OpenSBI and the pre-built opensbi32 and opensbi64 images to v1.5. The following commits were included in v1.5: 455de67 include: Bump-up version to 1.5 23b7bad lib: sbi: check incoming dbtr shmem address 0e45b63 docs: Fix wrong filename caae2f7 lib: sbi: fwft: return SBI_EINVAL rather than SBI_ERR_INVALID_PARAM e8717d1 lib: sbi: fwft: check feature value to be exactly 1 or 0 ecef14d lib: sbi: implement SBI FWFT extension e9ee967 lib: sbi: fwft: add support for SBI_FWFT_PTE_AD_HW_UPDATING c97a1d5 lib: sbi: fwft: add support for SBI_FWFT_MISALIGNED_EXC_DELEG aa5a859 lib: sbi: add support for firmware features extension 53844c9 lib: sbi: Add support for Svade and Svadu extensions 52dcf35 platform: generic: andes: Add support for RV32 to set up PMA f09f164 platform: generic: andes: Refine Andes PMA related code 7830e98 lib: serial: fix RX path in litex-uart 62e178a lib: utils/reset: Try initializing all reset devices in dt 3a94a32 sbi: sbi_domain_context: Fix trap context for domain context switching a73ff04 lib: utils/reset: Fix fdt_reset to search for more dt nodes b5c984b lib: utils/reset: Skip initialize reset when dt is not enabled 86bbe6c lib: utils/serial: Fix fdt_serial to match more dt nodes 179e00a lib: utils/serial: Skip initialize serial when dt is not enabled b1c7c75 lib: utils/irqchip: Skip initialize irqchip when dt is not enabled 5e3ad7d lib: utils/timer: Skip initialize timer when dt is not enabled c5be0e1 lib: utils/ipi: Skip initialize ipi when dt is not enabled df3db6a lib: utils/fdt: Fix DT property for APLIC delegation d962db2 lib: utils/gpio: respect flag GPIO_FLAG_ACTIVE_LOW ae5ef18 lib: sbi: sse: handle missing writable attributes 858754a lib: utils/irqchip: Add sanity checks in imsic_get_data() and imsic_get_target_file() 96f0a2e firmware: Bring back FW_TEXT_START as an optional parameter e3a30a2 lib: utils/irqchip: Check before initializing imsic 2bed4c1 platform: generic: thead: add Sophgo CV18XX/SG200X series 533067d lib: sbi: Put event after use in sbi_sse_exit() loop ea9cf6a utils/reset: Add SG2042 hwmon MCU support. 1cb792d lib: sbi: simplify inline function in sbi_dtbr.c 7b37da3 lib: sbi: fix return type of sbi_dbtr_shmem_disabled e065c3c lib: sbi: Fixed memory permission check in sbi_dbtr_setup_shmem 7f54527 lib: sbi: fix DBTR_SHMEM_MAKE_PHYS for RV64 744f495 lib: sbi: Removal unnecessary check dbtr_thishart_state_ptr 4953bd7 lib: sbi: fix hart_shmem_base 019a8e6 platform: generic: thead: add Canaan Kendryte K230 33e21c9 platform: generic: thead: separate T-Head PMU Errata 2b93ce0 platform: andes: Change all occurrences of andes45 to andes f68b3ae platform: andes: Rename files with the prefix andes45 17e8291 sbi: sbi_domain_context: Add spinlock for updating domain assigned_harts 1d89a9d lib: sbi: Refine the settings for switching to Virtual Supervisor Mode. 033104d lib: sbi: sse: check handler entry to belong to supervisor mode bd00765 lib: sbi: sse: use PRV_S instead of hardcoded value for mode ce3c82c lib: sbi: sse: call enable callback before sending IPI d528dbf lib: sbi: sse: remove superfluous sbi_list_empty() check 22ff750 lib: sbi: sse: simplify 32bits overflow check 7aa80ea lib: sbi: sse: rename sse_hart_unlock() to sse_enabled_event_unlock() c21c99d lib: sbi: sse: fix typos, comments and spacing errors 7b1ed96 lib: tests: Add test for spinlocks 7bdf41a lib: tests: Add test for atomic_t f6243d9 lib: tests: Add test suite init function d4d2582 firmware: remove FW_TEXT_START 73344d4 lib: utils: check correct value in fdt_node_offset_by_compatible 37e1544 lib: sbi: sse_event_get() may return NULL 68bc031 lib: sbi: Add missing sscrind and sscfg extensions in sbi_hart_ext[] a7c5c2c Makefile: Remove unnecessary dependencies 268feab Makefile: Respect manual changes to .config 29ecda9 sbi: sbi_domain_context: Check privilege spec version before accessing S-mode CSRs 7862c24 lib: sbi: Wakeup non-coldboot HARTs early in the coldboot path beb0cd1 lib: sbi: Simplify wait_for_coldboot() implementation f5375bc platform: generic: allwinner: Optimize current hart scratch access b94396c lib: utils/timer: Optimize current hart scratch access 5c9a735 include: sbi: Support byteorder macros in assembly 06fc453 lib: sbi: Add SSE support for PMU events 09ad214 lib: sbi: Implement SBI SSE extension c8cdf01 lib: sbi: Add support for Supervisor Software Events extension 76d7e9b firmware: remove copy-base relocation 5186da6 platform: generic: allwinner: sun20i-d1: Remove duplicated CSR definitions 3b2f89e docs: writing_tests: Make docs correspond the latest changes f7d0050 lib: sbi: Extend sbi_trap_error() to dump state in a nested trap 5b11f16 lib: sbi: Pass trap context pointer to sbi_ecall_handler() 43d346c lib: sbi: Remove regs parameter from trap irq handling functions d84e7eb lib: sbi: Remove regs paramter of sbi_irqchip_process() f414cf9 lib: sbi: Simplify parameters of sbi_illegal_insn_handler() fea33a9 lib: sbi: Simplify parameters of misaligned and access fault handlers abea949 lib: sbi: Introduce trap context 60ffc15 include: sbi: Add trap_context pointer in struct sbi_scratch ebb697a lib: sbi: Remove sbi_trap_exit() and related code 2e85178 lib: sbi: Remove epc from struct sbi_trap_info 86224ec docs/writing_tests: Update tests paths 5c992a1 lib: tests: Move tests to a separate directory 81e3ba7 lib: sbi: call platform load/store emulators ddf3b64 include: sbi: add emulate_load/store handler to platform ops 4c11265 lib: sbi: abstract out insn decoding to unify mem fault handlers 9221fe5 lib: sbi: change prototype of sbi_misaligned_load/store_handler a17600c lib: sbi: change prototype of sbi_trap_redirect 2471cf2 include: sbi: rename sbi_misaligned_ldst.h to sbi_trap_ldst.h c0a6320 lib: sbi: rename sbi_misaligned_ldst.c to sbi_trap_ldst.c e11025c lib: sbi: Add initial domain context management support 87d8fe7 lib: tests: Add sbi_console test e5f53fd lib: tests: Add a test for sbi_bitmap 874fcef lib: Add SBIUnit testing macros and functions b9e4de0 docs: Add documentation about tests and SBIUnit 526b9ce firmware: fw_base.S: fix _reset_regs 8151105 firmware: fw_base.S: Remove _relocate_lottery 187397f firmware: fw_dynamic.S: Remove _bad_dynamic_info b27b7c6 firmware: fw_base: Simplified setup trap handler fdf5589 firmware: fw_base.S: Simplify address get 748bef1 lib: sbi_misaligned_ldst: Add handling of C.LHU/C.LH and C.SH bc36678 platform: andes: Drop andes_pmu_setup() 6bb6b61 lib: sbi: Add support for smcsrind and smcdeleg 322b598 lib: sbi_hsm: Restor hart state to stop when fails to start 96a35db docs/firmware: document new options for jump and payload firmwares 2cff7f3 platform: Apply relocatable address f056939 firmware: Add relocatable FW_PAYLOAD_FDT_ADDR 7227cdd firmware: Add relocatable FW_JUMP_ADDR and FW_JUMP_FDT_ADDR 741e941 platform: starfive: call starfive_jh7110_inst_init() in pm_reset_init() 3edf044 platform: starfive: return error if needed devices are not present 80ae046 platform: starfive: rename "stf,axp15060-regulator" -> "x-powers,axp15060" 5335340 platform: starfive: remove redundant compatibility check in pmic_ops 4d8569d platform: starfive: get I2C offset address from clocks property 034af1f platform: starfive: correct system clock device tree node 88273fe lib: sbi_pmu: Before using we should ensure PMU init done 46c8c65 docs: move documentation of system suspend test. 8df836d platform: generic: Parse system suspend test from config node. 23e7e48 docs: Add OpenSBI DT configuration guide. 67ce5a7 platform: generic: Add support for specify coldboot harts in DT 9c8b18e firmware: fw_base.S: remove _runtime_offset 4c6b7cb firmware: fw_base.S: Improve loading u32 92e8aff firmware: always create dynsym section d1dad07 Makefile: check for --exclude-libs 4a76f79 Makefile: don't pass -mstrict-align if not supported 21caaa3 fw_base.S: Fix comment errors 1ec353d lib: sbi: Use mask to check the free bit during trigger allocation bb90a9e lib: sbi: Print number of debug triggers found 76a2a15 lib: sbi: Implement SBI debug trigger extension fa87ec9 include: sbi: Add SBI debug trigger extension related defines 97f234f lib: sbi: Introduce the SBI debug triggers extension support 40dac6b lib: sbi: Detect support of debug triggers 2499769 include: sbi: Introduce debug trigger register encodings 20ca19a include: sbi: Add TINFO debug trigger CSR b752099 include: sbi: Introduce common endianess conversion macro Signed-off-by: Daniel Henrique Barboza Reviewed-by: Alistair Francis Message-ID: <20240715171521.179517-1-dbarboza@ventanamicro.com> Signed-off-by: Alistair Francis --- .../opensbi-riscv32-generic-fw_dynamic.bin | Bin 267416 -> 268312 bytes .../opensbi-riscv64-generic-fw_dynamic.bin | Bin 270808 -> 272504 bytes roms/opensbi | 2 +- 3 files changed, 1 insertion(+), 1 deletion(-) diff --git a/pc-bios/opensbi-riscv32-generic-fw_dynamic.bin b/pc-bios/opensbi-riscv32-generic-fw_dynamic.bin index 60ca1165c820ff29b984566db22b9453541da19a..7ec260ff4047d11f7683c9a0b2fed73e1996cd75 100644 GIT binary patch delta 73365 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 T^0XH72Qd~9qj7qT2#X8=xC2V4 delta 62279 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�k$OLTw~t^tcNg2Y1i6iZZq)GY&vH86n0rfw;g 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 diff --git a/pc-bios/opensbi-riscv64-generic-fw_dynamic.bin b/pc-bios/opensbi-riscv64-generic-fw_dynamic.bin index bae158d4577341eb3d752ca13cc66149961f8cb4..090c0cf6ac988f811b220c45565eca027fc21d50 100644 GIT binary patch delta 73168 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�|G)nK|NqlpY-e#;`?|)SJ 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 Lg=6{wMHUGF>>Jsl delta 59449 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 diff --git a/roms/opensbi b/roms/opensbi index a2b255b889..455de672dd 160000 --- a/roms/opensbi +++ b/roms/opensbi @@ -1 +1 @@ -Subproject commit a2b255b88918715173942f2c5e1f97ac9e90c877 +Subproject commit 455de672dd7c2aa1992df54dfb08dc11abbc1b1a