Re: [PATCH v2 01/15] exec/memtxattr: add process identifier to the transaction attributes

2024-04-23 Thread Frank Chang
Reviewed-by: Frank Chang 

Daniel Henrique Barboza  於 2024年3月8日 週五 上午12:04寫道:
>
> From: Tomasz Jeznach 
>
> Extend memory transaction attributes with process identifier to allow
> per-request address translation logic to use requester_id / process_id
> to identify memory mapping (e.g. enabling IOMMU w/ PASID translations).
>
> Signed-off-by: Tomasz Jeznach 
> ---
>  include/exec/memattrs.h | 5 +
>  1 file changed, 5 insertions(+)
>
> diff --git a/include/exec/memattrs.h b/include/exec/memattrs.h
> index 14cdd8d582..46d0725416 100644
> --- a/include/exec/memattrs.h
> +++ b/include/exec/memattrs.h
> @@ -52,6 +52,11 @@ typedef struct MemTxAttrs {
>  unsigned int memory:1;
>  /* Requester ID (for MSI for example) */
>  unsigned int requester_id:16;
> +
> +/*
> + * PCI PASID support: Limited to 8 bits process identifier.
> + */
> +unsigned int pasid:8;
>  } MemTxAttrs;
>
>  /* Bus masters which don't specify any attributes will get this,
> --
> 2.43.2
>
>



[PATCH] hw/intc: Update APLIC IDC after claiming iforce register

2024-03-21 Thread frank . chang
From: Frank Chang 

Currently, QEMU only sets the iforce register to 0 and returns early
when claiming the iforce register. However, this may leave mip.meip
remains at 1 if a spurious external interrupt triggered by iforce
register is the only pending interrupt to be claimed, and the interrupt
cannot be lowered as expected.

This commit fixes this issue by calling riscv_aplic_idc_update() to
update the IDC status after the iforce register is claimed.

Signed-off-by: Frank Chang 
Reviewed-by: Jim Shu 
---
 hw/intc/riscv_aplic.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/hw/intc/riscv_aplic.c b/hw/intc/riscv_aplic.c
index 6a7fbfa861..fc5df0d598 100644
--- a/hw/intc/riscv_aplic.c
+++ b/hw/intc/riscv_aplic.c
@@ -488,6 +488,7 @@ static uint32_t riscv_aplic_idc_claimi(RISCVAPLICState 
*aplic, uint32_t idc)
 
 if (!topi) {
 aplic->iforce[idc] = 0;
+riscv_aplic_idc_update(aplic, idc);
 return 0;
 }
 
-- 
2.43.2




[PATCH] target/riscv: Add missing include guard in pmu.h

2024-02-20 Thread frank . chang
From: Frank Chang 

Add missing include guard in pmu.h to avoid the problem of double
inclusion.

Signed-off-by: Frank Chang 
---
 target/riscv/pmu.h | 5 +
 1 file changed, 5 insertions(+)

diff --git a/target/riscv/pmu.h b/target/riscv/pmu.h
index 505fc850d3..7c0ad661e0 100644
--- a/target/riscv/pmu.h
+++ b/target/riscv/pmu.h
@@ -16,6 +16,9 @@
  * this program.  If not, see <http://www.gnu.org/licenses/>.
  */
 
+#ifndef RISCV_PMU_H
+#define RISCV_PMU_H
+
 #include "cpu.h"
 #include "qapi/error.h"
 
@@ -31,3 +34,5 @@ int riscv_pmu_incr_ctr(RISCVCPU *cpu, enum 
riscv_pmu_event_idx event_idx);
 void riscv_pmu_generate_fdt_node(void *fdt, uint32_t cmask, char *pmu_name);
 int riscv_pmu_setup_timer(CPURISCVState *env, uint64_t value,
   uint32_t ctr_idx);
+
+#endif /* RISCV_PMU_H */
-- 
2.43.0




Re: [PATCH] target/riscv: Update $pc after linking to $ra in trans_cm_jalt()

2024-02-06 Thread Frank Chang
Reviewed-by: Frank Chang 

On Tue, Feb 6, 2024 at 9:19 PM Jason Chien  wrote:

> The original implementation sets $pc to the address read from the jump
> vector table first and links $ra with the address of the next instruction
> after the updated $pc. After jumping to the updated $pc and executing the
> next ret instruction, the program jumps to $ra, which is in the same
> function currently executing, which results in an infinite loop.
> This commit reverses the two action. Firstly, $ra is updated with the
> address of the next instruction after $pc, and sets $pc to the address
> read from the jump vector table.
>
> Signed-off-by: Jason Chien 
> ---
>  target/riscv/insn_trans/trans_rvzce.c.inc | 14 +++---
>  1 file changed, 7 insertions(+), 7 deletions(-)
>
> diff --git a/target/riscv/insn_trans/trans_rvzce.c.inc
> b/target/riscv/insn_trans/trans_rvzce.c.inc
> index 8d8a64f493..a185e2315f 100644
> --- a/target/riscv/insn_trans/trans_rvzce.c.inc
> +++ b/target/riscv/insn_trans/trans_rvzce.c.inc
> @@ -293,13 +293,6 @@ static bool trans_cm_jalt(DisasContext *ctx,
> arg_cm_jalt *a)
>  {
>  REQUIRE_ZCMT(ctx);
>
> -/*
> - * Update pc to current for the non-unwinding exception
> - * that might come from cpu_ld*_code() in the helper.
> - */
> -gen_update_pc(ctx, 0);
> -gen_helper_cm_jalt(cpu_pc, cpu_env, tcg_constant_i32(a->index));
> -
>  /* c.jt vs c.jalt depends on the index. */
>  if (a->index >= 32) {
>  TCGv succ_pc = dest_gpr(ctx, xRA);
> @@ -307,6 +300,13 @@ static bool trans_cm_jalt(DisasContext *ctx,
> arg_cm_jalt *a)
>  gen_set_gpr(ctx, xRA, succ_pc);
>  }
>
> +/*
> + * Update pc to current for the non-unwinding exception
> + * that might come from cpu_ld*_code() in the helper.
> + */
> +gen_update_pc(ctx, 0);
> +gen_helper_cm_jalt(cpu_pc, cpu_env, tcg_constant_i32(a->index));
> +
>  tcg_gen_lookup_and_goto_ptr();
>  ctx->base.is_jmp = DISAS_NORETURN;
>  return true;
> --
> 2.43.0
>
>
>


Re: [PATCH] hw/pci-host: Allow extended config space access for Designware PCIe host

2023-08-11 Thread Frank Chang
Reviewed-by: Frank Chang 

On Wed, Aug 9, 2023 at 6:23 PM Jason Chien  wrote:

> In pcie_bus_realize(), a root bus is realized as a PCIe bus and a non-root
> bus is realized as a PCIe bus if its parent bus is a PCIe bus. However,
> the child bus "dw-pcie" is realized before the parent bus "pcie" which is
> the root PCIe bus. Thus, the extended configuration space is not accessible
> on "dw-pcie". The issue can be resolved by adding the
> PCI_BUS_EXTENDED_CONFIG_SPACE flag to "pcie" before "dw-pcie" is realized.
>
> Signed-off-by: Jason Chien 
> ---
>  hw/pci-host/designware.c | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/hw/pci-host/designware.c b/hw/pci-host/designware.c
> index 9e183caa48..388d252ee2 100644
> --- a/hw/pci-host/designware.c
> +++ b/hw/pci-host/designware.c
> @@ -694,6 +694,7 @@ static void designware_pcie_host_realize(DeviceState
> *dev, Error **errp)
>   >pci.io,
>   0, 4,
>   TYPE_PCIE_BUS);
> +pci->bus->flags |= PCI_BUS_EXTENDED_CONFIG_SPACE;
>
>  memory_region_init(>pci.address_space_root,
> OBJECT(s),
> --
> 2.17.1
>
>
>


Re: [PATCH] target/riscv: Add Zihintntl extension ISA string to DTS

2023-07-04 Thread Frank Chang
Reviewed-by: Frank Chang 

On Tue, Jul 4, 2023 at 4:41 PM Jason Chien  wrote:

> RVA23 Profiles states:
> The RVA23 profiles are intended to be used for 64-bit application
> processors that will run rich OS stacks from standard binary OS
> distributions and with a substantial number of third-party binary user
> applications that will be supported over a considerable length of time
> in the field.
>
> The chapter 4 of the unprivileged spec introduces the Zihintntl extension
> and Zihintntl is a mandatory extension presented in RVA23 Profiles, whose
> purpose is to enable application and operating system portability across
> different implementations. Thus the DTS should contain the Zihintntl ISA
> string in order to pass to software.
>
> The unprivileged spec states:
> Like any HINTs, these instructions may be freely ignored. Hence, although
> they are described in terms of cache-based memory hierarchies, they do not
> mandate the provision of caches.
>
> These instructions are encoded with used opcode, e.g. ADD x0, x0, x2, which
> QEMU already supports, and QEMU does not emulate cache. Therefore these
> instructions can be considered as a no-op, and we only need to add a new
> property for the Zihintntl extension.
>
> Signed-off-by: Jason Chien 
> ---
>  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 881bddf393..6fd21466a4 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -81,6 +81,7 @@ static const struct isa_ext_data isa_edata_arr[] = {
>  ISA_EXT_DATA_ENTRY(zicond, PRIV_VERSION_1_12_0, ext_zicond),
>  ISA_EXT_DATA_ENTRY(zicsr, PRIV_VERSION_1_10_0, ext_icsr),
>  ISA_EXT_DATA_ENTRY(zifencei, PRIV_VERSION_1_10_0, ext_ifencei),
> +ISA_EXT_DATA_ENTRY(zihintntl, PRIV_VERSION_1_10_0, ext_zihintntl),
>  ISA_EXT_DATA_ENTRY(zihintpause, PRIV_VERSION_1_10_0, ext_zihintpause),
>  ISA_EXT_DATA_ENTRY(zawrs, PRIV_VERSION_1_12_0, ext_zawrs),
>  ISA_EXT_DATA_ENTRY(zfh, PRIV_VERSION_1_11_0, ext_zfh),
> @@ -1598,6 +1599,7 @@ static Property riscv_cpu_extensions[] = {
>  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),
> +DEFINE_PROP_BOOL("Zihintntl", RISCVCPU, cfg.ext_zihintntl, true),
>  DEFINE_PROP_BOOL("Zihintpause", RISCVCPU, cfg.ext_zihintpause, true),
>  DEFINE_PROP_BOOL("Zawrs", RISCVCPU, cfg.ext_zawrs, true),
>  DEFINE_PROP_BOOL("Zfh", RISCVCPU, cfg.ext_zfh, false),
> diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h
> index c4a627d335..c7da2facef 100644
> --- a/target/riscv/cpu_cfg.h
> +++ b/target/riscv/cpu_cfg.h
> @@ -66,6 +66,7 @@ struct RISCVCPUConfig {
>  bool ext_icbom;
>  bool ext_icboz;
>  bool ext_zicond;
> +bool ext_zihintntl;
>  bool ext_zihintpause;
>  bool ext_smstateen;
>  bool ext_sstc;
> --
> 2.17.1
>
>
>


Re: [PATCH] hw/dma/xilinx_axidma: Check DMASR.HALTED to prevent infinite loop.

2023-05-20 Thread Frank Chang
Reviewed-by: Frank Chang 

On Fri, May 19, 2023 at 2:23 PM Tommy Wu  wrote:

> When we receive a packet from the xilinx_axienet and then try to s2mem
> through the xilinx_axidma, if the descriptor ring buffer is full in the
> xilinx axidma driver, we’ll assert the DMASR.HALTED in the
> function : stream_process_s2mem and return 0. In the end, we’ll be stuck in
> an infinite loop in axienet_eth_rx_notify.
>
> This patch checks the DMASR.HALTED state when we try to push data
> from xilinx axi-enet to xilinx axi-dma. When the DMASR.HALTED is asserted,
> we will not keep pushing the data and then prevent the infinte loop.
>
> Signed-off-by: Tommy Wu 
> ---
>  hw/dma/xilinx_axidma.c | 11 ---
>  1 file changed, 8 insertions(+), 3 deletions(-)
>
> diff --git a/hw/dma/xilinx_axidma.c b/hw/dma/xilinx_axidma.c
> index 6030c76435..12c90267df 100644
> --- a/hw/dma/xilinx_axidma.c
> +++ b/hw/dma/xilinx_axidma.c
> @@ -168,6 +168,11 @@ static inline int stream_idle(struct Stream *s)
>  return !!(s->regs[R_DMASR] & DMASR_IDLE);
>  }
>
> +static inline int stream_halted(struct Stream *s)
> +{
> +return !!(s->regs[R_DMASR] & DMASR_HALTED);
> +}
> +
>  static void stream_reset(struct Stream *s)
>  {
>  s->regs[R_DMASR] = DMASR_HALTED;  /* starts up halted.  */
> @@ -269,7 +274,7 @@ static void stream_process_mem2s(struct Stream *s,
> StreamSink *tx_data_dev,
>  uint64_t addr;
>  bool eop;
>
> -if (!stream_running(s) || stream_idle(s)) {
> +if (!stream_running(s) || stream_idle(s) || stream_halted(s)) {
>  return;
>  }
>
> @@ -326,7 +331,7 @@ static size_t stream_process_s2mem(struct Stream *s,
> unsigned char *buf,
>  unsigned int rxlen;
>  size_t pos = 0;
>
> -if (!stream_running(s) || stream_idle(s)) {
> +if (!stream_running(s) || stream_idle(s) || stream_halted(s)) {
>  return 0;
>  }
>
> @@ -407,7 +412,7 @@ xilinx_axidma_data_stream_can_push(StreamSink *obj,
>  XilinxAXIDMAStreamSink *ds = XILINX_AXI_DMA_DATA_STREAM(obj);
>  struct Stream *s = >dma->streams[1];
>
> -if (!stream_running(s) || stream_idle(s)) {
> +if (!stream_running(s) || stream_idle(s) || stream_halted(s)) {
>  ds->dma->notify = notify;
>  ds->dma->notify_opaque = notify_opaque;
>  return false;
> --
> 2.31.1
>
>
>


Re: [PATCH] target/riscv: Add support for Zicond extension

2023-02-23 Thread Frank Chang
Reviewed-by: Frank Chang 

On Tue, Feb 21, 2023 at 5:10 PM Weiwei Li  wrote:

> The spec can be found in https://github.com/riscv/riscv-zicond.
> Two instructions are added:
>  - czero.eqz: Moves zero to a register rd, if the condition rs2 is
>equal to zero, otherwise moves rs1 to rd.
>  - czero.nez: Moves zero to a register rd, if the condition rs2 is
>nonzero, otherwise moves rs1 to rd.
>
> Signed-off-by: Weiwei Li 
> Signed-off-by: Junqiang Wang 
> ---
>  target/riscv/cpu.c   |  2 +
>  target/riscv/cpu.h   |  1 +
>  target/riscv/insn32.decode   |  4 ++
>  target/riscv/insn_trans/trans_rvzicond.c.inc | 49 
>  target/riscv/translate.c |  1 +
>  5 files changed, 57 insertions(+)
>  create mode 100644 target/riscv/insn_trans/trans_rvzicond.c.inc
>
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index 0dd2f0c753..80b92930ae 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -74,6 +74,7 @@ struct isa_ext_data {
>  static const struct isa_ext_data isa_edata_arr[] = {
>  ISA_EXT_DATA_ENTRY(h, false, PRIV_VERSION_1_12_0, ext_h),
>  ISA_EXT_DATA_ENTRY(v, false, PRIV_VERSION_1_12_0, ext_v),
> +ISA_EXT_DATA_ENTRY(zicond, true, PRIV_VERSION_1_12_0, ext_zicond),
>  ISA_EXT_DATA_ENTRY(zicsr, true, PRIV_VERSION_1_10_0, ext_icsr),
>  ISA_EXT_DATA_ENTRY(zifencei, true, PRIV_VERSION_1_10_0, ext_ifencei),
>  ISA_EXT_DATA_ENTRY(zihintpause, true, PRIV_VERSION_1_10_0,
> ext_zihintpause),
> @@ -1143,6 +1144,7 @@ static Property riscv_cpu_extensions[] = {
>  DEFINE_PROP_BOOL("xventanacondops", RISCVCPU,
> cfg.ext_XVentanaCondOps, false),
>
>  /* These are experimental so mark with 'x-' */
> +DEFINE_PROP_BOOL("x-zicond", RISCVCPU, cfg.ext_zicond, false),
>  DEFINE_PROP_BOOL("x-j", RISCVCPU, cfg.ext_j, false),
>  /* ePMP 0.9.3 */
>  DEFINE_PROP_BOOL("x-epmp", RISCVCPU, cfg.epmp, false),
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index 7128438d8e..81b7c92e7a 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -447,6 +447,7 @@ struct RISCVCPUConfig {
>  bool ext_zkt;
>  bool ext_ifencei;
>  bool ext_icsr;
> +bool ext_zicond;
>  bool ext_zihintpause;
>  bool ext_smstateen;
>  bool ext_sstc;
> diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
> index b7e7613ea2..fb537e922e 100644
> --- a/target/riscv/insn32.decode
> +++ b/target/riscv/insn32.decode
> @@ -890,3 +890,7 @@ sm3p1   00 01000 01001 . 001 . 0010011 @r2
>  # *** RV32 Zksed Standard Extension ***
>  sm4ed   .. 11000 . . 000 . 0110011 @k_aes
>  sm4ks   .. 11010 . . 000 . 0110011 @k_aes
> +
> +# *** RV32 Zicond Standard Extension ***
> +czero_eqz   111  . . 101 . 0110011 @r
> +czero_nez   111  . . 111 . 0110011 @r
> diff --git a/target/riscv/insn_trans/trans_rvzicond.c.inc
> b/target/riscv/insn_trans/trans_rvzicond.c.inc
> new file mode 100644
> index 00..645260164e
> --- /dev/null
> +++ b/target/riscv/insn_trans/trans_rvzicond.c.inc
> @@ -0,0 +1,49 @@
> +/*
> + * RISC-V translation routines for the Zicond Standard Extension.
> + *
> + * Copyright (c) 2020-2023 PLCT Lab
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2 or later, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
> for
> + * more details.
> + *
> + * You should have received a copy of the GNU General Public License
> along with
> + * this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#define REQUIRE_ZICOND(ctx) do {  \
> +if (!ctx->cfg_ptr->ext_zicond) {  \
> +return false; \
> +} \
> +} while (0)
> +
> +static bool trans_czero_eqz(DisasContext *ctx, arg_czero_eqz *a)
> +{
> +REQUIRE_ZICOND(ctx);
> +
> +TCGv dest = dest_gpr(ctx, a->rd);
> +TCGv src1 = get_gpr(ctx, a->rs1, EXT_NONE);
> +TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE);
> +
> +tcg_gen_movcond_tl(TCG_COND_EQ, dest, src2, ctx->zero, ctx->zero,
> src1);
> +gen_set_gpr(ctx, a->rd, dest);
> +return true;
> +}
> +
> +static bool trans_czero_nez(D

Re: [PATCH] target/riscv/vector_helper.c: create vext_set_tail_elems_1s()

2023-02-23 Thread Frank Chang
Reviewed-by: Frank Chang 

On Wed, Feb 22, 2023 at 2:46 AM Daniel Henrique Barboza <
dbarb...@ventanamicro.com> wrote:

> Commit 752614cab8e6 ("target/riscv: rvv: Add tail agnostic for vector
> load / store instructions") added code to set the tail elements to 1 in
> the end of vext_ldst_stride(), vext_ldst_us(), vext_ldst_index() and
> vext_ldff(). Aside from a env->vl versus an evl value being used in the
> first loop, the code is being repeated 4 times.
>
> Create a helper to avoid code repetition in all those functions.
> Arguments that are used in the callers (nf, esz and max_elems) are
> passed as arguments. All other values are being derived inside the
> helper.
>
> Signed-off-by: Daniel Henrique Barboza 
> ---
>  target/riscv/vector_helper.c | 86 +---
>  1 file changed, 30 insertions(+), 56 deletions(-)
>
> diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c
> index 00de879787..7d2e3978f1 100644
> --- a/target/riscv/vector_helper.c
> +++ b/target/riscv/vector_helper.c
> @@ -267,6 +267,28 @@ GEN_VEXT_ST_ELEM(ste_h, int16_t, H2, stw)
>  GEN_VEXT_ST_ELEM(ste_w, int32_t, H4, stl)
>  GEN_VEXT_ST_ELEM(ste_d, int64_t, H8, stq)
>
> +static void vext_set_tail_elems_1s(CPURISCVState *env, target_ulong vl,
> +   void *vd, uint32_t desc, uint32_t nf,
> +   uint32_t esz, uint32_t max_elems)
> +{
> +uint32_t total_elems = vext_get_total_elems(env, desc, esz);
> +uint32_t vlenb = env_archcpu(env)->cfg.vlen >> 3;
> +uint32_t vta = vext_vta(desc);
> +uint32_t registers_used;
> +int k;
> +
> +for (k = 0; k < nf; ++k) {
> +vext_set_elems_1s(vd, vta, (k * max_elems + vl) * esz,
> +  (k * max_elems + max_elems) * esz);
> +}
> +
> +if (nf * max_elems % total_elems != 0) {
> +registers_used = ((nf * max_elems) * esz + (vlenb - 1)) / vlenb;
> +vext_set_elems_1s(vd, vta, (nf * max_elems) * esz,
> +  registers_used * vlenb);
> +}
> +}
> +
>  /*
>   *** stride: access vector element from strided memory
>   */
> @@ -281,8 +303,6 @@ vext_ldst_stride(void *vd, void *v0, target_ulong base,
>  uint32_t nf = vext_nf(desc);
>  uint32_t max_elems = vext_max_elems(desc, log2_esz);
>  uint32_t esz = 1 << log2_esz;
> -uint32_t total_elems = vext_get_total_elems(env, desc, esz);
> -uint32_t vta = vext_vta(desc);
>  uint32_t vma = vext_vma(desc);
>
>  for (i = env->vstart; i < env->vl; i++, env->vstart++) {
> @@ -301,18 +321,8 @@ vext_ldst_stride(void *vd, void *v0, target_ulong
> base,
>  }
>  }
>  env->vstart = 0;
> -/* set tail elements to 1s */
> -for (k = 0; k < nf; ++k) {
> -vext_set_elems_1s(vd, vta, (k * max_elems + env->vl) * esz,
> -  (k * max_elems + max_elems) * esz);
> -}
> -if (nf * max_elems % total_elems != 0) {
> -uint32_t vlenb = env_archcpu(env)->cfg.vlen >> 3;
> -uint32_t registers_used =
> -((nf * max_elems) * esz + (vlenb - 1)) / vlenb;
> -vext_set_elems_1s(vd, vta, (nf * max_elems) * esz,
> -  registers_used * vlenb);
> -}
> +
> +vext_set_tail_elems_1s(env, env->vl, vd, desc, nf, esz, max_elems);
>  }
>
>  #define GEN_VEXT_LD_STRIDE(NAME, ETYPE, LOAD_FN)\
> @@ -359,8 +369,6 @@ vext_ldst_us(void *vd, target_ulong base,
> CPURISCVState *env, uint32_t desc,
>  uint32_t nf = vext_nf(desc);
>  uint32_t max_elems = vext_max_elems(desc, log2_esz);
>  uint32_t esz = 1 << log2_esz;
> -uint32_t total_elems = vext_get_total_elems(env, desc, esz);
> -uint32_t vta = vext_vta(desc);
>
>  /* load bytes from guest memory */
>  for (i = env->vstart; i < evl; i++, env->vstart++) {
> @@ -372,18 +380,8 @@ vext_ldst_us(void *vd, target_ulong base,
> CPURISCVState *env, uint32_t desc,
>  }
>  }
>  env->vstart = 0;
> -/* set tail elements to 1s */
> -for (k = 0; k < nf; ++k) {
> -vext_set_elems_1s(vd, vta, (k * max_elems + evl) * esz,
> -  (k * max_elems + max_elems) * esz);
> -}
> -if (nf * max_elems % total_elems != 0) {
> -uint32_t vlenb = env_archcpu(env)->cfg.vlen >> 3;
> -uint32_t registers_used =
> -((nf * max_elems) * esz + (vlenb - 1)) / vlenb;
> -vext_set_elems_1s(vd, vta, (nf * max_elems) * esz,
> -  registers_used * vlenb);
> -}
> +
> +v

Re: [PATCH] target/riscv: Fix vslide1up.vf and vslide1down.vf

2023-02-13 Thread Frank Chang
Reviewed-by: Frank Chang 

On Mon, Feb 13, 2023 at 5:45 PM LIU Zhiwei 
wrote:

> vslide1up_##BITWIDTH is used by the vslide1up.vx and vslide1up.vf. So its
> scalar input should be uint64_t to hold the 64 bits float register.And the
> same for vslide1down_##BITWIDTH.
>
> This bug is caught when run these instructions on qemu-riscv32.
>
> Signed-off-by: LIU Zhiwei 
> ---
>  target/riscv/vector_helper.c | 4 ++--
>  1 file changed, 2 insertions(+), 2 deletions(-)
>
> diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c
> index 00de879787..3073c54871 100644
> --- a/target/riscv/vector_helper.c
> +++ b/target/riscv/vector_helper.c
> @@ -5038,7 +5038,7 @@ GEN_VEXT_VSLIDEDOWN_VX(vslidedown_vx_w, uint32_t, H4)
>  GEN_VEXT_VSLIDEDOWN_VX(vslidedown_vx_d, uint64_t, H8)
>
>  #define GEN_VEXT_VSLIE1UP(BITWIDTH, H)
>   \
> -static void vslide1up_##BITWIDTH(void *vd, void *v0, target_ulong s1,
>\
> +static void vslide1up_##BITWIDTH(void *vd, void *v0, uint64_t s1,
>\
>   void *vs2, CPURISCVState *env, uint32_t desc)
>   \
>  {
>\
>  typedef uint##BITWIDTH##_t ETYPE;
>\
> @@ -5086,7 +5086,7 @@ GEN_VEXT_VSLIDE1UP_VX(vslide1up_vx_w, 32)
>  GEN_VEXT_VSLIDE1UP_VX(vslide1up_vx_d, 64)
>
>  #define GEN_VEXT_VSLIDE1DOWN(BITWIDTH, H)
>  \
> -static void vslide1down_##BITWIDTH(void *vd, void *v0, target_ulong s1,
>  \
> +static void vslide1down_##BITWIDTH(void *vd, void *v0, uint64_t s1,
>  \
> void *vs2, CPURISCVState *env, uint32_t desc)
> \
>  {
>  \
>  typedef uint##BITWIDTH##_t ETYPE;
>  \
> --
> 2.17.1
>
>


Re: [PATCH] MAINTAINERS: Add some RISC-V reviewers

2023-02-09 Thread Frank Chang
Reviewed-by: Frank Chang 

On Thu, Feb 9, 2023 at 8:34 AM Alistair Francis <
alistair.fran...@opensource.wdc.com> wrote:

> From: Alistair Francis 
>
> This patch adds some active RISC-V members as reviewers to the
> MAINTAINERS file.
>
> Signed-off-by: Alistair Francis 
> ---
>  MAINTAINERS | 3 +++
>  1 file changed, 3 insertions(+)
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index 96e25f62ac..847bc7f131 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -287,6 +287,9 @@ RISC-V TCG CPUs
>  M: Palmer Dabbelt 
>  M: Alistair Francis 
>  M: Bin Meng 
> +R: Weiwei Li 
> +R: Daniel Henrique Barboza 
> +R: Liu Zhiwei 
>  L: qemu-ri...@nongnu.org
>  S: Supported
>  F: target/riscv/
> --
> 2.39.1
>
>
>


[PATCH v2] target/riscv: Remove privileged spec version restriction for RVV

2023-02-07 Thread frank . chang
From: Frank Chang 

The RVV specification does not require that the core needs to support
the privileged specification v1.12.0 to support RVV, and there is no
dependency from ISA level.

This commit removes the restriction from both RVV CSRs and extension CPU
ISA string.

Signed-off-by: Frank Chang 
Reviewed-by: Bin Meng 
Reviewed-by: LIU Zhiwei 
---
 target/riscv/cpu.c |  2 +-
 target/riscv/csr.c | 21 +++--
 2 files changed, 8 insertions(+), 15 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 0dd2f0c753..93b52b826c 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -73,7 +73,7 @@ struct isa_ext_data {
  */
 static const struct isa_ext_data isa_edata_arr[] = {
 ISA_EXT_DATA_ENTRY(h, false, PRIV_VERSION_1_12_0, ext_h),
-ISA_EXT_DATA_ENTRY(v, false, PRIV_VERSION_1_12_0, ext_v),
+ISA_EXT_DATA_ENTRY(v, false, PRIV_VERSION_1_10_0, ext_v),
 ISA_EXT_DATA_ENTRY(zicsr, true, PRIV_VERSION_1_10_0, ext_icsr),
 ISA_EXT_DATA_ENTRY(zifencei, true, PRIV_VERSION_1_10_0, ext_ifencei),
 ISA_EXT_DATA_ENTRY(zihintpause, true, PRIV_VERSION_1_10_0, 
ext_zihintpause),
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index fa17d7770c..1b0a0c1693 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -3980,20 +3980,13 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
 [CSR_FRM]  = { "frm",  fs, read_frm, write_frm},
 [CSR_FCSR] = { "fcsr", fs, read_fcsr,write_fcsr   },
 /* Vector CSRs */
-[CSR_VSTART]   = { "vstart",   vs, read_vstart,  write_vstart,
-   .min_priv_ver = PRIV_VERSION_1_12_0},
-[CSR_VXSAT]= { "vxsat",vs, read_vxsat,   write_vxsat,
-   .min_priv_ver = PRIV_VERSION_1_12_0},
-[CSR_VXRM] = { "vxrm", vs, read_vxrm,write_vxrm,
-   .min_priv_ver = PRIV_VERSION_1_12_0},
-[CSR_VCSR] = { "vcsr", vs, read_vcsr,write_vcsr,
-   .min_priv_ver = PRIV_VERSION_1_12_0},
-[CSR_VL]   = { "vl",   vs, read_vl,
-   .min_priv_ver = PRIV_VERSION_1_12_0},
-[CSR_VTYPE]= { "vtype",vs, read_vtype,
-   .min_priv_ver = PRIV_VERSION_1_12_0},
-[CSR_VLENB]= { "vlenb",vs, read_vlenb,
-   .min_priv_ver = PRIV_VERSION_1_12_0},
+[CSR_VSTART]   = { "vstart",   vs, read_vstart,  write_vstart },
+[CSR_VXSAT]= { "vxsat",vs, read_vxsat,   write_vxsat  },
+[CSR_VXRM] = { "vxrm", vs, read_vxrm,write_vxrm   },
+[CSR_VCSR] = { "vcsr", vs, read_vcsr,write_vcsr   },
+[CSR_VL]   = { "vl",   vs, read_vl},
+[CSR_VTYPE]= { "vtype",vs, read_vtype },
+[CSR_VLENB]= { "vlenb",vs, read_vlenb },
 /* User Timers and Counters */
 [CSR_CYCLE]= { "cycle",ctr,read_hpmcounter  },
 [CSR_INSTRET]  = { "instret",  ctr,read_hpmcounter  },
-- 
2.36.1




Re: [PATCH] target/riscv: Remove .min_priv_ver restriction from RVV CSRs

2023-02-07 Thread Frank Chang
I realized that I should also remove the privileged version check
in isa_edata_arr[], too.
I will send out v2 patch to fix it.

Regards,
Frank Chang

On Tue, Feb 7, 2023 at 4:43 PM  wrote:

> From: Frank Chang 
>
> The RVV specification does not require that the core needs to support
> the privileged specification v1.12.0 to support RVV, and there is no
> dependency from ISA level. This commit removes the restriction.
>
> Signed-off-by: Frank Chang 
> ---
>  target/riscv/csr.c | 21 +++--
>  1 file changed, 7 insertions(+), 14 deletions(-)
>
> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> index fa17d7770c4..1b0a0c1693c 100644
> --- a/target/riscv/csr.c
> +++ b/target/riscv/csr.c
> @@ -3980,20 +3980,13 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
>  [CSR_FRM]  = { "frm",  fs, read_frm, write_frm},
>  [CSR_FCSR] = { "fcsr", fs, read_fcsr,write_fcsr   },
>  /* Vector CSRs */
> -[CSR_VSTART]   = { "vstart",   vs, read_vstart,  write_vstart,
> -   .min_priv_ver = PRIV_VERSION_1_12_0},
> -[CSR_VXSAT]= { "vxsat",vs, read_vxsat,   write_vxsat,
> -   .min_priv_ver = PRIV_VERSION_1_12_0},
> -[CSR_VXRM] = { "vxrm", vs, read_vxrm,write_vxrm,
> -   .min_priv_ver = PRIV_VERSION_1_12_0},
> -[CSR_VCSR] = { "vcsr", vs, read_vcsr,write_vcsr,
> -   .min_priv_ver = PRIV_VERSION_1_12_0},
> -[CSR_VL]   = { "vl",   vs, read_vl,
> -   .min_priv_ver = PRIV_VERSION_1_12_0},
> -[CSR_VTYPE]= { "vtype",vs, read_vtype,
> -   .min_priv_ver = PRIV_VERSION_1_12_0},
> -[CSR_VLENB]= { "vlenb",vs, read_vlenb,
> -   .min_priv_ver = PRIV_VERSION_1_12_0},
> +[CSR_VSTART]   = { "vstart",   vs, read_vstart,  write_vstart },
> +[CSR_VXSAT]= { "vxsat",vs, read_vxsat,   write_vxsat  },
> +[CSR_VXRM] = { "vxrm", vs, read_vxrm,write_vxrm   },
> +[CSR_VCSR] = { "vcsr", vs, read_vcsr,write_vcsr   },
> +[CSR_VL]   = { "vl",   vs, read_vl},
> +[CSR_VTYPE]= { "vtype",vs, read_vtype },
> +[CSR_VLENB]= { "vlenb",vs, read_vlenb },
>  /* User Timers and Counters */
>  [CSR_CYCLE]= { "cycle",ctr,read_hpmcounter  },
>  [CSR_INSTRET]  = { "instret",  ctr,read_hpmcounter  },
> --
> 2.25.1
>
>


[PATCH] target/riscv: Remove .min_priv_ver restriction from RVV CSRs

2023-02-07 Thread frank . chang
From: Frank Chang 

The RVV specification does not require that the core needs to support
the privileged specification v1.12.0 to support RVV, and there is no
dependency from ISA level. This commit removes the restriction.

Signed-off-by: Frank Chang 
---
 target/riscv/csr.c | 21 +++--
 1 file changed, 7 insertions(+), 14 deletions(-)

diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index fa17d7770c4..1b0a0c1693c 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -3980,20 +3980,13 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
 [CSR_FRM]  = { "frm",  fs, read_frm, write_frm},
 [CSR_FCSR] = { "fcsr", fs, read_fcsr,write_fcsr   },
 /* Vector CSRs */
-[CSR_VSTART]   = { "vstart",   vs, read_vstart,  write_vstart,
-   .min_priv_ver = PRIV_VERSION_1_12_0},
-[CSR_VXSAT]= { "vxsat",vs, read_vxsat,   write_vxsat,
-   .min_priv_ver = PRIV_VERSION_1_12_0},
-[CSR_VXRM] = { "vxrm", vs, read_vxrm,write_vxrm,
-   .min_priv_ver = PRIV_VERSION_1_12_0},
-[CSR_VCSR] = { "vcsr", vs, read_vcsr,write_vcsr,
-   .min_priv_ver = PRIV_VERSION_1_12_0},
-[CSR_VL]   = { "vl",   vs, read_vl,
-   .min_priv_ver = PRIV_VERSION_1_12_0},
-[CSR_VTYPE]= { "vtype",vs, read_vtype,
-   .min_priv_ver = PRIV_VERSION_1_12_0},
-[CSR_VLENB]= { "vlenb",vs, read_vlenb,
-   .min_priv_ver = PRIV_VERSION_1_12_0},
+[CSR_VSTART]   = { "vstart",   vs, read_vstart,  write_vstart },
+[CSR_VXSAT]= { "vxsat",vs, read_vxsat,   write_vxsat  },
+[CSR_VXRM] = { "vxrm", vs, read_vxrm,write_vxrm   },
+[CSR_VCSR] = { "vcsr", vs, read_vcsr,write_vcsr   },
+[CSR_VL]   = { "vl",   vs, read_vl},
+[CSR_VTYPE]= { "vtype",vs, read_vtype },
+[CSR_VLENB]= { "vlenb",vs, read_vlenb },
 /* User Timers and Counters */
 [CSR_CYCLE]= { "cycle",ctr,read_hpmcounter  },
 [CSR_INSTRET]  = { "instret",  ctr,read_hpmcounter  },
-- 
2.25.1




Re: [PATCH v10 3/5] riscv: Allow user to set the satp mode

2023-02-03 Thread Frank Chang
On Fri, Feb 3, 2023 at 2:01 PM Alexandre Ghiti 
wrote:

> RISC-V specifies multiple sizes for addressable memory and Linux probes for
> the machine's support at startup via the satp CSR register (done in
> csr.c:validate_vm).
>
> As per the specification, sv64 must support sv57, which in turn must
> support sv48...etc. So we can restrict machine support by simply setting
> the
> "highest" supported mode and the bare mode is always supported.
>
> You can set the satp mode using the new properties "sv32", "sv39", "sv48",
> "sv57" and "sv64" as follows:
> -cpu rv64,sv57=on  # Linux will boot using sv57 scheme
> -cpu rv64,sv39=on  # Linux will boot using sv39 scheme
> -cpu rv64,sv57=off # Linux will boot using sv48 scheme
> -cpu rv64  # Linux will boot using sv57 scheme by default
>
> We take the highest level set by the user:
> -cpu rv64,sv48=on,sv57=on # Linux will boot using sv57 scheme
>
> We make sure that invalid configurations are rejected:
> -cpu rv64,sv39=off,sv48=on # sv39 must be supported if higher modes are
># enabled
>
> We accept "redundant" configurations:
> -cpu rv64,sv48=on,sv57=off # Linux will boot using sv48 scheme
>
> And contradictory configurations:
> -cpu rv64,sv48=on,sv48=off # Linux will boot using sv39 scheme
>
> Co-Developed-by: Ludovic Henry 
> Signed-off-by: Ludovic Henry 
> Signed-off-by: Alexandre Ghiti 
> Reviewed-by: Andrew Jones 
> Reviewed-by: Bin Meng 
> Acked-by: Alistair Francis 
> ---
>  target/riscv/cpu.c | 215 +
>  target/riscv/cpu.h |  21 +
>  target/riscv/csr.c |  12 ++-
>  3 files changed, 241 insertions(+), 7 deletions(-)
>
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index 7181b34f86..56057cf87c 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -27,6 +27,7 @@
>  #include "time_helper.h"
>  #include "exec/exec-all.h"
>  #include "qapi/error.h"
> +#include "qapi/visitor.h"
>  #include "qemu/error-report.h"
>  #include "hw/qdev-properties.h"
>  #include "migration/vmstate.h"
> @@ -229,6 +230,83 @@ static void set_vext_version(CPURISCVState *env, int
> vext_ver)
>  env->vext_ver = vext_ver;
>  }
>
> +#ifndef CONFIG_USER_ONLY
> +static uint8_t satp_mode_from_str(const char *satp_mode_str)
> +{
> +if (!strncmp(satp_mode_str, "mbare", 5)) {
> +return VM_1_10_MBARE;
> +}
> +
> +if (!strncmp(satp_mode_str, "sv32", 4)) {
> +return VM_1_10_SV32;
> +}
> +
> +if (!strncmp(satp_mode_str, "sv39", 4)) {
> +return VM_1_10_SV39;
> +}
> +
> +if (!strncmp(satp_mode_str, "sv48", 4)) {
> +return VM_1_10_SV48;
> +}
> +
> +if (!strncmp(satp_mode_str, "sv57", 4)) {
> +return VM_1_10_SV57;
> +}
> +
> +if (!strncmp(satp_mode_str, "sv64", 4)) {
> +return VM_1_10_SV64;
> +}
> +
> +g_assert_not_reached();
> +}
> +
> +uint8_t satp_mode_max_from_map(uint32_t map)
> +{
> +/* map here has at least one bit set, so no problem with clz */
> +return 31 - __builtin_clz(map);
> +}
> +
> +const char *satp_mode_str(uint8_t satp_mode, bool is_32_bit)
> +{
> +if (is_32_bit) {
> +switch (satp_mode) {
> +case VM_1_10_SV32:
> +return "sv32";
> +case VM_1_10_MBARE:
> +return "none";
> +}
> +} else {
> +switch (satp_mode) {
> +case VM_1_10_SV64:
> +return "sv64";
> +case VM_1_10_SV57:
> +return "sv57";
> +case VM_1_10_SV48:
> +return "sv48";
> +case VM_1_10_SV39:
> +return "sv39";
> +case VM_1_10_MBARE:
> +return "none";
> +}
> +}
> +
> +g_assert_not_reached();
> +}
> +
> +/* Sets the satp mode to the max supported */
> +static void set_satp_mode_default_map(RISCVCPU *cpu)
> +{
> +bool rv32 = riscv_cpu_mxl(>env) == MXL_RV32;
> +
> +if (riscv_feature(>env, RISCV_FEATURE_MMU)) {
> +cpu->cfg.satp_mode.map |=
> +(1 << satp_mode_from_str(rv32 ? "sv32" : "sv57"));
>

Nit:
cpu->cfg.satp_mode.map |=
(1 << (rv32 ? VM_1_10_SV32 : VM_1_10_SV57));


> +} else {
> +cpu->cfg.satp_mode.map |= (1 << satp_mode_from_str("mb

Re: [PATCH v10 4/5] riscv: Introduce satp mode hw capabilities

2023-02-03 Thread Frank Chang
Reviewed-by: Frank Chang 

On Fri, Feb 3, 2023 at 2:02 PM Alexandre Ghiti 
wrote:

> Currently, the max satp mode is set with the only constraint that it must
> be
> implemented in QEMU, i.e. set in valid_vm_1_10_[32|64].
>
> But we actually need to add another level of constraint: what the hw is
> actually capable of, because currently, a linux booting on a sifive-u54
> boots in sv57 mode which is incompatible with the cpu's sv39 max
> capability.
>
> So add a new bitmap to RISCVSATPMap which contains this capability and
> initialize it in every XXX_cpu_init.
>
> Finally:
> - valid_vm_1_10_[32|64] constrains which satp mode the CPU can use
> - the CPU hw capabilities constrains what the user may select
> - the user's selection then constrains what's available to the guest
>   OS.
>
> Signed-off-by: Alexandre Ghiti 
> Reviewed-by: Andrew Jones 
> Reviewed-by: Bin Meng 
> ---
>  target/riscv/cpu.c | 91 +-
>  target/riscv/cpu.h |  8 +++-
>  2 files changed, 72 insertions(+), 27 deletions(-)
>
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index 56057cf87c..7e9924ede9 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -293,18 +293,24 @@ const char *satp_mode_str(uint8_t satp_mode, bool
> is_32_bit)
>  g_assert_not_reached();
>  }
>
> -/* Sets the satp mode to the max supported */
> -static void set_satp_mode_default_map(RISCVCPU *cpu)
> +static void set_satp_mode_max_supported(RISCVCPU *cpu,
> +uint8_t satp_mode)
>  {
>  bool rv32 = riscv_cpu_mxl(>env) == MXL_RV32;
> +const bool *valid_vm = rv32 ? valid_vm_1_10_32 : valid_vm_1_10_64;
>
> -if (riscv_feature(>env, RISCV_FEATURE_MMU)) {
> -cpu->cfg.satp_mode.map |=
> -(1 << satp_mode_from_str(rv32 ? "sv32" : "sv57"));
> -} else {
> -cpu->cfg.satp_mode.map |= (1 << satp_mode_from_str("mbare"));
> +for (int i = 0; i <= satp_mode; ++i) {
> +if (valid_vm[i]) {
> +cpu->cfg.satp_mode.supported |= (1 << i);
> +}
>  }
>  }
> +
> +/* Set the satp mode to the max supported */
> +static void set_satp_mode_default_map(RISCVCPU *cpu)
> +{
> +cpu->cfg.satp_mode.map = cpu->cfg.satp_mode.supported;
> +}
>  #endif
>
>  static void riscv_any_cpu_init(Object *obj)
> @@ -315,6 +321,13 @@ static void riscv_any_cpu_init(Object *obj)
>  #elif defined(TARGET_RISCV64)
>  set_misa(env, MXL_RV64, RVI | RVM | RVA | RVF | RVD | RVC | RVU);
>  #endif
> +
> +#ifndef CONFIG_USER_ONLY
> +set_satp_mode_max_supported(RISCV_CPU(obj),
> +riscv_cpu_mxl(_CPU(obj)->env) == MXL_RV32 ?
> +VM_1_10_SV32 : VM_1_10_SV57);
> +#endif
> +
>  set_priv_version(env, PRIV_VERSION_1_12_0);
>  register_cpu_props(obj);
>  }
> @@ -328,6 +341,9 @@ static void rv64_base_cpu_init(Object *obj)
>  register_cpu_props(obj);
>  /* Set latest version of privileged specification */
>  set_priv_version(env, PRIV_VERSION_1_12_0);
> +#ifndef CONFIG_USER_ONLY
> +set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV57);
> +#endif
>  }
>
>  static void rv64_sifive_u_cpu_init(Object *obj)
> @@ -335,6 +351,9 @@ static void rv64_sifive_u_cpu_init(Object *obj)
>  CPURISCVState *env = _CPU(obj)->env;
>  set_misa(env, MXL_RV64, RVI | RVM | RVA | RVF | RVD | RVC | RVS |
> RVU);
>  set_priv_version(env, PRIV_VERSION_1_10_0);
> +#ifndef CONFIG_USER_ONLY
> +set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV39);
> +#endif
>  }
>
>  static void rv64_sifive_e_cpu_init(Object *obj)
> @@ -345,6 +364,9 @@ static void rv64_sifive_e_cpu_init(Object *obj)
>  set_misa(env, MXL_RV64, RVI | RVM | RVA | RVC | RVU);
>  set_priv_version(env, PRIV_VERSION_1_10_0);
>  cpu->cfg.mmu = false;
> +#ifndef CONFIG_USER_ONLY
> +set_satp_mode_max_supported(cpu, VM_1_10_MBARE);
> +#endif
>  }
>
>  static void rv128_base_cpu_init(Object *obj)
> @@ -361,6 +383,9 @@ static void rv128_base_cpu_init(Object *obj)
>  register_cpu_props(obj);
>  /* Set latest version of privileged specification */
>  set_priv_version(env, PRIV_VERSION_1_12_0);
> +#ifndef CONFIG_USER_ONLY
> +set_satp_mode_max_supported(RISCV_CPU(obj), VM_1_10_SV57);
> +#endif
>  }
>  #else
>  static void rv32_base_cpu_init(Object *obj)
> @@ -371,6 +396,9 @@ static void rv32_base_cpu_init(Object *obj)
>  register_cpu_props(obj);
>  /* Set latest version of privileged specification */
>  set_priv_version(env, PRIV_VERSI

Re: [PATCH v9 4/5] riscv: Introduce satp mode hw capabilities

2023-02-02 Thread Frank Chang
On Thu, Feb 2, 2023 at 9:01 PM Alexandre Ghiti 
wrote:

> Hi Frank,
>
> On Wed, Feb 1, 2023 at 4:49 PM Frank Chang  wrote:
> >
> > On Tue, Jan 31, 2023 at 10:36 PM Alexandre Ghiti 
> wrote:
> >>
> >> Currently, the max satp mode is set with the only constraint that it
> must be
> >> implemented in QEMU, i.e. set in valid_vm_1_10_[32|64].
> >>
> >> But we actually need to add another level of constraint: what the hw is
> >> actually capable of, because currently, a linux booting on a sifive-u54
> >> boots in sv57 mode which is incompatible with the cpu's sv39 max
> >> capability.
> >>
> >> So add a new bitmap to RISCVSATPMap which contains this capability and
> >> initialize it in every XXX_cpu_init.
> >>
> >> Finally:
> >> - valid_vm_1_10_[32|64] constrains which satp mode the CPU can use
> >> - the CPU hw capabilities constrains what the user may select
> >> - the user's selection then constrains what's available to the guest
> >>   OS.
> >>
> >> Signed-off-by: Alexandre Ghiti 
> >> Reviewed-by: Andrew Jones 
> >> ---
> >>  target/riscv/cpu.c | 79 +++---
> >>  target/riscv/cpu.h |  8 +++--
> >>  2 files changed, 60 insertions(+), 27 deletions(-)
> >>
> >> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> >> index 3a7a1746aa..6dd76355ec 100644
> >> --- a/target/riscv/cpu.c
> >> +++ b/target/riscv/cpu.c
> >> @@ -292,26 +292,36 @@ const char *satp_mode_str(uint8_t satp_mode, bool
> is_32_bit)
> >>  g_assert_not_reached();
> >>  }
> >>
> >> -/* Sets the satp mode to the max supported */
> >> -static void set_satp_mode_default_map(RISCVCPU *cpu)
> >> +static void set_satp_mode_max_supported(RISCVCPU *cpu,
> >> +uint8_t satp_mode)
> >>  {
> >>  bool rv32 = riscv_cpu_mxl(>env) == MXL_RV32;
> >> +const bool *valid_vm = rv32 ? valid_vm_1_10_32 : valid_vm_1_10_64;
> >
> >
> > This will break user-mode QEMU.
> > valid_vm_1_10_32 and valid_vm_1_10_64 are defined in !CONFIG_USER_ONLY
> section.
> > This issue also exists in patch 3.
> > You have to move valid_vm_1_10_32 and valid_vm_1_10_64 out from
> !CONFIG_USER_ONLY.
>
> Indeed, good catch, thanks! Rather than moving valid_vm_1_10_[32|64],
> I'm going to try to surround all the satp handling inside #ifdef
> CONFIG_USER_ONLY. But if it's too cumbersome, I'll do as you suggest.
>

Hi Alex,

I think surrounding all the satp handling inside #ifdef is okay,
since satp is not been used in user-mode QEMU.

Regards,
Frank Chang


>
> Thanks again,
>
> Alex
>
> >
> > Regards,
> > Frank Chang
> >
> >>
> >> -if (riscv_feature(>env, RISCV_FEATURE_MMU)) {
> >> -cpu->cfg.satp_mode.map |=
> >> -(1 << satp_mode_from_str(rv32 ? "sv32" :
> "sv57"));
> >> -} else {
> >> -cpu->cfg.satp_mode.map |= (1 << satp_mode_from_str("mbare"));
> >> +for (int i = 0; i <= satp_mode; ++i) {
> >> +if (valid_vm[i]) {
> >> +cpu->cfg.satp_mode.supported |= (1 << i);
> >> +}
> >>  }
> >>  }
> >>
> >> +/* Set the satp mode to the max supported */
> >> +static void set_satp_mode_default_map(RISCVCPU *cpu)
> >> +{
> >> +cpu->cfg.satp_mode.map = cpu->cfg.satp_mode.supported;
> >> +}
> >> +
> >>  static void riscv_any_cpu_init(Object *obj)
> >>  {
> >>  CPURISCVState *env = _CPU(obj)->env;
> >> +RISCVCPU *cpu = RISCV_CPU(obj);
> >> +
> >>  #if defined(TARGET_RISCV32)
> >>  set_misa(env, MXL_RV32, RVI | RVM | RVA | RVF | RVD | RVC | RVU);
> >> +set_satp_mode_max_supported(cpu, VM_1_10_SV32);
> >>  #elif defined(TARGET_RISCV64)
> >>  set_misa(env, MXL_RV64, RVI | RVM | RVA | RVF | RVD | RVC | RVU);
> >> +set_satp_mode_max_supported(cpu, VM_1_10_SV57);
> >>  #endif
> >>  set_priv_version(env, PRIV_VERSION_1_12_0);
> >>  register_cpu_props(obj);
> >> @@ -321,18 +331,24 @@ static void riscv_any_cpu_init(Object *obj)
> >>  static void rv64_base_cpu_init(Object *obj)
> >>  {
> >>  CPURISCVState *env = _CPU(obj)->env;
> >> +RISCVCPU *cpu = RISCV_CPU(obj);
> >> +
> >>  /* We set 

Re: [PATCH v9 4/5] riscv: Introduce satp mode hw capabilities

2023-02-01 Thread Frank Chang
On Tue, Jan 31, 2023 at 10:36 PM Alexandre Ghiti 
wrote:

> Currently, the max satp mode is set with the only constraint that it must
> be
> implemented in QEMU, i.e. set in valid_vm_1_10_[32|64].
>
> But we actually need to add another level of constraint: what the hw is
> actually capable of, because currently, a linux booting on a sifive-u54
> boots in sv57 mode which is incompatible with the cpu's sv39 max
> capability.
>
> So add a new bitmap to RISCVSATPMap which contains this capability and
> initialize it in every XXX_cpu_init.
>
> Finally:
> - valid_vm_1_10_[32|64] constrains which satp mode the CPU can use
> - the CPU hw capabilities constrains what the user may select
> - the user's selection then constrains what's available to the guest
>   OS.
>
> Signed-off-by: Alexandre Ghiti 
> Reviewed-by: Andrew Jones 
> ---
>  target/riscv/cpu.c | 79 +++---
>  target/riscv/cpu.h |  8 +++--
>  2 files changed, 60 insertions(+), 27 deletions(-)
>
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index 3a7a1746aa..6dd76355ec 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -292,26 +292,36 @@ const char *satp_mode_str(uint8_t satp_mode, bool
> is_32_bit)
>  g_assert_not_reached();
>  }
>
> -/* Sets the satp mode to the max supported */
> -static void set_satp_mode_default_map(RISCVCPU *cpu)
> +static void set_satp_mode_max_supported(RISCVCPU *cpu,
> +uint8_t satp_mode)
>  {
>  bool rv32 = riscv_cpu_mxl(>env) == MXL_RV32;
> +const bool *valid_vm = rv32 ? valid_vm_1_10_32 : valid_vm_1_10_64;
>

This will break user-mode QEMU.
valid_vm_1_10_32 and valid_vm_1_10_64 are defined in !CONFIG_USER_ONLY
section.
This issue also exists in patch 3.
You have to move valid_vm_1_10_32 and valid_vm_1_10_64 out from
!CONFIG_USER_ONLY.

Regards,
Frank Chang


> -if (riscv_feature(>env, RISCV_FEATURE_MMU)) {
> -cpu->cfg.satp_mode.map |=
> -(1 << satp_mode_from_str(rv32 ? "sv32" : "sv57"));
> -} else {
> -cpu->cfg.satp_mode.map |= (1 << satp_mode_from_str("mbare"));
> +for (int i = 0; i <= satp_mode; ++i) {
> +if (valid_vm[i]) {
> +cpu->cfg.satp_mode.supported |= (1 << i);
> +}
>  }
>  }
>
> +/* Set the satp mode to the max supported */
> +static void set_satp_mode_default_map(RISCVCPU *cpu)
> +{
> +cpu->cfg.satp_mode.map = cpu->cfg.satp_mode.supported;
> +}
> +
>  static void riscv_any_cpu_init(Object *obj)
>  {
>  CPURISCVState *env = _CPU(obj)->env;
> +RISCVCPU *cpu = RISCV_CPU(obj);
> +
>  #if defined(TARGET_RISCV32)
>  set_misa(env, MXL_RV32, RVI | RVM | RVA | RVF | RVD | RVC | RVU);
> +set_satp_mode_max_supported(cpu, VM_1_10_SV32);
>  #elif defined(TARGET_RISCV64)
>  set_misa(env, MXL_RV64, RVI | RVM | RVA | RVF | RVD | RVC | RVU);
> +set_satp_mode_max_supported(cpu, VM_1_10_SV57);
>  #endif
>  set_priv_version(env, PRIV_VERSION_1_12_0);
>  register_cpu_props(obj);
> @@ -321,18 +331,24 @@ static void riscv_any_cpu_init(Object *obj)
>  static void rv64_base_cpu_init(Object *obj)
>  {
>  CPURISCVState *env = _CPU(obj)->env;
> +RISCVCPU *cpu = RISCV_CPU(obj);
> +
>  /* We set this in the realise function */
>  set_misa(env, MXL_RV64, 0);
>  register_cpu_props(obj);
>  /* Set latest version of privileged specification */
>  set_priv_version(env, PRIV_VERSION_1_12_0);
> +set_satp_mode_max_supported(cpu, VM_1_10_SV57);
>  }
>
>  static void rv64_sifive_u_cpu_init(Object *obj)
>  {
>  CPURISCVState *env = _CPU(obj)->env;
> +RISCVCPU *cpu = RISCV_CPU(obj);
> +
>  set_misa(env, MXL_RV64, RVI | RVM | RVA | RVF | RVD | RVC | RVS |
> RVU);
>  set_priv_version(env, PRIV_VERSION_1_10_0);
> +set_satp_mode_max_supported(cpu, VM_1_10_SV39);
>  }
>
>  static void rv64_sifive_e_cpu_init(Object *obj)
> @@ -343,6 +359,7 @@ static void rv64_sifive_e_cpu_init(Object *obj)
>  set_misa(env, MXL_RV64, RVI | RVM | RVA | RVC | RVU);
>  set_priv_version(env, PRIV_VERSION_1_10_0);
>  cpu->cfg.mmu = false;
> +set_satp_mode_max_supported(cpu, VM_1_10_MBARE);
>  }
>
>  static void rv128_base_cpu_init(Object *obj)
> @@ -354,28 +371,36 @@ static void rv128_base_cpu_init(Object *obj)
>  exit(EXIT_FAILURE);
>  }
>  CPURISCVState *env = _CPU(obj)->env;
> +RISCVCPU *cpu = RISCV_CPU(obj);
>  /* We set this in the realise function */
>  set_misa(env, MXL_RV128, 0);
>  register_cpu_props(obj

Re: [PATCH v9 5/5] riscv: Correctly set the device-tree entry 'mmu-type'

2023-02-01 Thread Frank Chang
Reviewed-by: Frank Chang 

On Tue, Jan 31, 2023 at 10:36 PM Alexandre Ghiti 
wrote:

> The 'mmu-type' should reflect what the hardware is capable of so use the
> new satp_mode field in RISCVCPUConfig to do that.
>
> Signed-off-by: Alexandre Ghiti 
> Reviewed-by: Andrew Jones 
> Reviewed-by: Alistair Francis 
> Reviewed-by: Bin Meng 
> ---
>  hw/riscv/virt.c | 19 ++-
>  1 file changed, 10 insertions(+), 9 deletions(-)
>
> diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
> index 94ff2a1584..48d034a5f7 100644
> --- a/hw/riscv/virt.c
> +++ b/hw/riscv/virt.c
> @@ -228,7 +228,8 @@ static void create_fdt_socket_cpus(RISCVVirtState *s,
> int socket,
>  int cpu;
>  uint32_t cpu_phandle;
>  MachineState *mc = MACHINE(s);
> -char *name, *cpu_name, *core_name, *intc_name;
> +uint8_t satp_mode_max;
> +char *name, *cpu_name, *core_name, *intc_name, *sv_name;
>
>  for (cpu = s->soc[socket].num_harts - 1; cpu >= 0; cpu--) {
>  cpu_phandle = (*phandle)++;
> @@ -236,14 +237,14 @@ static void create_fdt_socket_cpus(RISCVVirtState
> *s, int socket,
>  cpu_name = g_strdup_printf("/cpus/cpu@%d",
>  s->soc[socket].hartid_base + cpu);
>  qemu_fdt_add_subnode(mc->fdt, cpu_name);
> -if (riscv_feature(>soc[socket].harts[cpu].env,
> -  RISCV_FEATURE_MMU)) {
> -qemu_fdt_setprop_string(mc->fdt, cpu_name, "mmu-type",
> -(is_32_bit) ? "riscv,sv32" :
> "riscv,sv48");
> -} else {
> -qemu_fdt_setprop_string(mc->fdt, cpu_name, "mmu-type",
> -"riscv,none");
> -}
> +
> +satp_mode_max = satp_mode_max_from_map(
> +s->soc[socket].harts[cpu].cfg.satp_mode.map);
> +sv_name = g_strdup_printf("riscv,%s",
> +  satp_mode_str(satp_mode_max,
> is_32_bit));
> +qemu_fdt_setprop_string(mc->fdt, cpu_name, "mmu-type", sv_name);
> +g_free(sv_name);
> +
>  name = riscv_isa_string(>soc[socket].harts[cpu]);
>  qemu_fdt_setprop_string(mc->fdt, cpu_name, "riscv,isa", name);
>  g_free(name);
> --
> 2.37.2
>
>
>


Re: [PATCH v9 2/5] riscv: Change type of valid_vm_1_10_[32|64] to bool

2023-02-01 Thread Frank Chang
Reviewed-by: Frank Chang 

On Tue, Jan 31, 2023 at 10:29 PM Alexandre Ghiti 
wrote:

> This array is actually used as a boolean so swap its current char type
> to a boolean and at the same time, change the type of validate_vm to
> bool since it returns valid_vm_1_10_[32|64].
>
> Suggested-by: Andrew Jones 
> Signed-off-by: Alexandre Ghiti 
> Reviewed-by: Andrew Jones 
> Reviewed-by: Alistair Francis 
> Reviewed-by: Bin Meng 
> ---
>  target/riscv/csr.c | 21 +++--
>  1 file changed, 11 insertions(+), 10 deletions(-)
>
> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> index 0db2c233e5..6b157806a5 100644
> --- a/target/riscv/csr.c
> +++ b/target/riscv/csr.c
> @@ -1117,16 +1117,16 @@ static const target_ulong hip_writable_mask =
> MIP_VSSIP;
>  static const target_ulong hvip_writable_mask = MIP_VSSIP | MIP_VSTIP |
> MIP_VSEIP;
>  static const target_ulong vsip_writable_mask = MIP_VSSIP;
>
> -static const char valid_vm_1_10_32[16] = {
> -[VM_1_10_MBARE] = 1,
> -[VM_1_10_SV32] = 1
> +static const bool valid_vm_1_10_32[16] = {
> +[VM_1_10_MBARE] = true,
> +[VM_1_10_SV32] = true
>  };
>
> -static const char valid_vm_1_10_64[16] = {
> -[VM_1_10_MBARE] = 1,
> -[VM_1_10_SV39] = 1,
> -[VM_1_10_SV48] = 1,
> -[VM_1_10_SV57] = 1
> +static const bool valid_vm_1_10_64[16] = {
> +[VM_1_10_MBARE] = true,
> +[VM_1_10_SV39] = true,
> +[VM_1_10_SV48] = true,
> +[VM_1_10_SV57] = true
>  };
>
>  /* Machine Information Registers */
> @@ -1209,7 +1209,7 @@ static RISCVException read_mstatus(CPURISCVState
> *env, int csrno,
>  return RISCV_EXCP_NONE;
>  }
>
> -static int validate_vm(CPURISCVState *env, target_ulong vm)
> +static bool validate_vm(CPURISCVState *env, target_ulong vm)
>  {
>  if (riscv_cpu_mxl(env) == MXL_RV32) {
>  return valid_vm_1_10_32[vm & 0xf];
> @@ -2648,7 +2648,8 @@ static RISCVException read_satp(CPURISCVState *env,
> int csrno,
>  static RISCVException write_satp(CPURISCVState *env, int csrno,
>   target_ulong val)
>  {
> -target_ulong vm, mask;
> +target_ulong mask;
> +bool vm;
>
>  if (!riscv_feature(env, RISCV_FEATURE_MMU)) {
>  return RISCV_EXCP_NONE;
> --
> 2.37.2
>
>
>


Re: [PATCH v5 1/2] riscv: Pass Object to register_cpu_props instead of DeviceState

2023-01-16 Thread Frank Chang
Reviewed-by: Frank Chang 

On Fri, Jan 13, 2023 at 6:35 PM Alexandre Ghiti 
wrote:

> One can extract the DeviceState pointer from the Object pointer, so pass
> the Object for future commits to access other fields of Object.
>
> No functional changes intended.
>
> Signed-off-by: Alexandre Ghiti 
> ---
>  target/riscv/cpu.c | 15 ---
>  1 file changed, 8 insertions(+), 7 deletions(-)
>
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index cc75ca7667..7181b34f86 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -200,7 +200,7 @@ static const char * const riscv_intr_names[] = {
>  "reserved"
>  };
>
> -static void register_cpu_props(DeviceState *dev);
> +static void register_cpu_props(Object *obj);
>
>  const char *riscv_cpu_get_trap_name(target_ulong cause, bool async)
>  {
> @@ -238,7 +238,7 @@ static void riscv_any_cpu_init(Object *obj)
>  set_misa(env, MXL_RV64, RVI | RVM | RVA | RVF | RVD | RVC | RVU);
>  #endif
>  set_priv_version(env, PRIV_VERSION_1_12_0);
> -register_cpu_props(DEVICE(obj));
> +register_cpu_props(obj);
>  }
>
>  #if defined(TARGET_RISCV64)
> @@ -247,7 +247,7 @@ 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);
> -register_cpu_props(DEVICE(obj));
> +register_cpu_props(obj);
>  /* Set latest version of privileged specification */
>  set_priv_version(env, PRIV_VERSION_1_12_0);
>  }
> @@ -280,7 +280,7 @@ 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);
> -register_cpu_props(DEVICE(obj));
> +register_cpu_props(obj);
>  /* Set latest version of privileged specification */
>  set_priv_version(env, PRIV_VERSION_1_12_0);
>  }
> @@ -290,7 +290,7 @@ 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);
> -register_cpu_props(DEVICE(obj));
> +register_cpu_props(obj);
>  /* Set latest version of privileged specification */
>  set_priv_version(env, PRIV_VERSION_1_12_0);
>  }
> @@ -343,7 +343,7 @@ static void riscv_host_cpu_init(Object *obj)
>  #elif defined(TARGET_RISCV64)
>  set_misa(env, MXL_RV64, 0);
>  #endif
> -register_cpu_props(DEVICE(obj));
> +register_cpu_props(obj);
>  }
>  #endif
>
> @@ -1083,9 +1083,10 @@ static Property riscv_cpu_extensions[] = {
>  DEFINE_PROP_END_OF_LIST(),
>  };
>
> -static void register_cpu_props(DeviceState *dev)
> +static void register_cpu_props(Object *obj)
>  {
>  Property *prop;
> +DeviceState *dev = DEVICE(obj);
>
>  for (prop = riscv_cpu_extensions; prop && prop->name; prop++) {
>  qdev_property_add_static(dev, prop);
> --
> 2.37.2
>
>


Re: [PATCH v4] riscv: Allow user to set the satp mode

2022-12-16 Thread Frank Chang
Hi Alexandre,

Thanks for the contribution. This is really helpful.

It seems like if we want to specify the SATP mode for the "named" CPUs,
we have to do, e.g.:
cpu->cfg.satp_mode.map |= (1 << idx_satp_mode_from_str("sv39"));
in each CPU's init function.

Can we add another helper function to wrap this for the "named" CPUs?

Regards,
Frank Chang


On Mon, Dec 12, 2022 at 6:23 PM Alexandre Ghiti 
wrote:

> RISC-V specifies multiple sizes for addressable memory and Linux probes for
> the machine's support at startup via the satp CSR register (done in
> csr.c:validate_vm).
>
> As per the specification, sv64 must support sv57, which in turn must
> support sv48...etc. So we can restrict machine support by simply setting
> the
> "highest" supported mode and the bare mode is always supported.
>
> You can set the satp mode using the new properties "mbare", "sv32",
> "sv39", "sv48", "sv57" and "sv64" as follows:
> -cpu rv64,sv57=on # Linux will boot using sv57 scheme
> -cpu rv64,sv39=on # Linux will boot using sv39 scheme
>
> We take the highest level set by the user:
> -cpu rv64,sv48=on,sv57=on # Linux will boot using sv57 scheme
>
> We make sure that invalid configurations are rejected:
> -cpu rv64,sv32=on # Can't enable 32-bit satp mode in 64-bit
> -cpu rv64,sv39=off,sv48=on # sv39 must be supported if higher modes are
># enabled
>
> We accept "redundant" configurations:
> -cpu rv64,sv48=on,sv57=off # sv39 must be supported if higher modes are
>
> In addition, we now correctly set the device-tree entry 'mmu-type' using
> those new properties.
>
> Co-Developed-by: Ludovic Henry 
> Signed-off-by: Ludovic Henry 
> Signed-off-by: Alexandre Ghiti 
> ---
> v4:
> - Use custom boolean properties instead of OnOffAuto properties, based
>   on ARMVQMap, as suggested by Andrew
>
> v3:
> - Free sv_name as pointed by Bin
> - Replace satp-mode with boolean properties as suggested by Andrew
> - Removed RB from Atish as the patch considerably changed
>
> v2:
> - Use error_setg + return as suggested by Alistair
> - Add RB from Atish
> - Fixed checkpatch issues missed in v1
> - Replaced Ludovic email address with the rivos one
>
>  hw/riscv/virt.c|  20 +++--
>  target/riscv/cpu.c | 217 +++--
>  target/riscv/cpu.h |  25 ++
>  target/riscv/csr.c |  13 ++-
>  4 files changed, 256 insertions(+), 19 deletions(-)
>
> diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
> index a5bc7353b4..9bb5ba7366 100644
> --- a/hw/riscv/virt.c
> +++ b/hw/riscv/virt.c
> @@ -228,7 +228,8 @@ static void create_fdt_socket_cpus(RISCVVirtState *s,
> int socket,
>  int cpu;
>  uint32_t cpu_phandle;
>  MachineState *mc = MACHINE(s);
> -char *name, *cpu_name, *core_name, *intc_name;
> +uint8_t satp_mode_max;
> +char *name, *cpu_name, *core_name, *intc_name, *sv_name;
>
>  for (cpu = s->soc[socket].num_harts - 1; cpu >= 0; cpu--) {
>  cpu_phandle = (*phandle)++;
> @@ -236,14 +237,15 @@ static void create_fdt_socket_cpus(RISCVVirtState
> *s, int socket,
>  cpu_name = g_strdup_printf("/cpus/cpu@%d",
>  s->soc[socket].hartid_base + cpu);
>  qemu_fdt_add_subnode(mc->fdt, cpu_name);
> -if (riscv_feature(>soc[socket].harts[cpu].env,
> -  RISCV_FEATURE_MMU)) {
> -qemu_fdt_setprop_string(mc->fdt, cpu_name, "mmu-type",
> -(is_32_bit) ? "riscv,sv32" :
> "riscv,sv48");
> -} else {
> -qemu_fdt_setprop_string(mc->fdt, cpu_name, "mmu-type",
> -"riscv,none");
> -}
> +
> +satp_mode_max = satp_mode_max_from_map(
> +s->soc[socket].harts[cpu].cfg.satp_mode.map,
> +is_32_bit);
> +sv_name = g_strdup_printf("riscv,%s",
> +  satp_mode_str(satp_mode_max,
> is_32_bit));
> +qemu_fdt_setprop_string(mc->fdt, cpu_name, "mmu-type", sv_name);
> +g_free(sv_name);
> +
>  name = riscv_isa_string(>soc[socket].harts[cpu]);
>  qemu_fdt_setprop_string(mc->fdt, cpu_name, "riscv,isa", name);
>  g_free(name);
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index d14e95c9dc..639231ce2e 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -27,6 +27,7 @@
>  #include "time_helper.h"
>  #include "exec/exec-all.h&quo

Re: [PATCH] target/riscv/cpu.c: Fix elen check

2022-12-15 Thread Frank Chang
Reviewed-by: Frank Chang 

On Thu, Dec 15, 2022 at 11:09 PM Elta <503386...@qq.com> wrote:

> Should be cpu->cfg.elen in range [8, 64].
>
> Signed-off-by: Dongxue Zhang 
> ---
>  target/riscv/cpu.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index d14e95c9dc..1e8032c969 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -870,7 +870,7 @@ static void riscv_cpu_realize(DeviceState *dev, Error
> **errp)
>  "Vector extension ELEN must be power of 2");
>  return;
>  }
> -if (cpu->cfg.elen > 64 || cpu->cfg.vlen < 8) {
> +if (cpu->cfg.elen > 64 || cpu->cfg.elen < 8) {
>  error_setg(errp,
>  "Vector extension implementation only supports
> ELEN "
>  "in the range [8, 64]");
> --
> 2.17.1
>
>


Re: [PATCH 1/3] target/riscv: Set the CPU resetvec directly

2022-09-27 Thread Frank Chang
Reviewed-by: Frank Chang 

On Wed, Sep 14, 2022 at 6:12 PM Alistair Francis via 
wrote:

> Instead of using our properties to set a config value which then might
> be used to set the resetvec (depending on your timing), let's instead
> just set the resetvec directly in the env struct.
>
> This allows us to set the reset vec from the command line with:
> -global driver=riscv.hart_array,property=resetvec,value=0x2400
>
> Signed-off-by: Alistair Francis 
> ---
>  target/riscv/cpu.h |  3 +--
>  target/riscv/cpu.c | 13 +++--
>  target/riscv/machine.c |  6 +++---
>  3 files changed, 7 insertions(+), 15 deletions(-)
>
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index 06751e1e3e..22344a620b 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -190,7 +190,7 @@ struct CPUArchState {
>  /* This contains QEMU specific information about the virt state. */
>  target_ulong virt;
>  target_ulong geilen;
> -target_ulong resetvec;
> +uint64_t resetvec;
>
>  target_ulong mhartid;
>  /*
> @@ -474,7 +474,6 @@ struct RISCVCPUConfig {
>  bool pmp;
>  bool epmp;
>  bool debug;
> -uint64_t resetvec;
>
>  bool short_isa_string;
>  };
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index aee14a239a..b29c88b9f0 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -228,13 +228,6 @@ static void set_vext_version(CPURISCVState *env, int
> vext_ver)
>  env->vext_ver = vext_ver;
>  }
>
> -static void set_resetvec(CPURISCVState *env, target_ulong resetvec)
> -{
> -#ifndef CONFIG_USER_ONLY
> -env->resetvec = resetvec;
> -#endif
> -}
> -
>  static void riscv_any_cpu_init(Object *obj)
>  {
>  CPURISCVState *env = _CPU(obj)->env;
> @@ -336,7 +329,6 @@ static void rv32_imafcu_nommu_cpu_init(Object *obj)
>
>  set_misa(env, MXL_RV32, RVI | RVM | RVA | RVF | RVC | RVU);
>  set_priv_version(env, PRIV_VERSION_1_10_0);
> -set_resetvec(env, DEFAULT_RSTVEC);
>  cpu->cfg.mmu = false;
>  }
>  #endif
> @@ -676,7 +668,6 @@ static void riscv_cpu_realize(DeviceState *dev, Error
> **errp)
>  riscv_set_feature(env, RISCV_FEATURE_DEBUG);
>  }
>
> -set_resetvec(env, cpu->cfg.resetvec);
>
>  #ifndef CONFIG_USER_ONLY
>  if (cpu->cfg.ext_sstc) {
> @@ -1079,7 +1070,9 @@ static Property riscv_cpu_properties[] = {
>  DEFINE_PROP_UINT64("marchid", RISCVCPU, cfg.marchid,
> RISCV_CPU_MARCHID),
>  DEFINE_PROP_UINT64("mimpid", RISCVCPU, cfg.mimpid, RISCV_CPU_MIMPID),
>
> -DEFINE_PROP_UINT64("resetvec", RISCVCPU, cfg.resetvec,
> DEFAULT_RSTVEC),
> +#ifndef CONFIG_USER_ONLY
> +DEFINE_PROP_UINT64("resetvec", RISCVCPU, env.resetvec,
> DEFAULT_RSTVEC),
> +#endif
>
>  DEFINE_PROP_BOOL("short-isa-string", RISCVCPU, cfg.short_isa_string,
> false),
>
> diff --git a/target/riscv/machine.c b/target/riscv/machine.c
> index 41098f6ad0..c4e6b3bba4 100644
> --- a/target/riscv/machine.c
> +++ b/target/riscv/machine.c
> @@ -308,8 +308,8 @@ static const VMStateDescription vmstate_pmu_ctr_state
> = {
>
>  const VMStateDescription vmstate_riscv_cpu = {
>  .name = "cpu",
> -.version_id = 4,
> -.minimum_version_id = 4,
> +.version_id = 5,
> +.minimum_version_id = 5,
>  .post_load = riscv_cpu_post_load,
>  .fields = (VMStateField[]) {
>  VMSTATE_UINTTL_ARRAY(env.gpr, RISCVCPU, 32),
> @@ -331,7 +331,7 @@ const VMStateDescription vmstate_riscv_cpu = {
>  VMSTATE_UINT32(env.features, RISCVCPU),
>  VMSTATE_UINTTL(env.priv, RISCVCPU),
>  VMSTATE_UINTTL(env.virt, RISCVCPU),
> -VMSTATE_UINTTL(env.resetvec, RISCVCPU),
> +VMSTATE_UINT64(env.resetvec, RISCVCPU),
>  VMSTATE_UINTTL(env.mhartid, RISCVCPU),
>  VMSTATE_UINT64(env.mstatus, RISCVCPU),
>  VMSTATE_UINT64(env.mip, RISCVCPU),
> --
> 2.37.2
>
>
>


Re: [PATCH 2/3] hw/riscv: sifive_e: Support the watchdog timer of HiFive 1 rev b.

2022-09-27 Thread Frank Chang
Reviewed-by: Frank Chang 

On Thu, Sep 22, 2022 at 4:41 PM Tommy Wu  wrote:

> Create the AON device when we realize the sifive_e machine.
> This patch only implemented the functionality of the watchdog timer,
> not all the functionality of the AON device.
>
> Signed-off-by: Tommy Wu 
> ---
>  hw/riscv/Kconfig| 1 +
>  hw/riscv/sifive_e.c | 5 +++--
>  include/hw/riscv/sifive_e.h | 7 ---
>  3 files changed, 8 insertions(+), 5 deletions(-)
>
> diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig
> index 79ff61c464..50890b1b75 100644
> --- a/hw/riscv/Kconfig
> +++ b/hw/riscv/Kconfig
> @@ -59,6 +59,7 @@ config SIFIVE_E
>  select SIFIVE_PLIC
>  select SIFIVE_UART
>  select SIFIVE_E_PRCI
> +select SIFIVE_E_AON
>  select UNIMP
>
>  config SIFIVE_U
> diff --git a/hw/riscv/sifive_e.c b/hw/riscv/sifive_e.c
> index d65d2fd869..f9c05cfd3a 100644
> --- a/hw/riscv/sifive_e.c
> +++ b/hw/riscv/sifive_e.c
> @@ -45,6 +45,7 @@
>  #include "hw/intc/riscv_aclint.h"
>  #include "hw/intc/sifive_plic.h"
>  #include "hw/misc/sifive_e_prci.h"
> +#include "hw/misc/sifive_e_aon.h"
>  #include "chardev/char.h"
>  #include "sysemu/sysemu.h"
>
> @@ -222,8 +223,8 @@ static void sifive_e_soc_realize(DeviceState *dev,
> Error **errp)
>  RISCV_ACLINT_DEFAULT_MTIMER_SIZE, 0, ms->smp.cpus,
>  RISCV_ACLINT_DEFAULT_MTIMECMP, RISCV_ACLINT_DEFAULT_MTIME,
>  RISCV_ACLINT_DEFAULT_TIMEBASE_FREQ, false);
> -create_unimplemented_device("riscv.sifive.e.aon",
> -memmap[SIFIVE_E_DEV_AON].base, memmap[SIFIVE_E_DEV_AON].size);
> +sifive_e_aon_create(sys_mem, memmap[SIFIVE_E_DEV_AON].base,
> +qdev_get_gpio_in(DEVICE(s->plic), SIFIVE_E_AON_WDT_IRQ));
>  sifive_e_prci_create(memmap[SIFIVE_E_DEV_PRCI].base);
>
>  /* GPIO */
> diff --git a/include/hw/riscv/sifive_e.h b/include/hw/riscv/sifive_e.h
> index 83604da805..7de2221564 100644
> --- a/include/hw/riscv/sifive_e.h
> +++ b/include/hw/riscv/sifive_e.h
> @@ -75,9 +75,10 @@ enum {
>  };
>
>  enum {
> -SIFIVE_E_UART0_IRQ  = 3,
> -SIFIVE_E_UART1_IRQ  = 4,
> -SIFIVE_E_GPIO0_IRQ0 = 8
> +SIFIVE_E_AON_WDT_IRQ  = 1,
> +SIFIVE_E_UART0_IRQ= 3,
> +SIFIVE_E_UART1_IRQ= 4,
> +SIFIVE_E_GPIO0_IRQ0   = 8
>  };
>
>  #define SIFIVE_E_PLIC_HART_CONFIG "M"
> --
> 2.27.0
>
>
>


Re: [PATCH 1/3] hw/misc: sifive_e_aon: Support the watchdog timer of HiFive 1 rev b.

2022-09-27 Thread Frank Chang
Reviewed-by: Frank Chang 

On Thu, Sep 22, 2022 at 4:41 PM Tommy Wu  wrote:

> The watchdog timer is in the always-on domain device of HiFive 1 rev b,
> so this patch added the AON device to the sifive_e machine. This patch
> only implemented the functionality of the watchdog timer.
>
> Signed-off-by: Tommy Wu 
> ---
>  hw/misc/Kconfig|   3 +
>  hw/misc/meson.build|   1 +
>  hw/misc/sifive_e_aon.c | 330 +
>  include/hw/misc/sifive_e_aon.h |  87 +
>  4 files changed, 421 insertions(+)
>  create mode 100644 hw/misc/sifive_e_aon.c
>  create mode 100644 include/hw/misc/sifive_e_aon.h
>
> diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
> index cbabe9f78c..7d1247822e 100644
> --- a/hw/misc/Kconfig
> +++ b/hw/misc/Kconfig
> @@ -162,6 +162,9 @@ config SIFIVE_TEST
>  config SIFIVE_E_PRCI
>  bool
>
> +config SIFIVE_E_AON
> +bool
> +
>  config SIFIVE_U_OTP
>  bool
>
> diff --git a/hw/misc/meson.build b/hw/misc/meson.build
> index 95268eddc0..1536a0cc2e 100644
> --- a/hw/misc/meson.build
> +++ b/hw/misc/meson.build
> @@ -30,6 +30,7 @@ softmmu_ss.add(when: 'CONFIG_MCHP_PFSOC_DMC', if_true:
> files('mchp_pfsoc_dmc.c')
>  softmmu_ss.add(when: 'CONFIG_MCHP_PFSOC_IOSCB', if_true:
> files('mchp_pfsoc_ioscb.c'))
>  softmmu_ss.add(when: 'CONFIG_MCHP_PFSOC_SYSREG', if_true:
> files('mchp_pfsoc_sysreg.c'))
>  softmmu_ss.add(when: 'CONFIG_SIFIVE_TEST', if_true:
> files('sifive_test.c'))
> +softmmu_ss.add(when: 'CONFIG_SIFIVE_E_AON', if_true:
> files('sifive_e_aon.c'))
>  softmmu_ss.add(when: 'CONFIG_SIFIVE_E_PRCI', if_true:
> files('sifive_e_prci.c'))
>  softmmu_ss.add(when: 'CONFIG_SIFIVE_U_OTP', if_true:
> files('sifive_u_otp.c'))
>  softmmu_ss.add(when: 'CONFIG_SIFIVE_U_PRCI', if_true:
> files('sifive_u_prci.c'))
> diff --git a/hw/misc/sifive_e_aon.c b/hw/misc/sifive_e_aon.c
> new file mode 100644
> index 00..7773dfb168
> --- /dev/null
> +++ b/hw/misc/sifive_e_aon.c
> @@ -0,0 +1,330 @@
> +/*
> + * SiFive HiFive1 AON (Always On Domain) for QEMU.
> + *
> + * Copyright (c) 2022 SiFive, Inc. All rights reserved.
> + *
> + * This program is free software; you can redistribute it and/or modify it
> + * under the terms and conditions of the GNU General Public License,
> + * version 2 or later, as published by the Free Software Foundation.
> + *
> + * This program is distributed in the hope it will be useful, but WITHOUT
> + * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
> + * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License
> for
> + * more details.
> + *
> + * You should have received a copy of the GNU General Public License
> along with
> + * this program.  If not, see <http://www.gnu.org/licenses/>.
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qapi/error.h"
> +#include "qemu/timer.h"
> +#include "qemu/log.h"
> +#include "hw/irq.h"
> +#include "sysemu/watchdog.h"
> +#include "qapi/visitor.h"
> +#include "hw/misc/sifive_e_aon.h"
> +
> +static void sifive_e_aon_wdt_update_wdogcount(SiFiveEAONState *r)
> +{
> +if (0 == r->wdogcfg.wdogenalways &&
> +0 == r->wdogcfg.wdogencoreawake) {
> +return;
> +}
> +int64_t now = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
> +r->wdogcount += muldiv64(now - r->wdog_restart_time,
> + r->wdogclk_freq, NANOSECONDS_PER_SECOND);
> +/* Clean the most significant bit. */
> +r->wdogcount = ((r->wdogcount << 1) >> 1);
> +r->wdog_restart_time = now;
> +}
> +
> +static void sifive_e_aon_wdt_update_state(SiFiveEAONState *r)
> +{
> +sifive_e_aon_wdt_update_wdogcount(r);
> +uint16_t wdogs = (uint16_t)(r->wdogcount >> r->wdogcfg.wdogscale);
> +bool cmp_signal = false;
> +if (wdogs >= r->wdogcmp0) {
> +cmp_signal = true;
> +if (1 == r->wdogcfg.wdogzerocmp) {
> +r->wdogcount = 0;
> +wdogs = 0;
> +}
> +}
> +
> +if (cmp_signal) {
> +if (1 == r->wdogcfg.wdogrsten) {
> +watchdog_perform_action();
> +}
> +r->wdogcfg.wdogip0 = 1;
> +}
> +
> +qemu_set_irq(r->wdog_irq, r->wdogcfg.wdogip0);
> +
> +if (wdogs < r->wdogcmp0 &&
> +(r->wdogcfg.wdogenalways ||
> + r->wdogcfg.wdogencoreawake)) {
> +int64_t next = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL);
> +next += muldiv64((r->wdogcmp0 - wdogs) << r->wdo

Re: [PATCH 3/3] tests/qtest: sifive-e-aon-watchdog-test.c : Add QTest of watchdog of sifive_e

2022-09-27 Thread Frank Chang
Reviewed-by: Frank Chang 

On Thu, Sep 22, 2022 at 4:42 PM Tommy Wu  wrote:

> Add some simple tests of the watchdog timer in the always-on domain device
> of HiFive 1 rev b.
>
> Signed-off-by: Tommy Wu 
> ---
>  tests/qtest/meson.build  |   3 +
>  tests/qtest/sifive-e-aon-watchdog-test.c | 400 +++
>  2 files changed, 403 insertions(+)
>  create mode 100644 tests/qtest/sifive-e-aon-watchdog-test.c
>
> diff --git a/tests/qtest/meson.build b/tests/qtest/meson.build
> index e910cb32ca..446115ea34 100644
> --- a/tests/qtest/meson.build
> +++ b/tests/qtest/meson.build
> @@ -234,6 +234,9 @@ qtests_s390x = \
> 'cpu-plug-test',
> 'migration-test']
>
> +qtests_riscv32 = \
> +  (config_all_devices.has_key('CONFIG_SIFIVE_E_AON') ?
> ['sifive-e-aon-watchdog-test'] : [])
> +
>  qos_test_ss = ss.source_set()
>  qos_test_ss.add(
>'ac97-test.c',
> diff --git a/tests/qtest/sifive-e-aon-watchdog-test.c
> b/tests/qtest/sifive-e-aon-watchdog-test.c
> new file mode 100644
> index 00..a583539346
> --- /dev/null
> +++ b/tests/qtest/sifive-e-aon-watchdog-test.c
> @@ -0,0 +1,400 @@
> +#include "qemu/osdep.h"
> +#include "qemu/timer.h"
> +#include "qemu/bitops.h"
> +#include "libqtest-single.h"
> +#include "hw/misc/sifive_e_aon.h"
> +
> +#define WDOG_BASE (0x1000)
> +#define WDOGCFG (0x0)
> +#define WDOGCOUNT (0x8)
> +#define WDOGS (0x10)
> +#define WDOGFEED (0x18)
> +#define WDOGKEY (0x1c)
> +#define WDOGCMP0 (0x20)
> +
> +#define SIFIVE_E_AON_WDOGKEY (0x51F15E)
> +#define SIFIVE_E_AON_WDOGFEED (0xD09F00D)
> +#define SIFIVE_E_LFCLK_DEFAULT_FREQ (32768)
> +
> +static void test_init(void)
> +{
> +writel(WDOG_BASE + WDOGKEY, SIFIVE_E_AON_WDOGKEY);
> +writel(WDOG_BASE + WDOGCOUNT, 0);
> +
> +writel(WDOG_BASE + WDOGKEY, SIFIVE_E_AON_WDOGKEY);
> +writel(WDOG_BASE + WDOGCFG, 0);
> +
> +writel(WDOG_BASE + WDOGKEY, SIFIVE_E_AON_WDOGKEY);
> +writel(WDOG_BASE + WDOGCMP0, 0xBEEF);
> +}
> +
> +static void test_wdogcount(void)
> +{
> +test_init();
> +
> +uint64_t tmp;
> +tmp = readl(WDOG_BASE + WDOGCOUNT);
> +writel(WDOG_BASE + WDOGCOUNT, 0xBEEF);
> +g_assert(readl(WDOG_BASE + WDOGCOUNT) == tmp);
> +
> +writel(WDOG_BASE + WDOGKEY, SIFIVE_E_AON_WDOGKEY);
> +writel(WDOG_BASE + WDOGCOUNT, 0xBEEF);
> +g_assert(0xBEEF == readl(WDOG_BASE + WDOGCOUNT));
> +
> +writel(WDOG_BASE + WDOGKEY, SIFIVE_E_AON_WDOGKEY);
> +writel(WDOG_BASE + WDOGCOUNT, 0x);
> +g_assert(0x2AAA == readl(WDOG_BASE + WDOGCOUNT));
> +
> +writel(WDOG_BASE + WDOGKEY, SIFIVE_E_AON_WDOGKEY);
> +writel(WDOG_BASE + WDOGFEED, 0x);
> +g_assert(0x2AAA == readl(WDOG_BASE + WDOGCOUNT));
> +
> +writel(WDOG_BASE + WDOGKEY, SIFIVE_E_AON_WDOGKEY);
> +writel(WDOG_BASE + WDOGFEED, SIFIVE_E_AON_WDOGFEED);
> +g_assert(0 == readl(WDOG_BASE + WDOGCOUNT));
> +}
> +
> +static void test_wdogcfg(void)
> +{
> +test_init();
> +
> +wdogcfg_s tmp;
> +tmp.value = readl(WDOG_BASE + WDOGCFG);
> +writel(WDOG_BASE + WDOGCFG, 0x);
> +g_assert(readl(WDOG_BASE + WDOGCFG) == tmp.value);
> +
> +writel(WDOG_BASE + WDOGKEY, SIFIVE_E_AON_WDOGKEY);
> +writel(WDOG_BASE + WDOGCFG, 0x);
> +g_assert(0x == readl(WDOG_BASE + WDOGCFG));
> +
> +tmp.value = readl(WDOG_BASE + WDOGCFG);
> +g_assert(15 == tmp.wdogscale);
> +g_assert(1 == tmp.wdogrsten);
> +g_assert(1 == tmp.wdogzerocmp);
> +g_assert(1 == tmp.wdogenalways);
> +g_assert(1 == tmp.wdogencoreawake);
> +g_assert(1 == tmp.wdogip0);
> +
> +writel(WDOG_BASE + WDOGKEY, SIFIVE_E_AON_WDOGKEY);
> +writel(WDOG_BASE + WDOGCFG, 0);
> +g_assert(0 == readl(WDOG_BASE + WDOGCFG));
> +
> +tmp.value = readl(WDOG_BASE + WDOGCFG);
> +g_assert(0 == tmp.wdogscale);
> +g_assert(0 == tmp.wdogrsten);
> +g_assert(0 == tmp.wdogzerocmp);
> +g_assert(0 == tmp.wdogenalways);
> +g_assert(0 == tmp.wdogencoreawake);
> +g_assert(0 == tmp.wdogip0);
> +}
> +
> +static void test_wdogcmp0(void)
> +{
> +test_init();
> +
> +wdogcfg_s tmp;
> +tmp.value = readl(WDOG_BASE + WDOGCMP0);
> +writel(WDOG_BASE + WDOGCMP0, 0xBEEF);
> +g_assert(readl(WDOG_BASE + WDOGCMP0) == tmp.value);
> +
> +writel(WDOG_BASE + WDOGKEY, SIFIVE_E_AON_WDOGKEY);
> +writel(WDOG_BASE + WDOGCMP0, 0xBEEF);
> +g_assert(0xBEEF == readl(WDOG_BASE + WDOGCMP0));
> +}
> +
> +static void test_wdogkey(void)
> +{
> +test_init();
> +
> +g_a

Re: [PATCH 2/2] target/riscv: rvv-1.0: vf[w]redsum distinguish between ordered/unordered

2022-09-25 Thread Frank Chang
Reviewed-by: Frank Chang 

On Wed, Aug 17, 2022 at 11:45 PM Yang Liu  wrote:

> Starting with RVV1.0, the original vf[w]redsum_vs instruction was renamed
> to vf[w]redusum_vs. The distinction between ordered and unordered is also
> more consistent with other instructions, although there is no difference
> in implementation between the two for QEMU.
>
> Signed-off-by: Yang Liu 
> ---
>  target/riscv/helper.h   | 15 ++-
>  target/riscv/insn32.decode  |  6 --
>  target/riscv/insn_trans/trans_rvv.c.inc |  6 --
>  target/riscv/vector_helper.c| 19 +--
>  4 files changed, 31 insertions(+), 15 deletions(-)
>
> diff --git a/target/riscv/helper.h b/target/riscv/helper.h
> index 4ef3b2251d..a03014fe67 100644
> --- a/target/riscv/helper.h
> +++ b/target/riscv/helper.h
> @@ -1009,9 +1009,12 @@ DEF_HELPER_6(vwredsum_vs_b, void, ptr, ptr, ptr,
> ptr, env, i32)
>  DEF_HELPER_6(vwredsum_vs_h, void, ptr, ptr, ptr, ptr, env, i32)
>  DEF_HELPER_6(vwredsum_vs_w, void, ptr, ptr, ptr, ptr, env, i32)
>
> -DEF_HELPER_6(vfredsum_vs_h, void, ptr, ptr, ptr, ptr, env, i32)
> -DEF_HELPER_6(vfredsum_vs_w, void, ptr, ptr, ptr, ptr, env, i32)
> -DEF_HELPER_6(vfredsum_vs_d, void, ptr, ptr, ptr, ptr, env, i32)
> +DEF_HELPER_6(vfredusum_vs_h, void, ptr, ptr, ptr, ptr, env, i32)
> +DEF_HELPER_6(vfredusum_vs_w, void, ptr, ptr, ptr, ptr, env, i32)
> +DEF_HELPER_6(vfredusum_vs_d, void, ptr, ptr, ptr, ptr, env, i32)
> +DEF_HELPER_6(vfredosum_vs_h, void, ptr, ptr, ptr, ptr, env, i32)
> +DEF_HELPER_6(vfredosum_vs_w, void, ptr, ptr, ptr, ptr, env, i32)
> +DEF_HELPER_6(vfredosum_vs_d, void, ptr, ptr, ptr, ptr, env, i32)
>  DEF_HELPER_6(vfredmax_vs_h, void, ptr, ptr, ptr, ptr, env, i32)
>  DEF_HELPER_6(vfredmax_vs_w, void, ptr, ptr, ptr, ptr, env, i32)
>  DEF_HELPER_6(vfredmax_vs_d, void, ptr, ptr, ptr, ptr, env, i32)
> @@ -1019,8 +1022,10 @@ DEF_HELPER_6(vfredmin_vs_h, void, ptr, ptr, ptr,
> ptr, env, i32)
>  DEF_HELPER_6(vfredmin_vs_w, void, ptr, ptr, ptr, ptr, env, i32)
>  DEF_HELPER_6(vfredmin_vs_d, void, ptr, ptr, ptr, ptr, env, i32)
>
> -DEF_HELPER_6(vfwredsum_vs_h, void, ptr, ptr, ptr, ptr, env, i32)
> -DEF_HELPER_6(vfwredsum_vs_w, void, ptr, ptr, ptr, ptr, env, i32)
> +DEF_HELPER_6(vfwredusum_vs_h, void, ptr, ptr, ptr, ptr, env, i32)
> +DEF_HELPER_6(vfwredusum_vs_w, void, ptr, ptr, ptr, ptr, env, i32)
> +DEF_HELPER_6(vfwredosum_vs_h, void, ptr, ptr, ptr, ptr, env, i32)
> +DEF_HELPER_6(vfwredosum_vs_w, void, ptr, ptr, ptr, ptr, env, i32)
>
>  DEF_HELPER_6(vmand_mm, void, ptr, ptr, ptr, ptr, env, i32)
>  DEF_HELPER_6(vmnand_mm, void, ptr, ptr, ptr, ptr, env, i32)
> diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
> index 4033565393..2873a7ae04 100644
> --- a/target/riscv/insn32.decode
> +++ b/target/riscv/insn32.decode
> @@ -659,11 +659,13 @@ vredmax_vs  000111 . . . 010 .
> 1010111 @r_vm
>  vwredsumu_vs11 . . . 000 . 1010111 @r_vm
>  vwredsum_vs 110001 . . . 000 . 1010111 @r_vm
>  # Vector ordered and unordered reduction sum
> -vfredsum_vs -1 . . . 001 . 1010111 @r_vm
> +vfredusum_vs01 . . . 001 . 1010111 @r_vm
> +vfredosum_vs11 . . . 001 . 1010111 @r_vm
>  vfredmin_vs 000101 . . . 001 . 1010111 @r_vm
>  vfredmax_vs 000111 . . . 001 . 1010111 @r_vm
>  # Vector widening ordered and unordered float reduction sum
> -vfwredsum_vs1100-1 . . . 001 . 1010111 @r_vm
> +vfwredusum_vs   110001 . . . 001 . 1010111 @r_vm
> +vfwredosum_vs   110011 . . . 001 . 1010111 @r_vm
>  vmand_mm011001 - . . 010 . 1010111 @r
>  vmnand_mm   011101 - . . 010 . 1010111 @r
>  vmandn_mm   011000 - . . 010 . 1010111 @r
> diff --git a/target/riscv/insn_trans/trans_rvv.c.inc
> b/target/riscv/insn_trans/trans_rvv.c.inc
> index 6c091824b6..9c9de17f8a 100644
> --- a/target/riscv/insn_trans/trans_rvv.c.inc
> +++ b/target/riscv/insn_trans/trans_rvv.c.inc
> @@ -3112,7 +3112,8 @@ static bool freduction_check(DisasContext *s,
> arg_rmrr *a)
> require_zve64f(s);
>  }
>
> -GEN_OPFVV_TRANS(vfredsum_vs, freduction_check)
> +GEN_OPFVV_TRANS(vfredusum_vs, freduction_check)
> +GEN_OPFVV_TRANS(vfredosum_vs, freduction_check)
>  GEN_OPFVV_TRANS(vfredmax_vs, freduction_check)
>  GEN_OPFVV_TRANS(vfredmin_vs, freduction_check)
>
> @@ -3124,7 +3125,8 @@ static bool freduction_widen_check(DisasContext *s,
> arg_rmrr *a)
> (s->sew != MO_8);
>  }
>
> -GEN_OPFVV_WIDEN_TRANS(vfwredsum_vs, freduction_widen_check)
> +GEN_OPFVV_WIDEN_TRANS(vfwredusum_vs, freduction_widen_c

Re: [PATCH 1/2] target/riscv: rvv-1.0: Simplify vfwredsum code

2022-09-25 Thread Frank Chang
Reviewed-by: Frank Chang 

On Wed, Aug 17, 2022 at 11:32 PM Yang Liu  wrote:

> Remove duplicate code by wrapping vfwredsum_vs's OP function.
>
> Signed-off-by: Yang Liu 
> ---
>  target/riscv/vector_helper.c | 56 +++-
>  1 file changed, 10 insertions(+), 46 deletions(-)
>
> diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c
> index a96fc49c71..fd83c0b20b 100644
> --- a/target/riscv/vector_helper.c
> +++ b/target/riscv/vector_helper.c
> @@ -4655,58 +4655,22 @@ GEN_VEXT_FRED(vfredmin_vs_h, uint16_t, uint16_t,
> H2, H2, float16_minimum_number)
>  GEN_VEXT_FRED(vfredmin_vs_w, uint32_t, uint32_t, H4, H4,
> float32_minimum_number)
>  GEN_VEXT_FRED(vfredmin_vs_d, uint64_t, uint64_t, H8, H8,
> float64_minimum_number)
>
> -/* Vector Widening Floating-Point Reduction Instructions */
> -/* Unordered reduce 2*SEW = 2*SEW + sum(promote(SEW)) */
> -void HELPER(vfwredsum_vs_h)(void *vd, void *v0, void *vs1,
> -void *vs2, CPURISCVState *env, uint32_t desc)
> +/* Vector Widening Floating-Point Add Instructions */
> +static uint32_t fwadd16(uint32_t a, uint16_t b, float_status *s)
>  {
> -uint32_t vm = vext_vm(desc);
> -uint32_t vl = env->vl;
> -uint32_t esz = sizeof(uint32_t);
> -uint32_t vlenb = simd_maxsz(desc);
> -uint32_t vta = vext_vta(desc);
> -uint32_t i;
> -uint32_t s1 =  *((uint32_t *)vs1 + H4(0));
> -
> -for (i = env->vstart; i < vl; i++) {
> -uint16_t s2 = *((uint16_t *)vs2 + H2(i));
> -if (!vm && !vext_elem_mask(v0, i)) {
> -continue;
> -}
> -s1 = float32_add(s1, float16_to_float32(s2, true,
> >fp_status),
> - >fp_status);
> -}
> -*((uint32_t *)vd + H4(0)) = s1;
> -env->vstart = 0;
> -/* set tail elements to 1s */
> -vext_set_elems_1s(vd, vta, esz, vlenb);
> +return float32_add(a, float16_to_float32(b, true, s), s);
>  }
>
> -void HELPER(vfwredsum_vs_w)(void *vd, void *v0, void *vs1,
> -void *vs2, CPURISCVState *env, uint32_t desc)
> +static uint64_t fwadd32(uint64_t a, uint32_t b, float_status *s)
>  {
> -uint32_t vm = vext_vm(desc);
> -uint32_t vl = env->vl;
> -uint32_t esz = sizeof(uint64_t);
> -uint32_t vlenb = simd_maxsz(desc);
> -uint32_t vta = vext_vta(desc);
> -uint32_t i;
> -uint64_t s1 =  *((uint64_t *)vs1);
> -
> -for (i = env->vstart; i < vl; i++) {
> -uint32_t s2 = *((uint32_t *)vs2 + H4(i));
> -if (!vm && !vext_elem_mask(v0, i)) {
> -continue;
> -}
> -s1 = float64_add(s1, float32_to_float64(s2, >fp_status),
> - >fp_status);
> -}
> -*((uint64_t *)vd) = s1;
> -env->vstart = 0;
> -/* set tail elements to 1s */
> -vext_set_elems_1s(vd, vta, esz, vlenb);
> +return float64_add(a, float32_to_float64(b, s), s);
>  }
>
> +/* Vector Widening Floating-Point Reduction Instructions */
> +/* Unordered reduce 2*SEW = 2*SEW + sum(promote(SEW)) */
> +GEN_VEXT_FRED(vfwredsum_vs_h, uint32_t, uint16_t, H4, H2, fwadd16)
> +GEN_VEXT_FRED(vfwredsum_vs_w, uint64_t, uint32_t, H8, H4, fwadd32)
> +
>  /*
>   *** Vector Mask Operations
>   */
> --
> 2.30.1 (Apple Git-130)
>
>
>


Re: [PATCH] hw/riscv/sifive_e: Fix inheritance of SiFiveEState

2022-09-22 Thread Frank Chang
Hi Bernhard,

I think there's already a similar patch for this bug fix:
https://www.mail-archive.com/qemu-devel@nongnu.org/msg905424.html

Regards,
Frank Chang

On Thu, Sep 22, 2022 at 3:53 PM Bernhard Beschow  wrote:

> SiFiveEState inherits from SysBusDevice while it's TypeInfo claims it to
> inherit from TYPE_MACHINE. This is an inconsistency which can cause
> undefined behavior such as memory corruption.
>
> Change SiFiveEState to inherit from MachineState since it is registered
> as a machine.
>
> Fixes: 0869490b1c ("riscv: sifive_e: Manually define the machine")
>
> Signed-off-by: Bernhard Beschow 
> Reviewed-by: Alistair Francis 
> Reviewed-by: Philippe Mathieu-Daudé 
> ---
>  include/hw/riscv/sifive_e.h | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/include/hw/riscv/sifive_e.h b/include/hw/riscv/sifive_e.h
> index 83604da805..d738745925 100644
> --- a/include/hw/riscv/sifive_e.h
> +++ b/include/hw/riscv/sifive_e.h
> @@ -22,6 +22,7 @@
>  #include "hw/riscv/riscv_hart.h"
>  #include "hw/riscv/sifive_cpu.h"
>  #include "hw/gpio/sifive_gpio.h"
> +#include "hw/boards.h"
>
>  #define TYPE_RISCV_E_SOC "riscv.sifive.e.soc"
>  #define RISCV_E_SOC(obj) \
> @@ -41,7 +42,7 @@ typedef struct SiFiveESoCState {
>
>  typedef struct SiFiveEState {
>  /*< private >*/
> -SysBusDevice parent_obj;
> +MachineState parent_obj;
>
>  /*< public >*/
>  SiFiveESoCState soc;
> --
> 2.37.3
>
>
>


[PATCH] target/riscv: Check the correct exception cause in vector GDB stub

2022-09-18 Thread frank . chang
From: Frank Chang 

After RISCVException enum is introduced, riscv_csrrw_debug() returns
RISCV_EXCP_NONE to indicate there's no error. RISC-V vector GDB stub
should check the result against RISCV_EXCP_NONE instead of value 0.
Otherwise, 'E14' packet would be incorrectly reported for vector CSRs
when using "info reg vector" GDB command.

Signed-off-by: Frank Chang 
Reviewed-by: Jim Shu 
Reviewed-by: Tommy Wu 
---
 target/riscv/gdbstub.c | 4 ++--
 1 file changed, 2 insertions(+), 2 deletions(-)

diff --git a/target/riscv/gdbstub.c b/target/riscv/gdbstub.c
index 9ed049c29e..118bd40f10 100644
--- a/target/riscv/gdbstub.c
+++ b/target/riscv/gdbstub.c
@@ -211,7 +211,7 @@ static int riscv_gdb_get_vector(CPURISCVState *env, 
GByteArray *buf, int n)
 target_ulong val = 0;
 int result = riscv_csrrw_debug(env, csrno, , 0, 0);
 
-if (result == 0) {
+if (result == RISCV_EXCP_NONE) {
 return gdb_get_regl(buf, val);
 }
 
@@ -238,7 +238,7 @@ static int riscv_gdb_set_vector(CPURISCVState *env, uint8_t 
*mem_buf, int n)
 target_ulong val = ldtul_p(mem_buf);
 int result = riscv_csrrw_debug(env, csrno, NULL, val, -1);
 
-if (result == 0) {
+if (result == RISCV_EXCP_NONE) {
 return sizeof(target_ulong);
 }
 
-- 
2.36.1




Re: [PATCH 1/2] util/log: Add vu to dump content of vector unit

2022-07-11 Thread Frank Chang
On Fri, Jul 8, 2022 at 4:57 PM Kito Cheng  wrote:

> Add new option for -d vu to dump the content of vector unit, many target
> has vector register, but there is no easy way to dump the content, we
> use this on downstream for a while to help debug, and I feel that's
> really useful, so I think it would be great to upstream that to save debug
> time
> for other people :)
>
> Signed-off-by: Kito Cheng 
> ---
>  accel/tcg/cpu-exec.c  | 3 +++
>  include/hw/core/cpu.h | 2 ++
>  include/qemu/log.h| 1 +
>  util/log.c| 2 ++
>  4 files changed, 8 insertions(+)
>
> diff --git a/accel/tcg/cpu-exec.c b/accel/tcg/cpu-exec.c
> index a565a3f8ec..2cbec0a6ed 100644
> --- a/accel/tcg/cpu-exec.c
> +++ b/accel/tcg/cpu-exec.c
> @@ -221,6 +221,9 @@ static inline void log_cpu_exec(target_ulong pc,
> CPUState *cpu,
>  if (qemu_loglevel_mask(CPU_LOG_TB_FPU)) {
>  flags |= CPU_DUMP_FPU;
>  }
> +if (qemu_loglevel_mask(CPU_LOG_TB_VU)) {
> +flags |= CPU_DUMP_VU;
> +}
>  #if defined(TARGET_I386)
>  flags |= CPU_DUMP_CCOP;
>  #endif
> diff --git a/include/hw/core/cpu.h b/include/hw/core/cpu.h
> index 996f94059f..7a767e17cd 100644
> --- a/include/hw/core/cpu.h
> +++ b/include/hw/core/cpu.h
> @@ -535,11 +535,13 @@ GuestPanicInformation *cpu_get_crash_info(CPUState
> *cpu);
>   * @CPU_DUMP_CODE:
>   * @CPU_DUMP_FPU: dump FPU register state, not just integer
>   * @CPU_DUMP_CCOP: dump info about TCG QEMU's condition code optimization
> state
> + * @CPU_DUMP_VU: dump vector register state
>   */
>  enum CPUDumpFlags {
>  CPU_DUMP_CODE = 0x0001,
>  CPU_DUMP_FPU  = 0x0002,
>  CPU_DUMP_CCOP = 0x0004,
> +CPU_DUMP_VU   = 0x0008,
>  };
>
>  /**
> diff --git a/include/qemu/log.h b/include/qemu/log.h
> index c5643d8dd5..49bd0b0fbc 100644
> --- a/include/qemu/log.h
> +++ b/include/qemu/log.h
> @@ -35,6 +35,7 @@ bool qemu_log_separate(void);
>  /* LOG_STRACE is used for user-mode strace logging. */
>  #define LOG_STRACE (1 << 19)
>  #define LOG_PER_THREAD (1 << 20)
> +#define CPU_LOG_TB_VU  (1 << 21)
>
>  /* Lock/unlock output. */
>
> diff --git a/util/log.c b/util/log.c
> index d6eb0378c3..775d122c2e 100644
> --- a/util/log.c
> +++ b/util/log.c
> @@ -441,6 +441,8 @@ const QEMULogItem qemu_log_items[] = {
>  #ifdef CONFIG_PLUGIN
>  { CPU_LOG_PLUGIN, "plugin", "output from TCG plugins\n"},
>  #endif
> +{ CPU_LOG_TB_VU, "vu",
> +  "include vector unit registers in the 'cpu' logging" },
>  { LOG_STRACE, "strace",
>"log every user-mode syscall, its input, and its result" },
>  { LOG_PER_THREAD, "tid",
> --
> 2.34.0
>
>
Reviewed-by: Frank Chang 


Re: [PATCH 2/2] target/riscv: Auto set elen from vector extension by default

2022-07-11 Thread Frank Chang
On Fri, Jul 8, 2022 at 3:39 PM Kito Cheng  wrote:

> Default ELEN is setting to 64 for now, which is incorrect setting for
> Zve32*, and spec has mention minimum VLEN and supported EEW in chapter
> "Zve*: Vector Extensions for Embedded Processors" is 32 for Zve32.
>
> ELEN actaully could be derived from which extensions are enabled,
> so this patch set elen to 0 as auto detect, and keep the capability to
> let user could configure that.
>
> Signed-off-by: Kito Cheng 
> ---
>  target/riscv/cpu.c | 16 +---
>  1 file changed, 13 insertions(+), 3 deletions(-)
>
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index 487d0faa63..c1b96da7da 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -751,13 +751,22 @@ static void riscv_cpu_realize(DeviceState *dev,
> Error **errp)
>  "Vector extension ELEN must be power of 2");
>  return;
>  }
> -if (cpu->cfg.elen > 64 || cpu->cfg.vlen < 8) {
> +if (cpu->cfg.elen == 0) {
> +  if (cpu->cfg.ext_zve32f) {
> +cpu->cfg.elen = 32;
> +  }
> +  if (cpu->cfg.ext_zve64f || cpu->cfg.ext_v) {
> +cpu->cfg.elen = 64;
> +  }
> +}
> +if (cpu->cfg.elen != 0 && (cpu->cfg.elen > 64 ||
> +   cpu->cfg.elen < 8)) {
>  error_setg(errp,
>  "Vector extension implementation only supports
> ELEN "
>      "in the range [8, 64]");
>  return;
>  }
>

Should we also check whether cpu->cfg.elen set by user must >= 32 if Zve32f
is enabled?
Same for Zve64f.

Regards,
Frank Chang


> -if (cpu->cfg.vlen < cpu->cfg.elen) {
> +if (cpu->cfg.elen != 0 && cpu->cfg.vlen < cpu->cfg.elen) {
>  error_setg(errp,
>  "Vector extension VLEN must be greater than or
> equal "
>  "to ELEN");
> @@ -901,7 +910,8 @@ static Property riscv_cpu_extensions[] = {
>  DEFINE_PROP_STRING("priv_spec", RISCVCPU, cfg.priv_spec),
>  DEFINE_PROP_STRING("vext_spec", RISCVCPU, cfg.vext_spec),
>  DEFINE_PROP_UINT16("vlen", RISCVCPU, cfg.vlen, 128),
> -DEFINE_PROP_UINT16("elen", RISCVCPU, cfg.elen, 64),
> +/* elen = 0 means set from v or zve* extension */
> +DEFINE_PROP_UINT16("elen", RISCVCPU, cfg.elen, 0),
>
>  DEFINE_PROP_BOOL("svinval", RISCVCPU, cfg.ext_svinval, false),
>  DEFINE_PROP_BOOL("svnapot", RISCVCPU, cfg.ext_svnapot, false),
> --
> 2.34.0
>
>


[PATCH 8/9] target/riscv: debug: Return 0 if previous value written to tselect >= number of triggers

2022-06-09 Thread frank . chang
From: Frank Chang 

If the value written to tselect is greater than or equal to the number
of supported triggers, then the following reads of tselect would return
value 0.

Signed-off-by: Frank Chang 
---
 target/riscv/cpu.h   | 1 +
 target/riscv/debug.c | 6 ++
 2 files changed, 7 insertions(+)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index bac5f00722..c7ee3f80e6 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -289,6 +289,7 @@ struct CPUArchState {
 
 /* trigger module */
 target_ulong trigger_cur;
+target_ulong trigger_prev;
 target_ulong tdata1[RV_MAX_TRIGGERS];
 target_ulong tdata2[RV_MAX_TRIGGERS];
 target_ulong tdata3[RV_MAX_TRIGGERS];
diff --git a/target/riscv/debug.c b/target/riscv/debug.c
index ce9ff15d75..83b72fa1b9 100644
--- a/target/riscv/debug.c
+++ b/target/riscv/debug.c
@@ -158,6 +158,10 @@ bool tdata_available(CPURISCVState *env, int tdata_index)
 
 target_ulong tselect_csr_read(CPURISCVState *env)
 {
+if (env->trigger_prev >= RV_MAX_TRIGGERS) {
+return 0;
+}
+
 return env->trigger_cur;
 }
 
@@ -166,6 +170,8 @@ void tselect_csr_write(CPURISCVState *env, target_ulong val)
 if (val < RV_MAX_TRIGGERS) {
 env->trigger_cur = val;
 }
+
+env->trigger_prev = val;
 }
 
 static target_ulong tdata1_validate(CPURISCVState *env, target_ulong val,
-- 
2.36.1




[PATCH 9/9] target/riscv: debug: Add initial support of type 6 trigger

2022-06-09 Thread frank . chang
From: Frank Chang 

Type 6 trigger is similar to a type 2 trigger, but provides additional
functionality and should be used instead of type 2 in newer
implementations.

Signed-off-by: Frank Chang 
---
 target/riscv/debug.c | 174 ++-
 target/riscv/debug.h |  18 +
 2 files changed, 188 insertions(+), 4 deletions(-)

diff --git a/target/riscv/debug.c b/target/riscv/debug.c
index 83b72fa1b9..43ee10c1c3 100644
--- a/target/riscv/debug.c
+++ b/target/riscv/debug.c
@@ -39,7 +39,7 @@
  * - tdata3
  * - tinfo
  *
- * The following triggers are implemented:
+ * The following triggers are initialized by default:
  *
  * Index | Type |  tdata mapping | Description
  * --+--++
@@ -102,10 +102,12 @@ static trigger_action_t get_trigger_action(CPURISCVState 
*env,
 case TRIGGER_TYPE_AD_MATCH:
 action = (tdata1 & TYPE2_ACTION) >> 12;
 break;
+case TRIGGER_TYPE_AD_MATCH6:
+action = (tdata1 & TYPE6_ACTION) >> 12;
+break;
 case TRIGGER_TYPE_INST_CNT:
 case TRIGGER_TYPE_INT:
 case TRIGGER_TYPE_EXCP:
-case TRIGGER_TYPE_AD_MATCH6:
 case TRIGGER_TYPE_EXT_SRC:
 qemu_log_mask(LOG_UNIMP, "trigger type: %d is not supported\n",
   trigger_type);
@@ -380,6 +382,123 @@ static void type2_reg_write(CPURISCVState *env, 
target_ulong index,
 return;
 }
 
+/* type 6 trigger */
+
+static inline bool type6_breakpoint_enabled(target_ulong ctrl)
+{
+bool mode = !!(ctrl & (TYPE6_VU | TYPE6_VS | TYPE6_U | TYPE6_S | TYPE6_M));
+bool rwx = !!(ctrl & (TYPE6_LOAD | TYPE6_STORE | TYPE6_EXEC));
+
+return mode && rwx;
+}
+
+static target_ulong type6_mcontrol6_validate(CPURISCVState *env,
+ target_ulong ctrl)
+{
+target_ulong val;
+uint32_t size;
+
+/* validate the generic part first */
+val = tdata1_validate(env, ctrl, TRIGGER_TYPE_AD_MATCH6);
+
+/* validate unimplemented (always zero) bits */
+warn_always_zero_bit(ctrl, TYPE6_MATCH, "match");
+warn_always_zero_bit(ctrl, TYPE6_CHAIN, "chain");
+warn_always_zero_bit(ctrl, TYPE6_ACTION, "action");
+warn_always_zero_bit(ctrl, TYPE6_TIMING, "timing");
+warn_always_zero_bit(ctrl, TYPE6_SELECT, "select");
+warn_always_zero_bit(ctrl, TYPE6_HIT, "hit");
+
+/* validate size encoding */
+size = extract32(ctrl, 16, 4);
+if (access_size[size] == -1) {
+qemu_log_mask(LOG_UNIMP, "access size %d is not supported, using 
SIZE_ANY\n",
+  size);
+} else {
+val |= (ctrl & TYPE6_SIZE);
+}
+
+/* keep the mode and attribute bits */
+val |= (ctrl & (TYPE6_VU | TYPE6_VS | TYPE6_U | TYPE6_S | TYPE6_M |
+TYPE6_LOAD | TYPE6_STORE | TYPE6_EXEC));
+
+return val;
+}
+
+static void type6_breakpoint_insert(CPURISCVState *env, target_ulong index)
+{
+target_ulong ctrl = env->tdata1[index];
+target_ulong addr = env->tdata2[index];
+bool enabled = type6_breakpoint_enabled(ctrl);
+CPUState *cs = env_cpu(env);
+int flags = BP_CPU | BP_STOP_BEFORE_ACCESS;
+uint32_t size;
+
+if (!enabled) {
+return;
+}
+
+if (ctrl & TYPE6_EXEC) {
+cpu_breakpoint_insert(cs, addr, flags, >cpu_breakpoint[index]);
+}
+
+if (ctrl & TYPE6_LOAD) {
+flags |= BP_MEM_READ;
+}
+
+if (ctrl & TYPE6_STORE) {
+flags |= BP_MEM_WRITE;
+}
+
+if (flags & BP_MEM_ACCESS) {
+size = extract32(ctrl, 16, 4);
+if (size != 0) {
+cpu_watchpoint_insert(cs, addr, size, flags,
+  >cpu_watchpoint[index]);
+} else {
+cpu_watchpoint_insert(cs, addr, 8, flags,
+  >cpu_watchpoint[index]);
+}
+}
+}
+
+static void type6_breakpoint_remove(CPURISCVState *env, target_ulong index)
+{
+type2_breakpoint_remove(env, index);
+}
+
+static void type6_reg_write(CPURISCVState *env, target_ulong index,
+int tdata_index, target_ulong val)
+{
+target_ulong new_val;
+
+switch (tdata_index) {
+case TDATA1:
+new_val = type6_mcontrol6_validate(env, val);
+if (new_val != env->tdata1[index]) {
+env->tdata1[index] = new_val;
+type6_breakpoint_remove(env, index);
+type6_breakpoint_insert(env, index);
+}
+break;
+case TDATA2:
+if (val != env->tdata2[index]) {
+env->tdata2[index] = val;
+type6_breakpoint_remove(env, index);
+type6_breakpoint_insert(env, index);
+}
+break;
+case TDATA3:
+qemu_log_mask(LOG_UNIMP,
+  "tdata3 is not supported for type 6 trigger\n&q

[PATCH 7/9] target/riscv: debug: Check VU/VS modes for type 2 trigger

2022-06-09 Thread frank . chang
From: Frank Chang 

Type 2 trigger cannot be fired in VU/VS modes.

Signed-off-by: Frank Chang 
---
 target/riscv/debug.c | 10 ++
 1 file changed, 10 insertions(+)

diff --git a/target/riscv/debug.c b/target/riscv/debug.c
index ab23566113..ce9ff15d75 100644
--- a/target/riscv/debug.c
+++ b/target/riscv/debug.c
@@ -457,6 +457,11 @@ bool riscv_cpu_debug_check_breakpoint(CPUState *cs)
 
 switch (trigger_type) {
 case TRIGGER_TYPE_AD_MATCH:
+/* type 2 trigger cannot be fired in VU/VS mode */
+if (riscv_cpu_virt_enabled(env)) {
+return false;
+}
+
 ctrl = env->tdata1[i];
 pc = env->tdata2[i];
 
@@ -492,6 +497,11 @@ bool riscv_cpu_debug_check_watchpoint(CPUState *cs, 
CPUWatchpoint *wp)
 
 switch (trigger_type) {
 case TRIGGER_TYPE_AD_MATCH:
+/* type 2 trigger cannot be fired in VU/VS mode */
+if (riscv_cpu_virt_enabled(env)) {
+return false;
+}
+
 ctrl = env->tdata1[i];
 addr = env->tdata2[i];
 flags = 0;
-- 
2.36.1




[PATCH 6/9] target/riscv: debug: Create common trigger actions function

2022-06-09 Thread frank . chang
From: Frank Chang 

Trigger actions are shared among all triggers. Extract to a common
function.

Signed-off-by: Frank Chang 
---
 target/riscv/debug.c | 55 ++--
 target/riscv/debug.h | 13 +++
 2 files changed, 66 insertions(+), 2 deletions(-)

diff --git a/target/riscv/debug.c b/target/riscv/debug.c
index 1668b8abda..ab23566113 100644
--- a/target/riscv/debug.c
+++ b/target/riscv/debug.c
@@ -91,6 +91,35 @@ static inline target_ulong get_trigger_type(CPURISCVState 
*env,
 return extract_trigger_type(env, env->tdata1[trigger_index]);
 }
 
+static trigger_action_t get_trigger_action(CPURISCVState *env,
+   target_ulong trigger_index)
+{
+target_ulong tdata1 = env->tdata1[trigger_index];
+int trigger_type = get_trigger_type(env, trigger_index);
+trigger_action_t action = DBG_ACTION_NONE;
+
+switch (trigger_type) {
+case TRIGGER_TYPE_AD_MATCH:
+action = (tdata1 & TYPE2_ACTION) >> 12;
+break;
+case TRIGGER_TYPE_INST_CNT:
+case TRIGGER_TYPE_INT:
+case TRIGGER_TYPE_EXCP:
+case TRIGGER_TYPE_AD_MATCH6:
+case TRIGGER_TYPE_EXT_SRC:
+qemu_log_mask(LOG_UNIMP, "trigger type: %d is not supported\n",
+  trigger_type);
+break;
+case TRIGGER_TYPE_NO_EXIST:
+case TRIGGER_TYPE_UNAVAIL:
+break;
+default:
+g_assert_not_reached();
+}
+
+return action;
+}
+
 static inline target_ulong build_tdata1(CPURISCVState *env,
 trigger_type_t type,
 bool dmode, target_ulong data)
@@ -181,6 +210,28 @@ static inline void warn_always_zero_bit(target_ulong val, 
target_ulong mask,
 }
 }
 
+static void do_trigger_action(CPURISCVState *env, target_ulong trigger_index)
+{
+trigger_action_t action = get_trigger_action(env, trigger_index);
+
+switch (action) {
+case DBG_ACTION_BP:
+riscv_raise_exception(env, RISCV_EXCP_BREAKPOINT, 0);
+break;
+case DBG_ACTION_DBG_MODE:
+case DBG_ACTION_TRACE0:
+case DBG_ACTION_TRACE1:
+case DBG_ACTION_TRACE2:
+case DBG_ACTION_TRACE3:
+case DBG_ACTION_EXT_DBG0:
+case DBG_ACTION_EXT_DBG1:
+qemu_log_mask(LOG_UNIMP, "action: %d is not supported\n", action);
+break;
+default:
+g_assert_not_reached();
+}
+}
+
 /* type 2 trigger */
 
 static uint32_t type2_breakpoint_size(CPURISCVState *env, target_ulong ctrl)
@@ -381,11 +432,11 @@ void riscv_cpu_debug_excp_handler(CPUState *cs)
 if (cs->watchpoint_hit) {
 if (cs->watchpoint_hit->flags & BP_CPU) {
 cs->watchpoint_hit = NULL;
-riscv_raise_exception(env, RISCV_EXCP_BREAKPOINT, 0);
+do_trigger_action(env, DBG_ACTION_BP);
 }
 } else {
 if (cpu_breakpoint_test(cs, env->pc, BP_CPU)) {
-riscv_raise_exception(env, RISCV_EXCP_BREAKPOINT, 0);
+do_trigger_action(env, DBG_ACTION_BP);
 }
 }
 }
diff --git a/target/riscv/debug.h b/target/riscv/debug.h
index 9f69c64591..0e4859cf74 100644
--- a/target/riscv/debug.h
+++ b/target/riscv/debug.h
@@ -44,6 +44,19 @@ typedef enum {
 TRIGGER_TYPE_NUM
 } trigger_type_t;
 
+/* actions */
+typedef enum {
+DBG_ACTION_NONE = -1,   /* sentinel value */
+DBG_ACTION_BP = 0,
+DBG_ACTION_DBG_MODE,
+DBG_ACTION_TRACE0,
+DBG_ACTION_TRACE1,
+DBG_ACTION_TRACE2,
+DBG_ACTION_TRACE3,
+DBG_ACTION_EXT_DBG0 = 8,
+DBG_ACTION_EXT_DBG1
+} trigger_action_t;
+
 /* tdata1 field masks */
 
 #define RV32_TYPE(t)((uint32_t)(t) << 28)
-- 
2.36.1




[PATCH 1/9] target/riscv: debug: Determine the trigger type from tdata1.type

2022-06-09 Thread frank . chang
From: Frank Chang 

Current RISC-V debug assumes that only type 2 trigger is supported.
To allow more types of triggers to be supported in the future
(e.g. type 6 trigger, which is similar to type 2 trigger with additional
 functionality), we should determine the trigger type from tdata1.type.

RV_MAX_TRIGGERS is also introduced in replacement of TRIGGER_TYPE2_NUM.

Signed-off-by: Frank Chang 
---
 target/riscv/cpu.h |   2 +-
 target/riscv/csr.c |   2 +-
 target/riscv/debug.c   | 183 -
 target/riscv/debug.h   |  15 ++--
 target/riscv/machine.c |   2 +-
 5 files changed, 137 insertions(+), 67 deletions(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 7d6397acdf..535123a989 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -289,7 +289,7 @@ struct CPUArchState {
 
 /* trigger module */
 target_ulong trigger_cur;
-type2_trigger_t type2_trig[TRIGGER_TYPE2_NUM];
+type2_trigger_t type2_trig[RV_MAX_TRIGGERS];
 
 /* machine specific rdtime callback */
 uint64_t (*rdtime_fn)(void *);
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 6dbe9b541f..005ae31a01 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -2776,7 +2776,7 @@ static RISCVException read_tdata(CPURISCVState *env, int 
csrno,
  target_ulong *val)
 {
 /* return 0 in tdata1 to end the trigger enumeration */
-if (env->trigger_cur >= TRIGGER_NUM && csrno == CSR_TDATA1) {
+if (env->trigger_cur >= RV_MAX_TRIGGERS && csrno == CSR_TDATA1) {
 *val = 0;
 return RISCV_EXCP_NONE;
 }
diff --git a/target/riscv/debug.c b/target/riscv/debug.c
index fc6e13222f..abbcd38a17 100644
--- a/target/riscv/debug.c
+++ b/target/riscv/debug.c
@@ -52,8 +52,15 @@
 /* tdata availability of a trigger */
 typedef bool tdata_avail[TDATA_NUM];
 
-static tdata_avail tdata_mapping[TRIGGER_NUM] = {
-[TRIGGER_TYPE2_IDX_0 ... TRIGGER_TYPE2_IDX_1] = { true, true, false },
+static tdata_avail tdata_mapping[TRIGGER_TYPE_NUM] = {
+[TRIGGER_TYPE_NO_EXIST] = { false, false, false },
+[TRIGGER_TYPE_AD_MATCH] = { true, true, true },
+[TRIGGER_TYPE_INST_CNT] = { true, false, true },
+[TRIGGER_TYPE_INT] = { true, true, true },
+[TRIGGER_TYPE_EXCP] = { true, true, true },
+[TRIGGER_TYPE_AD_MATCH6] = { true, true, true },
+[TRIGGER_TYPE_EXT_SRC] = { true, false, false },
+[TRIGGER_TYPE_UNAVAIL] = { true, true, true }
 };
 
 /* only breakpoint size 1/2/4/8 supported */
@@ -67,6 +74,26 @@ static int access_size[SIZE_NUM] = {
 [6 ... 15] = -1,
 };
 
+static inline target_ulong extract_trigger_type(CPURISCVState *env,
+target_ulong tdata1)
+{
+switch (riscv_cpu_mxl(env)) {
+case MXL_RV32:
+return extract32(tdata1, 28, 4);
+case MXL_RV64:
+return extract64(tdata1, 60, 4);
+default:
+g_assert_not_reached();
+}
+}
+
+static inline target_ulong get_trigger_type(CPURISCVState *env,
+target_ulong trigger_index)
+{
+target_ulong tdata1 = env->type2_trig[trigger_index].mcontrol;
+return extract_trigger_type(env, tdata1);
+}
+
 static inline target_ulong trigger_type(CPURISCVState *env,
 trigger_type_t type)
 {
@@ -89,15 +116,17 @@ static inline target_ulong trigger_type(CPURISCVState *env,
 
 bool tdata_available(CPURISCVState *env, int tdata_index)
 {
+int trigger_type = get_trigger_type(env, env->trigger_cur);
+
 if (unlikely(tdata_index >= TDATA_NUM)) {
 return false;
 }
 
-if (unlikely(env->trigger_cur >= TRIGGER_NUM)) {
+if (unlikely(env->trigger_cur >= RV_MAX_TRIGGERS)) {
 return false;
 }
 
-return tdata_mapping[env->trigger_cur][tdata_index];
+return tdata_mapping[trigger_type][tdata_index];
 }
 
 target_ulong tselect_csr_read(CPURISCVState *env)
@@ -137,6 +166,7 @@ static target_ulong tdata1_validate(CPURISCVState *env, 
target_ulong val,
 qemu_log_mask(LOG_GUEST_ERROR,
   "ignoring type write to tdata1 register\n");
 }
+
 if (dmode != 0) {
 qemu_log_mask(LOG_UNIMP, "debug mode is not supported\n");
 }
@@ -261,9 +291,8 @@ static void type2_breakpoint_remove(CPURISCVState *env, 
target_ulong index)
 }
 
 static target_ulong type2_reg_read(CPURISCVState *env,
-   target_ulong trigger_index, int tdata_index)
+   target_ulong index, int tdata_index)
 {
-uint32_t index = trigger_index - TRIGGER_TYPE2_IDX_0;
 target_ulong tdata;
 
 switch (tdata_index) {
@@ -280,10 +309,9 @@ static target_ulong type2_reg_read(CPURISCVState *env,
 return tdata;
 }
 
-static void type2_reg_write(CPURISCVState *env, target_ulong trigger_index,
+static void type2_reg_write(CPURISCVStat

[PATCH 5/9] target/riscv: debug: Introduce tinfo CSR

2022-06-09 Thread frank . chang
From: Frank Chang 

tinfo.info:
  One bit for each possible type enumerated in tdata1.
  If the bit is set, then that type is supported by the currently
  selected trigger.

Signed-off-by: Frank Chang 
---
 target/riscv/cpu_bits.h |  1 +
 target/riscv/csr.c  |  8 
 target/riscv/debug.c| 10 +++---
 target/riscv/debug.h|  2 ++
 4 files changed, 18 insertions(+), 3 deletions(-)

diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index 4d04b20d06..666b4d69ca 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -331,6 +331,7 @@
 #define CSR_TDATA1  0x7a1
 #define CSR_TDATA2  0x7a2
 #define CSR_TDATA3  0x7a3
+#define CSR_TINFO   0x7a4
 
 /* Debug Mode Registers */
 #define CSR_DCSR0x7b0
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 005ae31a01..823b6bd520 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -2800,6 +2800,13 @@ static RISCVException write_tdata(CPURISCVState *env, 
int csrno,
 return RISCV_EXCP_NONE;
 }
 
+static RISCVException read_tinfo(CPURISCVState *env, int csrno,
+ target_ulong *val)
+{
+*val = tinfo_csr_read(env);
+return RISCV_EXCP_NONE;
+}
+
 /*
  * Functions to access Pointer Masking feature registers
  * We have to check if current priv lvl could modify
@@ -3588,6 +3595,7 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
 [CSR_TDATA1]=  { "tdata1",  debug, read_tdata,   write_tdata   },
 [CSR_TDATA2]=  { "tdata2",  debug, read_tdata,   write_tdata   },
 [CSR_TDATA3]=  { "tdata3",  debug, read_tdata,   write_tdata   },
+[CSR_TINFO] =  { "tinfo",   debug, read_tinfo,   write_ignore  },
 
 /* User Pointer Masking */
 [CSR_UMTE]={ "umte",pointer_masking, read_umte,write_umte  
  },
diff --git a/target/riscv/debug.c b/target/riscv/debug.c
index 296192ffc4..1668b8abda 100644
--- a/target/riscv/debug.c
+++ b/target/riscv/debug.c
@@ -37,9 +37,7 @@
  * - tdata1
  * - tdata2
  * - tdata3
- *
- * We don't support writable 'type' field in the tdata1 register, so there is
- * no need to implement the "tinfo" CSR.
+ * - tinfo
  *
  * The following triggers are implemented:
  *
@@ -369,6 +367,12 @@ void tdata_csr_write(CPURISCVState *env, int tdata_index, 
target_ulong val)
 }
 }
 
+target_ulong tinfo_csr_read(CPURISCVState *env)
+{
+/* assume all triggers support the same types of triggers */
+return BIT(TRIGGER_TYPE_AD_MATCH);
+}
+
 void riscv_cpu_debug_excp_handler(CPUState *cs)
 {
 RISCVCPU *cpu = RISCV_CPU(cs);
diff --git a/target/riscv/debug.h b/target/riscv/debug.h
index 76146f373a..9f69c64591 100644
--- a/target/riscv/debug.h
+++ b/target/riscv/debug.h
@@ -95,6 +95,8 @@ void tselect_csr_write(CPURISCVState *env, target_ulong val);
 target_ulong tdata_csr_read(CPURISCVState *env, int tdata_index);
 void tdata_csr_write(CPURISCVState *env, int tdata_index, target_ulong val);
 
+target_ulong tinfo_csr_read(CPURISCVState *env);
+
 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);
-- 
2.36.1




[PATCH 2/9] target/riscv: debug: Introduce build_tdata1() to build tdata1 register content

2022-06-09 Thread frank . chang
From: Frank Chang 

Introduce build_tdata1() to build tdata1 register content, which can be
shared among all types of triggers.

Signed-off-by: Frank Chang 
---
 target/riscv/debug.c | 15 ++-
 1 file changed, 10 insertions(+), 5 deletions(-)

diff --git a/target/riscv/debug.c b/target/riscv/debug.c
index abbcd38a17..089aae0696 100644
--- a/target/riscv/debug.c
+++ b/target/riscv/debug.c
@@ -94,18 +94,23 @@ static inline target_ulong get_trigger_type(CPURISCVState 
*env,
 return extract_trigger_type(env, tdata1);
 }
 
-static inline target_ulong trigger_type(CPURISCVState *env,
-trigger_type_t type)
+static inline target_ulong build_tdata1(CPURISCVState *env,
+trigger_type_t type,
+bool dmode, target_ulong data)
 {
 target_ulong tdata1;
 
 switch (riscv_cpu_mxl(env)) {
 case MXL_RV32:
-tdata1 = RV32_TYPE(type);
+tdata1 = RV32_TYPE(type) |
+ (dmode ? RV32_DMODE : 0) |
+ (data & RV32_DATA_MASK);
 break;
 case MXL_RV64:
 case MXL_RV128:
-tdata1 = RV64_TYPE(type);
+tdata1 = RV64_TYPE(type) |
+ (dmode ? RV64_DMODE : 0) |
+ (data & RV64_DATA_MASK);
 break;
 default:
 g_assert_not_reached();
@@ -490,7 +495,7 @@ bool riscv_cpu_debug_check_watchpoint(CPUState *cs, 
CPUWatchpoint *wp)
 
 void riscv_trigger_init(CPURISCVState *env)
 {
-target_ulong tdata1 = trigger_type(env, TRIGGER_TYPE_AD_MATCH);
+target_ulong tdata1 = build_tdata1(env, TRIGGER_TYPE_AD_MATCH, 0, 0);
 int i;
 
 /* init to type 2 triggers */
-- 
2.36.1




[PATCH 4/9] target/riscv: debug: Restrict the range of tselect value can be written

2022-06-09 Thread frank . chang
From: Frank Chang 

The value of tselect CSR can be written should be limited within the
range of supported triggers number.

Signed-off-by: Frank Chang 
---
 target/riscv/debug.c | 9 +++--
 1 file changed, 3 insertions(+), 6 deletions(-)

diff --git a/target/riscv/debug.c b/target/riscv/debug.c
index 6913682f75..296192ffc4 100644
--- a/target/riscv/debug.c
+++ b/target/riscv/debug.c
@@ -126,10 +126,6 @@ bool tdata_available(CPURISCVState *env, int tdata_index)
 return false;
 }
 
-if (unlikely(env->trigger_cur >= RV_MAX_TRIGGERS)) {
-return false;
-}
-
 return tdata_mapping[trigger_type][tdata_index];
 }
 
@@ -140,8 +136,9 @@ target_ulong tselect_csr_read(CPURISCVState *env)
 
 void tselect_csr_write(CPURISCVState *env, target_ulong val)
 {
-/* all target_ulong bits of tselect are implemented */
-env->trigger_cur = val;
+if (val < RV_MAX_TRIGGERS) {
+env->trigger_cur = val;
+}
 }
 
 static target_ulong tdata1_validate(CPURISCVState *env, target_ulong val,
-- 
2.36.1




[PATCH 0/9] Improve RISC-V Debug support

2022-06-09 Thread frank . chang
From: Frank Chang 

This patchset refactors RISC-V Debug support to allow more types of
triggers to be extended.

The initial support of type 6 trigger, which is similar to type 2
trigger with additional functionality, is also introduced in this
patchset.

Frank Chang (9):
  target/riscv: debug: Determine the trigger type from tdata1.type
  target/riscv: debug: Introduce build_tdata1() to build tdata1 register
content
  target/riscv: debug: Introduce tdata1, tdata2, and tdata3 CSRs
  target/riscv: debug: Restrict the range of tselect value can be
written
  target/riscv: debug: Introduce tinfo CSR
  target/riscv: debug: Create common trigger actions function
  target/riscv: debug: Check VU/VS modes for type 2 trigger
  target/riscv: debug: Return 0 if previous value written to tselect >=
number of triggers
  target/riscv: debug: Add initial support of type 6 trigger

 target/riscv/cpu.h  |   7 +-
 target/riscv/cpu_bits.h |   1 +
 target/riscv/csr.c  |  10 +-
 target/riscv/debug.c| 483 
 target/riscv/debug.h|  55 +++--
 target/riscv/machine.c  |  20 +-
 6 files changed, 445 insertions(+), 131 deletions(-)

--
2.36.1




[PATCH 3/9] target/riscv: debug: Introduce tdata1, tdata2, and tdata3 CSRs

2022-06-09 Thread frank . chang
From: Frank Chang 

Replace type2_trigger_t with the real tdata1, tdata2, and tdata3 CSRs,
which allows us to support more types of triggers in the future.

Signed-off-by: Frank Chang 
---
 target/riscv/cpu.h |   6 ++-
 target/riscv/debug.c   | 101 -
 target/riscv/debug.h   |   7 ---
 target/riscv/machine.c |  20 ++--
 4 files changed, 48 insertions(+), 86 deletions(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 535123a989..bac5f00722 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -289,7 +289,11 @@ struct CPUArchState {
 
 /* trigger module */
 target_ulong trigger_cur;
-type2_trigger_t type2_trig[RV_MAX_TRIGGERS];
+target_ulong tdata1[RV_MAX_TRIGGERS];
+target_ulong tdata2[RV_MAX_TRIGGERS];
+target_ulong tdata3[RV_MAX_TRIGGERS];
+struct CPUBreakpoint *cpu_breakpoint[RV_MAX_TRIGGERS];
+struct CPUWatchpoint *cpu_watchpoint[RV_MAX_TRIGGERS];
 
 /* machine specific rdtime callback */
 uint64_t (*rdtime_fn)(void *);
diff --git a/target/riscv/debug.c b/target/riscv/debug.c
index 089aae0696..6913682f75 100644
--- a/target/riscv/debug.c
+++ b/target/riscv/debug.c
@@ -90,8 +90,7 @@ static inline target_ulong extract_trigger_type(CPURISCVState 
*env,
 static inline target_ulong get_trigger_type(CPURISCVState *env,
 target_ulong trigger_index)
 {
-target_ulong tdata1 = env->type2_trig[trigger_index].mcontrol;
-return extract_trigger_type(env, tdata1);
+return extract_trigger_type(env, env->tdata1[trigger_index]);
 }
 
 static inline target_ulong build_tdata1(CPURISCVState *env,
@@ -187,6 +186,8 @@ static inline void warn_always_zero_bit(target_ulong val, 
target_ulong mask,
 }
 }
 
+/* type 2 trigger */
+
 static uint32_t type2_breakpoint_size(CPURISCVState *env, target_ulong ctrl)
 {
 uint32_t size, sizelo, sizehi = 0;
@@ -246,8 +247,8 @@ static target_ulong type2_mcontrol_validate(CPURISCVState 
*env,
 
 static void type2_breakpoint_insert(CPURISCVState *env, target_ulong index)
 {
-target_ulong ctrl = env->type2_trig[index].mcontrol;
-target_ulong addr = env->type2_trig[index].maddress;
+target_ulong ctrl = env->tdata1[index];
+target_ulong addr = env->tdata2[index];
 bool enabled = type2_breakpoint_enabled(ctrl);
 CPUState *cs = env_cpu(env);
 int flags = BP_CPU | BP_STOP_BEFORE_ACCESS;
@@ -258,7 +259,7 @@ static void type2_breakpoint_insert(CPURISCVState *env, 
target_ulong index)
 }
 
 if (ctrl & TYPE2_EXEC) {
-cpu_breakpoint_insert(cs, addr, flags, >type2_trig[index].bp);
+cpu_breakpoint_insert(cs, addr, flags, >cpu_breakpoint[index]);
 }
 
 if (ctrl & TYPE2_LOAD) {
@@ -272,10 +273,10 @@ static void type2_breakpoint_insert(CPURISCVState *env, 
target_ulong index)
 size = type2_breakpoint_size(env, ctrl);
 if (size != 0) {
 cpu_watchpoint_insert(cs, addr, size, flags,
-  >type2_trig[index].wp);
+  >cpu_watchpoint[index]);
 } else {
 cpu_watchpoint_insert(cs, addr, 8, flags,
-  >type2_trig[index].wp);
+  >cpu_watchpoint[index]);
 }
 }
 }
@@ -284,34 +285,15 @@ static void type2_breakpoint_remove(CPURISCVState *env, 
target_ulong index)
 {
 CPUState *cs = env_cpu(env);
 
-if (env->type2_trig[index].bp) {
-cpu_breakpoint_remove_by_ref(cs, env->type2_trig[index].bp);
-env->type2_trig[index].bp = NULL;
+if (env->cpu_breakpoint[index]) {
+cpu_breakpoint_remove_by_ref(cs, env->cpu_breakpoint[index]);
+env->cpu_breakpoint[index] = NULL;
 }
 
-if (env->type2_trig[index].wp) {
-cpu_watchpoint_remove_by_ref(cs, env->type2_trig[index].wp);
-env->type2_trig[index].wp = NULL;
-}
-}
-
-static target_ulong type2_reg_read(CPURISCVState *env,
-   target_ulong index, int tdata_index)
-{
-target_ulong tdata;
-
-switch (tdata_index) {
-case TDATA1:
-tdata = env->type2_trig[index].mcontrol;
-break;
-case TDATA2:
-tdata = env->type2_trig[index].maddress;
-break;
-default:
-g_assert_not_reached();
+if (env->cpu_watchpoint[index]) {
+cpu_watchpoint_remove_by_ref(cs, env->cpu_watchpoint[index]);
+env->cpu_watchpoint[index] = NULL;
 }
-
-return tdata;
 }
 
 static void type2_reg_write(CPURISCVState *env, target_ulong index,
@@ -322,19 +304,23 @@ static void type2_reg_write(CPURISCVState *env, 
target_ulong index,
 switch (tdata_index) {
 case TDATA1:
 new_val = type2_mcontrol_validate(env, val);
-if (new_val != env->type2_trig[index].mcontrol) {
-env->type2_trig[index].mcontrol = new_

Re: [PATCH v9 09/12] target/riscv: Simplify counter predicate function

2022-05-25 Thread Frank Chang
On Tue, May 24, 2022 at 8:02 AM Atish Patra  wrote:

> All the hpmcounters and the fixed counters (CY, IR, TM) can be represented
> as a unified counter. Thus, the predicate function doesn't need handle each
> case separately.
>
> Simplify the predicate function so that we just handle things differently
> between RV32/RV64 and S/HS mode.
>
> Reviewed-by: Bin Meng 
> Acked-by: Alistair Francis 
> Signed-off-by: Atish Patra 
> ---
>  target/riscv/csr.c | 111 -
>  1 file changed, 10 insertions(+), 101 deletions(-)
>
> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> index 723b52d836d3..e229f53c674d 100644
> --- a/target/riscv/csr.c
> +++ b/target/riscv/csr.c
> @@ -74,6 +74,7 @@ static RISCVException ctr(CPURISCVState *env, int csrno)
>  CPUState *cs = env_cpu(env);
>  RISCVCPU *cpu = RISCV_CPU(cs);
>  int ctr_index;
> +target_ulong ctr_mask;
>  int base_csrno = CSR_CYCLE;
>  bool rv32 = riscv_cpu_mxl(env) == MXL_RV32 ? true : false;
>
> @@ -82,122 +83,30 @@ static RISCVException ctr(CPURISCVState *env, int
> csrno)
>  base_csrno += 0x80;
>  }
>  ctr_index = csrno - base_csrno;
> +ctr_mask = BIT(ctr_index);
>
>  if ((csrno >= CSR_CYCLE && csrno <= CSR_INSTRET) ||
>  (csrno >= CSR_CYCLEH && csrno <= CSR_INSTRETH)) {
>  goto skip_ext_pmu_check;
>  }
>
> -if ((!cpu->cfg.pmu_num || !(cpu->pmu_avail_ctrs & BIT(ctr_index {
> +if ((!cpu->cfg.pmu_num || !(cpu->pmu_avail_ctrs & ctr_mask))) {
>  /* No counter is enabled in PMU or the counter is out of range */
>  return RISCV_EXCP_ILLEGAL_INST;
>  }
>
>  skip_ext_pmu_check:
>
> -if (env->priv == PRV_S) {
> -switch (csrno) {
> -case CSR_CYCLE:
> -if (!get_field(env->mcounteren, COUNTEREN_CY)) {
> -return RISCV_EXCP_ILLEGAL_INST;
> -}
> -break;
> -case CSR_TIME:
> -if (!get_field(env->mcounteren, COUNTEREN_TM)) {
> -return RISCV_EXCP_ILLEGAL_INST;
> -}
> -break;
> -case CSR_INSTRET:
> -if (!get_field(env->mcounteren, COUNTEREN_IR)) {
> -return RISCV_EXCP_ILLEGAL_INST;
> -}
> -break;
> -case CSR_HPMCOUNTER3...CSR_HPMCOUNTER31:
> -if (!get_field(env->mcounteren, 1 << ctr_index)) {
> -return RISCV_EXCP_ILLEGAL_INST;
> -}
> -break;
> -}
> -if (rv32) {
> -switch (csrno) {
> -case CSR_CYCLEH:
> -if (!get_field(env->mcounteren, COUNTEREN_CY)) {
> -return RISCV_EXCP_ILLEGAL_INST;
> -}
> -break;
> -case CSR_TIMEH:
> -if (!get_field(env->mcounteren, COUNTEREN_TM)) {
> -return RISCV_EXCP_ILLEGAL_INST;
> -}
> -break;
> -case CSR_INSTRETH:
> -if (!get_field(env->mcounteren, COUNTEREN_IR)) {
> -return RISCV_EXCP_ILLEGAL_INST;
> -}
> -break;
> -case CSR_HPMCOUNTER3H...CSR_HPMCOUNTER31H:
> -    if (!get_field(env->mcounteren, 1 << ctr_index)) {
> -return RISCV_EXCP_ILLEGAL_INST;
> -}
> -break;
> -}
> -}
> +if ((env->priv == PRV_S) && (!get_field(env->mcounteren, ctr_mask))) {
>

Should we also check PRV_U against env->scounteren here?

Regards,
Frank Chang


> +return RISCV_EXCP_ILLEGAL_INST;
>  }
>
>  if (riscv_cpu_virt_enabled(env)) {
> -switch (csrno) {
> -case CSR_CYCLE:
> -if (!get_field(env->hcounteren, COUNTEREN_CY) &&
> -get_field(env->mcounteren, COUNTEREN_CY)) {
> -return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
> -}
> -break;
> -case CSR_TIME:
> -if (!get_field(env->hcounteren, COUNTEREN_TM) &&
> -get_field(env->mcounteren, COUNTEREN_TM)) {
> -return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
> -}
> -break;
> -case CSR_INSTRET:
> -if (!get_field(env->hcounteren, COUNTEREN_IR) &&
> -get_field(env->mcounteren, COUNTEREN_IR)) {
> -return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
> -}
> -break;

Re: [PATCH v9 08/12] target/riscv: Add sscofpmf extension support

2022-05-25 Thread Frank Chang
  write_mhpmeventh},
> +[CSR_MHPMEVENT31H]   = { "mhpmevent31h",sscofpmf,
> read_mhpmeventh,
> +   write_mhpmeventh},
> +
>  [CSR_HPMCOUNTER3H]   = { "hpmcounter3h",   ctr32,  read_hpmcounterh },
>  [CSR_HPMCOUNTER4H]   = { "hpmcounter4h",   ctr32,  read_hpmcounterh },
>  [CSR_HPMCOUNTER5H]   = { "hpmcounter5h",   ctr32,  read_hpmcounterh },
> @@ -4089,5 +4249,7 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
> write_mhpmcounterh
> },
>  [CSR_MHPMCOUNTER31H] = { "mhpmcounter31h", mctr32,  read_hpmcounterh,
> write_mhpmcounterh
> },
> +[CSR_SCOUNTOVF]  = { "scountovf", sscofpmf,  read_scountovf },
> +
>  #endif /* !CONFIG_USER_ONLY */
>  };
> diff --git a/target/riscv/machine.c b/target/riscv/machine.c
> index dc182ca81119..000565745cef 100644
> --- a/target/riscv/machine.c
> +++ b/target/riscv/machine.c
> @@ -300,6 +300,7 @@ static const VMStateDescription vmstate_pmu_ctr_state
> = {
>  VMSTATE_UINTTL(mhpmcounterh_val, PMUCTRState),
>  VMSTATE_UINTTL(mhpmcounter_prev, PMUCTRState),
>  VMSTATE_UINTTL(mhpmcounterh_prev, PMUCTRState),
> +VMSTATE_UINT8(write_done, PMUCTRState),
>  VMSTATE_BOOL(started, PMUCTRState),
>  VMSTATE_END_OF_LIST()
>  }
> @@ -355,6 +356,9 @@ const VMStateDescription vmstate_riscv_cpu = {
>  VMSTATE_STRUCT_ARRAY(env.pmu_ctrs, RISCVCPU, RV_MAX_MHPMCOUNTERS,
> 0,
>   vmstate_pmu_ctr_state, PMUCTRState),
>  VMSTATE_UINTTL_ARRAY(env.mhpmevent_val, RISCVCPU,
> RV_MAX_MHPMEVENTS),
> +VMSTATE_UINT8_ARRAY(env.mhpmevent_write_done, RISCVCPU,
> +RV_MAX_MHPMEVENTS),
> +VMSTATE_UINTTL_ARRAY(env.mhpmeventh_val, RISCVCPU,
> RV_MAX_MHPMEVENTS),
>  VMSTATE_UINTTL(env.sscratch, RISCVCPU),
>  VMSTATE_UINTTL(env.mscratch, RISCVCPU),
>  VMSTATE_UINT64(env.mfromhost, RISCVCPU),
> diff --git a/target/riscv/pmu.c b/target/riscv/pmu.c
> index 000fe8da45ef..7bb85d8d6ad7 100644
> --- a/target/riscv/pmu.c
> +++ b/target/riscv/pmu.c
> @@ -19,14 +19,357 @@
>  #include "qemu/osdep.h"
>  #include "cpu.h"
>  #include "pmu.h"
> +#include "sysemu/cpu-timers.h"
> +
> +#define RISCV_TIMEBASE_FREQ 10 /* 1Ghz */
> +#define MAKE_32BIT_MASK(shift, length) \
> +(((uint32_t)(~0UL) >> (32 - (length))) << (shift))
> +
> +static bool riscv_pmu_counter_valid(RISCVCPU *cpu, uint32_t ctr_idx)
> +{
> +if (ctr_idx < 3 || ctr_idx >= RV_MAX_MHPMCOUNTERS ||
> +!(cpu->pmu_avail_ctrs & BIT(ctr_idx))) {
> +return false;
> +} else {
> +return true;
> +}
> +}
> +
> +static bool riscv_pmu_counter_enabled(RISCVCPU *cpu, uint32_t ctr_idx)
> +{
> +CPURISCVState *env = >env;
> +
> +if (!riscv_pmu_counter_valid(cpu, ctr_idx) ||
> +!get_field(env->mcounteren, BIT(ctr_idx))) {
>

Hi Atish,

May I ask why do we need to check mcounteren here?
riscv_pmu_counter_enabled() is called by:
riscv_pmu_incr_ctr() and pmu_timer_trigger_irq().

However, according to RISC-V privilege spec for mcounteren:
"The settings in this register only control accessibility.
The act of reading or writing this register does not affect
the underlying counters, which continue to increment even when not
accessible."

The counter should be able to increase no matter what the value mcounteren
is.

I think only mcountinhibit controls whether the counter can be increased.
"The counter-inhibit register mcountinhibit is a 32-bit WARL register that
controls which of the
hardware performance-monitoring counters increment. The settings in this
register only control
whether the counters increment; their accessibility is not affected by the
setting of this register."

Regards,
Frank Chang


> +return false;
> +} else {
> +return true;
> +}
> +}
> +
> +static int riscv_pmu_incr_ctr_rv32(RISCVCPU *cpu, uint32_t ctr_idx)
> +{
> +CPURISCVState *env = >env;
> +target_ulong max_val = UINT32_MAX;
> +PMUCTRState *counter = >pmu_ctrs[ctr_idx];
> +
> +/* Privilege mode filtering */
> +if ((env->priv == PRV_M &&
> +(env->mhpmeventh_val[ctr_idx] & MHPMEVENTH_BIT_MINH)) ||
> +(env->priv == PRV_S &&
> +(env->mhpmeventh_val[ctr_idx] & MHPMEVENTH_BIT_SINH)) ||
> +(env->priv == PRV_U &&
> +  

[RESEND PATCH v2] target/riscv: Fix typo of mimpid cpu option

2022-05-23 Thread frank . chang
From: Frank Chang 

"mimpid" cpu option was mistyped to "mipid".

Fixes: 9951ba94 ("target/riscv: Support configuarable marchid, mvendorid, mipid 
CSR values")
Signed-off-by: Frank Chang 
Reviewed-by: Alistair Francis 
---
 target/riscv/cpu.c | 4 ++--
 target/riscv/cpu.h | 2 +-
 target/riscv/csr.c | 8 
 3 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 6d01569cad..a1f847176e 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -37,7 +37,7 @@
 #define RISCV_CPU_MARCHID   ((QEMU_VERSION_MAJOR << 16) | \
  (QEMU_VERSION_MINOR << 8)  | \
  (QEMU_VERSION_MICRO))
-#define RISCV_CPU_MIPID RISCV_CPU_MARCHID
+#define RISCV_CPU_MIMPIDRISCV_CPU_MARCHID
 
 static const char riscv_single_letter_exts[] = "IEMAFDQCPVH";
 
@@ -869,7 +869,7 @@ static Property riscv_cpu_properties[] = {
 
 DEFINE_PROP_UINT32("mvendorid", RISCVCPU, cfg.mvendorid, 0),
 DEFINE_PROP_UINT64("marchid", RISCVCPU, cfg.marchid, RISCV_CPU_MARCHID),
-DEFINE_PROP_UINT64("mipid", RISCVCPU, cfg.mipid, RISCV_CPU_MIPID),
+DEFINE_PROP_UINT64("mimpid", RISCVCPU, cfg.mimpid, RISCV_CPU_MIMPID),
 
 DEFINE_PROP_BOOL("svinval", RISCVCPU, cfg.ext_svinval, false),
 DEFINE_PROP_BOOL("svnapot", RISCVCPU, cfg.ext_svnapot, false),
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index f5ff7294c6..44975e3e5a 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -408,7 +408,7 @@ struct RISCVCPUConfig {
 
 uint32_t mvendorid;
 uint64_t marchid;
-uint64_t mipid;
+uint64_t mimpid;
 
 /* Vendor-specific custom extensions */
 bool ext_XVentanaCondOps;
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 4ea7df02c9..0d5bc2f41d 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -674,13 +674,13 @@ static RISCVException read_marchid(CPURISCVState *env, 
int csrno,
 return RISCV_EXCP_NONE;
 }
 
-static RISCVException read_mipid(CPURISCVState *env, int csrno,
- target_ulong *val)
+static RISCVException read_mimpid(CPURISCVState *env, int csrno,
+  target_ulong *val)
 {
 CPUState *cs = env_cpu(env);
 RISCVCPU *cpu = RISCV_CPU(cs);
 
-*val = cpu->cfg.mipid;
+*val = cpu->cfg.mimpid;
 return RISCV_EXCP_NONE;
 }
 
@@ -3372,7 +3372,7 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
 /* Machine Information Registers */
 [CSR_MVENDORID] = { "mvendorid", any,   read_mvendorid },
 [CSR_MARCHID]   = { "marchid",   any,   read_marchid   },
-[CSR_MIMPID]= { "mimpid",any,   read_mipid },
+[CSR_MIMPID]= { "mimpid",any,   read_mimpid},
 [CSR_MHARTID]   = { "mhartid",   any,   read_mhartid   },
 
 [CSR_MCONFIGPTR]  = { "mconfigptr", any,   read_zero,
-- 
2.35.1




[PATCH v2] target/riscv: Fix typo of mimpid cpu option

2022-05-23 Thread frank . chang
From: Frank Chang 

"mimpid" cpu option was mistyped to "mipid".

Fixes: 9951ba94 ("target/riscv: Support configuarable marchid, mvendorid, mipid 
CSR values")
Signed-off-by: Frank Chang 
---
 target/riscv/cpu.c | 4 ++--
 target/riscv/cpu.h | 2 +-
 target/riscv/csr.c | 8 
 3 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 6d01569cad..a1f847176e 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -37,7 +37,7 @@
 #define RISCV_CPU_MARCHID   ((QEMU_VERSION_MAJOR << 16) | \
  (QEMU_VERSION_MINOR << 8)  | \
  (QEMU_VERSION_MICRO))
-#define RISCV_CPU_MIPID RISCV_CPU_MARCHID
+#define RISCV_CPU_MIMPIDRISCV_CPU_MARCHID
 
 static const char riscv_single_letter_exts[] = "IEMAFDQCPVH";
 
@@ -869,7 +869,7 @@ static Property riscv_cpu_properties[] = {
 
 DEFINE_PROP_UINT32("mvendorid", RISCVCPU, cfg.mvendorid, 0),
 DEFINE_PROP_UINT64("marchid", RISCVCPU, cfg.marchid, RISCV_CPU_MARCHID),
-DEFINE_PROP_UINT64("mipid", RISCVCPU, cfg.mipid, RISCV_CPU_MIPID),
+DEFINE_PROP_UINT64("mimpid", RISCVCPU, cfg.mimpid, RISCV_CPU_MIMPID),
 
 DEFINE_PROP_BOOL("svinval", RISCVCPU, cfg.ext_svinval, false),
 DEFINE_PROP_BOOL("svnapot", RISCVCPU, cfg.ext_svnapot, false),
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index f5ff7294c6..44975e3e5a 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -408,7 +408,7 @@ struct RISCVCPUConfig {
 
 uint32_t mvendorid;
 uint64_t marchid;
-uint64_t mipid;
+uint64_t mimpid;
 
 /* Vendor-specific custom extensions */
 bool ext_XVentanaCondOps;
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 4ea7df02c9..0d5bc2f41d 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -674,13 +674,13 @@ static RISCVException read_marchid(CPURISCVState *env, 
int csrno,
 return RISCV_EXCP_NONE;
 }
 
-static RISCVException read_mipid(CPURISCVState *env, int csrno,
- target_ulong *val)
+static RISCVException read_mimpid(CPURISCVState *env, int csrno,
+  target_ulong *val)
 {
 CPUState *cs = env_cpu(env);
 RISCVCPU *cpu = RISCV_CPU(cs);
 
-*val = cpu->cfg.mipid;
+*val = cpu->cfg.mimpid;
 return RISCV_EXCP_NONE;
 }
 
@@ -3372,7 +3372,7 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
 /* Machine Information Registers */
 [CSR_MVENDORID] = { "mvendorid", any,   read_mvendorid },
 [CSR_MARCHID]   = { "marchid",   any,   read_marchid   },
-[CSR_MIMPID]= { "mimpid",any,   read_mipid },
+[CSR_MIMPID]= { "mimpid",any,   read_mimpid},
 [CSR_MHARTID]   = { "mhartid",   any,   read_mhartid   },
 
 [CSR_MCONFIGPTR]  = { "mconfigptr", any,   read_zero,
-- 
2.35.1




[PATCH] target/riscv: Fix typo of mimpid cpu option

2022-05-20 Thread frank . chang
From: Frank Chang 

"mimpid" cpu option was mistyped to "mipid".
Fixes commit: 9951ba94

Signed-off-by: Frank Chang 
---
 target/riscv/cpu.c | 4 ++--
 target/riscv/cpu.h | 2 +-
 target/riscv/csr.c | 8 
 3 files changed, 7 insertions(+), 7 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 6d01569cad..a1f847176e 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -37,7 +37,7 @@
 #define RISCV_CPU_MARCHID   ((QEMU_VERSION_MAJOR << 16) | \
  (QEMU_VERSION_MINOR << 8)  | \
  (QEMU_VERSION_MICRO))
-#define RISCV_CPU_MIPID RISCV_CPU_MARCHID
+#define RISCV_CPU_MIMPIDRISCV_CPU_MARCHID
 
 static const char riscv_single_letter_exts[] = "IEMAFDQCPVH";
 
@@ -869,7 +869,7 @@ static Property riscv_cpu_properties[] = {
 
 DEFINE_PROP_UINT32("mvendorid", RISCVCPU, cfg.mvendorid, 0),
 DEFINE_PROP_UINT64("marchid", RISCVCPU, cfg.marchid, RISCV_CPU_MARCHID),
-DEFINE_PROP_UINT64("mipid", RISCVCPU, cfg.mipid, RISCV_CPU_MIPID),
+DEFINE_PROP_UINT64("mimpid", RISCVCPU, cfg.mimpid, RISCV_CPU_MIMPID),
 
 DEFINE_PROP_BOOL("svinval", RISCVCPU, cfg.ext_svinval, false),
 DEFINE_PROP_BOOL("svnapot", RISCVCPU, cfg.ext_svnapot, false),
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index f5ff7294c6..44975e3e5a 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -408,7 +408,7 @@ struct RISCVCPUConfig {
 
 uint32_t mvendorid;
 uint64_t marchid;
-uint64_t mipid;
+uint64_t mimpid;
 
 /* Vendor-specific custom extensions */
 bool ext_XVentanaCondOps;
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 4ea7df02c9..0d5bc2f41d 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -674,13 +674,13 @@ static RISCVException read_marchid(CPURISCVState *env, 
int csrno,
 return RISCV_EXCP_NONE;
 }
 
-static RISCVException read_mipid(CPURISCVState *env, int csrno,
- target_ulong *val)
+static RISCVException read_mimpid(CPURISCVState *env, int csrno,
+  target_ulong *val)
 {
 CPUState *cs = env_cpu(env);
 RISCVCPU *cpu = RISCV_CPU(cs);
 
-*val = cpu->cfg.mipid;
+*val = cpu->cfg.mimpid;
 return RISCV_EXCP_NONE;
 }
 
@@ -3372,7 +3372,7 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
 /* Machine Information Registers */
 [CSR_MVENDORID] = { "mvendorid", any,   read_mvendorid },
 [CSR_MARCHID]   = { "marchid",   any,   read_marchid   },
-[CSR_MIMPID]= { "mimpid",any,   read_mipid },
+[CSR_MIMPID]= { "mimpid",any,   read_mimpid},
 [CSR_MHARTID]   = { "mhartid",   any,   read_mhartid   },
 
 [CSR_MCONFIGPTR]  = { "mconfigptr", any,   read_zero,
-- 
2.35.1




Re: [PATCH v8 07/12] target/riscv: Support mcycle/minstret write operation

2022-05-14 Thread Frank Chang
On Fri, May 13, 2022 at 11:58 PM Atish Kumar Patra 
wrote:

> On Thu, May 12, 2022 at 11:29 PM Frank Chang 
> wrote:
> >
> > On Thu, May 12, 2022 at 6:01 AM Atish Patra  wrote:
> >>
> >> From: Atish Patra 
> >>
> >> mcycle/minstret are actually WARL registers and can be written with any
> >> given value. With SBI PMU extension, it will be used to store a initial
> >> value provided from supervisor OS. The Qemu also need prohibit the
> counter
> >> increment if mcountinhibit is set.
> >>
> >> Support mcycle/minstret through generic counter infrastructure.
> >>
> >> Reviewed-by: Alistair Francis 
> >> Signed-off-by: Atish Patra 
> >> Signed-off-by: Atish Patra 
> >> ---
> >>  target/riscv/cpu.h   |  23 --
> >>  target/riscv/csr.c   | 157 ---
> >>  target/riscv/machine.c   |  25 ++-
> >>  target/riscv/meson.build |   3 +-
> >>  target/riscv/pmu.c   |  32 
> >>  target/riscv/pmu.h   |  28 +++
> >>  6 files changed, 214 insertions(+), 54 deletions(-)
> >>  create mode 100644 target/riscv/pmu.c
> >>  create mode 100644 target/riscv/pmu.h
> >>
> >> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> >> index 32cdd9070be5..f60072e0fd3d 100644
> >> --- a/target/riscv/cpu.h
> >> +++ b/target/riscv/cpu.h
> >> @@ -111,7 +111,7 @@ typedef struct CPUArchState CPURISCVState;
> >>  #endif
> >>
> >>  #define RV_VLEN_MAX 1024
> >> -#define RV_MAX_MHPMEVENTS 29
> >> +#define RV_MAX_MHPMEVENTS 32
> >>  #define RV_MAX_MHPMCOUNTERS 32
> >>
> >>  FIELD(VTYPE, VLMUL, 0, 3)
> >> @@ -121,6 +121,18 @@ FIELD(VTYPE, VMA, 7, 1)
> >>  FIELD(VTYPE, VEDIV, 8, 2)
> >>  FIELD(VTYPE, RESERVED, 10, sizeof(target_ulong) * 8 - 11)
> >>
> >> +typedef struct PMUCTRState {
> >> +/* Current value of a counter */
> >> +target_ulong mhpmcounter_val;
> >> +/* Current value of a counter in RV32*/
> >> +target_ulong mhpmcounterh_val;
> >> +/* Snapshot values of counter */
> >> +target_ulong mhpmcounter_prev;
> >> +/* Snapshort value of a counter in RV32 */
> >> +target_ulong mhpmcounterh_prev;
> >> +bool started;
> >> +} PMUCTRState;
> >> +
> >>  struct CPUArchState {
> >>  target_ulong gpr[32];
> >>  target_ulong gprh[32]; /* 64 top bits of the 128-bit registers */
> >> @@ -273,13 +285,10 @@ struct CPUArchState {
> >>
> >>  target_ulong mcountinhibit;
> >>
> >> -/* PMU counter configured values */
> >> -target_ulong mhpmcounter_val[RV_MAX_MHPMCOUNTERS];
> >> -
> >> -/* for RV32 */
> >> -target_ulong mhpmcounterh_val[RV_MAX_MHPMCOUNTERS];
> >> +/* PMU counter state */
> >> +PMUCTRState pmu_ctrs[RV_MAX_MHPMCOUNTERS];
> >>
> >> -/* PMU event selector configured values */
> >> +/* PMU event selector configured values. First three are unused*/
> >>  target_ulong mhpmevent_val[RV_MAX_MHPMEVENTS];
> >>
> >>  target_ulong sscratch;
> >> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> >> index 87aa601e5ddb..c050ed2e2c1b 100644
> >> --- a/target/riscv/csr.c
> >> +++ b/target/riscv/csr.c
> >> @@ -21,6 +21,7 @@
> >>  #include "qemu/log.h"
> >>  #include "qemu/timer.h"
> >>  #include "cpu.h"
> >> +#include "pmu.h"
> >>  #include "qemu/main-loop.h"
> >>  #include "exec/exec-all.h"
> >>  #include "sysemu/cpu-timers.h"
> >> @@ -597,34 +598,28 @@ static int write_vcsr(CPURISCVState *env, int
> csrno, target_ulong val)
> >>  }
> >>
> >>  /* User Timers and Counters */
> >> -static RISCVException read_instret(CPURISCVState *env, int csrno,
> >> -   target_ulong *val)
> >> +static target_ulong get_ticks(bool shift)
> >>  {
> >> +int64_t val;
> >> +target_ulong result;
> >> +
> >>  #if !defined(CONFIG_USER_ONLY)
> >>  if (icount_enabled()) {
> >> -*val = icount_get();
> >> +val = icount_get();
> >>  } else {
> >> -*val = cpu_get_host_ticks();
> >> +val = cpu_get_host_ticks();
> >>  }
> >>  #else
&g

Re: [PATCH] hw/intc: Pass correct hartid while updating mtimecmp

2022-05-13 Thread Frank Chang
Reviewed-by: Frank Chang 

On Sat, May 14, 2022 at 6:15 AM Atish Patra  wrote:

> timecmp update function should be invoked with hartid for which
> timecmp is being updated. The following patch passes the incorrect
> hartid to the update function.
>
> Fixes: e2f01f3c2e13 ("hw/intc: Make RISC-V ACLINT mtime MMIO register
> writable")
>
> Signed-off-by: Atish Patra 
> ---
>  hw/intc/riscv_aclint.c | 3 ++-
>  1 file changed, 2 insertions(+), 1 deletion(-)
>
> diff --git a/hw/intc/riscv_aclint.c b/hw/intc/riscv_aclint.c
> index 0412edc98257..e6bceceefdbc 100644
> --- a/hw/intc/riscv_aclint.c
> +++ b/hw/intc/riscv_aclint.c
> @@ -233,7 +233,8 @@ static void riscv_aclint_mtimer_write(void *opaque,
> hwaddr addr,
>  continue;
>  }
>  riscv_aclint_mtimer_write_timecmp(mtimer, RISCV_CPU(cpu),
> -  i, env->timecmp);
> +  mtimer->hartid_base + i,
> +  env->timecmp);
>  }
>  return;
>  }
> --
> 2.25.1
>
>


Re: [PATCH v8 07/12] target/riscv: Support mcycle/minstret write operation

2022-05-13 Thread Frank Chang
nt read_hpmcounterh(CPURISCVState *env, int csrno, target_ulong
> *val)
> +{
> +*val = get_ticks(true);
> +return RISCV_EXCP_NONE;
> +}
> +
>  #else /* CONFIG_USER_ONLY */
>
>  static int read_mhpmevent(CPURISCVState *env, int csrno, target_ulong
> *val)
>  {
> -int evt_index = csrno - CSR_MHPMEVENT3;
> +int evt_index = csrno - CSR_MCOUNTINHIBIT;
>
>  *val = env->mhpmevent_val[evt_index];
>
> @@ -655,7 +662,7 @@ static int read_mhpmevent(CPURISCVState *env, int
> csrno, target_ulong *val)
>
>  static int write_mhpmevent(CPURISCVState *env, int csrno, target_ulong
> val)
>  {
> -int evt_index = csrno - CSR_MHPMEVENT3;
> +int evt_index = csrno - CSR_MCOUNTINHIBIT;
>
>  env->mhpmevent_val[evt_index] = val;
>
> @@ -664,52 +671,102 @@ static int write_mhpmevent(CPURISCVState *env, int
> csrno, target_ulong val)
>
>  static int write_mhpmcounter(CPURISCVState *env, int csrno, target_ulong
> val)
>  {
> -int ctr_index = csrno - CSR_MHPMCOUNTER3 + 3;
> +int ctr_idx = csrno - CSR_MCYCLE;
> +PMUCTRState *counter = >pmu_ctrs[ctr_idx];
>
> -env->mhpmcounter_val[ctr_index] = val;
> +counter->mhpmcounter_val = val;
> +if (riscv_pmu_ctr_monitor_cycles(env, ctr_idx) ||
> +riscv_pmu_ctr_monitor_instructions(env, ctr_idx)) {
> +counter->mhpmcounter_prev = get_ticks(false);
> +} else {
> +/* Other counters can keep incrementing from the given value */
> +counter->mhpmcounter_prev = val;
> +}
>
>  return RISCV_EXCP_NONE;
>  }
>
>  static int write_mhpmcounterh(CPURISCVState *env, int csrno, target_ulong
> val)
>  {
> -int ctr_index = csrno - CSR_MHPMCOUNTER3H + 3;
> +int ctr_idx = csrno - CSR_MCYCLEH;
> +PMUCTRState *counter = >pmu_ctrs[ctr_idx];
>
> -env->mhpmcounterh_val[ctr_index] = val;
> +counter->mhpmcounterh_val = val;
> +if (riscv_pmu_ctr_monitor_cycles(env, ctr_idx) ||
> +riscv_pmu_ctr_monitor_instructions(env, ctr_idx)) {
> +counter->mhpmcounterh_prev = get_ticks(true);
> +} else {
> +counter->mhpmcounterh_prev = val;
> +}
> +
> +return RISCV_EXCP_NONE;
> +}
> +
> +static RISCVException riscv_pmu_read_ctr(CPURISCVState *env, target_ulong
> *val,
> + bool upper_half, uint32_t
> ctr_idx)
> +{
> +PMUCTRState counter = env->pmu_ctrs[ctr_idx];
> +target_ulong ctr_prev = upper_half ? counter.mhpmcounterh_prev :
> + counter.mhpmcounter_prev;
> +target_ulong ctr_val = upper_half ? counter.mhpmcounterh_val :
> +counter.mhpmcounter_val;
> +
> +if (get_field(env->mcountinhibit, BIT(ctr_idx))) {
> +/**
> + * Counter should not increment if inhibit bit is set. We can't
> really
> + * stop the icount counting. Just return the counter value
> written by
> + * the supervisor to indicate that counter was not incremented.
> + */
> +if (!counter.started) {
> +*val = ctr_val;
> +return RISCV_EXCP_NONE;
> +} else {
> +/* Mark that the counter has been stopped */
> +counter.started = false;
> +}
> +}
> +
> +
> +/**
> + * The kernel computes the perf delta by subtracting the current
> value from
> + * the value it initialized previously (ctr_val).
> + */
> +if (riscv_pmu_ctr_monitor_cycles(env, ctr_idx) ||
> +riscv_pmu_ctr_monitor_instructions(env, ctr_idx)) {
> +*val = get_ticks(upper_half) - ctr_prev + ctr_val;
> +} else {
> +*val = ctr_val;
> +}
>
>  return RISCV_EXCP_NONE;
>  }
>
>  static int read_hpmcounter(CPURISCVState *env, int csrno, target_ulong
> *val)
>  {
> -int ctr_index;
> +uint16_t ctr_index;
>
>  if (env->priv == PRV_M) {
> -ctr_index = csrno - CSR_MHPMCOUNTER3 + 3;
> +ctr_index = csrno - CSR_MCYCLE;

 } else {
> -ctr_index = csrno - CSR_HPMCOUNTER3 + 3;
> +ctr_index = csrno - CSR_CYCLE;
>  }
>

Hi Atish,

According to spec:
"The RDCYCLE pseudoinstruction reads the low XLEN bits of the cycle CSR
which holds a count of the number of clock cycles executed by the
processor core on which the hart is running from an arbitrary start time in
the past."

However, the counter index calculation here would have the issue.
For example, if RDCYCLE instruction is executed in M-mode:
CYCLE csrno is: 0xc00, but MCYCLE csrno is: 0xb00
"csrno - CSR_MCYCLE" would result in the invalidate 

Re: [PATCH] hw/dma: Add Xilinx AXI CDMA

2022-05-04 Thread Frank Chang
On Thu, May 5, 2022 at 4:50 AM Edgar E. Iglesias 
wrote:

>
> On Tue, May 3, 2022 at 7:12 PM Edgar E. Iglesias 
> wrote:
>
>> On Tue, May 3, 2022 at 5:06 PM Frank Chang 
>> wrote:
>>
>>> On Tue, May 3, 2022 at 5:35 PM Edgar E. Iglesias <
>>> edgar.igles...@gmail.com> wrote:
>>>
>>>> On Tue, May 3, 2022 at 3:16 AM Frank Chang 
>>>> wrote:
>>>>
>>>>> On Mon, May 2, 2022 at 6:29 PM Edgar E. Iglesias <
>>>>> edgar.igles...@gmail.com> wrote:
>>>>>
>>>>>> On Thu, Apr 28, 2022 at 5:43 PM  wrote:
>>>>>>
>>>>>>> From: Frank Chang 
>>>>>>>
>>>>>>> Add Xilinx AXI CDMA model, which follows
>>>>>>> AXI Central Direct Memory Access v4.1 spec:
>>>>>>> https://docs.xilinx.com/v/u/en-US/pg034-axi-cdma
>>>>>>>
>>>>>>> Supports both Simple DMA and Scatter Gather modes.
>>>>>>>
>>>>>>
>>>>>> Hi Frank,
>>>>>>
>>>>>> Thanks for modeling this! I have a couple of questions.
>>>>>>
>>>>>
>>>>> Hi Edgar,
>>>>>
>>>>> Thanks for reviewing.
>>>>>
>>>>>
>>>>>>
>>>>>> Do you plan to submit a machine that uses this DMA?
>>>>>>
>>>>>
>>>>> Currently, Xilinx CDMA is used in our internal platform only, which is
>>>>> not upstream.
>>>>> Do you have any suggestions for the existing machine that I can add
>>>>> Xilinx CDMA to?
>>>>> Or perhaps, ARM virt machine?
>>>>>
>>>>
>>>> If there's a reference design somewhere we could use we could
>>>> potentially create a new zynqmp or versal based machine.
>>>>
>>>
>>> Thanks Edgar,
>>>
>>> Do you think it's a good idea to add CDMA in xlnx-zynqmp.c?
>>> (Though I found GDMA and ADMA already exist)
>>>
>>> I'm not familiar with Xilinx's FPGA family, and there are lots of
>>> variants.
>>> Not sure which machine is the best one for me to add CDMA.
>>>
>>
>> xlnx-zynqmp.c models the hardened logic of the ZynqMP, the GDMA and ADMA
>> are hard logic but this CDMA is not.
>> xlnx-zcu102.c models a board with a ZynqMP and off-chip peripherals
>> (reuses xlnx-zynqmp.c) but without anything programmed into the PL (FPGA)
>> parts.
>>
>> If there's some kind of public design (Demo, product, reference design,
>> whatever) that uses the CDMA as a soft IP on the PL and that is somewhat
>> documented, perhaps we could add a xlnx-zcu102-name-of-design.c or a
>> versal-xyz.c to enable this. I don't know of any such design though, but
>> I'll let you know if I find something.
>>
>
> Hi Frank,
>
> This could be something:
>
> https://xilinx.github.io/Embedded-Design-Tutorials/docs/2020.2/docs/Introduction/Zynq7000-EDT/6-using-hp-port.html
>
> A machine model would be based on hw/arm/xilinx_zynq.c.
>

Thanks Edgar,

I was also aware of Zynq-7000 series SoC.
But the datasheet:
https://docs.xilinx.com/v/u/en-US/ds190-Zynq-7000-Overview
doesn't mention that the DMA it uses is CDMA.
It is something interchangeable for Zynq-7000 series SoC?

And from the header comment of hw/arm/xilinx_zynq.c,
it says it models Xilinx Zynq Baseboard.
I'm not familiar with Xilinx's products family.
Do you know what are the differences between "Xilinx Zynq Baseboard" and
"Zynq-7000 SoC"?

Regards,
Frank Chang



>
> Best regards,
> Edgar
>
>
>
>>
>>
>>>
>>>
>>>> It would be great if you guys had a public RISCV design with the CDMA
>>>> that we could model.
>>>>
>>>
>>> I would love to,
>>> but unfortunately, we don't have the spec for this model publicly yet.
>>>
>>
>> Or we wait for your machine to become public and make a model of that
>>
>>
>>
>>>
>>>
>>>>
>>>>>
>>>>>
>>>>>>
>>>>>> The CDMA has a 32-bit AXI4-Lite port for register accesses (see page
>>>>>> 6 and 8 in the spec you referenced), so axicdma_ops.impl.max should be 4
>>>>>> and you shouldn't need the read/write q versions.
>>>>>>
>>>>>
>>>>> Okay, that's something I was not aware of.
>>>>>
>>

Re: [PATCH 2/3] target/riscv: Add dummy mcountinhibit CSR for priv spec v1.11 or higher

2022-05-04 Thread Frank Chang
Hi Anup,

I found that Atish has already submitted a patch to implement the
mcountinhibit CSR:
https://www.mail-archive.com/qemu-devel@nongnu.org/msg879349.html

Regards,
Frank Chang

On Fri, Apr 29, 2022 at 11:44 PM Anup Patel  wrote:

> The mcountinhibit CSR is mandatory for priv spec v1.11 or higher. For
> implementation that don't want to implement can simply have a dummy
> mcountinhibit which always zero.
>
> Fixes: a4b2fa433125 ("target/riscv: Introduce privilege version field in
> the CSR ops.")
> Signed-off-by: Anup Patel 
> ---
>  target/riscv/cpu_bits.h | 3 +++
>  target/riscv/csr.c  | 2 ++
>  2 files changed, 5 insertions(+)
>
> diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
> index 4d04b20d06..4a55c6a709 100644
> --- a/target/riscv/cpu_bits.h
> +++ b/target/riscv/cpu_bits.h
> @@ -159,6 +159,9 @@
>  #define CSR_MTVEC   0x305
>  #define CSR_MCOUNTEREN  0x306
>
> +/* Machine Counter Setup */
> +#define CSR_MCOUNTINHIBIT   0x320
> +
>  /* 32-bit only */
>  #define CSR_MSTATUSH0x310
>
> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> index 2bf0a97196..e144ce7135 100644
> --- a/target/riscv/csr.c
> +++ b/target/riscv/csr.c
> @@ -3391,6 +3391,8 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
>  [CSR_MIE] = { "mie",any,   NULL,NULL,rmw_mie
>  },
>  [CSR_MTVEC]   = { "mtvec",  any,   read_mtvec,
>  write_mtvec   },
>  [CSR_MCOUNTEREN]  = { "mcounteren", any,   read_mcounteren,
> write_mcounteren  },
> +[CSR_MCOUNTINHIBIT] = { "mcountinhibit", any, read_zero, write_ignore,
> + .min_priv_ver =
> PRIV_VERSION_1_11_0 },
>
>  [CSR_MSTATUSH]= { "mstatush",   any32, read_mstatush,
> write_mstatush},
>
> --
> 2.34.1
>
>
>


Re: [PATCH] hw/dma: Add Xilinx AXI CDMA

2022-05-03 Thread Frank Chang
On Tue, May 3, 2022 at 5:35 PM Edgar E. Iglesias 
wrote:

> On Tue, May 3, 2022 at 3:16 AM Frank Chang  wrote:
>
>> On Mon, May 2, 2022 at 6:29 PM Edgar E. Iglesias <
>> edgar.igles...@gmail.com> wrote:
>>
>>> On Thu, Apr 28, 2022 at 5:43 PM  wrote:
>>>
>>>> From: Frank Chang 
>>>>
>>>> Add Xilinx AXI CDMA model, which follows
>>>> AXI Central Direct Memory Access v4.1 spec:
>>>> https://docs.xilinx.com/v/u/en-US/pg034-axi-cdma
>>>>
>>>> Supports both Simple DMA and Scatter Gather modes.
>>>>
>>>
>>> Hi Frank,
>>>
>>> Thanks for modeling this! I have a couple of questions.
>>>
>>
>> Hi Edgar,
>>
>> Thanks for reviewing.
>>
>>
>>>
>>> Do you plan to submit a machine that uses this DMA?
>>>
>>
>> Currently, Xilinx CDMA is used in our internal platform only, which is
>> not upstream.
>> Do you have any suggestions for the existing machine that I can add
>> Xilinx CDMA to?
>> Or perhaps, ARM virt machine?
>>
>
> If there's a reference design somewhere we could use we could potentially
> create a new zynqmp or versal based machine.
>

Thanks Edgar,

Do you think it's a good idea to add CDMA in xlnx-zynqmp.c?
(Though I found GDMA and ADMA already exist)

I'm not familiar with Xilinx's FPGA family, and there are lots of variants.
Not sure which machine is the best one for me to add CDMA.


> It would be great if you guys had a public RISCV design with the CDMA that
> we could model.
>

I would love to,
but unfortunately, we don't have the spec for this model publicly yet.


>
>>
>>
>>>
>>> The CDMA has a 32-bit AXI4-Lite port for register accesses (see page 6
>>> and 8 in the spec you referenced), so axicdma_ops.impl.max should be 4 and
>>> you shouldn't need the read/write q versions.
>>>
>>
>> Okay, that's something I was not aware of.
>>
>> However, I have a question regarding the 64-bit address space.
>>
>> For 64-bit address space, i.e. xlnx,addrwidth = 64.
>> The CDMA spec says that:
>> "TAILDESC_PNTR[_MSB] register causes the AXI CDMA SG Engine
>> to start fetching descriptors starting from the CURDESC_PNTR register
>> value."
>>
>> It seems that DMA will start the transfer if either TAILDESC_PNTR or
>> TAILDESC_PNTR_MSB is written.
>> Then how can we guarantee that the full 64-bit address pointer is written
>> before the DMA transfer is started if we can't write both TAILDESC_PNTR
>> and TAILDESC_PNTR_MSB
>> at the same time?
>>
>
> This is described on pages 25 and 26:
> "When the AXI CDMA is in SG Mode and the address space is 32 bits
> (CDMACR.SGMode = 1), a write by the software application to the
> TAILDESC_PNTR register causes the AXI CDMA SG Engine to start fetching
> descriptors"
>
> I.e TAILDESC_PNTR only starts the DMA if 32bit addresses have been
> selected.
> If 64bit addresses are selected, TAILDESC_PNTR_MSB starts the DMA:
>
> "When the AXI CDMA is in SG Mode, and the address space is more than 32
> bits, (CDMACR.SGMode = 1), a write by the software application to the
> TAILDESC_PNTR_MSB register causes the AXI CDMA SG Engine to start fetching
> descriptors"
>

I guess I missed the description: "the address space is 32 bits" for
TAILDESC_PNTR register in the spec.
I will fix it in my next version patchset.

Regards,
Frank Chang


>
>
>
>>
>> I'm also awarded that Xilinx CDMA Linux driver also has separate 32-bit
>> writes for a 64-bit address.
>> But wouldn't that cause, e.g. dmatest to be failed?
>>
>
> The driver probably relies on the interconnect to down-size the 64bit
> access to 2x32bit ones. QEMU will do the same so this shouldn't be a
> problem.
>
> Best regards,
> Edgar
>
>
>
>>
>> Regards,
>> Frank Chang
>>
>>
>>>
>>> Best regards,
>>> Edgar
>>>
>>>
>>>
>>>>
>>>> Signed-off-by: Frank Chang 
>>>> Reviewed-by: Jim Shu 
>>>> ---
>>>>  hw/dma/meson.build  |   2 +-
>>>>  hw/dma/xilinx_axicdma.c | 792 
>>>>  include/hw/dma/xilinx_axicdma.h |  72 +++
>>>>  3 files changed, 865 insertions(+), 1 deletion(-)
>>>>  create mode 100644 hw/dma/xilinx_axicdma.c
>>>>  create mode 100644 include/hw/dma/xilinx_axicdma.h
>>>>
>>>> diff --git a/hw/dma/meson.build b/hw/dma/meson.build
>

Re: [PATCH] hw/dma: Add Xilinx AXI CDMA

2022-05-02 Thread Frank Chang
On Mon, May 2, 2022 at 6:29 PM Edgar E. Iglesias 
wrote:

> On Thu, Apr 28, 2022 at 5:43 PM  wrote:
>
>> From: Frank Chang 
>>
>> Add Xilinx AXI CDMA model, which follows
>> AXI Central Direct Memory Access v4.1 spec:
>> https://docs.xilinx.com/v/u/en-US/pg034-axi-cdma
>>
>> Supports both Simple DMA and Scatter Gather modes.
>>
>
> Hi Frank,
>
> Thanks for modeling this! I have a couple of questions.
>

Hi Edgar,

Thanks for reviewing.


>
> Do you plan to submit a machine that uses this DMA?
>

Currently, Xilinx CDMA is used in our internal platform only, which is not
upstream.
Do you have any suggestions for the existing machine that I can add Xilinx
CDMA to?
Or perhaps, ARM virt machine?


>
> The CDMA has a 32-bit AXI4-Lite port for register accesses (see page 6 and
> 8 in the spec you referenced), so axicdma_ops.impl.max should be 4 and you
> shouldn't need the read/write q versions.
>

Okay, that's something I was not aware of.

However, I have a question regarding the 64-bit address space.

For 64-bit address space, i.e. xlnx,addrwidth = 64.
The CDMA spec says that:
"TAILDESC_PNTR[_MSB] register causes the AXI CDMA SG Engine
to start fetching descriptors starting from the CURDESC_PNTR register
value."

It seems that DMA will start the transfer if either TAILDESC_PNTR or
TAILDESC_PNTR_MSB is written.
Then how can we guarantee that the full 64-bit address pointer is written
before the DMA transfer is started if we can't write both TAILDESC_PNTR and
TAILDESC_PNTR_MSB
at the same time?

I'm also awarded that Xilinx CDMA Linux driver also has separate 32-bit
writes for a 64-bit address.
But wouldn't that cause, e.g. dmatest to be failed?

Regards,
Frank Chang


>
> Best regards,
> Edgar
>
>
>
>>
>> Signed-off-by: Frank Chang 
>> Reviewed-by: Jim Shu 
>> ---
>>  hw/dma/meson.build  |   2 +-
>>  hw/dma/xilinx_axicdma.c | 792 
>>  include/hw/dma/xilinx_axicdma.h |  72 +++
>>  3 files changed, 865 insertions(+), 1 deletion(-)
>>  create mode 100644 hw/dma/xilinx_axicdma.c
>>  create mode 100644 include/hw/dma/xilinx_axicdma.h
>>
>> diff --git a/hw/dma/meson.build b/hw/dma/meson.build
>> index f3f0661bc3..85edf80b82 100644
>> --- a/hw/dma/meson.build
>> +++ b/hw/dma/meson.build
>> @@ -3,7 +3,7 @@ softmmu_ss.add(when: 'CONFIG_PL080', if_true:
>> files('pl080.c'))
>>  softmmu_ss.add(when: 'CONFIG_PL330', if_true: files('pl330.c'))
>>  softmmu_ss.add(when: 'CONFIG_I82374', if_true: files('i82374.c'))
>>  softmmu_ss.add(when: 'CONFIG_I8257', if_true: files('i8257.c'))
>> -softmmu_ss.add(when: 'CONFIG_XILINX_AXI', if_true:
>> files('xilinx_axidma.c'))
>> +softmmu_ss.add(when: 'CONFIG_XILINX_AXI', if_true:
>> files('xilinx_axidma.c', 'xilinx_axicdma.c'))
>>  softmmu_ss.add(when: 'CONFIG_ZYNQ_DEVCFG', if_true:
>> files('xlnx-zynq-devcfg.c'))
>>  softmmu_ss.add(when: 'CONFIG_ETRAXFS', if_true: files('etraxfs_dma.c'))
>>  softmmu_ss.add(when: 'CONFIG_STP2000', if_true: files('sparc32_dma.c'))
>> diff --git a/hw/dma/xilinx_axicdma.c b/hw/dma/xilinx_axicdma.c
>> new file mode 100644
>> index 00..50aec3ec45
>> --- /dev/null
>> +++ b/hw/dma/xilinx_axicdma.c
>> @@ -0,0 +1,792 @@
>> +/*
>> + * QEMU model of Xilinx AXI-CDMA block.
>> + *
>> + * Copyright (c) 2022 Frank Chang .
>> + *
>> + * Permission is hereby granted, free of charge, to any person obtaining
>> a copy
>> + * of this software and associated documentation files (the "Software"),
>> to deal
>> + * in the Software without restriction, including without limitation the
>> rights
>> + * to use, copy, modify, merge, publish, distribute, sublicense, and/or
>> sell
>> + * copies of the Software, and to permit persons to whom the Software is
>> + * furnished to do so, subject to the following conditions:
>> + *
>> + * The above copyright notice and this permission notice shall be
>> included in
>> + * all copies or substantial portions of the Software.
>> + *
>> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
>> EXPRESS OR
>> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
>> MERCHANTABILITY,
>> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT
>> SHALL
>> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
>> OTHER
>> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
>> ARISING FROM,
>> + * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
>> DEALINGS IN
>> + * THE SO

Re: [PATCH 3/3] target/riscv: Consider priv spec version when generating ISA string

2022-04-29 Thread Frank Chang
On Sat, Apr 30, 2022 at 12:30 PM Anup Patel  wrote:

> On Sat, Apr 30, 2022 at 8:39 AM Frank Chang 
> wrote:
> >
> > Hi Anup,
> >
> > If we want to limit the generated ISA string to/after a specific
> privilege spec version.
> > Shouldn't we also check the privilege spec version when these extensions
> are enabled?
> > Otherwise, it's possible that one extension is enabled,
> > but the privilege spec version is smaller than the one in which the
> extension is supported.
> > (This is possible if user specifies the privileged spec version through
> the command line.)
> > The ISA string therefore won't include the enabled extension.
>
> This patch is only a temporary fix for the sifive_u machine where I am
> seeing some
> of these new extensions available in ISA string.
>
> We need a separate series to have the priv spec version influence
> individual extension
> enabling/disabling.
>

If that's the case,
Reviewed-by: Frank Chang 


>
> Regards,
> Anup
>
> >
> > Regards,
> > Frank Chang
> >
> >
> > On Fri, Apr 29, 2022 at 11:49 PM Anup Patel 
> wrote:
> >>
> >> Most of the multi-letter extensions (such as Svpbmt, Svnapot, Svinval,
> >> etc) are only available after Priv spec v1.12 so ISA string generation
> >> should check the minimum required priv spec version for all extensions.
> >>
> >> Fixes: a775398be2e ("target/riscv: Add isa extenstion strings to the
> >> device tree")
> >> Signed-off-by: Anup Patel 
> >> ---
> >>  target/riscv/cpu.c | 36 +++-
> >>  1 file changed, 19 insertions(+), 17 deletions(-)
> >>
> >> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> >> index 02ee7d45d8..d8c88b96bc 100644
> >> --- a/target/riscv/cpu.c
> >> +++ b/target/riscv/cpu.c
> >> @@ -44,6 +44,7 @@ static const char riscv_single_letter_exts[] =
> "IEMAFDQCPVH";
> >>  struct isa_ext_data {
> >>  const char *name;
> >>  bool enabled;
> >> +uint32_t min_priv_ver;
> >>  };
> >>
> >>  const char * const riscv_int_regnames[] = {
> >> @@ -974,7 +975,7 @@ static void riscv_cpu_class_init(ObjectClass *c,
> void *data)
> >>  device_class_set_props(dc, riscv_cpu_properties);
> >>  }
> >>
> >> -#define ISA_EDATA_ENTRY(name, prop) {#name, cpu->cfg.prop}
> >> +#define ISA_EDATA_ENTRY(name, prop, priv) {#name, cpu->cfg.prop, priv}
> >>
> >>  static void riscv_isa_string_ext(RISCVCPU *cpu, char **isa_str, int
> max_str_len)
> >>  {
> >> @@ -1000,25 +1001,26 @@ static void riscv_isa_string_ext(RISCVCPU *cpu,
> char **isa_str, int max_str_len)
> >>   *extensions by an underscore.
> >>   */
> >>  struct isa_ext_data isa_edata_arr[] = {
> >> -ISA_EDATA_ENTRY(zfh, ext_zfh),
> >> -ISA_EDATA_ENTRY(zfhmin, ext_zfhmin),
> >> -ISA_EDATA_ENTRY(zfinx, ext_zfinx),
> >> -ISA_EDATA_ENTRY(zhinx, ext_zhinx),
> >> -ISA_EDATA_ENTRY(zhinxmin, ext_zhinxmin),
> >> -ISA_EDATA_ENTRY(zdinx, ext_zdinx),
> >> -ISA_EDATA_ENTRY(zba, ext_zba),
> >> -ISA_EDATA_ENTRY(zbb, ext_zbb),
> >> -ISA_EDATA_ENTRY(zbc, ext_zbc),
> >> -ISA_EDATA_ENTRY(zbs, ext_zbs),
> >> -ISA_EDATA_ENTRY(zve32f, ext_zve32f),
> >> -ISA_EDATA_ENTRY(zve64f, ext_zve64f),
> >> -ISA_EDATA_ENTRY(svinval, ext_svinval),
> >> -ISA_EDATA_ENTRY(svnapot, ext_svnapot),
> >> -ISA_EDATA_ENTRY(svpbmt, ext_svpbmt),
> >> +ISA_EDATA_ENTRY(zfh, ext_zfh, PRIV_VERSION_1_12_0),
> >> +ISA_EDATA_ENTRY(zfhmin, ext_zfhmin, PRIV_VERSION_1_12_0),
> >> +ISA_EDATA_ENTRY(zfinx, ext_zfinx, PRIV_VERSION_1_12_0),
> >> +ISA_EDATA_ENTRY(zhinx, ext_zhinx, PRIV_VERSION_1_12_0),
> >> +ISA_EDATA_ENTRY(zhinxmin, ext_zhinxmin, PRIV_VERSION_1_12_0),
> >> +ISA_EDATA_ENTRY(zdinx, ext_zdinx, PRIV_VERSION_1_12_0),
> >> +ISA_EDATA_ENTRY(zba, ext_zba, PRIV_VERSION_1_12_0),
> >> +ISA_EDATA_ENTRY(zbb, ext_zbb, PRIV_VERSION_1_12_0),
> >> +ISA_EDATA_ENTRY(zbc, ext_zbc, PRIV_VERSION_1_12_0),
> >> +ISA_EDATA_ENTRY(zbs, ext_zbs, PRIV_VERSION_1_12_0),
> >> +ISA_EDATA_ENTRY(zve32f, ext_zve32f, PRIV_VERSION_1_12_0),
> >> +ISA_EDATA_ENTRY(zve64f, ext_zve64f, PRIV_VERSION_1_12_0),
> >> +ISA_EDATA_ENTRY(svinval, ext_svinval, PRIV_VERSION_1_12_0),
> >> +ISA_EDATA_ENTRY(svnapot, ext_svnapot, PRIV_VERSION_1_12_0),
> >> +ISA_EDATA_ENTRY(svpbmt, ext_svpbmt, PRIV_VERSION_1_12_0),
> >>  };
> >>
> >>  for (i = 0; i < ARRAY_SIZE(isa_edata_arr); i++) {
> >> -if (isa_edata_arr[i].enabled) {
> >> +if (isa_edata_arr[i].enabled &&
> >> +cpu->env.priv_ver >= isa_edata_arr[i].min_priv_ver) {
> >>  new = g_strconcat(old, "_", isa_edata_arr[i].name, NULL);
> >>  g_free(old);
> >>  old = new;
> >> --
> >> 2.34.1
> >>
> >>
>


Re: [PATCH 1/4] target/riscv: Fix csr number based privilege checking

2022-04-29 Thread Frank Chang
Reviewed-by: Frank Chang 

On Fri, Apr 29, 2022 at 11:34 AM Anup Patel  wrote:

> When hypervisor and VS CSRs are accessed from VS-mode or VU-mode,
> the riscv_csrrw_check() function should generate virtual instruction
> trap instead illegal instruction trap.
>
> Fixes: 533c91e8f22c ("target/riscv: Use RISCVException enum for
> CSR access")
> Signed-off-by: Anup Patel 
> ---
>  target/riscv/csr.c | 8 ++--
>  1 file changed, 6 insertions(+), 2 deletions(-)
>
> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> index 3500e07f92..2bf0a97196 100644
> --- a/target/riscv/csr.c
> +++ b/target/riscv/csr.c
> @@ -3139,7 +3139,7 @@ static inline RISCVException
> riscv_csrrw_check(CPURISCVState *env,
>  int read_only = get_field(csrno, 0xC00) == 3;
>  int csr_min_priv = csr_ops[csrno].min_priv_ver;
>  #if !defined(CONFIG_USER_ONLY)
> -int effective_priv = env->priv;
> +int csr_priv, effective_priv = env->priv;
>
>  if (riscv_has_ext(env, RVH) &&
>  env->priv == PRV_S &&
> @@ -3152,7 +3152,11 @@ static inline RISCVException
> riscv_csrrw_check(CPURISCVState *env,
>  effective_priv++;
>  }
>
> -if (!env->debugger && (effective_priv < get_field(csrno, 0x300))) {
> +csr_priv = get_field(csrno, 0x300);
> +if (!env->debugger && (effective_priv < csr_priv)) {
> +if (csr_priv == (PRV_S + 1) && riscv_cpu_virt_enabled(env)) {
> +return RISCV_EXCP_VIRT_INSTRUCTION_FAULT;
> +}
>  return RISCV_EXCP_ILLEGAL_INST;
>  }
>  #endif
> --
> 2.34.1
>
>
>


Re: [PATCH 3/4] target/riscv: Set [m|s]tval for both illegal and virtual instruction traps

2022-04-29 Thread Frank Chang
Reviewed-by: Frank Chang 

On Fri, Apr 29, 2022 at 11:36 AM Anup Patel  wrote:

> Currently, the [m|s]tval CSRs are set with trapping instruction encoding
> only for illegal instruction traps taken at the time of instruction
> decoding.
>
> In RISC-V world, a valid instructions might also trap as illegal or
> virtual instruction based to trapping bits in various CSRs (such as
> mstatus.TVM or hstatus.VTVM).
>
> We improve setting of [m|s]tval CSRs for all types of illegal and
> virtual instruction traps.
>
> Signed-off-by: Anup Patel 
> ---
>  target/riscv/cpu.c|  2 ++
>  target/riscv/cpu.h|  8 +++-
>  target/riscv/cpu_helper.c |  1 +
>  target/riscv/translate.c  | 17 +
>  4 files changed, 23 insertions(+), 5 deletions(-)
>
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index dff4606585..f0a702fee6 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -406,6 +406,7 @@ void restore_state_to_opc(CPURISCVState *env,
> TranslationBlock *tb,
>  } else {
>  env->pc = data[0];
>  }
> +env->bins = data[1];
>  }
>
>  static void riscv_cpu_reset(DeviceState *dev)
> @@ -445,6 +446,7 @@ static void riscv_cpu_reset(DeviceState *dev)
>  env->mcause = 0;
>  env->miclaim = MIP_SGEIP;
>  env->pc = env->resetvec;
> +env->bins = 0;
>  env->two_stage_lookup = false;
>
>  /* Initialized default priorities of local interrupts. */
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index fe6c9a2c92..a55c918274 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -30,6 +30,12 @@
>
>  #define TCG_GUEST_DEFAULT_MO 0
>
> +/*
> + * RISC-V-specific extra insn start words:
> + * 1: Original instruction opcode
> + */
> +#define TARGET_INSN_START_EXTRA_WORDS 1
> +
>  #define TYPE_RISCV_CPU "riscv-cpu"
>
>  #define RISCV_CPU_TYPE_SUFFIX "-" TYPE_RISCV_CPU
> @@ -140,7 +146,7 @@ struct CPUArchState {
>  target_ulong frm;
>
>  target_ulong badaddr;
> -uint32_t bins;
> +target_ulong bins;
>
>  target_ulong guest_phys_fault_addr;
>
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index d83579accf..bba4fce777 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -1371,6 +1371,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
>  tval = env->badaddr;
>  break;
>  case RISCV_EXCP_ILLEGAL_INST:
> +case RISCV_EXCP_VIRT_INSTRUCTION_FAULT:
>  tval = env->bins;
>  break;
>  default:
> diff --git a/target/riscv/translate.c b/target/riscv/translate.c
> index 0cd1d9ee94..55a4713af2 100644
> --- a/target/riscv/translate.c
> +++ b/target/riscv/translate.c
> @@ -107,6 +107,8 @@ typedef struct DisasContext {
>  /* PointerMasking extension */
>  bool pm_mask_enabled;
>  bool pm_base_enabled;
> +/* TCG of the current insn_start */
> +TCGOp *insn_start;
>  } DisasContext;
>
>  static inline bool has_ext(DisasContext *ctx, uint32_t ext)
> @@ -236,9 +238,6 @@ static void generate_exception_mtval(DisasContext
> *ctx, int excp)
>
>  static void gen_exception_illegal(DisasContext *ctx)
>  {
> -tcg_gen_st_i32(tcg_constant_i32(ctx->opcode), cpu_env,
> -   offsetof(CPURISCVState, bins));
> -
>  generate_exception(ctx, RISCV_EXCP_ILLEGAL_INST);
>  }
>
> @@ -1017,6 +1016,13 @@ static uint32_t opcode_at(DisasContextBase *dcbase,
> target_ulong pc)
>  /* Include decoders for factored-out extensions */
>  #include "decode-XVentanaCondOps.c.inc"
>
> +static inline void decode_save_opc(DisasContext *ctx, target_ulong opc)
> +{
> +assert(ctx->insn_start != NULL);
> +tcg_set_insn_start_param(ctx->insn_start, 1, opc);
> +ctx->insn_start = NULL;
> +}
> +
>  static void decode_opc(CPURISCVState *env, DisasContext *ctx, uint16_t
> opcode)
>  {
>  /*
> @@ -1033,6 +1039,7 @@ static void decode_opc(CPURISCVState *env,
> DisasContext *ctx, uint16_t opcode)
>
>  /* Check for compressed insn */
>  if (extract16(opcode, 0, 2) != 3) {
> +decode_save_opc(ctx, opcode);
>  if (!has_ext(ctx, RVC)) {
>  gen_exception_illegal(ctx);
>  } else {
> @@ -1047,6 +1054,7 @@ static void decode_opc(CPURISCVState *env,
> DisasContext *ctx, uint16_t opcode)
>  opcode32 = deposit32(opcode32, 16, 16,
>   translator_lduw(env, >base,
>   ctx->base.pc_next + 2));
> +decode_save_opc(ctx, opcode32);
>

Re: [PATCH 2/3] target/riscv: Add dummy mcountinhibit CSR for priv spec v1.11 or higher

2022-04-29 Thread Frank Chang
Reviewed-by: Frank Chang 

On Fri, Apr 29, 2022 at 11:44 PM Anup Patel  wrote:

> The mcountinhibit CSR is mandatory for priv spec v1.11 or higher. For
> implementation that don't want to implement can simply have a dummy
> mcountinhibit which always zero.
>
> Fixes: a4b2fa433125 ("target/riscv: Introduce privilege version field in
> the CSR ops.")
> Signed-off-by: Anup Patel 
> ---
>  target/riscv/cpu_bits.h | 3 +++
>  target/riscv/csr.c  | 2 ++
>  2 files changed, 5 insertions(+)
>
> diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
> index 4d04b20d06..4a55c6a709 100644
> --- a/target/riscv/cpu_bits.h
> +++ b/target/riscv/cpu_bits.h
> @@ -159,6 +159,9 @@
>  #define CSR_MTVEC   0x305
>  #define CSR_MCOUNTEREN  0x306
>
> +/* Machine Counter Setup */
> +#define CSR_MCOUNTINHIBIT   0x320
> +
>  /* 32-bit only */
>  #define CSR_MSTATUSH0x310
>
> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> index 2bf0a97196..e144ce7135 100644
> --- a/target/riscv/csr.c
> +++ b/target/riscv/csr.c
> @@ -3391,6 +3391,8 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
>  [CSR_MIE] = { "mie",any,   NULL,NULL,rmw_mie
>  },
>  [CSR_MTVEC]   = { "mtvec",  any,   read_mtvec,
>  write_mtvec   },
>  [CSR_MCOUNTEREN]  = { "mcounteren", any,   read_mcounteren,
> write_mcounteren  },
> +[CSR_MCOUNTINHIBIT] = { "mcountinhibit", any, read_zero, write_ignore,
> + .min_priv_ver =
> PRIV_VERSION_1_11_0 },
>
>  [CSR_MSTATUSH]= { "mstatush",   any32, read_mstatush,
> write_mstatush},
>
> --
> 2.34.1
>
>
>


Re: [PATCH 3/3] target/riscv: Consider priv spec version when generating ISA string

2022-04-29 Thread Frank Chang
Hi Anup,

If we want to limit the generated ISA string to/after a specific privilege
spec version.
Shouldn't we also check the privilege spec version when these extensions
are enabled?
Otherwise, it's possible that one extension is enabled,
but the privilege spec version is smaller than the one in which the
extension is supported.
(This is possible if user specifies the privileged spec version through the
command line.)
The ISA string therefore won't include the enabled extension.

Regards,
Frank Chang


On Fri, Apr 29, 2022 at 11:49 PM Anup Patel  wrote:

> Most of the multi-letter extensions (such as Svpbmt, Svnapot, Svinval,
> etc) are only available after Priv spec v1.12 so ISA string generation
> should check the minimum required priv spec version for all extensions.
>
> Fixes: a775398be2e ("target/riscv: Add isa extenstion strings to the
> device tree")
> Signed-off-by: Anup Patel 
> ---
>  target/riscv/cpu.c | 36 +++-
>  1 file changed, 19 insertions(+), 17 deletions(-)
>
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index 02ee7d45d8..d8c88b96bc 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -44,6 +44,7 @@ static const char riscv_single_letter_exts[] =
> "IEMAFDQCPVH";
>  struct isa_ext_data {
>  const char *name;
>  bool enabled;
> +uint32_t min_priv_ver;
>  };
>
>  const char * const riscv_int_regnames[] = {
> @@ -974,7 +975,7 @@ static void riscv_cpu_class_init(ObjectClass *c, void
> *data)
>  device_class_set_props(dc, riscv_cpu_properties);
>  }
>
> -#define ISA_EDATA_ENTRY(name, prop) {#name, cpu->cfg.prop}
> +#define ISA_EDATA_ENTRY(name, prop, priv) {#name, cpu->cfg.prop, priv}
>
>  static void riscv_isa_string_ext(RISCVCPU *cpu, char **isa_str, int
> max_str_len)
>  {
> @@ -1000,25 +1001,26 @@ static void riscv_isa_string_ext(RISCVCPU *cpu,
> char **isa_str, int max_str_len)
>   *extensions by an underscore.
>   */
>  struct isa_ext_data isa_edata_arr[] = {
> -ISA_EDATA_ENTRY(zfh, ext_zfh),
> -ISA_EDATA_ENTRY(zfhmin, ext_zfhmin),
> -ISA_EDATA_ENTRY(zfinx, ext_zfinx),
> -ISA_EDATA_ENTRY(zhinx, ext_zhinx),
> -ISA_EDATA_ENTRY(zhinxmin, ext_zhinxmin),
> -ISA_EDATA_ENTRY(zdinx, ext_zdinx),
> -ISA_EDATA_ENTRY(zba, ext_zba),
> -ISA_EDATA_ENTRY(zbb, ext_zbb),
> -ISA_EDATA_ENTRY(zbc, ext_zbc),
> -ISA_EDATA_ENTRY(zbs, ext_zbs),
> -ISA_EDATA_ENTRY(zve32f, ext_zve32f),
> -ISA_EDATA_ENTRY(zve64f, ext_zve64f),
> -ISA_EDATA_ENTRY(svinval, ext_svinval),
> -ISA_EDATA_ENTRY(svnapot, ext_svnapot),
> -ISA_EDATA_ENTRY(svpbmt, ext_svpbmt),
> +ISA_EDATA_ENTRY(zfh, ext_zfh, PRIV_VERSION_1_12_0),
> +ISA_EDATA_ENTRY(zfhmin, ext_zfhmin, PRIV_VERSION_1_12_0),
> +ISA_EDATA_ENTRY(zfinx, ext_zfinx, PRIV_VERSION_1_12_0),
> +ISA_EDATA_ENTRY(zhinx, ext_zhinx, PRIV_VERSION_1_12_0),
> +ISA_EDATA_ENTRY(zhinxmin, ext_zhinxmin, PRIV_VERSION_1_12_0),
> +ISA_EDATA_ENTRY(zdinx, ext_zdinx, PRIV_VERSION_1_12_0),
> +ISA_EDATA_ENTRY(zba, ext_zba, PRIV_VERSION_1_12_0),
> +ISA_EDATA_ENTRY(zbb, ext_zbb, PRIV_VERSION_1_12_0),
> +ISA_EDATA_ENTRY(zbc, ext_zbc, PRIV_VERSION_1_12_0),
> +ISA_EDATA_ENTRY(zbs, ext_zbs, PRIV_VERSION_1_12_0),
> +ISA_EDATA_ENTRY(zve32f, ext_zve32f, PRIV_VERSION_1_12_0),
> +ISA_EDATA_ENTRY(zve64f, ext_zve64f, PRIV_VERSION_1_12_0),
> +ISA_EDATA_ENTRY(svinval, ext_svinval, PRIV_VERSION_1_12_0),
> +ISA_EDATA_ENTRY(svnapot, ext_svnapot, PRIV_VERSION_1_12_0),
> +ISA_EDATA_ENTRY(svpbmt, ext_svpbmt, PRIV_VERSION_1_12_0),
>  };
>
>  for (i = 0; i < ARRAY_SIZE(isa_edata_arr); i++) {
> -if (isa_edata_arr[i].enabled) {
> +if (isa_edata_arr[i].enabled &&
> +cpu->env.priv_ver >= isa_edata_arr[i].min_priv_ver) {
>  new = g_strconcat(old, "_", isa_edata_arr[i].name, NULL);
>  g_free(old);
>  old = new;
> --
> 2.34.1
>
>
>


Re: [PATCH 1/3] target/riscv: Don't force update priv spec version to latest

2022-04-29 Thread Frank Chang
Reviewed-by: Frank Chang 

On Fri, Apr 29, 2022 at 11:41 PM Anup Patel  wrote:

> The riscv_cpu_realize() sets priv spec verion to v1.12 when it is
> when "env->priv_ver == 0" (i.e. default v1.10) because the enum
> value of priv spec v1.10 is zero.
>
> Due to above issue, the sifive_u machine will see priv spec v1.12
> instead of priv spec v1.10.
>
> To fix this issue, we set latest priv spec version (i.e. v1.12)
> for base rv64/rv32 cpu and riscv_cpu_realize() will override priv
> spec version only when "cpu->cfg.priv_spec != NULL".
>
> Fixes: 7100fe6c2441 ("target/riscv: Enable privileged spec version 1.12")
> Signed-off-by: Anup Patel 
> ---
>  target/riscv/cpu.c | 10 ++
>  1 file changed, 6 insertions(+), 4 deletions(-)
>
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index f0a702fee6..02ee7d45d8 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -169,6 +169,8 @@ 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);
> +/* Set latest version of privileged specification */
> +set_priv_version(env, PRIV_VERSION_1_12_0);
>  }
>
>  static void rv64_sifive_u_cpu_init(Object *obj)
> @@ -204,6 +206,8 @@ static void rv32_base_cpu_init(Object *obj)
>  CPURISCVState *env = _CPU(obj)->env;
>  /* We set this in the realise function */
>  set_misa(env, MXL_RV32, 0);
> +/* Set latest version of privileged specification */
> +set_priv_version(env, PRIV_VERSION_1_12_0);
>  }
>
>  static void rv32_sifive_u_cpu_init(Object *obj)
> @@ -509,7 +513,7 @@ static void riscv_cpu_realize(DeviceState *dev, Error
> **errp)
>  CPURISCVState *env = >env;
>  RISCVCPUClass *mcc = RISCV_CPU_GET_CLASS(dev);
>  CPUClass *cc = CPU_CLASS(mcc);
> -int priv_version = 0;
> +int priv_version = -1;
>  Error *local_err = NULL;
>
>  cpu_exec_realizefn(cs, _err);
> @@ -533,10 +537,8 @@ static void riscv_cpu_realize(DeviceState *dev, Error
> **errp)
>  }
>  }
>
> -if (priv_version) {
> +if (priv_version >= PRIV_VERSION_1_10_0) {
>  set_priv_version(env, priv_version);
> -} else if (!env->priv_ver) {
> -set_priv_version(env, PRIV_VERSION_1_12_0);
>  }
>
>  if (cpu->cfg.mmu) {
> --
> 2.34.1
>
>
>


[PATCH] hw/dma: Add Xilinx AXI CDMA

2022-04-28 Thread frank . chang
From: Frank Chang 

Add Xilinx AXI CDMA model, which follows
AXI Central Direct Memory Access v4.1 spec:
https://docs.xilinx.com/v/u/en-US/pg034-axi-cdma

Supports both Simple DMA and Scatter Gather modes.

Signed-off-by: Frank Chang 
Reviewed-by: Jim Shu 
---
 hw/dma/meson.build  |   2 +-
 hw/dma/xilinx_axicdma.c | 792 
 include/hw/dma/xilinx_axicdma.h |  72 +++
 3 files changed, 865 insertions(+), 1 deletion(-)
 create mode 100644 hw/dma/xilinx_axicdma.c
 create mode 100644 include/hw/dma/xilinx_axicdma.h

diff --git a/hw/dma/meson.build b/hw/dma/meson.build
index f3f0661bc3..85edf80b82 100644
--- a/hw/dma/meson.build
+++ b/hw/dma/meson.build
@@ -3,7 +3,7 @@ softmmu_ss.add(when: 'CONFIG_PL080', if_true: files('pl080.c'))
 softmmu_ss.add(when: 'CONFIG_PL330', if_true: files('pl330.c'))
 softmmu_ss.add(when: 'CONFIG_I82374', if_true: files('i82374.c'))
 softmmu_ss.add(when: 'CONFIG_I8257', if_true: files('i8257.c'))
-softmmu_ss.add(when: 'CONFIG_XILINX_AXI', if_true: files('xilinx_axidma.c'))
+softmmu_ss.add(when: 'CONFIG_XILINX_AXI', if_true: files('xilinx_axidma.c', 
'xilinx_axicdma.c'))
 softmmu_ss.add(when: 'CONFIG_ZYNQ_DEVCFG', if_true: 
files('xlnx-zynq-devcfg.c'))
 softmmu_ss.add(when: 'CONFIG_ETRAXFS', if_true: files('etraxfs_dma.c'))
 softmmu_ss.add(when: 'CONFIG_STP2000', if_true: files('sparc32_dma.c'))
diff --git a/hw/dma/xilinx_axicdma.c b/hw/dma/xilinx_axicdma.c
new file mode 100644
index 00..50aec3ec45
--- /dev/null
+++ b/hw/dma/xilinx_axicdma.c
@@ -0,0 +1,792 @@
+/*
+ * QEMU model of Xilinx AXI-CDMA block.
+ *
+ * Copyright (c) 2022 Frank Chang .
+ *
+ * Permission is hereby granted, free of charge, to any person obtaining a copy
+ * of this software and associated documentation files (the "Software"), to 
deal
+ * in the Software without restriction, including without limitation the rights
+ * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
+ * copies of the Software, and to permit persons to whom the Software is
+ * furnished to do so, subject to the following conditions:
+ *
+ * The above copyright notice and this permission notice shall be included in
+ * all copies or substantial portions of the Software.
+ *
+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
+ * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
+ * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
+ * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
+ * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 
FROM,
+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN
+ * THE SOFTWARE.
+ */
+
+#include "qemu/osdep.h"
+#include "hw/hw.h"
+#include "hw/irq.h"
+#include "hw/ptimer.h"
+#include "hw/qdev-properties.h"
+#include "hw/sysbus.h"
+#include "qapi/error.h"
+#include "qemu/log.h"
+#include "qemu/module.h"
+#include "qemu/timer.h"
+#include "qom/object.h"
+#include "sysemu/dma.h"
+#include "hw/dma/xilinx_axicdma.h"
+
+#define R_CDMACR0x00
+#define R_CDMASR0x04
+#define R_CURDESC   0x08
+#define R_CURDESC_MSB   0x0c
+#define R_TAILDESC  0x10
+#define R_TAILDESC_MSB  0x14
+#define R_SA0x18
+#define R_SA_MSB0x1c
+#define R_DA0x20
+#define R_DA_MSB0x24
+#define R_BTT   0x28
+
+#define R_MAX   0x30
+
+/* CDMACR */
+#define CDMACR_TAIL_PNTR_EN BIT(1)
+#define CDMACR_RESETBIT(2)
+#define CDMACR_SGMODE   BIT(3)
+#define CDMACR_KEY_HOLE_READBIT(4)
+#define CDMACR_KEY_HOLE_WRITE   BIT(5)
+#define CDMACR_CYCLIC_BD_ENABLE BIT(6)
+#define CDMACR_IOC_IRQ_EN   BIT(12)
+#define CDMACR_DLY_IRQ_EN   BIT(13)
+#define CDMACR_ERR_IRQ_EN   BIT(14)
+
+#define CDMACR_MASK 0x707c
+
+/* TailPntrEn = 1,  IRQThreshold = 1. */
+#define CDMACR_DEFAULT  0x10002
+
+/* CDMASR */
+#define CDMASR_IDLE BIT(1)
+#define CDMASR_SG_INCLUDBIT(3)
+#define CDMASR_DMA_INT_ERR  BIT(4)
+#define CDMASR_DMA_SLV_ERR  BIT(5)
+#define CDMASR_DMA_DEC_ERR  BIT(6)
+#define CDMASR_SG_INT_ERR   BIT(8)
+#define CDMASR_SG_SLV_ERR   BIT(9)
+#define CDMASR_SG_DEC_ERR   BIT(10)
+#define CDMASR_IOC_IRQ  BIT(12)
+#define CDMASR_DLY_IRQ  BIT(13)
+#define CDMASR_ERR_IRQ  BIT(14)
+
+#define CDMASR_IRQ_THRES_SHIFT  16
+#define CDMASR_IRQ_THRES_WIDTH  8
+#define CDMASR_IRQ_DELAY_SHIFT  24
+#define CDMASR_IRQ_DELAY_WIDTH  8
+
+#define CDMASR_IRQ_MASK

[PATCH v3] target/riscv: Support configuarable marchid, mvendorid, mipid CSR values

2022-04-21 Thread frank . chang
From: Frank Chang 

Allow user to set core's marchid, mvendorid, mipid CSRs through
-cpu command line option.

The default values of marchid and mipid are built with QEMU's version
numbers.

Signed-off-by: Frank Chang 
Reviewed-by: Jim Shu 
Reviewed-by: Alistair Francis 
Reviewed-by: Bin Meng 
---
 target/riscv/cpu.c |  9 +
 target/riscv/cpu.h |  4 
 target/riscv/csr.c | 38 ++
 3 files changed, 47 insertions(+), 4 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 0c774056c5..ace68ed855 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -34,6 +34,11 @@
 
 /* RISC-V CPU definitions */
 
+#define RISCV_CPU_MARCHID   ((QEMU_VERSION_MAJOR << 16) | \
+ (QEMU_VERSION_MINOR << 8)  | \
+ (QEMU_VERSION_MICRO))
+#define RISCV_CPU_MIPID RISCV_CPU_MARCHID
+
 static const char riscv_single_letter_exts[] = "IEMAFDQCPVH";
 
 struct isa_ext_data {
@@ -810,6 +815,10 @@ static Property riscv_cpu_properties[] = {
 DEFINE_PROP_UINT16("vlen", RISCVCPU, cfg.vlen, 128),
 DEFINE_PROP_UINT16("elen", RISCVCPU, cfg.elen, 64),
 
+DEFINE_PROP_UINT32("mvendorid", RISCVCPU, cfg.mvendorid, 0),
+DEFINE_PROP_UINT64("marchid", RISCVCPU, cfg.marchid, RISCV_CPU_MARCHID),
+DEFINE_PROP_UINT64("mipid", RISCVCPU, cfg.mipid, RISCV_CPU_MIPID),
+
 DEFINE_PROP_BOOL("svinval", RISCVCPU, cfg.ext_svinval, false),
 DEFINE_PROP_BOOL("svnapot", RISCVCPU, cfg.ext_svnapot, false),
 DEFINE_PROP_BOOL("svpbmt", RISCVCPU, cfg.ext_svpbmt, false),
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 34c22d5d3b..46c66fbf8e 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -393,6 +393,10 @@ struct RISCVCPUConfig {
 bool ext_zve32f;
 bool ext_zve64f;
 
+uint32_t mvendorid;
+uint64_t marchid;
+uint64_t mipid;
+
 /* Vendor-specific custom extensions */
 bool ext_XVentanaCondOps;
 
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 6ba85e7b5d..1c2d3f7193 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -612,6 +612,36 @@ static RISCVException write_ignore(CPURISCVState *env, int 
csrno,
 return RISCV_EXCP_NONE;
 }
 
+static RISCVException read_mvendorid(CPURISCVState *env, int csrno,
+ target_ulong *val)
+{
+CPUState *cs = env_cpu(env);
+RISCVCPU *cpu = RISCV_CPU(cs);
+
+*val = cpu->cfg.mvendorid;
+return RISCV_EXCP_NONE;
+}
+
+static RISCVException read_marchid(CPURISCVState *env, int csrno,
+   target_ulong *val)
+{
+CPUState *cs = env_cpu(env);
+RISCVCPU *cpu = RISCV_CPU(cs);
+
+*val = cpu->cfg.marchid;
+return RISCV_EXCP_NONE;
+}
+
+static RISCVException read_mipid(CPURISCVState *env, int csrno,
+ target_ulong *val)
+{
+CPUState *cs = env_cpu(env);
+RISCVCPU *cpu = RISCV_CPU(cs);
+
+*val = cpu->cfg.mipid;
+return RISCV_EXCP_NONE;
+}
+
 static RISCVException read_mhartid(CPURISCVState *env, int csrno,
target_ulong *val)
 {
@@ -3260,10 +3290,10 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
 [CSR_MINSTRETH] = { "minstreth", any32, read_instreth },
 
 /* Machine Information Registers */
-[CSR_MVENDORID] = { "mvendorid", any,   read_zero},
-[CSR_MARCHID]   = { "marchid",   any,   read_zero},
-[CSR_MIMPID]= { "mimpid",any,   read_zero},
-[CSR_MHARTID]   = { "mhartid",   any,   read_mhartid },
+[CSR_MVENDORID] = { "mvendorid", any,   read_mvendorid },
+[CSR_MARCHID]   = { "marchid",   any,   read_marchid   },
+[CSR_MIMPID]= { "mimpid",any,   read_mipid },
+[CSR_MHARTID]   = { "mhartid",   any,   read_mhartid   },
 
 [CSR_MCONFIGPTR]  = { "mconfigptr", any,   read_zero,
 .min_priv_ver = PRIV_VERSION_1_12_0 },
-- 
2.35.1




Re: [PATCH v2] target/riscv: Support configuarable marchid, mvendorid, mipid CSR values

2022-04-21 Thread Frank Chang
On Fri, Apr 22, 2022 at 8:48 AM Alistair Francis 
wrote:

> On Thu, Apr 21, 2022 at 12:17 PM Bin Meng  wrote:
> >
> > On Wed, Apr 20, 2022 at 5:57 PM  wrote:
> > >
> > > From: Frank Chang 
> > >
> > > Allow user to set core's marchid, mvendorid, mipid CSRs through
> > > -cpu command line option.
> > >
> > > The default values of marchid and mipid are built with QEMU's version
> > > numbers.
> > >
> > > Signed-off-by: Frank Chang 
> > > Reviewed-by: Jim Shu 
> > > Reviewed-by: Alistair Francis 
> > > ---
> > >  target/riscv/cpu.c |  9 +
> > >  target/riscv/cpu.h |  4 
> > >  target/riscv/csr.c | 38 ++
> > >  3 files changed, 47 insertions(+), 4 deletions(-)
> > >
> >
> > Reviewed-by: Bin Meng 
>
> Do you mind rebasing this on
> https://github.com/alistair23/qemu/tree/riscv-to-apply.next ?
>

Sure, will do.

Regards,
Frank Chang


>
> I have sent a PR and hopefully it should be merged into master soon
>
> Alistair
>
> >
>


[PATCH v2] target/riscv: Support configuarable marchid, mvendorid, mipid CSR values

2022-04-20 Thread frank . chang
From: Frank Chang 

Allow user to set core's marchid, mvendorid, mipid CSRs through
-cpu command line option.

The default values of marchid and mipid are built with QEMU's version
numbers.

Signed-off-by: Frank Chang 
Reviewed-by: Jim Shu 
Reviewed-by: Alistair Francis 
---
 target/riscv/cpu.c |  9 +
 target/riscv/cpu.h |  4 
 target/riscv/csr.c | 38 ++
 3 files changed, 47 insertions(+), 4 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index ddda4906ff..84c3ff745a 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -34,6 +34,11 @@
 
 /* RISC-V CPU definitions */
 
+#define RISCV_CPU_MARCHID   ((QEMU_VERSION_MAJOR << 16) | \
+ (QEMU_VERSION_MINOR << 8)  | \
+ (QEMU_VERSION_MICRO))
+#define RISCV_CPU_MIPID RISCV_CPU_MARCHID
+
 static const char riscv_exts[26] = "IEMAFDQCLBJTPVNSUHKORWXYZG";
 
 const char * const riscv_int_regnames[] = {
@@ -786,6 +791,10 @@ static Property riscv_cpu_properties[] = {
 DEFINE_PROP_UINT16("vlen", RISCVCPU, cfg.vlen, 128),
 DEFINE_PROP_UINT16("elen", RISCVCPU, cfg.elen, 64),
 
+DEFINE_PROP_UINT32("mvendorid", RISCVCPU, cfg.mvendorid, 0),
+DEFINE_PROP_UINT64("marchid", RISCVCPU, cfg.marchid, RISCV_CPU_MARCHID),
+DEFINE_PROP_UINT64("mipid", RISCVCPU, cfg.mipid, RISCV_CPU_MIPID),
+
 DEFINE_PROP_BOOL("svinval", RISCVCPU, cfg.ext_svinval, false),
 DEFINE_PROP_BOOL("svnapot", RISCVCPU, cfg.ext_svnapot, false),
 DEFINE_PROP_BOOL("svpbmt", RISCVCPU, cfg.ext_svpbmt, false),
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index c069fe85fa..3ab92deb4b 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -370,6 +370,10 @@ struct RISCVCPUConfig {
 bool ext_zve32f;
 bool ext_zve64f;
 
+uint32_t mvendorid;
+uint64_t marchid;
+uint64_t mipid;
+
 /* Vendor-specific custom extensions */
 bool ext_XVentanaCondOps;
 
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 341c2e6f23..9a02038adb 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -603,6 +603,36 @@ static RISCVException write_ignore(CPURISCVState *env, int 
csrno,
 return RISCV_EXCP_NONE;
 }
 
+static RISCVException read_mvendorid(CPURISCVState *env, int csrno,
+ target_ulong *val)
+{
+CPUState *cs = env_cpu(env);
+RISCVCPU *cpu = RISCV_CPU(cs);
+
+*val = cpu->cfg.mvendorid;
+return RISCV_EXCP_NONE;
+}
+
+static RISCVException read_marchid(CPURISCVState *env, int csrno,
+   target_ulong *val)
+{
+CPUState *cs = env_cpu(env);
+RISCVCPU *cpu = RISCV_CPU(cs);
+
+*val = cpu->cfg.marchid;
+return RISCV_EXCP_NONE;
+}
+
+static RISCVException read_mipid(CPURISCVState *env, int csrno,
+ target_ulong *val)
+{
+CPUState *cs = env_cpu(env);
+RISCVCPU *cpu = RISCV_CPU(cs);
+
+*val = cpu->cfg.mipid;
+return RISCV_EXCP_NONE;
+}
+
 static RISCVException read_mhartid(CPURISCVState *env, int csrno,
target_ulong *val)
 {
@@ -3098,10 +3128,10 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
 [CSR_MINSTRETH] = { "minstreth", any32, read_instreth },
 
 /* Machine Information Registers */
-[CSR_MVENDORID] = { "mvendorid", any,   read_zero},
-[CSR_MARCHID]   = { "marchid",   any,   read_zero},
-[CSR_MIMPID]= { "mimpid",any,   read_zero},
-[CSR_MHARTID]   = { "mhartid",   any,   read_mhartid },
+[CSR_MVENDORID] = { "mvendorid", any,   read_mvendorid },
+[CSR_MARCHID]   = { "marchid",   any,   read_marchid   },
+[CSR_MIMPID]= { "mimpid",any,   read_mipid },
+[CSR_MHARTID]   = { "mhartid",   any,   read_mhartid   },
 
 /* Machine Trap Setup */
 [CSR_MSTATUS] = { "mstatus",any,   read_mstatus, 
write_mstatus, NULL,
-- 
2.35.1




Re: [PATCH] target/riscv: Support configuarable marchid, mvendorid, mipid CSR values

2022-04-20 Thread Frank Chang
On Tue, Apr 19, 2022 at 2:00 PM Frank Chang  wrote:

> On Tue, Apr 19, 2022 at 1:27 PM Anup Patel 
> wrote:
>
>> On Tue, Apr 19, 2022 at 10:52 AM Alistair Francis 
>> wrote:
>> >
>> > On Fri, Apr 15, 2022 at 7:37 PM  wrote:
>> > >
>> > > From: Frank Chang 
>> > >
>> > > Allow user to set core's marchid, mvendorid, mipid CSRs through
>> > > -cpu command line option.
>> > >
>> > > Signed-off-by: Frank Chang 
>> > > Reviewed-by: Jim Shu 
>> > > ---
>> > >  target/riscv/cpu.c |  4 
>> > >  target/riscv/cpu.h |  4 
>> > >  target/riscv/csr.c | 38 ++
>> > >  3 files changed, 42 insertions(+), 4 deletions(-)
>> > >
>> > > diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
>> > > index ddda4906ff..2eea0f9be7 100644
>> > > --- a/target/riscv/cpu.c
>> > > +++ b/target/riscv/cpu.c
>> > > @@ -786,6 +786,10 @@ static Property riscv_cpu_properties[] = {
>> > >  DEFINE_PROP_UINT16("vlen", RISCVCPU, cfg.vlen, 128),
>> > >  DEFINE_PROP_UINT16("elen", RISCVCPU, cfg.elen, 64),
>> > >
>> > > +DEFINE_PROP_UINT32("mvendorid", RISCVCPU, cfg.mvendorid, 0),
>> > > +DEFINE_PROP_UINT64("marchid", RISCVCPU, cfg.marchid, 0),
>> > > +DEFINE_PROP_UINT64("mipid", RISCVCPU, cfg.mipid, 0),
>> >
>> > Should we have non-zero defaults here?
>>
>> To do that, we need mvendorid for QEMU RISC-V.
>>
>> The marchid and mipid can be based on the QEMU version number.
>>
>> Regards,
>> Anup
>>
>
> The original intention for this patch is to allow users to define
> their own $mvendorid, $marchid, and $mipid through the command line
> when they initiate QEMU.
>
> If we want to provide the default values for QEMU RISC-V CPU,
> just like what Anup said.
> We need to define our own mvendorid, which should be a JEDEC manufacturer
> ID.
> (Perhaps it's fine to just give some random legal JEDEC manufacturer ID
> as I don't think we would really want to spend the money on that.)
>
> For $marchid and $mipid,
> I agree that it could base on QEMU's version from the QEMU_FULL_VERSION
> macro.
> (and $marchid should have MSB set to 1 for open-source projects.)
>

Sorry, I made a mistake.

The MSB of $marchid should be cleared for open source projects:
"Open-source project architecture IDs are allocated globally by the RISC-V
Foundation, and have
non-zero architecture IDs with a zero most-significant-bit (MSB).
Commercial architecture IDs are
allocated by each commercial vendor independently, but must have the MSB
set and cannot contain
zero in the remaining MXLEN-1 bits."

Regards,
Frank Chang


>
> Regards,
> Frank Chang
>
>
>>
>> >
>> > Alistair
>> >
>> > > +
>> > >  DEFINE_PROP_BOOL("svinval", RISCVCPU, cfg.ext_svinval, false),
>> > >  DEFINE_PROP_BOOL("svnapot", RISCVCPU, cfg.ext_svnapot, false),
>> > >  DEFINE_PROP_BOOL("svpbmt", RISCVCPU, cfg.ext_svpbmt, false),
>> > > diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
>> > > index c069fe85fa..3ab92deb4b 100644
>> > > --- a/target/riscv/cpu.h
>> > > +++ b/target/riscv/cpu.h
>> > > @@ -370,6 +370,10 @@ struct RISCVCPUConfig {
>> > >  bool ext_zve32f;
>> > >  bool ext_zve64f;
>> > >
>> > > +uint32_t mvendorid;
>> > > +uint64_t marchid;
>> > > +uint64_t mipid;
>> > > +
>> > >  /* Vendor-specific custom extensions */
>> > >  bool ext_XVentanaCondOps;
>> > >
>> > > diff --git a/target/riscv/csr.c b/target/riscv/csr.c
>> > > index 341c2e6f23..9a02038adb 100644
>> > > --- a/target/riscv/csr.c
>> > > +++ b/target/riscv/csr.c
>> > > @@ -603,6 +603,36 @@ static RISCVException write_ignore(CPURISCVState
>> *env, int csrno,
>> > >  return RISCV_EXCP_NONE;
>> > >  }
>> > >
>> > > +static RISCVException read_mvendorid(CPURISCVState *env, int csrno,
>> > > + target_ulong *val)
>> > > +{
>> > > +CPUState *cs = env_cpu(env);
>> > > +RISCVCPU *cpu = RISCV_CPU(cs);
>> > > +
>> > > +*val = cpu->cfg.mvendorid;
>> > > +return RISCV_EXCP_NONE;
&

[PATCH v4 3/4] hw/intc: Make RISC-V ACLINT mtime MMIO register writable

2022-04-20 Thread frank . chang
From: Frank Chang 

RISC-V privilege spec defines that mtime is exposed as a memory-mapped
machine-mode read-write register. However, as QEMU uses host monotonic
timer as timer source, this makes mtime to be read-only in RISC-V
ACLINT.

This patch makes mtime to be writable by recording the time delta value
between the mtime value to be written and the timer value at the time
mtime is written. Time delta value is then added back whenever the timer
value is retrieved.

Signed-off-by: Frank Chang 
Reviewed-by: Jim Shu 
Reviewed-by: Alistair Francis 
---
 hw/intc/riscv_aclint.c | 71 --
 include/hw/intc/riscv_aclint.h |  1 +
 target/riscv/cpu.h |  8 ++--
 target/riscv/cpu_helper.c  |  4 +-
 4 files changed, 57 insertions(+), 27 deletions(-)

diff --git a/hw/intc/riscv_aclint.c b/hw/intc/riscv_aclint.c
index ff082090fe..3b3ab548f6 100644
--- a/hw/intc/riscv_aclint.c
+++ b/hw/intc/riscv_aclint.c
@@ -38,12 +38,18 @@ typedef struct riscv_aclint_mtimer_callback {
 int num;
 } riscv_aclint_mtimer_callback;
 
-static uint64_t cpu_riscv_read_rtc(uint32_t timebase_freq)
+static uint64_t cpu_riscv_read_rtc_raw(uint32_t timebase_freq)
 {
 return muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
 timebase_freq, NANOSECONDS_PER_SECOND);
 }
 
+static uint64_t cpu_riscv_read_rtc(void *opaque)
+{
+RISCVAclintMTimerState *mtimer = opaque;
+return cpu_riscv_read_rtc_raw(mtimer->timebase_freq) + mtimer->time_delta;
+}
+
 /*
  * Called when timecmp is written to update the QEMU timer or immediately
  * trigger timer interrupt if mtimecmp <= current timer value.
@@ -51,13 +57,13 @@ static uint64_t cpu_riscv_read_rtc(uint32_t timebase_freq)
 static void riscv_aclint_mtimer_write_timecmp(RISCVAclintMTimerState *mtimer,
   RISCVCPU *cpu,
   int hartid,
-  uint64_t value,
-  uint32_t timebase_freq)
+  uint64_t value)
 {
+uint32_t timebase_freq = mtimer->timebase_freq;
 uint64_t next;
 uint64_t diff;
 
-uint64_t rtc_r = cpu_riscv_read_rtc(timebase_freq);
+uint64_t rtc_r = cpu_riscv_read_rtc(mtimer);
 
 cpu->env.timecmp = value;
 if (cpu->env.timecmp <= rtc_r) {
@@ -140,11 +146,11 @@ static uint64_t riscv_aclint_mtimer_read(void *opaque, 
hwaddr addr,
 }
 } else if (addr == mtimer->time_base) {
 /* time_lo for RV32/RV64 or timecmp for RV64 */
-uint64_t rtc = cpu_riscv_read_rtc(mtimer->timebase_freq);
+uint64_t rtc = cpu_riscv_read_rtc(mtimer);
 return (size == 4) ? (rtc & 0x) : rtc;
 } else if (addr == mtimer->time_base + 4) {
 /* time_hi */
-return (cpu_riscv_read_rtc(mtimer->timebase_freq) >> 32) & 0x;
+return (cpu_riscv_read_rtc(mtimer) >> 32) & 0x;
 }
 
 qemu_log_mask(LOG_UNIMP,
@@ -157,6 +163,7 @@ static void riscv_aclint_mtimer_write(void *opaque, hwaddr 
addr,
 uint64_t value, unsigned size)
 {
 RISCVAclintMTimerState *mtimer = opaque;
+int i;
 
 if (addr >= mtimer->timecmp_base &&
 addr < (mtimer->timecmp_base + (mtimer->num_harts << 3))) {
@@ -172,20 +179,18 @@ static void riscv_aclint_mtimer_write(void *opaque, 
hwaddr addr,
 /* timecmp_lo for RV32/RV64 */
 uint64_t timecmp_hi = env->timecmp >> 32;
 riscv_aclint_mtimer_write_timecmp(mtimer, RISCV_CPU(cpu), 
hartid,
-timecmp_hi << 32 | (value & 0x),
-mtimer->timebase_freq);
+timecmp_hi << 32 | (value & 0x));
 } else {
 /* timecmp for RV64 */
 riscv_aclint_mtimer_write_timecmp(mtimer, RISCV_CPU(cpu), 
hartid,
-  value, 
mtimer->timebase_freq);
+  value);
 }
 } else if ((addr & 0x7) == 4) {
 if (size == 4) {
 /* timecmp_hi for RV32/RV64 */
 uint64_t timecmp_lo = env->timecmp;
 riscv_aclint_mtimer_write_timecmp(mtimer, RISCV_CPU(cpu), 
hartid,
-value << 32 | (timecmp_lo & 0x),
-mtimer->timebase_freq);
+value << 32 | (timecmp_lo & 0x));
 } else {
 qemu_log_mask(LOG_GUEST_ERROR,
   "aclint-mtimer: invalid timecmp_hi write: %08x",
@@ -197,15 +202,39 @@ static void riscv_aclint_mtimer_write(void *opaque, 
hwaddr addr,
   (uint32_t)addr);
 }
 return;
-} el

[PATCH v4 4/4] hw/intc: riscv_aclint: Add reset function of ACLINT devices

2022-04-20 Thread frank . chang
From: Jim Shu 

This commit implements reset function of all ACLINT devices.
ACLINT device reset will clear MTIME and MSIP register to 0.

Depend on RISC-V ACLINT spec v1.0-rc4:
https://github.com/riscv/riscv-aclint/blob/v1.0-rc4/riscv-aclint.adoc

Signed-off-by: Jim Shu 
Reviewed-by: Frank Chang 
Reviewed-by: Alistair Francis 
---
 hw/intc/riscv_aclint.c | 39 +++
 1 file changed, 39 insertions(+)

diff --git a/hw/intc/riscv_aclint.c b/hw/intc/riscv_aclint.c
index 3b3ab548f6..0412edc982 100644
--- a/hw/intc/riscv_aclint.c
+++ b/hw/intc/riscv_aclint.c
@@ -293,11 +293,29 @@ static void riscv_aclint_mtimer_realize(DeviceState *dev, 
Error **errp)
 }
 }
 
+static void riscv_aclint_mtimer_reset_enter(Object *obj, ResetType type)
+{
+/*
+ * According to RISC-V ACLINT spec:
+ *   - On MTIMER device reset, the MTIME register is cleared to zero.
+ *   - On MTIMER device reset, the MTIMECMP registers are in unknown state.
+ */
+RISCVAclintMTimerState *mtimer = RISCV_ACLINT_MTIMER(obj);
+
+/*
+ * Clear mtime register by writing to 0 it.
+ * Pending mtime interrupts will also be cleared at the same time.
+ */
+riscv_aclint_mtimer_write(mtimer, mtimer->time_base, 0, 8);
+}
+
 static void riscv_aclint_mtimer_class_init(ObjectClass *klass, void *data)
 {
 DeviceClass *dc = DEVICE_CLASS(klass);
 dc->realize = riscv_aclint_mtimer_realize;
 device_class_set_props(dc, riscv_aclint_mtimer_properties);
+ResettableClass *rc = RESETTABLE_CLASS(klass);
+rc->phases.enter = riscv_aclint_mtimer_reset_enter;
 }
 
 static const TypeInfo riscv_aclint_mtimer_info = {
@@ -452,11 +470,32 @@ static void riscv_aclint_swi_realize(DeviceState *dev, 
Error **errp)
 }
 }
 
+static void riscv_aclint_swi_reset_enter(Object *obj, ResetType type)
+{
+/*
+ * According to RISC-V ACLINT spec:
+ *   - On MSWI device reset, each MSIP register is cleared to zero.
+ *
+ * p.s. SSWI device reset does nothing since SETSIP register always reads 
0.
+ */
+RISCVAclintSwiState *swi = RISCV_ACLINT_SWI(obj);
+int i;
+
+if (!swi->sswi) {
+for (i = 0; i < swi->num_harts; i++) {
+/* Clear MSIP registers by lowering software interrupts. */
+qemu_irq_lower(swi->soft_irqs[i]);
+}
+}
+}
+
 static void riscv_aclint_swi_class_init(ObjectClass *klass, void *data)
 {
 DeviceClass *dc = DEVICE_CLASS(klass);
 dc->realize = riscv_aclint_swi_realize;
 device_class_set_props(dc, riscv_aclint_swi_properties);
+ResettableClass *rc = RESETTABLE_CLASS(klass);
+rc->phases.enter = riscv_aclint_swi_reset_enter;
 }
 
 static const TypeInfo riscv_aclint_swi_info = {
-- 
2.35.1




[PATCH v4 2/4] hw/intc: Support 32/64-bit mtimecmp and mtime accesses in RISC-V ACLINT

2022-04-20 Thread frank . chang
From: Frank Chang 

RISC-V privilege spec defines that:

* In RV32, memory-mapped writes to mtimecmp modify only one 32-bit part
  of the register.
* For RV64, naturally aligned 64-bit memory accesses to the mtime and
  mtimecmp registers are additionally supported and are atomic.

It's possible to perform both 32/64-bit read/write accesses to both
mtimecmp and mtime registers.

Signed-off-by: Frank Chang 
Reviewed-by: Alistair Francis 
Reviewed-by: Jim Shu 
---
 hw/intc/riscv_aclint.c | 42 +++---
 1 file changed, 27 insertions(+), 15 deletions(-)

diff --git a/hw/intc/riscv_aclint.c b/hw/intc/riscv_aclint.c
index 37e9ace801..ff082090fe 100644
--- a/hw/intc/riscv_aclint.c
+++ b/hw/intc/riscv_aclint.c
@@ -126,9 +126,9 @@ static uint64_t riscv_aclint_mtimer_read(void *opaque, 
hwaddr addr,
 qemu_log_mask(LOG_GUEST_ERROR,
   "aclint-mtimer: invalid hartid: %zu", hartid);
 } else if ((addr & 0x7) == 0) {
-/* timecmp_lo */
+/* timecmp_lo for RV32/RV64 or timecmp for RV64 */
 uint64_t timecmp = env->timecmp;
-return timecmp & 0x;
+return (size == 4) ? (timecmp & 0x) : timecmp;
 } else if ((addr & 0x7) == 4) {
 /* timecmp_hi */
 uint64_t timecmp = env->timecmp;
@@ -139,8 +139,9 @@ static uint64_t riscv_aclint_mtimer_read(void *opaque, 
hwaddr addr,
 return 0;
 }
 } else if (addr == mtimer->time_base) {
-/* time_lo */
-return cpu_riscv_read_rtc(mtimer->timebase_freq) & 0x;
+/* time_lo for RV32/RV64 or timecmp for RV64 */
+uint64_t rtc = cpu_riscv_read_rtc(mtimer->timebase_freq);
+return (size == 4) ? (rtc & 0x) : rtc;
 } else if (addr == mtimer->time_base + 4) {
 /* time_hi */
 return (cpu_riscv_read_rtc(mtimer->timebase_freq) >> 32) & 0x;
@@ -167,18 +168,29 @@ static void riscv_aclint_mtimer_write(void *opaque, 
hwaddr addr,
 qemu_log_mask(LOG_GUEST_ERROR,
   "aclint-mtimer: invalid hartid: %zu", hartid);
 } else if ((addr & 0x7) == 0) {
-/* timecmp_lo */
-uint64_t timecmp_hi = env->timecmp >> 32;
-riscv_aclint_mtimer_write_timecmp(mtimer, RISCV_CPU(cpu), hartid,
-timecmp_hi << 32 | (value & 0x),
-mtimer->timebase_freq);
-return;
+if (size == 4) {
+/* timecmp_lo for RV32/RV64 */
+uint64_t timecmp_hi = env->timecmp >> 32;
+riscv_aclint_mtimer_write_timecmp(mtimer, RISCV_CPU(cpu), 
hartid,
+timecmp_hi << 32 | (value & 0x),
+mtimer->timebase_freq);
+} else {
+/* timecmp for RV64 */
+riscv_aclint_mtimer_write_timecmp(mtimer, RISCV_CPU(cpu), 
hartid,
+  value, 
mtimer->timebase_freq);
+}
 } else if ((addr & 0x7) == 4) {
-/* timecmp_hi */
-uint64_t timecmp_lo = env->timecmp;
-riscv_aclint_mtimer_write_timecmp(mtimer, RISCV_CPU(cpu), hartid,
-value << 32 | (timecmp_lo & 0x),
-mtimer->timebase_freq);
+if (size == 4) {
+/* timecmp_hi for RV32/RV64 */
+uint64_t timecmp_lo = env->timecmp;
+riscv_aclint_mtimer_write_timecmp(mtimer, RISCV_CPU(cpu), 
hartid,
+value << 32 | (timecmp_lo & 0x),
+mtimer->timebase_freq);
+} else {
+qemu_log_mask(LOG_GUEST_ERROR,
+  "aclint-mtimer: invalid timecmp_hi write: %08x",
+  (uint32_t)addr);
+}
 } else {
 qemu_log_mask(LOG_UNIMP,
   "aclint-mtimer: invalid timecmp write: %08x",
-- 
2.35.1




[PATCH v4 1/4] hw/intc: Add .impl.[min|max]_access_size declaration in RISC-V ACLINT

2022-04-20 Thread frank . chang
From: Frank Chang 

If device's MemoryRegion doesn't have .impl.[min|max]_access_size
declaration, the default access_size_min would be 1 byte and
access_size_max would be 4 bytes (see: softmmu/memory.c).
This will cause a 64-bit memory access to ACLINT to be splitted into
two 32-bit memory accesses.

Signed-off-by: Frank Chang 
Reviewed-by: Alistair Francis 
Reviewed-by: Jim Shu 
---
 hw/intc/riscv_aclint.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/hw/intc/riscv_aclint.c b/hw/intc/riscv_aclint.c
index e43b050e92..37e9ace801 100644
--- a/hw/intc/riscv_aclint.c
+++ b/hw/intc/riscv_aclint.c
@@ -208,6 +208,10 @@ static const MemoryRegionOps riscv_aclint_mtimer_ops = {
 .valid = {
 .min_access_size = 4,
 .max_access_size = 8
+},
+.impl = {
+.min_access_size = 4,
+.max_access_size = 8,
 }
 };
 
-- 
2.35.1




[PATCH v4 0/4] Support ACLINT 32/64-bit mtimecmp/mtime read/write accesses

2022-04-20 Thread frank . chang
From: Frank Chang 

This patchset makes ACLINT mtime to be writable as RISC-V privilege
spec defines that mtime is exposed as a memory-mapped machine-mode
read-write register. Also, mtimecmp and mtime should be 32/64-bit memory
accessible registers. ACLINT reset function is also added, which requires
mtime to be resetable if we need to support core power-gating feature in
the future.

This patchset is the updated verion of:
https://patchew.org/QEMU/20220126095448.2964-1-frank.ch...@sifive.com/

Changelog:

v4:
  * Replace the error log mask for invalid 8-byte timecmp_hi and time_hi
writes from LOG_UNIMP to LOG_GUEST_ERROR.

v3:
  * Forbid 8-byte write access to timecmp_hi and time_hi.
  * Add ACLINT reset function.

v2:
  * Support 32/64-bit mtimecmp/mtime memory accesses.
  * Add .impl.[min|max]_access_size declaration.

Frank Chang (3):
  hw/intc: Add .impl.[min|max]_access_size declaration in RISC-V ACLINT
  hw/intc: Support 32/64-bit mtimecmp and mtime accesses in RISC-V
ACLINT
  hw/intc: Make RISC-V ACLINT mtime MMIO register writable

Jim Shu (1):
  hw/intc: riscv_aclint: Add reset function of ACLINT devices

 hw/intc/riscv_aclint.c | 144 ++---
 include/hw/intc/riscv_aclint.h |   1 +
 target/riscv/cpu.h |   8 +-
 target/riscv/cpu_helper.c  |   4 +-
 4 files changed, 121 insertions(+), 36 deletions(-)

--
2.35.1




Re: [PATCH] target/riscv: Support configuarable marchid, mvendorid, mipid CSR values

2022-04-20 Thread Frank Chang
On Wed, Apr 20, 2022 at 3:47 PM Alistair Francis 
wrote:

> On Tue, Apr 19, 2022 at 5:04 PM Frank Chang 
> wrote:
> >
> > On Tue, Apr 19, 2022 at 2:00 PM Frank Chang 
> wrote:
> >>
> >> On Tue, Apr 19, 2022 at 1:27 PM Anup Patel 
> wrote:
> >>>
> >>> On Tue, Apr 19, 2022 at 10:52 AM Alistair Francis <
> alistai...@gmail.com> wrote:
> >>> >
> >>> > On Fri, Apr 15, 2022 at 7:37 PM  wrote:
> >>> > >
> >>> > > From: Frank Chang 
> >>> > >
> >>> > > Allow user to set core's marchid, mvendorid, mipid CSRs through
> >>> > > -cpu command line option.
> >>> > >
> >>> > > Signed-off-by: Frank Chang 
> >>> > > Reviewed-by: Jim Shu 
> >>> > > ---
> >>> > >  target/riscv/cpu.c |  4 
> >>> > >  target/riscv/cpu.h |  4 
> >>> > >  target/riscv/csr.c | 38 ++
> >>> > >  3 files changed, 42 insertions(+), 4 deletions(-)
> >>> > >
> >>> > > diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> >>> > > index ddda4906ff..2eea0f9be7 100644
> >>> > > --- a/target/riscv/cpu.c
> >>> > > +++ b/target/riscv/cpu.c
> >>> > > @@ -786,6 +786,10 @@ static Property riscv_cpu_properties[] = {
> >>> > >  DEFINE_PROP_UINT16("vlen", RISCVCPU, cfg.vlen, 128),
> >>> > >  DEFINE_PROP_UINT16("elen", RISCVCPU, cfg.elen, 64),
> >>> > >
> >>> > > +DEFINE_PROP_UINT32("mvendorid", RISCVCPU, cfg.mvendorid, 0),
> >>> > > +DEFINE_PROP_UINT64("marchid", RISCVCPU, cfg.marchid, 0),
> >>> > > +DEFINE_PROP_UINT64("mipid", RISCVCPU, cfg.mipid, 0),
> >>> >
> >>> > Should we have non-zero defaults here?
> >>>
> >>> To do that, we need mvendorid for QEMU RISC-V.
> >>>
> >>> The marchid and mipid can be based on the QEMU version number.
> >>>
> >>> Regards,
> >>> Anup
> >>
> >>
> >> The original intention for this patch is to allow users to define
> >> their own $mvendorid, $marchid, and $mipid through the command line
> >> when they initiate QEMU.
> >>
> >> If we want to provide the default values for QEMU RISC-V CPU,
> >> just like what Anup said.
> >> We need to define our own mvendorid, which should be a JEDEC
> manufacturer ID.
> >> (Perhaps it's fine to just give some random legal JEDEC manufacturer ID
> >> as I don't think we would really want to spend the money on that.)
>
> This is fine as zero I think.
>
> >>
> >> For $marchid and $mipid,
> >> I agree that it could base on QEMU's version from the QEMU_FULL_VERSION
> macro.
> >> (and $marchid should have MSB set to 1 for open-source projects.)
>
> There could be some use in setting this to the QEMU version by
> default. It doesn't really get us much though, but might be useful.
>
> I'll take this patch as is, feel free to send a new patch if you want
> to add a default value
>
> Alistair
>

Sure, I'll set QEMU version by default in the next version patchset.

Regards,
Frank Chang


>
> >>
> >> Regards,
> >> Frank Chang
> >
> >
> > Another simpler way is to stick with the current approach
> > and leave $mvendorid, $marchid and $mipid default to 0.
> > Which is still legal as RISC-V privilege spec says:
> > "A value of 0 can be returned to indicate the field is not implemented."
> >
> > Regards,
> > Frank Chang
> >
> >>
> >>
> >>>
> >>>
> >>> >
> >>> > Alistair
> >>> >
> >>> > > +
> >>> > >  DEFINE_PROP_BOOL("svinval", RISCVCPU, cfg.ext_svinval, false),
> >>> > >  DEFINE_PROP_BOOL("svnapot", RISCVCPU, cfg.ext_svnapot, false),
> >>> > >  DEFINE_PROP_BOOL("svpbmt", RISCVCPU, cfg.ext_svpbmt, false),
> >>> > > diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> >>> > > index c069fe85fa..3ab92deb4b 100644
> >>> > > --- a/target/riscv/cpu.h
> >>> > > +++ b/target/riscv/cpu.h
> >>> > > @@ -370,6 +370,10 @@ struct RISCVCPUConfig {
> >>> > >  bool ext_z

Re: [PATCH v3 3/4] hw/intc: Make RISC-V ACLINT mtime MMIO register writable

2022-04-20 Thread Frank Chang
On Wed, Apr 20, 2022 at 3:42 PM Alistair Francis 
wrote:

> On Tue, Apr 19, 2022 at 7:10 PM  wrote:
> >
> > From: Frank Chang 
> >
> > RISC-V privilege spec defines that mtime is exposed as a memory-mapped
> > machine-mode read-write register. However, as QEMU uses host monotonic
> > timer as timer source, this makes mtime to be read-only in RISC-V
> > ACLINT.
> >
> > This patch makes mtime to be writable by recording the time delta value
> > between the mtime value to be written and the timer value at the time
> > mtime is written. Time delta value is then added back whenever the timer
> > value is retrieved.
> >
> > Signed-off-by: Frank Chang 
> > Reviewed-by: Jim Shu 
> > ---
> >  hw/intc/riscv_aclint.c | 71 --
> >  include/hw/intc/riscv_aclint.h |  1 +
> >  target/riscv/cpu.h |  8 ++--
> >  target/riscv/cpu_helper.c  |  4 +-
> >  4 files changed, 57 insertions(+), 27 deletions(-)
> >
> > diff --git a/hw/intc/riscv_aclint.c b/hw/intc/riscv_aclint.c
> > index ad3c49706f..ad7ccf96cd 100644
> > --- a/hw/intc/riscv_aclint.c
> > +++ b/hw/intc/riscv_aclint.c
> > @@ -38,12 +38,18 @@ typedef struct riscv_aclint_mtimer_callback {
> >  int num;
> >  } riscv_aclint_mtimer_callback;
> >
> > -static uint64_t cpu_riscv_read_rtc(uint32_t timebase_freq)
> > +static uint64_t cpu_riscv_read_rtc_raw(uint32_t timebase_freq)
> >  {
> >  return muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
> >  timebase_freq, NANOSECONDS_PER_SECOND);
> >  }
> >
> > +static uint64_t cpu_riscv_read_rtc(void *opaque)
> > +{
> > +RISCVAclintMTimerState *mtimer = opaque;
> > +return cpu_riscv_read_rtc_raw(mtimer->timebase_freq) +
> mtimer->time_delta;
> > +}
> > +
> >  /*
> >   * Called when timecmp is written to update the QEMU timer or
> immediately
> >   * trigger timer interrupt if mtimecmp <= current timer value.
> > @@ -51,13 +57,13 @@ static uint64_t cpu_riscv_read_rtc(uint32_t
> timebase_freq)
> >  static void riscv_aclint_mtimer_write_timecmp(RISCVAclintMTimerState
> *mtimer,
> >RISCVCPU *cpu,
> >int hartid,
> > -  uint64_t value,
> > -  uint32_t timebase_freq)
> > +  uint64_t value)
> >  {
> > +uint32_t timebase_freq = mtimer->timebase_freq;
> >  uint64_t next;
> >  uint64_t diff;
> >
> > -uint64_t rtc_r = cpu_riscv_read_rtc(timebase_freq);
> > +uint64_t rtc_r = cpu_riscv_read_rtc(mtimer);
> >
> >  cpu->env.timecmp = value;
> >  if (cpu->env.timecmp <= rtc_r) {
> > @@ -140,11 +146,11 @@ static uint64_t riscv_aclint_mtimer_read(void
> *opaque, hwaddr addr,
> >  }
> >  } else if (addr == mtimer->time_base) {
> >  /* time_lo for RV32/RV64 or timecmp for RV64 */
> > -uint64_t rtc = cpu_riscv_read_rtc(mtimer->timebase_freq);
> > +uint64_t rtc = cpu_riscv_read_rtc(mtimer);
> >  return (size == 4) ? (rtc & 0x) : rtc;
> >  } else if (addr == mtimer->time_base + 4) {
> >  /* time_hi */
> > -return (cpu_riscv_read_rtc(mtimer->timebase_freq) >> 32) &
> 0x;
> > +return (cpu_riscv_read_rtc(mtimer) >> 32) & 0x;
> >  }
> >
> >  qemu_log_mask(LOG_UNIMP,
> > @@ -157,6 +163,7 @@ static void riscv_aclint_mtimer_write(void *opaque,
> hwaddr addr,
> >  uint64_t value, unsigned size)
> >  {
> >  RISCVAclintMTimerState *mtimer = opaque;
> > +int i;
> >
> >  if (addr >= mtimer->timecmp_base &&
> >  addr < (mtimer->timecmp_base + (mtimer->num_harts << 3))) {
> > @@ -172,20 +179,18 @@ static void riscv_aclint_mtimer_write(void
> *opaque, hwaddr addr,
> >  /* timecmp_lo for RV32/RV64 */
> >  uint64_t timecmp_hi = env->timecmp >> 32;
> >  riscv_aclint_mtimer_write_timecmp(mtimer,
> RISCV_CPU(cpu), hartid,
> > -timecmp_hi << 32 | (value & 0x),
> > -mtimer->timebase_freq);
> > +timecmp_hi << 32 | (value & 0x));
> >  } else {
> >  /* timecmp for RV64 */
&g

[PATCH v3 4/4] hw/intc: riscv_aclint: Add reset function of ACLINT devices

2022-04-19 Thread frank . chang
From: Jim Shu 

This commit implements reset function of all ACLINT devices.
ACLINT device reset will clear MTIME and MSIP register to 0.

Depend on RISC-V ACLINT spec v1.0-rc4:
https://github.com/riscv/riscv-aclint/blob/v1.0-rc4/riscv-aclint.adoc

Signed-off-by: Jim Shu 
Reviewed-by: Frank Chang 
---
 hw/intc/riscv_aclint.c | 39 +++
 1 file changed, 39 insertions(+)

diff --git a/hw/intc/riscv_aclint.c b/hw/intc/riscv_aclint.c
index ad7ccf96cd..67a07bb5b9 100644
--- a/hw/intc/riscv_aclint.c
+++ b/hw/intc/riscv_aclint.c
@@ -293,11 +293,29 @@ static void riscv_aclint_mtimer_realize(DeviceState *dev, 
Error **errp)
 }
 }
 
+static void riscv_aclint_mtimer_reset_enter(Object *obj, ResetType type)
+{
+/*
+ * According to RISC-V ACLINT spec:
+ *   - On MTIMER device reset, the MTIME register is cleared to zero.
+ *   - On MTIMER device reset, the MTIMECMP registers are in unknown state.
+ */
+RISCVAclintMTimerState *mtimer = RISCV_ACLINT_MTIMER(obj);
+
+/*
+ * Clear mtime register by writing to 0 it.
+ * Pending mtime interrupts will also be cleared at the same time.
+ */
+riscv_aclint_mtimer_write(mtimer, mtimer->time_base, 0, 8);
+}
+
 static void riscv_aclint_mtimer_class_init(ObjectClass *klass, void *data)
 {
 DeviceClass *dc = DEVICE_CLASS(klass);
 dc->realize = riscv_aclint_mtimer_realize;
 device_class_set_props(dc, riscv_aclint_mtimer_properties);
+ResettableClass *rc = RESETTABLE_CLASS(klass);
+rc->phases.enter = riscv_aclint_mtimer_reset_enter;
 }
 
 static const TypeInfo riscv_aclint_mtimer_info = {
@@ -452,11 +470,32 @@ static void riscv_aclint_swi_realize(DeviceState *dev, 
Error **errp)
 }
 }
 
+static void riscv_aclint_swi_reset_enter(Object *obj, ResetType type)
+{
+/*
+ * According to RISC-V ACLINT spec:
+ *   - On MSWI device reset, each MSIP register is cleared to zero.
+ *
+ * p.s. SSWI device reset does nothing since SETSIP register always reads 
0.
+ */
+RISCVAclintSwiState *swi = RISCV_ACLINT_SWI(obj);
+int i;
+
+if (!swi->sswi) {
+for (i = 0; i < swi->num_harts; i++) {
+/* Clear MSIP registers by lowering software interrupts. */
+qemu_irq_lower(swi->soft_irqs[i]);
+}
+}
+}
+
 static void riscv_aclint_swi_class_init(ObjectClass *klass, void *data)
 {
 DeviceClass *dc = DEVICE_CLASS(klass);
 dc->realize = riscv_aclint_swi_realize;
 device_class_set_props(dc, riscv_aclint_swi_properties);
+ResettableClass *rc = RESETTABLE_CLASS(klass);
+rc->phases.enter = riscv_aclint_swi_reset_enter;
 }
 
 static const TypeInfo riscv_aclint_swi_info = {
-- 
2.35.1




[PATCH v3 0/4] Support ACLINT 32/64-bit mtimecmp/mtime read/write accesses

2022-04-19 Thread frank . chang
From: Frank Chang 

This patchset makes ACLINT mtime to be writable as RISC-V privilege
spec defines that mtime is exposed as a memory-mapped machine-mode
read-write register. Also, mtimecmp and mtime should be 32/64-bit memory
accessible registers. ACLINT reset function is also added, which requires
mtime to be resetable if we need to support core power-gating feature in
the future.

This patchset is the updated verion of:
https://patchew.org/QEMU/20220126095448.2964-1-frank.ch...@sifive.com/

Changelog:

v3:
  * Forbid 8-byte write access to timecmp_hi and time_hi.
  * Add ACLINT reset function.

v2:
  * Support 32/64-bit mtimecmp/mtime memory accesses.
  * Add .impl.[min|max]_access_size declaration.

Frank Chang (3):
  hw/intc: Add .impl.[min|max]_access_size declaration in RISC-V ACLINT
  hw/intc: Support 32/64-bit mtimecmp and mtime accesses in RISC-V
ACLINT
  hw/intc: Make RISC-V ACLINT mtime MMIO register writable

Jim Shu (1):
  hw/intc: riscv_aclint: Add reset function of ACLINT devices

 hw/intc/riscv_aclint.c | 144 ++---
 include/hw/intc/riscv_aclint.h |   1 +
 target/riscv/cpu.h |   8 +-
 target/riscv/cpu_helper.c  |   4 +-
 4 files changed, 121 insertions(+), 36 deletions(-)

--
2.35.1




[PATCH v3 2/4] hw/intc: Support 32/64-bit mtimecmp and mtime accesses in RISC-V ACLINT

2022-04-19 Thread frank . chang
From: Frank Chang 

RISC-V privilege spec defines that:

* In RV32, memory-mapped writes to mtimecmp modify only one 32-bit part
  of the register.
* For RV64, naturally aligned 64-bit memory accesses to the mtime and
  mtimecmp registers are additionally supported and are atomic.

It's possible to perform both 32/64-bit read/write accesses to both
mtimecmp and mtime registers.

Signed-off-by: Frank Chang 
Reviewed-by: Alistair Francis 
Reviewed-by: Jim Shu 
---
 hw/intc/riscv_aclint.c | 42 +++---
 1 file changed, 27 insertions(+), 15 deletions(-)

diff --git a/hw/intc/riscv_aclint.c b/hw/intc/riscv_aclint.c
index 37e9ace801..ad3c49706f 100644
--- a/hw/intc/riscv_aclint.c
+++ b/hw/intc/riscv_aclint.c
@@ -126,9 +126,9 @@ static uint64_t riscv_aclint_mtimer_read(void *opaque, 
hwaddr addr,
 qemu_log_mask(LOG_GUEST_ERROR,
   "aclint-mtimer: invalid hartid: %zu", hartid);
 } else if ((addr & 0x7) == 0) {
-/* timecmp_lo */
+/* timecmp_lo for RV32/RV64 or timecmp for RV64 */
 uint64_t timecmp = env->timecmp;
-return timecmp & 0x;
+return (size == 4) ? (timecmp & 0x) : timecmp;
 } else if ((addr & 0x7) == 4) {
 /* timecmp_hi */
 uint64_t timecmp = env->timecmp;
@@ -139,8 +139,9 @@ static uint64_t riscv_aclint_mtimer_read(void *opaque, 
hwaddr addr,
 return 0;
 }
 } else if (addr == mtimer->time_base) {
-/* time_lo */
-return cpu_riscv_read_rtc(mtimer->timebase_freq) & 0x;
+/* time_lo for RV32/RV64 or timecmp for RV64 */
+uint64_t rtc = cpu_riscv_read_rtc(mtimer->timebase_freq);
+return (size == 4) ? (rtc & 0x) : rtc;
 } else if (addr == mtimer->time_base + 4) {
 /* time_hi */
 return (cpu_riscv_read_rtc(mtimer->timebase_freq) >> 32) & 0x;
@@ -167,18 +168,29 @@ static void riscv_aclint_mtimer_write(void *opaque, 
hwaddr addr,
 qemu_log_mask(LOG_GUEST_ERROR,
   "aclint-mtimer: invalid hartid: %zu", hartid);
 } else if ((addr & 0x7) == 0) {
-/* timecmp_lo */
-uint64_t timecmp_hi = env->timecmp >> 32;
-riscv_aclint_mtimer_write_timecmp(mtimer, RISCV_CPU(cpu), hartid,
-timecmp_hi << 32 | (value & 0x),
-mtimer->timebase_freq);
-return;
+if (size == 4) {
+/* timecmp_lo for RV32/RV64 */
+uint64_t timecmp_hi = env->timecmp >> 32;
+riscv_aclint_mtimer_write_timecmp(mtimer, RISCV_CPU(cpu), 
hartid,
+timecmp_hi << 32 | (value & 0x),
+mtimer->timebase_freq);
+} else {
+/* timecmp for RV64 */
+riscv_aclint_mtimer_write_timecmp(mtimer, RISCV_CPU(cpu), 
hartid,
+  value, 
mtimer->timebase_freq);
+}
 } else if ((addr & 0x7) == 4) {
-/* timecmp_hi */
-uint64_t timecmp_lo = env->timecmp;
-riscv_aclint_mtimer_write_timecmp(mtimer, RISCV_CPU(cpu), hartid,
-value << 32 | (timecmp_lo & 0x),
-mtimer->timebase_freq);
+if (size == 4) {
+/* timecmp_hi for RV32/RV64 */
+uint64_t timecmp_lo = env->timecmp;
+riscv_aclint_mtimer_write_timecmp(mtimer, RISCV_CPU(cpu), 
hartid,
+value << 32 | (timecmp_lo & 0x),
+mtimer->timebase_freq);
+} else {
+qemu_log_mask(LOG_UNIMP,
+  "aclint-mtimer: invalid timecmp_hi write: %08x",
+  (uint32_t)addr);
+}
 } else {
 qemu_log_mask(LOG_UNIMP,
   "aclint-mtimer: invalid timecmp write: %08x",
-- 
2.35.1




[PATCH v3 3/4] hw/intc: Make RISC-V ACLINT mtime MMIO register writable

2022-04-19 Thread frank . chang
From: Frank Chang 

RISC-V privilege spec defines that mtime is exposed as a memory-mapped
machine-mode read-write register. However, as QEMU uses host monotonic
timer as timer source, this makes mtime to be read-only in RISC-V
ACLINT.

This patch makes mtime to be writable by recording the time delta value
between the mtime value to be written and the timer value at the time
mtime is written. Time delta value is then added back whenever the timer
value is retrieved.

Signed-off-by: Frank Chang 
Reviewed-by: Jim Shu 
---
 hw/intc/riscv_aclint.c | 71 --
 include/hw/intc/riscv_aclint.h |  1 +
 target/riscv/cpu.h |  8 ++--
 target/riscv/cpu_helper.c  |  4 +-
 4 files changed, 57 insertions(+), 27 deletions(-)

diff --git a/hw/intc/riscv_aclint.c b/hw/intc/riscv_aclint.c
index ad3c49706f..ad7ccf96cd 100644
--- a/hw/intc/riscv_aclint.c
+++ b/hw/intc/riscv_aclint.c
@@ -38,12 +38,18 @@ typedef struct riscv_aclint_mtimer_callback {
 int num;
 } riscv_aclint_mtimer_callback;
 
-static uint64_t cpu_riscv_read_rtc(uint32_t timebase_freq)
+static uint64_t cpu_riscv_read_rtc_raw(uint32_t timebase_freq)
 {
 return muldiv64(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL),
 timebase_freq, NANOSECONDS_PER_SECOND);
 }
 
+static uint64_t cpu_riscv_read_rtc(void *opaque)
+{
+RISCVAclintMTimerState *mtimer = opaque;
+return cpu_riscv_read_rtc_raw(mtimer->timebase_freq) + mtimer->time_delta;
+}
+
 /*
  * Called when timecmp is written to update the QEMU timer or immediately
  * trigger timer interrupt if mtimecmp <= current timer value.
@@ -51,13 +57,13 @@ static uint64_t cpu_riscv_read_rtc(uint32_t timebase_freq)
 static void riscv_aclint_mtimer_write_timecmp(RISCVAclintMTimerState *mtimer,
   RISCVCPU *cpu,
   int hartid,
-  uint64_t value,
-  uint32_t timebase_freq)
+  uint64_t value)
 {
+uint32_t timebase_freq = mtimer->timebase_freq;
 uint64_t next;
 uint64_t diff;
 
-uint64_t rtc_r = cpu_riscv_read_rtc(timebase_freq);
+uint64_t rtc_r = cpu_riscv_read_rtc(mtimer);
 
 cpu->env.timecmp = value;
 if (cpu->env.timecmp <= rtc_r) {
@@ -140,11 +146,11 @@ static uint64_t riscv_aclint_mtimer_read(void *opaque, 
hwaddr addr,
 }
 } else if (addr == mtimer->time_base) {
 /* time_lo for RV32/RV64 or timecmp for RV64 */
-uint64_t rtc = cpu_riscv_read_rtc(mtimer->timebase_freq);
+uint64_t rtc = cpu_riscv_read_rtc(mtimer);
 return (size == 4) ? (rtc & 0x) : rtc;
 } else if (addr == mtimer->time_base + 4) {
 /* time_hi */
-return (cpu_riscv_read_rtc(mtimer->timebase_freq) >> 32) & 0x;
+return (cpu_riscv_read_rtc(mtimer) >> 32) & 0x;
 }
 
 qemu_log_mask(LOG_UNIMP,
@@ -157,6 +163,7 @@ static void riscv_aclint_mtimer_write(void *opaque, hwaddr 
addr,
 uint64_t value, unsigned size)
 {
 RISCVAclintMTimerState *mtimer = opaque;
+int i;
 
 if (addr >= mtimer->timecmp_base &&
 addr < (mtimer->timecmp_base + (mtimer->num_harts << 3))) {
@@ -172,20 +179,18 @@ static void riscv_aclint_mtimer_write(void *opaque, 
hwaddr addr,
 /* timecmp_lo for RV32/RV64 */
 uint64_t timecmp_hi = env->timecmp >> 32;
 riscv_aclint_mtimer_write_timecmp(mtimer, RISCV_CPU(cpu), 
hartid,
-timecmp_hi << 32 | (value & 0x),
-mtimer->timebase_freq);
+timecmp_hi << 32 | (value & 0x));
 } else {
 /* timecmp for RV64 */
 riscv_aclint_mtimer_write_timecmp(mtimer, RISCV_CPU(cpu), 
hartid,
-  value, 
mtimer->timebase_freq);
+  value);
 }
 } else if ((addr & 0x7) == 4) {
 if (size == 4) {
 /* timecmp_hi for RV32/RV64 */
 uint64_t timecmp_lo = env->timecmp;
 riscv_aclint_mtimer_write_timecmp(mtimer, RISCV_CPU(cpu), 
hartid,
-value << 32 | (timecmp_lo & 0x),
-mtimer->timebase_freq);
+value << 32 | (timecmp_lo & 0x));
 } else {
 qemu_log_mask(LOG_UNIMP,
   "aclint-mtimer: invalid timecmp_hi write: %08x",
@@ -197,15 +202,39 @@ static void riscv_aclint_mtimer_write(void *opaque, 
hwaddr addr,
   (uint32_t)addr);
 }
 return;
-} else if (addr == mtimer->time_base) {
-/* 

[PATCH v3 1/4] hw/intc: Add .impl.[min|max]_access_size declaration in RISC-V ACLINT

2022-04-19 Thread frank . chang
From: Frank Chang 

If device's MemoryRegion doesn't have .impl.[min|max]_access_size
declaration, the default access_size_min would be 1 byte and
access_size_max would be 4 bytes (see: softmmu/memory.c).
This will cause a 64-bit memory access to ACLINT to be splitted into
two 32-bit memory accesses.

Signed-off-by: Frank Chang 
Reviewed-by: Alistair Francis 
Reviewed-by: Jim Shu 
---
 hw/intc/riscv_aclint.c | 4 
 1 file changed, 4 insertions(+)

diff --git a/hw/intc/riscv_aclint.c b/hw/intc/riscv_aclint.c
index e43b050e92..37e9ace801 100644
--- a/hw/intc/riscv_aclint.c
+++ b/hw/intc/riscv_aclint.c
@@ -208,6 +208,10 @@ static const MemoryRegionOps riscv_aclint_mtimer_ops = {
 .valid = {
 .min_access_size = 4,
 .max_access_size = 8
+},
+.impl = {
+.min_access_size = 4,
+.max_access_size = 8,
 }
 };
 
-- 
2.35.1




Re: [PATCH] target/riscv: Support configuarable marchid, mvendorid, mipid CSR values

2022-04-19 Thread Frank Chang
On Tue, Apr 19, 2022 at 2:00 PM Frank Chang  wrote:

> On Tue, Apr 19, 2022 at 1:27 PM Anup Patel 
> wrote:
>
>> On Tue, Apr 19, 2022 at 10:52 AM Alistair Francis 
>> wrote:
>> >
>> > On Fri, Apr 15, 2022 at 7:37 PM  wrote:
>> > >
>> > > From: Frank Chang 
>> > >
>> > > Allow user to set core's marchid, mvendorid, mipid CSRs through
>> > > -cpu command line option.
>> > >
>> > > Signed-off-by: Frank Chang 
>> > > Reviewed-by: Jim Shu 
>> > > ---
>> > >  target/riscv/cpu.c |  4 
>> > >  target/riscv/cpu.h |  4 
>> > >  target/riscv/csr.c | 38 ++
>> > >  3 files changed, 42 insertions(+), 4 deletions(-)
>> > >
>> > > diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
>> > > index ddda4906ff..2eea0f9be7 100644
>> > > --- a/target/riscv/cpu.c
>> > > +++ b/target/riscv/cpu.c
>> > > @@ -786,6 +786,10 @@ static Property riscv_cpu_properties[] = {
>> > >  DEFINE_PROP_UINT16("vlen", RISCVCPU, cfg.vlen, 128),
>> > >  DEFINE_PROP_UINT16("elen", RISCVCPU, cfg.elen, 64),
>> > >
>> > > +DEFINE_PROP_UINT32("mvendorid", RISCVCPU, cfg.mvendorid, 0),
>> > > +DEFINE_PROP_UINT64("marchid", RISCVCPU, cfg.marchid, 0),
>> > > +DEFINE_PROP_UINT64("mipid", RISCVCPU, cfg.mipid, 0),
>> >
>> > Should we have non-zero defaults here?
>>
>> To do that, we need mvendorid for QEMU RISC-V.
>>
>> The marchid and mipid can be based on the QEMU version number.
>>
>> Regards,
>> Anup
>>
>
> The original intention for this patch is to allow users to define
> their own $mvendorid, $marchid, and $mipid through the command line
> when they initiate QEMU.
>
> If we want to provide the default values for QEMU RISC-V CPU,
> just like what Anup said.
> We need to define our own mvendorid, which should be a JEDEC manufacturer
> ID.
> (Perhaps it's fine to just give some random legal JEDEC manufacturer ID
> as I don't think we would really want to spend the money on that.)
>
> For $marchid and $mipid,
> I agree that it could base on QEMU's version from the QEMU_FULL_VERSION
> macro.
> (and $marchid should have MSB set to 1 for open-source projects.)
>
> Regards,
> Frank Chang
>

Another simpler way is to stick with the current approach
and leave $mvendorid, $marchid and $mipid default to 0.
Which is still legal as RISC-V privilege spec says:
"A value of 0 can be returned to indicate the field is not implemented."

Regards,
Frank Chang


>
>
>>
>> >
>> > Alistair
>> >
>> > > +
>> > >  DEFINE_PROP_BOOL("svinval", RISCVCPU, cfg.ext_svinval, false),
>> > >  DEFINE_PROP_BOOL("svnapot", RISCVCPU, cfg.ext_svnapot, false),
>> > >  DEFINE_PROP_BOOL("svpbmt", RISCVCPU, cfg.ext_svpbmt, false),
>> > > diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
>> > > index c069fe85fa..3ab92deb4b 100644
>> > > --- a/target/riscv/cpu.h
>> > > +++ b/target/riscv/cpu.h
>> > > @@ -370,6 +370,10 @@ struct RISCVCPUConfig {
>> > >  bool ext_zve32f;
>> > >  bool ext_zve64f;
>> > >
>> > > +uint32_t mvendorid;
>> > > +uint64_t marchid;
>> > > +uint64_t mipid;
>> > > +
>> > >  /* Vendor-specific custom extensions */
>> > >  bool ext_XVentanaCondOps;
>> > >
>> > > diff --git a/target/riscv/csr.c b/target/riscv/csr.c
>> > > index 341c2e6f23..9a02038adb 100644
>> > > --- a/target/riscv/csr.c
>> > > +++ b/target/riscv/csr.c
>> > > @@ -603,6 +603,36 @@ static RISCVException write_ignore(CPURISCVState
>> *env, int csrno,
>> > >  return RISCV_EXCP_NONE;
>> > >  }
>> > >
>> > > +static RISCVException read_mvendorid(CPURISCVState *env, int csrno,
>> > > + target_ulong *val)
>> > > +{
>> > > +CPUState *cs = env_cpu(env);
>> > > +RISCVCPU *cpu = RISCV_CPU(cs);
>> > > +
>> > > +*val = cpu->cfg.mvendorid;
>> > > +return RISCV_EXCP_NONE;
>> > > +}
>> > > +
>> > > +static RISCVException read_marchid(CPURISCVState *env, int csrno,
>> > > +   targe

Re: [PATCH] target/riscv: Support configuarable marchid, mvendorid, mipid CSR values

2022-04-19 Thread Frank Chang
On Tue, Apr 19, 2022 at 1:27 PM Anup Patel  wrote:

> On Tue, Apr 19, 2022 at 10:52 AM Alistair Francis 
> wrote:
> >
> > On Fri, Apr 15, 2022 at 7:37 PM  wrote:
> > >
> > > From: Frank Chang 
> > >
> > > Allow user to set core's marchid, mvendorid, mipid CSRs through
> > > -cpu command line option.
> > >
> > > Signed-off-by: Frank Chang 
> > > Reviewed-by: Jim Shu 
> > > ---
> > >  target/riscv/cpu.c |  4 
> > >  target/riscv/cpu.h |  4 
> > >  target/riscv/csr.c | 38 ++
> > >  3 files changed, 42 insertions(+), 4 deletions(-)
> > >
> > > diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> > > index ddda4906ff..2eea0f9be7 100644
> > > --- a/target/riscv/cpu.c
> > > +++ b/target/riscv/cpu.c
> > > @@ -786,6 +786,10 @@ static Property riscv_cpu_properties[] = {
> > >  DEFINE_PROP_UINT16("vlen", RISCVCPU, cfg.vlen, 128),
> > >  DEFINE_PROP_UINT16("elen", RISCVCPU, cfg.elen, 64),
> > >
> > > +DEFINE_PROP_UINT32("mvendorid", RISCVCPU, cfg.mvendorid, 0),
> > > +DEFINE_PROP_UINT64("marchid", RISCVCPU, cfg.marchid, 0),
> > > +DEFINE_PROP_UINT64("mipid", RISCVCPU, cfg.mipid, 0),
> >
> > Should we have non-zero defaults here?
>
> To do that, we need mvendorid for QEMU RISC-V.
>
> The marchid and mipid can be based on the QEMU version number.
>
> Regards,
> Anup
>

The original intention for this patch is to allow users to define
their own $mvendorid, $marchid, and $mipid through the command line
when they initiate QEMU.

If we want to provide the default values for QEMU RISC-V CPU,
just like what Anup said.
We need to define our own mvendorid, which should be a JEDEC manufacturer
ID.
(Perhaps it's fine to just give some random legal JEDEC manufacturer ID
as I don't think we would really want to spend the money on that.)

For $marchid and $mipid,
I agree that it could base on QEMU's version from the QEMU_FULL_VERSION
macro.
(and $marchid should have MSB set to 1 for open-source projects.)

Regards,
Frank Chang


>
> >
> > Alistair
> >
> > > +
> > >  DEFINE_PROP_BOOL("svinval", RISCVCPU, cfg.ext_svinval, false),
> > >  DEFINE_PROP_BOOL("svnapot", RISCVCPU, cfg.ext_svnapot, false),
> > >  DEFINE_PROP_BOOL("svpbmt", RISCVCPU, cfg.ext_svpbmt, false),
> > > diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> > > index c069fe85fa..3ab92deb4b 100644
> > > --- a/target/riscv/cpu.h
> > > +++ b/target/riscv/cpu.h
> > > @@ -370,6 +370,10 @@ struct RISCVCPUConfig {
> > >  bool ext_zve32f;
> > >  bool ext_zve64f;
> > >
> > > +uint32_t mvendorid;
> > > +uint64_t marchid;
> > > +uint64_t mipid;
> > > +
> > >  /* Vendor-specific custom extensions */
> > >  bool ext_XVentanaCondOps;
> > >
> > > diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> > > index 341c2e6f23..9a02038adb 100644
> > > --- a/target/riscv/csr.c
> > > +++ b/target/riscv/csr.c
> > > @@ -603,6 +603,36 @@ static RISCVException write_ignore(CPURISCVState
> *env, int csrno,
> > >  return RISCV_EXCP_NONE;
> > >  }
> > >
> > > +static RISCVException read_mvendorid(CPURISCVState *env, int csrno,
> > > + target_ulong *val)
> > > +{
> > > +CPUState *cs = env_cpu(env);
> > > +RISCVCPU *cpu = RISCV_CPU(cs);
> > > +
> > > +*val = cpu->cfg.mvendorid;
> > > +return RISCV_EXCP_NONE;
> > > +}
> > > +
> > > +static RISCVException read_marchid(CPURISCVState *env, int csrno,
> > > +   target_ulong *val)
> > > +{
> > > +CPUState *cs = env_cpu(env);
> > > +RISCVCPU *cpu = RISCV_CPU(cs);
> > > +
> > > +*val = cpu->cfg.marchid;
> > > +return RISCV_EXCP_NONE;
> > > +}
> > > +
> > > +static RISCVException read_mipid(CPURISCVState *env, int csrno,
> > > + target_ulong *val)
> > > +{
> > > +CPUState *cs = env_cpu(env);
> > > +RISCVCPU *cpu = RISCV_CPU(cs);
> > > +
> > > +*val = cpu->cfg.mipid;
> > > +return RISCV_EXCP_NONE;
> > > +}
> > > +
> > >  static RISCVException read_mhartid(CPURISCVState *env, int csrno,
> > 

[PATCH] target/riscv: Support configuarable marchid, mvendorid, mipid CSR values

2022-04-15 Thread frank . chang
From: Frank Chang 

Allow user to set core's marchid, mvendorid, mipid CSRs through
-cpu command line option.

Signed-off-by: Frank Chang 
Reviewed-by: Jim Shu 
---
 target/riscv/cpu.c |  4 
 target/riscv/cpu.h |  4 
 target/riscv/csr.c | 38 ++
 3 files changed, 42 insertions(+), 4 deletions(-)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index ddda4906ff..2eea0f9be7 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -786,6 +786,10 @@ static Property riscv_cpu_properties[] = {
 DEFINE_PROP_UINT16("vlen", RISCVCPU, cfg.vlen, 128),
 DEFINE_PROP_UINT16("elen", RISCVCPU, cfg.elen, 64),
 
+DEFINE_PROP_UINT32("mvendorid", RISCVCPU, cfg.mvendorid, 0),
+DEFINE_PROP_UINT64("marchid", RISCVCPU, cfg.marchid, 0),
+DEFINE_PROP_UINT64("mipid", RISCVCPU, cfg.mipid, 0),
+
 DEFINE_PROP_BOOL("svinval", RISCVCPU, cfg.ext_svinval, false),
 DEFINE_PROP_BOOL("svnapot", RISCVCPU, cfg.ext_svnapot, false),
 DEFINE_PROP_BOOL("svpbmt", RISCVCPU, cfg.ext_svpbmt, false),
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index c069fe85fa..3ab92deb4b 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -370,6 +370,10 @@ struct RISCVCPUConfig {
 bool ext_zve32f;
 bool ext_zve64f;
 
+uint32_t mvendorid;
+uint64_t marchid;
+uint64_t mipid;
+
 /* Vendor-specific custom extensions */
 bool ext_XVentanaCondOps;
 
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 341c2e6f23..9a02038adb 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -603,6 +603,36 @@ static RISCVException write_ignore(CPURISCVState *env, int 
csrno,
 return RISCV_EXCP_NONE;
 }
 
+static RISCVException read_mvendorid(CPURISCVState *env, int csrno,
+ target_ulong *val)
+{
+CPUState *cs = env_cpu(env);
+RISCVCPU *cpu = RISCV_CPU(cs);
+
+*val = cpu->cfg.mvendorid;
+return RISCV_EXCP_NONE;
+}
+
+static RISCVException read_marchid(CPURISCVState *env, int csrno,
+   target_ulong *val)
+{
+CPUState *cs = env_cpu(env);
+RISCVCPU *cpu = RISCV_CPU(cs);
+
+*val = cpu->cfg.marchid;
+return RISCV_EXCP_NONE;
+}
+
+static RISCVException read_mipid(CPURISCVState *env, int csrno,
+ target_ulong *val)
+{
+CPUState *cs = env_cpu(env);
+RISCVCPU *cpu = RISCV_CPU(cs);
+
+*val = cpu->cfg.mipid;
+return RISCV_EXCP_NONE;
+}
+
 static RISCVException read_mhartid(CPURISCVState *env, int csrno,
target_ulong *val)
 {
@@ -3098,10 +3128,10 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
 [CSR_MINSTRETH] = { "minstreth", any32, read_instreth },
 
 /* Machine Information Registers */
-[CSR_MVENDORID] = { "mvendorid", any,   read_zero},
-[CSR_MARCHID]   = { "marchid",   any,   read_zero},
-[CSR_MIMPID]= { "mimpid",any,   read_zero},
-[CSR_MHARTID]   = { "mhartid",   any,   read_mhartid },
+[CSR_MVENDORID] = { "mvendorid", any,   read_mvendorid },
+[CSR_MARCHID]   = { "marchid",   any,   read_marchid   },
+[CSR_MIMPID]= { "mimpid",any,   read_mipid },
+[CSR_MHARTID]   = { "mhartid",   any,   read_mhartid   },
 
 /* Machine Trap Setup */
 [CSR_MSTATUS] = { "mstatus",any,   read_mstatus, 
write_mstatus, NULL,
-- 
2.35.1




Re: [PATCH] hw/riscv: virt: fix DT property mmu-type when CPU mmu option is disabled

2022-04-14 Thread Frank Chang
On Thu, Apr 14, 2022 at 11:57 PM Niklas Cassel via 
wrote:

> The device tree property "mmu-type" is currently exported as either
> "riscv,sv32" or "riscv,sv48".
>
> However, the riscv cpu device tree binding [1] has a specific value
> "riscv,none" for a HART without a MMU.
>
> Set the device tree property "mmu-type" to "riscv,none" when the CPU mmu
> option is disabled using rv32,mmu=off or rv64,mmu=off.
>
> [1]
> https://git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git/tree/Documentation/devicetree/bindings/riscv/cpus.yaml?h=v5.17
>
> Signed-off-by: Niklas Cassel 
> ---
>  hw/riscv/virt.c | 10 --
>  1 file changed, 8 insertions(+), 2 deletions(-)
>
> diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
> index da50cbed43..3be6be9ad3 100644
> --- a/hw/riscv/virt.c
> +++ b/hw/riscv/virt.c
> @@ -230,8 +230,14 @@ static void create_fdt_socket_cpus(RISCVVirtState *s,
> int socket,
>  cpu_name = g_strdup_printf("/cpus/cpu@%d",
>  s->soc[socket].hartid_base + cpu);
>  qemu_fdt_add_subnode(mc->fdt, cpu_name);
> -qemu_fdt_setprop_string(mc->fdt, cpu_name, "mmu-type",
> -(is_32_bit) ? "riscv,sv32" : "riscv,sv48");
> +if (riscv_feature(>soc[socket].harts[cpu].env,
> +  RISCV_FEATURE_MMU)) {
> +qemu_fdt_setprop_string(mc->fdt, cpu_name, "mmu-type",
> +(is_32_bit) ? "riscv,sv32" :
> "riscv,sv48");
> +} else {
> +qemu_fdt_setprop_string(mc->fdt, cpu_name, "mmu-type",
> +    "riscv,none");
> +}
>  name = riscv_isa_string(>soc[socket].harts[cpu]);
>  qemu_fdt_setprop_string(mc->fdt, cpu_name, "riscv,isa", name);
>  g_free(name);
> --
> 2.35.1
>
>
>
Reviewed-by: Frank Chang 


Re: [PATCH (PING) 1/1] target/riscv: misa to ISA string conversion fix

2022-03-27 Thread Frank Chang
On Mon, Mar 28, 2022 at 7:30 AM Alistair Francis 
wrote:

> On Sat, Mar 26, 2022 at 3:46 PM Tsukasa OI 
> wrote:
> >
> > Some bits in RISC-V `misa' CSR should not be reflected in the ISA
> > string.  For instance, `S' and `U' (represents existence of supervisor
> > and user mode, respectively) in `misa' CSR must not be copied since
> > neither `S' nor `U' are valid single-letter extensions.
>
> Thanks for the patch.
>
> >
> > This commit restricts which bits to copy from `misa' CSR to ISA string
> > with another fix: `C' extension should be preceded by `L' extension.
>
> The L extension has been removed, so it probably makes more sense to
> just remove it at this stage instead of fixing the order.
>
> >
> > It also clarifies that RISC-V extension order string is actually a
> > single-letter extension order list.
> >
> > Signed-off-by: Tsukasa OI 
> > ---
> >  target/riscv/cpu.c | 10 +-
> >  1 file changed, 5 insertions(+), 5 deletions(-)
> >
> > diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> > index ddda4906ff..84877cf24a 100644
> > --- a/target/riscv/cpu.c
> > +++ b/target/riscv/cpu.c
> > @@ -34,7 +34,7 @@
> >
> >  /* RISC-V CPU definitions */
> >
> > -static const char riscv_exts[26] = "IEMAFDQCLBJTPVNSUHKORWXYZG";
> > +static const char riscv_single_letter_exts[] = "IEMAFDQLCBJTPVNH";
>
> What about K?
>
> Why not use IEMAFDQCBKJTPVNH instead?
>
> Alistair
>

The RISC-V ISA Manual (version 20191213) is quite old.
Where "L" was not removed and "K" was not introduced.
It seems Unprivileged spec is not "ratified" as often as Privileged spec
does (most of them are drafts...).

But I agree that it's better to remove "L" and add "K" into ISA string.

Regards,
Frank Chang


>
> >
> >  const char * const riscv_int_regnames[] = {
> >"x0/zero", "x1/ra",  "x2/sp",  "x3/gp",  "x4/tp",  "x5/t0",   "x6/t1",
> > @@ -901,12 +901,12 @@ static void riscv_cpu_class_init(ObjectClass *c,
> void *data)
> >  char *riscv_isa_string(RISCVCPU *cpu)
> >  {
> >  int i;
> > -const size_t maxlen = sizeof("rv128") + sizeof(riscv_exts) + 1;
> > +const size_t maxlen = sizeof("rv128") +
> sizeof(riscv_single_letter_exts);
> >  char *isa_str = g_new(char, maxlen);
> >  char *p = isa_str + snprintf(isa_str, maxlen, "rv%d",
> TARGET_LONG_BITS);
> > -for (i = 0; i < sizeof(riscv_exts); i++) {
> > -if (cpu->env.misa_ext & RV(riscv_exts[i])) {
> > -*p++ = qemu_tolower(riscv_exts[i]);
> > +for (i = 0; i < sizeof(riscv_single_letter_exts) - 1; i++) {
> > +if (cpu->env.misa_ext & RV(riscv_single_letter_exts[i])) {
> > +*p++ = qemu_tolower(riscv_single_letter_exts[i]);
> >  }
> >  }
> >  *p = '\0';
> > --
> > 2.32.0
> >
> >
>
>


Re: [RFC PATCH 0/2] hw/riscv: Baseline QEMU support for RISC-V IOMMU (draft)

2022-03-25 Thread Frank Chang
Hi Tomasz,

Could you please send this patchset to qemu-ri...@nongnu.org, too?

Regards,
Frank Chang

On Thu, Mar 17, 2022 at 6:24 AM Tomasz Jeznach 
wrote:

> This is the series of patches to introduce RISC-V IOMMU emulation in QEMU.
>
> The Rivos IOMMU device implementation is based on a draft proposal of a
> RISC-V I/O Management Unit (IOMMU) [1] as published on 2022/03/10, shared
> and
> discussed with RISCV-V IOMMU Task Group [2].
>
> Specification is in *draft* stage and is expected to be changed based on
> discussion and feedback received from RISC-V IOMMU TG.
>
> This series enables rivos-iommu support for riscv/virt machine emulation.
> With corresponding Linux kernel driver and (modified) pending AIA-IMSIC
> support [3] QEMU is able to boot into Linux with I/O protection enabled for
> PCIe devices.  Without AIA-IMSIC support interrupt based I/O translation
> fault
> reporting and MSI remapping features are not available, while all remaining
> IOMMU features are active.
>
> To enable IOMMU in QEMU add 'rivos-iommu' to the device list for 'virt'
> machine
> emulation.
>
>
> [1]
> https://docs.google.com/document/d/1ytBZ6eDk1pAeBlZjDvm6_qqJbKQ0fMYKedyx0uoAGB0/view
> [2] https://lists.riscv.org/g/tech-iommu/message/3
> [3]
> https://lore.kernel.org/qemu-devel/20220220085526.808674-1-a...@brainfault.org
>
> Tomasz Jeznach (2):
>   hw/riscv: rivos-iommu: Baseline implementation of RIVOS IOMMU.
>   hw/riscv: virt: Add rivos-iommu device to 'virt' machine.
>
>  hw/riscv/Kconfig   |4 +
>  hw/riscv/meson.build   |1 +
>  hw/riscv/rivos_iommu.c | 1350 
>  hw/riscv/trace-events  |7 +
>  hw/riscv/trace.h   |2 +
>  hw/riscv/virt.c|  115 ++-
>  include/hw/pci/pci_ids.h   |1 +
>  include/hw/riscv/rivos_iommu.h |   80 ++
>  include/hw/riscv/virt.h|2 +
>  meson.build|1 +
>  10 files changed, 1539 insertions(+), 24 deletions(-)
>  create mode 100644 hw/riscv/rivos_iommu.c
>  create mode 100644 hw/riscv/trace-events
>  create mode 100644 hw/riscv/trace.h
>  create mode 100644 include/hw/riscv/rivos_iommu.h
>
> --
> 2.25.1
>
>
>


Re: [RFC PATCH 2/2] hw/riscv: virt: Add rivos-iommu device to 'virt' machine.

2022-03-25 Thread Frank Chang
Hi Tomasz,

I think this patch is trying to do two things:
1. Split riscv_load_kernel() and riscv_load_fdt() +
riscv_setup_rom_reset_vec()
to allow the devices to be added with -device or device_add(), which
DTB should
reflect the changes.
2. Allow IOMMU to be hotplugable to riscv vrit machine.

So, I think this patch could be split into two patches as described above.
And also add more comments in the commit message to describe why the changes
are required.

The following two commits are good examples for you,
which helps me understand why we need to move load_dtb() to machine done
notifier:
4576704: arm/boot: split load_dtb() from arm_load_kernel()
ac9d32e: hw/arm/boot: arm_load_kernel implemented as a machine init done
notifier

Regards,
Frank Chang

On Thu, Mar 17, 2022 at 6:24 AM Tomasz Jeznach 
wrote:

> Enable rivos-iommu device support in riscv:virt machine emulation.
>
> Signed-off-by: Tomasz Jeznach 
> ---
>  hw/riscv/Kconfig|   1 +
>  hw/riscv/virt.c | 115 +++-
>  include/hw/riscv/virt.h |   2 +
>  3 files changed, 94 insertions(+), 24 deletions(-)
>
> diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig
> index c6cbd7b42c..3b1528e560 100644
> --- a/hw/riscv/Kconfig
> +++ b/hw/riscv/Kconfig
> @@ -51,6 +51,7 @@ config RISCV_VIRT
>  select SIFIVE_TEST
>  select VIRTIO_MMIO
>  select FW_CFG_DMA
> +select RIVOS_IOMMU
>
>  config SIFIVE_E
>  bool
> diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
> index da50cbed43..13e6f03400 100644
> --- a/hw/riscv/virt.c
> +++ b/hw/riscv/virt.c
> @@ -32,6 +32,7 @@
>  #include "hw/riscv/virt.h"
>  #include "hw/riscv/boot.h"
>  #include "hw/riscv/numa.h"
> +#include "hw/riscv/rivos_iommu.h"
>  #include "hw/intc/riscv_aclint.h"
>  #include "hw/intc/riscv_aplic.h"
>  #include "hw/intc/riscv_imsic.h"
> @@ -948,6 +949,33 @@ static void create_fdt_flash(RISCVVirtState *s, const
> MemMapEntry *memmap)
>  g_free(name);
>  }
>
> +static void create_rivos_iommu_dt_binding(RISCVVirtState *s, uint16_t bdf)
> +{
> +const char compat[] = "rivos,pci-iommu";
> +MachineState *mc = MACHINE(s);
> +uint32_t iommu_phandle;
> +char *iommu_node;
> +char *pci_node;
> +
> +pci_node = g_strdup_printf("/soc/pci@%lx",
> +(long) virt_memmap[VIRT_PCIE_ECAM].base);
> +iommu_node = g_strdup_printf("%s/iommu@%x", pci_node, bdf);
> +
> +iommu_phandle = qemu_fdt_alloc_phandle(mc->fdt);
> +qemu_fdt_add_subnode(mc->fdt, iommu_node);
> +qemu_fdt_setprop(mc->fdt, iommu_node, "compatible", compat,
> sizeof(compat));
> +qemu_fdt_setprop_sized_cells(mc->fdt, iommu_node, "reg",
> +1, bdf << 8, 1, 0, 1, 0, 1, 0, 1, 0);
> +qemu_fdt_setprop_cell(mc->fdt, iommu_node, "#iommu-cells", 1);
> +qemu_fdt_setprop_cell(mc->fdt, iommu_node, "phandle", iommu_phandle);
> +g_free(iommu_node);
> +
> +qemu_fdt_setprop_cells(mc->fdt, pci_node, "iommu-map",
> +0x0, iommu_phandle, 0x0, bdf,
> +bdf + 1, iommu_phandle, bdf + 1, 0x - bdf);
> +g_free(pci_node);
> +}
> +
>  static void create_fdt(RISCVVirtState *s, const MemMapEntry *memmap,
> uint64_t mem_size, const char *cmdline, bool
> is_32_bit)
>  {
> @@ -1156,6 +1184,34 @@ static DeviceState
> *virt_create_aia(RISCVVirtAIAType aia_type, int aia_guests,
>  return aplic_m;
>  }
>
> +static void virt_machine_done(Notifier *notifier, void *data)
> +{
> +const MemMapEntry *memmap = virt_memmap;
> +uint32_t fdt_load_addr;
> +target_ulong start_addr = memmap[VIRT_DRAM].base;
> +RISCVVirtState *s = container_of(notifier, RISCVVirtState,
> machine_done);
> +MachineState *machine = MACHINE(s);
> +
> +/* Compute the fdt load address in dram */
> +fdt_load_addr = riscv_load_fdt(memmap[VIRT_DRAM].base,
> +   machine->ram_size, machine->fdt);
> +/* load the reset vector */
> +riscv_setup_rom_reset_vec(machine, >soc[0], start_addr,
> +  virt_memmap[VIRT_MROM].base,
> +  virt_memmap[VIRT_MROM].size,
> +  s->kernel_entry,
> +  fdt_load_addr, machine->fdt);
> +
> +/*
> + * Only direct boot kernel is currently supported for KVM VM,
> + * So here setup kernel start address and fdt address.
> + * TODO:Support firmware loading and integrate to TCG start
> + */
> +if (kvm_enabled()) {

Re: [PATCH 1/2] target/riscv: optimize condition assign for scale < 0

2022-03-25 Thread Frank Chang
Reviewed-by: Frank Chang 

On Fri, Mar 25, 2022 at 5:00 PM Weiwei Li  wrote:

> for some cases, scale is always equal or less than 0, since lmul is not
> larger than 3
>
> Signed-off-by: Weiwei Li 
> Signed-off-by: Junqiang Wang 
> ---
>  target/riscv/insn_trans/trans_rvv.c.inc | 8 +++-
>  1 file changed, 3 insertions(+), 5 deletions(-)
>
> diff --git a/target/riscv/insn_trans/trans_rvv.c.inc
> b/target/riscv/insn_trans/trans_rvv.c.inc
> index 4ea7e41e1a..2878ca3132 100644
> --- a/target/riscv/insn_trans/trans_rvv.c.inc
> +++ b/target/riscv/insn_trans/trans_rvv.c.inc
> @@ -1198,7 +1198,7 @@ GEN_LDST_WHOLE_TRANS(vs8r_v, 8, true)
>  static inline uint32_t MAXSZ(DisasContext *s)
>  {
>  int scale = s->lmul - 3;
> -return scale < 0 ? s->cfg_ptr->vlen >> -scale : s->cfg_ptr->vlen <<
> scale;
> +return s->cfg_ptr->vlen >> -scale;
>  }
>
>  static bool opivv_check(DisasContext *s, arg_rmrr *a)
> @@ -3597,8 +3597,7 @@ static bool trans_vrgather_vx(DisasContext *s,
> arg_rmrr *a)
>
>  if (a->vm && s->vl_eq_vlmax) {
>  int scale = s->lmul - (s->sew + 3);
> -int vlmax = scale < 0 ?
> -   s->cfg_ptr->vlen >> -scale : s->cfg_ptr->vlen <<
> scale;
> +int vlmax = s->cfg_ptr->vlen >> -scale;
>  TCGv_i64 dest = tcg_temp_new_i64();
>
>  if (a->rs1 == 0) {
> @@ -3630,8 +3629,7 @@ static bool trans_vrgather_vi(DisasContext *s,
> arg_rmrr *a)
>
>  if (a->vm && s->vl_eq_vlmax) {
>  int scale = s->lmul - (s->sew + 3);
> -int vlmax = scale < 0 ?
> -   s->cfg_ptr->vlen >> -scale : s->cfg_ptr->vlen <<
> scale;
> +int vlmax = s->cfg_ptr->vlen >> -scale;
>  if (a->rs1 >= vlmax) {
>  tcg_gen_gvec_dup_imm(MO_64, vreg_ofs(s, a->rd),
>   MAXSZ(s), MAXSZ(s), 0);
> --
> 2.17.1
>
>
>


Re: [PATCH 2/2] target/riscv: optimize helper for vmvr.v

2022-03-25 Thread Frank Chang
Reviewed-by: Frank Chang 

On Fri, Mar 25, 2022 at 5:00 PM Weiwei Li  wrote:

> LEN is not used for GEN_VEXT_VMV_WHOLE macro, so vmvr.v can share
> the same helper
>
> Signed-off-by: Weiwei Li 
> Signed-off-by: Junqiang Wang 
> ---
>  target/riscv/helper.h   |  5 +
>  target/riscv/insn_trans/trans_rvv.c.inc | 17 +--
>  target/riscv/vector_helper.c| 29 ++---
>  3 files changed, 18 insertions(+), 33 deletions(-)
>
> diff --git a/target/riscv/helper.h b/target/riscv/helper.h
> index 26bbab2fab..a669d0187b 100644
> --- a/target/riscv/helper.h
> +++ b/target/riscv/helper.h
> @@ -1086,10 +1086,7 @@ DEF_HELPER_6(vcompress_vm_h, void, ptr, ptr, ptr,
> ptr, env, i32)
>  DEF_HELPER_6(vcompress_vm_w, void, ptr, ptr, ptr, ptr, env, i32)
>  DEF_HELPER_6(vcompress_vm_d, void, ptr, ptr, ptr, ptr, env, i32)
>
> -DEF_HELPER_4(vmv1r_v, void, ptr, ptr, env, i32)
> -DEF_HELPER_4(vmv2r_v, void, ptr, ptr, env, i32)
> -DEF_HELPER_4(vmv4r_v, void, ptr, ptr, env, i32)
> -DEF_HELPER_4(vmv8r_v, void, ptr, ptr, env, i32)
> +DEF_HELPER_4(vmvr_v, void, ptr, ptr, env, i32)
>
>  DEF_HELPER_5(vzext_vf2_h, void, ptr, ptr, ptr, env, i32)
>  DEF_HELPER_5(vzext_vf2_w, void, ptr, ptr, ptr, env, i32)
> diff --git a/target/riscv/insn_trans/trans_rvv.c.inc
> b/target/riscv/insn_trans/trans_rvv.c.inc
> index 2878ca3132..ec7c0e0d36 100644
> --- a/target/riscv/insn_trans/trans_rvv.c.inc
> +++ b/target/riscv/insn_trans/trans_rvv.c.inc
> @@ -3695,7 +3695,7 @@ static bool trans_vcompress_vm(DisasContext *s,
> arg_r *a)
>   * Whole Vector Register Move Instructions ignore vtype and vl setting.
>   * Thus, we don't need to check vill bit. (Section 16.6)
>   */
> -#define GEN_VMV_WHOLE_TRANS(NAME, LEN, SEQ) \
> +#define GEN_VMV_WHOLE_TRANS(NAME, LEN) \
>  static bool trans_##NAME(DisasContext *s, arg_##NAME * a)   \
>  {   \
>  if (require_rvv(s) &&   \
> @@ -3710,13 +3710,8 @@ static bool trans_##NAME(DisasContext *s,
> arg_##NAME * a)   \
>  } else {\
>  TCGLabel *over = gen_new_label();   \
>  tcg_gen_brcondi_tl(TCG_COND_GEU, cpu_vstart, maxsz, over);  \
> -\
> -static gen_helper_gvec_2_ptr * const fns[4] = { \
> -gen_helper_vmv1r_v, gen_helper_vmv2r_v, \
> -gen_helper_vmv4r_v, gen_helper_vmv8r_v, \
> -};  \
>  tcg_gen_gvec_2_ptr(vreg_ofs(s, a->rd), vreg_ofs(s, a->rs2), \
> -   cpu_env, maxsz, maxsz, 0, fns[SEQ]); \
> +   cpu_env, maxsz, maxsz, 0,
> gen_helper_vmvr_v); \
>  mark_vs_dirty(s);   \
>  gen_set_label(over);\
>  }   \
> @@ -3725,10 +3720,10 @@ static bool trans_##NAME(DisasContext *s,
> arg_##NAME * a)   \
>  return false;   \
>  }
>
> -GEN_VMV_WHOLE_TRANS(vmv1r_v, 1, 0)
> -GEN_VMV_WHOLE_TRANS(vmv2r_v, 2, 1)
> -GEN_VMV_WHOLE_TRANS(vmv4r_v, 4, 2)
> -GEN_VMV_WHOLE_TRANS(vmv8r_v, 8, 3)
> +GEN_VMV_WHOLE_TRANS(vmv1r_v, 1)
> +GEN_VMV_WHOLE_TRANS(vmv2r_v, 2)
> +GEN_VMV_WHOLE_TRANS(vmv4r_v, 4)
> +GEN_VMV_WHOLE_TRANS(vmv8r_v, 8)
>
>  static bool int_ext_check(DisasContext *s, arg_rmr *a, uint8_t div)
>  {
> diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c
> index 3bd4aac9c9..1d4982ef7f 100644
> --- a/target/riscv/vector_helper.c
> +++ b/target/riscv/vector_helper.c
> @@ -4888,25 +4888,18 @@ GEN_VEXT_VCOMPRESS_VM(vcompress_vm_w, uint32_t, H4)
>  GEN_VEXT_VCOMPRESS_VM(vcompress_vm_d, uint64_t, H8)
>
>  /* Vector Whole Register Move */
> -#define GEN_VEXT_VMV_WHOLE(NAME, LEN)  \
> -void HELPER(NAME)(void *vd, void *vs2, CPURISCVState *env, \
> -  uint32_t desc)   \
> -{  \
> -/* EEW = 8 */  \
> -uint32_t maxsz = simd_maxsz(desc); \
> -uint32_t i = env->vstart;  \
> -  

Re: [PATCH v6] target/riscv: Add isa extenstion strings to the device tree

2022-03-17 Thread Frank Chang
On Thu, Mar 17, 2022 at 1:58 AM Atish Patra  wrote:

> The Linux kernel parses the ISA extensions from "riscv,isa" DT
> property. It used to parse only the single letter base extensions
> until now. A generic ISA extension parsing framework was proposed[1]
> recently that can parse multi-letter ISA extensions as well.
>
> Generate the extended ISA string by appending the available ISA extensions
> to the "riscv,isa" string if it is enabled so that kernel can process it.
>
> [1] https://lkml.org/lkml/2022/2/15/263
>
> Reviewed-by: Anup Patel 
> Reviewed-by: Alistair Francis 
> Suggested-by: Heiko Stubner 
> Signed-off-by: Atish Patra 
> ---
> Changes from v5->v6:
> 1. Improved commit message.
> 2. Fixed a typo for Zfh.
>
> Changes from v4->v5:
> 1. Fixed the order of Zxx extensions.
> 2. Added a comment clearly describing the rules of extension order.
>
> Changes from v3->v4:
> 1. Fixed the order of the extension names.
> 2. Added all the available ISA extensions in Qemu.
>
> Changes from v2->v3:
> 1. Used g_strconcat to replace snprintf & a max isa string length as
> suggested by Anup.
> 2. I have not included the Tested-by Tag from Heiko because the
> implementation changed from v2 to v3.
>
> Changes from v1->v2:
> 1. Improved the code redability by using arrays instead of individual check
> ---
>  target/riscv/cpu.c | 60 ++
>  1 file changed, 60 insertions(+)
>
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index ddda4906ffb7..937ccdda997b 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -34,6 +34,11 @@
>
>  /* RISC-V CPU definitions */
>
> +struct isa_ext_data {
> +const char *name;
> +bool enabled;
>

Nit: Should be 4 spaces indent.

Regards,
Frank Chang


> +};
> +
>  static const char riscv_exts[26] = "IEMAFDQCLBJTPVNSUHKORWXYZG";
>
>  const char * const riscv_int_regnames[] = {
> @@ -898,6 +903,60 @@ static void riscv_cpu_class_init(ObjectClass *c, void
> *data)
>  device_class_set_props(dc, riscv_cpu_properties);
>  }
>
> +#define ISA_EDATA_ENTRY(name, prop) {#name, cpu->cfg.prop}
> +
> +static void riscv_isa_string_ext(RISCVCPU *cpu, char **isa_str, int
> max_str_len)
> +{
> +char *old = *isa_str;
> +char *new = *isa_str;
> +int i;
> +
> +/**
> + * Here are the ordering rules of extension naming defined by RISC-V
> + * specification :
> + * 1. All extensions should be separated from from other multi-letter
> + *extensions by an underscore.
> + * 2. The first letter following the 'Z' conventionally indicates the
> most
> + *closely related alphabetical extension category,
> IMAFDQLCBKJTPVH.
> + *If multiple 'Z' extensions are named, they should be ordered
> first
> + *by category, then alphabetically within a category.
> + * 3. Standard supervisor-level extensions (starts with 'S') should be
> + *listed after standard unprivileged extensions.  If multiple
> + *supervisor-level extensions are listed, they should be ordered
> + *alphabetically.
> + * 4. Non-standard extensions (starts with 'X') must be listed after
> all
> + *standard extensions. They must be separated from other
> multi-letter
> + *extensions by an underscore.
> + */
> +struct isa_ext_data isa_edata_arr[] = {
> +ISA_EDATA_ENTRY(zfh, ext_zfh),
> +ISA_EDATA_ENTRY(zfhmin, ext_zfhmin),
> +ISA_EDATA_ENTRY(zfinx, ext_zfinx),
> +ISA_EDATA_ENTRY(zdinx, ext_zdinx),
> +ISA_EDATA_ENTRY(zba, ext_zba),
> +ISA_EDATA_ENTRY(zbb, ext_zbb),
> +ISA_EDATA_ENTRY(zbc, ext_zbc),
> +ISA_EDATA_ENTRY(zbs, ext_zbs),
> +ISA_EDATA_ENTRY(zve32f, ext_zve32f),
> +ISA_EDATA_ENTRY(zve64f, ext_zve64f),
> +ISA_EDATA_ENTRY(zhinx, ext_zhinx),
> +ISA_EDATA_ENTRY(zhinxmin, ext_zhinxmin),
> +ISA_EDATA_ENTRY(svinval, ext_svinval),
> +ISA_EDATA_ENTRY(svnapot, ext_svnapot),
> +ISA_EDATA_ENTRY(svpbmt, ext_svpbmt),
> +};
> +
> +for (i = 0; i < ARRAY_SIZE(isa_edata_arr); i++) {
> +if (isa_edata_arr[i].enabled) {
> +new = g_strconcat(old, "_", isa_edata_arr[i].name, NULL);
> +g_free(old);
> +old = new;
> +}
> +}
> +
> +*isa_str = new;
> +}
> +
>  char *riscv_isa_string(RISCVCPU *cpu)
>  {
>  int i;
> @@ -910,6 +969,7 @@ char *riscv_isa_string(RISCVCPU *cpu)
>  }
>  }
>  *p = '\0';
> +riscv_isa_string_ext(cpu, _str, maxlen);
>  return isa_str;
>  }
>
> --
> 2.25.1
>
>
>


Re: [PATCH v6] target/riscv: Add isa extenstion strings to the device tree

2022-03-17 Thread Frank Chang
On Thu, Mar 17, 2022 at 1:58 AM Atish Patra  wrote:

> The Linux kernel parses the ISA extensions from "riscv,isa" DT
> property. It used to parse only the single letter base extensions
> until now. A generic ISA extension parsing framework was proposed[1]
> recently that can parse multi-letter ISA extensions as well.
>
> Generate the extended ISA string by appending the available ISA extensions
> to the "riscv,isa" string if it is enabled so that kernel can process it.
>
> [1] https://lkml.org/lkml/2022/2/15/263
>
> Reviewed-by: Anup Patel 
> Reviewed-by: Alistair Francis 
> Suggested-by: Heiko Stubner 
> Signed-off-by: Atish Patra 
> ---
> Changes from v5->v6:
> 1. Improved commit message.
> 2. Fixed a typo for Zfh.
>
> Changes from v4->v5:
> 1. Fixed the order of Zxx extensions.
> 2. Added a comment clearly describing the rules of extension order.
>
> Changes from v3->v4:
> 1. Fixed the order of the extension names.
> 2. Added all the available ISA extensions in Qemu.
>
> Changes from v2->v3:
> 1. Used g_strconcat to replace snprintf & a max isa string length as
> suggested by Anup.
> 2. I have not included the Tested-by Tag from Heiko because the
> implementation changed from v2 to v3.
>
> Changes from v1->v2:
> 1. Improved the code redability by using arrays instead of individual check
> ---
>  target/riscv/cpu.c | 60 ++
>  1 file changed, 60 insertions(+)
>
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index ddda4906ffb7..937ccdda997b 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -34,6 +34,11 @@
>
>  /* RISC-V CPU definitions */
>
> +struct isa_ext_data {
> +const char *name;
> +bool enabled;
> +};
> +
>  static const char riscv_exts[26] = "IEMAFDQCLBJTPVNSUHKORWXYZG";
>
>  const char * const riscv_int_regnames[] = {
> @@ -898,6 +903,60 @@ static void riscv_cpu_class_init(ObjectClass *c, void
> *data)
>  device_class_set_props(dc, riscv_cpu_properties);
>  }
>
> +#define ISA_EDATA_ENTRY(name, prop) {#name, cpu->cfg.prop}
> +
> +static void riscv_isa_string_ext(RISCVCPU *cpu, char **isa_str, int
> max_str_len)
> +{
> +char *old = *isa_str;
> +char *new = *isa_str;
> +int i;
> +
> +/**
> + * Here are the ordering rules of extension naming defined by RISC-V
> + * specification :
> + * 1. All extensions should be separated from from other multi-letter
> + *extensions by an underscore.
> + * 2. The first letter following the 'Z' conventionally indicates the
> most
> + *closely related alphabetical extension category,
> IMAFDQLCBKJTPVH.
> + *If multiple 'Z' extensions are named, they should be ordered
> first
> + *by category, then alphabetically within a category.
> + * 3. Standard supervisor-level extensions (starts with 'S') should be
> + *listed after standard unprivileged extensions.  If multiple
> + *supervisor-level extensions are listed, they should be ordered
> + *alphabetically.
> + * 4. Non-standard extensions (starts with 'X') must be listed after
> all
> + *standard extensions. They must be separated from other
> multi-letter
> + *extensions by an underscore.
> + */
> +struct isa_ext_data isa_edata_arr[] = {
> +ISA_EDATA_ENTRY(zfh, ext_zfh),
> +ISA_EDATA_ENTRY(zfhmin, ext_zfhmin),
> +ISA_EDATA_ENTRY(zfinx, ext_zfinx),
> +ISA_EDATA_ENTRY(zdinx, ext_zdinx),
> +ISA_EDATA_ENTRY(zba, ext_zba),
> +ISA_EDATA_ENTRY(zbb, ext_zbb),
> +ISA_EDATA_ENTRY(zbc, ext_zbc),
> +ISA_EDATA_ENTRY(zbs, ext_zbs),
> +ISA_EDATA_ENTRY(zve32f, ext_zve32f),
> +ISA_EDATA_ENTRY(zve64f, ext_zve64f),
> +ISA_EDATA_ENTRY(zhinx, ext_zhinx),
> +ISA_EDATA_ENTRY(zhinxmin, ext_zhinxmin),
> +ISA_EDATA_ENTRY(svinval, ext_svinval),
> +ISA_EDATA_ENTRY(svnapot, ext_svnapot),
> +ISA_EDATA_ENTRY(svpbmt, ext_svpbmt),
> +};
> +
> +for (i = 0; i < ARRAY_SIZE(isa_edata_arr); i++) {
> +if (isa_edata_arr[i].enabled) {
> +new = g_strconcat(old, "_", isa_edata_arr[i].name, NULL);
> +g_free(old);
> +old = new;
> +}
> +}
> +
> +*isa_str = new;
> +}
> +
>  char *riscv_isa_string(RISCVCPU *cpu)
>  {
>  int i;
> @@ -910,6 +969,7 @@ char *riscv_isa_string(RISCVCPU *cpu)
>  }
>  }
>  *p = '\0';
> +riscv_isa_string_ext(cpu, _str, maxlen);
>  return isa_str;
>  }
>
> --
> 2.25.1
>
>
>
Reviewed-by: Frank Chang 


Re: [PATCH v6 08/12] target/riscv: Add sscofpmf extension support

2022-03-17 Thread Frank Chang
gt; diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
> index 48b39e6d52a7..da78e2704081 100644
> --- a/target/riscv/cpu_bits.h
> +++ b/target/riscv/cpu_bits.h
> @@ -400,6 +400,37 @@
>  #define CSR_MHPMEVENT29 0x33d
>  #define CSR_MHPMEVENT30 0x33e
>  #define CSR_MHPMEVENT31 0x33f
> +
> +#define CSR_MHPMEVENT3H 0x723
> +#define CSR_MHPMEVENT4H 0x724
> +#define CSR_MHPMEVENT5H 0x725
> +#define CSR_MHPMEVENT6H 0x726
> +#define CSR_MHPMEVENT7H 0x727
> +#define CSR_MHPMEVENT8H 0x728
> +#define CSR_MHPMEVENT9H 0x729
> +#define CSR_MHPMEVENT10H0x72a
> +#define CSR_MHPMEVENT11H0x72b
> +#define CSR_MHPMEVENT12H0x72c
> +#define CSR_MHPMEVENT13H0x72d
> +#define CSR_MHPMEVENT14H0x72e
> +#define CSR_MHPMEVENT15H0x72f
> +#define CSR_MHPMEVENT16H0x730
> +#define CSR_MHPMEVENT17H0x731
> +#define CSR_MHPMEVENT18H0x732
> +#define CSR_MHPMEVENT19H0x733
> +#define CSR_MHPMEVENT20H0x734
> +#define CSR_MHPMEVENT21H0x735
> +#define CSR_MHPMEVENT22H0x736
> +#define CSR_MHPMEVENT23H0x737
> +#define CSR_MHPMEVENT24H0x738
> +#define CSR_MHPMEVENT25H0x739
> +#define CSR_MHPMEVENT26H0x73a
> +#define CSR_MHPMEVENT27H0x73b
> +#define CSR_MHPMEVENT28H0x73c
> +#define CSR_MHPMEVENT29H0x73d
> +#define CSR_MHPMEVENT30H0x73e
> +#define CSR_MHPMEVENT31H0x73f
> +
>  #define CSR_MHPMCOUNTER3H   0xb83
>  #define CSR_MHPMCOUNTER4H   0xb84
>  #define CSR_MHPMCOUNTER5H   0xb85
> @@ -461,6 +492,7 @@
>  #define CSR_VSMTE   0x2c0
>  #define CSR_VSPMMASK0x2c1
>  #define CSR_VSPMBASE0x2c2
> +#define CSR_SCOUNTOVF   0xda0
>
>  /* mstatus CSR bits */
>  #define MSTATUS_UIE 0x0001
> @@ -635,6 +667,7 @@ typedef enum RISCVException {
>  #define IRQ_VS_EXT 10
>  #define IRQ_M_EXT  11
>  #define IRQ_S_GEXT 12
> +#define IRQ_PMU_OVF13
>  #define IRQ_LOCAL_MAX  16
>  #define IRQ_LOCAL_GUEST_MAX(TARGET_LONG_BITS - 1)
>
> @@ -652,11 +685,13 @@ typedef enum RISCVException {
>  #define MIP_VSEIP  (1 << IRQ_VS_EXT)
>  #define MIP_MEIP   (1 << IRQ_M_EXT)
>  #define MIP_SGEIP  (1 << IRQ_S_GEXT)
> +#define MIP_LCOFIP (1 << IRQ_PMU_OVF)
>
>  /* sip masks */
>  #define SIP_SSIP   MIP_SSIP
>  #define SIP_STIP   MIP_STIP
>  #define SIP_SEIP   MIP_SEIP
> +#define SIP_LCOFIP MIP_LCOFIP
>
>  /* MIE masks */
>  #define MIE_SEIE   (1 << IRQ_S_EXT)
> @@ -804,4 +839,24 @@ typedef enum RISCVException {
>  #define HVICTL_VALID_MASK  \
>  (HVICTL_VTI | HVICTL_IID | HVICTL_IPRIOM | HVICTL_IPRIO)
>
> +/* PMU related bits */
> +#define MIE_LCOFIE (1 << IRQ_PMU_OVF)
> +
> +#define MHPMEVENT_BIT_OF   BIT(63)
>

Hi Atish,

I think it's better to use BIT_ULL() for value >= 32.
BIT() is defined to: (1UL << (nr)),
which might cause the overflow issue on some platforms (e.g. Windows).

Regards,
Frank Chang

+#define MHPMEVENTH_BIT_OF  BIT(31)
> +#define MHPMEVENT_BIT_MINH BIT(62)
> +#define MHPMEVENTH_BIT_MINHBIT(30)
> +#define MHPMEVENT_BIT_SINH BIT(61)
> +#define MHPMEVENTH_BIT_SINHBIT(29)
> +#define MHPMEVENT_BIT_UINH BIT(60)
> +#define MHPMEVENTH_BIT_UINHBIT(28)
> +#define MHPMEVENT_BIT_VSINHBIT(59)
> +#define MHPMEVENTH_BIT_VSINH   BIT(27)
> +#define MHPMEVENT_BIT_VUINHBIT(58)
> +#define MHPMEVENTH_BIT_VUINH   BIT(26)
> +
> +#define MHPMEVENT_SSCOF_MASK   _ULL(0x)
> +#define MHPMEVENT_IDX_MASK 0xF
> +#define MHPMEVENT_SSCOF_RESVD  16
> +
>  #endif
> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> index 3286e1e44455..cfcc1a0882d9 100644
> --- a/target/riscv/csr.c
> +++ b/target/riscv/csr.c
> @@ -96,13 +96,26 @@ static RISCVException mctr32(CPURISCVState *env, int
> csrno)
>  return mctr(env, csrno);
>  }
>
> +static RISCVException sscofpmf(CPURISCVState *env, int csrno)
> +{
> + #if !defined(CONFIG_USER_ONLY)
> +CPUState *cs = env_cpu(env);
> +RISCVCPU *cpu = RISCV_CPU(cs);
> +
> +if (!cpu->cfg.ext_sscofpmf) {
> +return RISCV_EXCP_ILLEGAL_INST;
> +}
> +#endif
> +retur

Re: [PATCH v6 10/12] target/riscv: Add few cache related PMU events

2022-03-15 Thread Frank Chang
On Fri, Mar 4, 2022 at 8:11 AM Atish Patra  wrote:

> From: Atish Patra 
>
> Qemu can monitor the following cache related PMU events through
> tlb_fill functions.
>
> 1. DTLB load/store miss
> 3. ITLB prefetch miss
>
> Increment the PMU counter in tlb_fill function.
>
> Reviewed-by: Alistair Francis 
> Signed-off-by: Atish Patra 
> Signed-off-by: Atish Patra 
> ---
>  target/riscv/cpu_helper.c | 26 ++
>  1 file changed, 26 insertions(+)
>
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index 1c60fb2e8057..72ae1a612ae8 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -21,10 +21,13 @@
>  #include "qemu/log.h"
>  #include "qemu/main-loop.h"
>  #include "cpu.h"
> +#include "pmu.h"
>  #include "exec/exec-all.h"
>  #include "tcg/tcg-op.h"
>  #include "trace.h"
>  #include "semihosting/common-semi.h"
> +#include "cpu.h"
>

Redundant: #include "cpu.h"

Regards,
Frank Chang


> +#include "cpu_bits.h"
>
>  int riscv_cpu_mmu_index(CPURISCVState *env, bool ifetch)
>  {
> @@ -1178,6 +1181,28 @@ void riscv_cpu_do_unaligned_access(CPUState *cs,
> vaddr addr,
>  riscv_raise_exception(env, cs->exception_index, retaddr);
>  }
>
> +
> +static void pmu_tlb_fill_incr_ctr(RISCVCPU *cpu, MMUAccessType
> access_type)
> +{
> +enum riscv_pmu_event_idx pmu_event_type;
> +
> +switch (access_type) {
> +case MMU_INST_FETCH:
> +pmu_event_type = RISCV_PMU_EVENT_CACHE_ITLB_PREFETCH_MISS;
> +break;
> +case MMU_DATA_LOAD:
> +pmu_event_type = RISCV_PMU_EVENT_CACHE_DTLB_READ_MISS;
> +break;
> +case MMU_DATA_STORE:
> +pmu_event_type = RISCV_PMU_EVENT_CACHE_DTLB_WRITE_MISS;
> +break;
> +default:
> +return;
> +}
> +
> +riscv_pmu_incr_ctr(cpu, pmu_event_type);
> +}
> +
>  bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
>  MMUAccessType access_type, int mmu_idx,
>  bool probe, uintptr_t retaddr)
> @@ -1274,6 +1299,7 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address,
> int size,
>  }
>  }
>  } else {
> +pmu_tlb_fill_incr_ctr(cpu, access_type);
>  /* Single stage lookup */
>  ret = get_physical_address(env, , , address, NULL,
> access_type, mmu_idx, true, false,
> false);
> --
> 2.30.2
>
>
>


Re: [PATCH v6 06/12] target/riscv: Add support for hpmcounters/hpmevents

2022-03-15 Thread Frank Chang
nterh },
> +[CSR_HPMCOUNTER6H]   = { "hpmcounter6h",   ctr32,  read_hpmcounterh },
> +[CSR_HPMCOUNTER7H]   = { "hpmcounter7h",   ctr32,  read_hpmcounterh },
> +[CSR_HPMCOUNTER8H]   = { "hpmcounter8h",   ctr32,  read_hpmcounterh },
> +[CSR_HPMCOUNTER9H]   = { "hpmcounter9h",   ctr32,  read_hpmcounterh },
> +[CSR_HPMCOUNTER10H]  = { "hpmcounter10h",  ctr32,  read_hpmcounterh },
> +[CSR_HPMCOUNTER11H]  = { "hpmcounter11h",  ctr32,  read_hpmcounterh },
> +[CSR_HPMCOUNTER12H]  = { "hpmcounter12h",  ctr32,  read_hpmcounterh },
> +[CSR_HPMCOUNTER13H]  = { "hpmcounter13h",  ctr32,  read_hpmcounterh },
> +[CSR_HPMCOUNTER14H]  = { "hpmcounter14h",  ctr32,  read_hpmcounterh },
> +[CSR_HPMCOUNTER15H]  = { "hpmcounter15h",  ctr32,  read_hpmcounterh },
> +[CSR_HPMCOUNTER16H]  = { "hpmcounter16h",  ctr32,  read_hpmcounterh },
> +[CSR_HPMCOUNTER17H]  = { "hpmcounter17h",  ctr32,  read_hpmcounterh },
> +[CSR_HPMCOUNTER18H]  = { "hpmcounter18h",  ctr32,  read_hpmcounterh },
> +[CSR_HPMCOUNTER19H]  = { "hpmcounter19h",  ctr32,  read_hpmcounterh },
> +[CSR_HPMCOUNTER20H]  = { "hpmcounter20h",  ctr32,  read_hpmcounterh },
> +[CSR_HPMCOUNTER21H]  = { "hpmcounter21h",  ctr32,  read_hpmcounterh },
> +[CSR_HPMCOUNTER22H]  = { "hpmcounter22h",  ctr32,  read_hpmcounterh },
> +[CSR_HPMCOUNTER23H]  = { "hpmcounter23h",  ctr32,  read_hpmcounterh },
> +[CSR_HPMCOUNTER24H]  = { "hpmcounter24h",  ctr32,  read_hpmcounterh },
> +[CSR_HPMCOUNTER25H]  = { "hpmcounter25h",  ctr32,  read_hpmcounterh },
> +[CSR_HPMCOUNTER26H]  = { "hpmcounter26h",  ctr32,  read_hpmcounterh },
> +[CSR_HPMCOUNTER27H]  = { "hpmcounter27h",  ctr32,  read_hpmcounterh },
> +[CSR_HPMCOUNTER28H]  = { "hpmcounter28h",  ctr32,  read_hpmcounterh },
> +[CSR_HPMCOUNTER29H]  = { "hpmcounter29h",  ctr32,  read_hpmcounterh },
> +[CSR_HPMCOUNTER30H]  = { "hpmcounter30h",  ctr32,  read_hpmcounterh },
> +[CSR_HPMCOUNTER31H]  = { "hpmcounter31h",  ctr32,  read_hpmcounterh },
> +
> +[CSR_MHPMCOUNTER3H]  = { "mhpmcounter3h",  mctr32,  read_hpmcounterh,
> +   write_mhpmcounterh
> },
> +[CSR_MHPMCOUNTER4H]  = { "mhpmcounter4h",  mctr32,  read_hpmcounterh,
> +   write_mhpmcounterh
> },
> +[CSR_MHPMCOUNTER5H]  = { "mhpmcounter5h",  mctr32,  read_hpmcounterh,
> +   write_mhpmcounterh
> },
> +[CSR_MHPMCOUNTER6H]  = { "mhpmcounter6h",  mctr32,  read_hpmcounterh,
> +   write_mhpmcounterh
> },
> +[CSR_MHPMCOUNTER7H]  = { "mhpmcounter7h",  mctr32,  read_hpmcounterh,
> +   write_mhpmcounterh
> },
> +[CSR_MHPMCOUNTER8H]  = { "mhpmcounter8h",  mctr32,  read_hpmcounterh,
> +   write_mhpmcounterh
> },
> +[CSR_MHPMCOUNTER9H]  = { "mhpmcounter9h",  mctr32,  read_hpmcounterh,
> +   write_mhpmcounterh
> },
> +[CSR_MHPMCOUNTER10H] = { "mhpmcounter10h", mctr32,  read_hpmcounterh,
> +   write_mhpmcounterh
> },
> +[CSR_MHPMCOUNTER11H] = { "mhpmcounter11h", mctr32,  read_hpmcounterh,
> +   write_mhpmcounterh
> },
> +[CSR_MHPMCOUNTER12H] = { "mhpmcounter12h", mctr32,  read_hpmcounterh,
> +   write_mhpmcounterh
> },
> +[CSR_MHPMCOUNTER13H] = { "mhpmcounter13h", mctr32,  read_hpmcounterh,
> +   write_mhpmcounterh
> },
> +[CSR_MHPMCOUNTER14H] = { "mhpmcounter14h", mctr32,  read_hpmcounterh,
> +   write_mhpmcounterh
> },
> +[CSR_MHPMCOUNTER15H] = { "mhpmcounter15h", mctr32,  read_hpmcounterh,
> +   write_mhpmcounterh
> },
> +[CSR_MHPMCOUNTER16H] = { "mhpmcounter16h", mctr32,  read_hpmcounterh,
> +   write_mhpmcounterh
> },
> +[CSR_MHPMCOUNTER17H] = { "mhpmcounter17h", mctr32,  read_hpmcounterh,
> +   write_mhpmcounterh
> },
> +[CSR_MHPMCOUNTER18H] = { "mhpmcounter18h", mctr32,  read_hpmcounterh,
> +   write_mhpmcounterh
> },
> +[CSR_MHPMCOUNTER19H] = { "mhpmcounter19h", mctr32,  read_hpmcounterh,
> +   write_mhpmcounterh
> },
> +[CSR_MHPMCOUNTER20H] = { "mhpmcounter20h", mctr32,  read_hpmcounterh,
> +   write_mhpmcounterh
> },
> +[CSR_MHPMCOUNTER21H] = { "mhpmcounter21h", mctr32,  read_hpmcounterh,
> +   write_mhpmcounterh
> },
> +[CSR_MHPMCOUNTER22H] = { "mhpmcounter22h", mctr32,  read_hpmcounterh,
> +   write_mhpmcounterh
> },
> +[CSR_MHPMCOUNTER23H] = { "mhpmcounter23h", mctr32,  read_hpmcounterh,
> +   write_mhpmcounterh
> },
> +[CSR_MHPMCOUNTER24H] = { "mhpmcounter24h", mctr32,  read_hpmcounterh,
> +   write_mhpmcounterh
> },
> +[CSR_MHPMCOUNTER25H] = { "mhpmcounter25h", mctr32,  read_hpmcounterh,
> +   write_mhpmcounterh
> },
> +[CSR_MHPMCOUNTER26H] = { "mhpmcounter26h", mctr32,  read_hpmcounterh,
> +   write_mhpmcounterh
> },
> +[CSR_MHPMCOUNTER27H] = { "mhpmcounter27h", mctr32,  read_hpmcounterh,
> +   write_mhpmcounterh
> },
> +[CSR_MHPMCOUNTER28H] = { "mhpmcounter28h", mctr32,  read_hpmcounterh,
> +   write_mhpmcounterh
> },
> +[CSR_MHPMCOUNTER29H] = { "mhpmcounter29h", mctr32,  read_hpmcounterh,
> +   write_mhpmcounterh
> },
> +[CSR_MHPMCOUNTER30H] = { "mhpmcounter30h", mctr32,  read_hpmcounterh,
> +   write_mhpmcounterh
> },
> +[CSR_MHPMCOUNTER31H] = { "mhpmcounter31h", mctr32,  read_hpmcounterh,
> +   write_mhpmcounterh
> },
>  #endif /* !CONFIG_USER_ONLY */
>  };
> diff --git a/target/riscv/machine.c b/target/riscv/machine.c
> index 2a48bcf81d3d..d706a97e65c8 100644
> --- a/target/riscv/machine.c
> +++ b/target/riscv/machine.c
> @@ -300,6 +300,9 @@ const VMStateDescription vmstate_riscv_cpu = {
>  VMSTATE_UINTTL(env.scounteren, RISCVCPU),
>  VMSTATE_UINTTL(env.mcounteren, RISCVCPU),
>  VMSTATE_UINTTL(env.mcountinhibit, RISCVCPU),
> +VMSTATE_UINTTL_ARRAY(env.mhpmcounter_val, RISCVCPU,
> RV_MAX_MHPMCOUNTERS),
> +VMSTATE_UINTTL_ARRAY(env.mhpmcounterh_val, RISCVCPU,
> RV_MAX_MHPMCOUNTERS),
> +VMSTATE_UINTTL_ARRAY(env.mhpmevent_val, RISCVCPU,
> RV_MAX_MHPMEVENTS),
>  VMSTATE_UINTTL(env.sscratch, RISCVCPU),
>  VMSTATE_UINTTL(env.mscratch, RISCVCPU),
>  VMSTATE_UINT64(env.mfromhost, RISCVCPU),
> --
> 2.30.2
>
>
>
Hi Atish,

I encountered the compilation error when compiling user-mode QEMU
checked out from the branch in your repo:
error: ‘CPURISCVState {aka struct CPURISCVState}’ has no member named
‘mhpmevent_val’
error: ‘CPURISCVState {aka struct CPURISCVState}’ has no member named
‘mhpmeventh_val’
error: ‘CPURISCVState {aka struct CPURISCVState}’ has no member named
‘pmu_ctrs’
error: ‘CPURISCVState {aka struct CPURISCVState}’ has no member named ‘priv’
error: ‘CPURISCVState {aka struct CPURISCVState}’ has no member named
‘mcounteren’

Also, some functions are defined but not used in user-mode QEMU:
error: ‘read_scountovf’ defined but not used [-Werror=unused-function]
error: ‘write_mhpmcounterh’ defined but not used [-Werror=unused-function]
error: ‘write_mhpmcounter’ defined but not used [-Werror=unused-function]
... etc

I think you need to add the #if !defined(CONFIG_USER_ONLY) macros
to prevent using the variables which are available only in system-mode QEMU
and excluding the functions which are called only in system-mode QEMU.

Regards,
Frank Chang


Re: [PATCH v4] target/riscv: Add isa extenstion strings to the device tree

2022-03-10 Thread Frank Chang
On Fri, Mar 11, 2022 at 2:42 AM Atish Kumar Patra 
wrote:

> On Wed, Mar 9, 2022 at 5:47 AM Frank Chang  wrote:
> >
> > Atish Patra  於 2022年3月9日 週三 上午8:53寫道:
> >>
> >> The Linux kernel parses the ISA extensions from "riscv,isa" DT
> >> property. It used to parse only the single letter base extensions
> >> until now. A generic ISA extension parsing framework was proposed[1]
> >> recently that can parse multi-letter ISA extensions as well.
> >>
> >> Generate the extended ISA string by appending  the available ISA
> extensions
> >> to the "riscv,isa" string if it is enabled so that kernel can process
> it.
> >>
> >> [1] https://lkml.org/lkml/2022/2/15/263
> >>
> >> Reviewed-by: Anup Patel 
> >> Reviewed-by: Alistair Francis 
> >> Suggested-by: Heiko Stubner 
> >> Signed-off-by: Atish Patra 
> >> ---
> >>
> >> Changes from v3->v4:
> >> 1. Fixed the order of the extension names.
> >> 2. Added all the available ISA extensions in Qemu.
> >>
> >> Changes from v2->v3:
> >> 1. Used g_strconcat to replace snprintf & a max isa string length as
> >> suggested by Anup.
> >> 2. I have not included the Tested-by Tag from Heiko because the
> >> implementation changed from v2 to v3.
> >>
> >> Changes from v1->v2:
> >> 1. Improved the code redability by using arrays instead of individual
> check
> >> ---
> >>  target/riscv/cpu.c | 43 +++
> >>  1 file changed, 43 insertions(+)
> >>
> >> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> >> index ddda4906ffb7..2521a6f31f9f 100644
> >> --- a/target/riscv/cpu.c
> >> +++ b/target/riscv/cpu.c
> >> @@ -34,6 +34,12 @@
> >>
> >>  /* RISC-V CPU definitions */
> >>
> >> +/* This includes the null terminated character '\0' */
> >> +struct isa_ext_data {
> >> +const char *name;
> >> +bool enabled;
> >> +};
> >> +
> >>  static const char riscv_exts[26] = "IEMAFDQCLBJTPVNSUHKORWXYZG";
> >>
> >>  const char * const riscv_int_regnames[] = {
> >> @@ -898,6 +904,42 @@ static void riscv_cpu_class_init(ObjectClass *c,
> void *data)
> >>  device_class_set_props(dc, riscv_cpu_properties);
> >>  }
> >>
> >> +#define ISA_EDATA_ENTRY(name, prop) {#name, cpu->cfg.prop}
> >> +
> >> +static void riscv_isa_string_ext(RISCVCPU *cpu, char **isa_str, int
> max_str_len)
> >> +{
> >> +char *old = *isa_str;
> >> +char *new = *isa_str;
> >> +int i;
> >> +struct isa_ext_data isa_edata_arr[] = {
> >> +ISA_EDATA_ENTRY(svinval, ext_svinval),
> >> +ISA_EDATA_ENTRY(svnapot, ext_svnapot),
> >> +ISA_EDATA_ENTRY(svpbmt, ext_svpbmt),
> >> +ISA_EDATA_ENTRY(zba, ext_zba),
> >> +ISA_EDATA_ENTRY(zbb, ext_zbb),
> >> +ISA_EDATA_ENTRY(zbc, ext_zbc),
> >> +ISA_EDATA_ENTRY(zbs, ext_zbs),
> >> +ISA_EDATA_ENTRY(zdinx, ext_zdinx),
> >> +ISA_EDATA_ENTRY(zfh, ext_zfhmin),
> >> +ISA_EDATA_ENTRY(zfhmin, ext_zfhmin),
> >> +ISA_EDATA_ENTRY(zfinx, ext_zfinx),
> >> +ISA_EDATA_ENTRY(zhinx, ext_zhinx),
> >> +ISA_EDATA_ENTRY(zhinxmin, ext_zhinxmin),
> >> +ISA_EDATA_ENTRY(zve32f, ext_zve32f),
> >> +ISA_EDATA_ENTRY(zve64f, ext_zve64f),
> >> +};
> >
> >
> > Hi Atish,
> >
> > According to RISC-V Unpriviledge spec, Section 28.6:
> > https://github.com/riscv/riscv-isa-manual/blob/master/src/naming.tex#L85
> >
> > "The first letter following the “Z” conventionally indicates the most
> closely
> > related alphabetical extension category, IMAFDQLCBKJTPV.
> > For the “Zam” extension for misaligned atomics,
> > for example, the letter “a” indicates the extension is related to the
> “A” standard extension.
> > If multiple “Z” extensions are named, they should be ordered first by
> category,
> > then alphabetically within a category—for example, “Zicsr Zifencei Zam”."
> >
>
> Yes. Sorry I missed that part. Will fix it.
>
> > So I think the order of "Z" extensions should be:
> > zfh, zfhmin, zfinx, zdinx, zba, zbb, zbc, zbs, zve32f, zve64f, zhinx,
> zhinxmin
> >
> > Also, I think "Zifencei" and "Zicsr" should also be co

Re: [PATCH 1/1] target/riscv: misa to ISA string conversion fix

2022-03-09 Thread Frank Chang
Tsukasa OI  於 2022年2月12日 週六 下午10:55寫道:

> Some bits in RISC-V `misa' CSR should not be reflected in the ISA
> string.  For instance, `S' and `U' (represents existence of supervisor
> and user mode, respectively) in `misa' CSR must not be copied since
> neither `S' nor `U' are valid single-letter extensions.
>
> This commit restricts which bits to copy from `misa' CSR to ISA string
> with another fix: `C' extension should be preceded by `L' extension.
>
> It also clarifies that RISC-V extension order string is actually a
> single-letter extension order list.
>
> Signed-off-by: Tsukasa OI 
> ---
>  target/riscv/cpu.c | 10 +-
>  1 file changed, 5 insertions(+), 5 deletions(-)
>
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index 1cb0436187..7a8d6ce104 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -34,7 +34,7 @@
>
>  /* RISC-V CPU definitions */
>
> -static const char riscv_exts[26] = "IEMAFDQCLBJTPVNSUHKORWXYZG";
> +static const char riscv_single_letter_exts[] = "IEMAFDQLCBJTPVNH";
>
>  const char * const riscv_int_regnames[] = {
>"x0/zero", "x1/ra",  "x2/sp",  "x3/gp",  "x4/tp",  "x5/t0",   "x6/t1",
> @@ -831,12 +831,12 @@ static void riscv_cpu_class_init(ObjectClass *c,
> void *data)
>  char *riscv_isa_string(RISCVCPU *cpu)
>  {
>  int i;
> -const size_t maxlen = sizeof("rv128") + sizeof(riscv_exts) + 1;
> +const size_t maxlen = sizeof("rv128") +
> sizeof(riscv_single_letter_exts);
>  char *isa_str = g_new(char, maxlen);
>  char *p = isa_str + snprintf(isa_str, maxlen, "rv%d",
> TARGET_LONG_BITS);
> -for (i = 0; i < sizeof(riscv_exts); i++) {
> -if (cpu->env.misa_ext & RV(riscv_exts[i])) {
> -*p++ = qemu_tolower(riscv_exts[i]);
> +for (i = 0; i < sizeof(riscv_single_letter_exts) - 1; i++) {
> +if (cpu->env.misa_ext & RV(riscv_single_letter_exts[i])) {
> +*p++ = qemu_tolower(riscv_single_letter_exts[i]);
>  }
>  }
>  *p = '\0';
> --
> 2.32.0
>
>
Reviewed-by: Frank Chang 

BTW, could you please send this patchset again to both
qemu-devel@nongnu.org and qemu-ri...@nongnu.org
just like what Atish suggested?
https://www.mail-archive.com/qemu-devel@nongnu.org/msg874776.html


Re: [PATCH v4] target/riscv: Add isa extenstion strings to the device tree

2022-03-09 Thread Frank Chang
Atish Patra  於 2022年3月9日 週三 上午8:53寫道:

> The Linux kernel parses the ISA extensions from "riscv,isa" DT
> property. It used to parse only the single letter base extensions
> until now. A generic ISA extension parsing framework was proposed[1]
> recently that can parse multi-letter ISA extensions as well.
>
> Generate the extended ISA string by appending  the available ISA extensions
> to the "riscv,isa" string if it is enabled so that kernel can process it.
>
> [1] https://lkml.org/lkml/2022/2/15/263
>
> Reviewed-by: Anup Patel 
> Reviewed-by: Alistair Francis 
> Suggested-by: Heiko Stubner 
> Signed-off-by: Atish Patra 
> ---
>
> Changes from v3->v4:
> 1. Fixed the order of the extension names.
> 2. Added all the available ISA extensions in Qemu.
>
> Changes from v2->v3:
> 1. Used g_strconcat to replace snprintf & a max isa string length as
> suggested by Anup.
> 2. I have not included the Tested-by Tag from Heiko because the
> implementation changed from v2 to v3.
>
> Changes from v1->v2:
> 1. Improved the code redability by using arrays instead of individual check
> ---
>  target/riscv/cpu.c | 43 +++
>  1 file changed, 43 insertions(+)
>
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index ddda4906ffb7..2521a6f31f9f 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -34,6 +34,12 @@
>
>  /* RISC-V CPU definitions */
>
> +/* This includes the null terminated character '\0' */
> +struct isa_ext_data {
> +const char *name;
> +bool enabled;
> +};
> +
>  static const char riscv_exts[26] = "IEMAFDQCLBJTPVNSUHKORWXYZG";
>
>  const char * const riscv_int_regnames[] = {
> @@ -898,6 +904,42 @@ static void riscv_cpu_class_init(ObjectClass *c, void
> *data)
>  device_class_set_props(dc, riscv_cpu_properties);
>  }
>
> +#define ISA_EDATA_ENTRY(name, prop) {#name, cpu->cfg.prop}
> +
> +static void riscv_isa_string_ext(RISCVCPU *cpu, char **isa_str, int
> max_str_len)
> +{
> +char *old = *isa_str;
> +char *new = *isa_str;
> +int i;
> +struct isa_ext_data isa_edata_arr[] = {
> +ISA_EDATA_ENTRY(svinval, ext_svinval),
> +ISA_EDATA_ENTRY(svnapot, ext_svnapot),
> +ISA_EDATA_ENTRY(svpbmt, ext_svpbmt),
> +ISA_EDATA_ENTRY(zba, ext_zba),
> +ISA_EDATA_ENTRY(zbb, ext_zbb),
> +ISA_EDATA_ENTRY(zbc, ext_zbc),
> +ISA_EDATA_ENTRY(zbs, ext_zbs),
> +ISA_EDATA_ENTRY(zdinx, ext_zdinx),
> +ISA_EDATA_ENTRY(zfh, ext_zfhmin),
> +ISA_EDATA_ENTRY(zfhmin, ext_zfhmin),
> +ISA_EDATA_ENTRY(zfinx, ext_zfinx),
> +ISA_EDATA_ENTRY(zhinx, ext_zhinx),
> +ISA_EDATA_ENTRY(zhinxmin, ext_zhinxmin),
> +ISA_EDATA_ENTRY(zve32f, ext_zve32f),
> +ISA_EDATA_ENTRY(zve64f, ext_zve64f),
> +};
>

Hi Atish,

According to RISC-V Unpriviledge spec, Section 28.6:
https://github.com/riscv/riscv-isa-manual/blob/master/src/naming.tex#L85
<https://github.com/riscv/riscv-isa-manual/blob/master/src/naming.tex#L199>

"The first letter following the “Z” conventionally indicates the most
closely
related alphabetical extension category, IMAFDQLCBKJTPV.
For the “Zam” extension for misaligned atomics,
for example, the letter “a” indicates the extension is related to the “A”
standard extension.
If multiple “Z” extensions are named, they should be ordered first by
category,
then alphabetically within a category—for example, “Zicsr Zifencei Zam”."

So I think the order of "Z" extensions should be:
zfh, zfhmin, zfinx, zdinx, zba, zbb, zbc, zbs, zve32f, zve64f, zhinx,
zhinxmin

Also, I think "Zifencei" and "Zicsr" should also be covered as well,
and all extensions should follow the order defined in Table 28.11:
https://github.com/riscv/riscv-isa-manual/blob/master/src/naming.tex#L141

"The table also defines the canonical order in which extension names must
appear in the name string,
with top-to-bottom in table indicating first-to-last in the name string,
e.g., RV32IMACV is legal, whereas RV32IMAVC is not."

So the overall order would be:
zicsr, zifencei, zfh, zfhmin, zfinx, zdinx, zba, zbb, zbc, zbs, zve32f,
zve64f, zhinx, zhinxmin, svinval, svnapot, svpbmt,

Regards,
Frank Chang


> +
> +for (i = 0; i < ARRAY_SIZE(isa_edata_arr); i++) {
> +if (isa_edata_arr[i].enabled) {
> +new = g_strconcat(old, "_", isa_edata_arr[i].name, NULL);
> +g_free(old);
> +old = new;
> +}
> +}
> +
> +*isa_str = new;
> +}
> +
>  char *riscv_isa_string(RISCVCPU *cpu)
>  {
>  int i;
> @@ -910,6 +952,7 @@ char *riscv_isa_string(RISCVCPU *cpu)
>  }
>  }
>  *p = '\0';
> +riscv_isa_string_ext(cpu, _str, maxlen);
>  return isa_str;
>  }
>
> --
> 2.30.2
>
>
>


Re: [PATCH v4 2/2] target/riscv: Enable Zicbo[m,z,p] instructions

2022-03-06 Thread Frank Chang
ception
> if address translation does not permit any
> access or raises a store access fault exception otherwise.
> """
>
> In your scenario we have (1...allowed; 0...not allowed):
> * read: perm:1, pmp:0
> * fetch: perm:1: pmp:0
> * write: perm:0, pmp:0
>
> Address translation would allow read and fetch access, but PMP blocks that.
> So the "does not permit any"-part is wrong, therefore we should raise a
> store page fault.
>
> In fact, I can't predict what will happen, because the code in
> target/riscv/cpu_helper.c does
> not really prioritize page faults or PMP faults. it returns one of them,
> once they are encountered.
>

Hi Christoph,

May I ask what does "page faults or PMP faults are not prioritized" here
mean?

In target/riscv/cpu_helper.c, if "pmp_violation" flag is not set to true,
page fault will be picked.
So as long as the TRANSLATE_PMP_FAIL is returned, it will be indicated as a
PMP fault.
(The only exception I can see is that TRANSLATE_PMP_FAIL may be converted
to TRANSLATE_G_STAGE_FAIL
  if it's the second stage translation and PMP fault on PTE entry's PA.)
As the "final PA" is checked only after the page table is walked,
shouldn't the "pmp_violation" flag only be set after all the translation
accesses are checked and granted?

Regards,
Frank Chang


>
> In order to model this properly, we would have to refactor cpu_helper.c to
> separate page permissions
> from PMP. However, that seems a bit out of scope for a Zicbo* support
> patchset.
>
>
>
>>
>> I think the final exception should be access fault instead of the page
>> fault caused by probe_access_range_flags with MMU_DATA_STORE.
>>
>> Regards,
>>
>> Weiwei Li
>>
>>


Re: [PATCH v3] target/riscv: Add isa extenstion strings to the device tree

2022-03-05 Thread Frank Chang
Typo in patch title:
s/extenstion/extension/g

Regards,
Frank Chang

On Sat, Feb 26, 2022 at 3:45 PM Frank Chang  wrote:

>
>
> Atish Patra  於 2022年2月23日 週三 上午6:39寫道:
>
>> The Linux kernel parses the ISA extensions from "riscv,isa" DT
>> property. It used to parse only the single letter base extensions
>> until now. A generic ISA extension parsing framework was proposed[1]
>> recently that can parse multi-letter ISA extensions as well.
>>
>> Generate the extended ISA string by appending  the available ISA
>> extensions
>> to the "riscv,isa" string if it is enabled so that kernel can process it.
>>
>> [1] https://lkml.org/lkml/2022/2/15/263
>>
>> Suggested-by: Heiko Stubner 
>> Signed-off-by: Atish Patra 
>> ---
>> Changes from v2->v3:
>> 1. Used g_strconcat to replace snprintf & a max isa string length as
>> suggested by Anup.
>> 2. I have not included the Tested-by Tag from Heiko because the
>> implementation changed from v2 to v3.
>>
>> Changes from v1->v2:
>> 1. Improved the code redability by using arrays instead of individual
>> check
>> ---
>>  target/riscv/cpu.c | 29 +
>>  1 file changed, 29 insertions(+)
>>
>> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
>> index b0a40b83e7a8..2c7ff6ef555a 100644
>> --- a/target/riscv/cpu.c
>> +++ b/target/riscv/cpu.c
>> @@ -34,6 +34,12 @@
>>
>>  /* RISC-V CPU definitions */
>>
>> +/* This includes the null terminated character '\0' */
>> +struct isa_ext_data {
>> +const char *name;
>> +bool enabled;
>> +};
>> +
>>  static const char riscv_exts[26] = "IEMAFDQCLBJTPVNSUHKORWXYZG";
>>
>>  const char * const riscv_int_regnames[] = {
>> @@ -881,6 +887,28 @@ static void riscv_cpu_class_init(ObjectClass *c,
>> void *data)
>>  device_class_set_props(dc, riscv_cpu_properties);
>>  }
>>
>> +static void riscv_isa_string_ext(RISCVCPU *cpu, char **isa_str, int
>> max_str_len)
>> +{
>> +char *old = *isa_str;
>> +char *new = *isa_str;
>> +int i;
>> +struct isa_ext_data isa_edata_arr[] = {
>> +{ "svpbmt", cpu->cfg.ext_svpbmt   },
>> +{ "svinval", cpu->cfg.ext_svinval },
>> +{ "svnapot", cpu->cfg.ext_svnapot },
>>
>
> We still have other sub-extensions, e.g. Zfh, Zba, Zbb, Zbc, Zbs... etc.
> Do you mind adding them as well?
>
> Also, I think the order of ISA strings should be alphabetical as described:
> https://github.com/riscv/riscv-isa-manual/blob/master/src/naming.tex#L96
>
> Regards,
> Frank Chang
>
>
>> +};
>> +
>> +for (i = 0; i < ARRAY_SIZE(isa_edata_arr); i++) {
>> +if (isa_edata_arr[i].enabled) {
>> +new = g_strconcat(old, "_", isa_edata_arr[i].name, NULL);
>> +g_free(old);
>> +old = new;
>> +}
>> +}
>> +
>> +*isa_str = new;
>> +}
>> +
>>  char *riscv_isa_string(RISCVCPU *cpu)
>>  {
>>  int i;
>> @@ -893,6 +921,7 @@ char *riscv_isa_string(RISCVCPU *cpu)
>>  }
>>  }
>>  *p = '\0';
>> +riscv_isa_string_ext(cpu, _str, maxlen);
>>  return isa_str;
>>  }
>>
>> --
>> 2.30.2
>>
>>


Re: [PATCH v3] target/riscv: Add isa extenstion strings to the device tree

2022-03-05 Thread Frank Chang
On Sun, Mar 6, 2022 at 2:12 PM Atish Kumar Patra 
wrote:

>
>
> On Sat, Mar 5, 2022 at 9:36 PM Frank Chang  wrote:
>
>> On Sun, Mar 6, 2022 at 7:42 AM Atish Kumar Patra 
>> wrote:
>>
>>>
>>>
>>> On Sat, Mar 5, 2022 at 10:05 AM Heiko Stuebner  wrote:
>>>
>>>> Hi,
>>>>
>>>> Am Donnerstag, 3. März 2022, 19:58:38 CET schrieb Atish Patra:
>>>> > On Fri, Feb 25, 2022 at 11:46 PM Frank Chang 
>>>> wrote:
>>>> > > Atish Patra  於 2022年2月23日 週三 上午6:39寫道:
>>>> > >>
>>>> > >> The Linux kernel parses the ISA extensions from "riscv,isa" DT
>>>> > >> property. It used to parse only the single letter base extensions
>>>> > >> until now. A generic ISA extension parsing framework was
>>>> proposed[1]
>>>> > >> recently that can parse multi-letter ISA extensions as well.
>>>> > >>
>>>> > >> Generate the extended ISA string by appending  the available ISA
>>>> extensions
>>>> > >> to the "riscv,isa" string if it is enabled so that kernel can
>>>> process it.
>>>> > >>
>>>> > >> [1] https://lkml.org/lkml/2022/2/15/263
>>>> > >>
>>>> > >> Suggested-by: Heiko Stubner 
>>>> > >> Signed-off-by: Atish Patra 
>>>> > >> ---
>>>> > >> Changes from v2->v3:
>>>> > >> 1. Used g_strconcat to replace snprintf & a max isa string length
>>>> as
>>>> > >> suggested by Anup.
>>>> > >> 2. I have not included the Tested-by Tag from Heiko because the
>>>> > >> implementation changed from v2 to v3.
>>>> > >>
>>>> > >> Changes from v1->v2:
>>>> > >> 1. Improved the code redability by using arrays instead of
>>>> individual check
>>>> > >> ---
>>>> > >>  target/riscv/cpu.c | 29 +
>>>> > >>  1 file changed, 29 insertions(+)
>>>> > >>
>>>> > >> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
>>>> > >> index b0a40b83e7a8..2c7ff6ef555a 100644
>>>> > >> --- a/target/riscv/cpu.c
>>>> > >> +++ b/target/riscv/cpu.c
>>>> > >> @@ -34,6 +34,12 @@
>>>> > >>
>>>> > >>  /* RISC-V CPU definitions */
>>>> > >>
>>>> > >> +/* This includes the null terminated character '\0' */
>>>> > >> +struct isa_ext_data {
>>>> > >> +const char *name;
>>>> > >> +bool enabled;
>>>> > >> +};
>>>> > >> +
>>>> > >>  static const char riscv_exts[26] = "IEMAFDQCLBJTPVNSUHKORWXYZG";
>>>> > >>
>>>> > >>  const char * const riscv_int_regnames[] = {
>>>> > >> @@ -881,6 +887,28 @@ static void riscv_cpu_class_init(ObjectClass
>>>> *c, void *data)
>>>> > >>  device_class_set_props(dc, riscv_cpu_properties);
>>>> > >>  }
>>>> > >>
>>>> > >> +static void riscv_isa_string_ext(RISCVCPU *cpu, char **isa_str,
>>>> int max_str_len)
>>>> > >> +{
>>>> > >> +char *old = *isa_str;
>>>> > >> +char *new = *isa_str;
>>>> > >> +int i;
>>>> > >> +struct isa_ext_data isa_edata_arr[] = {
>>>> > >> +{ "svpbmt", cpu->cfg.ext_svpbmt   },
>>>> > >> +{ "svinval", cpu->cfg.ext_svinval },
>>>> > >> +{ "svnapot", cpu->cfg.ext_svnapot },
>>>> > >
>>>> > >
>>>> > > We still have other sub-extensions, e.g. Zfh, Zba, Zbb, Zbc, Zbs...
>>>> etc.
>>>> > > Do you mind adding them as well?
>>>> > >
>>>> >
>>>> > Do we really need it ? Does any OS actually parse it from the device
>>>> tree ?
>>>> > AFAIK, Linux kernel doesn't use them. As the device tree is intended
>>>> > to keep the information useful
>>>> > for supervisor software,
>>>>
>>>> That actually

Re: [PATCH v3] target/riscv: Add isa extenstion strings to the device tree

2022-03-05 Thread Frank Chang
On Sun, Mar 6, 2022 at 7:42 AM Atish Kumar Patra 
wrote:

>
>
> On Sat, Mar 5, 2022 at 10:05 AM Heiko Stuebner  wrote:
>
>> Hi,
>>
>> Am Donnerstag, 3. März 2022, 19:58:38 CET schrieb Atish Patra:
>> > On Fri, Feb 25, 2022 at 11:46 PM Frank Chang 
>> wrote:
>> > > Atish Patra  於 2022年2月23日 週三 上午6:39寫道:
>> > >>
>> > >> The Linux kernel parses the ISA extensions from "riscv,isa" DT
>> > >> property. It used to parse only the single letter base extensions
>> > >> until now. A generic ISA extension parsing framework was proposed[1]
>> > >> recently that can parse multi-letter ISA extensions as well.
>> > >>
>> > >> Generate the extended ISA string by appending  the available ISA
>> extensions
>> > >> to the "riscv,isa" string if it is enabled so that kernel can
>> process it.
>> > >>
>> > >> [1] https://lkml.org/lkml/2022/2/15/263
>> > >>
>> > >> Suggested-by: Heiko Stubner 
>> > >> Signed-off-by: Atish Patra 
>> > >> ---
>> > >> Changes from v2->v3:
>> > >> 1. Used g_strconcat to replace snprintf & a max isa string length as
>> > >> suggested by Anup.
>> > >> 2. I have not included the Tested-by Tag from Heiko because the
>> > >> implementation changed from v2 to v3.
>> > >>
>> > >> Changes from v1->v2:
>> > >> 1. Improved the code redability by using arrays instead of
>> individual check
>> > >> ---
>> > >>  target/riscv/cpu.c | 29 +
>> > >>  1 file changed, 29 insertions(+)
>> > >>
>> > >> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
>> > >> index b0a40b83e7a8..2c7ff6ef555a 100644
>> > >> --- a/target/riscv/cpu.c
>> > >> +++ b/target/riscv/cpu.c
>> > >> @@ -34,6 +34,12 @@
>> > >>
>> > >>  /* RISC-V CPU definitions */
>> > >>
>> > >> +/* This includes the null terminated character '\0' */
>> > >> +struct isa_ext_data {
>> > >> +const char *name;
>> > >> +bool enabled;
>> > >> +};
>> > >> +
>> > >>  static const char riscv_exts[26] = "IEMAFDQCLBJTPVNSUHKORWXYZG";
>> > >>
>> > >>  const char * const riscv_int_regnames[] = {
>> > >> @@ -881,6 +887,28 @@ static void riscv_cpu_class_init(ObjectClass
>> *c, void *data)
>> > >>  device_class_set_props(dc, riscv_cpu_properties);
>> > >>  }
>> > >>
>> > >> +static void riscv_isa_string_ext(RISCVCPU *cpu, char **isa_str, int
>> max_str_len)
>> > >> +{
>> > >> +char *old = *isa_str;
>> > >> +char *new = *isa_str;
>> > >> +int i;
>> > >> +struct isa_ext_data isa_edata_arr[] = {
>> > >> +{ "svpbmt", cpu->cfg.ext_svpbmt   },
>> > >> +{ "svinval", cpu->cfg.ext_svinval },
>> > >> +{ "svnapot", cpu->cfg.ext_svnapot },
>> > >
>> > >
>> > > We still have other sub-extensions, e.g. Zfh, Zba, Zbb, Zbc, Zbs...
>> etc.
>> > > Do you mind adding them as well?
>> > >
>> >
>> > Do we really need it ? Does any OS actually parse it from the device
>> tree ?
>> > AFAIK, Linux kernel doesn't use them. As the device tree is intended
>> > to keep the information useful
>> > for supervisor software,
>>
>> That actually isn't true ;-) .
>>
>> The devicetree is intended to _describe_ the hardware present in full
>> and has really nothing to do with what the userspace needs.
>> So the argument "Linux doesn't need this" is never true when talking
>> about devicetrees ;-) .
>>
>
> Yes. I didn’t mean that way. I was simply asking if these extensions
> currently in use. I just mentioned Linux as an example.
>
> The larger point I was trying to make if we should add all the supported
> extensions when they are added to Qemu or on a need basis.
>
> I don’t feel strongly either way. So I am okay with the former approach if
> that’s what everyone prefers!
>

Linux Kernel itself might not,
but userspace applications may query /proc/cpuinfo to get core's
capabilities, e.g. for those vector applications.
It reall

Re: [PATCH v3] target/riscv: Add isa extenstion strings to the device tree

2022-02-25 Thread Frank Chang
Atish Patra  於 2022年2月23日 週三 上午6:39寫道:

> The Linux kernel parses the ISA extensions from "riscv,isa" DT
> property. It used to parse only the single letter base extensions
> until now. A generic ISA extension parsing framework was proposed[1]
> recently that can parse multi-letter ISA extensions as well.
>
> Generate the extended ISA string by appending  the available ISA extensions
> to the "riscv,isa" string if it is enabled so that kernel can process it.
>
> [1] https://lkml.org/lkml/2022/2/15/263
>
> Suggested-by: Heiko Stubner 
> Signed-off-by: Atish Patra 
> ---
> Changes from v2->v3:
> 1. Used g_strconcat to replace snprintf & a max isa string length as
> suggested by Anup.
> 2. I have not included the Tested-by Tag from Heiko because the
> implementation changed from v2 to v3.
>
> Changes from v1->v2:
> 1. Improved the code redability by using arrays instead of individual check
> ---
>  target/riscv/cpu.c | 29 +
>  1 file changed, 29 insertions(+)
>
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index b0a40b83e7a8..2c7ff6ef555a 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -34,6 +34,12 @@
>
>  /* RISC-V CPU definitions */
>
> +/* This includes the null terminated character '\0' */
> +struct isa_ext_data {
> +const char *name;
> +bool enabled;
> +};
> +
>  static const char riscv_exts[26] = "IEMAFDQCLBJTPVNSUHKORWXYZG";
>
>  const char * const riscv_int_regnames[] = {
> @@ -881,6 +887,28 @@ static void riscv_cpu_class_init(ObjectClass *c, void
> *data)
>  device_class_set_props(dc, riscv_cpu_properties);
>  }
>
> +static void riscv_isa_string_ext(RISCVCPU *cpu, char **isa_str, int
> max_str_len)
> +{
> +char *old = *isa_str;
> +char *new = *isa_str;
> +int i;
> +struct isa_ext_data isa_edata_arr[] = {
> +{ "svpbmt", cpu->cfg.ext_svpbmt   },
> +{ "svinval", cpu->cfg.ext_svinval },
> +{ "svnapot", cpu->cfg.ext_svnapot },
>

We still have other sub-extensions, e.g. Zfh, Zba, Zbb, Zbc, Zbs... etc.
Do you mind adding them as well?

Also, I think the order of ISA strings should be alphabetical as described:
https://github.com/riscv/riscv-isa-manual/blob/master/src/naming.tex#L96

Regards,
Frank Chang


> +};
> +
> +for (i = 0; i < ARRAY_SIZE(isa_edata_arr); i++) {
> +if (isa_edata_arr[i].enabled) {
> +new = g_strconcat(old, "_", isa_edata_arr[i].name, NULL);
> +g_free(old);
> +old = new;
> +}
> +}
> +
> +*isa_str = new;
> +}
> +
>  char *riscv_isa_string(RISCVCPU *cpu)
>  {
>  int i;
> @@ -893,6 +921,7 @@ char *riscv_isa_string(RISCVCPU *cpu)
>  }
>  }
>  *p = '\0';
> +riscv_isa_string_ext(cpu, _str, maxlen);
>  return isa_str;
>  }
>
> --
> 2.30.2
>
>


  1   2   3   4   5   6   7   8   9   10   >