Re: [PATCH v2] riscv: thead: Add th.sxstatus CSR emulation
riscv_set_csr_ops(csrno, csr_ops); +} +} Otherwise, Reviewed-by: LIU Zhiwei Zhiwei
Re: [PATCH v2] target/riscv: Fix the element agnostic function problem
On 2024/3/21 11:58, Huang Tao wrote: In RVV and vcrypto instructions, the masked and tail elements are set to 1s using vext_set_elems_1s function if the vma/vta bit is set. It is the element agnostic policy. However, this function can't deal the big endian situation. This patch fixes the problem by adding handling of such case. Signed-off-by: Huang Tao Suggested-by: Richard Henderson --- Changes in v2: - Keep the api of vext_set_elems_1s - Reduce the number of patches. --- target/riscv/vector_internals.c | 22 ++ 1 file changed, 22 insertions(+) diff --git a/target/riscv/vector_internals.c b/target/riscv/vector_internals.c index 12f5964fbb..3e45b9b4a7 100644 --- a/target/riscv/vector_internals.c +++ b/target/riscv/vector_internals.c @@ -30,6 +30,28 @@ void vext_set_elems_1s(void *base, uint32_t is_agnostic, uint32_t cnt, if (tot - cnt == 0) { return ; } + +#if HOST_BIG_ENDIAN +/* + * Deal the situation when the elements are insdie + * only one uint64 block including setting the + * masked-off element. + */ +if ((tot - 1) ^ cnt < 8) { +memset(base + H1(tot - 1), -1, tot - cnt); +return; +} +/* + * Otherwise, at least cross two uint64_t blocks. + * Set first unaligned block. + */ +if (cnt % 8 != 0) { +uint32_t j = ROUND_UP(cnt, 8); +memset(base + H1(j - 1), -1, j - cnt); +cnt = j; +} +/* Set other 64bit aligend blocks */ +#endif Reviewed-by: LIU Zhiwei Zhiwei memset(base + cnt, -1, tot - cnt); }
Re: [PATCH for 9.0 v15 04/10] target/riscv: always clear vstart in whole vec move insns
On 2024/3/15 1:56, Daniel Henrique Barboza wrote: These insns have 2 paths: we'll either have vstart already cleared if vstart_eq_zero or we'll do a brcond to check if vstart >= maxsz to call the 'vmvr_v' helper. The helper will clear vstart if it executes until the end, or if vstart >= vl. For starters, the check itself is wrong: we're checking vstart >= maxsz, when in fact we should use vstart in bytes, or 'startb' like 'vmvr_v' is calling, to do the comparison. But even after fixing the comparison we'll still need to clear vstart in the end, which isn't happening too. We want to make the helpers responsible to manage vstart, including these corner cases, precisely to avoid these situations: - remove the wrong vstart >= maxsz cond from the translation; - add a 'startb >= maxsz' cond in 'vmvr_v', and clear vstart if that happens. This way we're now sure that vstart is being cleared in the end of the execution, regardless of the path taken. Fixes: f714361ed7 ("target/riscv: rvv-1.0: implement vstart CSR") Signed-off-by: Daniel Henrique Barboza Reviewed-by: LIU Zhiwei Zhiwei --- target/riscv/insn_trans/trans_rvv.c.inc | 3 --- target/riscv/vector_helper.c| 5 + 2 files changed, 5 insertions(+), 3 deletions(-) diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc index 8c16a9f5b3..52c26a7834 100644 --- a/target/riscv/insn_trans/trans_rvv.c.inc +++ b/target/riscv/insn_trans/trans_rvv.c.inc @@ -3664,12 +3664,9 @@ static bool trans_##NAME(DisasContext *s, arg_##NAME * a) \ vreg_ofs(s, a->rs2), maxsz, maxsz);\ mark_vs_dirty(s); \ } else {\ -TCGLabel *over = gen_new_label(); \ -tcg_gen_brcondi_tl(TCG_COND_GEU, cpu_vstart, maxsz, over); \ tcg_gen_gvec_2_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, a->rs2), \ tcg_env, maxsz, maxsz, 0, gen_helper_vmvr_v); \ mark_vs_dirty(s); \ -gen_set_label(over);\ } \ return true;\ } \ diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c index 34ac4aa808..bcc553c0e2 100644 --- a/target/riscv/vector_helper.c +++ b/target/riscv/vector_helper.c @@ -5075,6 +5075,11 @@ void HELPER(vmvr_v)(void *vd, void *vs2, CPURISCVState *env, uint32_t desc) uint32_t startb = env->vstart * sewb; uint32_t i = startb; +if (startb >= maxsz) { +env->vstart = 0; +return; +} + if (HOST_BIG_ENDIAN && i % 8 != 0) { uint32_t j = ROUND_UP(i, 8); memcpy((uint8_t *)vd + H1(j - 1),
Re: [PATCH for 9.0 v15 03/10] target/riscv/vector_helper.c: fix 'vmvr_v' memcpy endianess
On 2024/3/15 1:56, Daniel Henrique Barboza wrote: vmvr_v isn't handling the case where the host might be big endian and the bytes to be copied aren't sequential. Suggested-by: Richard Henderson Fixes: f714361ed7 ("target/riscv: rvv-1.0: implement vstart CSR") Signed-off-by: Daniel Henrique Barboza --- target/riscv/vector_helper.c | 10 +- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c index ca79571ae2..34ac4aa808 100644 --- a/target/riscv/vector_helper.c +++ b/target/riscv/vector_helper.c @@ -5075,9 +5075,17 @@ void HELPER(vmvr_v)(void *vd, void *vs2, CPURISCVState *env, uint32_t desc) uint32_t startb = env->vstart * sewb; uint32_t i = startb; +if (HOST_BIG_ENDIAN && i % 8 != 0) { +uint32_t j = ROUND_UP(i, 8); +memcpy((uint8_t *)vd + H1(j - 1), + (uint8_t *)vs2 + H1(j - 1), + j - i); +i = j; +} + memcpy((uint8_t *)vd + H1(i), (uint8_t *)vs2 + H1(i), - maxsz - startb); + maxsz - i); Reviewed-by: LIU Zhiwei Zhiwei env->vstart = 0; }
Re: [PATCH for 9.0 v15 02/10] trans_rvv.c.inc: set vstart = 0 in int scalar move insns
On 2024/3/15 1:56, Daniel Henrique Barboza wrote: trans_vmv_x_s, trans_vmv_s_x, trans_vfmv_f_s and trans_vfmv_s_f aren't setting vstart = 0 after execution. This is usually done by a helper in vector_helper.c but these functions don't use helpers. We'll set vstart after any potential 'over' brconds, and that will also mandate a mark_vs_dirty() too. Fixes: dedc53cbc9 ("target/riscv: rvv-1.0: integer scalar move instructions") Signed-off-by: Daniel Henrique Barboza Reviewed-by: Richard Henderson Reviewd-by: LIU Zhiwei Zhiwei --- target/riscv/insn_trans/trans_rvv.c.inc | 10 -- 1 file changed, 8 insertions(+), 2 deletions(-) diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc index e42728990e..8c16a9f5b3 100644 --- a/target/riscv/insn_trans/trans_rvv.c.inc +++ b/target/riscv/insn_trans/trans_rvv.c.inc @@ -3373,6 +3373,8 @@ static bool trans_vmv_x_s(DisasContext *s, arg_vmv_x_s *a) vec_element_loadi(s, t1, a->rs2, 0, true); tcg_gen_trunc_i64_tl(dest, t1); gen_set_gpr(s, a->rd, dest); +tcg_gen_movi_tl(cpu_vstart, 0); +mark_vs_dirty(s); return true; } return false; @@ -3399,8 +3401,9 @@ static bool trans_vmv_s_x(DisasContext *s, arg_vmv_s_x *a) s1 = get_gpr(s, a->rs1, EXT_NONE); tcg_gen_ext_tl_i64(t1, s1); vec_element_storei(s, a->rd, 0, t1); -mark_vs_dirty(s); gen_set_label(over); +tcg_gen_movi_tl(cpu_vstart, 0); +mark_vs_dirty(s); return true; } return false; @@ -3427,6 +3430,8 @@ static bool trans_vfmv_f_s(DisasContext *s, arg_vfmv_f_s *a) } mark_fs_dirty(s); +tcg_gen_movi_tl(cpu_vstart, 0); +mark_vs_dirty(s); return true; } return false; @@ -3452,8 +3457,9 @@ static bool trans_vfmv_s_f(DisasContext *s, arg_vfmv_s_f *a) do_nanbox(s, t1, cpu_fpr[a->rs1]); vec_element_storei(s, a->rd, 0, t1); -mark_vs_dirty(s); gen_set_label(over); +tcg_gen_movi_tl(cpu_vstart, 0); +mark_vs_dirty(s); return true; } return false;
Re: [PATCH for 9.0 v15 01/10] target/riscv/vector_helper.c: set vstart = 0 in GEN_VEXT_VSLIDEUP_VX()
On 2024/3/15 1:56, Daniel Henrique Barboza wrote: The helper isn't setting env->vstart = 0 after its execution, as it is expected from every vector instruction that completes successfully. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Richard Henderson Reviewed-by: Alistair Francis Reviewed-by: LIU Zhiwei Zhiwei --- target/riscv/vector_helper.c | 1 + 1 file changed, 1 insertion(+) diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c index fe56c007d5..ca79571ae2 100644 --- a/target/riscv/vector_helper.c +++ b/target/riscv/vector_helper.c @@ -4781,6 +4781,7 @@ void HELPER(NAME)(void *vd, void *v0, target_ulong s1, void *vs2, \ } \ *((ETYPE *)vd + H(i)) = *((ETYPE *)vs2 + H(i - offset)); \ } \ +env->vstart = 0; \ /* set tail elements to 1s */ \ vext_set_elems_1s(vd, vta, vl * esz, total_elems * esz); \ }
Re: [PATCH v2] target/riscv: raise an exception when CSRRS/CSRRC writes a read-only CSR
On 2024/3/11 11:08, Yu-Ming Chang wrote: 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 --- This incorporated the comments from Richard. Thank you. target/riscv/cpu.h | 2 ++ target/riscv/csr.c | 17 ++--- target/riscv/op_helper.c | 2 +- 3 files changed, 17 insertions(+), 4 deletions(-) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 5d291a7092..452841ae2f 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -710,6 +710,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); diff --git a/target/riscv/csr.c b/target/riscv/csr.c index d4e8ac13b9..0d14ba2ba5 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -4306,7 +4306,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; @@ -4328,7 +4328,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; } @@ -4415,11 +4415,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; } diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c index f414aaebdb..f3aa705be8 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, , 0, 0); +RISCVException ret = riscv_csrr(env, csr, ); if (ret != RISCV_EXCP_NONE) { riscv_raise_exception(env, ret, GETPC()); Hi Yu-Ming, The 128-bit CSR operations have the similar errors. Could you solve the similar bug in this patch set? Otherwise, Reviewed-by: LIU Zhiwei Thanks, Zhiwei
Re: [PATCH v12 4/7] target/riscv: remove 'over' brconds from vector trans
On 2024/3/12 2:08, Daniel Henrique Barboza wrote: The previous patch added an early vstart >= vl exit in all vector helpers, most of them using the VSTART_CHECK_EARLY_EXIT() macro, and now we're left with a lot of 'brcond' that has not use. The pattern goes like this: VSTART_CHECK_EARLY_EXIT(env); (...) tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over); (...) gen_set_label(over); return true; The early exit makes the 'brcond' unneeded since it's already granted that vstart < vl. Remove all 'over' conditionals from the vector helpers. Note that not all insns uses helpers, and for those cases the 'brcond' jump is the only way to filter vstart >= vl. This is the case of trans_vmv_s_x() and trans_vfmv_s_f(). We won't remove the 'brcond' conditionals from them. While we're at it, remove the (vl == 0) brconds from trans_rvbf16.c.inc too since they're unneeded. Suggested-by: Richard Henderson Signed-off-by: Daniel Henrique Barboza Reviewed-by: Richard Henderson Reviewed-by: Alistair Francis --- target/riscv/insn_trans/trans_rvbf16.c.inc | 12 --- target/riscv/insn_trans/trans_rvv.c.inc| 108 - target/riscv/insn_trans/trans_rvvk.c.inc | 18 3 files changed, 138 deletions(-) diff --git a/target/riscv/insn_trans/trans_rvbf16.c.inc b/target/riscv/insn_trans/trans_rvbf16.c.inc index 8ee99df3f3..a842e76a6b 100644 --- a/target/riscv/insn_trans/trans_rvbf16.c.inc +++ b/target/riscv/insn_trans/trans_rvbf16.c.inc @@ -71,11 +71,8 @@ static bool trans_vfncvtbf16_f_f_w(DisasContext *ctx, arg_vfncvtbf16_f_f_w *a) if (opfv_narrow_check(ctx, a) && (ctx->sew == MO_16)) { uint32_t data = 0; -TCGLabel *over = gen_new_label(); gen_set_rm_chkfrm(ctx, RISCV_FRM_DYN); -tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); -tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over); data = FIELD_DP32(data, VDATA, VM, a->vm); data = FIELD_DP32(data, VDATA, LMUL, ctx->lmul); @@ -87,7 +84,6 @@ static bool trans_vfncvtbf16_f_f_w(DisasContext *ctx, arg_vfncvtbf16_f_f_w *a) ctx->cfg_ptr->vlenb, data, gen_helper_vfncvtbf16_f_f_w); mark_vs_dirty(ctx); -gen_set_label(over); return true; } return false; @@ -100,11 +96,8 @@ static bool trans_vfwcvtbf16_f_f_v(DisasContext *ctx, arg_vfwcvtbf16_f_f_v *a) if (opfv_widen_check(ctx, a) && (ctx->sew == MO_16)) { uint32_t data = 0; -TCGLabel *over = gen_new_label(); gen_set_rm_chkfrm(ctx, RISCV_FRM_DYN); -tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); -tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over); data = FIELD_DP32(data, VDATA, VM, a->vm); data = FIELD_DP32(data, VDATA, LMUL, ctx->lmul); @@ -116,7 +109,6 @@ static bool trans_vfwcvtbf16_f_f_v(DisasContext *ctx, arg_vfwcvtbf16_f_f_v *a) ctx->cfg_ptr->vlenb, data, gen_helper_vfwcvtbf16_f_f_v); mark_vs_dirty(ctx); -gen_set_label(over); return true; } return false; @@ -130,11 +122,8 @@ static bool trans_vfwmaccbf16_vv(DisasContext *ctx, arg_vfwmaccbf16_vv *a) if (require_rvv(ctx) && vext_check_isa_ill(ctx) && (ctx->sew == MO_16) && vext_check_dss(ctx, a->rd, a->rs1, a->rs2, a->vm)) { uint32_t data = 0; -TCGLabel *over = gen_new_label(); gen_set_rm_chkfrm(ctx, RISCV_FRM_DYN); -tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); -tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over); data = FIELD_DP32(data, VDATA, VM, a->vm); data = FIELD_DP32(data, VDATA, LMUL, ctx->lmul); @@ -147,7 +136,6 @@ static bool trans_vfwmaccbf16_vv(DisasContext *ctx, arg_vfwmaccbf16_vv *a) ctx->cfg_ptr->vlenb, data, gen_helper_vfwmaccbf16_vv); mark_vs_dirty(ctx); -gen_set_label(over); return true; } return false; diff --git a/target/riscv/insn_trans/trans_rvv.c.inc b/target/riscv/insn_trans/trans_rvv.c.inc index 8c16a9f5b3..4c1a064cf6 100644 --- a/target/riscv/insn_trans/trans_rvv.c.inc +++ b/target/riscv/insn_trans/trans_rvv.c.inc @@ -616,9 +616,6 @@ static bool ldst_us_trans(uint32_t vd, uint32_t rs1, uint32_t data, TCGv base; TCGv_i32 desc; -TCGLabel *over = gen_new_label(); -tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over); - dest = tcg_temp_new_ptr(); mask = tcg_temp_new_ptr(); base = get_gpr(s, rs1, EXT_NONE); @@ -660,7 +657,6 @@ static bool ldst_us_trans(uint32_t vd, uint32_t rs1, uint32_t data, tcg_gen_mb(TCG_MO_ALL | TCG_BAR_LDAQ); } -gen_set_label(over); return true; } @@ -802,9 +798,6 @@ static bool ldst_stride_trans(uint32_t vd, uint32_t
Re: [PATCH v9 04/10] target/riscv/vector_helper.c: update tail with vext_set_tail_elems_1s()
On 2024/3/10 4:43, Daniel Henrique Barboza wrote: Change all code that updates tail elems to use vext_set_tail_elems_1s() instead of vext_set_elems_1s(). Hi Daniel, Notice vext_set_tail_elems_1s will use NF field, which is zero for most vector instructions. Thus it will do nothing. I think you need encode the right NF value(1) into desc for them if you want to do this replacement. Thanks, Zhiwei Setting 'env->vstart=0' needs to be the very last thing a helper does because env->vstart is being checked by vext_set_tail_elems_1s(). A side effect of this change is that a lot of 'vta' local variables got unused. The reason is that 'vta' was being fetched to be used with vext_set_elems_1s() but vext_set_tail_elems_1s() doesn't use it - 'vta' is retrieve inside the helper using 'desc'. Signed-off-by: Daniel Henrique Barboza --- target/riscv/vector_helper.c | 130 ++- 1 file changed, 52 insertions(+), 78 deletions(-) diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c index 86b990ce03..b174ddeae8 100644 --- a/target/riscv/vector_helper.c +++ b/target/riscv/vector_helper.c @@ -913,7 +913,6 @@ void HELPER(NAME)(void *vd, void *v0, void *vs1, void *vs2, \ uint32_t esz = sizeof(ETYPE); \ uint32_t total_elems =\ vext_get_total_elems(env, desc, esz); \ -uint32_t vta = vext_vta(desc);\ uint32_t i; \ \ for (i = env->vstart; i < vl; i++) { \ @@ -923,9 +922,9 @@ void HELPER(NAME)(void *vd, void *v0, void *vs1, void *vs2, \ \ *((ETYPE *)vd + H(i)) = DO_OP(s2, s1, carry); \ } \ -env->vstart = 0; \ /* set tail elements to 1s */ \ -vext_set_elems_1s(vd, vta, vl * esz, total_elems * esz); \ +vext_set_tail_elems_1s(env, vd, desc, esz, total_elems); \ +env->vstart = 0; \ } GEN_VEXT_VADC_VVM(vadc_vvm_b, uint8_t, H1, DO_VADC) @@ -945,7 +944,6 @@ void HELPER(NAME)(void *vd, void *v0, target_ulong s1, void *vs2,\ uint32_t vl = env->vl; \ uint32_t esz = sizeof(ETYPE);\ uint32_t total_elems = vext_get_total_elems(env, desc, esz); \ -uint32_t vta = vext_vta(desc); \ uint32_t i; \ \ for (i = env->vstart; i < vl; i++) { \ @@ -954,9 +952,9 @@ void HELPER(NAME)(void *vd, void *v0, target_ulong s1, void *vs2,\ \ *((ETYPE *)vd + H(i)) = DO_OP(s2, (ETYPE)(target_long)s1, carry);\ }\ -env->vstart = 0; \ /* set tail elements to 1s */\ -vext_set_elems_1s(vd, vta, vl * esz, total_elems * esz); \ +vext_set_tail_elems_1s(env, vd, desc, esz, total_elems); \ +env->vstart = 0; \ } GEN_VEXT_VADC_VXM(vadc_vxm_b, uint8_t, H1, DO_VADC) @@ -1113,7 +,6 @@ void HELPER(NAME)(void *vd, void *v0, void *vs1, \ uint32_t vl = env->vl;\ uint32_t esz = sizeof(TS1); \ uint32_t total_elems = vext_get_total_elems(env, desc, esz); \ -uint32_t vta = vext_vta(desc);\ uint32_t vma = vext_vma(desc);\ uint32_t i; \ \ @@ -1127,9 +1124,9 @@ void HELPER(NAME)(void *vd, void *v0, void *vs1, \ TS2 s2 = *((TS2 *)vs2 + HS2(i)); \ *((TS1 *)vd + HS1(i)) = OP(s2, s1 & MASK);\ } \ -env->vstart = 0; \ /* set tail elements to 1s */ \ -vext_set_elems_1s(vd, vta, vl * esz, total_elems * esz); \ +
Re: [PATCH v7 3/9] target/riscv: remove 'over' brconds from vector trans
Hi Daniel and Alistair, Hope it is not too late. I think there are two bugs in this patch. 1) The first is for instruction vfmv.s.f. vfmv.s.f doesn't use helper function. If we remove the over check, it will set the first element of destination vector register, which is against the specification. According to the riscv-v-specification, 16.2. Floating-Point Scalar Move Instructions, "If vstart ≥ vl, no operation is performed and the destination register is not updated". 2) The second is for vector instruction with helper functions. we should not change any elements including the tail elements when vstart >=vl. But this patch break this behavior. According to the riscv-v-specification, 5.4. Prestart, Active, Inactive, Body, and Tail Element Denitions, "When vstart ≥ vl, there are no body elements, and no elements are updated in any destination vector register group, including that no tail elements are updated with agnostic values." I will review this patch set in more details later. Thanks, Zhiwei On 2024/3/7 1:19, Daniel Henrique Barboza wrote: Most of the vector translations has this following pattern at the start: TCGLabel *over = gen_new_label(); tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over); And then right at the end: gen_set_label(over); return true; This means that if vstart >= vl we'll not set vstart = 0 at the end of the insns - this is done inside the helper that is being skipped. The reason why this pattern hasn't been a bigger problem is because the conditional vstart >= vl is very rare. Checking all the helpers in vector_helper.c we see all of them with a pattern like this: for (i = env->vstart; i < vl; i++) { (...) } env->vstart = 0; Thus they can handle vstart >= vl case gracefully, with the benefit of setting env->vstart = 0 during the process. Remove all 'over' conditionals and let the helper set env->vstart = 0 every time. While we're at it, remove the (vl == 0) brconds from trans_rvbf16.c.inc too since they're unneeded. Suggested-by: Richard Henderson Signed-off-by: Daniel Henrique Barboza Reviewed-by: Richard Henderson Reviewed-by: Alistair Francis --- target/riscv/insn_trans/trans_rvbf16.c.inc | 12 --- target/riscv/insn_trans/trans_rvv.c.inc| 117 - target/riscv/insn_trans/trans_rvvk.c.inc | 18 3 files changed, 147 deletions(-) diff --git a/target/riscv/insn_trans/trans_rvbf16.c.inc b/target/riscv/insn_trans/trans_rvbf16.c.inc index 8ee99df3f3..a842e76a6b 100644 --- a/target/riscv/insn_trans/trans_rvbf16.c.inc +++ b/target/riscv/insn_trans/trans_rvbf16.c.inc @@ -71,11 +71,8 @@ static bool trans_vfncvtbf16_f_f_w(DisasContext *ctx, arg_vfncvtbf16_f_f_w *a) if (opfv_narrow_check(ctx, a) && (ctx->sew == MO_16)) { uint32_t data = 0; -TCGLabel *over = gen_new_label(); gen_set_rm_chkfrm(ctx, RISCV_FRM_DYN); -tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); -tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over); data = FIELD_DP32(data, VDATA, VM, a->vm); data = FIELD_DP32(data, VDATA, LMUL, ctx->lmul); @@ -87,7 +84,6 @@ static bool trans_vfncvtbf16_f_f_w(DisasContext *ctx, arg_vfncvtbf16_f_f_w *a) ctx->cfg_ptr->vlenb, data, gen_helper_vfncvtbf16_f_f_w); mark_vs_dirty(ctx); -gen_set_label(over); return true; } return false; @@ -100,11 +96,8 @@ static bool trans_vfwcvtbf16_f_f_v(DisasContext *ctx, arg_vfwcvtbf16_f_f_v *a) if (opfv_widen_check(ctx, a) && (ctx->sew == MO_16)) { uint32_t data = 0; -TCGLabel *over = gen_new_label(); gen_set_rm_chkfrm(ctx, RISCV_FRM_DYN); -tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); -tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over); data = FIELD_DP32(data, VDATA, VM, a->vm); data = FIELD_DP32(data, VDATA, LMUL, ctx->lmul); @@ -116,7 +109,6 @@ static bool trans_vfwcvtbf16_f_f_v(DisasContext *ctx, arg_vfwcvtbf16_f_f_v *a) ctx->cfg_ptr->vlenb, data, gen_helper_vfwcvtbf16_f_f_v); mark_vs_dirty(ctx); -gen_set_label(over); return true; } return false; @@ -130,11 +122,8 @@ static bool trans_vfwmaccbf16_vv(DisasContext *ctx, arg_vfwmaccbf16_vv *a) if (require_rvv(ctx) && vext_check_isa_ill(ctx) && (ctx->sew == MO_16) && vext_check_dss(ctx, a->rd, a->rs1, a->rs2, a->vm)) { uint32_t data = 0; -TCGLabel *over = gen_new_label(); gen_set_rm_chkfrm(ctx, RISCV_FRM_DYN); -tcg_gen_brcondi_tl(TCG_COND_EQ, cpu_vl, 0, over); -tcg_gen_brcond_tl(TCG_COND_GEU, cpu_vstart, cpu_vl, over); data = FIELD_DP32(data, VDATA, VM, a->vm); data = FIELD_DP32(data, VDATA, LMUL, ctx->lmul); @@ -147,7 +136,6
Re: [PATCH v5 1/5] target/riscv: Fix the predicate functions for mhpmeventhX CSRs
On 2024/2/29 2:51, Atish Patra wrote: 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 Reviewed-by: LIU Zhiwei Zhiwei Signed-off-by: Atish Patra --- 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 d4e8ac13b90c..a3d979c4c72c 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; @@ -5035,91 +5044,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",sscofpm
Re: [PATCH v5 2/5] target/riscv: Add cycle & instret privilege mode filtering properties
On 2024/2/29 2:51, Atish Patra wrote: From: Kaiwen Xue This adds the properties for ISA extension smcntrpmf. Patches implementing it will follow. Signed-off-by: Atish Patra Signed-off-by: Kaiwen Xue --- target/riscv/cpu.c | 2 ++ target/riscv/cpu_cfg.h | 1 + 2 files changed, 3 insertions(+) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 1b8d001d237f..f9d3c80597fc 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -169,6 +169,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), @@ -1447,6 +1448,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), We should not add the configure option for users before the feature has been implemented for bitsect reasons. Thanks, Zhiwei diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h index 833bf5821708..0828841445c5 100644 --- a/target/riscv/cpu_cfg.h +++ b/target/riscv/cpu_cfg.h @@ -73,6 +73,7 @@ struct RISCVCPUConfig { bool ext_zihpm; bool ext_smstateen; bool ext_sstc; +bool ext_smcntrpmf; bool ext_svadu; bool ext_svinval; bool ext_svnapot;
Re: [PATCH v5 5/5] target/riscv: Implement privilege mode filtering for cycle/instret
On 2024/2/29 2:51, Atish Patra wrote: 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. Reviewed-by: Daniel Henrique Barboza Signed-off-by: Atish Patra --- target/riscv/cpu.h| 11 + target/riscv/cpu_bits.h | 5 ++ target/riscv/cpu_helper.c | 17 ++- target/riscv/csr.c| 96 ++- target/riscv/pmu.c| 64 ++ target/riscv/pmu.h| 2 + 6 files changed, 171 insertions(+), 24 deletions(-) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 174e8ba8e847..9e21d7f7d635 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -157,6 +157,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 */ @@ -353,6 +362,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_bits.h b/target/riscv/cpu_bits.h index e866c60a400c..5fe349e313dc 100644 --- a/target/riscv/cpu_bits.h +++ b/target/riscv/cpu_bits.h @@ -920,6 +920,11 @@ typedef enum RISCVException { #define MHPMEVENT_BIT_VUINHBIT_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 MHPMEVENT_SSCOF_MASK _ULL(0x) #define MHPMEVENT_IDX_MASK 0xF #define MHPMEVENT_SSCOF_RESVD 16 diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index d462d95ee165..33965d843d46 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -718,8 +718,21 @@ void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv) { g_assert(newpriv <= PRV_M && newpriv != PRV_RESERVED); -if (icount_enabled() && newpriv != env->priv) { -riscv_itrigger_update_priv(env); +/* + * Invoke cycle/instret update between priv mode changes or + * VS->HS mode transition is SPV bit must be set + * HS->VS mode transition where virt_enabled must be set + * In both cases, priv will S mode only. + */ +if (newpriv != env->priv || + (env->priv == PRV_S && newpriv == PRV_S && +(env->virt_enabled || get_field(env->hstatus, HSTATUS_SPV { +if (icount_enabled()) { +riscv_itrigger_update_priv(env); +riscv_pmu_icount_update_priv(env, newpriv); +} else { +riscv_pmu_cycle_update_priv(env, newpriv); +} } /* tlb_flush is unnecessary as mode is contained in mmu_idx */ env->priv = newpriv; diff --git a/target/riscv/csr.c b/target/riscv/csr.c index ff9bac537593..482e212c5f74 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -788,32 +788,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) { -int64_t val; -target_ulong result; - -#if !defined(CONFIG_USER_ONLY) -if (icount_enabled()) { -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) { @@ -952,6 +936,71 @@ static RISCVException write_mhpmeventh(CPURISCVState *env, int csrno, return RISCV_EXCP_NONE; } +static
[PATCH] target/riscv: Enable xtheadsync under user mode
According to xtheadsync[1][2] documentation, it can be used in user mode and the behavior is same with other priviledges. [1]:https://github.com/T-head-Semi/thead-extension-spec/blob/master/xtheadsync/sync.adoc [2]:https://github.com/T-head-Semi/thead-extension-spec/blob/master/xtheadsync/sync_i.adoc Signed-off-by: LIU Zhiwei --- target/riscv/insn_trans/trans_xthead.c.inc | 10 -- 1 file changed, 10 deletions(-) diff --git a/target/riscv/insn_trans/trans_xthead.c.inc b/target/riscv/insn_trans/trans_xthead.c.inc index dbb6411239..22488412d4 100644 --- a/target/riscv/insn_trans/trans_xthead.c.inc +++ b/target/riscv/insn_trans/trans_xthead.c.inc @@ -992,7 +992,6 @@ static bool trans_th_sfence_vmas(DisasContext *ctx, arg_th_sfence_vmas *a) #endif } -#ifndef CONFIG_USER_ONLY static void gen_th_sync_local(DisasContext *ctx) { /* @@ -1003,14 +1002,12 @@ static void gen_th_sync_local(DisasContext *ctx) tcg_gen_exit_tb(NULL, 0); ctx->base.is_jmp = DISAS_NORETURN; } -#endif static bool trans_th_sync(DisasContext *ctx, arg_th_sync *a) { (void) a; REQUIRE_XTHEADSYNC(ctx); -#ifndef CONFIG_USER_ONLY REQUIRE_PRIV_MSU(ctx); /* @@ -1019,9 +1016,6 @@ static bool trans_th_sync(DisasContext *ctx, arg_th_sync *a) gen_th_sync_local(ctx); return true; -#else -return false; -#endif } static bool trans_th_sync_i(DisasContext *ctx, arg_th_sync_i *a) @@ -1029,7 +1023,6 @@ static bool trans_th_sync_i(DisasContext *ctx, arg_th_sync_i *a) (void) a; REQUIRE_XTHEADSYNC(ctx); -#ifndef CONFIG_USER_ONLY REQUIRE_PRIV_MSU(ctx); /* @@ -1038,9 +1031,6 @@ static bool trans_th_sync_i(DisasContext *ctx, arg_th_sync_i *a) gen_th_sync_local(ctx); return true; -#else -return false; -#endif } static bool trans_th_sync_is(DisasContext *ctx, arg_th_sync_is *a) -- 2.25.1
Re: [PATCH 2/2] target/riscv: Support xtheadmaee for thead-c906
On 2024/1/30 19:43, Christoph Müllner wrote: On Tue, Jan 30, 2024 at 12:12 PM LIU Zhiwei wrote: thead-c906 uses some flags in pte [60-63] bits. It has history reasons that SVPBMT didn't exist when thead-c906 came to world. We named this feature as xtheadmaee. this feature is controlled by an custom CSR named mxstatus, whose maee field encodes whether enable the pte [60-63] bits. The sections "5.2.2.1 Page table structure" and "15.1.7.1 M-mode extension status register (MXSTATUS)" in document[1] give the detailed information about its design. I would prefer if we would not define an extension like XTheadMaee without a specification. The linked document defines the bit MAEE in a custom CSR, but the scope of XTheadMaee is not clearly defined (the term XTheadMaee is not even part of the PDF). We have all the XThead* extensions well described here: https://github.com/T-head-Semi/thead-extension-spec/tree/master And it would not be much effort to add XTheadMaee there as well. Done. Thanks for the comment. The XTheadMaee specification is here: https://github.com/T-head-Semi/thead-extension-spec/blob/master/xtheadmaee.adoc Thanks, Zhiwei For those who don't know the context of this patch, here is the c906 boot regression report from Björn: https://lists.gnu.org/archive/html/qemu-devel/2024-01/msg04766.html BR Christoph Christoph [1]:https://occ-intl-prod.oss-ap-southeast-1.aliyuncs.com/resource//1699265191641/XuanTie-Openc906-UserManual.pdf Signed-off-by: LIU Zhiwei --- target/riscv/cpu.c | 6 target/riscv/cpu.h | 9 ++ target/riscv/cpu_bits.h| 6 target/riscv/cpu_cfg.h | 4 ++- target/riscv/cpu_helper.c | 25 --- target/riscv/meson.build | 1 + target/riscv/tcg/tcg-cpu.c | 9 ++ target/riscv/xthead_csr.c | 63 ++ 8 files changed, 105 insertions(+), 18 deletions(-) create mode 100644 target/riscv/xthead_csr.c diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 2dcbc9ff32..bfdbb0539a 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -171,6 +171,7 @@ const RISCVIsaExtData isa_edata_arr[] = { ISA_EXT_DATA_ENTRY(xtheadmemidx, PRIV_VERSION_1_11_0, ext_xtheadmemidx), ISA_EXT_DATA_ENTRY(xtheadmempair, PRIV_VERSION_1_11_0, ext_xtheadmempair), ISA_EXT_DATA_ENTRY(xtheadsync, PRIV_VERSION_1_11_0, ext_xtheadsync), +ISA_EXT_DATA_ENTRY(xtheadmaee, PRIV_VERSION_1_11_0, ext_xtheadmaee), ISA_EXT_DATA_ENTRY(xventanacondops, PRIV_VERSION_1_12_0, ext_XVentanaCondOps), DEFINE_PROP_END_OF_LIST(), @@ -506,6 +507,7 @@ static void rv64_thead_c906_cpu_init(Object *obj) cpu->cfg.mvendorid = THEAD_VENDOR_ID; #ifndef CONFIG_USER_ONLY +cpu->cfg.ext_xtheadmaee = true; set_satp_mode_max_supported(cpu, VM_1_10_SV39); #endif @@ -949,6 +951,9 @@ static void riscv_cpu_reset_hold(Object *obj) } pmp_unlock_entries(env); +if (riscv_cpu_cfg(env)->ext_xtheadmaee) { +env->th_mxstatus |= TH_MXSTATUS_MAEE; +} #endif env->xl = riscv_cpu_mxl(env); riscv_cpu_update_mask(env); @@ -1439,6 +1444,7 @@ const RISCVCPUMultiExtConfig riscv_cpu_vendor_exts[] = { MULTI_EXT_CFG_BOOL("xtheadmemidx", ext_xtheadmemidx, false), MULTI_EXT_CFG_BOOL("xtheadmempair", ext_xtheadmempair, false), MULTI_EXT_CFG_BOOL("xtheadsync", ext_xtheadsync, false), +MULTI_EXT_CFG_BOOL("xtheadmaee", ext_xtheadmaee, false), MULTI_EXT_CFG_BOOL("xventanacondops", ext_XVentanaCondOps, false), DEFINE_PROP_END_OF_LIST(), diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 5f3955c38d..1bacf40355 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -412,6 +412,14 @@ struct CPUArchState { target_ulong cur_pmmask; target_ulong cur_pmbase; +union { +/* Custom CSR for Xuantie CPU */ +struct { +#ifndef CONFIG_USER_ONLY +target_ulong th_mxstatus; +#endif +}; +}; /* Fields from here on are preserved across CPU reset. */ QEMUTimer *stimer; /* Internal timer for S-mode interrupt */ QEMUTimer *vstimer; /* Internal timer for VS-mode interrupt */ @@ -799,6 +807,7 @@ void riscv_add_satp_mode_properties(Object *obj); bool riscv_cpu_accelerator_compatible(RISCVCPU *cpu); /* CSR function table */ +extern riscv_csr_operations th_csr_ops[CSR_TABLE_SIZE]; extern riscv_csr_operations csr_ops[CSR_TABLE_SIZE]; extern const bool valid_vm_1_10_32[], valid_vm_1_10_64[]; diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h index e116f6c252..67ebb1cefe 100644 --- a/target/riscv/cpu_bits.h +++ b/target/riscv/cpu_bits.h @@ -897,4 +897,10 @@ typedef enum RISCVException { /* JVT CSR bits */ #define JVT_MODE 0x3F #define JVT_BASE (~0x3F) + +/* Xuantie custom CSRs */ +#define CSR_TH_MXSTA
[PATCH v2 1/2] target/riscv: Register vendors CSR
riscv specification allows custom CSRs in decode area. So we should register all vendor CSRs in cpu realize stage. Signed-off-by: LIU Zhiwei --- 1) Use int index to quiet the Werror for "i < 0". --- target/riscv/cpu.c | 3 +++ target/riscv/tcg/tcg-cpu.c | 18 ++ target/riscv/tcg/tcg-cpu.h | 1 + 3 files changed, 22 insertions(+) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 8cbfc7e781..2dcbc9ff32 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -1113,6 +1113,9 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp) return; } +if (tcg_enabled()) { +riscv_tcg_cpu_register_vendor_csr(cpu); +} riscv_cpu_register_gdb_regs_for_features(cs); #ifndef CONFIG_USER_ONLY diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c index 994ca1cdf9..559bf373f3 100644 --- a/target/riscv/tcg/tcg-cpu.c +++ b/target/riscv/tcg/tcg-cpu.c @@ -871,6 +871,24 @@ static void riscv_cpu_validate_profiles(RISCVCPU *cpu) } } +void riscv_tcg_cpu_register_vendor_csr(RISCVCPU *cpu) +{ +static const struct { +bool (*guard_func)(const RISCVCPUConfig *); +riscv_csr_operations *csr_ops; +} vendors[] = { +}; +for (int i = 0; i < ARRAY_SIZE(vendors); ++i) { +if (!vendors[i].guard_func(>cfg)) { +continue; +} +for (size_t j = 0; j < CSR_TABLE_SIZE && + vendors[i].csr_ops[j].name; j++) { +csr_ops[j] = vendors[i].csr_ops[j]; +} +} +} + void riscv_tcg_cpu_finalize_features(RISCVCPU *cpu, Error **errp) { CPURISCVState *env = >env; diff --git a/target/riscv/tcg/tcg-cpu.h b/target/riscv/tcg/tcg-cpu.h index f7b32417f8..3daaebf4fb 100644 --- a/target/riscv/tcg/tcg-cpu.h +++ b/target/riscv/tcg/tcg-cpu.h @@ -25,5 +25,6 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp); void riscv_tcg_cpu_finalize_features(RISCVCPU *cpu, Error **errp); bool riscv_cpu_tcg_compatible(RISCVCPU *cpu); +void riscv_tcg_cpu_register_vendor_csr(RISCVCPU *cpu); #endif -- 2.25.1
[PATCH v2 2/2] target/riscv: Support xtheadmaee for thead-c906
This patch set fix the regression on kernel pointed by Björn Töpel in https://www.mail-archive.com/qemu-devel@nongnu.org/msg1018232.html. thead-c906 uses some flags in pte [60-63] bits. It has history reasons that SVPBMT didn't exist when thead-c906 came to wotrld. We named this feature as xtheadmaee[1]. this feature is controlled by an custom CSR named mxstatus, whose maee field encodes whether enable the pte [60-63] bits. [1]:https://github.com/T-head-Semi/thead-extension-spec/blob/master/xtheadmaee.adoc Signed-off-by: LIU Zhiwei --- v1->v2: 1) Remove mxstatus user mode access 2) Add reference documentation to the commit log --- target/riscv/cpu.c | 6 target/riscv/cpu.h | 9 ++ target/riscv/cpu_bits.h| 6 target/riscv/cpu_cfg.h | 4 ++- target/riscv/cpu_helper.c | 25 --- target/riscv/meson.build | 1 + target/riscv/tcg/tcg-cpu.c | 7 +++- target/riscv/xthead_csr.c | 65 ++ 8 files changed, 110 insertions(+), 13 deletions(-) create mode 100644 target/riscv/xthead_csr.c diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 2dcbc9ff32..bfdbb0539a 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -171,6 +171,7 @@ const RISCVIsaExtData isa_edata_arr[] = { ISA_EXT_DATA_ENTRY(xtheadmemidx, PRIV_VERSION_1_11_0, ext_xtheadmemidx), ISA_EXT_DATA_ENTRY(xtheadmempair, PRIV_VERSION_1_11_0, ext_xtheadmempair), ISA_EXT_DATA_ENTRY(xtheadsync, PRIV_VERSION_1_11_0, ext_xtheadsync), +ISA_EXT_DATA_ENTRY(xtheadmaee, PRIV_VERSION_1_11_0, ext_xtheadmaee), ISA_EXT_DATA_ENTRY(xventanacondops, PRIV_VERSION_1_12_0, ext_XVentanaCondOps), DEFINE_PROP_END_OF_LIST(), @@ -506,6 +507,7 @@ static void rv64_thead_c906_cpu_init(Object *obj) cpu->cfg.mvendorid = THEAD_VENDOR_ID; #ifndef CONFIG_USER_ONLY +cpu->cfg.ext_xtheadmaee = true; set_satp_mode_max_supported(cpu, VM_1_10_SV39); #endif @@ -949,6 +951,9 @@ static void riscv_cpu_reset_hold(Object *obj) } pmp_unlock_entries(env); +if (riscv_cpu_cfg(env)->ext_xtheadmaee) { +env->th_mxstatus |= TH_MXSTATUS_MAEE; +} #endif env->xl = riscv_cpu_mxl(env); riscv_cpu_update_mask(env); @@ -1439,6 +1444,7 @@ const RISCVCPUMultiExtConfig riscv_cpu_vendor_exts[] = { MULTI_EXT_CFG_BOOL("xtheadmemidx", ext_xtheadmemidx, false), MULTI_EXT_CFG_BOOL("xtheadmempair", ext_xtheadmempair, false), MULTI_EXT_CFG_BOOL("xtheadsync", ext_xtheadsync, false), +MULTI_EXT_CFG_BOOL("xtheadmaee", ext_xtheadmaee, false), MULTI_EXT_CFG_BOOL("xventanacondops", ext_XVentanaCondOps, false), DEFINE_PROP_END_OF_LIST(), diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 5f3955c38d..1bacf40355 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -412,6 +412,14 @@ struct CPUArchState { target_ulong cur_pmmask; target_ulong cur_pmbase; +union { +/* Custom CSR for Xuantie CPU */ +struct { +#ifndef CONFIG_USER_ONLY +target_ulong th_mxstatus; +#endif +}; +}; /* Fields from here on are preserved across CPU reset. */ QEMUTimer *stimer; /* Internal timer for S-mode interrupt */ QEMUTimer *vstimer; /* Internal timer for VS-mode interrupt */ @@ -799,6 +807,7 @@ void riscv_add_satp_mode_properties(Object *obj); bool riscv_cpu_accelerator_compatible(RISCVCPU *cpu); /* CSR function table */ +extern riscv_csr_operations th_csr_ops[CSR_TABLE_SIZE]; extern riscv_csr_operations csr_ops[CSR_TABLE_SIZE]; extern const bool valid_vm_1_10_32[], valid_vm_1_10_64[]; diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h index e116f6c252..67ebb1cefe 100644 --- a/target/riscv/cpu_bits.h +++ b/target/riscv/cpu_bits.h @@ -897,4 +897,10 @@ typedef enum RISCVException { /* JVT CSR bits */ #define JVT_MODE 0x3F #define JVT_BASE (~0x3F) + +/* Xuantie custom CSRs */ +#define CSR_TH_MXSTATUS 0x7c0 + +#define TH_MXSTATUS_MAEE_SHIFT 21 +#define TH_MXSTATUS_MAEE(0x1 << TH_MXSTATUS_MAEE_SHIFT) #endif diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h index 780ae6ef17..3735c69fd6 100644 --- a/target/riscv/cpu_cfg.h +++ b/target/riscv/cpu_cfg.h @@ -136,6 +136,7 @@ struct RISCVCPUConfig { bool ext_xtheadmemidx; bool ext_xtheadmempair; bool ext_xtheadsync; +bool ext_xtheadmaee; bool ext_XVentanaCondOps; uint32_t pmu_mask; @@ -176,7 +177,8 @@ static inline bool has_xthead_p(const RISCVCPUConfig *cfg) cfg->ext_xtheadcondmov || cfg->ext_xtheadfmemidx || cfg->ext_xtheadfmv || cfg->ext_xtheadmac || cfg->ext_xtheadmemidx || - cfg->ext_xtheadmempair || cfg->ext_xtheadsync; + cfg->ext_xtheadmempair || cfg->ext_xtheadsync || + cfg->ext_xtheadmaee; } #define M
[PATCH v2 0/2] target/riscv: Support mxstatus CSR for thead-c906
This patch set fix the regression on kernel pointed by Björn Töpel in https://www.mail-archive.com/qemu-devel@nongnu.org/msg1018232.html. We first add a framework for vendor CSRs in patch 1. After that we add one thead-c906 CSR mxstatus, which is used for mmu extension xtheadmaee. thead-c906 uses some flags in pte [60-63] bits. It has history reasons that SVPBMT didn't exist when thead-c906 came to wotrld. We named this feature as xtheadmaee[1]. this feature is controlled by an custom CSR named mxstatus, whose maee field encodes whether enable the pte [60-63] bits. [1]:https://github.com/T-head-Semi/thead-extension-spec/blob/master/xtheadmaee.adoc LIU Zhiwei (2): target/riscv: Register vendors CSR target/riscv: Support xtheadmaee for thead-c906 target/riscv/cpu.c | 9 ++ target/riscv/cpu.h | 9 ++ target/riscv/cpu_bits.h| 6 target/riscv/cpu_cfg.h | 4 ++- target/riscv/cpu_helper.c | 25 --- target/riscv/meson.build | 1 + target/riscv/tcg/tcg-cpu.c | 25 ++- target/riscv/tcg/tcg-cpu.h | 1 + target/riscv/xthead_csr.c | 65 ++ 9 files changed, 132 insertions(+), 13 deletions(-) create mode 100644 target/riscv/xthead_csr.c -- 2.25.1
Re: [PATCH 2/2] target/riscv: Support xtheadmaee for thead-c906
On 2024/1/31 13:07, Richard Henderson wrote: On 1/30/24 21:11, LIU Zhiwei wrote: +riscv_csr_operations th_csr_ops[CSR_TABLE_SIZE] = { +#if !defined(CONFIG_USER_ONLY) + [CSR_TH_MXSTATUS] = { "th_mxstatus", th_maee_check, read_th_mxstatus, + write_th_mxstatus}, +#endif /* !CONFIG_USER_ONLY */ +}; This is clearly the wrong data structure for a single entry in the array. This array should have the same size with csr_ops so that we can override custom CSR behavior directly. Besides, It will have other entries in the near future. I see that I missed surround the th_maee_check, read_th_mxstatus, write_mxstatus with !CONFIG_USER_ONLY. But I don't understand why it is wrong for a single entry in the array, at least the compiler think it has no error. Thanks, Zhiwei r~
Re: [PATCH 1/2] target/riscv: Register vendors CSR
On 2024/1/31 13:06, Richard Henderson wrote: On 1/30/24 21:11, LIU Zhiwei wrote: +/* This stub just works for making vendors array not empty */ +riscv_csr_operations stub_csr_ops[CSR_TABLE_SIZE]; +static inline bool never_p(const RISCVCPUConfig *cfg) +{ + return false; +} + +void riscv_tcg_cpu_register_vendor_csr(RISCVCPU *cpu) +{ + static const struct { + bool (*guard_func)(const RISCVCPUConfig *); + riscv_csr_operations *csr_ops; + } vendors[] = { + { never_p, stub_csr_ops }, + }; + for (size_t i = 0; i < ARRAY_SIZE(vendors); ++i) { Presumably you did this to avoid a Werror for "i < 0", since i is unsigned. Yes. That's the gcc complains. It would be better to either use "int i" OK , or for (size_t i = 0, n = ARRAY_SIZE(vendors); i < n; ++i) either of which will not Werror. This works. I don't know why it works, because n is 0 and never changes. Especially considering the size of stub_csr_ops. Do you mean we should remove the stub_csr_ops? I don't know how to relate your two solving ways to stub_csr_ops. Thanks, Zhiwei r~
[PATCH 2/2] target/riscv: Support xtheadmaee for thead-c906
thead-c906 uses some flags in pte [60-63] bits. It has history reasons that SVPBMT didn't exist when thead-c906 came to world. We named this feature as xtheadmaee. this feature is controlled by an custom CSR named mxstatus, whose maee field encodes whether enable the pte [60-63] bits. The sections "5.2.2.1 Page table structure" and "15.1.7.1 M-mode extension status register (MXSTATUS)" in document[1] give the detailed information about its design. [1]:https://occ-intl-prod.oss-ap-southeast-1.aliyuncs.com/resource//1699265191641/XuanTie-Openc906-UserManual.pdf Signed-off-by: LIU Zhiwei --- target/riscv/cpu.c | 6 target/riscv/cpu.h | 9 ++ target/riscv/cpu_bits.h| 6 target/riscv/cpu_cfg.h | 4 ++- target/riscv/cpu_helper.c | 25 --- target/riscv/meson.build | 1 + target/riscv/tcg/tcg-cpu.c | 9 ++ target/riscv/xthead_csr.c | 63 ++ 8 files changed, 105 insertions(+), 18 deletions(-) create mode 100644 target/riscv/xthead_csr.c diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 2dcbc9ff32..bfdbb0539a 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -171,6 +171,7 @@ const RISCVIsaExtData isa_edata_arr[] = { ISA_EXT_DATA_ENTRY(xtheadmemidx, PRIV_VERSION_1_11_0, ext_xtheadmemidx), ISA_EXT_DATA_ENTRY(xtheadmempair, PRIV_VERSION_1_11_0, ext_xtheadmempair), ISA_EXT_DATA_ENTRY(xtheadsync, PRIV_VERSION_1_11_0, ext_xtheadsync), +ISA_EXT_DATA_ENTRY(xtheadmaee, PRIV_VERSION_1_11_0, ext_xtheadmaee), ISA_EXT_DATA_ENTRY(xventanacondops, PRIV_VERSION_1_12_0, ext_XVentanaCondOps), DEFINE_PROP_END_OF_LIST(), @@ -506,6 +507,7 @@ static void rv64_thead_c906_cpu_init(Object *obj) cpu->cfg.mvendorid = THEAD_VENDOR_ID; #ifndef CONFIG_USER_ONLY +cpu->cfg.ext_xtheadmaee = true; set_satp_mode_max_supported(cpu, VM_1_10_SV39); #endif @@ -949,6 +951,9 @@ static void riscv_cpu_reset_hold(Object *obj) } pmp_unlock_entries(env); +if (riscv_cpu_cfg(env)->ext_xtheadmaee) { +env->th_mxstatus |= TH_MXSTATUS_MAEE; +} #endif env->xl = riscv_cpu_mxl(env); riscv_cpu_update_mask(env); @@ -1439,6 +1444,7 @@ const RISCVCPUMultiExtConfig riscv_cpu_vendor_exts[] = { MULTI_EXT_CFG_BOOL("xtheadmemidx", ext_xtheadmemidx, false), MULTI_EXT_CFG_BOOL("xtheadmempair", ext_xtheadmempair, false), MULTI_EXT_CFG_BOOL("xtheadsync", ext_xtheadsync, false), +MULTI_EXT_CFG_BOOL("xtheadmaee", ext_xtheadmaee, false), MULTI_EXT_CFG_BOOL("xventanacondops", ext_XVentanaCondOps, false), DEFINE_PROP_END_OF_LIST(), diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 5f3955c38d..1bacf40355 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -412,6 +412,14 @@ struct CPUArchState { target_ulong cur_pmmask; target_ulong cur_pmbase; +union { +/* Custom CSR for Xuantie CPU */ +struct { +#ifndef CONFIG_USER_ONLY +target_ulong th_mxstatus; +#endif +}; +}; /* Fields from here on are preserved across CPU reset. */ QEMUTimer *stimer; /* Internal timer for S-mode interrupt */ QEMUTimer *vstimer; /* Internal timer for VS-mode interrupt */ @@ -799,6 +807,7 @@ void riscv_add_satp_mode_properties(Object *obj); bool riscv_cpu_accelerator_compatible(RISCVCPU *cpu); /* CSR function table */ +extern riscv_csr_operations th_csr_ops[CSR_TABLE_SIZE]; extern riscv_csr_operations csr_ops[CSR_TABLE_SIZE]; extern const bool valid_vm_1_10_32[], valid_vm_1_10_64[]; diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h index e116f6c252..67ebb1cefe 100644 --- a/target/riscv/cpu_bits.h +++ b/target/riscv/cpu_bits.h @@ -897,4 +897,10 @@ typedef enum RISCVException { /* JVT CSR bits */ #define JVT_MODE 0x3F #define JVT_BASE (~0x3F) + +/* Xuantie custom CSRs */ +#define CSR_TH_MXSTATUS 0x7c0 + +#define TH_MXSTATUS_MAEE_SHIFT 21 +#define TH_MXSTATUS_MAEE(0x1 << TH_MXSTATUS_MAEE_SHIFT) #endif diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h index 780ae6ef17..3735c69fd6 100644 --- a/target/riscv/cpu_cfg.h +++ b/target/riscv/cpu_cfg.h @@ -136,6 +136,7 @@ struct RISCVCPUConfig { bool ext_xtheadmemidx; bool ext_xtheadmempair; bool ext_xtheadsync; +bool ext_xtheadmaee; bool ext_XVentanaCondOps; uint32_t pmu_mask; @@ -176,7 +177,8 @@ static inline bool has_xthead_p(const RISCVCPUConfig *cfg) cfg->ext_xtheadcondmov || cfg->ext_xtheadfmemidx || cfg->ext_xtheadfmv || cfg->ext_xtheadmac || cfg->ext_xtheadmemidx || - cfg->ext_xtheadmempair || cfg->ext_xtheadsync; + cfg->ext_xtheadmempair || cfg->ext_xtheadsync || + cfg->ext_xtheadmaee; } #define MATERIALISE_EXT_PREDICATE(ext) \
[PATCH 1/2] target/riscv: Register vendors CSR
riscv specification allows custom CSRs in decode area. So we should register all vendor CSRs in cpu realize stage. Signed-off-by: LIU Zhiwei --- target/riscv/cpu.c | 3 +++ target/riscv/tcg/tcg-cpu.c | 26 ++ target/riscv/tcg/tcg-cpu.h | 1 + 3 files changed, 30 insertions(+) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 8cbfc7e781..2dcbc9ff32 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -1113,6 +1113,9 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp) return; } +if (tcg_enabled()) { +riscv_tcg_cpu_register_vendor_csr(cpu); +} riscv_cpu_register_gdb_regs_for_features(cs); #ifndef CONFIG_USER_ONLY diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c index 994ca1cdf9..408b2ebffa 100644 --- a/target/riscv/tcg/tcg-cpu.c +++ b/target/riscv/tcg/tcg-cpu.c @@ -871,6 +871,32 @@ static void riscv_cpu_validate_profiles(RISCVCPU *cpu) } } +/* This stub just works for making vendors array not empty */ +riscv_csr_operations stub_csr_ops[CSR_TABLE_SIZE]; +static inline bool never_p(const RISCVCPUConfig *cfg) +{ +return false; +} + +void riscv_tcg_cpu_register_vendor_csr(RISCVCPU *cpu) +{ +static const struct { +bool (*guard_func)(const RISCVCPUConfig *); +riscv_csr_operations *csr_ops; +} vendors[] = { +{ never_p, stub_csr_ops }, +}; +for (size_t i = 0; i < ARRAY_SIZE(vendors); ++i) { +if (!vendors[i].guard_func(>cfg)) { +continue; +} +for (size_t j = 0; j < CSR_TABLE_SIZE && + vendors[i].csr_ops[j].name; j++) { +csr_ops[j] = vendors[i].csr_ops[j]; +} +} +} + void riscv_tcg_cpu_finalize_features(RISCVCPU *cpu, Error **errp) { CPURISCVState *env = >env; diff --git a/target/riscv/tcg/tcg-cpu.h b/target/riscv/tcg/tcg-cpu.h index f7b32417f8..3daaebf4fb 100644 --- a/target/riscv/tcg/tcg-cpu.h +++ b/target/riscv/tcg/tcg-cpu.h @@ -25,5 +25,6 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp); void riscv_tcg_cpu_finalize_features(RISCVCPU *cpu, Error **errp); bool riscv_cpu_tcg_compatible(RISCVCPU *cpu); +void riscv_tcg_cpu_register_vendor_csr(RISCVCPU *cpu); #endif -- 2.25.1
[PATCH 0/2] target/riscv: Support mxstatus CSR for thead-c906
We first add a framework for vendor CSRs in patch 1. After that we add one thead-c906 CSR mxstatus, which is used for mmu extension xtheadmaee. This patch set fix the regression on kernel pointed by Björn Töpel in https://www.mail-archive.com/qemu-devel@nongnu.org/msg1018232.html. LIU Zhiwei (2): target/riscv: Register vendors CSR target/riscv: Support xtheadmaee for thead-c906 target/riscv/cpu.c | 9 ++ target/riscv/cpu.h | 9 ++ target/riscv/cpu_bits.h| 6 target/riscv/cpu_cfg.h | 4 ++- target/riscv/cpu_helper.c | 25 --- target/riscv/meson.build | 1 + target/riscv/tcg/tcg-cpu.c | 25 ++- target/riscv/tcg/tcg-cpu.h | 1 + target/riscv/xthead_csr.c | 63 ++ 9 files changed, 130 insertions(+), 13 deletions(-) create mode 100644 target/riscv/xthead_csr.c -- 2.25.1
[PATCH] target/riscv: FCSR doesn't contain vxrm and vxsat
vxrm and vxsat have been moved into a special register vcsr since RVV v1.0. So remove them from FCSR for vector 1.0. Signed-off-by: LIU Zhiwei --- target/riscv/cpu_bits.h | 8 1 file changed, 8 deletions(-) diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h index ebd7917d49..e116f6c252 100644 --- a/target/riscv/cpu_bits.h +++ b/target/riscv/cpu_bits.h @@ -32,14 +32,6 @@ #define FSR_NXA (FPEXC_NX << FSR_AEXC_SHIFT) #define FSR_AEXC(FSR_NVA | FSR_OFA | FSR_UFA | FSR_DZA | FSR_NXA) -/* Vector Fixed-Point round model */ -#define FSR_VXRM_SHIFT 9 -#define FSR_VXRM(0x3 << FSR_VXRM_SHIFT) - -/* Vector Fixed-Point saturation flag */ -#define FSR_VXSAT_SHIFT 8 -#define FSR_VXSAT (0x1 << FSR_VXSAT_SHIFT) - /* Control and Status Registers */ /* User Trap Setup */ -- 2.25.1
[PATCH] target/riscv: Use RISCVException as return type for all csr ops
The real return value type has been converted to RISCVException, but some function declarations still not. This patch makes all csr operation declarations use RISCVExcetion. Signed-off-by: LIU Zhiwei --- target/riscv/csr.c | 117 - 1 file changed, 74 insertions(+), 43 deletions(-) diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 674ea075a4..ac9a856cc5 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -242,7 +242,7 @@ static RISCVException any32(CPURISCVState *env, int csrno) } -static int aia_any(CPURISCVState *env, int csrno) +static RISCVException aia_any(CPURISCVState *env, int csrno) { if (!riscv_cpu_cfg(env)->ext_smaia) { return RISCV_EXCP_ILLEGAL_INST; @@ -251,7 +251,7 @@ static int aia_any(CPURISCVState *env, int csrno) return any(env, csrno); } -static int aia_any32(CPURISCVState *env, int csrno) +static RISCVException aia_any32(CPURISCVState *env, int csrno) { if (!riscv_cpu_cfg(env)->ext_smaia) { return RISCV_EXCP_ILLEGAL_INST; @@ -269,7 +269,7 @@ static RISCVException smode(CPURISCVState *env, int csrno) return RISCV_EXCP_ILLEGAL_INST; } -static int smode32(CPURISCVState *env, int csrno) +static RISCVException smode32(CPURISCVState *env, int csrno) { if (riscv_cpu_mxl(env) != MXL_RV32) { return RISCV_EXCP_ILLEGAL_INST; @@ -278,7 +278,7 @@ static int smode32(CPURISCVState *env, int csrno) return smode(env, csrno); } -static int aia_smode(CPURISCVState *env, int csrno) +static RISCVException aia_smode(CPURISCVState *env, int csrno) { if (!riscv_cpu_cfg(env)->ext_ssaia) { return RISCV_EXCP_ILLEGAL_INST; @@ -287,7 +287,7 @@ static int aia_smode(CPURISCVState *env, int csrno) return smode(env, csrno); } -static int aia_smode32(CPURISCVState *env, int csrno) +static RISCVException aia_smode32(CPURISCVState *env, int csrno) { if (!riscv_cpu_cfg(env)->ext_ssaia) { return RISCV_EXCP_ILLEGAL_INST; @@ -496,7 +496,7 @@ static RISCVException pointer_masking(CPURISCVState *env, int csrno) return RISCV_EXCP_ILLEGAL_INST; } -static int aia_hmode(CPURISCVState *env, int csrno) +static RISCVException aia_hmode(CPURISCVState *env, int csrno) { if (!riscv_cpu_cfg(env)->ext_ssaia) { return RISCV_EXCP_ILLEGAL_INST; @@ -505,7 +505,7 @@ static int aia_hmode(CPURISCVState *env, int csrno) return hmode(env, csrno); } -static int aia_hmode32(CPURISCVState *env, int csrno) +static RISCVException aia_hmode32(CPURISCVState *env, int csrno) { if (!riscv_cpu_cfg(env)->ext_ssaia) { return RISCV_EXCP_ILLEGAL_INST; @@ -681,7 +681,8 @@ static RISCVException read_vl(CPURISCVState *env, int csrno, return RISCV_EXCP_NONE; } -static int read_vlenb(CPURISCVState *env, int csrno, target_ulong *val) +static RISCVException read_vlenb(CPURISCVState *env, int csrno, + target_ulong *val) { *val = riscv_cpu_cfg(env)->vlen >> 3; return RISCV_EXCP_NONE; @@ -742,13 +743,15 @@ static RISCVException write_vstart(CPURISCVState *env, int csrno, return RISCV_EXCP_NONE; } -static int read_vcsr(CPURISCVState *env, int csrno, target_ulong *val) +static RISCVException read_vcsr(CPURISCVState *env, int csrno, +target_ulong *val) { *val = (env->vxrm << VCSR_VXRM_SHIFT) | (env->vxsat << VCSR_VXSAT_SHIFT); return RISCV_EXCP_NONE; } -static int write_vcsr(CPURISCVState *env, int csrno, target_ulong val) +static RISCVException write_vcsr(CPURISCVState *env, int csrno, + target_ulong val) { #if !defined(CONFIG_USER_ONLY) env->mstatus |= MSTATUS_VS; @@ -798,13 +801,15 @@ static RISCVException read_timeh(CPURISCVState *env, int csrno, return RISCV_EXCP_NONE; } -static int read_hpmcounter(CPURISCVState *env, int csrno, target_ulong *val) +static RISCVException read_hpmcounter(CPURISCVState *env, int csrno, + target_ulong *val) { *val = get_ticks(false); return RISCV_EXCP_NONE; } -static int read_hpmcounterh(CPURISCVState *env, int csrno, target_ulong *val) +static RISCVException read_hpmcounterh(CPURISCVState *env, int csrno, + target_ulong *val) { *val = get_ticks(true); return RISCV_EXCP_NONE; @@ -812,7 +817,8 @@ static int read_hpmcounterh(CPURISCVState *env, int csrno, target_ulong *val) #else /* CONFIG_USER_ONLY */ -static int read_mhpmevent(CPURISCVState *env, int csrno, target_ulong *val) +static RISCVException read_mhpmevent(CPURISCVState *env, int csrno, + target_ulong *val) { int evt_index = csrno - CSR_MCOUNTINHIBIT; @@ -821,7 +827,8 @@ static int read_mhpmevent(CPURISCVState *env, int csrno, target_ulong *val) return RISCV_EXCP_NONE; } -static int write_mhpmevent(CPURISCV
Re: qemu riscv, thead c906, Linux boot regression
On 2024/1/24 20:49, Björn Töpel wrote: Hi! I bumped the RISC-V Linux kernel CI to use qemu 8.2.0, and realized that thead c906 didn't boot anymore. Bisection points to commit d6a427e2c0b2 ("target/riscv/cpu.c: restrict 'marchid' value") Reverting that commit, or the hack below solves the boot issue: --8<-- diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 8cbfc7e781ad..e18596c8a55a 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -505,6 +505,9 @@ static void rv64_thead_c906_cpu_init(Object *obj) cpu->cfg.ext_xtheadsync = true; cpu->cfg.mvendorid = THEAD_VENDOR_ID; +cpu->cfg.marchid = ((QEMU_VERSION_MAJOR << 16) | +(QEMU_VERSION_MINOR << 8) | +(QEMU_VERSION_MICRO)); #ifndef CONFIG_USER_ONLY set_satp_mode_max_supported(cpu, VM_1_10_SV39); #endif --8<-- I'm unsure what the correct qemu way of adding a default value is, or if c906 should have a proper marchid. Maybe Christoph or Zhiwei can answer? qemu command-line: qemu-system-riscv64 -nodefaults -nographic -machine virt,acpi=off \ -cpu thead-c906 ... Hi Björn, I think it is caused by an mmu extension(named XTheadMaee) not implemented on QEMU which is conflicts with Svpbmt, which is the reason for error-ta in Linux. I will try to fix this on QEMU and at the same time give a way to implement vendor custom CSR(XTheadMaee is controlled by an CSR named mexstatus) on QEMU. Thanks, Zhiwei Thanks, Björn
[PATCH 1/1] target/riscv: Not allow write mstatus_vs without RVV
If CPU does not implement the Vector extension, it usually means mstatus vs hardwire to zero. So we should not allow write a non-zero value to this field. Signed-off-by: LIU Zhiwei --- target/riscv/csr.c | 5 - 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/target/riscv/csr.c b/target/riscv/csr.c index fde7ce1a53..d1de6b2390 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -1328,11 +1328,14 @@ static RISCVException write_mstatus(CPURISCVState *env, int csrno, mask = MSTATUS_SIE | MSTATUS_SPIE | MSTATUS_MIE | MSTATUS_MPIE | MSTATUS_SPP | MSTATUS_MPRV | MSTATUS_SUM | MSTATUS_MPP | MSTATUS_MXR | MSTATUS_TVM | MSTATUS_TSR | -MSTATUS_TW | MSTATUS_VS; +MSTATUS_TW; if (riscv_has_ext(env, RVF)) { mask |= MSTATUS_FS; } +if (riscv_has_ext(env, RVV)) { +mask |= MSTATUS_VS; +} if (xl != MXL_RV32 || env->debugger) { if (riscv_has_ext(env, RVH)) { -- 2.25.1
[PATCH for 8.2] target/riscv: Fix th.dcache.cval1 priviledge check
According to the specification, the th.dcache.cvall1 can be executed under all priviledges. The specification about xtheadcmo located in, https://github.com/T-head-Semi/thead-extension-spec/blob/master/xtheadcmo/dcache_cval1.adoc Signed-off-by: LIU Zhiwei --- target/riscv/insn_trans/trans_xthead.c.inc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/riscv/insn_trans/trans_xthead.c.inc b/target/riscv/insn_trans/trans_xthead.c.inc index 810d76665a..dbb6411239 100644 --- a/target/riscv/insn_trans/trans_xthead.c.inc +++ b/target/riscv/insn_trans/trans_xthead.c.inc @@ -296,7 +296,7 @@ NOP_PRIVCHECK(th_dcache_csw, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MS) NOP_PRIVCHECK(th_dcache_cisw, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MS) NOP_PRIVCHECK(th_dcache_isw, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MS) NOP_PRIVCHECK(th_dcache_cpal1, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MS) -NOP_PRIVCHECK(th_dcache_cval1, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MS) +NOP_PRIVCHECK(th_dcache_cval1, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MSU) NOP_PRIVCHECK(th_icache_iall, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MS) NOP_PRIVCHECK(th_icache_ialls, REQUIRE_XTHEADCMO, REQUIRE_PRIV_MS) -- 2.17.1
Re: [PATCH 1/2] target/riscv: FIX xATP_MODE validation
Hi Irina, On 2023/12/1 19:53, Irina Ryapolova wrote: The SATP register is an SXLEN-bit read/write WARL register. It means that CSR fields are only defined for a subset of bit encodings, but allow any value to be written while guaranteeing to return a legal value whenever read (See riscv-privileged-20211203, SATP CSR). For example on rv64 we are trying to write to SATP CSR val = 0x1000 (SATP_MODE = 1 - Reserved for standard use) and after that we are trying to read SATP_CSR. We read from the SATP CSR value = 0x1000, which is not a correct operation (return illegal value). Signed-off-by: Irina Ryapolova --- target/riscv/csr.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/target/riscv/csr.c b/target/riscv/csr.c index fde7ce1a53..6f244815b7 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -1278,8 +1278,8 @@ static RISCVException read_mstatus(CPURISCVState *env, int csrno, static bool validate_vm(CPURISCVState *env, target_ulong vm) { -return (vm & 0xf) <= - satp_mode_max_from_map(riscv_cpu_cfg(env)->satp_mode.map); +uint64_t mode_supported = riscv_cpu_cfg(env)->satp_mode.supported; Why not use satp_mode.map? Using satp_mode.supported will violate the SATP settings in cpu init. Zhiwei +return get_field(mode_supported, (1 << vm)); } static target_ulong legalize_mpp(CPURISCVState *env, target_ulong old_mpp,
Re: [PATCH 1/1] accel/tcg: Fix the comment for CPUTLBEntryFull
On 2023/11/28 21:04, Mark Cave-Ayland wrote: On 01/09/2023 07:01, LIU Zhiwei wrote: When memory region is ram, the lower TARGET_PAGE_BITS is not the physical section number. Instead, its value is always 0. Add comment and assert to make it clear. Signed-off-by: LIU Zhiwei --- accel/tcg/cputlb.c | 11 +++ include/exec/cpu-defs.h | 12 ++-- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c index d68fa6867c..a1ebf75068 100644 --- a/accel/tcg/cputlb.c +++ b/accel/tcg/cputlb.c @@ -1192,6 +1192,7 @@ void tlb_set_page_full(CPUState *cpu, int mmu_idx, write_flags = read_flags; if (is_ram) { iotlb = memory_region_get_ram_addr(section->mr) + xlat; + assert(!(iotlb & ~TARGET_PAGE_MASK)); /* * Computing is_clean is expensive; avoid all that unless * the page is actually writable. @@ -1254,10 +1255,12 @@ void tlb_set_page_full(CPUState *cpu, int mmu_idx, /* refill the tlb */ /* - * At this point iotlb contains a physical section number in the lower - * TARGET_PAGE_BITS, and either - * + the ram_addr_t of the page base of the target RAM (RAM) - * + the offset within section->mr of the page base (I/O, ROMD) + * When memory region is ram, iotlb contains a TARGET_PAGE_BITS + * aligned ram_addr_t of the page base of the target RAM. + * Otherwise, iotlb contains + * - a physical section number in the lower TARGET_PAGE_BITS + * - the offset within section->mr of the page base (I/O, ROMD) with the + * TARGET_PAGE_BITS masked off. * We subtract addr_page (which is page aligned and thus won't * disturb the low bits) to give an offset which can be added to the * (non-page-aligned) vaddr of the eventual memory access to get diff --git a/include/exec/cpu-defs.h b/include/exec/cpu-defs.h index fb4c8d480f..350287852e 100644 --- a/include/exec/cpu-defs.h +++ b/include/exec/cpu-defs.h @@ -100,12 +100,12 @@ typedef struct CPUTLBEntryFull { /* * @xlat_section contains: - * - in the lower TARGET_PAGE_BITS, a physical section number - * - with the lower TARGET_PAGE_BITS masked off, an offset which - * must be added to the virtual address to obtain: - * + the ram_addr_t of the target RAM (if the physical section - * number is PHYS_SECTION_NOTDIRTY or PHYS_SECTION_ROM) - * + the offset within the target MemoryRegion (otherwise) + * - For ram, an offset which must be added to the virtual address + * to obtain the ram_addr_t of the target RAM + * - For other memory regions, + * + in the lower TARGET_PAGE_BITS, the physical section number + * + with the TARGET_PAGE_BITS masked off, the offset within + * the target MemoryRegion */ hwaddr xlat_section; Someone sent me a test case that triggers the assert() introduced by this commit dff1ab6 ("accel/tcg: Fix the comment for CPUTLBEntryFull") for qemu-system-m68k which is still present in git master. The reproducer is easy: 1. Grab the machine ROM file from https://www.ilande.co.uk/tmp/qemu/tQuadra800.rom 2. Create an empty declaration ROM greater than 4K: dd if=/dev/zero of=/tmp/badrom bs=512 count=12 3. Start QEMU like this: qemu-system-m68k -M q800 -bios tQuadra800.rom \ -device nubus-macfb,romfile=/tmp/badrom The QEMU process hits the assert() with the following backtrace: (gdb) bt #0 0x758a9d3c in ?? () from /lib/x86_64-linux-gnu/libc.so.6 #1 0x7585af32 in raise () from /lib/x86_64-linux-gnu/libc.so.6 #2 0x75845472 in abort () from /lib/x86_64-linux-gnu/libc.so.6 #3 0x75845395 in ?? () from /lib/x86_64-linux-gnu/libc.so.6 #4 0x75853e32 in __assert_fail () from /lib/x86_64-linux-gnu/libc.so.6 #5 0x55942e0a in tlb_set_page_full (cpu=0x5618d4a0, mmu_idx=0, addr=4244631552, full=0x7fffe7d7f7c0) at ../accel/tcg/cputlb.c:1171 #6 0x559432a0 in tlb_set_page_with_attrs (cpu=0x5618d4a0, addr=4244631552, paddr=4244631552, attrs=..., prot=7, mmu_idx=0, size=4096) at ../accel/tcg/cputlb.c:1290 #7 0x55943305 in tlb_set_page (cpu=0x5618d4a0, addr=4244631552, paddr=4244631552, prot=7, mmu_idx=0, size=4096) at ../accel/tcg/cputlb.c:1297 #8 0x5588aade in m68k_cpu_tlb_fill (cs=0x5618d4a0, address=4244635647, size=1, qemu_access_type=MMU_DATA_LOAD, mmu_idx=0, probe=false, retaddr=140734805255937) at ../target/m68k/helper.c:1018 #9 0x55943367 in tlb_fill (cpu=0x5618d4a0, addr=4244635647, size=1, access_type=MMU_DATA_LOAD, mmu_idx=0, retaddr=140734805255937) at ../accel/tcg/cputlb.c:1315 #10 0x55945d78 in mmu_lookup1 (cpu=0x5618d4a0, data=0x7fffe7d7fa00, mmu_idx=0, access_type=MMU_DATA_LOAD, ra=140734805255937) at ../accel/tcg/cputlb.c:1713 #11 0x55946081 in mmu_lookup (cp
[PATCH for 8.2] accel/tcg/cputlb: Fix iotlb page alignment check
For ram memory region the iotlb(which will be filled into the xlat_section of CPUTLBEntryFull) is calculated as: iotlb = memory_region_get_ram_addr(section->mr) + xlat; 1) xlat here is the offset_within_region of a MemoryRegionSection, which maybe not TARGET_PAGE_BITS aligned. 2) The ram_addr_t returned by memory_region_get_ram_addr is always HOST PAGE ALIGNED. So we cann't assert the sum of them is TARGET_PAGE_BITS aligend. A fail case has been give by the link: https://lore.kernel.org/all/b68ab7d3-d3d3-9f81-569d-454ae9c11...@linaro.org/T/ Fixes: dff1ab68d8c5 ("accel/tcg: Fix the comment for CPUTLBEntryFull") Signed-off-by: LIU Zhiwei --- accel/tcg/cputlb.c | 6 ++ 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c index db3f93fda9..7a50a21a2e 100644 --- a/accel/tcg/cputlb.c +++ b/accel/tcg/cputlb.c @@ -1168,7 +1168,6 @@ void tlb_set_page_full(CPUState *cpu, int mmu_idx, write_flags = read_flags; if (is_ram) { iotlb = memory_region_get_ram_addr(section->mr) + xlat; -assert(!(iotlb & ~TARGET_PAGE_MASK)); /* * Computing is_clean is expensive; avoid all that unless * the page is actually writable. @@ -1231,9 +1230,8 @@ void tlb_set_page_full(CPUState *cpu, int mmu_idx, /* refill the tlb */ /* - * When memory region is ram, iotlb contains a TARGET_PAGE_BITS - * aligned ram_addr_t of the page base of the target RAM. - * Otherwise, iotlb contains + * When memory region is ram, iotlb contains ram_addr_t of the page base + * of the target RAM. Otherwise, iotlb contains * - a physical section number in the lower TARGET_PAGE_BITS * - the offset within section->mr of the page base (I/O, ROMD) with the *TARGET_PAGE_BITS masked off. -- 2.17.1
Re: [PATCH 1/1] MAINTAINERS: update mail address for Weiwei Li
On 2023/10/30 16:16, Weiwei Li wrote: My Iscas mail account will be disabled soon, change to my personal gmail account. Signed-off-by: Weiwei Li --- MAINTAINERS | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index cd8d6b140f..aa5c5d4bff 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -323,7 +323,7 @@ RISC-V TCG CPUs M: Palmer Dabbelt M: Alistair Francis M: Bin Meng -R: Weiwei Li +R: Weiwei Li R: Daniel Henrique Barboza R: Liu Zhiwei L: qemu-ri...@nongnu.org Reviewed-by: LIU Zhiwei Zhiwei
Re: [PATCH v3 5/6] target/riscv/tcg: add riscv_cpu_write_misa_bit()
On 2023/10/21 6:39, Daniel Henrique Barboza wrote: We have two instances of the setting/clearing a MISA bit from env->misa_ext and env->misa_ext_mask pattern. And the next patch will end up adding one more. Create a helper to avoid code repetition. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Alistair Francis --- target/riscv/tcg/tcg-cpu.c | 44 -- 1 file changed, 23 insertions(+), 21 deletions(-) diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c index 59b75a14ac..ba11d0566d 100644 --- a/target/riscv/tcg/tcg-cpu.c +++ b/target/riscv/tcg/tcg-cpu.c @@ -42,6 +42,20 @@ static bool cpu_cfg_ext_is_user_set(uint32_t ext_offset) GUINT_TO_POINTER(ext_offset)); } +static void riscv_cpu_write_misa_bit(RISCVCPU *cpu, uint32_t bit, + bool enabled) +{ +CPURISCVState *env = >env; + +if (enabled) { +env->misa_ext |= bit; +env->misa_ext_mask |= bit; +} else { +env->misa_ext &= ~bit; +env->misa_ext_mask &= ~bit; +} +} + static void riscv_cpu_synchronize_from_tb(CPUState *cs, const TranslationBlock *tb) { @@ -680,20 +694,14 @@ static void cpu_set_misa_ext_cfg(Object *obj, Visitor *v, const char *name, return; } -if (value) { -if (!generic_cpu) { -g_autofree char *cpuname = riscv_cpu_get_name(cpu); -error_setg(errp, "'%s' CPU does not allow enabling extensions", - cpuname); -return; -} - -env->misa_ext |= misa_bit; -env->misa_ext_mask |= misa_bit; -} else { -env->misa_ext &= ~misa_bit; -env->misa_ext_mask &= ~misa_bit; +if (value && !generic_cpu) { +g_autofree char *cpuname = riscv_cpu_get_name(cpu); +error_setg(errp, "'%s' CPU does not allow enabling extensions", + cpuname); +return; } + +riscv_cpu_write_misa_bit(cpu, misa_bit, value); } static void cpu_get_misa_ext_cfg(Object *obj, Visitor *v, const char *name, @@ -737,7 +745,6 @@ static const RISCVCPUMisaExtConfig misa_ext_cfgs[] = { */ static void riscv_cpu_add_misa_properties(Object *cpu_obj) { -CPURISCVState *env = _CPU(cpu_obj)->env; bool use_def_vals = riscv_cpu_is_generic(cpu_obj); int i; @@ -758,13 +765,8 @@ static void riscv_cpu_add_misa_properties(Object *cpu_obj) NULL, (void *)misa_cfg); object_property_set_description(cpu_obj, name, desc); if (use_def_vals) { -if (misa_cfg->enabled) { -env->misa_ext |= bit; -env->misa_ext_mask |= bit; -} else { -env->misa_ext &= ~bit; -env->misa_ext_mask &= ~bit; -} +riscv_cpu_write_misa_bit(RISCV_CPU(cpu_obj), bit, + misa_cfg->enabled); Reviewed-by: LIU Zhiwei Zhiwei } } }
Re: [PATCH v3 6/6] target/riscv/tcg: handle profile MISA bits
On 2023/10/21 6:39, Daniel Henrique Barboza wrote: The profile support is handling multi-letter extensions only. Let's add support for MISA bits as well. We'll go through every known MISA bit. If the user set the bit, doesn't matter if to 'true' or 'false', ignore it. If the profile doesn't declare the bit as mandatory, ignore it. Otherwise, set or clear the bit in env->misa_ext and env->misa_ext_mask depending on whether the profile was set to 'true' or 'false'. Signed-off-by: Daniel Henrique Barboza --- target/riscv/tcg/tcg-cpu.c | 16 1 file changed, 16 insertions(+) diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c index ba11d0566d..73c7453af6 100644 --- a/target/riscv/tcg/tcg-cpu.c +++ b/target/riscv/tcg/tcg-cpu.c @@ -42,6 +42,12 @@ static bool cpu_cfg_ext_is_user_set(uint32_t ext_offset) GUINT_TO_POINTER(ext_offset)); } +static bool cpu_misa_ext_is_user_set(uint32_t misa_bit) +{ +return g_hash_table_contains(misa_ext_user_opts, + GUINT_TO_POINTER(misa_bit)); +} + static void riscv_cpu_write_misa_bit(RISCVCPU *cpu, uint32_t bit, bool enabled) { @@ -797,6 +803,16 @@ static void cpu_set_profile(Object *obj, Visitor *v, const char *name, profile->enabled = value; +for (i = 0; misa_bits[i] != 0; i++) { +uint32_t bit = misa_bits[i]; + +if (cpu_misa_ext_is_user_set(bit) || !(profile->misa_ext & bit)) { +continue; +} + +riscv_cpu_write_misa_bit(cpu, bit, profile->enabled); +} + Reviewed-by: LIU Zhiwei Zhiwei for (i = 0; profile->ext_offsets[i] != RISCV_PROFILE_EXT_LIST_END; i++) { ext_offset = profile->ext_offsets[i];
Re: [PATCH v3 4/6] target/riscv/tcg: add MISA user options hash
On 2023/10/21 6:39, Daniel Henrique Barboza wrote: We already track user choice for multi-letter extensions because we needed to honor user choice when enabling/disabling extensions during realize(). We refrained from adding the same mechanism for MISA extensions since we didn't need it. Profile support requires tne need to check for user choice for MISA extensions, so let's add the corresponding hash now. It works like the existing multi-letter hash (multi_ext_user_opts) but tracking MISA bits options in the cpu_set_misa_ext_cfg() callback. Note that we can't re-use the same hash from multi-letter extensions because that hash uses cpu->cfg offsets as keys, while for MISA extensions we're using MISA bits as keys. After adding the user hash in cpu_set_misa_ext_cfg(), setting default values with object_property_set_bool() in add_misa_properties() will end up marking the user choice hash with them. Set the default value manually to avoid it. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Alistair Francis --- target/riscv/tcg/tcg-cpu.c | 15 ++- 1 file changed, 14 insertions(+), 1 deletion(-) diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c index 3dd4783191..59b75a14ac 100644 --- a/target/riscv/tcg/tcg-cpu.c +++ b/target/riscv/tcg/tcg-cpu.c @@ -34,6 +34,7 @@ /* Hash that stores user set extensions */ static GHashTable *multi_ext_user_opts; +static GHashTable *misa_ext_user_opts; static bool cpu_cfg_ext_is_user_set(uint32_t ext_offset) { @@ -669,6 +670,10 @@ static void cpu_set_misa_ext_cfg(Object *obj, Visitor *v, const char *name, return; } +g_hash_table_insert(misa_ext_user_opts, +GUINT_TO_POINTER(misa_bit), +(gpointer)value); + prev_val = env->misa_ext & misa_bit; if (value == prev_val) { @@ -732,6 +737,7 @@ static const RISCVCPUMisaExtConfig misa_ext_cfgs[] = { */ static void riscv_cpu_add_misa_properties(Object *cpu_obj) { +CPURISCVState *env = _CPU(cpu_obj)->env; bool use_def_vals = riscv_cpu_is_generic(cpu_obj); int i; @@ -752,7 +758,13 @@ static void riscv_cpu_add_misa_properties(Object *cpu_obj) NULL, (void *)misa_cfg); object_property_set_description(cpu_obj, name, desc); if (use_def_vals) { -object_property_set_bool(cpu_obj, name, misa_cfg->enabled, NULL); +if (misa_cfg->enabled) { +env->misa_ext |= bit; +env->misa_ext_mask |= bit; +} else { +env->misa_ext &= ~bit; +env->misa_ext_mask &= ~bit; +} } } } @@ -989,6 +1001,7 @@ static void tcg_cpu_instance_init(CPUState *cs) RISCVCPU *cpu = RISCV_CPU(cs); Object *obj = OBJECT(cpu); +misa_ext_user_opts = g_hash_table_new(NULL, g_direct_equal); Reviewed-by: LIU Zhiwei Zhiwei multi_ext_user_opts = g_hash_table_new(NULL, g_direct_equal); riscv_cpu_add_user_properties(obj);
Re: [PATCH v3 3/6] target/riscv/tcg: add user flag for profile support
On 2023/10/21 6:39, Daniel Henrique Barboza wrote: The TCG emulation implements all the extensions described in the RVA22U64 profile, both mandatory and optional. The mandatory extensions will be enabled via the profile flag. We'll leave the optional extensions to be enabled by hand. Given that this is the first profile we're implementing in TCG we'll need some ground work first: - all profiles declared in riscv_profiles[] will be exposed to users. TCG is the main accelerator we're considering when adding profile support in QEMU, so for now it's safe to assume that all profiles in riscv_profiles[] will be relevant to TCG; - we'll not support user profile settings for vendor CPUs. The flags will still be exposed but users won't be able to change them. The idea is that vendor CPUs in the future can enable profiles internally in their cpu_init() functions, showing to the external world that the CPU supports a certain profile. But users won't be able to enable/disable it; - Setting a profile to 'true' means 'enable all mandatory extensions of this profile, setting it to 'false' means disabling all its mandatory extensions. Disabling a profile is discouraged for regular use and will issue an user warning. User choices for individual extensions will take precedence, i.e. enabling a profile will not enable extensions that the user set to 'false', and vice-versa. This will make us independent of left-to-right ordering in the QEMU command line, i.e. the following QEMU command lines: -cpu rv64,zicbom=false,rva22u64=true,Zifencei=false -cpu rv64,zicbom=false,Zifencei=false,rva22u64=true -cpu rv64,rva22u64=true,zicbom=false,Zifencei=false They mean the same thing: "enable all mandatory extensions of the rva22u64 profile while keeping zicbom and Zifencei disabled". For now we'll handle multi-letter extensions only. MISA extensions need additional steps that we'll take care later. Signed-off-by: Daniel Henrique Barboza --- target/riscv/tcg/tcg-cpu.c | 59 ++ 1 file changed, 59 insertions(+) diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c index 7a4400e2ba..3dd4783191 100644 --- a/target/riscv/tcg/tcg-cpu.c +++ b/target/riscv/tcg/tcg-cpu.c @@ -757,6 +757,63 @@ static void riscv_cpu_add_misa_properties(Object *cpu_obj) } } +static void cpu_set_profile(Object *obj, Visitor *v, const char *name, +void *opaque, Error **errp) +{ +RISCVCPUProfile *profile = opaque; +RISCVCPU *cpu = RISCV_CPU(obj); +bool value; +int i, ext_offset; + +if (object_dynamic_cast(obj, TYPE_RISCV_DYNAMIC_CPU) == NULL) { +error_setg(errp, "Profile %s only available for generic CPUs", + profile->name); +return; +} + +if (!visit_type_bool(v, name, , errp)) { +return; +} + +if (!value) { +warn_report("Disabling the '%s' profile is a debug/development " +"tool, not recommended for regular use", +profile->name); +} + +profile->enabled = value; + +for (i = 0; profile->ext_offsets[i] != RISCV_PROFILE_EXT_LIST_END; i++) { +ext_offset = profile->ext_offsets[i]; + +if (cpu_cfg_ext_is_user_set(ext_offset)) { +continue; +} + +isa_ext_update_enabled(cpu, ext_offset, profile->enabled); +} +} + +static void cpu_get_profile(Object *obj, Visitor *v, const char *name, +void *opaque, Error **errp) +{ +RISCVCPUProfile *profile = opaque; +bool value = profile->enabled; + +visit_type_bool(v, name, , errp); +} + +static void riscv_cpu_add_profiles(Object *cpu_obj) +{ +for (int i = 0; riscv_profiles[i] != NULL; i++) { +const RISCVCPUProfile *profile = riscv_profiles[i]; + +object_property_add(cpu_obj, profile->name, "bool", +cpu_get_profile, cpu_set_profile, +NULL, (void *)profile); +} +} + static bool cpu_ext_is_deprecated(const char *ext_name) { return isupper(ext_name[0]); @@ -880,6 +937,8 @@ static void riscv_cpu_add_user_properties(Object *obj) riscv_cpu_add_multiext_prop_array(obj, riscv_cpu_deprecated_exts); +riscv_cpu_add_profiles(obj); + Acked-by: LIU Zhiwei Zhiwei for (Property *prop = riscv_cpu_options; prop && prop->name; prop++) { qdev_property_add_static(DEVICE(obj), prop); }
Re: [PATCH v3 2/6] target/riscv/kvm: add 'rva22u64' flag as unavailable
On 2023/10/21 6:39, Daniel Henrique Barboza wrote: KVM does not have the means to support enabling the rva22u64 profile. The main reasons are: - we're missing support for some mandatory rva22u64 extensions in the KVM module; - we can't make promises about enabling a profile since it all depends on host support in the end. We'll revisit this decision in the future if needed. For now mark the 'rva22u64' profile as unavailable when running a KVM CPU: $ qemu-system-riscv64 -machine virt,accel=kvm -cpu rv64,rva22u64=true qemu-system-riscv64: can't apply global rv64-riscv-cpu.rva22u64=true: 'rva22u64' is not available with KVM Signed-off-by: Daniel Henrique Barboza Reviewed-by: Alistair Francis --- target/riscv/kvm/kvm-cpu.c | 7 ++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c index 5246fc2bdc..dc14c54ce4 100644 --- a/target/riscv/kvm/kvm-cpu.c +++ b/target/riscv/kvm/kvm-cpu.c @@ -360,7 +360,7 @@ static void cpu_set_cfg_unavailable(Object *obj, Visitor *v, } if (value) { -error_setg(errp, "extension %s is not available with KVM", +error_setg(errp, "'%s' is not available with KVM", propname); } } @@ -440,6 +440,11 @@ static void kvm_riscv_add_cpu_user_properties(Object *cpu_obj) riscv_cpu_add_kvm_unavail_prop_array(cpu_obj, riscv_cpu_extensions); riscv_cpu_add_kvm_unavail_prop_array(cpu_obj, riscv_cpu_vendor_exts); riscv_cpu_add_kvm_unavail_prop_array(cpu_obj, riscv_cpu_experimental_exts); + + /* We don't have the needed KVM support for profiles */ +for (i = 0; riscv_profiles[i] != NULL; i++) { +riscv_cpu_add_kvm_unavail_prop(cpu_obj, riscv_profiles[i]->name); + } Reviewed-by: LIU Zhiwei Zhiwei } static int kvm_riscv_get_regs_core(CPUState *cs)
Re: [PATCH v3 1/6] target/riscv: add rva22u64 profile definition
On 2023/10/21 6:39, Daniel Henrique Barboza wrote: The rva22U64 profile, described in: https://github.com/riscv/riscv-profiles/blob/main/profiles.adoc#rva22-profiles Contains a set of CPU extensions aimed for 64-bit userspace applications. Enabling this set to be enabled via a single user flag makes it convenient to enable a predictable set of features for the CPU, giving users more predicability when running/testing their workloads. QEMU implements all possible extensions of this profile. The exception is Zicbop (Cache-Block Prefetch Operations) that is not available since QEMU RISC-V does not implement a cache model. For this same reason all the so called 'synthetic extensions' described in the profile that are cache related are ignored (Za64rs, Zic64b, Ziccif, Ziccrse, Ziccamoa, Zicclsm). An abstraction called RISCVCPUProfile is created to store the profile. 'ext_offsets' contains mandatory extensions that QEMU supports. Same thing with the 'misa_ext' mask. Optional extensions must be enabled manually in the command line if desired. The design here is to use the common target/riscv/cpu.c file to store the profile declaration and export it to the accelerator files. Each accelerator is then responsible to expose it (or not) to users and how to enable the extensions. Next patches will implement the profile for TCG and KVM. Signed-off-by: Daniel Henrique Barboza Acked-by: Alistair Francis --- target/riscv/cpu.c | 20 target/riscv/cpu.h | 12 2 files changed, 32 insertions(+) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index c64cd726f4..1b75b506c4 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -1397,6 +1397,26 @@ Property riscv_cpu_options[] = { DEFINE_PROP_END_OF_LIST(), }; +/* Optional extensions left out: RVV, zfh, zkn, zks */ +static RISCVCPUProfile RVA22U64 = { +.name = "rva22u64", +.misa_ext = RVM | RVA | RVF | RVD | RVC, Why not include RVI? Zhiwei +.ext_offsets = { +CPU_CFG_OFFSET(ext_zicsr), CPU_CFG_OFFSET(ext_zihintpause), +CPU_CFG_OFFSET(ext_zba), CPU_CFG_OFFSET(ext_zbb), +CPU_CFG_OFFSET(ext_zbs), CPU_CFG_OFFSET(ext_zfhmin), +CPU_CFG_OFFSET(ext_zkt), CPU_CFG_OFFSET(ext_zicntr), +CPU_CFG_OFFSET(ext_zihpm), CPU_CFG_OFFSET(ext_zicbom), +CPU_CFG_OFFSET(ext_zicboz), + +RISCV_PROFILE_EXT_LIST_END +} +}; + +RISCVCPUProfile *riscv_profiles[] = { +, NULL, +}; + static Property riscv_cpu_properties[] = { DEFINE_PROP_BOOL("debug", RISCVCPU, cfg.debug, true), diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 7f61e17202..53c1970e0a 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -66,6 +66,18 @@ const char *riscv_get_misa_ext_description(uint32_t bit); #define CPU_CFG_OFFSET(_prop) offsetof(struct RISCVCPUConfig, _prop) +typedef struct riscv_cpu_profile { +const char *name; +uint32_t misa_ext; +bool enabled; +bool user_set; +const int32_t ext_offsets[]; +} RISCVCPUProfile; + +#define RISCV_PROFILE_EXT_LIST_END -1 + +extern RISCVCPUProfile *riscv_profiles[]; + /* Privileged specification version */ enum { PRIV_VERSION_1_10_0 = 0,
Re: [PATCH 0/6] hw/ppc: SysBus simplifications
On 2023/10/18 21:30, Philippe Mathieu-Daudé wrote: Hi, There is no point in exposing an internal MMIO region via SysBus and directly mapping it in the very same device. This series replaces a sequence of: - sysbus_init_mmio() - sysbus_mmio_map() by a single call to memory_region_add_subregion(). Reviewed-by: LIU Zhiwei Zhiwei Philippe Mathieu-Daudé (6): hw/ppc/pnv_xscom: Rename pnv_xscom_realize(Error **) -> pnv_xscom_init() hw/ppc/pnv_xscom: Move sysbus_mmio_map() call within pnv_xscom_init() hw/ppc/pnv_xscom: Do not use SysBus API to map local MMIO region hw/ppc/pnv: Do not use SysBus API to map local MMIO region hw/intc/spapr_xive: Move sysbus_init_mmio() calls around hw/intc/spapr_xive: Do not use SysBus API to map local MMIO region include/hw/ppc/pnv_xscom.h | 2 +- hw/intc/spapr_xive.c | 12 ++-- hw/ppc/pnv.c | 26 +- hw/ppc/pnv_xscom.c | 5 ++--- 4 files changed, 14 insertions(+), 31 deletions(-)
Re: [PATCH v4 3/5] target/riscv: Move misa_mxl_max to class
On 2023/10/18 2:53, Akihiko Odaki wrote: misa_mxl_max is common for all instances of a RISC-V CPU class so they are better put into class. Signed-off-by: Akihiko Odaki --- target/riscv/cpu-qom.h | 1 + target/riscv/cpu.h | 3 +- hw/riscv/boot.c| 2 +- target/riscv/cpu.c | 118 +++-- target/riscv/gdbstub.c | 12 ++-- target/riscv/kvm/kvm-cpu.c | 10 ++-- target/riscv/machine.c | 7 +-- target/riscv/tcg/tcg-cpu.c | 12 ++-- target/riscv/translate.c | 3 +- 9 files changed, 88 insertions(+), 80 deletions(-) diff --git a/target/riscv/cpu-qom.h b/target/riscv/cpu-qom.h index f3fbe37a2c..33b6d52c90 100644 --- a/target/riscv/cpu-qom.h +++ b/target/riscv/cpu-qom.h @@ -68,5 +68,6 @@ struct RISCVCPUClass { /*< public >*/ DeviceRealize parent_realize; ResettablePhases parent_phases; +uint32_t misa_mxl_max; /* max mxl for this cpu */ }; #endif /* RISCV_CPU_QOM_H */ diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index f8ffa5ee38..ef10efd1e7 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -159,7 +159,6 @@ struct CPUArchState { /* RISCVMXL, but uint32_t for vmstate migration */ uint32_t misa_mxl; /* current mxl */ -uint32_t misa_mxl_max; /* max mxl for this cpu */ uint32_t misa_ext; /* current extensions */ uint32_t misa_ext_mask; /* max ext for this cpu */ uint32_t xl;/* current xlen */ @@ -711,7 +710,7 @@ enum riscv_pmu_event_idx { /* used by tcg/tcg-cpu.c*/ void isa_ext_update_enabled(RISCVCPU *cpu, uint32_t ext_offset, bool en); bool isa_ext_is_enabled(RISCVCPU *cpu, uint32_t ext_offset); -void riscv_cpu_set_misa(CPURISCVState *env, RISCVMXL mxl, uint32_t ext); +void riscv_cpu_set_misa_ext(CPURISCVState *env, uint32_t ext); typedef struct RISCVCPUMultiExtConfig { const char *name; diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c index 52bf8e67de..b7cf08f479 100644 --- a/hw/riscv/boot.c +++ b/hw/riscv/boot.c @@ -36,7 +36,7 @@ bool riscv_is_32bit(RISCVHartArrayState *harts) { -return harts->harts[0].env.misa_mxl_max == MXL_RV32; +return RISCV_CPU_GET_CLASS(>harts[0])->misa_mxl_max == MXL_RV32; Hi Akihiko, Can we use the cached CPUClass in CPUState? Like (RISCVCPUClass *)((CPUState *)(>harts[0])->cc) Zhiwei } /* diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index ac4a6c7eec..1fb5747f00 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -263,9 +263,8 @@ const char *riscv_cpu_get_trap_name(target_ulong cause, bool async) } } -void riscv_cpu_set_misa(CPURISCVState *env, RISCVMXL mxl, uint32_t ext) +void riscv_cpu_set_misa_ext(CPURISCVState *env, uint32_t ext) { -env->misa_mxl_max = env->misa_mxl = mxl; env->misa_ext_mask = env->misa_ext = ext; } @@ -367,11 +366,7 @@ static void riscv_any_cpu_init(Object *obj) { RISCVCPU *cpu = RISCV_CPU(obj); CPURISCVState *env = >env; -#if defined(TARGET_RISCV32) -riscv_cpu_set_misa(env, MXL_RV32, RVI | RVM | RVA | RVF | RVD | RVC | RVU); -#elif defined(TARGET_RISCV64) -riscv_cpu_set_misa(env, MXL_RV64, RVI | RVM | RVA | RVF | RVD | RVC | RVU); -#endif +riscv_cpu_set_misa_ext(env, RVI | RVM | RVA | RVF | RVD | RVC | RVU); #ifndef CONFIG_USER_ONLY set_satp_mode_max_supported(RISCV_CPU(obj), @@ -392,16 +387,14 @@ static void riscv_max_cpu_init(Object *obj) { RISCVCPU *cpu = RISCV_CPU(obj); CPURISCVState *env = >env; -RISCVMXL mlx = MXL_RV64; -#ifdef TARGET_RISCV32 -mlx = MXL_RV32; -#endif -riscv_cpu_set_misa(env, mlx, 0); env->priv_ver = PRIV_VERSION_LATEST; #ifndef CONFIG_USER_ONLY -set_satp_mode_max_supported(RISCV_CPU(obj), mlx == MXL_RV32 ? -VM_1_10_SV32 : VM_1_10_SV57); +#ifdef TARGET_RISCV32 +set_satp_mode_max_supported(cpu, VM_1_10_SV32); +#else +set_satp_mode_max_supported(cpu, VM_1_10_SV57); +#endif #endif } @@ -409,8 +402,6 @@ static void riscv_max_cpu_init(Object *obj) static void rv64_base_cpu_init(Object *obj) { CPURISCVState *env = _CPU(obj)->env; -/* We set this in the realise function */ -riscv_cpu_set_misa(env, MXL_RV64, 0); /* Set latest version of privileged specification */ env->priv_ver = PRIV_VERSION_LATEST; #ifndef CONFIG_USER_ONLY @@ -422,8 +413,7 @@ static void rv64_sifive_u_cpu_init(Object *obj) { RISCVCPU *cpu = RISCV_CPU(obj); CPURISCVState *env = >env; -riscv_cpu_set_misa(env, MXL_RV64, - RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU); +riscv_cpu_set_misa_ext(env, RVI | RVM | RVA | RVF | RVD | RVC | RVS | RVU); env->priv_ver = PRIV_VERSION_1_10_0; #ifndef CONFIG_USER_ONLY set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV39); @@ -441,7 +431,7 @@ static void rv64_sifive_e_cpu_init(Object *obj) CPURISCVState *env = _CPU(obj)->env;
Re: [PATCH v4 2/5] target/riscv: Remove misa_mxl validation
On 2023/10/18 2:53, Akihiko Odaki wrote: It is initialized with a simple assignment and there is little room for error. In fact, the validation is even more complex. Signed-off-by: Akihiko Odaki --- target/riscv/tcg/tcg-cpu.c | 13 ++--- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c index a28918ab30..7f45e42000 100644 --- a/target/riscv/tcg/tcg-cpu.c +++ b/target/riscv/tcg/tcg-cpu.c @@ -148,7 +148,7 @@ static void riscv_cpu_validate_misa_priv(CPURISCVState *env, Error **errp) } } -static void riscv_cpu_validate_misa_mxl(RISCVCPU *cpu, Error **errp) +static void riscv_cpu_validate_misa_mxl(RISCVCPU *cpu) { RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(cpu); CPUClass *cc = CPU_CLASS(mcc); @@ -168,11 +168,6 @@ static void riscv_cpu_validate_misa_mxl(RISCVCPU *cpu, Error **errp) default: g_assert_not_reached(); } - -if (env->misa_mxl_max != env->misa_mxl) { -error_setg(errp, "misa_mxl_max must be equal to misa_mxl"); -return; -} } static void riscv_cpu_validate_priv_spec(RISCVCPU *cpu, Error **errp) @@ -573,11 +568,7 @@ static bool tcg_cpu_realize(CPUState *cs, Error **errp) return false; } -riscv_cpu_validate_misa_mxl(cpu, _err); -if (local_err != NULL) { -error_propagate(errp, local_err); -return false; -} +riscv_cpu_validate_misa_mxl(cpu); Acked-by: LIU Zhiwei Zhiwei riscv_cpu_validate_priv_spec(cpu, _err); if (local_err != NULL) {
Re: [PATCH 1/4] target/riscv: Remove misa_mxl validation
+CC Richard On 2023/10/17 11:37, Akihiko Odaki wrote: On 2023/10/17 11:29, LIU Zhiwei wrote: On 2023/10/12 13:42, Akihiko Odaki wrote: It is initialized with a simple assignment and there is little room for error. In fact, the validation is even more complex. Signed-off-by: Akihiko Odaki --- target/riscv/cpu.c | 13 ++--- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index f5572704de..550b357fb7 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -1042,7 +1042,7 @@ static void riscv_cpu_disable_priv_spec_isa_exts(RISCVCPU *cpu) } } -static void riscv_cpu_validate_misa_mxl(RISCVCPU *cpu, Error **errp) +static void riscv_cpu_validate_misa_mxl(RISCVCPU *cpu) { RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(cpu); CPUClass *cc = CPU_CLASS(mcc); @@ -1062,11 +1062,6 @@ static void riscv_cpu_validate_misa_mxl(RISCVCPU *cpu, Error **errp) default: g_assert_not_reached(); } - - if (env->misa_mxl_max != env->misa_mxl) { - error_setg(errp, "misa_mxl_max must be equal to misa_mxl"); - return; - } } /* @@ -1447,11 +1442,7 @@ static void riscv_cpu_realize_tcg(DeviceState *dev, Error **errp) return; } - riscv_cpu_validate_misa_mxl(cpu, _err); - if (local_err != NULL) { - error_propagate(errp, local_err); - return; - } + riscv_cpu_validate_misa_mxl(cpu); This it not right. As we are still working on the supporting for MXL32 or SXL32, this validation is needed. It's not preventing supporting MXL32 or SXL32. It's removing env->misa_mxl_max != env->misa_mxl just because it's initialized with a simple statement: env->misa_mxl_max = env->misa_mxl = mxl; It makes little sense to have a validation code that is more complex than the validated code. And we can't ensure the all RISC-V cpus have the same misa_mxl_max or misa_mxl, it is not right to move it to class. For example, in the future, riscv64-softmmu can run 32-bit cpu and 64-bit cpu. And maybe in heterogeneous SOC, we have 32-bit cpu and 64-bit cpu together. This patch series does not touch misa_mxl. We don't need to ensure that all CPUs have the same misa_mxl_max, but we just need to ensure that CPUs in the same class do. Creating a heterogeneous SoC is still possible by combining e.g. TYPE_RISCV_CPU_SIFIVE_E31 and TYPE_RISCV_CPU_SIFIVE_E51, for example. I see what you mean. It makes sense to move the misa_mxl_max field from env to the class struct. The misa_mxl_max is always be set by cpu init or the migration. The former is OK. I don't know whether QEMU supports migration from 32-bit CPU to 64-bit CPU. Otherwise, Acked-by: LIU Zhiwei Zhiwei
Re: [PATCH v2 1/3] target/riscv: Do not allow MXL_RV32 for TARGET_RISCV64
On 2023/10/17 11:32, Alistair Francis wrote: On Tue, Oct 17, 2023 at 12:14 PM LIU Zhiwei wrote: On 2023/10/16 9:51, Alistair Francis wrote: On Sun, Oct 15, 2023 at 4:05 AM Daniel Henrique Barboza wrote: On 10/14/23 00:35, Akihiko Odaki wrote: TARGET_RISCV64 does not have riscv-32bit-cpu.xml so it shouldn't accept MXL_RV32. Signed-off-by: Akihiko Odaki --- Reviewed-by: Daniel Henrique Barboza target/riscv/tcg/tcg-cpu.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c index a28918ab30..e0cbc56320 100644 --- a/target/riscv/tcg/tcg-cpu.c +++ b/target/riscv/tcg/tcg-cpu.c @@ -161,10 +161,11 @@ static void riscv_cpu_validate_misa_mxl(RISCVCPU *cpu, Error **errp) case MXL_RV128: cc->gdb_core_xml_file = "riscv-64bit-cpu.xml"; break; -#endif +#elif defined(TARGET_RISCV32) case MXL_RV32: cc->gdb_core_xml_file = "riscv-32bit-cpu.xml"; break; +#endif This isn't the right fix. The idea is that riscv64-softmmu can run 32-bit CPUs, so we instead should include riscv-32bit-cpu.xml Agree. I'd like to go on the work. The question is that we don't have 64-bit OpenSBI which supports booting 32-bit Linux. So even we have implemented the SXLEN 32bit, we may not have the software to test it. Ah! So I was first talking around just a full 32-bit CPU. So for example: qemu-system-riscv64 -machine opentitan So we are using qemu-system-riscv64 to run a 32-bit only CPU. Yes, if the 32-bit only cpu only has M mode, it can work now. I have tried this for Xuantie E series cpu, for example the e902, in the wild tree. Then we can think about SXLEN Agree, maybe we can expose these cpus now. Thanks, Zhiwei Do you support the SXL upstreaming with no testing? No, it should be tested Alistair Thanks, Zhiwei Alistair default: g_assert_not_reached(); }
Re: [PATCH 1/4] target/riscv: Remove misa_mxl validation
On 2023/10/12 13:42, Akihiko Odaki wrote: It is initialized with a simple assignment and there is little room for error. In fact, the validation is even more complex. Signed-off-by: Akihiko Odaki --- target/riscv/cpu.c | 13 ++--- 1 file changed, 2 insertions(+), 11 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index f5572704de..550b357fb7 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -1042,7 +1042,7 @@ static void riscv_cpu_disable_priv_spec_isa_exts(RISCVCPU *cpu) } } -static void riscv_cpu_validate_misa_mxl(RISCVCPU *cpu, Error **errp) +static void riscv_cpu_validate_misa_mxl(RISCVCPU *cpu) { RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(cpu); CPUClass *cc = CPU_CLASS(mcc); @@ -1062,11 +1062,6 @@ static void riscv_cpu_validate_misa_mxl(RISCVCPU *cpu, Error **errp) default: g_assert_not_reached(); } - -if (env->misa_mxl_max != env->misa_mxl) { -error_setg(errp, "misa_mxl_max must be equal to misa_mxl"); -return; -} } /* @@ -1447,11 +1442,7 @@ static void riscv_cpu_realize_tcg(DeviceState *dev, Error **errp) return; } -riscv_cpu_validate_misa_mxl(cpu, _err); -if (local_err != NULL) { -error_propagate(errp, local_err); -return; -} +riscv_cpu_validate_misa_mxl(cpu); This it not right. As we are still working on the supporting for MXL32 or SXL32, this validation is needed. And we can't ensure the all RISC-V cpus have the same misa_mxl_max or misa_mxl, it is not right to move it to class. For example, in the future, riscv64-softmmu can run 32-bit cpu and 64-bit cpu. And maybe in heterogeneous SOC, we have 32-bit cpu and 64-bit cpu together. I am afraid that we can not accept this patch set. Thanks, Zhiwei riscv_cpu_validate_priv_spec(cpu, _err); if (local_err != NULL) {
Re: [PATCH v2 1/3] target/riscv: Do not allow MXL_RV32 for TARGET_RISCV64
On 2023/10/16 9:51, Alistair Francis wrote: On Sun, Oct 15, 2023 at 4:05 AM Daniel Henrique Barboza wrote: On 10/14/23 00:35, Akihiko Odaki wrote: TARGET_RISCV64 does not have riscv-32bit-cpu.xml so it shouldn't accept MXL_RV32. Signed-off-by: Akihiko Odaki --- Reviewed-by: Daniel Henrique Barboza target/riscv/tcg/tcg-cpu.c | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c index a28918ab30..e0cbc56320 100644 --- a/target/riscv/tcg/tcg-cpu.c +++ b/target/riscv/tcg/tcg-cpu.c @@ -161,10 +161,11 @@ static void riscv_cpu_validate_misa_mxl(RISCVCPU *cpu, Error **errp) case MXL_RV128: cc->gdb_core_xml_file = "riscv-64bit-cpu.xml"; break; -#endif +#elif defined(TARGET_RISCV32) case MXL_RV32: cc->gdb_core_xml_file = "riscv-32bit-cpu.xml"; break; +#endif This isn't the right fix. The idea is that riscv64-softmmu can run 32-bit CPUs, so we instead should include riscv-32bit-cpu.xml Agree. I'd like to go on the work. The question is that we don't have 64-bit OpenSBI which supports booting 32-bit Linux. So even we have implemented the SXLEN 32bit, we may not have the software to test it. Do you support the SXL upstreaming with no testing? Thanks, Zhiwei Alistair default: g_assert_not_reached(); }
Re: [PATCH 2/6] target/riscv: Use env_archcpu() in [check_]nanbox()
On 2023/10/13 0:06, Richard Henderson wrote: On 10/11/23 22:59, LIU Zhiwei wrote: On 2023/10/11 13:31, Philippe Mathieu-Daudé wrote: On 11/10/23 05:25, LIU Zhiwei wrote: On 2023/10/11 1:04, Richard Henderson wrote: On 10/9/23 05:42, LIU Zhiwei wrote: On 2023/10/9 19:02, Philippe Mathieu-Daudé wrote: When CPUArchState* is available (here CPURISCVState*), we can use the fast env_archcpu() macro to get ArchCPU* (here RISCVCPU*). The QOM cast RISCV_CPU() macro will be slower when building with --enable-qom-cast-debug. If so, maybe we have to do this qom cast somewhere. No, I don't think so. Or at least not in these places. Yes. Perhaps, we should remove all RISCV_CPU macros using after the qom objects realized. Do you think we should remove the RISCV_CPU using in riscv_cpu_exec_interrupt? Although it is not so hot. I think there is no reason to use it there. I have some note in my TODO to check replacing CPUState by ArchCPU in TCGCPUOps (like the cpu_exec_interrupt handler you mentioned). IMHO, this will make it harder for heterogeneous SOC support. ArchCPU is not a target agnostic struct. ArchCPU is a target-agnostic typedef of a structure with no visible definition. C is perfectly happy to manipulate pointers to such structures. Get it. Thanks Whether it is worthwhile to adjust interfaces from CPUState to ArchCPU, I don't know. OK. Let's just wait for a good reason to do that. Zhiwei r~
Re: [PATCH v2 5/6] target/riscv: Add "pmu-mask" property to replace "pmu-num"
On 2023/10/12 20:38, Rob Bradford wrote: On Thu, 2023-10-12 at 17:05 +0800, LIU Zhiwei wrote: On 2023/10/11 22:45, Rob Bradford wrote: Using a mask instead of the number of PMU devices supports the accurate emulation of platforms that have a discontinuous set of PMU counters. Generate a warning if the old property changed from the default but still go ahead and use it to generate the mask if the user has changed it from the default Signed-off-by: Rob Bradford --- target/riscv/cpu.c | 5 +++-- target/riscv/cpu_cfg.h | 3 ++- target/riscv/machine.c | 2 +- target/riscv/pmu.c | 14 ++ 4 files changed, 16 insertions(+), 8 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index c9d8fc12fe..4d2987e568 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -1487,7 +1487,7 @@ static void riscv_cpu_realize_tcg(DeviceState *dev, Error **errp) riscv_timer_init(cpu); } -if (cpu->cfg.pmu_num) { +if (cpu->cfg.pmu_mask) { riscv_pmu_init(cpu, _err); if (local_err != NULL) { error_propagate(errp, local_err); @@ -1812,7 +1812,8 @@ static void riscv_cpu_add_misa_properties(Object *cpu_obj) static Property riscv_cpu_extensions[] = { /* Defaults for standard extensions */ -DEFINE_PROP_UINT8("pmu-num", RISCVCPU, cfg.pmu_num, 16), +DEFINE_PROP_UINT8("pmu-num", RISCVCPU, cfg.pmu_num, 16), /* Deprecated */ +DEFINE_PROP_UINT32("pmu-mask", RISCVCPU, cfg.pmu_mask, MAKE_32BIT_MASK(3, 16)), DEFINE_PROP_BOOL("sscofpmf", RISCVCPU, cfg.ext_sscofpmf, false), DEFINE_PROP_BOOL("Zifencei", RISCVCPU, cfg.ext_ifencei, true), DEFINE_PROP_BOOL("Zicsr", RISCVCPU, cfg.ext_icsr, true), diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h index 0e6a0f245c..d273487040 100644 --- a/target/riscv/cpu_cfg.h +++ b/target/riscv/cpu_cfg.h @@ -123,7 +123,8 @@ struct RISCVCPUConfig { bool ext_xtheadsync; bool ext_XVentanaCondOps; -uint8_t pmu_num; +uint8_t pmu_num; /* Deprecated */ +uint32_t pmu_mask; char *priv_spec; char *user_spec; char *bext_spec; diff --git a/target/riscv/machine.c b/target/riscv/machine.c index c7c862cdd3..9f6e3f7a6d 100644 --- a/target/riscv/machine.c +++ b/target/riscv/machine.c @@ -313,7 +313,7 @@ static bool pmu_needed(void *opaque) { RISCVCPU *cpu = opaque; -return cpu->cfg.pmu_num; +return (cpu->cfg.pmu_mask > 0); } static const VMStateDescription vmstate_pmu_ctr_state = { diff --git a/target/riscv/pmu.c b/target/riscv/pmu.c index 360c76f63e..f2d35b4d3b 100644 --- a/target/riscv/pmu.c +++ b/target/riscv/pmu.c @@ -18,6 +18,7 @@ #include "qemu/osdep.h" #include "qemu/log.h" +#include "qemu/error-report.h" #include "cpu.h" #include "pmu.h" #include "sysemu/cpu-timers.h" @@ -182,7 +183,7 @@ int riscv_pmu_incr_ctr(RISCVCPU *cpu, enum riscv_pmu_event_idx event_idx) CPURISCVState *env = >env; gpointer value; -if (!cpu->cfg.pmu_num) { +if (!cpu->cfg.pmu_mask) { return 0; } value = g_hash_table_lookup(cpu->pmu_event_ctr_map, @@ -432,7 +433,7 @@ void riscv_pmu_init(RISCVCPU *cpu, Error **errp) { uint8_t pmu_num = cpu->cfg.pmu_num; -if (pmu_num > (RV_MAX_MHPMCOUNTERS - 3)) { +if (ctpop32(cpu->cfg.pmu_mask) > (RV_MAX_MHPMCOUNTERS - 3)) { error_setg(errp, "Number of counters exceeds maximum available"); return; } @@ -443,6 +444,11 @@ void riscv_pmu_init(RISCVCPU *cpu, Error **errp) return; } -/* Create a bitmask of available programmable counters */ -cpu->pmu_avail_ctrs = MAKE_32BIT_MASK(3, pmu_num); +/* Check if user set it by comparing against default */ +if (pmu_num != 16) { +warn_report("\"pmu-num\" property is deprecated; use \"pmu-mask\""); +cpu->cfg.pmu_mask = MAKE_32BIT_MASK(3, pmu_num); +} + +cpu->pmu_avail_ctrs = cpu->cfg.pmu_mask; How to process the pmu_mask[0:2] no-zero bits? They should not included into pmu_avail_ctrs. Good point, thanks Zhiwei. I think rather than masking those bits it is better to add a check and error out if those bits are set. Agree. Thanks, Zhiwei Cheers, Rob Zhiwei }
Re: [PATCH v2 6/6] docs/about/deprecated: Document RISC-V "pmu-num" deprecation
On 2023/10/11 22:45, Rob Bradford wrote: This has been replaced by a "pmu-mask" property that provides much more flexibility. Signed-off-by: Rob Bradford --- docs/about/deprecated.rst | 10 ++ 1 file changed, 10 insertions(+) diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst index 8b136320e2..37f3414ef8 100644 --- a/docs/about/deprecated.rst +++ b/docs/about/deprecated.rst @@ -361,6 +361,16 @@ Specifying the iSCSI password in plain text on the command line using the used instead, to refer to a ``--object secret...`` instance that provides a password via a file, or encrypted. +CPU device properties +' + +``pmu-num=x`` on RISC-V CPUs (since 8.2) + + +In order to support more flexible counter configurations this has been +replaced by a ``pmu-mask`` property + + Acked-by: LIU Zhiwei Zhiwei Backwards compatibility ---
Re: [PATCH v2 5/6] target/riscv: Add "pmu-mask" property to replace "pmu-num"
On 2023/10/11 22:45, Rob Bradford wrote: Using a mask instead of the number of PMU devices supports the accurate emulation of platforms that have a discontinuous set of PMU counters. Generate a warning if the old property changed from the default but still go ahead and use it to generate the mask if the user has changed it from the default Signed-off-by: Rob Bradford --- target/riscv/cpu.c | 5 +++-- target/riscv/cpu_cfg.h | 3 ++- target/riscv/machine.c | 2 +- target/riscv/pmu.c | 14 ++ 4 files changed, 16 insertions(+), 8 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index c9d8fc12fe..4d2987e568 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -1487,7 +1487,7 @@ static void riscv_cpu_realize_tcg(DeviceState *dev, Error **errp) riscv_timer_init(cpu); } -if (cpu->cfg.pmu_num) { +if (cpu->cfg.pmu_mask) { riscv_pmu_init(cpu, _err); if (local_err != NULL) { error_propagate(errp, local_err); @@ -1812,7 +1812,8 @@ static void riscv_cpu_add_misa_properties(Object *cpu_obj) static Property riscv_cpu_extensions[] = { /* Defaults for standard extensions */ -DEFINE_PROP_UINT8("pmu-num", RISCVCPU, cfg.pmu_num, 16), +DEFINE_PROP_UINT8("pmu-num", RISCVCPU, cfg.pmu_num, 16), /* Deprecated */ +DEFINE_PROP_UINT32("pmu-mask", RISCVCPU, cfg.pmu_mask, MAKE_32BIT_MASK(3, 16)), DEFINE_PROP_BOOL("sscofpmf", RISCVCPU, cfg.ext_sscofpmf, false), DEFINE_PROP_BOOL("Zifencei", RISCVCPU, cfg.ext_ifencei, true), DEFINE_PROP_BOOL("Zicsr", RISCVCPU, cfg.ext_icsr, true), diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h index 0e6a0f245c..d273487040 100644 --- a/target/riscv/cpu_cfg.h +++ b/target/riscv/cpu_cfg.h @@ -123,7 +123,8 @@ struct RISCVCPUConfig { bool ext_xtheadsync; bool ext_XVentanaCondOps; -uint8_t pmu_num; +uint8_t pmu_num; /* Deprecated */ +uint32_t pmu_mask; char *priv_spec; char *user_spec; char *bext_spec; diff --git a/target/riscv/machine.c b/target/riscv/machine.c index c7c862cdd3..9f6e3f7a6d 100644 --- a/target/riscv/machine.c +++ b/target/riscv/machine.c @@ -313,7 +313,7 @@ static bool pmu_needed(void *opaque) { RISCVCPU *cpu = opaque; -return cpu->cfg.pmu_num; +return (cpu->cfg.pmu_mask > 0); } static const VMStateDescription vmstate_pmu_ctr_state = { diff --git a/target/riscv/pmu.c b/target/riscv/pmu.c index 360c76f63e..f2d35b4d3b 100644 --- a/target/riscv/pmu.c +++ b/target/riscv/pmu.c @@ -18,6 +18,7 @@ #include "qemu/osdep.h" #include "qemu/log.h" +#include "qemu/error-report.h" #include "cpu.h" #include "pmu.h" #include "sysemu/cpu-timers.h" @@ -182,7 +183,7 @@ int riscv_pmu_incr_ctr(RISCVCPU *cpu, enum riscv_pmu_event_idx event_idx) CPURISCVState *env = >env; gpointer value; -if (!cpu->cfg.pmu_num) { +if (!cpu->cfg.pmu_mask) { return 0; } value = g_hash_table_lookup(cpu->pmu_event_ctr_map, @@ -432,7 +433,7 @@ void riscv_pmu_init(RISCVCPU *cpu, Error **errp) { uint8_t pmu_num = cpu->cfg.pmu_num; -if (pmu_num > (RV_MAX_MHPMCOUNTERS - 3)) { +if (ctpop32(cpu->cfg.pmu_mask) > (RV_MAX_MHPMCOUNTERS - 3)) { error_setg(errp, "Number of counters exceeds maximum available"); return; } @@ -443,6 +444,11 @@ void riscv_pmu_init(RISCVCPU *cpu, Error **errp) return; } -/* Create a bitmask of available programmable counters */ -cpu->pmu_avail_ctrs = MAKE_32BIT_MASK(3, pmu_num); +/* Check if user set it by comparing against default */ +if (pmu_num != 16) { +warn_report("\"pmu-num\" property is deprecated; use \"pmu-mask\""); +cpu->cfg.pmu_mask = MAKE_32BIT_MASK(3, pmu_num); +} + +cpu->pmu_avail_ctrs = cpu->cfg.pmu_mask; How to process the pmu_mask[0:2] no-zero bits? They should not included into pmu_avail_ctrs. Zhiwei }
Re: [PATCH v2 4/6] qemu/bitops.h: Add MAKE_32BIT_MASK macro
On 2023/10/11 22:45, Rob Bradford wrote: Add 32-bit version of mask generating macro and use it in the RISC-V PMU code. CC Richard Signed-off-by: Rob Bradford --- include/qemu/bitops.h | 3 +++ target/riscv/pmu.c| 2 -- 2 files changed, 3 insertions(+), 2 deletions(-) diff --git a/include/qemu/bitops.h b/include/qemu/bitops.h index cb3526d1f4..9b25b2d5e4 100644 --- a/include/qemu/bitops.h +++ b/include/qemu/bitops.h @@ -25,6 +25,9 @@ #define BIT_WORD(nr)((nr) / BITS_PER_LONG) #define BITS_TO_LONGS(nr) DIV_ROUND_UP(nr, BITS_PER_BYTE * sizeof(long)) +#define MAKE_32BIT_MASK(shift, length) \ +(((uint32_t)(~0UL) >> (32 - (length))) << (shift)) + #define MAKE_64BIT_MASK(shift, length) \ (((~0ULL) >> (64 - (length))) << (shift)) diff --git a/target/riscv/pmu.c b/target/riscv/pmu.c index 7ddf4977b1..360c76f63e 100644 --- a/target/riscv/pmu.c +++ b/target/riscv/pmu.c @@ -24,8 +24,6 @@ #include "sysemu/device_tree.h" #define RISCV_TIMEBASE_FREQ 10 /* 1Ghz */ -#define MAKE_32BIT_MASK(shift, length) \ -(((uint32_t)(~0UL) >> (32 - (length))) << (shift)) We can always use the MAKE_64BIT_MASK instead of MAKE_32BIT_MASK. And MAKE_32BIT_MASK only used in target/riscv. I am not sure whether this patch will be accepted. Acked-by: LIU Zhiwei Zhiwei /* * To keep it simple, any event can be mapped to any programmable counters in
Re: [PATCH v2 3/6] target/riscv: Use existing PMU counter mask in FDT generation
On 2023/10/11 22:45, Rob Bradford wrote: During the FDT generation use the existing mask containing the enabled counters rather then generating a new one. Using the existing mask will support the use of discontinuous counters. Signed-off-by: Rob Bradford --- hw/riscv/virt.c| 2 +- target/riscv/pmu.c | 6 +- target/riscv/pmu.h | 2 +- 3 files changed, 3 insertions(+), 7 deletions(-) diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c index 5edc1d98d2..acdbaf9da5 100644 --- a/hw/riscv/virt.c +++ b/hw/riscv/virt.c @@ -722,7 +722,7 @@ static void create_fdt_pmu(RISCVVirtState *s) pmu_name = g_strdup_printf("/pmu"); qemu_fdt_add_subnode(ms->fdt, pmu_name); qemu_fdt_setprop_string(ms->fdt, pmu_name, "compatible", "riscv,pmu"); -riscv_pmu_generate_fdt_node(ms->fdt, hart.cfg.pmu_num, pmu_name); +riscv_pmu_generate_fdt_node(ms->fdt, hart.pmu_avail_ctrs, pmu_name); g_free(pmu_name); } diff --git a/target/riscv/pmu.c b/target/riscv/pmu.c index 13801ccb78..7ddf4977b1 100644 --- a/target/riscv/pmu.c +++ b/target/riscv/pmu.c @@ -34,13 +34,9 @@ * to provide the correct value as well. Heterogeneous PMU per hart is not * supported yet. Thus, number of counters are same across all harts. */ -void riscv_pmu_generate_fdt_node(void *fdt, int num_ctrs, char *pmu_name) +void riscv_pmu_generate_fdt_node(void *fdt, uint32_t cmask, char *pmu_name) { uint32_t fdt_event_ctr_map[15] = {}; -uint32_t cmask; - -/* All the programmable counters can map to any event */ -cmask = MAKE_32BIT_MASK(3, num_ctrs); /* * The event encoding is specified in the SBI specification diff --git a/target/riscv/pmu.h b/target/riscv/pmu.h index 88e0713296..505fc850d3 100644 --- a/target/riscv/pmu.h +++ b/target/riscv/pmu.h @@ -28,6 +28,6 @@ void riscv_pmu_init(RISCVCPU *cpu, Error **errp); int riscv_pmu_update_event_map(CPURISCVState *env, uint64_t value, uint32_t ctr_idx); int riscv_pmu_incr_ctr(RISCVCPU *cpu, enum riscv_pmu_event_idx event_idx); -void riscv_pmu_generate_fdt_node(void *fdt, int num_counters, char *pmu_name); +void riscv_pmu_generate_fdt_node(void *fdt, uint32_t cmask, char *pmu_name); Reviewed-by: LIU Zhiwei Zhiwei int riscv_pmu_setup_timer(CPURISCVState *env, uint64_t value, uint32_t ctr_idx);
Re: [PATCH 3/3] target/riscv: Don't assume PMU counters are continuous
On 2023/10/3 20:49, Rob Bradford wrote: Check the PMU available bitmask when checking if a counter is valid rather than comparing the index against the number of PMUs. Signed-off-by: Rob Bradford --- target/riscv/csr.c | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/target/riscv/csr.c b/target/riscv/csr.c index 85a31dc420..3e126219ba 100644 --- a/target/riscv/csr.c +++ b/target/riscv/csr.c @@ -182,7 +182,8 @@ static RISCVException zcmt(CPURISCVState *env, int csrno) #if !defined(CONFIG_USER_ONLY) static RISCVException mctr(CPURISCVState *env, int csrno) { -int pmu_num = riscv_cpu_cfg(env)->pmu_num; +RISCVCPU *cpu = RISCV_CPU(env_cpu(env)); Use env_archcpu(env) instead of RISCV_CPU(env_cpu(env)) macro. +uint32_t pmu_avail_ctrs = cpu->pmu_avail_ctrs; int ctr_index; int base_csrno = CSR_MHPMCOUNTER3; @@ -191,7 +192,7 @@ static RISCVException mctr(CPURISCVState *env, int csrno) base_csrno += 0x80; } ctr_index = csrno - base_csrno; -if (!pmu_num || ctr_index >= pmu_num) { +if ((BIT(ctr_index) & pmu_avail_ctrs >> 3) == 0) { Otherwise, Reviewed-by: LIU Zhiwei Zhiwei /* The PMU is not enabled or counter is out of range */ return RISCV_EXCP_ILLEGAL_INST; }
Re: [PATCH 2/6] target/riscv: Use env_archcpu() in [check_]nanbox()
On 2023/10/11 13:31, Philippe Mathieu-Daudé wrote: On 11/10/23 05:25, LIU Zhiwei wrote: On 2023/10/11 1:04, Richard Henderson wrote: On 10/9/23 05:42, LIU Zhiwei wrote: On 2023/10/9 19:02, Philippe Mathieu-Daudé wrote: When CPUArchState* is available (here CPURISCVState*), we can use the fast env_archcpu() macro to get ArchCPU* (here RISCVCPU*). The QOM cast RISCV_CPU() macro will be slower when building with --enable-qom-cast-debug. If so, maybe we have to do this qom cast somewhere. No, I don't think so. Or at least not in these places. Yes. Perhaps, we should remove all RISCV_CPU macros using after the qom objects realized. Do you think we should remove the RISCV_CPU using in riscv_cpu_exec_interrupt? Although it is not so hot. I think there is no reason to use it there. I have some note in my TODO to check replacing CPUState by ArchCPU in TCGCPUOps (like the cpu_exec_interrupt handler you mentioned). IMHO, this will make it harder for heterogeneous SOC support. ArchCPU is not a target agnostic struct. I must miss something. However I'm running out of time, so feel free to try it. I'd like to have a try if it will not block the heterogeneous SOC support. Using ArchCPU avoids the cast in target code. Yes Except this, there are many other places in hw/ and target/riscv using the RISCV_CPU macro. If a method is exposed as API, we need to check the type. After that for internal calls this is pointless. Make sense. Thanks. Zhiwei If we know whether we should remove the RISCV_CPU macro use in these places, we can do it in another patch. Thanks, Zhiwei r~
Re: [PATCH v2 1/6] target/riscv: Propagate error from PMU setup
On 2023/10/11 22:45, Rob Bradford wrote: More closely follow the QEMU style by returning an Error and propagating it there is an error relating to the PMU setup. Further simplify the function by removing the num_counters parameter as this is available from the passed in cpu pointer. Signed-off-by: Rob Bradford Reviewed-by: Alistair Francis --- target/riscv/cpu.c | 8 +++- target/riscv/pmu.c | 19 +-- target/riscv/pmu.h | 3 ++- 3 files changed, 18 insertions(+), 12 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index ac2b94b6a6..c9d8fc12fe 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -1488,7 +1488,13 @@ static void riscv_cpu_realize_tcg(DeviceState *dev, Error **errp) } if (cpu->cfg.pmu_num) { -if (!riscv_pmu_init(cpu, cpu->cfg.pmu_num) && cpu->cfg.ext_sscofpmf) { +riscv_pmu_init(cpu, _err); +if (local_err != NULL) { +error_propagate(errp, local_err); +return; +} + +if (cpu->cfg.ext_sscofpmf) { cpu->pmu_timer = timer_new_ns(QEMU_CLOCK_VIRTUAL, riscv_pmu_timer_cb, cpu); } diff --git a/target/riscv/pmu.c b/target/riscv/pmu.c index 36f6307d28..13801ccb78 100644 --- a/target/riscv/pmu.c +++ b/target/riscv/pmu.c @@ -434,22 +434,21 @@ int riscv_pmu_setup_timer(CPURISCVState *env, uint64_t value, uint32_t ctr_idx) } -int riscv_pmu_init(RISCVCPU *cpu, int num_counters) +void riscv_pmu_init(RISCVCPU *cpu, Error **errp) { -if (num_counters > (RV_MAX_MHPMCOUNTERS - 3)) { -return -1; +uint8_t pmu_num = cpu->cfg.pmu_num; + +if (pmu_num > (RV_MAX_MHPMCOUNTERS - 3)) { +error_setg(errp, "Number of counters exceeds maximum available"); +return; } cpu->pmu_event_ctr_map = g_hash_table_new(g_direct_hash, g_direct_equal); if (!cpu->pmu_event_ctr_map) { -/* PMU support can not be enabled */ -qemu_log_mask(LOG_UNIMP, "PMU events can't be supported\n"); -cpu->cfg.pmu_num = 0; -return -1; +error_setg(errp, "Unable to allocate PMU event hash table"); +return; } /* Create a bitmask of available programmable counters */ -cpu->pmu_avail_ctrs = MAKE_32BIT_MASK(3, num_counters); - -return 0; +cpu->pmu_avail_ctrs = MAKE_32BIT_MASK(3, pmu_num); } diff --git a/target/riscv/pmu.h b/target/riscv/pmu.h index 2bfb71ba87..88e0713296 100644 --- a/target/riscv/pmu.h +++ b/target/riscv/pmu.h @@ -17,13 +17,14 @@ */ #include "cpu.h" +#include "qapi/error.h" bool riscv_pmu_ctr_monitor_instructions(CPURISCVState *env, uint32_t target_ctr); bool riscv_pmu_ctr_monitor_cycles(CPURISCVState *env, uint32_t target_ctr); void riscv_pmu_timer_cb(void *priv); -int riscv_pmu_init(RISCVCPU *cpu, int num_counters); +void riscv_pmu_init(RISCVCPU *cpu, Error **errp); Reviewed-by: LIU Zhiwei Zhiwei int riscv_pmu_update_event_map(CPURISCVState *env, uint64_t value, uint32_t ctr_idx); int riscv_pmu_incr_ctr(RISCVCPU *cpu, enum riscv_pmu_event_idx event_idx);
Re: [PATCH 04/18] target: Declare FOO_CPU_TYPE_NAME/SUFFIX in 'cpu-qom.h'
On 2023/10/11 11:21, Philippe Mathieu-Daudé wrote: Hi Zhiwei, On 11/10/23 04:51, LIU Zhiwei wrote: On 2023/10/10 17:28, Philippe Mathieu-Daudé wrote: Hegerogeneous code needs access to the FOO_CPU_TYPE_NAME() macro to resolve target CPU types. Hi Philippe, I don't understand why should we use FOO_CPU_TYPE_NAME macro to resolve target CPU types? In my opinion, we should pass the CPU typename from command line for heterogeneous case. Could you make it clearer how should we use FOO_CPU_TYPE_NAME macro to resolve target CPU types in heterogeneous case? To be honest I start to feel a bit lost with the "cpu resolving type" design. We are not quite there yet to "create from command line" or "create from QMP", so I'm prototyping in plain C. One of my test is: #include "target/arm/cpu-qom.h" #include "target/hexagon/cpu-qom.h" ... static void my_machine3_init((MachineState *machine) { CPUState cpu[2]; ... cpu[0] = CPU(object_new(ARM_CPU_TYPE_NAME("cortex-a72"))); cpu[1] = CPU(object_new(HEXAGON_CPU_TYPE_NAME("v68"))); ... } The machine code need access to the per-target FOO_CPU_TYPE_NAME() macros. I see what you mean. It works if we will pass the cpu model instead of cpu typename to the machine state(Not yet). Acked-by: LIU Zhiwei Zhiwei I'm not sure what each macro expands to is considered stable, so IIUC I can't inline and use: cpu[0] = CPU(object_new("cortex-a72-arm-cpu")); cpu[1] = CPU(object_new("v68"-hexagon-cpu)); That said, maybe I'm mistaken. Kinda related discussion with Gavin/Igor: https://lore.kernel.org/qemu-devel/35653f53-a977-02ea-28f6-6fe85b1ef...@redhat.com/ (related to https://lore.kernel.org/qemu-devel/20230907003553.1636896-1-gs...@redhat.com/). Thanks, Zhiwei Move the declaration (along with the required FOO_CPU_TYPE_SUFFIX) to "cpu-qom.h". Signed-off-by: Philippe Mathieu-Daudé --- target/alpha/cpu-qom.h | 5 - target/alpha/cpu.h | 2 -- target/avr/cpu-qom.h | 5 - target/avr/cpu.h | 2 -- target/cris/cpu-qom.h | 5 - target/cris/cpu.h | 2 -- target/i386/cpu-qom.h | 3 +++ target/i386/cpu.h | 2 -- target/m68k/cpu-qom.h | 5 - target/m68k/cpu.h | 2 -- target/mips/cpu-qom.h | 3 +++ target/mips/cpu.h | 2 -- target/rx/cpu-qom.h | 5 - target/rx/cpu.h | 2 -- target/s390x/cpu-qom.h | 5 - target/s390x/cpu.h | 2 -- target/sh4/cpu-qom.h | 5 - target/sh4/cpu.h | 2 -- target/sparc/cpu-qom.h | 5 - target/sparc/cpu.h | 2 -- target/tricore/cpu-qom.h | 5 + target/tricore/cpu.h | 2 -- target/xtensa/cpu-qom.h | 5 - target/xtensa/cpu.h | 2 -- 24 files changed, 47 insertions(+), 33 deletions(-) diff --git a/target/alpha/cpu-qom.h b/target/alpha/cpu-qom.h index 1f200724b6..d596d1b69f 100644 --- a/target/alpha/cpu-qom.h +++ b/target/alpha/cpu-qom.h @@ -1,5 +1,5 @@ /* - * QEMU Alpha CPU + * QEMU Alpha CPU QOM header (target agnostic) * * Copyright (c) 2012 SUSE LINUX Products GmbH * @@ -27,6 +27,9 @@ OBJECT_DECLARE_CPU_TYPE(AlphaCPU, AlphaCPUClass, ALPHA_CPU) +#define ALPHA_CPU_TYPE_SUFFIX "-" TYPE_ALPHA_CPU +#define ALPHA_CPU_TYPE_NAME(model) model ALPHA_CPU_TYPE_SUFFIX + /** * AlphaCPUClass: * @parent_realize: The parent class' realize handler. diff --git a/target/alpha/cpu.h b/target/alpha/cpu.h index e2a467ec17..ba0d9e3468 100644 --- a/target/alpha/cpu.h +++ b/target/alpha/cpu.h @@ -428,8 +428,6 @@ enum { void alpha_translate_init(void); -#define ALPHA_CPU_TYPE_SUFFIX "-" TYPE_ALPHA_CPU -#define ALPHA_CPU_TYPE_NAME(model) model ALPHA_CPU_TYPE_SUFFIX #define CPU_RESOLVING_TYPE TYPE_ALPHA_CPU void alpha_cpu_list(void); [...]
Re: [PATCH 2/6] target/riscv: Use env_archcpu() in [check_]nanbox()
On 2023/10/11 1:04, Richard Henderson wrote: On 10/9/23 05:42, LIU Zhiwei wrote: On 2023/10/9 19:02, Philippe Mathieu-Daudé wrote: When CPUArchState* is available (here CPURISCVState*), we can use the fast env_archcpu() macro to get ArchCPU* (here RISCVCPU*). The QOM cast RISCV_CPU() macro will be slower when building with --enable-qom-cast-debug. Inspired-by: Richard W.M. Jones Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: LIU Zhiwei By the way, does the community has the plan to support heterogeneous architecture cpus in one soc? Yes. Hi Richard, It's a good news. Thanks. If so, maybe we have to do this qom cast somewhere. No, I don't think so. Or at least not in these places. Yes. Perhaps, we should remove all RISCV_CPU macros using after the qom objects realized. Do you think we should remove the RISCV_CPU using in riscv_cpu_exec_interrupt? Although it is not so hot. I think there is no reason to use it there. Except this, there are many other places in hw/ and target/riscv using the RISCV_CPU macro. If we know whether we should remove the RISCV_CPU macro use in these places, we can do it in another patch. Thanks, Zhiwei r~
Re: [PATCH 04/18] target: Declare FOO_CPU_TYPE_NAME/SUFFIX in 'cpu-qom.h'
On 2023/10/10 17:28, Philippe Mathieu-Daudé wrote: Hegerogeneous code needs access to the FOO_CPU_TYPE_NAME() macro to resolve target CPU types. Hi Philippe, I don't understand why should we use FOO_CPU_TYPE_NAME macro to resolve target CPU types? In my opinion, we should pass the CPU typename from command line for heterogeneous case. Could you make it clearer how should we use FOO_CPU_TYPE_NAME macro to resolve target CPU types in heterogeneous case? Thanks, Zhiwei Move the declaration (along with the required FOO_CPU_TYPE_SUFFIX) to "cpu-qom.h". Signed-off-by: Philippe Mathieu-Daudé --- target/alpha/cpu-qom.h | 5 - target/alpha/cpu.h | 2 -- target/avr/cpu-qom.h | 5 - target/avr/cpu.h | 2 -- target/cris/cpu-qom.h| 5 - target/cris/cpu.h| 2 -- target/i386/cpu-qom.h| 3 +++ target/i386/cpu.h| 2 -- target/m68k/cpu-qom.h| 5 - target/m68k/cpu.h| 2 -- target/mips/cpu-qom.h| 3 +++ target/mips/cpu.h| 2 -- target/rx/cpu-qom.h | 5 - target/rx/cpu.h | 2 -- target/s390x/cpu-qom.h | 5 - target/s390x/cpu.h | 2 -- target/sh4/cpu-qom.h | 5 - target/sh4/cpu.h | 2 -- target/sparc/cpu-qom.h | 5 - target/sparc/cpu.h | 2 -- target/tricore/cpu-qom.h | 5 + target/tricore/cpu.h | 2 -- target/xtensa/cpu-qom.h | 5 - target/xtensa/cpu.h | 2 -- 24 files changed, 47 insertions(+), 33 deletions(-) diff --git a/target/alpha/cpu-qom.h b/target/alpha/cpu-qom.h index 1f200724b6..d596d1b69f 100644 --- a/target/alpha/cpu-qom.h +++ b/target/alpha/cpu-qom.h @@ -1,5 +1,5 @@ /* - * QEMU Alpha CPU + * QEMU Alpha CPU QOM header (target agnostic) * * Copyright (c) 2012 SUSE LINUX Products GmbH * @@ -27,6 +27,9 @@ OBJECT_DECLARE_CPU_TYPE(AlphaCPU, AlphaCPUClass, ALPHA_CPU) +#define ALPHA_CPU_TYPE_SUFFIX "-" TYPE_ALPHA_CPU +#define ALPHA_CPU_TYPE_NAME(model) model ALPHA_CPU_TYPE_SUFFIX + /** * AlphaCPUClass: * @parent_realize: The parent class' realize handler. diff --git a/target/alpha/cpu.h b/target/alpha/cpu.h index e2a467ec17..ba0d9e3468 100644 --- a/target/alpha/cpu.h +++ b/target/alpha/cpu.h @@ -428,8 +428,6 @@ enum { void alpha_translate_init(void); -#define ALPHA_CPU_TYPE_SUFFIX "-" TYPE_ALPHA_CPU -#define ALPHA_CPU_TYPE_NAME(model) model ALPHA_CPU_TYPE_SUFFIX #define CPU_RESOLVING_TYPE TYPE_ALPHA_CPU void alpha_cpu_list(void); diff --git a/target/avr/cpu-qom.h b/target/avr/cpu-qom.h index 01ea5f160b..a810d6dc09 100644 --- a/target/avr/cpu-qom.h +++ b/target/avr/cpu-qom.h @@ -1,5 +1,5 @@ /* - * QEMU AVR CPU + * QEMU AVR CPU QOM header (target agnostic) * * Copyright (c) 2016-2020 Michael Rolnik * @@ -28,6 +28,9 @@ OBJECT_DECLARE_CPU_TYPE(AVRCPU, AVRCPUClass, AVR_CPU) +#define AVR_CPU_TYPE_SUFFIX "-" TYPE_AVR_CPU +#define AVR_CPU_TYPE_NAME(name) (name AVR_CPU_TYPE_SUFFIX) + /** * AVRCPUClass: * @parent_realize: The parent class' realize handler. diff --git a/target/avr/cpu.h b/target/avr/cpu.h index 4ce22d8e4f..d3f0cc65d4 100644 --- a/target/avr/cpu.h +++ b/target/avr/cpu.h @@ -28,8 +28,6 @@ #error "AVR 8-bit does not support user mode" #endif -#define AVR_CPU_TYPE_SUFFIX "-" TYPE_AVR_CPU -#define AVR_CPU_TYPE_NAME(name) (name AVR_CPU_TYPE_SUFFIX) #define CPU_RESOLVING_TYPE TYPE_AVR_CPU #define TCG_GUEST_DEFAULT_MO 0 diff --git a/target/cris/cpu-qom.h b/target/cris/cpu-qom.h index 431a1d536a..02a5b589b8 100644 --- a/target/cris/cpu-qom.h +++ b/target/cris/cpu-qom.h @@ -1,5 +1,5 @@ /* - * QEMU CRIS CPU + * QEMU CRIS CPU QOM header (target agnostic) * * Copyright (c) 2012 SUSE LINUX Products GmbH * @@ -27,6 +27,9 @@ OBJECT_DECLARE_CPU_TYPE(CRISCPU, CRISCPUClass, CRIS_CPU) +#define CRIS_CPU_TYPE_SUFFIX "-" TYPE_CRIS_CPU +#define CRIS_CPU_TYPE_NAME(name) (name CRIS_CPU_TYPE_SUFFIX) + /** * CRISCPUClass: * @parent_realize: The parent class' realize handler. diff --git a/target/cris/cpu.h b/target/cris/cpu.h index 676b8e93ca..1af7ae5ef9 100644 --- a/target/cris/cpu.h +++ b/target/cris/cpu.h @@ -242,8 +242,6 @@ enum { /* CRIS uses 8k pages. */ #define MMAP_SHIFT TARGET_PAGE_BITS -#define CRIS_CPU_TYPE_SUFFIX "-" TYPE_CRIS_CPU -#define CRIS_CPU_TYPE_NAME(name) (name CRIS_CPU_TYPE_SUFFIX) #define CPU_RESOLVING_TYPE TYPE_CRIS_CPU /* MMU modes definitions */ diff --git a/target/i386/cpu-qom.h b/target/i386/cpu-qom.h index 2350f4ae60..78207c0a7c 100644 --- a/target/i386/cpu-qom.h +++ b/target/i386/cpu-qom.h @@ -32,6 +32,9 @@ OBJECT_DECLARE_CPU_TYPE(X86CPU, X86CPUClass, X86_CPU) +#define X86_CPU_TYPE_SUFFIX "-" TYPE_X86_CPU +#define X86_CPU_TYPE_NAME(name) (name X86_CPU_TYPE_SUFFIX) + typedef struct X86CPUModel X86CPUModel; /** diff --git a/target/i386/cpu.h b/target/i386/cpu.h index e1875466b9..862e4f1ff5 100644 --- a/target/i386/cpu.h +++ b/target/i386/cpu.h @@ -2241,8 +2241,6 @@
Re: [PATCH 03/18] target/riscv: Remove CPU_RESOLVING_TYPE from 'cpu-qom.h'
On 2023/10/10 17:28, Philippe Mathieu-Daudé wrote: CPU_RESOLVING_TYPE is a per-target definition, and is irrelevant for other targets. Move it to "cpu.h". Signed-off-by: Philippe Mathieu-Daudé --- target/riscv/cpu-qom.h | 1 - target/riscv/cpu.h | 2 ++ 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/target/riscv/cpu-qom.h b/target/riscv/cpu-qom.h index 04af50983e..8cb67b84a4 100644 --- a/target/riscv/cpu-qom.h +++ b/target/riscv/cpu-qom.h @@ -27,7 +27,6 @@ #define RISCV_CPU_TYPE_SUFFIX "-" TYPE_RISCV_CPU #define RISCV_CPU_TYPE_NAME(name) (name RISCV_CPU_TYPE_SUFFIX) -#define CPU_RESOLVING_TYPE TYPE_RISCV_CPU #define TYPE_RISCV_CPU_ANY RISCV_CPU_TYPE_NAME("any") #define TYPE_RISCV_CPU_BASE32 RISCV_CPU_TYPE_NAME("rv32") diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index ef9cf21c0c..374b813f20 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -31,6 +31,8 @@ #include "qapi/qapi-types-common.h" #include "cpu-qom.h" +#define CPU_RESOLVING_TYPE TYPE_RISCV_CPU Reviewed-by: LIU Zhiwei Zhiwei + #define TCG_GUEST_DEFAULT_MO 0 /*
Re: [PATCH 10/18] target/riscv: Inline target specific TYPE_RISCV_CPU_BASE definition
On 2023/10/10 17:28, Philippe Mathieu-Daudé wrote: TYPE_RISCV_CPU_BASE depends on the TARGET_RISCV32/TARGET_RISCV64 definitions which are target specific. Such target specific definition taints "cpu-qom.h". Since "cpu-qom.h" must be target agnostic, remove its target specific definition uses by inlining TYPE_RISCV_CPU_BASE in the two machines using it. "target/riscv/cpu-qom.h" is now fully target agnostic. Signed-off-by: Philippe Mathieu-Daudé --- target/riscv/cpu-qom.h | 8 +--- hw/riscv/spike.c | 8 +++- hw/riscv/virt.c| 8 +++- 3 files changed, 15 insertions(+), 9 deletions(-) diff --git a/target/riscv/cpu-qom.h b/target/riscv/cpu-qom.h index 8cb67b84a4..f607687384 100644 --- a/target/riscv/cpu-qom.h +++ b/target/riscv/cpu-qom.h @@ -1,5 +1,5 @@ /* - * QEMU RISC-V CPU QOM header + * QEMU RISC-V CPU QOM header (target agnostic) * * Copyright (c) 2023 Ventana Micro Systems Inc. * @@ -43,12 +43,6 @@ #define TYPE_RISCV_CPU_VEYRON_V1RISCV_CPU_TYPE_NAME("veyron-v1") #define TYPE_RISCV_CPU_HOST RISCV_CPU_TYPE_NAME("host") -#if defined(TARGET_RISCV32) -# define TYPE_RISCV_CPU_BASETYPE_RISCV_CPU_BASE32 -#elif defined(TARGET_RISCV64) -# define TYPE_RISCV_CPU_BASETYPE_RISCV_CPU_BASE64 -#endif - typedef struct CPUArchState CPURISCVState; OBJECT_DECLARE_CPU_TYPE(RISCVCPU, RISCVCPUClass, RISCV_CPU) diff --git a/hw/riscv/spike.c b/hw/riscv/spike.c index 81f7e53aed..eae49da6d6 100644 --- a/hw/riscv/spike.c +++ b/hw/riscv/spike.c @@ -349,7 +349,13 @@ static void spike_machine_class_init(ObjectClass *oc, void *data) mc->init = spike_board_init; mc->max_cpus = SPIKE_CPUS_MAX; mc->is_default = true; -mc->default_cpu_type = TYPE_RISCV_CPU_BASE; +#if defined(TARGET_RISCV32) +mc->default_cpu_type = TYPE_RISCV_CPU_BASE32; +#elif defined(TARGET_RISCV64) +mc->default_cpu_type = TYPE_RISCV_CPU_BASE64; +#else +#error unsupported target +#endif mc->possible_cpu_arch_ids = riscv_numa_possible_cpu_arch_ids; mc->cpu_index_to_instance_props = riscv_numa_cpu_index_to_props; mc->get_default_cpu_node_id = riscv_numa_get_default_cpu_node_id; diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c index 5edc1d98d2..620a4e5f07 100644 --- a/hw/riscv/virt.c +++ b/hw/riscv/virt.c @@ -1685,7 +1685,13 @@ static void virt_machine_class_init(ObjectClass *oc, void *data) mc->desc = "RISC-V VirtIO board"; mc->init = virt_machine_init; mc->max_cpus = VIRT_CPUS_MAX; -mc->default_cpu_type = TYPE_RISCV_CPU_BASE; +#if defined(TARGET_RISCV32) +mc->default_cpu_type = TYPE_RISCV_CPU_BASE32; +#elif defined(TARGET_RISCV64) +mc->default_cpu_type = TYPE_RISCV_CPU_BASE64; +#else +#error unsupported target +#endif Reviewed-by: LIU Zhiwei Zhiwei mc->pci_allow_0_address = true; mc->possible_cpu_arch_ids = riscv_numa_possible_cpu_arch_ids; mc->cpu_index_to_instance_props = riscv_numa_cpu_index_to_props;
Re: [PATCH] target/riscv: Fix vfwmaccbf16.vf
On 2023/10/5 17:57, Max Chou wrote: The operator (fwmacc16) of vfwmaccbf16.vf helper function should be replaced by fwmaccbf16. Signed-off-by: Max Chou --- target/riscv/vector_helper.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c index 3fb05cc3d6e..c45d94c165c 100644 --- a/target/riscv/vector_helper.c +++ b/target/riscv/vector_helper.c @@ -3361,7 +3361,7 @@ static uint32_t fwmaccbf16(uint16_t a, uint16_t b, uint32_t d, float_status *s) RVVCALL(OPFVV3, vfwmaccbf16_vv, WOP_UUU_H, H4, H2, H2, fwmaccbf16) GEN_VEXT_VV_ENV(vfwmaccbf16_vv, 4) -RVVCALL(OPFVF3, vfwmaccbf16_vf, WOP_UUU_H, H4, H2, fwmacc16) +RVVCALL(OPFVF3, vfwmaccbf16_vf, WOP_UUU_H, H4, H2, fwmaccbf16) Reviewed-by: LIU Zhiwei Zhiwei GEN_VEXT_VF(vfwmaccbf16_vf, 4) static uint32_t fwnmacc16(uint16_t a, uint16_t b, uint32_t d, float_status *s)
Re: [PATCH v2] target/riscv: Use a direct cast for better performance
On 2023/10/9 20:53, Richard W.M. Jones wrote: On Mon, Oct 09, 2023 at 08:36:28PM +0800, LIU Zhiwei wrote: On 2023/10/9 5:50, Richard W.M. Jones wrote: RISCV_CPU(cs) uses a checked cast. When QOM cast debugging is enabled this adds about 5% total overhead when emulating RV64 on x86-64 host. Using a RISC-V guest with 16 vCPUs, 16 GB of guest RAM, virtio-blk disk. The guest has a copy of the qemu source tree. The test involves compiling the qemu source tree with 'make clean; time make -j16'. Before making this change the compile step took 449 & 447 seconds over two consecutive runs. After making this change, 428 & 422 seconds. The saving is about 5%. Thanks: Paolo Bonzini Signed-off-by: Richard W.M. Jones Reviewed-by: Daniel Henrique Barboza --- target/riscv/cpu_helper.c | 6 +- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index 3a02079290..479d9863ae 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -66,7 +66,11 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, vaddr *pc, uint64_t *cs_base, uint32_t *pflags) { CPUState *cs = env_cpu(env); -RISCVCPU *cpu = RISCV_CPU(cs); +/* + * Using the checked cast RISCV_CPU(cs) imposes ~ 5% overhead when + * QOM cast debugging is enabled, so use a direct cast instead. + */ +RISCVCPU *cpu = (RISCVCPU *)cs; This function is very hot. Maybe we should cache the tbflags instead of calculate it here. Otherwise, This function is indeed very hot, taking over 20% of total host time in my guest stress test. How would we cache the flags? AIUI they simply depend on machine state and we must recalculate them either when the machine state changes (sprinkle "update_tbflags" everywhere) Yes, we should do in this way. or here. If you have any suggestions I can try things. I think it exceeds this patch. Reviewed-by: LIU Zhiwei I posted a v3 based on Philippe's feedback. OK. Thanks Zhiwei Rich. Zhiwei RISCVExtStatus fs, vs; uint32_t flags = 0;
Re: [PATCH 2/6] target/riscv: Use env_archcpu() in [check_]nanbox()
On 2023/10/9 19:02, Philippe Mathieu-Daudé wrote: When CPUArchState* is available (here CPURISCVState*), we can use the fast env_archcpu() macro to get ArchCPU* (here RISCVCPU*). The QOM cast RISCV_CPU() macro will be slower when building with --enable-qom-cast-debug. Inspired-by: Richard W.M. Jones Signed-off-by: Philippe Mathieu-Daudé Reviewed-by: LIU Zhiwei By the way, does the community has the plan to support heterogeneous architecture cpus in one soc? If so, maybe we have to do this qom cast somewhere. Zhiwei --- target/riscv/internals.h | 8 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/target/riscv/internals.h b/target/riscv/internals.h index b5f823c7ec..8239ae83cc 100644 --- a/target/riscv/internals.h +++ b/target/riscv/internals.h @@ -87,7 +87,7 @@ enum { static inline uint64_t nanbox_s(CPURISCVState *env, float32 f) { /* the value is sign-extended instead of NaN-boxing for zfinx */ -if (RISCV_CPU(env_cpu(env))->cfg.ext_zfinx) { +if (env_archcpu(env)->cfg.ext_zfinx) { return (int32_t)f; } else { return f | MAKE_64BIT_MASK(32, 32); @@ -97,7 +97,7 @@ static inline uint64_t nanbox_s(CPURISCVState *env, float32 f) static inline float32 check_nanbox_s(CPURISCVState *env, uint64_t f) { /* Disable NaN-boxing check when enable zfinx */ -if (RISCV_CPU(env_cpu(env))->cfg.ext_zfinx) { +if (env_archcpu(env)->cfg.ext_zfinx) { return (uint32_t)f; } @@ -113,7 +113,7 @@ static inline float32 check_nanbox_s(CPURISCVState *env, uint64_t f) static inline uint64_t nanbox_h(CPURISCVState *env, float16 f) { /* the value is sign-extended instead of NaN-boxing for zfinx */ -if (RISCV_CPU(env_cpu(env))->cfg.ext_zfinx) { +if (env_archcpu(env)->cfg.ext_zfinx) { return (int16_t)f; } else { return f | MAKE_64BIT_MASK(16, 48); @@ -123,7 +123,7 @@ static inline uint64_t nanbox_h(CPURISCVState *env, float16 f) static inline float16 check_nanbox_h(CPURISCVState *env, uint64_t f) { /* Disable nanbox check when enable zfinx */ -if (RISCV_CPU(env_cpu(env))->cfg.ext_zfinx) { +if (env_archcpu(env)->cfg.ext_zfinx) { return (uint16_t)f; }
Re: [PATCH v2] target/riscv: Use a direct cast for better performance
On 2023/10/9 5:50, Richard W.M. Jones wrote: RISCV_CPU(cs) uses a checked cast. When QOM cast debugging is enabled this adds about 5% total overhead when emulating RV64 on x86-64 host. Using a RISC-V guest with 16 vCPUs, 16 GB of guest RAM, virtio-blk disk. The guest has a copy of the qemu source tree. The test involves compiling the qemu source tree with 'make clean; time make -j16'. Before making this change the compile step took 449 & 447 seconds over two consecutive runs. After making this change, 428 & 422 seconds. The saving is about 5%. Thanks: Paolo Bonzini Signed-off-by: Richard W.M. Jones Reviewed-by: Daniel Henrique Barboza --- target/riscv/cpu_helper.c | 6 +- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index 3a02079290..479d9863ae 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -66,7 +66,11 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, vaddr *pc, uint64_t *cs_base, uint32_t *pflags) { CPUState *cs = env_cpu(env); -RISCVCPU *cpu = RISCV_CPU(cs); +/* + * Using the checked cast RISCV_CPU(cs) imposes ~ 5% overhead when + * QOM cast debugging is enabled, so use a direct cast instead. + */ +RISCVCPU *cpu = (RISCVCPU *)cs; This function is very hot. Maybe we should cache the tbflags instead of calculate it here. Otherwise, Reviewed-by: LIU Zhiwei Zhiwei RISCVExtStatus fs, vs; uint32_t flags = 0;
Re: [PATCH] MAINTAINERS: Add unowned RISC-V related files to the right sections
On 2023/9/29 20:37, Thomas Huth wrote: There are a bunch of RISC-V files that are currently not covered by the "get_maintainers.pl" script. Add them to the right sections in MAINTAINERS to fix this problem. Signed-off-by: Thomas Huth Reviewed-by: LIU Zhiwei Zhiwei --- MAINTAINERS | 10 +- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/MAINTAINERS b/MAINTAINERS index 355b1960ce..1313257180 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -317,8 +317,11 @@ R: Daniel Henrique Barboza R: Liu Zhiwei L: qemu-ri...@nongnu.org S: Supported +F: configs/targets/riscv* +F: docs/system/target-riscv.rst F: target/riscv/ F: hw/riscv/ +F: hw/intc/riscv* F: include/hw/riscv/ F: linux-user/host/riscv32/ F: linux-user/host/riscv64/ @@ -330,6 +333,7 @@ L: qemu-ri...@nongnu.org S: Supported F: target/riscv/insn_trans/trans_xthead.c.inc F: target/riscv/xthead*.decode +F: disas/riscv-xthead* RISC-V XVentanaCondOps extension M: Philipp Tomsich @@ -337,6 +341,7 @@ L: qemu-ri...@nongnu.org S: Maintained F: target/riscv/XVentanaCondOps.decode F: target/riscv/insn_trans/trans_xventanacondops.c.inc +F: disas/riscv-xventana* RENESAS RX CPUs R: Yoshinori Sato @@ -1518,6 +1523,7 @@ Microchip PolarFire SoC Icicle Kit M: Bin Meng L: qemu-ri...@nongnu.org S: Supported +F: docs/system/riscv/microchip-icicle-kit.rst F: hw/riscv/microchip_pfsoc.c F: hw/char/mchp_pfsoc_mmuart.c F: hw/misc/mchp_pfsoc_dmc.c @@ -1533,6 +1539,7 @@ Shakti C class SoC M: Vijai Kumar K L: qemu-ri...@nongnu.org S: Supported +F: docs/system/riscv/shakti-c.rst F: hw/riscv/shakti_c.c F: hw/char/shakti_uart.c F: include/hw/riscv/shakti_c.h @@ -1544,6 +1551,7 @@ M: Bin Meng M: Palmer Dabbelt L: qemu-ri...@nongnu.org S: Supported +F: docs/system/riscv/sifive_u.rst F: hw/*/*sifive*.c F: include/hw/*/*sifive*.h @@ -3543,7 +3551,7 @@ M: Alistair Francis L: qemu-ri...@nongnu.org S: Maintained F: tcg/riscv/ -F: disas/riscv.c +F: disas/riscv.[ch] S390 TCG target M: Richard Henderson
Re: [PATCH v2 04/19] target/riscv: move riscv_tcg_ops to tcg-cpu.c
On 2023/9/6 17:16, Daniel Henrique Barboza wrote: Move the remaining of riscv_tcg_ops now that we have a working realize() implementation. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Andrew Jones Reviewed-by: LIU Zhiwei Zhiwei --- target/riscv/cpu.c | 58 target/riscv/cpu.h | 4 --- target/riscv/tcg/tcg-cpu.c | 60 +- 3 files changed, 59 insertions(+), 63 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index e186c026c9..7569955c7e 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -838,24 +838,6 @@ static vaddr riscv_cpu_get_pc(CPUState *cs) return env->pc; } -static void riscv_cpu_synchronize_from_tb(CPUState *cs, - const TranslationBlock *tb) -{ -if (!(tb_cflags(tb) & CF_PCREL)) { -RISCVCPU *cpu = RISCV_CPU(cs); -CPURISCVState *env = >env; -RISCVMXL xl = FIELD_EX32(tb->flags, TB_FLAGS, XL); - -tcg_debug_assert(!(cs->tcg_cflags & CF_PCREL)); - -if (xl == MXL_RV32) { -env->pc = (int32_t) tb->pc; -} else { -env->pc = tb->pc; -} -} -} - static bool riscv_cpu_has_work(CPUState *cs) { #ifndef CONFIG_USER_ONLY @@ -871,29 +853,6 @@ static bool riscv_cpu_has_work(CPUState *cs) #endif } -static void riscv_restore_state_to_opc(CPUState *cs, - const TranslationBlock *tb, - const uint64_t *data) -{ -RISCVCPU *cpu = RISCV_CPU(cs); -CPURISCVState *env = >env; -RISCVMXL xl = FIELD_EX32(tb->flags, TB_FLAGS, XL); -target_ulong pc; - -if (tb_cflags(tb) & CF_PCREL) { -pc = (env->pc & TARGET_PAGE_MASK) | data[0]; -} else { -pc = data[0]; -} - -if (xl == MXL_RV32) { -env->pc = (int32_t)pc; -} else { -env->pc = pc; -} -env->bins = data[1]; -} - static void riscv_cpu_reset_hold(Object *obj) { #ifndef CONFIG_USER_ONLY @@ -1811,23 +1770,6 @@ static const struct SysemuCPUOps riscv_sysemu_ops = { }; #endif -const struct TCGCPUOps riscv_tcg_ops = { -.initialize = riscv_translate_init, -.synchronize_from_tb = riscv_cpu_synchronize_from_tb, -.restore_state_to_opc = riscv_restore_state_to_opc, - -#ifndef CONFIG_USER_ONLY -.tlb_fill = riscv_cpu_tlb_fill, -.cpu_exec_interrupt = riscv_cpu_exec_interrupt, -.do_interrupt = riscv_cpu_do_interrupt, -.do_transaction_failed = riscv_cpu_do_transaction_failed, -.do_unaligned_access = riscv_cpu_do_unaligned_access, -.debug_excp_handler = riscv_cpu_debug_excp_handler, -.debug_check_breakpoint = riscv_cpu_debug_check_breakpoint, -.debug_check_watchpoint = riscv_cpu_debug_check_watchpoint, -#endif /* !CONFIG_USER_ONLY */ -}; - static bool riscv_cpu_is_dynamic(Object *cpu_obj) { return object_dynamic_cast(cpu_obj, TYPE_RISCV_DYNAMIC_CPU) != NULL; diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 721bd0b119..2ac00a0304 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -706,10 +706,6 @@ enum riscv_pmu_event_idx { RISCV_PMU_EVENT_CACHE_ITLB_PREFETCH_MISS = 0x10021, }; -/* Export tcg_ops until we move everything to tcg/tcg-cpu.c */ -#include "hw/core/tcg-cpu-ops.h" -extern const struct TCGCPUOps riscv_tcg_ops; - /* used by tcg/tcg-cpu.c*/ void isa_ext_update_enabled(RISCVCPU *cpu, uint32_t ext_offset, bool en); bool cpu_cfg_ext_is_user_set(uint32_t ext_offset); diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c index da18851ed4..8698ce4765 100644 --- a/target/riscv/tcg/tcg-cpu.c +++ b/target/riscv/tcg/tcg-cpu.c @@ -26,7 +26,66 @@ #include "qemu/accel.h" #include "qemu/error-report.h" #include "hw/core/accel-cpu.h" +#include "hw/core/tcg-cpu-ops.h" +#include "tcg/tcg.h" +static void riscv_cpu_synchronize_from_tb(CPUState *cs, + const TranslationBlock *tb) +{ +if (!(tb_cflags(tb) & CF_PCREL)) { +RISCVCPU *cpu = RISCV_CPU(cs); +CPURISCVState *env = >env; +RISCVMXL xl = FIELD_EX32(tb->flags, TB_FLAGS, XL); + +tcg_debug_assert(!(cs->tcg_cflags & CF_PCREL)); + +if (xl == MXL_RV32) { +env->pc = (int32_t) tb->pc; +} else { +env->pc = tb->pc; +} +} +} + +static void riscv_restore_state_to_opc(CPUState *cs, + const TranslationBlock *tb, + const uint64_t *data) +{ +RISCVCPU *cpu = RISCV_CPU(cs); +CPURISCVState *env = >env; +RISCVMXL xl = FIELD_EX32(tb->flags, TB_FLAGS, XL); +target_ulong pc; + +if (tb_cflags(tb) & CF_PCREL) {
Re: [PATCH v2 12/19] target/riscv: move KVM only files to kvm subdir
On 2023/9/6 17:16, Daniel Henrique Barboza wrote: Move the files to a 'kvm' dir to promote more code separation between accelerators and making our lives easier supporting build options such as --disable-tcg. Rename kvm.c to kvm-cpu.c to keep it in line with its TCG counterpart. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Andrew Jones Reviewed-by: LIU Zhiwei Zhiwei --- hw/intc/riscv_aplic.c | 2 +- hw/riscv/virt.c | 2 +- target/riscv/cpu.c| 2 +- target/riscv/{kvm.c => kvm/kvm-cpu.c} | 0 target/riscv/{ => kvm}/kvm_riscv.h| 0 target/riscv/kvm/meson.build | 1 + target/riscv/meson.build | 2 +- 7 files changed, 5 insertions(+), 4 deletions(-) rename target/riscv/{kvm.c => kvm/kvm-cpu.c} (100%) rename target/riscv/{ => kvm}/kvm_riscv.h (100%) create mode 100644 target/riscv/kvm/meson.build diff --git a/hw/intc/riscv_aplic.c b/hw/intc/riscv_aplic.c index 99aae8ccbe..c677b5cfbb 100644 --- a/hw/intc/riscv_aplic.c +++ b/hw/intc/riscv_aplic.c @@ -32,7 +32,7 @@ #include "target/riscv/cpu.h" #include "sysemu/sysemu.h" #include "sysemu/kvm.h" -#include "kvm_riscv.h" +#include "kvm/kvm_riscv.h" #include "migration/vmstate.h" #define APLIC_MAX_IDC (1UL << 14) diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c index 3b259b9305..6d9542f0a2 100644 --- a/hw/riscv/virt.c +++ b/hw/riscv/virt.c @@ -35,7 +35,7 @@ #include "hw/riscv/virt.h" #include "hw/riscv/boot.h" #include "hw/riscv/numa.h" -#include "kvm_riscv.h" +#include "kvm/kvm_riscv.h" #include "hw/intc/riscv_aclint.h" #include "hw/intc/riscv_aplic.h" #include "hw/intc/riscv_imsic.h" diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index c8a19be1af..51567c2f12 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -33,7 +33,7 @@ #include "fpu/softfloat-helpers.h" #include "sysemu/kvm.h" #include "sysemu/tcg.h" -#include "kvm_riscv.h" +#include "kvm/kvm_riscv.h" #include "tcg/tcg.h" /* RISC-V CPU definitions */ diff --git a/target/riscv/kvm.c b/target/riscv/kvm/kvm-cpu.c similarity index 100% rename from target/riscv/kvm.c rename to target/riscv/kvm/kvm-cpu.c diff --git a/target/riscv/kvm_riscv.h b/target/riscv/kvm/kvm_riscv.h similarity index 100% rename from target/riscv/kvm_riscv.h rename to target/riscv/kvm/kvm_riscv.h diff --git a/target/riscv/kvm/meson.build b/target/riscv/kvm/meson.build new file mode 100644 index 00..7e92415091 --- /dev/null +++ b/target/riscv/kvm/meson.build @@ -0,0 +1 @@ +riscv_ss.add(when: 'CONFIG_KVM', if_true: files('kvm-cpu.c')) diff --git a/target/riscv/meson.build b/target/riscv/meson.build index 3323b78b84..c53962215f 100644 --- a/target/riscv/meson.build +++ b/target/riscv/meson.build @@ -24,7 +24,6 @@ riscv_ss.add(files( 'zce_helper.c', 'vcrypto_helper.c' )) -riscv_ss.add(when: 'CONFIG_KVM', if_true: files('kvm.c')) riscv_system_ss = ss.source_set() riscv_system_ss.add(files( @@ -39,6 +38,7 @@ riscv_system_ss.add(files( )) subdir('tcg') +subdir('kvm') target_arch += {'riscv': riscv_ss} target_softmmu_arch += {'riscv': riscv_system_ss}
Re: [PATCH v2 11/19] target/riscv: introduce KVM AccelCPUClass
On 2023/9/6 17:16, Daniel Henrique Barboza wrote: Add a KVM accelerator class like we did with TCG. The difference is that, at least for now, we won't be using a realize() implementation for this accelerator. We'll start by assiging kvm_riscv_cpu_add_kvm_properties(), renamed to kvm_cpu_instance_init(), as a 'cpu_instance_init' implementation. Change riscv_cpu_post_init() to invoke accel_cpu_instance_init(), which will go through the 'cpu_instance_init' impl of the current acceleration (if available) and execute it. The end result is that the KVM initial setup, i.e. starting registers and adding its specific properties, will be done via this hook. Add a 'tcg_enabled()' condition in riscv_cpu_post_init() to avoid calling riscv_cpu_add_user_properties() when running KVM. We'll remove this condition when the TCG accel class get its own 'cpu_instance_init' implementation. Signed-off-by: Daniel Henrique Barboza Reviewed-by: LIU Zhiwei Zhiwei --- target/riscv/cpu.c | 8 +++- target/riscv/kvm.c | 26 -- target/riscv/kvm_riscv.h | 6 -- 3 files changed, 27 insertions(+), 13 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 50be127f36..c8a19be1af 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -1219,7 +1219,9 @@ static bool riscv_cpu_has_user_properties(Object *cpu_obj) static void riscv_cpu_post_init(Object *obj) { -if (riscv_cpu_has_user_properties(obj)) { +accel_cpu_instance_init(CPU(obj)); + +if (tcg_enabled() && riscv_cpu_has_user_properties(obj)) { riscv_cpu_add_user_properties(obj); } @@ -1589,10 +1591,6 @@ static void riscv_cpu_add_multiext_prop_array(Object *obj, static void riscv_cpu_add_user_properties(Object *obj) { #ifndef CONFIG_USER_ONLY -if (kvm_enabled()) { -kvm_riscv_cpu_add_kvm_properties(obj); -return; -} riscv_add_satp_mode_properties(obj); #endif diff --git a/target/riscv/kvm.c b/target/riscv/kvm.c index ef6b2cfffe..492b97d19b 100644 --- a/target/riscv/kvm.c +++ b/target/riscv/kvm.c @@ -31,6 +31,7 @@ #include "sysemu/kvm_int.h" #include "cpu.h" #include "trace.h" +#include "hw/core/accel-cpu.h" #include "hw/pci/pci.h" #include "exec/memattrs.h" #include "exec/address-spaces.h" @@ -1274,8 +1275,9 @@ void kvm_riscv_aia_create(MachineState *machine, uint64_t group_shift, kvm_msi_via_irqfd_allowed = kvm_irqfds_enabled(); } -void kvm_riscv_cpu_add_kvm_properties(Object *obj) +static void kvm_cpu_instance_init(CPUState *cs) { +Object *obj = OBJECT(RISCV_CPU(cs)); DeviceState *dev = DEVICE(obj); riscv_init_user_properties(obj); @@ -1287,7 +1289,7 @@ void kvm_riscv_cpu_add_kvm_properties(Object *obj) riscv_cpu_add_kvm_unavail_prop_array(obj, riscv_cpu_experimental_exts); for (Property *prop = riscv_cpu_options; prop && prop->name; prop++) { -/* Check if KVM created the property already */ +/* Check if we have a specific KVM handler for the option */ if (object_property_find(obj, prop->name)) { continue; } @@ -1295,6 +1297,26 @@ void kvm_riscv_cpu_add_kvm_properties(Object *obj) } } +static void kvm_cpu_accel_class_init(ObjectClass *oc, void *data) +{ +AccelCPUClass *acc = ACCEL_CPU_CLASS(oc); + +acc->cpu_instance_init = kvm_cpu_instance_init; +} + +static const TypeInfo kvm_cpu_accel_type_info = { +.name = ACCEL_CPU_NAME("kvm"), + +.parent = TYPE_ACCEL_CPU, +.class_init = kvm_cpu_accel_class_init, +.abstract = true, +}; +static void kvm_cpu_accel_register_types(void) +{ +type_register_static(_cpu_accel_type_info); +} +type_init(kvm_cpu_accel_register_types); + static void riscv_host_cpu_init(Object *obj) { CPURISCVState *env = _CPU(obj)->env; diff --git a/target/riscv/kvm_riscv.h b/target/riscv/kvm_riscv.h index c9ecd9a967..8fe6e3e6fb 100644 --- a/target/riscv/kvm_riscv.h +++ b/target/riscv/kvm_riscv.h @@ -20,7 +20,6 @@ #define QEMU_KVM_RISCV_H #ifdef CONFIG_KVM -void kvm_riscv_cpu_add_kvm_properties(Object *obj); void kvm_riscv_reset_vcpu(RISCVCPU *cpu); void kvm_riscv_set_irq(RISCVCPU *cpu, int irq, int level); void kvm_riscv_aia_create(MachineState *machine, uint64_t group_shift, @@ -29,11 +28,6 @@ void kvm_riscv_aia_create(MachineState *machine, uint64_t group_shift, uint64_t guest_num); void riscv_kvm_aplic_request(void *opaque, int irq, int level); #else -static inline void kvm_riscv_cpu_add_kvm_properties(Object *obj) -{ -g_assert_not_reached(); -} - static inline void kvm_riscv_reset_vcpu(RISCVCPU *cpu) { g_assert_not_reached();
Re: [PATCH v2 09/19] target/riscv: make riscv_add_satp_mode_properties() public
On 2023/9/6 17:16, Daniel Henrique Barboza wrote: This function is used for both accelerators. Make it public, and call it from kvm_riscv_cpu_add_kvm_properties(). This will make it easier to split KVM specific code for the KVM accelerator class in the next patch. Signed-off-by: Daniel Henrique Barboza Reviewed-by: LIU Zhiwei Zhiwei --- target/riscv/cpu.c | 5 ++--- target/riscv/cpu.h | 1 + target/riscv/kvm.c | 1 + 3 files changed, 4 insertions(+), 3 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 0dc9b3201d..50be127f36 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -1115,7 +1115,7 @@ static void cpu_riscv_set_satp(Object *obj, Visitor *v, const char *name, satp_map->init |= 1 << satp; } -static void riscv_add_satp_mode_properties(Object *obj) +void riscv_add_satp_mode_properties(Object *obj) { RISCVCPU *cpu = RISCV_CPU(obj); @@ -1589,12 +1589,11 @@ static void riscv_cpu_add_multiext_prop_array(Object *obj, static void riscv_cpu_add_user_properties(Object *obj) { #ifndef CONFIG_USER_ONLY -riscv_add_satp_mode_properties(obj); - if (kvm_enabled()) { kvm_riscv_cpu_add_kvm_properties(obj); return; } +riscv_add_satp_mode_properties(obj); #endif riscv_cpu_add_misa_properties(obj); diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index b9c4bea3f7..950c2301f2 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -726,6 +726,7 @@ extern const RISCVCPUMultiExtConfig riscv_cpu_experimental_exts[]; extern Property riscv_cpu_options[]; void riscv_cpu_add_misa_properties(Object *cpu_obj); +void riscv_add_satp_mode_properties(Object *obj); /* CSR function table */ extern riscv_csr_operations csr_ops[CSR_TABLE_SIZE]; diff --git a/target/riscv/kvm.c b/target/riscv/kvm.c index 7dac01374f..ef6b2cfffe 100644 --- a/target/riscv/kvm.c +++ b/target/riscv/kvm.c @@ -1279,6 +1279,7 @@ void kvm_riscv_cpu_add_kvm_properties(Object *obj) DeviceState *dev = DEVICE(obj); riscv_init_user_properties(obj); +riscv_add_satp_mode_properties(obj); riscv_cpu_add_misa_properties(obj); riscv_cpu_add_kvm_unavail_prop_array(obj, riscv_cpu_extensions);
Re: [PATCH v2 08/19] target/riscv: move riscv_cpu_add_kvm_properties() to kvm.c
On 2023/9/6 17:16, Daniel Henrique Barboza wrote: We'll introduce the KVM accelerator class with a 'cpu_instance_init' implementation that is going to be invoked during the common riscv_cpu_post_init() (via accel_cpu_instance_init()). This instance_init will execute KVM exclusive code that TCG doesn't care about, such as adding KVM specific properties, initing registers using a KVM scratch CPU and so on. The core of the forementioned cpu_instance_init impl is the current riscv_cpu_add_kvm_properties() that is being used by the common code via riscv_cpu_add_user_properties() in cpu.c. Move it to kvm.c, together will all the relevant artifacts, exporting and renaming it to kvm_riscv_cpu_add_kvm_properties() so cpu.c can keep using it for now. To make this work we'll need to export riscv_cpu_extensions, riscv_cpu_vendor_exts and riscv_cpu_experimental_exts from cpu.c as well. The TCG accelerator will also need to access those in the near future so this export will benefit us in the long run. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Andrew Jones Reviewed-by: LIU Zhiwei Zhiwei --- target/riscv/cpu.c | 89 +++- target/riscv/cpu.h | 14 +++ target/riscv/kvm.c | 68 +- target/riscv/kvm_riscv.h | 2 +- 4 files changed, 88 insertions(+), 85 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 50c2819d68..0dc9b3201d 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -1370,7 +1370,7 @@ static RISCVCPUMisaExtConfig misa_ext_cfgs[] = { * change MISA bits during realize() (RVG enables MISA * bits but the user is warned about it). */ -static void riscv_cpu_add_misa_properties(Object *cpu_obj) +void riscv_cpu_add_misa_properties(Object *cpu_obj) { int i; @@ -1397,17 +1397,11 @@ static void riscv_cpu_add_misa_properties(Object *cpu_obj) } } -typedef struct RISCVCPUMultiExtConfig { -const char *name; -uint32_t offset; -bool enabled; -} RISCVCPUMultiExtConfig; - #define MULTI_EXT_CFG_BOOL(_name, _prop, _defval) \ {.name = _name, .offset = CPU_CFG_OFFSET(_prop), \ .enabled = _defval} -static const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = { +const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = { /* Defaults for standard extensions */ MULTI_EXT_CFG_BOOL("sscofpmf", ext_sscofpmf, false), MULTI_EXT_CFG_BOOL("Zifencei", ext_ifencei, true), @@ -1469,7 +1463,7 @@ static const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = { DEFINE_PROP_END_OF_LIST(), }; -static const RISCVCPUMultiExtConfig riscv_cpu_vendor_exts[] = { +const RISCVCPUMultiExtConfig riscv_cpu_vendor_exts[] = { MULTI_EXT_CFG_BOOL("xtheadba", ext_xtheadba, false), MULTI_EXT_CFG_BOOL("xtheadbb", ext_xtheadbb, false), MULTI_EXT_CFG_BOOL("xtheadbs", ext_xtheadbs, false), @@ -1487,7 +1481,7 @@ static const RISCVCPUMultiExtConfig riscv_cpu_vendor_exts[] = { }; /* These are experimental so mark with 'x-' */ -static const RISCVCPUMultiExtConfig riscv_cpu_experimental_exts[] = { +const RISCVCPUMultiExtConfig riscv_cpu_experimental_exts[] = { /* ePMP 0.9.3 */ MULTI_EXT_CFG_BOOL("x-epmp", epmp, false), MULTI_EXT_CFG_BOOL("x-smaia", ext_smaia, false), @@ -1513,7 +1507,7 @@ static const RISCVCPUMultiExtConfig riscv_cpu_experimental_exts[] = { DEFINE_PROP_END_OF_LIST(), }; -static Property riscv_cpu_options[] = { +Property riscv_cpu_options[] = { DEFINE_PROP_UINT8("pmu-num", RISCVCPU, cfg.pmu_num, 16), DEFINE_PROP_BOOL("mmu", RISCVCPU, cfg.mmu, true), @@ -1574,25 +1568,6 @@ static void cpu_add_multi_ext_prop(Object *cpu_obj, multi_cfg->enabled); } -#ifndef CONFIG_USER_ONLY -static void cpu_set_cfg_unavailable(Object *obj, Visitor *v, -const char *name, -void *opaque, Error **errp) -{ -const char *propname = opaque; -bool value; - -if (!visit_type_bool(v, name, , errp)) { -return; -} - -if (value) { -error_setg(errp, "extension %s is not available with KVM", - propname); -} -} -#endif - static void riscv_cpu_add_multiext_prop_array(Object *obj, const RISCVCPUMultiExtConfig *array) { @@ -1605,58 +1580,6 @@ static void riscv_cpu_add_multiext_prop_array(Object *obj, } } -#ifndef CONFIG_USER_ONLY -static void riscv_cpu_add_kvm_unavail_prop(Object *obj, const char *prop_name) -{ -/* Check if KVM created the property already */ -if (object_property_find(obj, prop_name)) { -return; -} - -/* - * Set the default to disabled for every extension - * unknown to KVM and error out if the user attempts - * to enab
Re: [PATCH v2 07/19] target/riscv/cpu.c: mark extensions arrays as 'const'
On 2023/9/6 17:16, Daniel Henrique Barboza wrote: We'll need to export these arrays to the accelerator classes in the next patches. Mark them as 'const' now because they should not be modified at runtime. Note that 'riscv_cpu_options' will also be exported, but can't be marked as 'const', because the properties are changed via qdev_property_add_static(). Signed-off-by: Daniel Henrique Barboza Reviewed-by: Andrew Jones Reviewed-by: LIU Zhiwei Zhiwei --- target/riscv/cpu.c | 22 +- 1 file changed, 13 insertions(+), 9 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index c15bb572d4..50c2819d68 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -1407,7 +1407,7 @@ typedef struct RISCVCPUMultiExtConfig { {.name = _name, .offset = CPU_CFG_OFFSET(_prop), \ .enabled = _defval} -static RISCVCPUMultiExtConfig riscv_cpu_extensions[] = { +static const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = { /* Defaults for standard extensions */ MULTI_EXT_CFG_BOOL("sscofpmf", ext_sscofpmf, false), MULTI_EXT_CFG_BOOL("Zifencei", ext_ifencei, true), @@ -1469,7 +1469,7 @@ static RISCVCPUMultiExtConfig riscv_cpu_extensions[] = { DEFINE_PROP_END_OF_LIST(), }; -static RISCVCPUMultiExtConfig riscv_cpu_vendor_exts[] = { +static const RISCVCPUMultiExtConfig riscv_cpu_vendor_exts[] = { MULTI_EXT_CFG_BOOL("xtheadba", ext_xtheadba, false), MULTI_EXT_CFG_BOOL("xtheadbb", ext_xtheadbb, false), MULTI_EXT_CFG_BOOL("xtheadbs", ext_xtheadbs, false), @@ -1487,7 +1487,7 @@ static RISCVCPUMultiExtConfig riscv_cpu_vendor_exts[] = { }; /* These are experimental so mark with 'x-' */ -static RISCVCPUMultiExtConfig riscv_cpu_experimental_exts[] = { +static const RISCVCPUMultiExtConfig riscv_cpu_experimental_exts[] = { /* ePMP 0.9.3 */ MULTI_EXT_CFG_BOOL("x-epmp", epmp, false), MULTI_EXT_CFG_BOOL("x-smaia", ext_smaia, false), @@ -1558,7 +1558,7 @@ static void cpu_get_multi_ext_cfg(Object *obj, Visitor *v, const char *name, } static void cpu_add_multi_ext_prop(Object *cpu_obj, - RISCVCPUMultiExtConfig *multi_cfg) + const RISCVCPUMultiExtConfig *multi_cfg) { object_property_add(cpu_obj, multi_cfg->name, "bool", cpu_get_multi_ext_cfg, @@ -1594,11 +1594,13 @@ static void cpu_set_cfg_unavailable(Object *obj, Visitor *v, #endif static void riscv_cpu_add_multiext_prop_array(Object *obj, - RISCVCPUMultiExtConfig *array) +const RISCVCPUMultiExtConfig *array) { +const RISCVCPUMultiExtConfig *prop; + g_assert(array); -for (RISCVCPUMultiExtConfig *prop = array; prop && prop->name; prop++) { +for (prop = array; prop && prop->name; prop++) { cpu_add_multi_ext_prop(obj, prop); } } @@ -1622,11 +1624,13 @@ static void riscv_cpu_add_kvm_unavail_prop(Object *obj, const char *prop_name) } static void riscv_cpu_add_kvm_unavail_prop_array(Object *obj, - RISCVCPUMultiExtConfig *array) +const RISCVCPUMultiExtConfig *array) { +const RISCVCPUMultiExtConfig *prop; + g_assert(array); -for (RISCVCPUMultiExtConfig *prop = array; prop && prop->name; prop++) { +for (prop = array; prop && prop->name; prop++) { riscv_cpu_add_kvm_unavail_prop(obj, prop->name); } } @@ -1689,7 +1693,7 @@ static void riscv_init_max_cpu_extensions(Object *obj) { RISCVCPU *cpu = RISCV_CPU(obj); CPURISCVState *env = >env; -RISCVCPUMultiExtConfig *prop; +const RISCVCPUMultiExtConfig *prop; /* Enable RVG, RVJ and RVV that are disabled by default */ set_misa(env, env->misa_mxl, env->misa_ext | RVG | RVJ | RVV);
Re: [PATCH v2 06/19] target/riscv: move 'host' CPU declaration to kvm.c
On 2023/9/6 17:16, Daniel Henrique Barboza wrote: This CPU only exists if we're compiling with KVM so move it to the kvm specific file. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Philippe Mathieu-Daudé Reviewed-by: Andrew Jones --- target/riscv/cpu.c | 16 target/riscv/kvm.c | 21 + 2 files changed, 21 insertions(+), 16 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 4c6d595067..c15bb572d4 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -652,19 +652,6 @@ static void rv32_imafcu_nommu_cpu_init(Object *obj) } #endif -#if defined(CONFIG_KVM) -static void riscv_host_cpu_init(Object *obj) -{ -CPURISCVState *env = _CPU(obj)->env; -#if defined(TARGET_RISCV32) -set_misa(env, MXL_RV32, 0); -#elif defined(TARGET_RISCV64) -set_misa(env, MXL_RV64, 0); -#endif -riscv_cpu_add_user_properties(obj); Remove this statement in patch 5. Otherwise, Reviewed-by: LIU Zhiwei Zhiwei -} -#endif /* CONFIG_KVM */ - static ObjectClass *riscv_cpu_class_by_name(const char *cpu_model) { ObjectClass *oc; @@ -2044,9 +2031,6 @@ static const TypeInfo riscv_cpu_type_infos[] = { }, DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_ANY, riscv_any_cpu_init), DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_MAX, riscv_max_cpu_init), -#if defined(CONFIG_KVM) -DEFINE_CPU(TYPE_RISCV_CPU_HOST, riscv_host_cpu_init), -#endif #if defined(TARGET_RISCV32) DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_BASE32, rv32_base_cpu_init), DEFINE_CPU(TYPE_RISCV_CPU_IBEX, rv32_ibex_cpu_init), diff --git a/target/riscv/kvm.c b/target/riscv/kvm.c index 14763ec0cd..b4d8d7a46c 100644 --- a/target/riscv/kvm.c +++ b/target/riscv/kvm.c @@ -1227,3 +1227,24 @@ void kvm_riscv_aia_create(MachineState *machine, uint64_t group_shift, kvm_msi_via_irqfd_allowed = kvm_irqfds_enabled(); } + +static void riscv_host_cpu_init(Object *obj) +{ +CPURISCVState *env = _CPU(obj)->env; + +#if defined(TARGET_RISCV32) +env->misa_mxl_max = env->misa_mxl = MXL_RV32; +#elif defined(TARGET_RISCV64) +env->misa_mxl_max = env->misa_mxl = MXL_RV64; +#endif +} + +static const TypeInfo riscv_kvm_cpu_type_infos[] = { +{ +.name = TYPE_RISCV_CPU_HOST, +.parent = TYPE_RISCV_CPU, +.instance_init = riscv_host_cpu_init, +} +}; + +DEFINE_TYPES(riscv_kvm_cpu_type_infos)
Re: [PATCH v2 03/19] target/riscv: move riscv_cpu_validate_set_extensions() to tcg-cpu.c
On 2023/9/6 17:16, Daniel Henrique Barboza wrote: This function is the core of the RISC-V validations for TCG CPUs, and it has a lot going on. Functions in cpu.c were made public to allow them to be used by the KVM accelerator class later on. 'cpu_cfg_ext_get_min_version()' is notably hard to move it to another file due to its dependency with isa_edata_arr[] array, thus make it public and use it as is for now. riscv_cpu_validate_set_extensions() is kept public because it's used by csr.c in write_misa(). Signed-off-by: Daniel Henrique Barboza Reviewed-by: Andrew Jones Reviewed-by: LIU Zhiwei Zhiwei --- target/riscv/cpu.c | 361 + target/riscv/cpu.h | 8 +- target/riscv/csr.c | 1 + target/riscv/tcg/tcg-cpu.c | 356 target/riscv/tcg/tcg-cpu.h | 28 +++ 5 files changed, 397 insertions(+), 357 deletions(-) create mode 100644 target/riscv/tcg/tcg-cpu.h diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 59785f5d9a..e186c026c9 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -163,22 +163,21 @@ static const struct isa_ext_data isa_edata_arr[] = { /* Hash that stores user set extensions */ static GHashTable *multi_ext_user_opts; -static bool isa_ext_is_enabled(RISCVCPU *cpu, uint32_t ext_offset) +bool isa_ext_is_enabled(RISCVCPU *cpu, uint32_t ext_offset) { bool *ext_enabled = (void *)>cfg + ext_offset; return *ext_enabled; } -static void isa_ext_update_enabled(RISCVCPU *cpu, uint32_t ext_offset, - bool en) +void isa_ext_update_enabled(RISCVCPU *cpu, uint32_t ext_offset, bool en) { bool *ext_enabled = (void *)>cfg + ext_offset; *ext_enabled = en; } -static int cpu_cfg_ext_get_min_version(uint32_t ext_offset) +int cpu_cfg_ext_get_min_version(uint32_t ext_offset) { int i; @@ -193,38 +192,12 @@ static int cpu_cfg_ext_get_min_version(uint32_t ext_offset) g_assert_not_reached(); } -static bool cpu_cfg_ext_is_user_set(uint32_t ext_offset) +bool cpu_cfg_ext_is_user_set(uint32_t ext_offset) { return g_hash_table_contains(multi_ext_user_opts, GUINT_TO_POINTER(ext_offset)); } -static void cpu_cfg_ext_auto_update(RISCVCPU *cpu, uint32_t ext_offset, -bool value) -{ -CPURISCVState *env = >env; -bool prev_val = isa_ext_is_enabled(cpu, ext_offset); -int min_version; - -if (prev_val == value) { -return; -} - -if (cpu_cfg_ext_is_user_set(ext_offset)) { -return; -} - -if (value && env->priv_ver != PRIV_VERSION_LATEST) { -/* Do not enable it if priv_ver is older than min_version */ -min_version = cpu_cfg_ext_get_min_version(ext_offset); -if (env->priv_ver < min_version) { -return; -} -} - -isa_ext_update_enabled(cpu, ext_offset, value); -} - const char * const riscv_int_regnames[] = { "x0/zero", "x1/ra", "x2/sp", "x3/gp", "x4/tp", "x5/t0", "x6/t1", "x7/t2", "x8/s0", "x9/s1", "x10/a0", "x11/a1", "x12/a2", "x13/a3", @@ -1023,46 +996,7 @@ static void riscv_cpu_disas_set_info(CPUState *s, disassemble_info *info) } } -static void riscv_cpu_validate_v(CPURISCVState *env, RISCVCPUConfig *cfg, - Error **errp) -{ -if (!is_power_of_2(cfg->vlen)) { -error_setg(errp, "Vector extension VLEN must be power of 2"); -return; -} -if (cfg->vlen > RV_VLEN_MAX || cfg->vlen < 128) { -error_setg(errp, - "Vector extension implementation only supports VLEN " - "in the range [128, %d]", RV_VLEN_MAX); -return; -} -if (!is_power_of_2(cfg->elen)) { -error_setg(errp, "Vector extension ELEN must be power of 2"); -return; -} -if (cfg->elen > 64 || cfg->elen < 8) { -error_setg(errp, - "Vector extension implementation only supports ELEN " - "in the range [8, 64]"); -return; -} -if (cfg->vext_spec) { -if (!g_strcmp0(cfg->vext_spec, "v1.0")) { -env->vext_ver = VEXT_VERSION_1_00_0; -} else { -error_setg(errp, "Unsupported vector spec version '%s'", - cfg->vext_spec); -return; -} -} else if (env->vext_ver == 0) { -qemu_log("vector version is not specified, " - "use the default value v1.0\n"); - -env->vext_ver = VEXT_VERSION_1_00_0; -} -} - -static void riscv_cpu_disabl
Re: [PATCH v2 02/19] target/riscv: move riscv_cpu_realize_tcg() to TCG::cpu_realizefn()
On 2023/9/6 17:16, Daniel Henrique Barboza wrote: riscv_cpu_realize_tcg() was added to allow TCG cpus to have a different realize() path during the common riscv_cpu_realize(), making it a good choice to start moving TCG exclusive code to tcg-cpu.c. Rename it to tcg_cpu_realizefn() and assign it as a implementation of accel::cpu_realizefn(). tcg_cpu_realizefn() will then be called during riscv_cpu_realize() via cpu_exec_realizefn(). We'll use a similar approach with KVM in the near future. riscv_cpu_validate_set_extensions() is too big and with too many dependencies to be moved in this same patch. We'll do that next. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Andrew Jones Reviewed-by: LIU Zhiwei Zhiwei --- target/riscv/cpu.c | 128 --- target/riscv/tcg/tcg-cpu.c | 132 + 2 files changed, 132 insertions(+), 128 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 2c6972fa0d..59785f5d9a 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -23,9 +23,7 @@ #include "qemu/log.h" #include "cpu.h" #include "cpu_vendorid.h" -#include "pmu.h" #include "internals.h" -#include "time_helper.h" #include "exec/exec-all.h" #include "qapi/error.h" #include "qapi/visitor.h" @@ -1064,29 +1062,6 @@ static void riscv_cpu_validate_v(CPURISCVState *env, RISCVCPUConfig *cfg, } } -static void riscv_cpu_validate_priv_spec(RISCVCPU *cpu, Error **errp) -{ -CPURISCVState *env = >env; -int priv_version = -1; - -if (cpu->cfg.priv_spec) { -if (!g_strcmp0(cpu->cfg.priv_spec, "v1.12.0")) { -priv_version = PRIV_VERSION_1_12_0; -} else if (!g_strcmp0(cpu->cfg.priv_spec, "v1.11.0")) { -priv_version = PRIV_VERSION_1_11_0; -} else if (!g_strcmp0(cpu->cfg.priv_spec, "v1.10.0")) { -priv_version = PRIV_VERSION_1_10_0; -} else { -error_setg(errp, - "Unsupported privilege spec version '%s'", - cpu->cfg.priv_spec); -return; -} - -env->priv_ver = priv_version; -} -} - static void riscv_cpu_disable_priv_spec_isa_exts(RISCVCPU *cpu) { CPURISCVState *env = >env; @@ -,33 +1086,6 @@ static void riscv_cpu_disable_priv_spec_isa_exts(RISCVCPU *cpu) } } -static void riscv_cpu_validate_misa_mxl(RISCVCPU *cpu, Error **errp) -{ -RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(cpu); -CPUClass *cc = CPU_CLASS(mcc); -CPURISCVState *env = >env; - -/* Validate that MISA_MXL is set properly. */ -switch (env->misa_mxl_max) { -#ifdef TARGET_RISCV64 -case MXL_RV64: -case MXL_RV128: -cc->gdb_core_xml_file = "riscv-64bit-cpu.xml"; -break; -#endif -case MXL_RV32: -cc->gdb_core_xml_file = "riscv-32bit-cpu.xml"; -break; -default: -g_assert_not_reached(); -} - -if (env->misa_mxl_max != env->misa_mxl) { -error_setg(errp, "misa_mxl_max must be equal to misa_mxl"); -return; -} -} - /* * Check consistency between chosen extensions while setting * cpu->cfg accordingly. @@ -1511,74 +1459,6 @@ static void riscv_cpu_finalize_features(RISCVCPU *cpu, Error **errp) #endif } -static void riscv_cpu_validate_misa_priv(CPURISCVState *env, Error **errp) -{ -if (riscv_has_ext(env, RVH) && env->priv_ver < PRIV_VERSION_1_12_0) { -error_setg(errp, "H extension requires priv spec 1.12.0"); -return; -} -} - -static void riscv_cpu_realize_tcg(DeviceState *dev, Error **errp) -{ -RISCVCPU *cpu = RISCV_CPU(dev); -CPURISCVState *env = >env; -Error *local_err = NULL; - -if (object_dynamic_cast(OBJECT(dev), TYPE_RISCV_CPU_HOST)) { -error_setg(errp, "'host' CPU is not compatible with TCG acceleration"); -return; -} - -riscv_cpu_validate_misa_mxl(cpu, _err); -if (local_err != NULL) { -error_propagate(errp, local_err); -return; -} - -riscv_cpu_validate_priv_spec(cpu, _err); -if (local_err != NULL) { -error_propagate(errp, local_err); -return; -} - -riscv_cpu_validate_misa_priv(env, _err); -if (local_err != NULL) { -error_propagate(errp, local_err); -return; -} - -if (cpu->cfg.epmp && !cpu->cfg.pmp) { -/* - * Enhanced PMP should only be available - * on harts with PMP support - */ -error_setg(errp, "Invalid configuration: EPMP requires PMP support"); -return; -} - -riscv_cpu_validate_set_extensions(cpu, _err); -if (local_err != NULL) { -error_propagate(errp, local_err); -
Re: [PATCH v2 01/19] target/riscv: introduce TCG AccelCPUClass
On 2023/9/6 17:16, Daniel Henrique Barboza wrote: target/riscv/cpu.c needs to handle all possible accelerators (TCG and KVM at this moment) during both init() and realize() time. This forces us to resort to a lot of "if tcg" and "if kvm" throughout the code, which isn't wrong, but can get cluttered over time. Splitting acceleration specific code from cpu.c to its own file will help to declutter the existing code and it will also make it easier to support KVM/TCG only builds in the future. We'll start by adding a new subdir called 'tcg' and a new file called 'tcg-cpu.c'. This file will be used to introduce a new accelerator class for TCG acceleration in RISC-V, allowing us to center all TCG exclusive code in its file instead of using 'cpu.c' for everything. This design is inpired by the work Claudio Fontana did in x86 a few years ago in commit f5cc5a5c1 ("i386: split cpu accelerators from cpu.c, using AccelCPUClass"). To avoid moving too much code at once we'll start by adding the new file and TCG AccelCPUClass declaration. The 'class_init' from the accel class will init 'tcg_ops', relieving the common riscv_cpu_class_init() from doing it. 'riscv_tcg_ops' is being exported from 'cpu.c' for now to avoid having to deal with moving code and files around right now. We'll focus on decoupling the realize() logic first. Signed-off-by: Daniel Henrique Barboza Reviewed-by: Andrew Jones Reviewed-by: LIU Zhiwei Zhiwei --- target/riscv/cpu.c | 5 +--- target/riscv/cpu.h | 4 +++ target/riscv/meson.build | 2 ++ target/riscv/tcg/meson.build | 2 ++ target/riscv/tcg/tcg-cpu.c | 58 5 files changed, 67 insertions(+), 4 deletions(-) create mode 100644 target/riscv/tcg/meson.build create mode 100644 target/riscv/tcg/tcg-cpu.c diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index be1c028095..2c6972fa0d 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -2290,9 +2290,7 @@ static const struct SysemuCPUOps riscv_sysemu_ops = { }; #endif -#include "hw/core/tcg-cpu-ops.h" - -static const struct TCGCPUOps riscv_tcg_ops = { +const struct TCGCPUOps riscv_tcg_ops = { .initialize = riscv_translate_init, .synchronize_from_tb = riscv_cpu_synchronize_from_tb, .restore_state_to_opc = riscv_restore_state_to_opc, @@ -2451,7 +2449,6 @@ static void riscv_cpu_class_init(ObjectClass *c, void *data) #endif cc->gdb_arch_name = riscv_gdb_arch_name; cc->gdb_get_dynamic_xml = riscv_gdb_get_dynamic_xml; -cc->tcg_ops = _tcg_ops; object_class_property_add(c, "mvendorid", "uint32", cpu_get_mvendorid, cpu_set_mvendorid, NULL, NULL); diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 577abcd724..b84b62f84e 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -707,6 +707,10 @@ enum riscv_pmu_event_idx { RISCV_PMU_EVENT_CACHE_ITLB_PREFETCH_MISS = 0x10021, }; +/* Export tcg_ops until we move everything to tcg/tcg-cpu.c */ +#include "hw/core/tcg-cpu-ops.h" +extern const struct TCGCPUOps riscv_tcg_ops; + /* CSR function table */ extern riscv_csr_operations csr_ops[CSR_TABLE_SIZE]; diff --git a/target/riscv/meson.build b/target/riscv/meson.build index 660078bda1..f0486183fa 100644 --- a/target/riscv/meson.build +++ b/target/riscv/meson.build @@ -38,5 +38,7 @@ riscv_system_ss.add(files( 'riscv-qmp-cmds.c', )) +subdir('tcg') + target_arch += {'riscv': riscv_ss} target_softmmu_arch += {'riscv': riscv_system_ss} diff --git a/target/riscv/tcg/meson.build b/target/riscv/tcg/meson.build new file mode 100644 index 00..061df3d74a --- /dev/null +++ b/target/riscv/tcg/meson.build @@ -0,0 +1,2 @@ +riscv_ss.add(when: 'CONFIG_TCG', if_true: files( + 'tcg-cpu.c')) diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c new file mode 100644 index 00..0326cead0d --- /dev/null +++ b/target/riscv/tcg/tcg-cpu.c @@ -0,0 +1,58 @@ +/* + * riscv TCG cpu class initialization + * + * Copyright (c) 2023 Ventana Micro Systems Inc. + * + * This library is free software; you can redistribute it and/or + * modify it under the terms of the GNU Lesser General Public + * License as published by the Free Software Foundation; either + * version 2 of the License, or (at your option) any later version. + * + * This library is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * Lesser General Public License for more details. + * + * You should have received a copy of the GNU Lesser General Public + * License along with this library; if not, see <http://www.gnu.org/licenses/>. + */ + +#include "qemu/osdep.h" +#include "cpu.h" +#include "qemu/accel.h" +#include "hw/core/accel
Re: [PATCH v2 05/19] target/riscv/cpu.c: add .instance_post_init()
On 2023/9/6 17:16, Daniel Henrique Barboza wrote: All generic CPUs call riscv_cpu_add_user_properties(). The 'max' CPU calls riscv_init_max_cpu_extensions(). Both can be moved to a common instance_post_init() callback, implemented in riscv_cpu_post_init(), called by all CPUs. The call order then becomes: riscv_cpu_init() -> cpu_init() of each CPU -> .instance_post_init() In the near future riscv_cpu_post_init() will call the init() function of the current accelerator, providing a hook for KVM and TCG accel classes to change the init() process of the CPU. Signed-off-by: Daniel Henrique Barboza --- target/riscv/cpu.c | 42 -- 1 file changed, 32 insertions(+), 10 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 7569955c7e..4c6d595067 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -427,8 +427,6 @@ static void riscv_max_cpu_init(Object *obj) mlx = MXL_RV32; #endif set_misa(env, mlx, 0); -riscv_cpu_add_user_properties(obj); -riscv_init_max_cpu_extensions(obj); env->priv_ver = PRIV_VERSION_LATEST; #ifndef CONFIG_USER_ONLY set_satp_mode_max_supported(RISCV_CPU(obj), mlx == MXL_RV32 ? @@ -442,7 +440,6 @@ static void rv64_base_cpu_init(Object *obj) CPURISCVState *env = _CPU(obj)->env; /* We set this in the realise function */ set_misa(env, MXL_RV64, 0); -riscv_cpu_add_user_properties(obj); /* Set latest version of privileged specification */ env->priv_ver = PRIV_VERSION_LATEST; #ifndef CONFIG_USER_ONLY @@ -566,7 +563,6 @@ static void rv128_base_cpu_init(Object *obj) CPURISCVState *env = _CPU(obj)->env; /* We set this in the realise function */ set_misa(env, MXL_RV128, 0); -riscv_cpu_add_user_properties(obj); /* Set latest version of privileged specification */ env->priv_ver = PRIV_VERSION_LATEST; #ifndef CONFIG_USER_ONLY @@ -579,7 +575,6 @@ static void rv32_base_cpu_init(Object *obj) CPURISCVState *env = _CPU(obj)->env; /* We set this in the realise function */ set_misa(env, MXL_RV32, 0); -riscv_cpu_add_user_properties(obj); /* Set latest version of privileged specification */ env->priv_ver = PRIV_VERSION_LATEST; #ifndef CONFIG_USER_ONLY I think we should also remove riscv_cpu_add_user_properties from host cpu init. @@ -1215,6 +1210,37 @@ static void riscv_cpu_set_irq(void *opaque, int irq, int level) } #endif /* CONFIG_USER_ONLY */ +static bool riscv_cpu_is_dynamic(Object *cpu_obj) +{ +return object_dynamic_cast(cpu_obj, TYPE_RISCV_DYNAMIC_CPU) != NULL; +} + +static bool riscv_cpu_has_max_extensions(Object *cpu_obj) +{ +return object_dynamic_cast(cpu_obj, TYPE_RISCV_CPU_MAX) != NULL; +} + +static bool riscv_cpu_has_user_properties(Object *cpu_obj) +{ +if (kvm_enabled() && +object_dynamic_cast(cpu_obj, TYPE_RISCV_CPU_HOST) != NULL) { +return true; +} + +return riscv_cpu_is_dynamic(cpu_obj); +} + +static void riscv_cpu_post_init(Object *obj) +{ +if (riscv_cpu_has_user_properties(obj)) { +riscv_cpu_add_user_properties(obj); Otherwise, we will enter here for host cpu. Thanks, Zhiwei +} + +if (riscv_cpu_has_max_extensions(obj)) { +riscv_init_max_cpu_extensions(obj); +} +} + static void riscv_cpu_init(Object *obj) { RISCVCPU *cpu = RISCV_CPU(obj); @@ -1770,11 +1796,6 @@ static const struct SysemuCPUOps riscv_sysemu_ops = { }; #endif -static bool riscv_cpu_is_dynamic(Object *cpu_obj) -{ -return object_dynamic_cast(cpu_obj, TYPE_RISCV_DYNAMIC_CPU) != NULL; -} - static void cpu_set_mvendorid(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { @@ -2011,6 +2032,7 @@ static const TypeInfo riscv_cpu_type_infos[] = { .instance_size = sizeof(RISCVCPU), .instance_align = __alignof__(RISCVCPU), .instance_init = riscv_cpu_init, +.instance_post_init = riscv_cpu_post_init, .abstract = true, .class_size = sizeof(RISCVCPUClass), .class_init = riscv_cpu_class_init,
Re: [PATCH] fpu: Add conversions between bfloat16 and [u]int8
Hi Richard, Can you pick it to your tree? Thanks, Zhiwei On 2023/5/31 14:54, LIU Zhiwei wrote: We missed these functions when upstreaming the bfloat16 support. Signed-off-by: LIU Zhiwei --- fpu/softfloat.c | 58 + include/fpu/softfloat.h | 12 + 2 files changed, 70 insertions(+) diff --git a/fpu/softfloat.c b/fpu/softfloat.c index 108f9cb224..576b026f4e 100644 --- a/fpu/softfloat.c +++ b/fpu/softfloat.c @@ -3113,6 +3113,15 @@ int64_t float64_to_int64_scalbn(float64 a, FloatRoundMode rmode, int scale, return parts_float_to_sint(, rmode, scale, INT64_MIN, INT64_MAX, s); } +int8_t bfloat16_to_int8_scalbn(bfloat16 a, FloatRoundMode rmode, int scale, + float_status *s) +{ +FloatParts64 p; + +bfloat16_unpack_canonical(, a, s); +return parts_float_to_sint(, rmode, scale, INT8_MIN, INT8_MAX, s); +} + int16_t bfloat16_to_int16_scalbn(bfloat16 a, FloatRoundMode rmode, int scale, float_status *s) { @@ -3379,6 +3388,11 @@ int64_t floatx80_to_int64_round_to_zero(floatx80 a, float_status *s) return floatx80_to_int64_scalbn(a, float_round_to_zero, 0, s); } +int8_t bfloat16_to_int8(bfloat16 a, float_status *s) +{ +return bfloat16_to_int8_scalbn(a, s->float_rounding_mode, 0, s); +} + int16_t bfloat16_to_int16(bfloat16 a, float_status *s) { return bfloat16_to_int16_scalbn(a, s->float_rounding_mode, 0, s); @@ -3394,6 +3408,11 @@ int64_t bfloat16_to_int64(bfloat16 a, float_status *s) return bfloat16_to_int64_scalbn(a, s->float_rounding_mode, 0, s); } +int8_t bfloat16_to_int8_round_to_zero(bfloat16 a, float_status *s) +{ +return bfloat16_to_int8_scalbn(a, float_round_to_zero, 0, s); +} + int16_t bfloat16_to_int16_round_to_zero(bfloat16 a, float_status *s) { return bfloat16_to_int16_scalbn(a, float_round_to_zero, 0, s); @@ -3503,6 +3522,15 @@ uint64_t float64_to_uint64_scalbn(float64 a, FloatRoundMode rmode, int scale, return parts_float_to_uint(, rmode, scale, UINT64_MAX, s); } +uint8_t bfloat16_to_uint8_scalbn(bfloat16 a, FloatRoundMode rmode, + int scale, float_status *s) +{ +FloatParts64 p; + +bfloat16_unpack_canonical(, a, s); +return parts_float_to_uint(, rmode, scale, UINT8_MAX, s); +} + uint16_t bfloat16_to_uint16_scalbn(bfloat16 a, FloatRoundMode rmode, int scale, float_status *s) { @@ -3728,6 +3756,11 @@ Int128 float128_to_uint128_round_to_zero(float128 a, float_status *s) return float128_to_uint128_scalbn(a, float_round_to_zero, 0, s); } +uint8_t bfloat16_to_uint8(bfloat16 a, float_status *s) +{ +return bfloat16_to_uint8_scalbn(a, s->float_rounding_mode, 0, s); +} + uint16_t bfloat16_to_uint16(bfloat16 a, float_status *s) { return bfloat16_to_uint16_scalbn(a, s->float_rounding_mode, 0, s); @@ -3743,6 +3776,11 @@ uint64_t bfloat16_to_uint64(bfloat16 a, float_status *s) return bfloat16_to_uint64_scalbn(a, s->float_rounding_mode, 0, s); } +uint8_t bfloat16_to_uint8_round_to_zero(bfloat16 a, float_status *s) +{ +return bfloat16_to_uint8_scalbn(a, float_round_to_zero, 0, s); +} + uint16_t bfloat16_to_uint16_round_to_zero(bfloat16 a, float_status *s) { return bfloat16_to_uint16_scalbn(a, float_round_to_zero, 0, s); @@ -3898,6 +3936,11 @@ bfloat16 int16_to_bfloat16_scalbn(int16_t a, int scale, float_status *status) return int64_to_bfloat16_scalbn(a, scale, status); } +bfloat16 int8_to_bfloat16_scalbn(int8_t a, int scale, float_status *status) +{ +return int64_to_bfloat16_scalbn(a, scale, status); +} + bfloat16 int64_to_bfloat16(int64_t a, float_status *status) { return int64_to_bfloat16_scalbn(a, 0, status); @@ -3913,6 +3956,11 @@ bfloat16 int16_to_bfloat16(int16_t a, float_status *status) return int64_to_bfloat16_scalbn(a, 0, status); } +bfloat16 int8_to_bfloat16(int8_t a, float_status *status) +{ +return int64_to_bfloat16_scalbn(a, 0, status); +} + float128 int128_to_float128(Int128 a, float_status *status) { FloatParts128 p = { }; @@ -4108,6 +4156,11 @@ bfloat16 uint16_to_bfloat16_scalbn(uint16_t a, int scale, float_status *status) return uint64_to_bfloat16_scalbn(a, scale, status); } +bfloat16 uint8_to_bfloat16_scalbn(uint8_t a, int scale, float_status *status) +{ +return uint64_to_bfloat16_scalbn(a, scale, status); +} + bfloat16 uint64_to_bfloat16(uint64_t a, float_status *status) { return uint64_to_bfloat16_scalbn(a, 0, status); @@ -4123,6 +4176,11 @@ bfloat16 uint16_to_bfloat16(uint16_t a, float_status *status) return uint64_to_bfloat16_scalbn(a, 0, status); } +bfloat16 uint8_to_bfloat16(uint8_t a, float_status *status) +{ +return uint64_to_bfloat16_scalbn(a, 0, status); +} + float128 uint64_to_float128(uint64_t a, fl
Re: qemu-riscv32 usermode still broken?
On 2023/9/13 6:31, Andreas K. Huettel wrote: Dear all, I've once more tried to build up a riscv32 linux install in a qemu-riscv32 usermode systemd-nspawn, and am running into the same problems as some time ago... https://dev.gentoo.org/~dilfridge/riscv32/riscv32.tar.xz (220M) The problems manifest themselves mostly in bash; if I replace /bin/bash with a static x86-64 binary (in the tarball as /bin/bash.amd64), bypassing qemu, I can make the chroot rebuild itself completely. https://lists.gnu.org/archive/html/bug-bash/2023-09/msg00119.html ^ Here I'm trying to find out more. Bash tests apparently indicate that argv[0] is overwritten, and that reading through a pipe or from /dev/tty fails or loses data. Apart from the bash testsuite failing, symptoms are as follows: * Something seems wrong in the signal handling (?): If it is wrong for signal handling and for 32-bit, I guess it may be fixed by this patch https://www.mail-archive.com/qemu-devel@nongnu.org/msg981238.html And this patch has been merged into master branch yesterday. May be you can have a try based on the master branch. Thanks, Zhiwei --- our package manager (bash/python combo, there bash) hangs reproducibly at one point. --- when I run a console program and try to background it with ctl-z, it hangs (only the first time per bash instance, it seems) repeated ctl-c gets me back to the shell, then the program is in the background riscv32 ~ # python Python 3.11.5 (main, Aug 31 2023, 21:56:30) [GCC 13.2.1 20230826] on linux Type "help", "copyright", "credits" or "license" for more information. [1]+ Stopped python ^C^C^C^C^C^C^C riscv32 ~ # ^C riscv32 ~ # riscv32 ~ # jobs [1]+ Stopped python riscv32 ~ # fg python --- make, when building something, seems to always start only one job in parallel Any advice or debugging would be appreciated. If we get this running then I can set up regular riscv32 Gentoo stage builds within a week. [*] Thanks in advance, Andreas PS. huettel@pinacolada ~ $ /var/lib/machines/riscv32/usr/bin/qemu-riscv32 -version qemu-riscv32 version 8.1.0 Copyright (c) 2003-2023 Fabrice Bellard and the QEMU Project developers [*] https://www.gentoo.org/downloads/#riscv
[PATCH v2] qemu/timer: Add host ticks function for RISC-V
Signed-off-by: LIU Zhiwei --- v2: 1) Use rdtime instead of rdcycle for dynamic cpuclk adjustment. 2) Read timeh twice in case of time overflow for 32-bit cpu. --- include/qemu/timer.h | 22 ++ 1 file changed, 22 insertions(+) diff --git a/include/qemu/timer.h b/include/qemu/timer.h index 9a91cb1248..9a366e551f 100644 --- a/include/qemu/timer.h +++ b/include/qemu/timer.h @@ -979,6 +979,28 @@ static inline int64_t cpu_get_host_ticks(void) return cur - ofs; } +#elif defined(__riscv) && __riscv_xlen == 32 +static inline int64_t cpu_get_host_ticks(void) +{ +uint32_t lo, hi, tmph; +do { +asm volatile("RDTIMEH %0\n\t" + "RDTIME %1\n\t" + "RDTIMEH %2" + : "=r"(hi), "=r"(lo), "=r"(tmph)); +} while (unlikely(tmph != hi)); +return lo | (uint64_t)hi << 32; +} + +#elif defined(__riscv) && __riscv_xlen > 32 +static inline int64_t cpu_get_host_ticks(void) +{ +int64_t val; + +asm volatile("RDTIME %0" : "=r"(val)); +return val; +} + #else /* The host CPU doesn't have an easily accessible cycle counter. Just return a monotonically increasing value. This will be -- 2.17.1
Re: [RESEND] qemu/timer: Add host ticks function for RISC-V
On 2023/9/9 22:45, Palmer Dabbelt wrote: On Sat, 09 Sep 2023 00:18:02 PDT (-0700), pbonz...@redhat.com wrote: Il sab 9 set 2023, 03:35 Atish Patra ha scritto: On Fri, Sep 8, 2023 at 3:29 AM Paolo Bonzini wrote: > > Queued, thanks. > I didn't realize it was already queued. Gmail threads failed me this time. @Paolo Bonzini : Can you please drop this one as this will break as soon as the host riscv system has the latest kernel ? I have provided more details in the original thread. https://lists.gnu.org/archive/html/qemu-devel/2023-09/msg01941.html If you have dynamic clock adjustment, does rdcycle increase with a fixed frequency or does it provide the raw number of clock cycles? If the latter, I agree that it should be provided by perf; but if the frequency is fixed then it would be the same as rdtsc on Intel. That really depends on exactly how the system is set up, but there are systems for which the rdcycle frequency changes when clock speeds change and thus will produce surprising answers for users trying to use rdcycle as a RTC. We have rdtime for that, but it has other problems (it's trapped and emulated in M-mode on some systems, so it's slow and noisy). So we're steering folks towards perf where we can, as at least that way we've got a higher-level interface we can use to describe these quirks. OK. I will send a v2 patch using rdtime. Thanks, Zhiwei Paolo > Paolo > > -- Regards, Atish
Re: [PATCH] qemu/timer: Add host ticks function for RISC-V
On 2023/9/10 1:43, Richard Henderson wrote: On 9/7/23 20:23, LIU Zhiwei wrote: From: LIU Zhiwei Signed-off-by: LIU Zhiwei --- include/qemu/timer.h | 19 +++ 1 file changed, 19 insertions(+) diff --git a/include/qemu/timer.h b/include/qemu/timer.h index 9a91cb1248..ce0b66d122 100644 --- a/include/qemu/timer.h +++ b/include/qemu/timer.h @@ -979,6 +979,25 @@ static inline int64_t cpu_get_host_ticks(void) return cur - ofs; } +#elif defined(__riscv) && defined(__riscv_xlen) && __riscv_xlen == 32 +static inline int64_t cpu_get_host_ticks(void) +{ + uint32_t lo, hi; + asm volatile("RDCYCLE %0\n\t" + "RDCYCLEH %1" + : "=r"(lo), "=r"(hi)); + return lo | (uint64_t)hi << 32; +} + +#elif defined(__riscv) && defined(__riscv_xlen) && __riscv_xlen > 32 +static inline int64_t cpu_get_host_ticks(void) +{ + int64_t val; + + asm volatile("RDCYCLE %0" : "=r"(cc)); + return val; +} __riscv_xlen should never be undefined. OK Don't you need a loop for RDCYCLEH to avoid time going backward? do { asm("rdcycleh %0\n\t" "rdcycle %1\n\t" "rdcycleh %2\n\t" : "=r"(hi), "=r"(lo), "=r"(tmph)); } while (unlikely(tmph != hi)); Yes, I think we should do this for XLEN == 32bits. Thanks, Zhiwei r~
[RESEND] qemu/timer: Add host ticks function for RISC-V
From: LIU Zhiwei Signed-off-by: LIU Zhiwei --- include/qemu/timer.h | 19 +++ 1 file changed, 19 insertions(+) diff --git a/include/qemu/timer.h b/include/qemu/timer.h index 9a91cb1248..105767c195 100644 --- a/include/qemu/timer.h +++ b/include/qemu/timer.h @@ -979,6 +979,25 @@ static inline int64_t cpu_get_host_ticks(void) return cur - ofs; } +#elif defined(__riscv) && defined(__riscv_xlen) && __riscv_xlen == 32 +static inline int64_t cpu_get_host_ticks(void) +{ +uint32_t lo, hi; +asm volatile("RDCYCLE %0\n\t" + "RDCYCLEH %1" + : "=r"(lo), "=r"(hi)); +return lo | (uint64_t)hi << 32; +} + +#elif defined(__riscv) && defined(__riscv_xlen) && __riscv_xlen > 32 +static inline int64_t cpu_get_host_ticks(void) +{ +int64_t val; + +asm volatile("RDCYCLE %0" : "=r"(val)); +return val; +} + #else /* The host CPU doesn't have an easily accessible cycle counter. Just return a monotonically increasing value. This will be -- 2.17.1
[PATCH] qemu/timer: Add host ticks function for RISC-V
From: LIU Zhiwei Signed-off-by: LIU Zhiwei --- include/qemu/timer.h | 19 +++ 1 file changed, 19 insertions(+) diff --git a/include/qemu/timer.h b/include/qemu/timer.h index 9a91cb1248..ce0b66d122 100644 --- a/include/qemu/timer.h +++ b/include/qemu/timer.h @@ -979,6 +979,25 @@ static inline int64_t cpu_get_host_ticks(void) return cur - ofs; } +#elif defined(__riscv) && defined(__riscv_xlen) && __riscv_xlen == 32 +static inline int64_t cpu_get_host_ticks(void) +{ +uint32_t lo, hi; +asm volatile("RDCYCLE %0\n\t" + "RDCYCLEH %1" + : "=r"(lo), "=r"(hi)); +return lo | (uint64_t)hi << 32; +} + +#elif defined(__riscv) && defined(__riscv_xlen) && __riscv_xlen > 32 +static inline int64_t cpu_get_host_ticks(void) +{ +int64_t val; + +asm volatile("RDCYCLE %0" : "=r"(cc)); +return val; +} + #else /* The host CPU doesn't have an easily accessible cycle counter. Just return a monotonically increasing value. This will be -- 2.17.1
[PATCH 1/1] accel/tcg: Fix the comment for CPUTLBEntryFull
When memory region is ram, the lower TARGET_PAGE_BITS is not the physical section number. Instead, its value is always 0. Add comment and assert to make it clear. Signed-off-by: LIU Zhiwei --- accel/tcg/cputlb.c | 11 +++ include/exec/cpu-defs.h | 12 ++-- 2 files changed, 13 insertions(+), 10 deletions(-) diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c index d68fa6867c..a1ebf75068 100644 --- a/accel/tcg/cputlb.c +++ b/accel/tcg/cputlb.c @@ -1192,6 +1192,7 @@ void tlb_set_page_full(CPUState *cpu, int mmu_idx, write_flags = read_flags; if (is_ram) { iotlb = memory_region_get_ram_addr(section->mr) + xlat; +assert(!(iotlb & ~TARGET_PAGE_MASK)); /* * Computing is_clean is expensive; avoid all that unless * the page is actually writable. @@ -1254,10 +1255,12 @@ void tlb_set_page_full(CPUState *cpu, int mmu_idx, /* refill the tlb */ /* - * At this point iotlb contains a physical section number in the lower - * TARGET_PAGE_BITS, and either - * + the ram_addr_t of the page base of the target RAM (RAM) - * + the offset within section->mr of the page base (I/O, ROMD) + * When memory region is ram, iotlb contains a TARGET_PAGE_BITS + * aligned ram_addr_t of the page base of the target RAM. + * Otherwise, iotlb contains + * - a physical section number in the lower TARGET_PAGE_BITS + * - the offset within section->mr of the page base (I/O, ROMD) with the + *TARGET_PAGE_BITS masked off. * We subtract addr_page (which is page aligned and thus won't * disturb the low bits) to give an offset which can be added to the * (non-page-aligned) vaddr of the eventual memory access to get diff --git a/include/exec/cpu-defs.h b/include/exec/cpu-defs.h index fb4c8d480f..350287852e 100644 --- a/include/exec/cpu-defs.h +++ b/include/exec/cpu-defs.h @@ -100,12 +100,12 @@ typedef struct CPUTLBEntryFull { /* * @xlat_section contains: - * - in the lower TARGET_PAGE_BITS, a physical section number - * - with the lower TARGET_PAGE_BITS masked off, an offset which - *must be added to the virtual address to obtain: - * + the ram_addr_t of the target RAM (if the physical section - * number is PHYS_SECTION_NOTDIRTY or PHYS_SECTION_ROM) - * + the offset within the target MemoryRegion (otherwise) + * - For ram, an offset which must be added to the virtual address + *to obtain the ram_addr_t of the target RAM + * - For other memory regions, + * + in the lower TARGET_PAGE_BITS, the physical section number + * + with the TARGET_PAGE_BITS masked off, the offset within + * the target MemoryRegion */ hwaddr xlat_section; -- 2.17.1
Re: [RFC PATCH v2 0/6] Add API for list cpu extensions
On 2023/8/28 21:58, Igor Mammedov wrote: On Mon, 28 Aug 2023 16:45:30 +0800 LIU Zhiwei wrote: Some times we want to know what is the really mean of one cpu option. For example, in RISC-V, we usually specify a cpu in this way: -cpu rv64,v=on If we don't look into the source code, we can't get the ISA extensions of this -cpu command line. In this patch set, we add one list_cpu_props API for common cores. It will output the enabled ISA extensions. In the near future, I will also list all possible user configurable options and all possible extensions for this cpu. In order to reuse the options parse code, I also add a QemuOptsList for cpu. After this patch, we can output the extensions for cpu, """ ./qemu-system-riscv64 -cpu rv64,help Enabled extensions: rv64imafdch_zicbom_zicboz_zicsr_zifencei_zihintpause_zawrs_zfa_zba_zbb_zbc_zbs_sstc_svadu It's not that easy to get features with values in general. (many factors influence defaults, which may include: * properties set and/or added at realize time * defaults amended by machine type version * defaults amended by -global CLI options ) To do that consensus was to query features after CPU object is realized. Typically that implies starting dummy QEMU with needed CPU model and then using query-cpu-model-expansion command to get actual property values. I agree query-cpu-model-expansion command is necessary. But for users that manually run qemu command line, it is difficult to for them to give a json-based input. The task is solved by implementing query-cpu-model-expansion command so that user (mainly management layer) could get defaults via QMP. So if your goal is to get the given cpu defaults to mgmt layer it is sufficient to implement query-cpu-model-expansion command for riscv. (CC-ing libvirt folks to see if it picks up the command automatically for every target or some more work would be needed on their side as well) PS: no one cared about making -cpu name,help working till this moment and certainly not for linux-user part. To make this option work reliably it's would be necessary to make sure that query-cpu-model-expansion work in user mode as well. Also the timing when 'help' is processed should ensure that machine is available/initialized (i.e. compat properties are in effect) Agree. I can defer the helper handler process to the machine initialized stage. Thanks, Zhiwei Once you have working query-cpu-model-expansion, your new -cpu foo,help handler can translate json to human readable format that everyone would agree upon. To get all configuable options for this cpu, use -device rv64-riscv-cpu,help """ v1->v2: 1) Give a hint to use -device cpu,help for configualbe options on cpu 2) Support list_cpu_props for linux user mode 3) Add default to some properties to make -device cpu,help output better Todo: 1) Fix Daniel comments on KVM and cpu option check 2) Add support for other archs 3) Move qdev help function from qdev-monitor to qdev-property LIU Zhiwei (6): cpu: Add new API cpu_type_by_name target/riscv: Add API list_cpu_props softmmu/vl: Add qemu_cpu_opts QemuOptsList target/riscv: Add default value for misa property target/riscv: Add defalut value for string property linux-user: Move qemu_cpu_opts to cpu.c cpu.c| 63 +--- hw/core/qdev-prop-internal.h | 2 ++ hw/core/qdev-properties.c| 7 include/exec/cpu-common.h| 3 ++ include/hw/core/cpu.h| 11 +++ include/hw/qdev-properties.h | 8 + linux-user/main.c| 10 ++ softmmu/vl.c | 11 +++ target/riscv/cpu.c | 30 + target/riscv/cpu.h | 2 ++ 10 files changed, 128 insertions(+), 19 deletions(-)
[RFC PATCH v2 6/6] linux-user: Move qemu_cpu_opts to cpu.c
Make qemu_cpu_opts also works for linux user mode. Notice, currently qdev monitor is not included in linux user mode. We just output current enabled extentions for RISC-V(without the hint to print all properties with -device). With this patch, """ qemu-riscv64 -cpu rv64,help Enabled extensions: rv64_zicbom_zicboz_zicsr_zifencei_zihintpause_zawrs_zfa_zba_zbb_zbc_zbs_sstc_svadu """ Signed-off-by: LIU Zhiwei --- cpu.c | 24 include/exec/cpu-common.h | 2 ++ linux-user/main.c | 10 ++ softmmu/vl.c | 24 target/riscv/cpu.c| 8 +--- 5 files changed, 41 insertions(+), 27 deletions(-) diff --git a/cpu.c b/cpu.c index 712bd02684..590d75def0 100644 --- a/cpu.c +++ b/cpu.c @@ -47,6 +47,30 @@ uintptr_t qemu_host_page_size; intptr_t qemu_host_page_mask; +QemuOptsList qemu_cpu_opts = { +.name = "cpu", +.implied_opt_name = "cpu_model", +.head = QTAILQ_HEAD_INITIALIZER(qemu_cpu_opts.head), +.desc = { +{ /* end of list */ } +}, +}; + +int cpu_help_func(void *opaque, QemuOpts *opts, Error **errp) +{ +const char *cpu_model, *cpu_type; +cpu_model = qemu_opt_get(opts, "cpu_model"); +if (!cpu_model) { +return 1; +} +if (!qemu_opt_has_help_opt(opts)) { +return 0; +} +cpu_type = cpu_type_by_name(cpu_model); +list_cpu_props((CPUState *)object_new(cpu_type)); +return 1; +} + #ifndef CONFIG_USER_ONLY static int cpu_common_post_load(void *opaque, int version_id) { diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h index b3160d9218..4d385436a5 100644 --- a/include/exec/cpu-common.h +++ b/include/exec/cpu-common.h @@ -168,4 +168,6 @@ int cpu_memory_rw_debug(CPUState *cpu, vaddr addr, void list_cpus(void); void list_cpu_props(CPUState *); +int cpu_help_func(void *opaque, QemuOpts *opts, Error **errp); +extern QemuOptsList qemu_cpu_opts; #endif /* CPU_COMMON_H */ diff --git a/linux-user/main.c b/linux-user/main.c index 96be354897..c3ef84b1a7 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -362,6 +362,15 @@ static void handle_arg_cpu(const char *arg) list_cpus(); exit(EXIT_FAILURE); } +QemuOpts *opts = qemu_opts_parse_noisily(qemu_find_opts("cpu"), + arg, true); +if (!opts) { +exit(1); +} +if (qemu_opts_foreach(qemu_find_opts("cpu"), + cpu_help_func, NULL, NULL)) { +exit(0); +} } static void handle_arg_guest_base(const char *arg) @@ -720,6 +729,7 @@ int main(int argc, char **argv, char **envp) cpu_model = NULL; qemu_add_opts(_trace_opts); +qemu_add_opts(_cpu_opts); qemu_plugin_add_opts(); optind = parse_args(argc, argv); diff --git a/softmmu/vl.c b/softmmu/vl.c index bc30f3954d..d6a395454a 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -218,15 +218,6 @@ static struct { { .driver = "virtio-vga-gl",.flag = _vga }, }; -static QemuOptsList qemu_cpu_opts = { -.name = "cpu", -.implied_opt_name = "cpu_model", -.head = QTAILQ_HEAD_INITIALIZER(qemu_cpu_opts.head), -.desc = { -{ /* end of list */ } -}, -}; - static QemuOptsList qemu_rtc_opts = { .name = "rtc", .head = QTAILQ_HEAD_INITIALIZER(qemu_rtc_opts.head), @@ -1149,21 +1140,6 @@ static int parse_fw_cfg(void *opaque, QemuOpts *opts, Error **errp) return 0; } -static int cpu_help_func(void *opaque, QemuOpts *opts, Error **errp) -{ -const char *cpu_model, *cpu_type; -cpu_model = qemu_opt_get(opts, "cpu_model"); -if (!cpu_model) { -return 1; -} -if (!qemu_opt_has_help_opt(opts)) { -return 0; -} -cpu_type = cpu_type_by_name(cpu_model); -list_cpu_props((CPUState *)object_new(cpu_type)); -return 1; -} - static int device_help_func(void *opaque, QemuOpts *opts, Error **errp) { return qdev_device_help(opts); diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index edcd34e62b..e4318fcc46 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -2229,15 +2229,17 @@ void riscv_cpu_list(void) void riscv_cpu_list_props(CPUState *cs) { char *enabled_isa; -RISCVCPU *cpu = RISCV_CPU(cs); -RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(cpu); -ObjectClass *oc = OBJECT_CLASS(mcc); enabled_isa = riscv_isa_string(RISCV_CPU(cs)); qemu_printf("Enabled extensions:\n"); qemu_printf("\t%s\n", enabled_isa); +#ifndef CONFIG_USER_ONLY +RISCVCPU *cpu = RISCV_CPU(cs); +RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(cpu); +ObjectClass *oc = OBJECT_CLASS(mcc); qemu_printf("To get all configuable options for this cpu, use" " -device %s,help\n", object_class_get_name(oc)); +#endif } #define DEFINE_CPU(type_name, initfn) \ -- 2.17.1
[RFC PATCH v2 5/6] target/riscv: Add defalut value for string property
Before this patch, """ qemu-system-riscv64 -device rv64-riscv-cpu,v=true,help ... vext_spec= ... """ After this patch, """ vext_spec= - (default: "v1.0") """ Signed-off-by: LIU Zhiwei --- hw/core/qdev-prop-internal.h | 2 ++ hw/core/qdev-properties.c| 7 +++ include/hw/qdev-properties.h | 8 target/riscv/cpu.c | 2 +- 4 files changed, 18 insertions(+), 1 deletion(-) diff --git a/hw/core/qdev-prop-internal.h b/hw/core/qdev-prop-internal.h index d7b77844fe..f0613b9757 100644 --- a/hw/core/qdev-prop-internal.h +++ b/hw/core/qdev-prop-internal.h @@ -13,6 +13,8 @@ void qdev_propinfo_get_enum(Object *obj, Visitor *v, const char *name, void qdev_propinfo_set_enum(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp); +void qdev_propinfo_set_default_value_string(ObjectProperty *op, +const Property *prop); void qdev_propinfo_set_default_value_enum(ObjectProperty *op, const Property *prop); void qdev_propinfo_set_default_value_int(ObjectProperty *op, diff --git a/hw/core/qdev-properties.c b/hw/core/qdev-properties.c index 357b8761b5..64f70a7292 100644 --- a/hw/core/qdev-properties.c +++ b/hw/core/qdev-properties.c @@ -96,6 +96,12 @@ static ObjectPropertyAccessor *field_prop_setter(const PropertyInfo *info) return info->set ? field_prop_set : NULL; } +void qdev_propinfo_set_default_value_string(ObjectProperty *op, +const Property *prop) +{ +object_property_set_default_str(op, prop->defval.p); +} + void qdev_propinfo_get_enum(Object *obj, Visitor *v, const char *name, void *opaque, Error **errp) { @@ -488,6 +494,7 @@ const PropertyInfo qdev_prop_string = { .release = release_string, .get = get_string, .set = set_string, +.set_default_value = qdev_propinfo_set_default_value_string, }; /* --- on/off/auto --- */ diff --git a/include/hw/qdev-properties.h b/include/hw/qdev-properties.h index e1df08876c..8e5651724a 100644 --- a/include/hw/qdev-properties.h +++ b/include/hw/qdev-properties.h @@ -22,6 +22,7 @@ struct Property { union { int64_t i; uint64_t u; +void *p; } defval; int arrayoffset; const PropertyInfo *arrayinfo; @@ -91,6 +92,11 @@ extern const PropertyInfo qdev_prop_link; .set_default = true, \ .defval.u = (_type)_defval) +#define DEFINE_PROP_STR(_name, _state, _field, _defval, _prop, _type) \ +DEFINE_PROP(_name, _state, _field, _prop, _type, \ +.set_default = true, \ +.defval.p = (_type)_defval) + #define DEFINE_PROP_UNSIGNED_NODEFAULT(_name, _state, _field, _prop, _type) \ DEFINE_PROP(_name, _state, _field, _prop, _type) @@ -171,6 +177,8 @@ extern const PropertyInfo qdev_prop_link; DEFINE_PROP_UNSIGNED(_n, _s, _f, _d, qdev_prop_size, uint64_t) #define DEFINE_PROP_STRING(_n, _s, _f) \ DEFINE_PROP(_n, _s, _f, qdev_prop_string, char*) +#define DEFINE_PROP_STRING_DEF(_n, _s, _f, _d) \ +DEFINE_PROP_STR(_n, _s, _f, _d, qdev_prop_string, char*) #define DEFINE_PROP_ON_OFF_AUTO(_n, _s, _f, _d) \ DEFINE_PROP_SIGNED(_n, _s, _f, _d, qdev_prop_on_off_auto, OnOffAuto) #define DEFINE_PROP_SIZE32(_n, _s, _f, _d) \ diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 38838cd2c0..edcd34e62b 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -1769,7 +1769,7 @@ static Property riscv_cpu_extensions[] = { DEFINE_PROP_BOOL("sstc", RISCVCPU, cfg.ext_sstc, true), DEFINE_PROP_STRING("priv_spec", RISCVCPU, cfg.priv_spec), -DEFINE_PROP_STRING("vext_spec", RISCVCPU, cfg.vext_spec), +DEFINE_PROP_STRING_DEF("vext_spec", RISCVCPU, cfg.vext_spec, "v1.0"), DEFINE_PROP_UINT16("vlen", RISCVCPU, cfg.vlen, 128), DEFINE_PROP_UINT16("elen", RISCVCPU, cfg.elen, 64), -- 2.17.1
[RFC PATCH v2 4/6] target/riscv: Add default value for misa property
Before this patch, " qemu-system-riscv64 -device rv64-riscv-cpu,v=true,help ... v= - Vector operations ... " After this patch, " v= - Vector operations (default: false) " Signed-off-by: LIU Zhiwei --- target/riscv/cpu.c | 12 ++-- 1 file changed, 6 insertions(+), 6 deletions(-) diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index c2f102fae1..38838cd2c0 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -1728,6 +1728,7 @@ static void riscv_cpu_add_misa_properties(Object *cpu_obj) int i; for (i = 0; i < ARRAY_SIZE(misa_ext_cfgs); i++) { +ObjectProperty *op; RISCVCPUMisaExtConfig *misa_cfg = _ext_cfgs[i]; int bit = misa_cfg->misa_bit; @@ -1739,14 +1740,13 @@ static void riscv_cpu_add_misa_properties(Object *cpu_obj) continue; } -object_property_add(cpu_obj, misa_cfg->name, "bool", -cpu_get_misa_ext_cfg, -cpu_set_misa_ext_cfg, -NULL, (void *)misa_cfg); +op = object_property_add(cpu_obj, misa_cfg->name, "bool", + cpu_get_misa_ext_cfg, + cpu_set_misa_ext_cfg, + NULL, (void *)misa_cfg); object_property_set_description(cpu_obj, misa_cfg->name, misa_cfg->description); -object_property_set_bool(cpu_obj, misa_cfg->name, - misa_cfg->enabled, NULL); +object_property_set_default_bool(op, misa_cfg->enabled); } } -- 2.17.1
Re: [RFC PATCH 2/3] target/riscv: Add API list_cpu_props
On 2023/8/25 21:46, Daniel Henrique Barboza wrote: On 8/25/23 09:16, LIU Zhiwei wrote: This API used for output current configuration for one specified CPU. Currently only RISC-V frontend implements this API. Signed-off-by: LIU Zhiwei --- cpu.c | 8 include/exec/cpu-common.h | 1 + target/riscv/cpu.c | 10 ++ target/riscv/cpu.h | 2 ++ 4 files changed, 21 insertions(+) diff --git a/cpu.c b/cpu.c index e1a9239d0f..03a313cd72 100644 --- a/cpu.c +++ b/cpu.c @@ -299,6 +299,14 @@ void list_cpus(void) #endif } +void list_cpu_props(CPUState *cs) +{ + /* XXX: implement xxx_cpu_list_props for targets that still miss it */ +#if defined(cpu_list_props) + cpu_list_props(cs); +#endif +} + #if defined(CONFIG_USER_ONLY) void tb_invalidate_phys_addr(hwaddr addr) { diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h index 87dc9a752c..b3160d9218 100644 --- a/include/exec/cpu-common.h +++ b/include/exec/cpu-common.h @@ -166,5 +166,6 @@ int cpu_memory_rw_debug(CPUState *cpu, vaddr addr, /* vl.c */ void list_cpus(void); +void list_cpu_props(CPUState *); #endif /* CPU_COMMON_H */ diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 6b93b04453..3ea18de06f 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -2226,6 +2226,16 @@ void riscv_cpu_list(void) g_slist_free(list); } +void riscv_cpu_list_props(CPUState *cs) +{ + char *enabled_isa; + + enabled_isa = riscv_isa_string(RISCV_CPU(cs)); + qemu_printf("Enable extension:\n"); I suggest "Enabled extensions". LGTM otherwise. Fixed, thanks. Zhiwei Daniel + qemu_printf("\t%s\n", enabled_isa); + /* TODO: output all user configurable options and all possible extensions */ +} + #define DEFINE_CPU(type_name, initfn) \ { \ .name = type_name, \ diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 6ea22e0eea..af1d47605b 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -443,9 +443,11 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size, bool probe, uintptr_t retaddr); char *riscv_isa_string(RISCVCPU *cpu); void riscv_cpu_list(void); +void riscv_cpu_list_props(CPUState *cs); void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp); #define cpu_list riscv_cpu_list +#define cpu_list_props riscv_cpu_list_props #define cpu_mmu_index riscv_cpu_mmu_index #ifndef CONFIG_USER_ONLY
[RFC PATCH v2 3/6] softmmu/vl: Add qemu_cpu_opts QemuOptsList
This make the cpu works the similar way like the -device option. For device option, """ ./qemu-system-riscv64 -device e1000,help e1000 options: acpi-index=- (default: 0) addr= - Slot and optional function number, example: 06.0 or 06 (default: -1) autonegotiation= - on/off (default: true) bootindex= extra_mac_registers= - on/off (default: true) failover_pair_id= """ After this patch, the cpu can output its configurations, """ ./qemu-system-riscv64 -cpu rv64,help Enable extension: rv64imafdch_zicbom_zicboz_zicsr_zifencei_zihintpause_zawrs_zfa_zba_zbb_zbc_zbs_sstc_svadu """ Signed-off-by: LIU Zhiwei --- cpu.c | 2 +- include/hw/core/cpu.h | 11 +++ softmmu/vl.c | 35 +++ 3 files changed, 47 insertions(+), 1 deletion(-) diff --git a/cpu.c b/cpu.c index 03a313cd72..712bd02684 100644 --- a/cpu.c +++ b/cpu.c @@ -257,7 +257,7 @@ void cpu_exec_initfn(CPUState *cpu) #endif } -static const char *cpu_type_by_name(const char *cpu_model) +const char *cpu_type_by_name(const char *cpu_model) { ObjectClass *oc; const char *cpu_type; diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h index fdcbe87352..49d41afdfa 100644 --- a/include/hw/core/cpu.h +++ b/include/hw/core/cpu.h @@ -657,6 +657,17 @@ CPUState *cpu_create(const char *typename); */ const char *parse_cpu_option(const char *cpu_option); +/** + * cpu_type_by_name: + * @cpu_model: The -cpu command line model name. + * + * Looks up type name by the -cpu command line model name + * + * Returns: type name of CPU or prints error and terminates process + * if an error occurred. + */ +const char *cpu_type_by_name(const char *cpu_model); + /** * cpu_has_work: * @cpu: The vCPU to check. diff --git a/softmmu/vl.c b/softmmu/vl.c index b0b96f67fa..bc30f3954d 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -218,6 +218,15 @@ static struct { { .driver = "virtio-vga-gl",.flag = _vga }, }; +static QemuOptsList qemu_cpu_opts = { +.name = "cpu", +.implied_opt_name = "cpu_model", +.head = QTAILQ_HEAD_INITIALIZER(qemu_cpu_opts.head), +.desc = { +{ /* end of list */ } +}, +}; + static QemuOptsList qemu_rtc_opts = { .name = "rtc", .head = QTAILQ_HEAD_INITIALIZER(qemu_rtc_opts.head), @@ -1140,6 +1149,21 @@ static int parse_fw_cfg(void *opaque, QemuOpts *opts, Error **errp) return 0; } +static int cpu_help_func(void *opaque, QemuOpts *opts, Error **errp) +{ +const char *cpu_model, *cpu_type; +cpu_model = qemu_opt_get(opts, "cpu_model"); +if (!cpu_model) { +return 1; +} +if (!qemu_opt_has_help_opt(opts)) { +return 0; +} +cpu_type = cpu_type_by_name(cpu_model); +list_cpu_props((CPUState *)object_new(cpu_type)); +return 1; +} + static int device_help_func(void *opaque, QemuOpts *opts, Error **errp) { return qdev_device_help(opts); @@ -2467,6 +2491,11 @@ static void qemu_process_help_options(void) exit(0); } +if (qemu_opts_foreach(qemu_find_opts("cpu"), + cpu_help_func, NULL, NULL)) { +exit(0); +} + if (qemu_opts_foreach(qemu_find_opts("device"), device_help_func, NULL, NULL)) { exit(0); @@ -2680,6 +2709,7 @@ void qemu_init(int argc, char **argv) qemu_add_drive_opts(_runtime_opts); qemu_add_opts(_chardev_opts); qemu_add_opts(_device_opts); +qemu_add_opts(_cpu_opts); qemu_add_opts(_netdev_opts); qemu_add_opts(_nic_opts); qemu_add_opts(_net_opts); @@ -2756,6 +2786,11 @@ void qemu_init(int argc, char **argv) case QEMU_OPTION_cpu: /* hw initialization will check this */ cpu_option = optarg; +opts = qemu_opts_parse_noisily(qemu_find_opts("cpu"), + optarg, true); +if (!opts) { +exit(1); +} break; case QEMU_OPTION_hda: case QEMU_OPTION_hdb: -- 2.17.1
[RFC PATCH v2 2/6] target/riscv: Add API list_cpu_props
This API used for output current configuration for one specified CPU. Currently only RISC-V frontend implements this API. Signed-off-by: LIU Zhiwei --- cpu.c | 8 include/exec/cpu-common.h | 1 + target/riscv/cpu.c| 14 ++ target/riscv/cpu.h| 2 ++ 4 files changed, 25 insertions(+) diff --git a/cpu.c b/cpu.c index e1a9239d0f..03a313cd72 100644 --- a/cpu.c +++ b/cpu.c @@ -299,6 +299,14 @@ void list_cpus(void) #endif } +void list_cpu_props(CPUState *cs) +{ +/* XXX: implement xxx_cpu_list_props for targets that still miss it */ +#if defined(cpu_list_props) +cpu_list_props(cs); +#endif +} + #if defined(CONFIG_USER_ONLY) void tb_invalidate_phys_addr(hwaddr addr) { diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h index 87dc9a752c..b3160d9218 100644 --- a/include/exec/cpu-common.h +++ b/include/exec/cpu-common.h @@ -166,5 +166,6 @@ int cpu_memory_rw_debug(CPUState *cpu, vaddr addr, /* vl.c */ void list_cpus(void); +void list_cpu_props(CPUState *); #endif /* CPU_COMMON_H */ diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 6b93b04453..c2f102fae1 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -2226,6 +2226,20 @@ void riscv_cpu_list(void) g_slist_free(list); } +void riscv_cpu_list_props(CPUState *cs) +{ +char *enabled_isa; +RISCVCPU *cpu = RISCV_CPU(cs); +RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(cpu); +ObjectClass *oc = OBJECT_CLASS(mcc); + +enabled_isa = riscv_isa_string(RISCV_CPU(cs)); +qemu_printf("Enabled extensions:\n"); +qemu_printf("\t%s\n", enabled_isa); +qemu_printf("To get all configuable options for this cpu, use" +" -device %s,help\n", object_class_get_name(oc)); +} + #define DEFINE_CPU(type_name, initfn) \ { \ .name = type_name, \ diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 6ea22e0eea..af1d47605b 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -443,9 +443,11 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size, bool probe, uintptr_t retaddr); char *riscv_isa_string(RISCVCPU *cpu); void riscv_cpu_list(void); +void riscv_cpu_list_props(CPUState *cs); void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp); #define cpu_list riscv_cpu_list +#define cpu_list_props riscv_cpu_list_props #define cpu_mmu_index riscv_cpu_mmu_index #ifndef CONFIG_USER_ONLY -- 2.17.1
[RFC PATCH v2 0/6] Add API for list cpu extensions
Some times we want to know what is the really mean of one cpu option. For example, in RISC-V, we usually specify a cpu in this way: -cpu rv64,v=on If we don't look into the source code, we can't get the ISA extensions of this -cpu command line. In this patch set, we add one list_cpu_props API for common cores. It will output the enabled ISA extensions. In the near future, I will also list all possible user configurable options and all possible extensions for this cpu. In order to reuse the options parse code, I also add a QemuOptsList for cpu. After this patch, we can output the extensions for cpu, """ ./qemu-system-riscv64 -cpu rv64,help Enabled extensions: rv64imafdch_zicbom_zicboz_zicsr_zifencei_zihintpause_zawrs_zfa_zba_zbb_zbc_zbs_sstc_svadu To get all configuable options for this cpu, use -device rv64-riscv-cpu,help """ v1->v2: 1) Give a hint to use -device cpu,help for configualbe options on cpu 2) Support list_cpu_props for linux user mode 3) Add default to some properties to make -device cpu,help output better Todo: 1) Fix Daniel comments on KVM and cpu option check 2) Add support for other archs 3) Move qdev help function from qdev-monitor to qdev-property LIU Zhiwei (6): cpu: Add new API cpu_type_by_name target/riscv: Add API list_cpu_props softmmu/vl: Add qemu_cpu_opts QemuOptsList target/riscv: Add default value for misa property target/riscv: Add defalut value for string property linux-user: Move qemu_cpu_opts to cpu.c cpu.c| 63 +--- hw/core/qdev-prop-internal.h | 2 ++ hw/core/qdev-properties.c| 7 include/exec/cpu-common.h| 3 ++ include/hw/core/cpu.h| 11 +++ include/hw/qdev-properties.h | 8 + linux-user/main.c| 10 ++ softmmu/vl.c | 11 +++ target/riscv/cpu.c | 30 + target/riscv/cpu.h | 2 ++ 10 files changed, 128 insertions(+), 19 deletions(-) -- 2.17.1
[RFC PATCH v2 1/6] cpu: Add new API cpu_type_by_name
cpu_type_by_name is used to get the cpu type name from the command line -cpu. Currently it is only used by parse_cpu_option. In the next patch, it will be used by other cpu query functions. Signed-off-by: LIU Zhiwei --- cpu.c | 31 +++ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/cpu.c b/cpu.c index 1c948d1161..e1a9239d0f 100644 --- a/cpu.c +++ b/cpu.c @@ -257,28 +257,35 @@ void cpu_exec_initfn(CPUState *cpu) #endif } -const char *parse_cpu_option(const char *cpu_option) +static const char *cpu_type_by_name(const char *cpu_model) { ObjectClass *oc; -CPUClass *cc; -gchar **model_pieces; const char *cpu_type; -model_pieces = g_strsplit(cpu_option, ",", 2); -if (!model_pieces[0]) { -error_report("-cpu option cannot be empty"); -exit(1); -} -oc = cpu_class_by_name(CPU_RESOLVING_TYPE, model_pieces[0]); +oc = cpu_class_by_name(CPU_RESOLVING_TYPE, cpu_model); if (oc == NULL) { -error_report("unable to find CPU model '%s'", model_pieces[0]); -g_strfreev(model_pieces); +error_report("unable to find CPU model '%s'", cpu_model); exit(EXIT_FAILURE); } cpu_type = object_class_get_name(oc); -cc = CPU_CLASS(oc); +return cpu_type; +} + +const char *parse_cpu_option(const char *cpu_option) +{ +const char *cpu_type; +CPUClass *cc; +gchar **model_pieces; + +model_pieces = g_strsplit(cpu_option, ",", 2); +if (!model_pieces[0]) { +error_report("-cpu option cannot be empty"); +exit(1); +} +cpu_type = cpu_type_by_name(model_pieces[0]); +cc = CPU_CLASS(object_class_by_name(cpu_type)); cc->parse_features(cpu_type, model_pieces[1], _fatal); g_strfreev(model_pieces); return cpu_type; -- 2.17.1
Re: [RFC PATCH 3/3] softmmu/vl: Add qemu_cpu_opts QemuOptsList
Hi Drew On 2023/8/25 23:58, Andrew Jones wrote: On Fri, Aug 25, 2023 at 08:16:51PM +0800, LIU Zhiwei wrote: This make the cpu works the similar way like the -device option. For device option, """ ./qemu-system-riscv64 -device e1000,help e1000 options: acpi-index=- (default: 0) addr= - Slot and optional function number, example: 06.0 or 06 (default: -1) autonegotiation= - on/off (default: true) bootindex= extra_mac_registers= - on/off (default: true) failover_pair_id= """ After this patch, the cpu can output its configurations, """ ./qemu-system-riscv64 -cpu rv64,help Enable extension: rv64imafdch_zicbom_zicboz_zicsr_zifencei_zihintpause_zawrs_zfa_zba_zbb_zbc_zbs_sstc_svadu """ I recommend we make it more similar to -device and list the properties (not just extensions). Besides a listing being easier to read than the isa string format, listing properties would also output, e.g. cbom_blocksize=- (default: 64) which would also be helpful. I agree that we should add more outputs in cpu_list_props to aid the understanding of the isa string output. And let users know what they should explicitly added the -cpu command line. I will refer to the -device option output. However, The -device option is not enough for cpu model. """ qemu-system-riscv64 -device rv64-riscv-cpu,zba=false,help rv64-riscv-cpu options: Zawrs= - (default: true) Zfa= - (default: true) Zfh= - (default: false) Zfhmin= - (default: false) Zicsr= - (default: true) Zifencei= - (default: true) Zihintpause= - (default: true) Zve32f= - (default: false) Zve64d= - (default: false) Zve64f= - (default: false) a= - Atomic instructions c= - Compressed instructions cbom_blocksize= - (default: 64) cboz_blocksize= - (default: 64) d= - Double-precision float point ... unnamed-gpio-in[0]=> unnamed-gpio-in[10]=> unnamed-gpio-in[11]=> unnamed-gpio-in[12]=> unnamed-gpio-in[13]=> unnamed-gpio-in[14]=> ... memory=> ... start-powered-off= ... v= - Vector operations vext_spec= ... zba= - (default: true) zbb= - (default: true) zbc= - (default: true) zbkb= - (default: false) ... """ 1) IMHO, unnamed-gpio-in and start-powered-off exposing to users is meaningless. 2) Option like v and vext_spec doesn't output the defalut value. 3) The zba=false in command line can't reflect in the output. That is the reason why I want to add a new API cpu_list_props. Thanks, Zhwei Thanks, drew Signed-off-by: LIU Zhiwei --- cpu.c | 2 +- include/hw/core/cpu.h | 11 +++ softmmu/vl.c | 35 +++ 3 files changed, 47 insertions(+), 1 deletion(-) diff --git a/cpu.c b/cpu.c index 03a313cd72..712bd02684 100644 --- a/cpu.c +++ b/cpu.c @@ -257,7 +257,7 @@ void cpu_exec_initfn(CPUState *cpu) #endif } -static const char *cpu_type_by_name(const char *cpu_model) +const char *cpu_type_by_name(const char *cpu_model) { ObjectClass *oc; const char *cpu_type; diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h index fdcbe87352..49d41afdfa 100644 --- a/include/hw/core/cpu.h +++ b/include/hw/core/cpu.h @@ -657,6 +657,17 @@ CPUState *cpu_create(const char *typename); */ const char *parse_cpu_option(const char *cpu_option); +/** + * cpu_type_by_name: + * @cpu_model: The -cpu command line model name. + * + * Looks up type name by the -cpu command line model name + * + * Returns: type name of CPU or prints error and terminates process + * if an error occurred. + */ +const char *cpu_type_by_name(const char *cpu_model); + /** * cpu_has_work: * @cpu: The vCPU to check. diff --git a/softmmu/vl.c b/softmmu/vl.c index b0b96f67fa..bc30f3954d 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -218,6 +218,15 @@ static struct { { .driver = "virtio-vga-gl",.flag = _vga }, }; +static QemuOptsList qemu_cpu_opts = { +.name = "cpu", +.implied_opt_name = "cpu_model", +.head = QTAILQ_HEAD_INITIALIZER(qemu_cpu_opts.head), +.desc = { +{ /* end of list */ } +}, +}; + static QemuOptsList qemu_rtc_opts = { .name = "rtc", .head = QTAILQ_HEAD_INITIALIZER(qemu_rtc_opts.head), @@ -1140,6 +1149,21 @@ static int parse_fw_cfg(void *opaque, QemuOpts *opts, Error **errp) return 0; } +static int cpu_help_func(void *opaque, QemuOpts *opts, Error **errp) +{ +const char *cpu_model, *cpu_type; +cpu_model = qemu_opt_get(opts, "cpu_model"); +if (!cpu_model) { +return 1; +} +if (!qemu_opt_has_help_opt(opts))
[RFC PATCH 3/3] softmmu/vl: Add qemu_cpu_opts QemuOptsList
This make the cpu works the similar way like the -device option. For device option, """ ./qemu-system-riscv64 -device e1000,help e1000 options: acpi-index=- (default: 0) addr= - Slot and optional function number, example: 06.0 or 06 (default: -1) autonegotiation= - on/off (default: true) bootindex= extra_mac_registers= - on/off (default: true) failover_pair_id= """ After this patch, the cpu can output its configurations, """ ./qemu-system-riscv64 -cpu rv64,help Enable extension: rv64imafdch_zicbom_zicboz_zicsr_zifencei_zihintpause_zawrs_zfa_zba_zbb_zbc_zbs_sstc_svadu """ Signed-off-by: LIU Zhiwei --- cpu.c | 2 +- include/hw/core/cpu.h | 11 +++ softmmu/vl.c | 35 +++ 3 files changed, 47 insertions(+), 1 deletion(-) diff --git a/cpu.c b/cpu.c index 03a313cd72..712bd02684 100644 --- a/cpu.c +++ b/cpu.c @@ -257,7 +257,7 @@ void cpu_exec_initfn(CPUState *cpu) #endif } -static const char *cpu_type_by_name(const char *cpu_model) +const char *cpu_type_by_name(const char *cpu_model) { ObjectClass *oc; const char *cpu_type; diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h index fdcbe87352..49d41afdfa 100644 --- a/include/hw/core/cpu.h +++ b/include/hw/core/cpu.h @@ -657,6 +657,17 @@ CPUState *cpu_create(const char *typename); */ const char *parse_cpu_option(const char *cpu_option); +/** + * cpu_type_by_name: + * @cpu_model: The -cpu command line model name. + * + * Looks up type name by the -cpu command line model name + * + * Returns: type name of CPU or prints error and terminates process + * if an error occurred. + */ +const char *cpu_type_by_name(const char *cpu_model); + /** * cpu_has_work: * @cpu: The vCPU to check. diff --git a/softmmu/vl.c b/softmmu/vl.c index b0b96f67fa..bc30f3954d 100644 --- a/softmmu/vl.c +++ b/softmmu/vl.c @@ -218,6 +218,15 @@ static struct { { .driver = "virtio-vga-gl",.flag = _vga }, }; +static QemuOptsList qemu_cpu_opts = { +.name = "cpu", +.implied_opt_name = "cpu_model", +.head = QTAILQ_HEAD_INITIALIZER(qemu_cpu_opts.head), +.desc = { +{ /* end of list */ } +}, +}; + static QemuOptsList qemu_rtc_opts = { .name = "rtc", .head = QTAILQ_HEAD_INITIALIZER(qemu_rtc_opts.head), @@ -1140,6 +1149,21 @@ static int parse_fw_cfg(void *opaque, QemuOpts *opts, Error **errp) return 0; } +static int cpu_help_func(void *opaque, QemuOpts *opts, Error **errp) +{ +const char *cpu_model, *cpu_type; +cpu_model = qemu_opt_get(opts, "cpu_model"); +if (!cpu_model) { +return 1; +} +if (!qemu_opt_has_help_opt(opts)) { +return 0; +} +cpu_type = cpu_type_by_name(cpu_model); +list_cpu_props((CPUState *)object_new(cpu_type)); +return 1; +} + static int device_help_func(void *opaque, QemuOpts *opts, Error **errp) { return qdev_device_help(opts); @@ -2467,6 +2491,11 @@ static void qemu_process_help_options(void) exit(0); } +if (qemu_opts_foreach(qemu_find_opts("cpu"), + cpu_help_func, NULL, NULL)) { +exit(0); +} + if (qemu_opts_foreach(qemu_find_opts("device"), device_help_func, NULL, NULL)) { exit(0); @@ -2680,6 +2709,7 @@ void qemu_init(int argc, char **argv) qemu_add_drive_opts(_runtime_opts); qemu_add_opts(_chardev_opts); qemu_add_opts(_device_opts); +qemu_add_opts(_cpu_opts); qemu_add_opts(_netdev_opts); qemu_add_opts(_nic_opts); qemu_add_opts(_net_opts); @@ -2756,6 +2786,11 @@ void qemu_init(int argc, char **argv) case QEMU_OPTION_cpu: /* hw initialization will check this */ cpu_option = optarg; +opts = qemu_opts_parse_noisily(qemu_find_opts("cpu"), + optarg, true); +if (!opts) { +exit(1); +} break; case QEMU_OPTION_hda: case QEMU_OPTION_hdb: -- 2.17.1
[RFC PATCH 0/3] Add API for list cpu extensions
Some times we want to know what is the really mean of one cpu option. For example, in RISC-V, we usually specify a cpu in this way: -cpu rv64,v=on If we don't look into the source code, we can't get the ISA extensions of this -cpu command line. In this patch set, we add one list_cpu_props API for common cores. It will output the enabled ISA extensions. In the near future, I will also list all possible user configurable options and all possible extensions for this cpu. In order to reuse the options parse code, I also add a QemuOptsList for cpu. After this patch, we can output the extensions for cpu, """ ./qemu-system-riscv64 -cpu rv64,help Enable extension: rv64imafdch_zicbom_zicboz_zicsr_zifencei_zihintpause_zawrs_zfa_zba_zbb_zbc_zbs_sstc_svadu """ Notice currently this patch is only working for RISC-V system mode. Thanks Andrew Jones for your suggestion! Todo: 1) Output all possible user configurable options and all extensions. 2) Add support for RISC-V linux-user mode 3) Add support for other archs LIU Zhiwei (3): cpu: Add new API cpu_type_by_name target/riscv: Add API list_cpu_props softmmu/vl: Add qemu_cpu_opts QemuOptsList cpu.c | 39 +++ include/exec/cpu-common.h | 1 + include/hw/core/cpu.h | 11 +++ softmmu/vl.c | 35 +++ target/riscv/cpu.c| 10 ++ target/riscv/cpu.h| 2 ++ 6 files changed, 86 insertions(+), 12 deletions(-) -- 2.17.1
[RFC PATCH 2/3] target/riscv: Add API list_cpu_props
This API used for output current configuration for one specified CPU. Currently only RISC-V frontend implements this API. Signed-off-by: LIU Zhiwei --- cpu.c | 8 include/exec/cpu-common.h | 1 + target/riscv/cpu.c| 10 ++ target/riscv/cpu.h| 2 ++ 4 files changed, 21 insertions(+) diff --git a/cpu.c b/cpu.c index e1a9239d0f..03a313cd72 100644 --- a/cpu.c +++ b/cpu.c @@ -299,6 +299,14 @@ void list_cpus(void) #endif } +void list_cpu_props(CPUState *cs) +{ +/* XXX: implement xxx_cpu_list_props for targets that still miss it */ +#if defined(cpu_list_props) +cpu_list_props(cs); +#endif +} + #if defined(CONFIG_USER_ONLY) void tb_invalidate_phys_addr(hwaddr addr) { diff --git a/include/exec/cpu-common.h b/include/exec/cpu-common.h index 87dc9a752c..b3160d9218 100644 --- a/include/exec/cpu-common.h +++ b/include/exec/cpu-common.h @@ -166,5 +166,6 @@ int cpu_memory_rw_debug(CPUState *cpu, vaddr addr, /* vl.c */ void list_cpus(void); +void list_cpu_props(CPUState *); #endif /* CPU_COMMON_H */ diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index 6b93b04453..3ea18de06f 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -2226,6 +2226,16 @@ void riscv_cpu_list(void) g_slist_free(list); } +void riscv_cpu_list_props(CPUState *cs) +{ +char *enabled_isa; + +enabled_isa = riscv_isa_string(RISCV_CPU(cs)); +qemu_printf("Enable extension:\n"); +qemu_printf("\t%s\n", enabled_isa); +/* TODO: output all user configurable options and all possible extensions */ +} + #define DEFINE_CPU(type_name, initfn) \ { \ .name = type_name, \ diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index 6ea22e0eea..af1d47605b 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -443,9 +443,11 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size, bool probe, uintptr_t retaddr); char *riscv_isa_string(RISCVCPU *cpu); void riscv_cpu_list(void); +void riscv_cpu_list_props(CPUState *cs); void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, Error **errp); #define cpu_list riscv_cpu_list +#define cpu_list_props riscv_cpu_list_props #define cpu_mmu_index riscv_cpu_mmu_index #ifndef CONFIG_USER_ONLY -- 2.17.1
[RFC PATCH 1/3] cpu: Add new API cpu_type_by_name
cpu_type_by_name is used to get the cpu type name from the command line -cpu. Currently it is only used by parse_cpu_option. In the next patch, it will be used by other cpu query functions. Signed-off-by: LIU Zhiwei --- cpu.c | 31 +++ 1 file changed, 19 insertions(+), 12 deletions(-) diff --git a/cpu.c b/cpu.c index 1c948d1161..e1a9239d0f 100644 --- a/cpu.c +++ b/cpu.c @@ -257,28 +257,35 @@ void cpu_exec_initfn(CPUState *cpu) #endif } -const char *parse_cpu_option(const char *cpu_option) +static const char *cpu_type_by_name(const char *cpu_model) { ObjectClass *oc; -CPUClass *cc; -gchar **model_pieces; const char *cpu_type; -model_pieces = g_strsplit(cpu_option, ",", 2); -if (!model_pieces[0]) { -error_report("-cpu option cannot be empty"); -exit(1); -} -oc = cpu_class_by_name(CPU_RESOLVING_TYPE, model_pieces[0]); +oc = cpu_class_by_name(CPU_RESOLVING_TYPE, cpu_model); if (oc == NULL) { -error_report("unable to find CPU model '%s'", model_pieces[0]); -g_strfreev(model_pieces); +error_report("unable to find CPU model '%s'", cpu_model); exit(EXIT_FAILURE); } cpu_type = object_class_get_name(oc); -cc = CPU_CLASS(oc); +return cpu_type; +} + +const char *parse_cpu_option(const char *cpu_option) +{ +const char *cpu_type; +CPUClass *cc; +gchar **model_pieces; + +model_pieces = g_strsplit(cpu_option, ",", 2); +if (!model_pieces[0]) { +error_report("-cpu option cannot be empty"); +exit(1); +} +cpu_type = cpu_type_by_name(model_pieces[0]); +cc = CPU_CLASS(object_class_by_name(cpu_type)); cc->parse_features(cpu_type, model_pieces[1], _fatal); g_strfreev(model_pieces); return cpu_type; -- 2.17.1
Re: [PATCH] target/riscv: Allocate itrigger timers only once
On 2023/8/17 0:27, Akihiko Odaki wrote: riscv_trigger_init() had been called on reset events that can happen several times for a CPU and it allocated timers for itrigger. If old timers were present, they were simply overwritten by the new timers, resulting in a memory leak. Divide riscv_trigger_init() into two functions, namely riscv_trigger_realize() and riscv_trigger_reset() and call them in appropriate timing. The timer allocation will happen only once for a CPU in riscv_trigger_realize(). Fixes: 5a4ae64cac ("target/riscv: Add itrigger support when icount is enabled") Signed-off-by: Akihiko Odaki --- target/riscv/debug.h | 3 ++- target/riscv/cpu.c | 8 +++- target/riscv/debug.c | 15 --- 3 files changed, 21 insertions(+), 5 deletions(-) diff --git a/target/riscv/debug.h b/target/riscv/debug.h index c471748d5a..7edc31e7cc 100644 --- a/target/riscv/debug.h +++ b/target/riscv/debug.h @@ -143,7 +143,8 @@ void riscv_cpu_debug_excp_handler(CPUState *cs); bool riscv_cpu_debug_check_breakpoint(CPUState *cs); bool riscv_cpu_debug_check_watchpoint(CPUState *cs, CPUWatchpoint *wp); -void riscv_trigger_init(CPURISCVState *env); +void riscv_trigger_realize(CPURISCVState *env); +void riscv_trigger_reset(CPURISCVState *env); bool riscv_itrigger_enabled(CPURISCVState *env); void riscv_itrigger_update_priv(CPURISCVState *env); diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c index e12b6ef7f6..3bc3f96a58 100644 --- a/target/riscv/cpu.c +++ b/target/riscv/cpu.c @@ -904,7 +904,7 @@ static void riscv_cpu_reset_hold(Object *obj) #ifndef CONFIG_USER_ONLY if (cpu->cfg.debug) { -riscv_trigger_init(env); +riscv_trigger_reset(env); } if (kvm_enabled()) { @@ -1475,6 +1475,12 @@ static void riscv_cpu_realize(DeviceState *dev, Error **errp) riscv_cpu_register_gdb_regs_for_features(cs); +#ifndef CONFIG_USER_ONLY +if (cpu->cfg.debug) { +riscv_trigger_realize(>env); +} +#endif + qemu_init_vcpu(cs); cpu_reset(cs); diff --git a/target/riscv/debug.c b/target/riscv/debug.c index 75ee1c4971..1c44403205 100644 --- a/target/riscv/debug.c +++ b/target/riscv/debug.c @@ -903,7 +903,17 @@ bool riscv_cpu_debug_check_watchpoint(CPUState *cs, CPUWatchpoint *wp) return false; } -void riscv_trigger_init(CPURISCVState *env) +void riscv_trigger_realize(CPURISCVState *env) +{ +int i; + +for (i = 0; i < RV_MAX_TRIGGERS; i++) { +env->itrigger_timer[i] = timer_new_ns(QEMU_CLOCK_VIRTUAL, + riscv_itrigger_timer_cb, env); +} +} + +void riscv_trigger_reset(CPURISCVState *env) { target_ulong tdata1 = build_tdata1(env, TRIGGER_TYPE_AD_MATCH, 0, 0); int i; @@ -928,7 +938,6 @@ void riscv_trigger_init(CPURISCVState *env) env->tdata3[i] = 0; env->cpu_breakpoint[i] = NULL; env->cpu_watchpoint[i] = NULL; -env->itrigger_timer[i] = timer_new_ns(QEMU_CLOCK_VIRTUAL, - riscv_itrigger_timer_cb, env); +timer_del(env->itrigger_timer[i]); Reviewed-by: LIU Zhiwei Zhiwei } }
[PATCH v2] linux-user/riscv: Use abi type for target_ucontext
We should not use types dependend on host arch for target_ucontext. This bug is found when run rv32 applications. Signed-off-by: LIU Zhiwei Reviewed-by: Richard Henderson Reviewed-by: Daniel Henrique Barboza --- v2: - Use abi_ptr instead of abi_ulong for uc_link. (Suggest by Philippe Mathieu-Daudé) --- linux-user/riscv/signal.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/linux-user/riscv/signal.c b/linux-user/riscv/signal.c index eaa168199a..f989f7f51f 100644 --- a/linux-user/riscv/signal.c +++ b/linux-user/riscv/signal.c @@ -38,8 +38,8 @@ struct target_sigcontext { }; /* cf. riscv-linux:arch/riscv/include/uapi/asm/ptrace.h */ struct target_ucontext { -unsigned long uc_flags; -struct target_ucontext *uc_link; +abi_ulong uc_flags; +abi_ptr uc_link; target_stack_t uc_stack; target_sigset_t uc_sigmask; uint8_t __unused[1024 / 8 - sizeof(target_sigset_t)]; -- 2.17.1
Re: [PATCH] linux-user/riscv: Use abi_ulong for target_ucontext
On 2023/8/10 18:48, Philippe Mathieu-Daudé wrote: On 8/8/23 11:34, LIU Zhiwei wrote: We should not use types dependend on host arch for target_ucontext. This bug is found when run rv32 applications. Signed-off-by: LIU Zhiwei --- linux-user/riscv/signal.c | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/linux-user/riscv/signal.c b/linux-user/riscv/signal.c index eaa168199a..ff8634a272 100644 --- a/linux-user/riscv/signal.c +++ b/linux-user/riscv/signal.c @@ -38,8 +38,8 @@ struct target_sigcontext { }; /* cf. riscv-linux:arch/riscv/include/uapi/asm/ptrace.h */ struct target_ucontext { - unsigned long uc_flags; - struct target_ucontext *uc_link; + abi_ulong uc_flags; Correct. + abi_ulong uc_link; Isn't it 'abi_ptr uc_link' instead? Thanks, I think abi_ptr is better. As RISC-V doesn't has similar ABI as sparc32plus(64bit long but 32bit space address). It is also right here. And many arches use the abi_ulong for uc_link, such as ARM. I will send a v2 patch. Zhiwei target_stack_t uc_stack; target_sigset_t uc_sigmask; uint8_t __unused[1024 / 8 - sizeof(target_sigset_t)];