From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from lists.gnu.org (lists.gnu.org [209.51.188.17]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.lore.kernel.org (Postfix) with ESMTPS id E074FC27C5E for ; Mon, 10 Jun 2024 14:12:44 +0000 (UTC) Received: from localhost ([::1] helo=lists1p.gnu.org) by lists.gnu.org with esmtp (Exim 4.90_1) (envelope-from ) id 1sGfkq-0001fm-6T; Mon, 10 Jun 2024 10:12:12 -0400 Received: from eggs.gnu.org ([2001:470:142:3::10]) by lists.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_256_GCM_SHA384:256) (Exim 4.90_1) (envelope-from ) id 1sGfko-0001eU-3z for qemu-devel@nongnu.org; Mon, 10 Jun 2024 10:12:10 -0400 Received: from mail-lf1-x130.google.com ([2a00:1450:4864:20::130]) by eggs.gnu.org with esmtps (TLS1.2:ECDHE_RSA_AES_128_GCM_SHA256:128) (Exim 4.90_1) (envelope-from ) id 1sGfkj-0002pO-LY for qemu-devel@nongnu.org; Mon, 10 Jun 2024 10:12:09 -0400 Received: by mail-lf1-x130.google.com with SMTP id 2adb3069b0e04-52c819f6146so2420137e87.1 for ; Mon, 10 Jun 2024 07:12:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=rivosinc-com.20230601.gappssmtp.com; s=20230601; t=1718028722; x=1718633522; darn=nongnu.org; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:from:to:cc:subject:date:message-id:reply-to; bh=ivox2W8sxS/bjywmyH03eVUmMDpwedjtsCPSqCXwe4A=; b=qnfN3MykhUreX0eIj6ye7foGavNHd9HJI6mcLj6SuEPxRIOHKJM062toMU9EsZH5Y9 LcZq+dVo+BSCqytgamJdbnv+0AvnkFIRSL0nQqJPiRyNiPe/PL6nd4LfgdTS64704Br7 NTUUdYSbrL9kFM5+f3vAT/alDfONrYD6uCEqKLvBERYAxpkVQxUUtNS0uzuPX4bbRojM mz5pfttRuvsVBeIauFTr0X1v0XIvePgNyWzIClJ/dZV4UBtVrG8PbBBl8NhkwamYkVMY dAwXAa+e9diTlJvPhDUYlDHzLvQ7LQJzKnz5I6kW3YXIBtbMZ9+qsrhLgGNDbDs7k2XV BZBw== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1718028722; x=1718633522; h=cc:to:subject:message-id:date:from:in-reply-to:references :mime-version:x-gm-message-state:from:to:cc:subject:date:message-id :reply-to; bh=ivox2W8sxS/bjywmyH03eVUmMDpwedjtsCPSqCXwe4A=; b=qn9W3+A/vKx8BhMIVfxOwqT2pWEXoiqfgqjjhSGf5raDGdLIV8HhWLDN3dKqB0cq1k rnEG9U11rlQ+nRo8Edb31yap1MJ1DlWds6a2j1tj5XxiY1tfNM/6SW05TntYqkw5Xjne dc8e+dlKG4OzJI6uvlcejqJvQ9HuYAghBCp4GWdvqHW6rBsCpZXHGIYr6LICsJ86w/ON RpxFy6z9NdV3wJMAlMe1VzPUKQQ++65XK+e4CyOeSDTZ87P+Qe/oX705iuDZ3sJjAaJU SSxUHknom7iLgjzu+ODAdfZ3tWcxL6k07FefeG8PvNd49G9epE/IT3vnM6fBFwohTlo0 i4Sw== X-Forwarded-Encrypted: i=1; AJvYcCWtTdJExJcy/l04VC2KZbgwD0w9EJQXYXrn4DEgjByvWGGyoTIsY6xAwtHJCtmI4pGnUC1C60jCBRaHjEjXfBVcmKOin1M= X-Gm-Message-State: AOJu0Yx+WeAowqqubPt162+k3/EHbgfRxfGLk4yOeAtWG9+8Ch7Z7B7S p1ASjxXU9KxFg9Z7Q5rJIOuhiAtvAq5Kl9hYUZ+MHXgkh43nxM8mAx65Yk13JUwJXojbEaTxceN 2Y61t9giievzETIIrmMUtJm7XP8PfqZKwfNnXVw== X-Google-Smtp-Source: AGHT+IHzAbHctT6F0UHQF+Gm+fctISLb9TM1Ee/jylMVjHgdxkEbKd9nE2sfjmJ+E2mrM+nvI/XOQ9tF3gKus5NkpBc= X-Received: by 2002:a05:6512:282a:b0:52c:85d1:6eb3 with SMTP id 2adb3069b0e04-52c85d16fcdmr3823044e87.30.1718028721913; Mon, 10 Jun 2024 07:12:01 -0700 (PDT) MIME-Version: 1.0 References: <20240529160950.132754-1-rkanwal@rivosinc.com> <20240529160950.132754-4-rkanwal@rivosinc.com> <3f3cc0f1-0a56-452a-a934-b3f770056570@sifive.com> In-Reply-To: <3f3cc0f1-0a56-452a-a934-b3f770056570@sifive.com> From: Rajnesh Kanwal Date: Mon, 10 Jun 2024 15:11:50 +0100 Message-ID: Subject: Re: [PATCH 3/6] target/riscv: Add support for Control Transfer Records extension CSRs. To: Jason Chien Cc: qemu-riscv@nongnu.org, qemu-devel@nongnu.org, alistair.francis@wdc.com, bin.meng@windriver.com, liweiwei@iscas.ac.cn, dbarboza@ventanamicro.com, zhiwei_liu@linux.alibaba.com, atishp@rivosinc.com, apatel@ventanamicro.com, beeman@rivosinc.com, tech-control-transfer-records@lists.riscv.org Content-Type: multipart/alternative; boundary="000000000000af1fd5061a89bb96" Received-SPF: pass client-ip=2a00:1450:4864:20::130; envelope-from=rkanwal@rivosinc.com; helo=mail-lf1-x130.google.com X-Spam_score_int: -18 X-Spam_score: -1.9 X-Spam_bar: - X-Spam_report: (-1.9 / 5.0 requ) BAYES_00=-1.9, DKIM_SIGNED=0.1, DKIM_VALID=-0.1, HTML_MESSAGE=0.001, RCVD_IN_DNSWL_NONE=-0.0001, SPF_HELO_NONE=0.001, SPF_PASS=-0.001, T_SCC_BODY_TEXT_LINE=-0.01 autolearn=ham autolearn_force=no X-Spam_action: no action X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Errors-To: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org Sender: qemu-devel-bounces+qemu-devel=archiver.kernel.org@nongnu.org --000000000000af1fd5061a89bb96 Content-Type: text/plain; charset="UTF-8" Content-Transfer-Encoding: quoted-printable Thanks Jason for your review. On Tue, Jun 4, 2024 at 11:14=E2=80=AFAM Jason Chien wrote: > > > Rajnesh Kanwal =E6=96=BC 2024/5/30 =E4=B8=8A=E5=8D=88 12:09 =E5=AF=AB=E9= =81=93: > > This commit adds support for [m|s|vs]ctrcontrol, sctrstatus and > sctrdepth CSRs handling. > > Signed-off-by: Rajnesh Kanwal > --- > target/riscv/cpu.h | 5 ++ > target/riscv/cpu_cfg.h | 2 + > target/riscv/csr.c | 159 +++++++++++++++++++++++++++++++++++++++++ > 3 files changed, 166 insertions(+) > > diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h > index a185e2d494..3d4d5172b8 100644 > --- a/target/riscv/cpu.h > +++ b/target/riscv/cpu.h > @@ -263,6 +263,11 @@ struct CPUArchState { > target_ulong mcause; > target_ulong mtval; /* since: priv-1.10.0 */ > > + uint64_t mctrctl; > + uint32_t sctrdepth; > + uint32_t sctrstatus; > + uint64_t vsctrctl; > + > /* Machine and Supervisor interrupt priorities */ > uint8_t miprio[64]; > uint8_t siprio[64]; > diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h > index d9354dc80a..d329a65811 100644 > --- a/target/riscv/cpu_cfg.h > +++ b/target/riscv/cpu_cfg.h > @@ -123,6 +123,8 @@ struct RISCVCPUConfig { > bool ext_zvfhmin; > bool ext_smaia; > bool ext_ssaia; > + bool ext_smctr; > + bool ext_ssctr; > bool ext_sscofpmf; > bool ext_smepmp; > bool rvv_ta_all_1s; > diff --git a/target/riscv/csr.c b/target/riscv/csr.c > index 2f92e4b717..888084d8e5 100644 > --- a/target/riscv/csr.c > +++ b/target/riscv/csr.c > @@ -621,6 +621,61 @@ static RISCVException pointer_masking(CPURISCVState *env, int csrno) > return RISCV_EXCP_ILLEGAL_INST; > } > > +/* > + * M-mode: > + * Without ext_smctr raise illegal inst excep. > + * Otherwise everything is accessible to m-mode. > + * > + * S-mode: > + * Without ext_ssctr or mstateen.ctr raise illegal inst excep. > + * Otherwise everything other than mctrctl is accessible. > + * > + * VS-mode: > + * Without ext_ssctr or mstateen.ctr raise illegal inst excep. > + * Without hstateen.ctr raise virtual illegal inst excep. > + * Otherwise allow vsctrctl, sctrstatus, 0x200-0x2ff entry range. > + * Always raise illegal instruction exception for sctrdepth. > + */ > +static RISCVException ctr_mmode(CPURISCVState *env, int csrno) > +{ > + /* Check if smctr-ext is present */ > + if (riscv_cpu_cfg(env)->ext_smctr) { > + return RISCV_EXCP_NONE; > + } > + > + return RISCV_EXCP_ILLEGAL_INST; > +} > + > +static RISCVException ctr_smode(CPURISCVState *env, int csrno) > +{ > + if ((env->priv =3D=3D PRV_M && riscv_cpu_cfg(env)->ext_smctr) || > + (env->priv =3D=3D PRV_S && !env->virt_enabled && > + riscv_cpu_cfg(env)->ext_ssctr)) { > + return smstateen_acc_ok(env, 0, SMSTATEEN0_CTR); > + } > + > + if (env->priv =3D=3D PRV_S && env->virt_enabled && > + riscv_cpu_cfg(env)->ext_ssctr) { > + if (csrno =3D=3D CSR_SCTRSTATUS) { > > missing sctrctl? > > + return smstateen_acc_ok(env, 0, SMSTATEEN0_CTR); > + } > + > + return RISCV_EXCP_VIRT_INSTRUCTION_FAULT; > + } > + > + return RISCV_EXCP_ILLEGAL_INST; > +} > > I think there is no need to bind M-mode with ext_smctr, S-mode with ext_ssctr and VS-mode with ext_ssctr, since this predicate function is for S-mode CSRs, which are defined in both smctr and ssctr, we just need to check at least one of ext_ssctr or ext_smctr is true. > > The spec states that: > Attempts to access sctrdepth from VS-mode or VU-mode raise a virtual-instruction exception, unless CTR state enable access restrictions apply. > > In my understanding, we should check the presence of smstateen extension first, and > > if smstateen is implemented: > > for sctrctl and sctrstatus, call smstateen_acc_ok() > for sctrdepth, call smstateen_acc_ok(), and if there is any exception returned, always report virtual-instruction exception. For sctrdepth, we are supposed to always return a virt-inst exception in case of VS-VU mode unless CTR state enable access restrictions apply. So for sctrdepth, call smstateen_acc_ok(), and if there is no exception returned (mstateen.CTR=3D1 and hstateen.CTR=3D1 for virt mode), check if we are in virtual mode and return virtual-instruction exception otherwise return RISCV_EXCP_NONE. Note that if hstateen.CTR=3D0, smstateen_acc_ok() will return virtual-instruction exception which means regardless of the hstateen.CTR state, we will always return virtual-instruction exception for VS/VU mode access to sctrdepth. Basically this covers following rules for sctrdepth: if mstateen.ctr =3D=3D 0 return RISCV_EXCP_ILLEGAL_INST; // For all modes lower than M-mode. else if in virt-mode // regardless of the state of hstateen.CTR return RISCV_EXCP_VIRT_INSTRUCTION_FAULT; else return RISCV_EXCP_NONE > > If smstateen is not implemented: > > for sctrctl and sctrstatus, there is no check. > for sctrdepth, I think the spec is ambiguous. What does "CTR state enable access restrictions apply" mean when smstateen is not implemented? As per my understanding, this means if mstateen.CTR=3D0 then we return an illegal instruction exception regardless if it's virtual mode or not. This is the only effect of CTR state enable on sctrdepth CSR. If mstateen.CTR=3D1, sctrdepth access from VS-mode results in virtual-instruction exception regardless of hstateen.CTR. Based on this, we have following model for predicate checks: if smstateen is implemented: for sctrctl and sctrstatus, call smstateen_acc_ok() for sctrdepth, call smstateen_acc_ok(), and if there is no exception, check if we are in virtual mode and return virtual-instruction exceptio= n otherwise return RISCV_EXCP_NONE. If smstateen is not implemented: for sctrctl and sctrstatus, there is no check. for sctrdepth, if in VS/VU mode return virtual-instruction exception otherwise no check. Here is the code to better understand this. static RISCVException ctr_smode(CPURISCVState *env, int csrno) { const RISCVCPUConfig *cfg =3D riscv_cpu_cfg(env); if (!cfg->ext_ssctr && !cfg->ext_smctr) { return RISCV_EXCP_ILLEGAL_INST; } if (riscv_cpu_cfg(env)->ext_smstateen) { RISCVException ret =3D smstateen_acc_ok(env, 0, SMSTATEEN0_CTR); if (ret =3D=3D RISCV_EXCP_NONE && csrno =3D=3D CSR_SCTRDEPTH && env->virt_enabled) { return RISCV_EXCP_VIRT_INSTRUCTION_FAULT; } return ret; } else { if (csrno =3D=3D CSR_SCTRDEPTH && env->virt_enabled) { return RISCV_EXCP_VIRT_INSTRUCTION_FAULT; } } return RISCV_EXCP_NONE; } Given smstateen_acc_ok() returns RISCV_EXCP_NONE in case if ext_smstateen is not implemented, this can be further simplified to: static RISCVException ctr_smode(CPURISCVState *env, int csrno) { const RISCVCPUConfig *cfg =3D riscv_cpu_cfg(env); if (!cfg->ext_ssctr && !cfg->ext_smctr) { return RISCV_EXCP_ILLEGAL_INST; } RISCVException ret =3D smstateen_acc_ok(env, 0, SMSTATEEN0_CTR); if (ret =3D=3D RISCV_EXCP_NONE && csrno =3D=3D CSR_SCTRDEPTH && env->virt_enabled) { return RISCV_EXCP_VIRT_INSTRUCTION_FAULT; } return ret; } > > Here is the code to better understand my description. > > static RISCVException ctr_smode(CPURISCVState *env, int csrno) > { > const RISCVCPUConfig *cfg =3D riscv_cpu_cfg(env); > > if (!cfg->ext_ssctr && !cfg->ext_smctr) { > return RISCV_EXCP_ILLEGAL_INST; > } > > if (riscv_cpu_cfg(env)->ext_smstateen) { > RISCVException ret =3D smstateen_acc_ok(env, 0, SMSTATEEN0_CTR); > if (ret !=3D RISCV_EXCP_NONE) { > if (csrno =3D=3D CSR_SCTRDEPTH && env->virt_enabled) { > return RISCV_EXCP_VIRT_INSTRUCTION_FAULT; > } > > return ret; > } > } else { > /* The spec is ambiguous. */ > if (csrno =3D=3D CSR_SCTRDEPTH && env->virt_enabled) { > return RISCV_EXCP_VIRT_INSTRUCTION_FAULT; > } > } > > return RISCV_EXCP_NONE; > } > > + > +static RISCVException ctr_vsmode(CPURISCVState *env, int csrno) > +{ > + if (env->priv =3D=3D PRV_S && env->virt_enabled && > + riscv_cpu_cfg(env)->ext_ssctr) { > + return smstateen_acc_ok(env, 0, SMSTATEEN0_CTR); > > In riscv_csrrw_check(), an virtual-instruction exception is always reported no matter what. Do we need this check? > > + } > + > + return ctr_smode(env, csrno); > +} > + > static RISCVException aia_hmode(CPURISCVState *env, int csrno) > { > int ret; > @@ -3835,6 +3890,100 @@ static RISCVException write_satp(CPURISCVState *env, int csrno, > return RISCV_EXCP_NONE; > } > > +static RISCVException rmw_sctrdepth(CPURISCVState *env, int csrno, > + target_ulong *ret_val, > + target_ulong new_val, target_ulong wr_mask) > +{ > + uint64_t mask =3D wr_mask & SCTRDEPTH_MASK; > + > + if (ret_val) { > + *ret_val =3D env->sctrdepth & SCTRDEPTH_MASK; > > We don't need to do bitwise and with SCTRDEPTH_MASK on read accesses when we always do bitwise and with SCTRDEPTH_MASK on write accesses. > > + } > + > + env->sctrdepth =3D (env->sctrdepth & ~mask) | (new_val & mask); > + > + /* Correct depth. */ > + if (wr_mask & SCTRDEPTH_MASK) { > + uint64_t depth =3D get_field(env->sctrdepth, SCTRDEPTH_MASK); > + > + if (depth > SCTRDEPTH_MAX) { > + env->sctrdepth =3D > + set_field(env->sctrdepth, SCTRDEPTH_MASK, SCTRDEPTH_MAX)= ; > + } > + > + /* Update sctrstatus.WRPTR with a legal value */ > + depth =3D 16 << depth; > > The "depth" on the right side may exceed SCTRDEPTH_MAX. > > + env->sctrstatus =3D > + env->sctrstatus & (~SCTRSTATUS_WRPTR_MASK | (depth - 1)); > + } > + > + return RISCV_EXCP_NONE; > +} > + > +static RISCVException rmw_mctrctl(CPURISCVState *env, int csrno, > + target_ulong *ret_val, > + target_ulong new_val, target_ulong wr_mask) > +{ > + uint64_t mask =3D wr_mask & MCTRCTL_MASK; > + > + if (ret_val) { > + *ret_val =3D env->mctrctl & MCTRCTL_MASK; > > There is no need to do bitwise and with the mask on read accesses when we always do bitwise and with the mask on write accesses. > > + } > + > + env->mctrctl =3D (env->mctrctl & ~mask) | (new_val & mask); > + > + return RISCV_EXCP_NONE; > +} > + > +static RISCVException rmw_sctrctl(CPURISCVState *env, int csrno, > + target_ulong *ret_val, > + target_ulong new_val, target_ulong wr_mask) > +{ > + uint64_t mask =3D wr_mask & SCTRCTL_MASK; > + RISCVException ret; > + > + ret =3D rmw_mctrctl(env, csrno, ret_val, new_val, mask); > > When V=3D1, vsctrctl substitutes for sctrctl. > > + if (ret_val) { > + *ret_val &=3D SCTRCTL_MASK; > + } > + > + return ret; > +} > + > +static RISCVException rmw_sctrstatus(CPURISCVState *env, int csrno, > + target_ulong *ret_val, > + target_ulong new_val, target_ulong wr_mask) > +{ > + uint32_t depth =3D 16 << get_field(env->sctrdepth, SCTRDEPTH_MASK); > + uint32_t mask =3D wr_mask & SCTRSTATUS_MASK; > + > + if (ret_val) { > + *ret_val =3D env->sctrstatus & SCTRSTATUS_MASK; > > There is no need to do bitwise and with the mask on read accesses when we always do bitwise and with the mask on write accesses. > > + } > + > + env->sctrstatus =3D (env->sctrstatus & ~mask) | (new_val & mask); > + > + /* Update sctrstatus.WRPTR with a legal value */ > + env->sctrstatus =3D env->sctrstatus & (~SCTRSTATUS_WRPTR_MASK | (dep= th - 1)); > + > + return RISCV_EXCP_NONE; > +} > + > +static RISCVException rmw_vsctrctl(CPURISCVState *env, int csrno, > + target_ulong *ret_val, > + target_ulong new_val, target_ulong wr_mask) > +{ > + uint64_t mask =3D wr_mask & VSCTRCTL_MASK; > + > + if (ret_val) { > + *ret_val =3D env->vsctrctl & VSCTRCTL_MASK; > > There is no need to do bitwise and with the mask on read accesses when we always do bitwise and with the mask on write accesses. > > + } > + > + env->vsctrctl =3D (env->vsctrctl & ~mask) | (new_val & mask); > + > + return RISCV_EXCP_NONE; > +} > > Is it possible to define rmw_xctrctl() instead of three individual rmw functions and use a switch case to select the mask and the CSR for the purpose of reducing code size? > > + > static RISCVException read_vstopi(CPURISCVState *env, int csrno, > target_ulong *val) > { > @@ -5771,6 +5920,16 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] =3D { > [CSR_SPMBASE] =3D { "spmbase", pointer_masking, read_spmbase, > write_spmbase }, > > + [CSR_MCTRCTL] =3D { "mctrctl", ctr_mmode, NULL, NULL, > + rmw_mctrctl }, > > I think this can be one line. > > + [CSR_SCTRCTL] =3D { "sctrctl", ctr_smode, NULL, NULL, > + rmw_sctrctl }, > > same here > > + [CSR_SCTRDEPTH] =3D { "sctrdepth", ctr_smode, NULL, NULL= , > + rmw_sctrdepth }, > > same here > > + [CSR_SCTRSTATUS] =3D { "sctrstatus", ctr_smode, NULL, NU= LL, > + rmw_sctrstatus }, > > same here > > + [CSR_VSCTRCTL] =3D { "vsctrctl", ctr_vsmode, NULL, NULL, > + rmw_vsctrctl }, > > same here > > /* Performance Counters */ > [CSR_HPMCOUNTER3] =3D { "hpmcounter3", ctr, read_hpmcounter= }, > [CSR_HPMCOUNTER4] =3D { "hpmcounter4", ctr, read_hpmcounter= }, --000000000000af1fd5061a89bb96 Content-Type: text/html; charset="UTF-8" Content-Transfer-Encoding: quoted-printable

Thanks Jason for your review.

On Tue, Jun 4, 20= 24 at 11:14=E2=80=AFAM Jason Chien <jason.chien@sifive.com> wrote:
>
>
> Rajnesh= Kanwal =E6=96=BC 2024/5/30 =E4=B8=8A=E5=8D=88 12:09 =E5=AF=AB=E9=81=93:>
> This commit adds support for [m|s|vs]ctrcontrol, sctrstatus a= nd
> sctrdepth CSRs handling.
>
> Signed-off-by: Rajnesh = Kanwal <rkanwal@rivosinc.com= >
> ---
> =C2=A0target/riscv/cpu.h =C2=A0 =C2=A0 | =C2=A0 5 = ++
> =C2=A0target/riscv/cpu_cfg.h | =C2=A0 2 +
> =C2=A0target/r= iscv/csr.c =C2=A0 =C2=A0 | 159 +++++++++++++++++++++++++++++++++++++++++> =C2=A03 files changed, 166 insertions(+)
>
> diff --git a= /target/riscv/cpu.h b/target/riscv/cpu.h
> index a185e2d494..3d4d5172= b8 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h=
> @@ -263,6 +263,11 @@ struct CPUArchState {
> =C2=A0 =C2=A0 = =C2=A0target_ulong mcause;
> =C2=A0 =C2=A0 =C2=A0target_ulong mtval; = =C2=A0/* since: priv-1.10.0 */
> =C2=A0
> + =C2=A0 =C2=A0uint64= _t mctrctl;
> + =C2=A0 =C2=A0uint32_t sctrdepth;
> + =C2=A0 =C2= =A0uint32_t sctrstatus;
> + =C2=A0 =C2=A0uint64_t vsctrctl;
> +=
> =C2=A0 =C2=A0 =C2=A0/* Machine and Supervisor interrupt priorities= */
> =C2=A0 =C2=A0 =C2=A0uint8_t miprio[64];
> =C2=A0 =C2=A0 = =C2=A0uint8_t siprio[64];
> diff --git a/target/riscv/cpu_cfg.h b/tar= get/riscv/cpu_cfg.h
> index d9354dc80a..d329a65811 100644
> ---= a/target/riscv/cpu_cfg.h
> +++ b/target/riscv/cpu_cfg.h
> @@ -= 123,6 +123,8 @@ struct RISCVCPUConfig {
> =C2=A0 =C2=A0 =C2=A0bool ex= t_zvfhmin;
> =C2=A0 =C2=A0 =C2=A0bool ext_smaia;
> =C2=A0 =C2= =A0 =C2=A0bool ext_ssaia;
> + =C2=A0 =C2=A0bool ext_smctr;
> + = =C2=A0 =C2=A0bool ext_ssctr;
> =C2=A0 =C2=A0 =C2=A0bool ext_sscofpmf;=
> =C2=A0 =C2=A0 =C2=A0bool ext_smepmp;
> =C2=A0 =C2=A0 =C2=A0b= ool rvv_ta_all_1s;
> diff --git a/target/riscv/csr.c b/target/riscv/c= sr.c
> index 2f92e4b717..888084d8e5 100644
> --- a/target/riscv= /csr.c
> +++ b/target/riscv/csr.c
> @@ -621,6 +621,61 @@ static= RISCVException pointer_masking(CPURISCVState *env, int csrno)
> =C2= =A0 =C2=A0 =C2=A0return RISCV_EXCP_ILLEGAL_INST;
> =C2=A0}
> = =C2=A0
> +/*
> + * M-mode:
> + * Without ext_smctr raise = illegal inst excep.
> + * Otherwise everything is accessible to m-mod= e.
> + *
> + * S-mode:
> + * Without ext_ssctr or mstatee= n.ctr raise illegal inst excep.
> + * Otherwise everything other than= mctrctl is accessible.
> + *
> + * VS-mode:
> + * Withou= t ext_ssctr or mstateen.ctr raise illegal inst excep.
> + * Without h= stateen.ctr raise virtual illegal inst excep.
> + * Otherwise allow v= sctrctl, sctrstatus, 0x200-0x2ff entry range.
> + * Always raise ille= gal instruction exception for sctrdepth.
> + */
> +static RISCV= Exception ctr_mmode(CPURISCVState *env, int csrno)
> +{
> + =C2= =A0 =C2=A0/* Check if smctr-ext is present */
> + =C2=A0 =C2=A0if (ri= scv_cpu_cfg(env)->ext_smctr) {
> + =C2=A0 =C2=A0 =C2=A0 =C2=A0retu= rn RISCV_EXCP_NONE;
> + =C2=A0 =C2=A0}
> +
> + =C2=A0 =C2= =A0return RISCV_EXCP_ILLEGAL_INST;
> +}
> +
> +static RIS= CVException ctr_smode(CPURISCVState *env, int csrno)
> +{
> + = =C2=A0 =C2=A0if ((env->priv =3D=3D PRV_M && riscv_cpu_cfg(env)-&= gt;ext_smctr) ||
> + =C2=A0 =C2=A0 =C2=A0 =C2=A0(env->priv =3D=3D = PRV_S && !env->virt_enabled &&
> + =C2=A0 =C2=A0 = =C2=A0 =C2=A0 riscv_cpu_cfg(env)->ext_ssctr)) {
> + =C2=A0 =C2=A0 = =C2=A0 =C2=A0return smstateen_acc_ok(env, 0, SMSTATEEN0_CTR);
> + =C2= =A0 =C2=A0}
> +
> + =C2=A0 =C2=A0if (env->priv =3D=3D PRV_S = && env->virt_enabled &&
> + =C2=A0 =C2=A0 =C2=A0 = =C2=A0riscv_cpu_cfg(env)->ext_ssctr) {
> + =C2=A0 =C2=A0 =C2=A0 = =C2=A0if (csrno =3D=3D CSR_SCTRSTATUS) {
>
> missing sctrctl?>
> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0return smstateen_= acc_ok(env, 0, SMSTATEEN0_CTR);
> + =C2=A0 =C2=A0 =C2=A0 =C2=A0}
&= gt; +
> + =C2=A0 =C2=A0 =C2=A0 =C2=A0return RISCV_EXCP_VIRT_INSTRUCTI= ON_FAULT;
> + =C2=A0 =C2=A0}
> +
> + =C2=A0 =C2=A0return = RISCV_EXCP_ILLEGAL_INST;
> +}
>
> I think there is no nee= d to bind M-mode with ext_smctr, S-mode with ext_ssctr and VS-mode with ext= _ssctr, since this predicate function is for S-mode CSRs, which are defined= in both smctr and ssctr, we just need to check at least one of ext_ssctr o= r ext_smctr is true.
>
> The spec states that:
> Attempts= to access sctrdepth from VS-mode or VU-mode raise a virtual-instruction ex= ception, unless CTR state enable access restrictions apply.
>
>= In my understanding, we should check the presence of smstateen extension f= irst, and
>
> if smstateen is implemented:
>
> for = sctrctl and sctrstatus, call smstateen_acc_ok()
> for sctrdepth, call= smstateen_acc_ok(), and if there is any exception returned, always report = virtual-instruction exception.

For sctrdepth, we are supposed to alw= ays return a virt-inst exception in case of
VS-VU mode unless CTR state = enable access restrictions apply.

So for sctrdepth, call smstateen_a= cc_ok(), and if there is no exception returned
(mstateen.CTR=3D1 and hst= ateen.CTR=3D1 for virt mode), check if we are in virtual
mode and r= eturn virtual-instruction exception otherwise return RISCV_EXCP_NONE.
=
Note that if hstateen.CTR=3D0, smstateen_acc_ok() will return virtual-= instruction
exception which means regardless of the hstateen.CTR = state, we will always
return virtual-instruction exception for VS= /VU mode access to sctrdepth.

Basically this covers following = rules for sctrdepth:

if mstateen.ctr =3D=3D 0
=C2=A0 =C2=A0 retur= n RISCV_EXCP_ILLEGAL_INST; // For all modes lower than M-mode.
else if i= n virt-mode // regardless of the state of hstateen.CTR
=C2=A0 =C2=A0 ret= urn RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
else
=C2=A0 =C2=A0 return RISC= V_EXCP_NONE

>
> If smstateen is not implemented:
>> for sctrctl and sctrstatus, there is no check.
> for sctrdepth,= I think the spec is ambiguous. What does "CTR state enable access res= trictions apply" mean when smstateen is not implemented?

As per= my understanding, this means if mstateen.CTR=3D0 then we return an
ille= gal instruction exception regardless if it's virtual mode or not. This = is
the only effect of CTR state enable on sctrdepth CSR. If mstateen.CTR= =3D1,
sctrdepth access from VS-mode results in virtual-instruction excep= tion
regardless of hstateen.CTR.

Based on this, we have following= model for predicate checks:

if smstateen is implemented:

for= sctrctl and sctrstatus, call smstateen_acc_ok()
for sctrdepth, call sms= tateen_acc_ok(), and if there is no exception,
=C2=A0 =C2=A0 check if we= are in virtual mode and return virtual-instruction exception
=C2=A0 =C2= =A0 otherwise return RISCV_EXCP_NONE.

If smstateen is not implemente= d:

for sctrctl and sctrstatus, there is no check.
for sctrdepth, = if in VS/VU mode return virtual-instruction exception otherwise
=C2=A0 = =C2=A0 no check.

Here is the code to better understand this.

= static RISCVException ctr_smode(CPURISCVState *env, int csrno)
{
=C2= =A0 =C2=A0 const RISCVCPUConfig *cfg =3D riscv_cpu_cfg(env);

=C2=A0 = =C2=A0 if (!cfg->ext_ssctr && !cfg->ext_smctr) {
=C2=A0 = =C2=A0 =C2=A0 =C2=A0 return RISCV_EXCP_ILLEGAL_INST;
=C2=A0 =C2=A0 }
=
=C2=A0 =C2=A0 if (riscv_cpu_cfg(env)->ext_smstateen) {
=C2=A0 =C2= =A0 =C2=A0 =C2=A0 RISCVException ret =3D smstateen_acc_ok(env, 0, SMSTATEEN= 0_CTR);
=C2=A0 =C2=A0 =C2=A0 =C2=A0 if (ret =3D=3D RISCV_EXCP_NONE &= & csrno =3D=3D CSR_SCTRDEPTH && env->virt_enabled) {
=C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 return RISCV_EXCP_VIRT_INSTRUCTION_F= AULT;
=C2=A0 =C2=A0 =C2=A0 =C2=A0 }
=C2=A0 =C2=A0 =C2=A0 =C2=A0 retur= n ret;
=C2=A0 =C2=A0 } else {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 if (csrno = =3D=3D CSR_SCTRDEPTH && env->virt_enabled) {
=C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
= =C2=A0 =C2=A0 =C2=A0 =C2=A0 }
=C2=A0 =C2=A0 }

=C2=A0 =C2=A0 retur= n RISCV_EXCP_NONE;
}

Given smstateen_acc_ok() returns RISCV_EXCP_= NONE in case if ext_smstateen is not
implemented, this can be further si= mplified to:

static RISCVException ctr_smode(CPURISCVState *env, int= csrno)
{
=C2=A0 =C2=A0 const RISCVCPUConfig *cfg =3D riscv_cpu_cfg(e= nv);

=C2=A0 =C2=A0 if (!cfg->ext_ssctr && !cfg->ext_sm= ctr) {
=C2=A0 =C2=A0 =C2=A0 =C2=A0 return RISCV_EXCP_ILLEGAL_INST;
= =C2=A0 =C2=A0 }

=C2=A0 =C2=A0 RISCVException ret =3D smstateen_acc_o= k(env, 0, SMSTATEEN0_CTR);
=C2=A0 =C2=A0 if (ret =3D=3D RISCV_EXCP_NONE = && csrno =3D=3D CSR_SCTRDEPTH && env->virt_enabled) {=C2=A0 =C2=A0 =C2=A0 =C2=A0 return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
= =C2=A0 =C2=A0 }
=C2=A0 =C2=A0 return ret;
}

>
> Here = is the code to better understand my description.
>
> static RIS= CVException ctr_smode(CPURISCVState *env, int csrno)
> {
> =C2= =A0 =C2=A0 const RISCVCPUConfig *cfg =3D riscv_cpu_cfg(env);
>
>= ; =C2=A0 =C2=A0 if (!cfg->ext_ssctr && !cfg->ext_smctr) {
= > =C2=A0 =C2=A0 =C2=A0 =C2=A0 return RISCV_EXCP_ILLEGAL_INST;
> = =C2=A0 =C2=A0 }
>
> =C2=A0 =C2=A0 if (riscv_cpu_cfg(env)->ex= t_smstateen) {
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 RISCVException ret =3D s= mstateen_acc_ok(env, 0, SMSTATEEN0_CTR);
> =C2=A0 =C2=A0 =C2=A0 =C2= =A0 if (ret !=3D RISCV_EXCP_NONE) {
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 if (csrno =3D=3D CSR_SCTRDEPTH && env->virt_enabled) = {
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 return RI= SCV_EXCP_VIRT_INSTRUCTION_FAULT;
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 }
>
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 return = ret;
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 }
> =C2=A0 =C2=A0 } else {> =C2=A0 =C2=A0 =C2=A0 =C2=A0 /* The spec is ambiguous. */
> =C2= =A0 =C2=A0 =C2=A0 =C2=A0 if (csrno =3D=3D CSR_SCTRDEPTH && env->= virt_enabled) {
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 return RI= SCV_EXCP_VIRT_INSTRUCTION_FAULT;
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 }
&= gt; =C2=A0 =C2=A0 }
>
> =C2=A0 =C2=A0 return RISCV_EXCP_NONE;> }
>
> +
> +static RISCVException ctr_vsmode(CPURIS= CVState *env, int csrno)
> +{
> + =C2=A0 =C2=A0if (env->priv= =3D=3D PRV_S && env->virt_enabled &&
> + =C2=A0 = =C2=A0 =C2=A0 =C2=A0riscv_cpu_cfg(env)->ext_ssctr) {
> + =C2=A0 = =C2=A0 =C2=A0 =C2=A0return smstateen_acc_ok(env, 0, SMSTATEEN0_CTR);
>= ;
> In riscv_csrrw_check(), an virtual-instruction exception is alway= s reported no matter what. Do we need this check?
>
> + =C2=A0 = =C2=A0}
> +
> + =C2=A0 =C2=A0return ctr_smode(env, csrno);
&= gt; +}
> +
> =C2=A0static RISCVException aia_hmode(CPURISCVStat= e *env, int csrno)
> =C2=A0{
> =C2=A0 =C2=A0 =C2=A0int ret;
= > @@ -3835,6 +3890,100 @@ static RISCVException write_satp(CPURISCVState= *env, int csrno,
> =C2=A0 =C2=A0 =C2=A0return RISCV_EXCP_NONE;
&g= t; =C2=A0}
> =C2=A0
> +static RISCVException rmw_sctrdepth(CPUR= ISCVState *env, int csrno,
> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0target_ulong *ret_val,
> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0target_ulong new_val, target_ulong wr_mask)
>= +{
> + =C2=A0 =C2=A0uint64_t mask =3D wr_mask & SCTRDEPTH_MASK;<= br>> +
> + =C2=A0 =C2=A0if (ret_val) {
> + =C2=A0 =C2=A0 =C2= =A0 =C2=A0*ret_val =3D env->sctrdepth & SCTRDEPTH_MASK;
>
&= gt; We don't need to do bitwise and with SCTRDEPTH_MASK on read accesse= s when we always do bitwise and with SCTRDEPTH_MASK on write accesses.
&= gt;
> + =C2=A0 =C2=A0}
> +
> + =C2=A0 =C2=A0env->sctrd= epth =3D (env->sctrdepth & ~mask) | (new_val & mask);
> +<= br>> + =C2=A0 =C2=A0/* Correct depth. */
> + =C2=A0 =C2=A0if (wr_m= ask & SCTRDEPTH_MASK) {
> + =C2=A0 =C2=A0 =C2=A0 =C2=A0uint64_t d= epth =3D get_field(env->sctrdepth, SCTRDEPTH_MASK);
> +
> + = =C2=A0 =C2=A0 =C2=A0 =C2=A0if (depth > SCTRDEPTH_MAX) {
> + =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0env->sctrdepth =3D
> + =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0set_field(env->sctrdepth= , SCTRDEPTH_MASK, SCTRDEPTH_MAX);
> + =C2=A0 =C2=A0 =C2=A0 =C2=A0}> +
> + =C2=A0 =C2=A0 =C2=A0 =C2=A0/* Update sctrstatus.WRPTR wit= h a legal value */
> + =C2=A0 =C2=A0 =C2=A0 =C2=A0depth =3D 16 <&l= t; depth;
>
> The "depth" on the right side may excee= d SCTRDEPTH_MAX.
>
> + =C2=A0 =C2=A0 =C2=A0 =C2=A0env->sctrs= tatus =3D
> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0env->sctrst= atus & (~SCTRSTATUS_WRPTR_MASK | (depth - 1));
> + =C2=A0 =C2=A0}=
> +
> + =C2=A0 =C2=A0return RISCV_EXCP_NONE;
> +}
>= ; +
> +static RISCVException rmw_mctrctl(CPURISCVState *env, int csrn= o,
> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0target_ulong= *ret_val,
> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0ta= rget_ulong new_val, target_ulong wr_mask)
> +{
> + =C2=A0 =C2= =A0uint64_t mask =3D wr_mask & MCTRCTL_MASK;
> +
> + =C2=A0= =C2=A0if (ret_val) {
> + =C2=A0 =C2=A0 =C2=A0 =C2=A0*ret_val =3D env= ->mctrctl & MCTRCTL_MASK;
>
> There is no need to do bit= wise and with the mask on read accesses when we always do bitwise and with = the mask on write accesses.
>
> + =C2=A0 =C2=A0}
> +
&= gt; + =C2=A0 =C2=A0env->mctrctl =3D (env->mctrctl & ~mask) | (new= _val & mask);
> +
> + =C2=A0 =C2=A0return RISCV_EXCP_NONE;<= br>> +}
> +
> +static RISCVException rmw_sctrctl(CPURISCVSta= te *env, int csrno,
> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0target_ulong *ret_val,
> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0target_ulong new_val, target_ulong wr_mask)
> +{
= > + =C2=A0 =C2=A0uint64_t mask =3D wr_mask & SCTRCTL_MASK;
> += =C2=A0 =C2=A0RISCVException ret;
> +
> + =C2=A0 =C2=A0ret =3D = rmw_mctrctl(env, csrno, ret_val, new_val, mask);
>
> When V=3D1= , vsctrctl substitutes for sctrctl.
>
> + =C2=A0 =C2=A0if (ret_= val) {
> + =C2=A0 =C2=A0 =C2=A0 =C2=A0*ret_val &=3D SCTRCTL_MASK;=
> + =C2=A0 =C2=A0}
> +
> + =C2=A0 =C2=A0return ret;
&= gt; +}
> +
> +static RISCVException rmw_sctrstatus(CPURISCVStat= e *env, int csrno,
> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 target_ulong *ret_val,
> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 target_ulong new_val, target_ulong wr_mask)
> +{> + =C2=A0 =C2=A0uint32_t depth =3D 16 << get_field(env->sctrd= epth, SCTRDEPTH_MASK);
> + =C2=A0 =C2=A0uint32_t mask =3D wr_mask &am= p; SCTRSTATUS_MASK;
> +
> + =C2=A0 =C2=A0if (ret_val) {
>= + =C2=A0 =C2=A0 =C2=A0 =C2=A0*ret_val =3D env->sctrstatus & SCTRSTA= TUS_MASK;
>
> There is no need to do bitwise and with the mask = on read accesses when we always do bitwise and with the mask on write acces= ses.
>
> + =C2=A0 =C2=A0}
> +
> + =C2=A0 =C2=A0env-= >sctrstatus =3D (env->sctrstatus & ~mask) | (new_val & mask);=
> +
> + =C2=A0 =C2=A0/* Update sctrstatus.WRPTR with a legal v= alue */
> + =C2=A0 =C2=A0env->sctrstatus =3D env->sctrstatus &a= mp; (~SCTRSTATUS_WRPTR_MASK | (depth - 1));
> +
> + =C2=A0 =C2= =A0return RISCV_EXCP_NONE;
> +}
> +
> +static RISCVExcept= ion rmw_vsctrctl(CPURISCVState *env, int csrno,
> + =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0target_ulong *ret_val,
> + =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0target_ulong new_val, target_u= long wr_mask)
> +{
> + =C2=A0 =C2=A0uint64_t mask =3D wr_mask &= amp; VSCTRCTL_MASK;
> +
> + =C2=A0 =C2=A0if (ret_val) {
>= + =C2=A0 =C2=A0 =C2=A0 =C2=A0*ret_val =3D env->vsctrctl & VSCTRCTL_= MASK;
>
> There is no need to do bitwise and with the mask on r= ead accesses when we always do bitwise and with the mask on write accesses.=
>
> + =C2=A0 =C2=A0}
> +
> + =C2=A0 =C2=A0env->= vsctrctl =3D (env->vsctrctl & ~mask) | (new_val & mask);
>= +
> + =C2=A0 =C2=A0return RISCV_EXCP_NONE;
> +}
>
>= ; Is it possible to define rmw_xctrctl() instead of three individual rmw fu= nctions and use a switch case to select the mask and the CSR for the purpos= e of reducing code size?
>
> +
> =C2=A0static RISCVExcept= ion read_vstopi(CPURISCVState *env, int csrno,
> =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0target_ulong *val)
> =C2=A0{
> @= @ -5771,6 +5920,16 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] =3D {> =C2=A0 =C2=A0 =C2=A0[CSR_SPMBASE] =3D =C2=A0 =C2=A0{ "spmbase&qu= ot;, pointer_masking, read_spmbase,
> =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 write_spmbase = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0},
> =C2= =A0
> + =C2=A0 =C2=A0[CSR_MCTRCTL] =C2=A0 =C2=A0 =C2=A0 =3D { "m= ctrctl", =C2=A0 =C2=A0 =C2=A0 ctr_mmode, NULL, NULL,
> + =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0rmw_mctrctl },
>
> I think this = can be one line.
>
> + =C2=A0 =C2=A0[CSR_SCTRCTL] =C2=A0 =C2=A0= =C2=A0 =3D { "sctrctl", =C2=A0 =C2=A0 =C2=A0 ctr_smode, NULL, NU= LL,
> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0rmw_sctrctl },
><= br>> same here
>
> + =C2=A0 =C2=A0[CSR_SCTRDEPTH] =C2=A0 =C2= =A0 =C2=A0 =3D { "sctrdepth", =C2=A0 =C2=A0 =C2=A0 ctr_smode, NUL= L, NULL,
> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 = =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0rmw_sctrdepth },
= >
> same here
>
> + =C2=A0 =C2=A0[CSR_SCTRSTATUS] =C2= =A0 =C2=A0 =C2=A0 =3D { "sctrstatus", =C2=A0 =C2=A0 =C2=A0 ctr_sm= ode, NULL, NULL,
> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0= =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0rmw_sctrstat= us },
>
> same here
>
> + =C2=A0 =C2=A0[CSR_VSCTRCT= L] =C2=A0 =C2=A0 =C2=A0=3D { "vsctrctl", =C2=A0 =C2=A0 =C2=A0ctr_= vsmode, NULL, NULL,
> + =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2= =A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0 =C2=A0rmw_vsctr= ctl },
>
> same here
>
> =C2=A0 =C2=A0 =C2=A0/* Per= formance Counters */
> =C2=A0 =C2=A0 =C2=A0[CSR_HPMCOUNTER3] =C2=A0 = =C2=A0=3D { "hpmcounter3", =C2=A0 =C2=A0ctr, =C2=A0 =C2=A0read_hp= mcounter },
> =C2=A0 =C2=A0 =C2=A0[CSR_HPMCOUNTER4] =C2=A0 =C2=A0=3D = { "hpmcounter4", =C2=A0 =C2=A0ctr, =C2=A0 =C2=A0read_hpmcounter }= ,
--000000000000af1fd5061a89bb96--