Re: [PATCH v2 1/2] target/riscv: Preliminary textra trigger CSR writting support

2024-07-19 Thread Alistair Francis
On Wed, Jul 10, 2024 at 8:01 PM Alvin Chang via  wrote:
>
> This commit allows program to write textra trigger CSR for type 2, 3, 6
> triggers. In this preliminary patch, the textra.MHVALUE and the
> textra.MHSELECT fields are allowed to be configured. Other fields, such
> as textra.SBYTEMASK, textra.SVALUE, and textra.SSELECT, are hardwired to
> zero for now.
>
> For textra.MHSELECT field, the only legal values are 0 (ignore) and 4
> (mcontext). Writing 1~3 into textra.MHSELECT will be changed to 0, and
> writing 5~7 into textra.MHSELECT will be changed to 4. This behavior is
> aligned to RISC-V SPIKE simulator.
>
> Signed-off-by: Alvin Chang 
> ---
>  target/riscv/cpu_bits.h | 10 ++
>  target/riscv/debug.c| 75 +
>  2 files changed, 79 insertions(+), 6 deletions(-)
>
> diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
> index c257c5ed7d..0530b4f9f4 100644
> --- a/target/riscv/cpu_bits.h
> +++ b/target/riscv/cpu_bits.h
> @@ -906,6 +906,16 @@ typedef enum RISCVException {
>  #define JVT_BASE   (~0x3F)
>
>  /* Debug Sdtrig CSR masks */
> +#define TEXTRA32_MHVALUE   0xFC00
> +#define TEXTRA32_MHSELECT  0x0380
> +#define TEXTRA32_SBYTEMASK 0x000C
> +#define TEXTRA32_SVALUE0x0003FFFC
> +#define TEXTRA32_SSELECT   0x0003
> +#define TEXTRA64_MHVALUE   0xFFF8ULL
> +#define TEXTRA64_MHSELECT  0x0007ULL
> +#define TEXTRA64_SBYTEMASK 0x00F0ULL
> +#define TEXTRA64_SVALUE0x0003FFFCULL
> +#define TEXTRA64_SSELECT   0x0003ULL
>  #define MCONTEXT32 0x003F
>  #define MCONTEXT64 0x1FFFULL
>  #define MCONTEXT32_HCONTEXT0x007F
> diff --git a/target/riscv/debug.c b/target/riscv/debug.c
> index 0b5099ff9a..139b722a7e 100644
> --- a/target/riscv/debug.c
> +++ b/target/riscv/debug.c
> @@ -217,6 +217,72 @@ static inline void warn_always_zero_bit(target_ulong 
> val, target_ulong mask,
>  }
>  }
>
> +static target_ulong textra_validate(CPURISCVState *env, target_ulong tdata3)
> +{
> +target_ulong mhvalue, mhselect;
> +target_ulong mhselect_new;
> +target_ulong textra;
> +const uint32_t mhselect_no_rvh[8] = { 0, 0, 0, 0, 4, 4, 4, 4 };
> +
> +switch (riscv_cpu_mxl(env)) {
> +case MXL_RV32:
> +mhvalue  = get_field(tdata3, TEXTRA32_MHVALUE);
> +mhselect = get_field(tdata3, TEXTRA32_MHSELECT);
> +/* Validate unimplemented (always zero) bits */
> +warn_always_zero_bit(tdata3, (target_ulong)TEXTRA32_SBYTEMASK,
> + "sbytemask");
> +warn_always_zero_bit(tdata3, (target_ulong)TEXTRA32_SVALUE,
> + "svalue");
> +warn_always_zero_bit(tdata3, (target_ulong)TEXTRA32_SSELECT,
> + "sselect");
> +break;
> +case MXL_RV64:
> +case MXL_RV128:
> +mhvalue  = get_field(tdata3, TEXTRA64_MHVALUE);
> +mhselect = get_field(tdata3, TEXTRA64_MHSELECT);
> +/* Validate unimplemented (always zero) bits */
> +warn_always_zero_bit(tdata3, (target_ulong)TEXTRA64_SBYTEMASK,
> + "sbytemask");
> +warn_always_zero_bit(tdata3, (target_ulong)TEXTRA64_SVALUE,
> + "svalue");
> +warn_always_zero_bit(tdata3, (target_ulong)TEXTRA64_SSELECT,
> + "sselect");
> +break;
> +default:
> +g_assert_not_reached();
> +}
> +
> +/* Validate mhselect. */
> +mhselect_new = mhselect_no_rvh[mhselect];
> +if (mhselect != mhselect_new) {
> +qemu_log_mask(LOG_UNIMP, "mhselect only supports 0 or 4 for now\n");
> +}
> +
> +/* Write legal values into textra */
> +textra = 0;
> +switch (riscv_cpu_mxl(env)) {
> +case MXL_RV32:
> +textra = set_field(textra, TEXTRA32_MHVALUE,  mhvalue);
> +textra = set_field(textra, TEXTRA32_MHSELECT, mhselect_new);
> +break;
> +case MXL_RV64:
> +case MXL_RV128:
> +textra = set_field(textra, TEXTRA64_MHVALUE,  mhvalue);
> +textra = set_field(textra, TEXTRA64_MHSELECT, mhselect_new);
> +break;
> +default:
> +g_assert_not_reached();
> +}
> +
> +if (textra != tdata3) {
> +qemu_log_mask(LOG_GUEST_ERROR,
> +  "different value 0x" TARGET_FMT_lx " write to 
> tdata3\n",
> +  textra);
> +}

You don't need this, you have already reported on all of the possible
differences

With the above removed

Reviewed-by: Alistair Francis 

Alistair



Re: [PATCH v5 13/13] docs/specs: add riscv-iommu

2024-07-19 Thread Alistair Francis
On Tue, Jul 9, 2024 at 3:37 AM Daniel Henrique Barboza
 wrote:
>
> Add a simple guideline to use the existing RISC-V IOMMU support we just
> added.
>
> This doc will be updated once we add the riscv-iommu-sys device.
>
> Signed-off-by: Daniel Henrique Barboza 
> ---
>  docs/specs/index.rst   |  1 +
>  docs/specs/riscv-iommu.rst | 55 ++
>  docs/system/riscv/virt.rst | 13 +
>  3 files changed, 69 insertions(+)
>  create mode 100644 docs/specs/riscv-iommu.rst
>
> diff --git a/docs/specs/index.rst b/docs/specs/index.rst
> index 1484e3e760..c68cd9ae6c 100644
> --- a/docs/specs/index.rst
> +++ b/docs/specs/index.rst
> @@ -33,3 +33,4 @@ guest hardware that is specific to QEMU.
> virt-ctlr
> vmcoreinfo
> vmgenid
> +   riscv-iommu
> diff --git a/docs/specs/riscv-iommu.rst b/docs/specs/riscv-iommu.rst
> new file mode 100644
> index 00..fa38ff7667
> --- /dev/null
> +++ b/docs/specs/riscv-iommu.rst
> @@ -0,0 +1,55 @@
> +.. _riscv-iommu:
> +
> +RISC-V IOMMU support for RISC-V machines
> +
> +
> +QEMU implements a RISC-V IOMMU emulation based on the RISC-V IOMMU spec
> +version 1.0 [1].
> +
> +The emulation includes a PCI reference device, riscv-iommu-pci, that QEMU
> +RISC-V boards can use.  The 'virt' RISC-V machine is compatible with this
> +device.
> +
> +A platform device that implements the RISC-V IOMMU will be added in the
> +future.
> +
> +
> +riscv-iommu-pci reference device
> +
> +
> +This device implements the RISC-V IOMMU emulation as recommended by the 
> section
> +"Integrating an IOMMU as a PCIe device" of [1]: a PCI device with base class 
> 08h,
> +sub-class 06h and programming interface 00h.
> +
> +As a reference device it doesn't implement anything outside of the 
> specification,
> +so it uses a generic default PCI ID given by QEMU: 1b36:0014.
> +
> +To include the device in the 'virt' machine:
> +
> +.. code-block:: bash
> +
> +  $ qemu-system-riscv64 -M virt -device riscv-iommu-pci (...)

We should add a sentence saying what this does. As in what should a
user expect after they have done this

Alistair

> +
> +As of this writing the existing Linux kernel support [2], not yet merged, is 
> being
> +created as a Rivos device, i.e. it uses Rivos vendor ID.  To use the 
> riscv-iommu-pci
> +device with the existing kernel support we need to emulate a Rivos PCI IOMMU 
> by
> +setting 'vendor-id' and 'device-id':
> +
> +.. code-block:: bash
> +
> +  $ qemu-system-riscv64 -M virt\
> + -device riscv-iommu-pci,vendor-id=0x1efd,device-id=0xedf1 (...)
> +
> +Several options are available to control the capabilities of the device, 
> namely:
> +
> +- "bus"
> +- "ioatc-limit"
> +- "intremap"
> +- "ats"
> +- "off" (Out-of-reset translation mode: 'on' for DMA disabled, 'off' for 
> 'BARE' (passthrough))
> +- "s-stage"
> +- "g-stage"
> +
> +
> +[1] 
> https://github.com/riscv-non-isa/riscv-iommu/releases/download/v1.0/riscv-iommu.pdf
> +[2] 
> https://lore.kernel.org/linux-riscv/cover.1718388908.git.tjezn...@rivosinc.com/
> diff --git a/docs/system/riscv/virt.rst b/docs/system/riscv/virt.rst
> index 9a06f95a34..8e9a2e4dda 100644
> --- a/docs/system/riscv/virt.rst
> +++ b/docs/system/riscv/virt.rst
> @@ -84,6 +84,19 @@ none``, as in
>
>  Firmware images used for pflash must be exactly 32 MiB in size.
>
> +riscv-iommu support
> +---
> +
> +The board has support for the riscv-iommu-pci device by using the following
> +command line:
> +
> +.. code-block:: bash
> +
> +  $ qemu-system-riscv64 -M virt -device riscv-iommu-pci (...)
> +
> +Refer to :ref:`riscv-iommu` for more information on how the RISC-V IOMMU 
> support
> +works.
> +
>  Machine-specific options
>  
>
> --
> 2.45.2
>
>



Re: [PATCH v5 12/13] qtest/riscv-iommu-test: add init queues test

2024-07-19 Thread Alistair Francis
On Tue, Jul 9, 2024 at 3:36 AM Daniel Henrique Barboza
 wrote:
>
> Add an additional test to further exercise the IOMMU where we attempt to
> initialize the command, fault and page-request queues.
>
> These steps are taken from chapter 6.2 of the RISC-V IOMMU spec,
> "Guidelines for initialization". It emulates what we expect from the
> software/OS when initializing the IOMMU.
>
> Signed-off-by: Daniel Henrique Barboza 
> Reviewed-by: Frank Chang 

Acked-by: Alistair Francis 

Alistair

> ---
>  tests/qtest/libqos/riscv-iommu.h |  29 +++
>  tests/qtest/riscv-iommu-test.c   | 141 +++
>  2 files changed, 170 insertions(+)
>
> diff --git a/tests/qtest/libqos/riscv-iommu.h 
> b/tests/qtest/libqos/riscv-iommu.h
> index d123efb41f..c62ddedbac 100644
> --- a/tests/qtest/libqos/riscv-iommu.h
> +++ b/tests/qtest/libqos/riscv-iommu.h
> @@ -62,6 +62,35 @@
>
>  #define RISCV_IOMMU_REG_IPSR0x0054
>
> +#define RISCV_IOMMU_REG_IVEC0x02F8
> +#define RISCV_IOMMU_REG_IVEC_CIVGENMASK_ULL(3, 0)
> +#define RISCV_IOMMU_REG_IVEC_FIVGENMASK_ULL(7, 4)
> +#define RISCV_IOMMU_REG_IVEC_PIVGENMASK_ULL(15, 12)
> +
> +#define RISCV_IOMMU_REG_CQB 0x0018
> +#define RISCV_IOMMU_CQB_PPN_START   10
> +#define RISCV_IOMMU_CQB_PPN_LEN 44
> +#define RISCV_IOMMU_CQB_LOG2SZ_START0
> +#define RISCV_IOMMU_CQB_LOG2SZ_LEN  5
> +
> +#define RISCV_IOMMU_REG_CQT 0x0024
> +
> +#define RISCV_IOMMU_REG_FQB 0x0028
> +#define RISCV_IOMMU_FQB_PPN_START   10
> +#define RISCV_IOMMU_FQB_PPN_LEN 44
> +#define RISCV_IOMMU_FQB_LOG2SZ_START0
> +#define RISCV_IOMMU_FQB_LOG2SZ_LEN  5
> +
> +#define RISCV_IOMMU_REG_FQT 0x0034
> +
> +#define RISCV_IOMMU_REG_PQB 0x0038
> +#define RISCV_IOMMU_PQB_PPN_START   10
> +#define RISCV_IOMMU_PQB_PPN_LEN 44
> +#define RISCV_IOMMU_PQB_LOG2SZ_START0
> +#define RISCV_IOMMU_PQB_LOG2SZ_LEN  5
> +
> +#define RISCV_IOMMU_REG_PQT 0x0044
> +
>  typedef struct QRISCVIOMMU {
>  QOSGraphObject obj;
>  QPCIDevice dev;
> diff --git a/tests/qtest/riscv-iommu-test.c b/tests/qtest/riscv-iommu-test.c
> index 7f0dbd0211..9e2afcb4b9 100644
> --- a/tests/qtest/riscv-iommu-test.c
> +++ b/tests/qtest/riscv-iommu-test.c
> @@ -33,6 +33,20 @@ static uint64_t riscv_iommu_read_reg64(QRISCVIOMMU 
> *r_iommu, int reg_offset)
>  return reg;
>  }
>
> +static void riscv_iommu_write_reg32(QRISCVIOMMU *r_iommu, int reg_offset,
> +uint32_t val)
> +{
> +qpci_memwrite(_iommu->dev, r_iommu->reg_bar, reg_offset,
> +  , sizeof(val));
> +}
> +
> +static void riscv_iommu_write_reg64(QRISCVIOMMU *r_iommu, int reg_offset,
> +uint64_t val)
> +{
> +qpci_memwrite(_iommu->dev, r_iommu->reg_bar, reg_offset,
> +  , sizeof(val));
> +}
> +
>  static void test_pci_config(void *obj, void *data, QGuestAllocator *t_alloc)
>  {
>  QRISCVIOMMU *r_iommu = obj;
> @@ -84,10 +98,137 @@ static void test_reg_reset(void *obj, void *data, 
> QGuestAllocator *t_alloc)
>  g_assert_cmpuint(reg, ==, 0);
>  }
>
> +/*
> + * Common timeout-based poll for CQCSR, FQCSR and PQCSR. All
> + * their ON bits are mapped as RISCV_IOMMU_QUEUE_ACTIVE (16),
> + */
> +static void qtest_wait_for_queue_active(QRISCVIOMMU *r_iommu,
> +uint32_t queue_csr)
> +{
> +QTestState *qts = global_qtest;
> +guint64 timeout_us = 2 * 1000 * 1000;
> +gint64 start_time = g_get_monotonic_time();
> +uint32_t reg;
> +
> +for (;;) {
> +qtest_clock_step(qts, 100);
> +
> +reg = riscv_iommu_read_reg32(r_iommu, queue_csr);
> +if (reg & RISCV_IOMMU_QUEUE_ACTIVE) {
> +break;
> +}
> +g_assert(g_get_monotonic_time() - start_time <= timeout_us);
> +}
> +}
> +
> +/*
> + * Goes through the queue activation procedures of chapter 6.2,
> + * "Guidelines for initialization", of the RISCV-IOMMU spec.
> + */
> +static void test_iommu_init_queues(void *obj, void *data,
> +   QGuestAllocator *t_alloc)
> +{
> +QRISCVIOMMU *r_iommu = obj;
> +uint64_t reg64, q_addr;
> +uint32_t reg;
> +int k;
> +
> +reg64 = riscv_iommu_read_reg64(r_iommu, RISCV_IOMMU_REG_CAP);
> +g_assert_cmpuint(reg64 & RISCV_IOMMU_CAP_VERSION, ==, 0x10);
> +
> +/*
> + * Program the command queue. Write 0xF to civ, assert that
> + * we have 4 writa

Re: [PATCH v5 09/13] hw/riscv/riscv-iommu: add ATS support

2024-07-18 Thread Alistair Francis
On Tue, Jul 9, 2024 at 3:37 AM Daniel Henrique Barboza
 wrote:
>
> From: Tomasz Jeznach 
>
> Add PCIe Address Translation Services (ATS) capabilities to the IOMMU.
> This will add support for ATS translation requests in Fault/Event
> queues, Page-request queue and IOATC invalidations.
>
> Signed-off-by: Tomasz Jeznach 
> Signed-off-by: Daniel Henrique Barboza 
> Reviewed-by: Frank Chang 

Acked-by: Alistair Francis 

Alistair

> ---
>  hw/riscv/riscv-iommu-bits.h |  43 +++-
>  hw/riscv/riscv-iommu.c  | 129 +++-
>  hw/riscv/riscv-iommu.h  |   1 +
>  hw/riscv/trace-events   |   3 +
>  4 files changed, 173 insertions(+), 3 deletions(-)
>
> diff --git a/hw/riscv/riscv-iommu-bits.h b/hw/riscv/riscv-iommu-bits.h
> index 1dd2e2c7d6..b1546d3669 100644
> --- a/hw/riscv/riscv-iommu-bits.h
> +++ b/hw/riscv/riscv-iommu-bits.h
> @@ -79,6 +79,7 @@ struct riscv_iommu_pq_record {
>  #define RISCV_IOMMU_CAP_SV57X4  BIT_ULL(19)
>  #define RISCV_IOMMU_CAP_MSI_FLATBIT_ULL(22)
>  #define RISCV_IOMMU_CAP_MSI_MRIFBIT_ULL(23)
> +#define RISCV_IOMMU_CAP_ATS BIT_ULL(25)
>  #define RISCV_IOMMU_CAP_T2GPA   BIT_ULL(26)
>  #define RISCV_IOMMU_CAP_IGS GENMASK_ULL(29, 28)
>  #define RISCV_IOMMU_CAP_PAS GENMASK_ULL(37, 32)
> @@ -208,6 +209,7 @@ struct riscv_iommu_dc {
>
>  /* Translation control fields */
>  #define RISCV_IOMMU_DC_TC_V BIT_ULL(0)
> +#define RISCV_IOMMU_DC_TC_EN_ATSBIT_ULL(1)
>  #define RISCV_IOMMU_DC_TC_EN_PRIBIT_ULL(2)
>  #define RISCV_IOMMU_DC_TC_T2GPA BIT_ULL(3)
>  #define RISCV_IOMMU_DC_TC_DTF   BIT_ULL(4)
> @@ -269,6 +271,20 @@ struct riscv_iommu_command {
>  #define RISCV_IOMMU_CMD_IODIR_DVBIT_ULL(33)
>  #define RISCV_IOMMU_CMD_IODIR_DID   GENMASK_ULL(63, 40)
>
> +/* 3.1.4 I/O MMU PCIe ATS */
> +#define RISCV_IOMMU_CMD_ATS_OPCODE  4
> +#define RISCV_IOMMU_CMD_ATS_FUNC_INVAL  0
> +#define RISCV_IOMMU_CMD_ATS_FUNC_PRGR   1
> +#define RISCV_IOMMU_CMD_ATS_PID GENMASK_ULL(31, 12)
> +#define RISCV_IOMMU_CMD_ATS_PV  BIT_ULL(32)
> +#define RISCV_IOMMU_CMD_ATS_DSV BIT_ULL(33)
> +#define RISCV_IOMMU_CMD_ATS_RID GENMASK_ULL(55, 40)
> +#define RISCV_IOMMU_CMD_ATS_DSEGGENMASK_ULL(63, 56)
> +/* dword1 is the ATS payload, two different payload types for INVAL and PRGR 
> */
> +
> +/* ATS.PRGR payload */
> +#define RISCV_IOMMU_CMD_ATS_PRGR_RESP_CODE  GENMASK_ULL(47, 44)
> +
>  enum riscv_iommu_dc_fsc_atp_modes {
>  RISCV_IOMMU_DC_FSC_MODE_BARE = 0,
>  RISCV_IOMMU_DC_FSC_IOSATP_MODE_SV32 = 8,
> @@ -335,7 +351,32 @@ enum riscv_iommu_fq_ttypes {
>  RISCV_IOMMU_FQ_TTYPE_TADDR_INST_FETCH = 5,
>  RISCV_IOMMU_FQ_TTYPE_TADDR_RD = 6,
>  RISCV_IOMMU_FQ_TTYPE_TADDR_WR = 7,
> -RISCV_IOMMU_FW_TTYPE_PCIE_MSG_REQ = 8,
> +RISCV_IOMMU_FQ_TTYPE_PCIE_ATS_REQ = 8,
> +RISCV_IOMMU_FW_TTYPE_PCIE_MSG_REQ = 9,
> +};
> +
> +/* Header fields */
> +#define RISCV_IOMMU_PREQ_HDR_PIDGENMASK_ULL(31, 12)
> +#define RISCV_IOMMU_PREQ_HDR_PV BIT_ULL(32)
> +#define RISCV_IOMMU_PREQ_HDR_PRIV   BIT_ULL(33)
> +#define RISCV_IOMMU_PREQ_HDR_EXEC   BIT_ULL(34)
> +#define RISCV_IOMMU_PREQ_HDR_DIDGENMASK_ULL(63, 40)
> +
> +/* Payload fields */
> +#define RISCV_IOMMU_PREQ_PAYLOAD_R  BIT_ULL(0)
> +#define RISCV_IOMMU_PREQ_PAYLOAD_W  BIT_ULL(1)
> +#define RISCV_IOMMU_PREQ_PAYLOAD_L  BIT_ULL(2)
> +#define RISCV_IOMMU_PREQ_PAYLOAD_M  GENMASK_ULL(2, 0)
> +#define RISCV_IOMMU_PREQ_PRG_INDEX  GENMASK_ULL(11, 3)
> +#define RISCV_IOMMU_PREQ_UADDR  GENMASK_ULL(63, 12)
> +
> +
> +/*
> + * struct riscv_iommu_msi_pte - MSI Page Table Entry
> + */
> +struct riscv_iommu_msi_pte {
> +  uint64_t pte;
> +  uint64_t mrif_info;
>  };
>
>  /* Fields on pte */
> diff --git a/hw/riscv/riscv-iommu.c b/hw/riscv/riscv-iommu.c
> index 76728baa77..78058a49ae 100644
> --- a/hw/riscv/riscv-iommu.c
> +++ b/hw/riscv/riscv-iommu.c
> @@ -639,6 +639,20 @@ static bool 
> riscv_iommu_validate_device_ctx(RISCVIOMMUState *s,
>  RISCVIOMMUContext *ctx)
>  {
>  uint32_t fsc_mode, msi_mode;
> +uint64_t gatp;
> +
> +if (!(s->cap & RISCV_IOMMU_CAP_ATS) &&
> +(ctx->tc & RISCV_IOMMU_DC_TC_EN_ATS ||
> + ctx->tc & RISCV_IOMMU_DC_TC_EN_PRI ||
> + ctx->tc & RISCV_IOMMU_DC_TC_PRPR)) {
> +return false;
> +}
> +
> +if (!(ctx->tc & RISCV_IOMMU_DC_TC_EN_ATS) &&
> +(ctx->tc & RISCV_IOMMU_

Re: [PATCH v5 08/13] hw/riscv/riscv-iommu: add Address Translation Cache (IOATC)

2024-07-17 Thread Alistair Francis
On Tue, Jul 9, 2024 at 3:38 AM Daniel Henrique Barboza
 wrote:
>
> From: Tomasz Jeznach 
>
> The RISC-V IOMMU spec predicts that the IOMMU can use translation caches
> to hold entries from the DDT. This includes implementation for all cache
> commands that are marked as 'not implemented'.
>
> There are some artifacts included in the cache that predicts s-stage and
> g-stage elements, although we don't support it yet. We'll introduce them
> next.
>
> Signed-off-by: Tomasz Jeznach 
> Signed-off-by: Daniel Henrique Barboza 
> Reviewed-by: Frank Chang 

Acked-by: Alistair Francis 

Alistair

> ---
>  hw/riscv/riscv-iommu.c | 199 -
>  hw/riscv/riscv-iommu.h |   3 +
>  2 files changed, 198 insertions(+), 4 deletions(-)
>
> diff --git a/hw/riscv/riscv-iommu.c b/hw/riscv/riscv-iommu.c
> index 5faa76a904..76728baa77 100644
> --- a/hw/riscv/riscv-iommu.c
> +++ b/hw/riscv/riscv-iommu.c
> @@ -65,6 +65,16 @@ struct RISCVIOMMUContext {
>  uint64_t msiptp;/* MSI redirection page table pointer */
>  };
>
> +/* Address translation cache entry */
> +struct RISCVIOMMUEntry {
> +uint64_t iova:44;   /* IOVA Page Number */
> +uint64_t pscid:20;  /* Process Soft-Context identifier */
> +uint64_t phys:44;   /* Physical Page Number */
> +uint64_t gscid:16;  /* Guest Soft-Context identifier */
> +uint64_t perm:2;/* IOMMU_RW flags */
> +uint64_t __rfu:2;
> +};
> +
>  /* IOMMU index for transactions without process_id specified. */
>  #define RISCV_IOMMU_NOPROCID 0
>
> @@ -1130,13 +1140,130 @@ static AddressSpace 
> *riscv_iommu_space(RISCVIOMMUState *s, uint32_t devid)
>  return >iova_as;
>  }
>
> +/* Translation Object cache support */
> +static gboolean __iot_equal(gconstpointer v1, gconstpointer v2)
> +{
> +RISCVIOMMUEntry *t1 = (RISCVIOMMUEntry *) v1;
> +RISCVIOMMUEntry *t2 = (RISCVIOMMUEntry *) v2;
> +return t1->gscid == t2->gscid && t1->pscid == t2->pscid &&
> +   t1->iova == t2->iova;
> +}
> +
> +static guint __iot_hash(gconstpointer v)
> +{
> +RISCVIOMMUEntry *t = (RISCVIOMMUEntry *) v;
> +return (guint)t->iova;
> +}
> +
> +/* GV: 1 PSCV: 1 AV: 1 */
> +static void __iot_inval_pscid_iova(gpointer key, gpointer value, gpointer 
> data)
> +{
> +RISCVIOMMUEntry *iot = (RISCVIOMMUEntry *) value;
> +RISCVIOMMUEntry *arg = (RISCVIOMMUEntry *) data;
> +if (iot->gscid == arg->gscid &&
> +iot->pscid == arg->pscid &&
> +iot->iova == arg->iova) {
> +iot->perm = IOMMU_NONE;
> +}
> +}
> +
> +/* GV: 1 PSCV: 1 AV: 0 */
> +static void __iot_inval_pscid(gpointer key, gpointer value, gpointer data)
> +{
> +RISCVIOMMUEntry *iot = (RISCVIOMMUEntry *) value;
> +RISCVIOMMUEntry *arg = (RISCVIOMMUEntry *) data;
> +if (iot->gscid == arg->gscid &&
> +iot->pscid == arg->pscid) {
> +iot->perm = IOMMU_NONE;
> +}
> +}
> +
> +/* GV: 1 GVMA: 1 */
> +static void __iot_inval_gscid_gpa(gpointer key, gpointer value, gpointer 
> data)
> +{
> +RISCVIOMMUEntry *iot = (RISCVIOMMUEntry *) value;
> +RISCVIOMMUEntry *arg = (RISCVIOMMUEntry *) data;
> +if (iot->gscid == arg->gscid) {
> +/* simplified cache, no GPA matching */
> +iot->perm = IOMMU_NONE;
> +}
> +}
> +
> +/* GV: 1 GVMA: 0 */
> +static void __iot_inval_gscid(gpointer key, gpointer value, gpointer data)
> +{
> +RISCVIOMMUEntry *iot = (RISCVIOMMUEntry *) value;
> +RISCVIOMMUEntry *arg = (RISCVIOMMUEntry *) data;
> +if (iot->gscid == arg->gscid) {
> +iot->perm = IOMMU_NONE;
> +}
> +}
> +
> +/* GV: 0 */
> +static void __iot_inval_all(gpointer key, gpointer value, gpointer data)
> +{
> +RISCVIOMMUEntry *iot = (RISCVIOMMUEntry *) value;
> +iot->perm = IOMMU_NONE;
> +}
> +
> +/* caller should keep ref-count for iot_cache object */
> +static RISCVIOMMUEntry *riscv_iommu_iot_lookup(RISCVIOMMUContext *ctx,
> +GHashTable *iot_cache, hwaddr iova)
> +{
> +RISCVIOMMUEntry key = {
> +.gscid = get_field(ctx->gatp, RISCV_IOMMU_DC_IOHGATP_GSCID),
> +.pscid = get_field(ctx->ta, RISCV_IOMMU_DC_TA_PSCID),
> +.iova  = PPN_DOWN(iova),
> +};
> +return g_hash_table_lookup(iot_cache, );
> +}
> +
> +/* caller should keep ref-count for iot_cache object */
> +static void riscv_iommu_iot_update(RISCVIOMMUState *s,
> +GHashTable *iot_cache, RISCVIOMMUEntry *iot)
> +{
> +if (!s->iot_lim

Re: [PATCH v5 05/13] hw/riscv: add riscv-iommu-pci reference device

2024-07-17 Thread Alistair Francis
On Tue, Jul 9, 2024 at 3:38 AM Daniel Henrique Barboza
 wrote:
>
> From: Tomasz Jeznach 
>
> The RISC-V IOMMU can be modelled as a PCIe device following the
> guidelines of the RISC-V IOMMU spec, chapter 7.1, "Integrating an IOMMU
> as a PCIe device".
>
> Signed-off-by: Tomasz Jeznach 
> Signed-off-by: Daniel Henrique Barboza 
> Reviewed-by: Frank Chang 

Reviewed-by: Alistair Francis 

Alistair

> ---
>  hw/riscv/meson.build   |   2 +-
>  hw/riscv/riscv-iommu-pci.c | 178 +
>  2 files changed, 179 insertions(+), 1 deletion(-)
>  create mode 100644 hw/riscv/riscv-iommu-pci.c
>
> diff --git a/hw/riscv/meson.build b/hw/riscv/meson.build
> index cbc99c6e8e..adbef8a9b2 100644
> --- a/hw/riscv/meson.build
> +++ b/hw/riscv/meson.build
> @@ -10,6 +10,6 @@ riscv_ss.add(when: 'CONFIG_SIFIVE_U', if_true: 
> files('sifive_u.c'))
>  riscv_ss.add(when: 'CONFIG_SPIKE', if_true: files('spike.c'))
>  riscv_ss.add(when: 'CONFIG_MICROCHIP_PFSOC', if_true: 
> files('microchip_pfsoc.c'))
>  riscv_ss.add(when: 'CONFIG_ACPI', if_true: files('virt-acpi-build.c'))
> -riscv_ss.add(when: 'CONFIG_RISCV_IOMMU', if_true: files('riscv-iommu.c'))
> +riscv_ss.add(when: 'CONFIG_RISCV_IOMMU', if_true: files('riscv-iommu.c', 
> 'riscv-iommu-pci.c'))
>
>  hw_arch += {'riscv': riscv_ss}
> diff --git a/hw/riscv/riscv-iommu-pci.c b/hw/riscv/riscv-iommu-pci.c
> new file mode 100644
> index 00..7b82ce0645
> --- /dev/null
> +++ b/hw/riscv/riscv-iommu-pci.c
> @@ -0,0 +1,178 @@
> +/*
> + * QEMU emulation of an RISC-V IOMMU
> + *
> + * Copyright (C) 2022-2023 Rivos Inc.
> + *
> + * This program is free software; you can redistribute it and/or modify
> + * it under the terms of the GNU General Public License as published by
> + * the Free Software Foundation; either version 2 of the License.
> + *
> + * This program is distributed in the hope that it will be useful,
> + * but WITHOUT ANY WARRANTY; without even the implied warranty of
> + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
> + * GNU 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 "hw/pci/msi.h"
> +#include "hw/pci/msix.h"
> +#include "hw/pci/pci_bus.h"
> +#include "hw/qdev-properties.h"
> +#include "hw/riscv/riscv_hart.h"
> +#include "migration/vmstate.h"
> +#include "qapi/error.h"
> +#include "qemu/error-report.h"
> +#include "qemu/host-utils.h"
> +#include "qom/object.h"
> +
> +#include "cpu_bits.h"
> +#include "riscv-iommu.h"
> +#include "riscv-iommu-bits.h"
> +
> +/* RISC-V IOMMU PCI Device Emulation */
> +#define RISCV_PCI_CLASS_SYSTEM_IOMMU 0x0806
> +
> +typedef struct RISCVIOMMUStatePci {
> +PCIDevicepci; /* Parent PCIe device state */
> +uint16_t vendor_id;
> +uint16_t device_id;
> +uint8_t  revision;
> +MemoryRegion bar0;/* PCI BAR (including MSI-x config) */
> +RISCVIOMMUState  iommu;   /* common IOMMU state */
> +} RISCVIOMMUStatePci;
> +
> +/* interrupt delivery callback */
> +static void riscv_iommu_pci_notify(RISCVIOMMUState *iommu, unsigned vector)
> +{
> +RISCVIOMMUStatePci *s = container_of(iommu, RISCVIOMMUStatePci, iommu);
> +
> +if (msix_enabled(&(s->pci))) {
> +msix_notify(&(s->pci), vector);
> +}
> +}
> +
> +static void riscv_iommu_pci_realize(PCIDevice *dev, Error **errp)
> +{
> +RISCVIOMMUStatePci *s = DO_UPCAST(RISCVIOMMUStatePci, pci, dev);
> +RISCVIOMMUState *iommu = >iommu;
> +uint8_t *pci_conf = dev->config;
> +Error *err = NULL;
> +
> +pci_set_word(pci_conf + PCI_VENDOR_ID, s->vendor_id);
> +pci_set_word(pci_conf + PCI_SUBSYSTEM_VENDOR_ID, s->vendor_id);
> +pci_set_word(pci_conf + PCI_DEVICE_ID, s->device_id);
> +pci_set_word(pci_conf + PCI_SUBSYSTEM_ID, s->device_id);
> +pci_set_byte(pci_conf + PCI_REVISION_ID, s->revision);
> +
> +/* Set device id for trace / debug */
> +DEVICE(iommu)->id = g_strdup_printf("%02x:%02x.%01x",
> +pci_dev_bus_num(dev), PCI_SLOT(dev->devfn), PCI_FUNC(dev->devfn));
> +qdev_realize(DEVICE(iommu), NULL, errp);
> +
> +memory_region_init(>bar0, OBJECT(s), "riscv-iommu-bar0",
> +QEMU_ALIGN_UP(memory_region_size(>regs_mr), 
> TARGET_PAGE_SIZE));
> +memory_re

Re: [PATCH v5 03/13] hw/riscv: add RISC-V IOMMU base emulation

2024-07-17 Thread Alistair Francis
On Tue, Jul 9, 2024 at 3:37 AM Daniel Henrique Barboza
 wrote:
>
> From: Tomasz Jeznach 
>
> The RISC-V IOMMU specification is now ratified as-per the RISC-V
> international process. The latest frozen specifcation can be found at:
>
> https://github.com/riscv-non-isa/riscv-iommu/releases/download/v1.0/riscv-iommu.pdf
>
> Add the foundation of the device emulation for RISC-V IOMMU. It includes
> support for s-stage (sv32, sv39, sv48, sv57 caps) and g-stage (sv32x4,
> sv39x4, sv48x4, sv57x4 caps).
>
> Other capabilities like ATS and DBG support will be added incrementally
> in the next patches.
>
> Co-developed-by: Sebastien Boeuf 
> Signed-off-by: Sebastien Boeuf 
> Signed-off-by: Tomasz Jeznach 
> Signed-off-by: Daniel Henrique Barboza 
> ---
>  hw/riscv/Kconfig|4 +
>  hw/riscv/meson.build|1 +
>  hw/riscv/riscv-iommu-bits.h |   14 +
>  hw/riscv/riscv-iommu.c  | 1994 +++
>  hw/riscv/riscv-iommu.h  |  144 +++
>  hw/riscv/trace-events   |   11 +
>  hw/riscv/trace.h|1 +
>  include/hw/riscv/iommu.h|   36 +
>  meson.build |1 +
>  9 files changed, 2206 insertions(+)
>  create mode 100644 hw/riscv/riscv-iommu.c
>  create mode 100644 hw/riscv/riscv-iommu.h
>  create mode 100644 hw/riscv/trace-events
>  create mode 100644 hw/riscv/trace.h
>  create mode 100644 include/hw/riscv/iommu.h
>
> diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig
> index a2030e3a6f..f69d6e3c8e 100644
> --- a/hw/riscv/Kconfig
> +++ b/hw/riscv/Kconfig
> @@ -1,3 +1,6 @@
> +config RISCV_IOMMU
> +bool
> +
>  config RISCV_NUMA
>  bool
>
> @@ -47,6 +50,7 @@ config RISCV_VIRT
>  select SERIAL
>  select RISCV_ACLINT
>  select RISCV_APLIC
> +select RISCV_IOMMU
>  select RISCV_IMSIC
>  select SIFIVE_PLIC
>  select SIFIVE_TEST
> diff --git a/hw/riscv/meson.build b/hw/riscv/meson.build
> index f872674093..cbc99c6e8e 100644
> --- a/hw/riscv/meson.build
> +++ b/hw/riscv/meson.build
> @@ -10,5 +10,6 @@ riscv_ss.add(when: 'CONFIG_SIFIVE_U', if_true: 
> files('sifive_u.c'))
>  riscv_ss.add(when: 'CONFIG_SPIKE', if_true: files('spike.c'))
>  riscv_ss.add(when: 'CONFIG_MICROCHIP_PFSOC', if_true: 
> files('microchip_pfsoc.c'))
>  riscv_ss.add(when: 'CONFIG_ACPI', if_true: files('virt-acpi-build.c'))
> +riscv_ss.add(when: 'CONFIG_RISCV_IOMMU', if_true: files('riscv-iommu.c'))
>
>  hw_arch += {'riscv': riscv_ss}
> diff --git a/hw/riscv/riscv-iommu-bits.h b/hw/riscv/riscv-iommu-bits.h
> index eda1ba5575..1dd2e2c7d6 100644
> --- a/hw/riscv/riscv-iommu-bits.h
> +++ b/hw/riscv/riscv-iommu-bits.h
> @@ -69,6 +69,14 @@ struct riscv_iommu_pq_record {
>  /* 5.3 IOMMU Capabilities (64bits) */
>  #define RISCV_IOMMU_REG_CAP 0x
>  #define RISCV_IOMMU_CAP_VERSION GENMASK_ULL(7, 0)
> +#define RISCV_IOMMU_CAP_SV32BIT_ULL(8)
> +#define RISCV_IOMMU_CAP_SV39BIT_ULL(9)
> +#define RISCV_IOMMU_CAP_SV48BIT_ULL(10)
> +#define RISCV_IOMMU_CAP_SV57BIT_ULL(11)
> +#define RISCV_IOMMU_CAP_SV32X4  BIT_ULL(16)
> +#define RISCV_IOMMU_CAP_SV39X4  BIT_ULL(17)
> +#define RISCV_IOMMU_CAP_SV48X4  BIT_ULL(18)
> +#define RISCV_IOMMU_CAP_SV57X4  BIT_ULL(19)
>  #define RISCV_IOMMU_CAP_MSI_FLATBIT_ULL(22)
>  #define RISCV_IOMMU_CAP_MSI_MRIFBIT_ULL(23)
>  #define RISCV_IOMMU_CAP_T2GPA   BIT_ULL(26)
> @@ -80,7 +88,9 @@ struct riscv_iommu_pq_record {
>
>  /* 5.4 Features control register (32bits) */
>  #define RISCV_IOMMU_REG_FCTL0x0008
> +#define RISCV_IOMMU_FCTL_BE BIT(0)
>  #define RISCV_IOMMU_FCTL_WSIBIT(1)
> +#define RISCV_IOMMU_FCTL_GXLBIT(2)
>
>  /* 5.5 Device-directory-table pointer (64bits) */
>  #define RISCV_IOMMU_REG_DDTP0x0010
> @@ -203,6 +213,8 @@ struct riscv_iommu_dc {
>  #define RISCV_IOMMU_DC_TC_DTF   BIT_ULL(4)
>  #define RISCV_IOMMU_DC_TC_PDTV  BIT_ULL(5)
>  #define RISCV_IOMMU_DC_TC_PRPR  BIT_ULL(6)
> +#define RISCV_IOMMU_DC_TC_GADE  BIT_ULL(7)
> +#define RISCV_IOMMU_DC_TC_SADE  BIT_ULL(8)
>  #define RISCV_IOMMU_DC_TC_DPE   BIT_ULL(9)
>  #define RISCV_IOMMU_DC_TC_SBE   BIT_ULL(10)
>  #define RISCV_IOMMU_DC_TC_SXL   BIT_ULL(11)
> @@ -309,9 +321,11 @@ enum riscv_iommu_fq_causes {
>
>  /* Translation attributes fields */
>  #define RISCV_IOMMU_PC_TA_V BIT_ULL(0)
> +#define RISCV_IOMMU_PC_TA_RESERVED  GENMASK_ULL(63, 32)
>
>  /* First stage context fields */
>  #define RISCV_IOMMU_PC_FSC_PPN  GENMASK_ULL(43, 0)
> +#define RISCV_IOMMU_PC_FSC_RESERVED GENMASK_ULL(59, 44)
>
>  enum riscv_iommu_fq_ttypes {
>  RISCV_IOMMU_FQ_TTYPE_NONE = 0,
> diff --git a/hw/riscv/riscv-iommu.c b/hw/riscv/riscv-iommu.c
> new file mode 100644
> index 00..5faa76a904
> --- /dev/null
> +++ b/hw/riscv/riscv-iommu.c
> @@ -0,0 +1,1994 @@
> +/*
> + * QEMU emulation of an RISC-V IOMMU
> + 

[PULL 29/30] hw/riscv/virt.c: re-insert and deprecate 'riscv, delegate'

2024-07-17 Thread Alistair Francis
From: Daniel Henrique Barboza 

Commit b1f1e9dcfa renamed 'riscv,delegate' to 'riscv,delegation' since
it is the correct name as per dt-bindings, and the absence of the
correct name will result in validation fails when dumping the dtb and
using dt-validate.

But this change has a side-effect: every other firmware available that
is AIA capable is using 'riscv,delegate', and it will fault/misbehave if
this property isn't present. The property was added back in QEMU 7.0,
meaning we have 2 years of firmware development using the wrong
property.

Re-introducing 'riscv,delegate' while keeping 'riscv,delegation' allows
older firmwares to keep booting with the 'virt' machine.
'riscv,delegate' is then marked for future deprecation with its use
being discouraged from now on.

Cc: Conor Dooley 
Cc: Anup Patel 
Fixes: b1f1e9dcfa ("hw/riscv/virt.c: aplic DT: rename prop to 'riscv, 
delegation'")
Signed-off-by: Daniel Henrique Barboza 
Reviewed-by: Alistair Francis 
Message-ID: <20240715090455.145888-1-dbarb...@ventanamicro.com>
Signed-off-by: Alistair Francis 
---
 docs/about/deprecated.rst | 11 +++
 hw/riscv/virt.c   |  9 +
 2 files changed, 20 insertions(+)

diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst
index 20b7a17cf0..88f0f03786 100644
--- a/docs/about/deprecated.rst
+++ b/docs/about/deprecated.rst
@@ -479,6 +479,17 @@ versions, aliases will point to newer CPU model versions
 depending on the machine type, so management software must
 resolve CPU model aliases before starting a virtual machine.
 
+RISC-V "virt" board "riscv,delegate" DT property (since 9.1)
+
+
+The "riscv,delegate" DT property was added in QEMU 7.0 as part of
+the AIA APLIC support.  The property changed name during the review
+process in Linux and the correct name ended up being
+"riscv,delegation".  Changing the DT property name will break all
+available firmwares that are using the current (wrong) name.  The
+property is kept as is in 9.1, together with "riscv,delegation", to
+give more time for firmware developers to change their code.
+
 Migration
 -
 
diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
index bc0893e087..9981e0f6c9 100644
--- a/hw/riscv/virt.c
+++ b/hw/riscv/virt.c
@@ -651,6 +651,15 @@ static void create_fdt_one_aplic(RISCVVirtState *s, int 
socket,
 qemu_fdt_setprop_cells(ms->fdt, aplic_name, "riscv,delegation",
aplic_child_phandle, 0x1,
VIRT_IRQCHIP_NUM_SOURCES);
+/*
+ * DEPRECATED_9.1: Compat property kept temporarily
+ * to allow old firmwares to work with AIA. Do *not*
+ * use 'riscv,delegate' in new code: use
+ * 'riscv,delegation' instead.
+ */
+qemu_fdt_setprop_cells(ms->fdt, aplic_name, "riscv,delegate",
+   aplic_child_phandle, 0x1,
+   VIRT_IRQCHIP_NUM_SOURCES);
 }
 
 riscv_socket_fdt_write_id(ms, aplic_name, socket);
-- 
2.45.2




[PULL 15/30] target/riscv: Combine set_mode and set_virt functions.

2024-07-17 Thread Alistair Francis
From: Rajnesh Kanwal 

Combining riscv_cpu_set_virt_enabled() and riscv_cpu_set_mode()
functions. This is to make complete mode change information
available through a single function.

This allows to easily differentiate between HS->VS, VS->HS
and VS->VS transitions when executing state update codes.
For example: One use-case which inspired this change is
to update mode-specific instruction and cycle counters
which requires information of both prev mode and current
mode.

Signed-off-by: Rajnesh Kanwal 
Reviewed-by: Alistair Francis 
Reviewed-by: Daniel Henrique Barboza 
Message-ID: <20240711-smcntrpmf_v7-v8-1-b7c38ae7b...@rivosinc.com>
Signed-off-by: Alistair Francis 
---
 target/riscv/cpu.h|  2 +-
 target/riscv/cpu_helper.c | 57 +++
 target/riscv/op_helper.c  | 17 +---
 3 files changed, 35 insertions(+), 41 deletions(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 87742047ce..6520e0f5d5 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -567,7 +567,7 @@ void riscv_cpu_set_aia_ireg_rmw_fn(CPURISCVState *env, 
uint32_t priv,
 RISCVException smstateen_acc_ok(CPURISCVState *env, int index, uint64_t bit);
 #endif /* !CONFIG_USER_ONLY */
 
-void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv);
+void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv, bool 
virt_en);
 
 void riscv_translate_init(void);
 G_NORETURN void riscv_raise_exception(CPURISCVState *env,
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 6709622dd3..10d3fdaed3 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -619,30 +619,6 @@ void riscv_cpu_set_geilen(CPURISCVState *env, target_ulong 
geilen)
 env->geilen = geilen;
 }
 
-/* This function can only be called to set virt when RVH is enabled */
-void riscv_cpu_set_virt_enabled(CPURISCVState *env, bool enable)
-{
-/* Flush the TLB on all virt mode changes. */
-if (env->virt_enabled != enable) {
-tlb_flush(env_cpu(env));
-}
-
-env->virt_enabled = enable;
-
-if (enable) {
-/*
- * The guest external interrupts from an interrupt controller are
- * delivered only when the Guest/VM is running (i.e. V=1). This means
- * any guest external interrupt which is triggered while the Guest/VM
- * is not running (i.e. V=0) will be missed on QEMU resulting in guest
- * with sluggish response to serial console input and other I/O events.
- *
- * To solve this, we check and inject interrupt after setting V=1.
- */
-riscv_cpu_update_mip(env, 0, 0);
-}
-}
-
 int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint64_t interrupts)
 {
 CPURISCVState *env = >env;
@@ -715,7 +691,7 @@ void riscv_cpu_set_aia_ireg_rmw_fn(CPURISCVState *env, 
uint32_t priv,
 }
 }
 
-void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv)
+void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv, bool virt_en)
 {
 g_assert(newpriv <= PRV_M && newpriv != PRV_RESERVED);
 
@@ -736,6 +712,28 @@ void riscv_cpu_set_mode(CPURISCVState *env, target_ulong 
newpriv)
  * preemptive context switch. As a result, do both.
  */
 env->load_res = -1;
+
+if (riscv_has_ext(env, RVH)) {
+/* Flush the TLB on all virt mode changes. */
+if (env->virt_enabled != virt_en) {
+tlb_flush(env_cpu(env));
+}
+
+env->virt_enabled = virt_en;
+if (virt_en) {
+/*
+ * The guest external interrupts from an interrupt controller are
+ * delivered only when the Guest/VM is running (i.e. V=1). This
+ * means any guest external interrupt which is triggered while the
+ * Guest/VM is not running (i.e. V=0) will be missed on QEMU
+ * resulting in guest with sluggish response to serial console
+ * input and other I/O events.
+ *
+ * To solve this, we check and inject interrupt after setting V=1.
+ */
+riscv_cpu_update_mip(env, 0, 0);
+}
+}
 }
 
 /*
@@ -1648,6 +1646,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
 {
 RISCVCPU *cpu = RISCV_CPU(cs);
 CPURISCVState *env = >env;
+bool virt = env->virt_enabled;
 bool write_gva = false;
 uint64_t s;
 
@@ -1778,7 +1777,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
 
 htval = env->guest_phys_fault_addr;
 
-riscv_cpu_set_virt_enabled(env, 0);
+virt = false;
 } else {
 /* Trap into HS mode */
 env->hstatus = set_field(env->hstatus, HSTATUS_SPV, false);
@@ -1799,7 +1798,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
 env->htinst = tinst;
 env->pc = (env->stvec >> 2 << 2) +
   ((async && (env->stvec & 3) == 1) ? cau

[PULL 27/30] target/riscv: Expose the Smcntrpmf config

2024-07-17 Thread Alistair Francis
From: Atish Patra 

Create a new config for Smcntrpmf extension so that it can be enabled/
disabled from the qemu commandline.

Signed-off-by: Atish Patra 
Acked-by: Alistair Francis 
Message-ID: <20240711-smcntrpmf_v7-v8-13-b7c38ae7b...@rivosinc.com>
Signed-off-by: Alistair Francis 
---
 target/riscv/cpu.c | 1 +
 1 file changed, 1 insertion(+)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 4efe7ee3b0..a90808a3ba 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -1472,6 +1472,7 @@ const char *riscv_get_misa_ext_description(uint32_t bit)
 const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
 /* Defaults for standard extensions */
 MULTI_EXT_CFG_BOOL("sscofpmf", ext_sscofpmf, false),
+MULTI_EXT_CFG_BOOL("smcntrpmf", ext_smcntrpmf, false),
 MULTI_EXT_CFG_BOOL("zifencei", ext_zifencei, true),
 MULTI_EXT_CFG_BOOL("zicsr", ext_zicsr, true),
 MULTI_EXT_CFG_BOOL("zihintntl", ext_zihintntl, true),
-- 
2.45.2




[PULL 06/30] target/riscv: Move gen_amo before implement Zabha

2024-07-17 Thread Alistair Francis
From: LIU Zhiwei 

Signed-off-by: LIU Zhiwei 
Acked-by: Alistair Francis 
Message-ID: <20240709113652.1239-7-zhiwei_...@linux.alibaba.com>
Signed-off-by: Alistair Francis 
---
 target/riscv/translate.c| 21 +
 target/riscv/insn_trans/trans_rva.c.inc | 21 -
 2 files changed, 21 insertions(+), 21 deletions(-)

diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 8a546f4ece..133550d6e2 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -1077,6 +1077,27 @@ static bool gen_unary_per_ol(DisasContext *ctx, arg_r2 
*a, DisasExtend ext,
 return gen_unary(ctx, a, ext, f_tl);
 }
 
+static bool gen_amo(DisasContext *ctx, arg_atomic *a,
+void(*func)(TCGv, TCGv, TCGv, TCGArg, MemOp),
+MemOp mop)
+{
+TCGv dest = dest_gpr(ctx, a->rd);
+TCGv src1, src2 = get_gpr(ctx, a->rs2, EXT_NONE);
+
+if (ctx->cfg_ptr->ext_zama16b) {
+mop |= MO_ATOM_WITHIN16;
+} else {
+mop |= MO_ALIGN;
+}
+
+decode_save_opc(ctx);
+src1 = get_address(ctx, a->rs1, 0);
+func(dest, src1, src2, ctx->mem_idx, mop);
+
+gen_set_gpr(ctx, a->rd, dest);
+return true;
+}
+
 static uint32_t opcode_at(DisasContextBase *dcbase, target_ulong pc)
 {
 DisasContext *ctx = container_of(dcbase, DisasContext, base);
diff --git a/target/riscv/insn_trans/trans_rva.c.inc 
b/target/riscv/insn_trans/trans_rva.c.inc
index eb080baddd..39bbf60f3c 100644
--- a/target/riscv/insn_trans/trans_rva.c.inc
+++ b/target/riscv/insn_trans/trans_rva.c.inc
@@ -96,27 +96,6 @@ static bool gen_sc(DisasContext *ctx, arg_atomic *a, MemOp 
mop)
 return true;
 }
 
-static bool gen_amo(DisasContext *ctx, arg_atomic *a,
-void(*func)(TCGv, TCGv, TCGv, TCGArg, MemOp),
-MemOp mop)
-{
-TCGv dest = dest_gpr(ctx, a->rd);
-TCGv src1, src2 = get_gpr(ctx, a->rs2, EXT_NONE);
-
-if (ctx->cfg_ptr->ext_zama16b) {
-mop |= MO_ATOM_WITHIN16;
-} else {
-mop |= MO_ALIGN;
-}
-
-decode_save_opc(ctx);
-src1 = get_address(ctx, a->rs1, 0);
-func(dest, src1, src2, ctx->mem_idx, mop);
-
-gen_set_gpr(ctx, a->rd, dest);
-return true;
-}
-
 static bool trans_lr_w(DisasContext *ctx, arg_lr_w *a)
 {
 REQUIRE_A_OR_ZALRSC(ctx);
-- 
2.45.2




[PULL 26/30] target/riscv: Do not setup pmu timer if OF is disabled

2024-07-17 Thread Alistair Francis
From: Atish Patra 

The timer is setup function is invoked in both hpmcounter
write and mcountinhibit write path. If the OF bit set, the
LCOFI interrupt is disabled. There is no benefitting in
setting up the qemu timer until LCOFI is cleared to indicate
that interrupts can be fired again.

Reviewed-by: Daniel Henrique Barboza 
Signed-off-by: Atish Patra 
Message-ID: <20240711-smcntrpmf_v7-v8-12-b7c38ae7b...@rivosinc.com>
Signed-off-by: Alistair Francis 
---
 target/riscv/pmu.c | 56 --
 1 file changed, 44 insertions(+), 12 deletions(-)

diff --git a/target/riscv/pmu.c b/target/riscv/pmu.c
index a4729f6c53..3cc0b3648c 100644
--- a/target/riscv/pmu.c
+++ b/target/riscv/pmu.c
@@ -416,14 +416,49 @@ int riscv_pmu_update_event_map(CPURISCVState *env, 
uint64_t value,
 return 0;
 }
 
+static bool pmu_hpmevent_is_of_set(CPURISCVState *env, uint32_t ctr_idx)
+{
+target_ulong mhpmevent_val;
+uint64_t of_bit_mask;
+
+if (riscv_cpu_mxl(env) == MXL_RV32) {
+mhpmevent_val = env->mhpmeventh_val[ctr_idx];
+of_bit_mask = MHPMEVENTH_BIT_OF;
+ } else {
+mhpmevent_val = env->mhpmevent_val[ctr_idx];
+of_bit_mask = MHPMEVENT_BIT_OF;
+}
+
+return get_field(mhpmevent_val, of_bit_mask);
+}
+
+static bool pmu_hpmevent_set_of_if_clear(CPURISCVState *env, uint32_t ctr_idx)
+{
+target_ulong *mhpmevent_val;
+uint64_t of_bit_mask;
+
+if (riscv_cpu_mxl(env) == MXL_RV32) {
+mhpmevent_val = >mhpmeventh_val[ctr_idx];
+of_bit_mask = MHPMEVENTH_BIT_OF;
+ } else {
+mhpmevent_val = >mhpmevent_val[ctr_idx];
+of_bit_mask = MHPMEVENT_BIT_OF;
+}
+
+if (!get_field(*mhpmevent_val, of_bit_mask)) {
+*mhpmevent_val |= of_bit_mask;
+return true;
+}
+
+return false;
+}
+
 static void pmu_timer_trigger_irq(RISCVCPU *cpu,
   enum riscv_pmu_event_idx evt_idx)
 {
 uint32_t ctr_idx;
 CPURISCVState *env = >env;
 PMUCTRState *counter;
-target_ulong *mhpmevent_val;
-uint64_t of_bit_mask;
 int64_t irq_trigger_at;
 uint64_t curr_ctr_val, curr_ctrh_val;
 uint64_t ctr_val;
@@ -439,12 +474,9 @@ static void pmu_timer_trigger_irq(RISCVCPU *cpu,
 return;
 }
 
-if (riscv_cpu_mxl(env) == MXL_RV32) {
-mhpmevent_val = >mhpmeventh_val[ctr_idx];
-of_bit_mask = MHPMEVENTH_BIT_OF;
- } else {
-mhpmevent_val = >mhpmevent_val[ctr_idx];
-of_bit_mask = MHPMEVENT_BIT_OF;
+/* Generate interrupt only if OF bit is clear */
+if (pmu_hpmevent_is_of_set(env, ctr_idx)) {
+return;
 }
 
 counter = >pmu_ctrs[ctr_idx];
@@ -477,9 +509,7 @@ static void pmu_timer_trigger_irq(RISCVCPU *cpu,
 }
 
 if (cpu->pmu_avail_ctrs & BIT(ctr_idx)) {
-/* Generate interrupt only if OF bit is clear */
-if (!(*mhpmevent_val & of_bit_mask)) {
-*mhpmevent_val |= of_bit_mask;
+if (pmu_hpmevent_set_of_if_clear(env, ctr_idx)) {
 riscv_cpu_update_mip(env, MIP_LCOFIP, BOOL_TO_MASK(1));
 }
 }
@@ -502,7 +532,9 @@ int riscv_pmu_setup_timer(CPURISCVState *env, uint64_t 
value, uint32_t ctr_idx)
 RISCVCPU *cpu = env_archcpu(env);
 PMUCTRState *counter = >pmu_ctrs[ctr_idx];
 
-if (!riscv_pmu_counter_valid(cpu, ctr_idx) || !cpu->cfg.ext_sscofpmf) {
+/* No need to setup a timer if LCOFI is disabled when OF is set */
+if (!riscv_pmu_counter_valid(cpu, ctr_idx) || !cpu->cfg.ext_sscofpmf ||
+pmu_hpmevent_is_of_set(env, ctr_idx)) {
 return -1;
 }
 
-- 
2.45.2




[PULL 23/30] target/riscv: Enforce WARL behavior for scounteren/hcounteren

2024-07-17 Thread Alistair Francis
From: Atish Patra 

scounteren/hcountern are also WARL registers similar to mcountern.
Only set the bits for the available counters during the write to
preserve the WARL behavior.

Signed-off-by: Atish Patra 
Reviewed-by: Daniel Henrique Barboza 
Reviewed-by: Alistair Francis 
Message-ID: <20240711-smcntrpmf_v7-v8-9-b7c38ae7b...@rivosinc.com>
Signed-off-by: Alistair Francis 
---
 target/riscv/csr.c | 12 ++--
 1 file changed, 10 insertions(+), 2 deletions(-)

diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index b7a24f9c60..d6c5b73afd 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -3063,7 +3063,11 @@ static RISCVException read_scounteren(CPURISCVState 
*env, int csrno,
 static RISCVException write_scounteren(CPURISCVState *env, int csrno,
target_ulong val)
 {
-env->scounteren = val;
+RISCVCPU *cpu = env_archcpu(env);
+
+/* WARL register - disable unavailable counters */
+env->scounteren = val & (cpu->pmu_avail_ctrs | COUNTEREN_CY | COUNTEREN_TM 
|
+ COUNTEREN_IR);
 return RISCV_EXCP_NONE;
 }
 
@@ -3722,7 +3726,11 @@ static RISCVException read_hcounteren(CPURISCVState 
*env, int csrno,
 static RISCVException write_hcounteren(CPURISCVState *env, int csrno,
target_ulong val)
 {
-env->hcounteren = val;
+RISCVCPU *cpu = env_archcpu(env);
+
+/* WARL register - disable unavailable counters */
+env->hcounteren = val & (cpu->pmu_avail_ctrs | COUNTEREN_CY | COUNTEREN_TM 
|
+ COUNTEREN_IR);
 return RISCV_EXCP_NONE;
 }
 
-- 
2.45.2




[PULL 14/30] target/riscv/kvm: update KVM regs to Linux 6.10-rc5

2024-07-17 Thread Alistair Francis
From: Daniel Henrique Barboza 

Two new regs added: ztso and zacas.

Signed-off-by: Daniel Henrique Barboza 
Reviewed-by: Alistair Francis 
Message-ID: <20240709085431.455541-1-dbarb...@ventanamicro.com>
Signed-off-by: Alistair Francis 
---
 target/riscv/kvm/kvm-cpu.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c
index 1047961fed..f6e3156b8d 100644
--- a/target/riscv/kvm/kvm-cpu.c
+++ b/target/riscv/kvm/kvm-cpu.c
@@ -281,6 +281,7 @@ static KVMCPUConfig kvm_multi_ext_cfgs[] = {
 KVM_EXT_CFG("zihintntl", ext_zihintntl, KVM_RISCV_ISA_EXT_ZIHINTNTL),
 KVM_EXT_CFG("zihintpause", ext_zihintpause, KVM_RISCV_ISA_EXT_ZIHINTPAUSE),
 KVM_EXT_CFG("zihpm", ext_zihpm, KVM_RISCV_ISA_EXT_ZIHPM),
+KVM_EXT_CFG("zacas", ext_zacas, KVM_RISCV_ISA_EXT_ZACAS),
 KVM_EXT_CFG("zfa", ext_zfa, KVM_RISCV_ISA_EXT_ZFA),
 KVM_EXT_CFG("zfh", ext_zfh, KVM_RISCV_ISA_EXT_ZFH),
 KVM_EXT_CFG("zfhmin", ext_zfhmin, KVM_RISCV_ISA_EXT_ZFHMIN),
@@ -298,6 +299,7 @@ static KVMCPUConfig kvm_multi_ext_cfgs[] = {
 KVM_EXT_CFG("zksed", ext_zksed, KVM_RISCV_ISA_EXT_ZKSED),
 KVM_EXT_CFG("zksh", ext_zksh, KVM_RISCV_ISA_EXT_ZKSH),
 KVM_EXT_CFG("zkt", ext_zkt, KVM_RISCV_ISA_EXT_ZKT),
+KVM_EXT_CFG("ztso", ext_ztso, KVM_RISCV_ISA_EXT_ZTSO),
 KVM_EXT_CFG("zvbb", ext_zvbb, KVM_RISCV_ISA_EXT_ZVBB),
 KVM_EXT_CFG("zvbc", ext_zvbc, KVM_RISCV_ISA_EXT_ZVBC),
 KVM_EXT_CFG("zvfh", ext_zvfh, KVM_RISCV_ISA_EXT_ZVFH),
-- 
2.45.2




[PULL 28/30] target/riscv: raise an exception when CSRRS/CSRRC writes a read-only CSR

2024-07-17 Thread Alistair Francis
From: Yu-Ming Chang 

Both CSRRS and CSRRC always read the addressed CSR and cause any read side
effects regardless of rs1 and rd fields. Note that if rs1 specifies a register
holding a zero value other than x0, the instruction will still attempt to write
the unmodified value back to the CSR and will cause any attendant side effects.

So if CSRRS or CSRRC tries to write a read-only CSR with rs1 which specifies
a register holding a zero value, an illegal instruction exception should be
raised.

Signed-off-by: Yu-Ming Chang 
Signed-off-by: Alvin Chang 
Reviewed-by: Alistair Francis 
Message-ID: <172100444279.18077.689307237871805954...@git.sr.ht>
Signed-off-by: Alistair Francis 
---
 target/riscv/cpu.h   |  4 +++
 target/riscv/csr.c   | 57 
 target/riscv/op_helper.c |  6 ++---
 3 files changed, 58 insertions(+), 9 deletions(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 093c86b8b9..1619c3acb6 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -751,6 +751,8 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, vaddr *pc,
 void riscv_cpu_update_mask(CPURISCVState *env);
 bool riscv_cpu_is_32bit(RISCVCPU *cpu);
 
+RISCVException riscv_csrr(CPURISCVState *env, int csrno,
+  target_ulong *ret_value);
 RISCVException riscv_csrrw(CPURISCVState *env, int csrno,
target_ulong *ret_value,
target_ulong new_value, target_ulong write_mask);
@@ -783,6 +785,8 @@ typedef RISCVException (*riscv_csr_op_fn)(CPURISCVState 
*env, int csrno,
   target_ulong new_value,
   target_ulong write_mask);
 
+RISCVException riscv_csrr_i128(CPURISCVState *env, int csrno,
+   Int128 *ret_value);
 RISCVException riscv_csrrw_i128(CPURISCVState *env, int csrno,
 Int128 *ret_value,
 Int128 new_value, Int128 write_mask);
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 781ef27eba..ea3560342c 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -4624,7 +4624,7 @@ static RISCVException rmw_seed(CPURISCVState *env, int 
csrno,
 
 static inline RISCVException riscv_csrrw_check(CPURISCVState *env,
int csrno,
-   bool write_mask)
+   bool write)
 {
 /* check privileges and return RISCV_EXCP_ILLEGAL_INST if check fails */
 bool read_only = get_field(csrno, 0xC00) == 3;
@@ -4646,7 +4646,7 @@ static inline RISCVException 
riscv_csrrw_check(CPURISCVState *env,
 }
 
 /* read / write check */
-if (write_mask && read_only) {
+if (write && read_only) {
 return RISCV_EXCP_ILLEGAL_INST;
 }
 
@@ -4733,11 +4733,22 @@ static RISCVException riscv_csrrw_do64(CPURISCVState 
*env, int csrno,
 return RISCV_EXCP_NONE;
 }
 
+RISCVException riscv_csrr(CPURISCVState *env, int csrno,
+   target_ulong *ret_value)
+{
+RISCVException ret = riscv_csrrw_check(env, csrno, false);
+if (ret != RISCV_EXCP_NONE) {
+return ret;
+}
+
+return riscv_csrrw_do64(env, csrno, ret_value, 0, 0);
+}
+
 RISCVException riscv_csrrw(CPURISCVState *env, int csrno,
target_ulong *ret_value,
target_ulong new_value, target_ulong write_mask)
 {
-RISCVException ret = riscv_csrrw_check(env, csrno, write_mask);
+RISCVException ret = riscv_csrrw_check(env, csrno, true);
 if (ret != RISCV_EXCP_NONE) {
 return ret;
 }
@@ -4785,13 +4796,45 @@ static RISCVException riscv_csrrw_do128(CPURISCVState 
*env, int csrno,
 return RISCV_EXCP_NONE;
 }
 
+RISCVException riscv_csrr_i128(CPURISCVState *env, int csrno,
+   Int128 *ret_value)
+{
+RISCVException ret;
+
+ret = riscv_csrrw_check(env, csrno, false);
+if (ret != RISCV_EXCP_NONE) {
+return ret;
+}
+
+if (csr_ops[csrno].read128) {
+return riscv_csrrw_do128(env, csrno, ret_value,
+ int128_zero(), int128_zero());
+}
+
+/*
+ * Fall back to 64-bit version for now, if the 128-bit alternative isn't
+ * at all defined.
+ * Note, some CSRs don't need to extend to MXLEN (64 upper bits non
+ * significant), for those, this fallback is correctly handling the
+ * accesses
+ */
+target_ulong old_value;
+ret = riscv_csrrw_do64(env, csrno, _value,
+   (target_ulong)0,
+   (target_ulong)0);
+if (ret == RISCV_EXCP_NONE && ret_value) {
+*ret_value = int128_make64(old_value);
+}
+return ret;
+}
+
 RISCVException riscv_csrrw_i128(CPURISCVState *env, int csrno,
 Int128 *ret_value,
 

[PULL 07/30] target/riscv: Add AMO instructions for Zabha

2024-07-17 Thread Alistair Francis
From: LIU Zhiwei 

Signed-off-by: LIU Zhiwei 
Acked-by: Alistair Francis 
Message-ID: <20240709113652.1239-8-zhiwei_...@linux.alibaba.com>
Signed-off-by: Alistair Francis 
---
 target/riscv/cpu_cfg.h  |   1 +
 target/riscv/insn32.decode  |  20 +++
 target/riscv/translate.c|   4 +-
 target/riscv/insn_trans/trans_rvzabha.c.inc | 131 
 4 files changed, 155 insertions(+), 1 deletion(-)
 create mode 100644 target/riscv/insn_trans/trans_rvzabha.c.inc

diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h
index ddbfae37e5..120905a254 100644
--- a/target/riscv/cpu_cfg.h
+++ b/target/riscv/cpu_cfg.h
@@ -84,6 +84,7 @@ struct RISCVCPUConfig {
 bool ext_zaamo;
 bool ext_zacas;
 bool ext_zama16b;
+bool ext_zabha;
 bool ext_zalrsc;
 bool ext_zawrs;
 bool ext_zfa;
diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index 60da673153..3bad6372f2 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -1021,3 +1021,23 @@ amocas_q00101 . . . . 100 . 010 
@atom_st
 # *** Zimop may-be-operation extension ***
 mop_r_n 1 . 00 .. 0111 .. . 100 . 1110011 @mop5
 mop_rr_n1 . 00 .. 1 . . 100 . 1110011 @mop3
+
+# *** Zabhb Standard Extension ***
+amoswap_b  1 . . . . 000 . 010 @atom_st
+amoadd_b   0 . . . . 000 . 010 @atom_st
+amoxor_b   00100 . . . . 000 . 010 @atom_st
+amoand_b   01100 . . . . 000 . 010 @atom_st
+amoor_b01000 . . . . 000 . 010 @atom_st
+amomin_b   1 . . . . 000 . 010 @atom_st
+amomax_b   10100 . . . . 000 . 010 @atom_st
+amominu_b  11000 . . . . 000 . 010 @atom_st
+amomaxu_b  11100 . . . . 000 . 010 @atom_st
+amoswap_h  1 . . . . 001 . 010 @atom_st
+amoadd_h   0 . . . . 001 . 010 @atom_st
+amoxor_h   00100 . . . . 001 . 010 @atom_st
+amoand_h   01100 . . . . 001 . 010 @atom_st
+amoor_h01000 . . . . 001 . 010 @atom_st
+amomin_h   1 . . . . 001 . 010 @atom_st
+amomax_h   10100 . . . . 001 . 010 @atom_st
+amominu_h  11000 . . . . 001 . 010 @atom_st
+amomaxu_h  11100 . . . . 001 . 010 @atom_st
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 133550d6e2..4a3e786560 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -1083,8 +1083,9 @@ static bool gen_amo(DisasContext *ctx, arg_atomic *a,
 {
 TCGv dest = dest_gpr(ctx, a->rd);
 TCGv src1, src2 = get_gpr(ctx, a->rs2, EXT_NONE);
+MemOp size = mop & MO_SIZE;
 
-if (ctx->cfg_ptr->ext_zama16b) {
+if (ctx->cfg_ptr->ext_zama16b && size >= MO_32) {
 mop |= MO_ATOM_WITHIN16;
 } else {
 mop |= MO_ALIGN;
@@ -1118,6 +1119,7 @@ static uint32_t opcode_at(DisasContextBase *dcbase, 
target_ulong pc)
 #include "insn_trans/trans_rvb.c.inc"
 #include "insn_trans/trans_rvzicond.c.inc"
 #include "insn_trans/trans_rvzacas.c.inc"
+#include "insn_trans/trans_rvzabha.c.inc"
 #include "insn_trans/trans_rvzawrs.c.inc"
 #include "insn_trans/trans_rvzicbo.c.inc"
 #include "insn_trans/trans_rvzimop.c.inc"
diff --git a/target/riscv/insn_trans/trans_rvzabha.c.inc 
b/target/riscv/insn_trans/trans_rvzabha.c.inc
new file mode 100644
index 00..9093a1cfc1
--- /dev/null
+++ b/target/riscv/insn_trans/trans_rvzabha.c.inc
@@ -0,0 +1,131 @@
+/*
+ * RISC-V translation routines for the Zabha Standard Extension.
+ *
+ * Copyright (c) 2024 Alibaba Group
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
+ * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
+ * more details.
+ *
+ * You should have received a copy of the GNU General Public License along with
+ * this program.  If not, see <http://www.gnu.org/licenses/>.
+ */
+
+#define REQUIRE_ZABHA(ctx) do {   \
+if (!ctx->cfg_ptr->ext_zabha) {   \
+return false; \
+} \
+} while (0)
+
+static bool trans_amoswap_b(DisasContext *ctx, arg_amoswap_b *a)
+{
+REQUIRE_ZABHA(ctx);
+return gen_amo(ctx, a, _gen_atomic_xchg_tl, MO_SB);
+}
+
+static bool trans_amoadd_b(DisasContext *ctx, arg_amoadd_b *a)
+{
+REQUIRE_ZABHA(ctx);
+return gen_amo(ctx, a, _gen_atomic_fetch_add_tl, MO_SB);
+}
+
+static bool trans_amoxor_b(Di

[PULL 12/30] target/riscv: Validate the mode in write_vstvec

2024-07-17 Thread Alistair Francis
From: Jiayi Li 

Base on the riscv-privileged spec, vstvec substitutes for the usual stvec.
Therefore, the encoding of the MODE should also be restricted to 0 and 1.

Signed-off-by: Jiayi Li 
Reviewed-by: Alistair Francis 
Reviewed-by: LIU Zhiwei 
Message-ID: <20240701022553.1982-1-liji...@eswincomputing.com>
Signed-off-by: Alistair Francis 
---
 target/riscv/csr.c | 7 ++-
 1 file changed, 6 insertions(+), 1 deletion(-)

diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 432c59dc66..f9229d92ab 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -3791,7 +3791,12 @@ static RISCVException read_vstvec(CPURISCVState *env, 
int csrno,
 static RISCVException write_vstvec(CPURISCVState *env, int csrno,
target_ulong val)
 {
-env->vstvec = val;
+/* bits [1:0] encode mode; 0 = direct, 1 = vectored, 2 >= reserved */
+if ((val & 3) < 2) {
+env->vstvec = val;
+} else {
+qemu_log_mask(LOG_UNIMP, "CSR_VSTVEC: reserved mode not supported\n");
+}
 return RISCV_EXCP_NONE;
 }
 
-- 
2.45.2




[PULL 24/30] target/riscv: Start counters from both mhpmcounter and mcountinhibit

2024-07-17 Thread Alistair Francis
From: Rajnesh Kanwal 

Currently we start timer counter from write_mhpmcounter path only
without checking for mcountinhibit bit. This changes adds mcountinhibit
check and also programs the counter from write_mcountinhibit as well.

When a counter is stopped using mcountinhibit we simply update
the value of the counter based on current host ticks and save
it for future reads.

We don't need to disable running timer as pmu_timer_trigger_irq
will discard the interrupt if the counter has been inhibited.

Signed-off-by: Rajnesh Kanwal 
Reviewed-by: Daniel Henrique Barboza 
Message-ID: <20240711-smcntrpmf_v7-v8-10-b7c38ae7b...@rivosinc.com>
Signed-off-by: Alistair Francis 
---
 target/riscv/csr.c | 75 --
 target/riscv/pmu.c |  3 +-
 2 files changed, 54 insertions(+), 24 deletions(-)

diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index d6c5b73afd..bb6ac33ac2 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -1077,8 +1077,9 @@ static RISCVException write_mhpmcounter(CPURISCVState 
*env, int csrno,
 uint64_t mhpmctr_val = val;
 
 counter->mhpmcounter_val = val;
-if (riscv_pmu_ctr_monitor_cycles(env, ctr_idx) ||
-riscv_pmu_ctr_monitor_instructions(env, ctr_idx)) {
+if (!get_field(env->mcountinhibit, BIT(ctr_idx)) &&
+(riscv_pmu_ctr_monitor_cycles(env, ctr_idx) ||
+ riscv_pmu_ctr_monitor_instructions(env, ctr_idx))) {
 counter->mhpmcounter_prev = riscv_pmu_ctr_get_fixed_counters_val(env,
 ctr_idx, 
false);
 if (ctr_idx > 2) {
@@ -1106,8 +1107,9 @@ static RISCVException write_mhpmcounterh(CPURISCVState 
*env, int csrno,
 
 counter->mhpmcounterh_val = val;
 mhpmctr_val = mhpmctr_val | (mhpmctrh_val << 32);
-if (riscv_pmu_ctr_monitor_cycles(env, ctr_idx) ||
-riscv_pmu_ctr_monitor_instructions(env, ctr_idx)) {
+if (!get_field(env->mcountinhibit, BIT(ctr_idx)) &&
+(riscv_pmu_ctr_monitor_cycles(env, ctr_idx) ||
+ riscv_pmu_ctr_monitor_instructions(env, ctr_idx))) {
 counter->mhpmcounterh_prev = riscv_pmu_ctr_get_fixed_counters_val(env,
  ctr_idx, 
true);
 if (ctr_idx > 2) {
@@ -2170,31 +2172,60 @@ static RISCVException write_mcountinhibit(CPURISCVState 
*env, int csrno,
 int cidx;
 PMUCTRState *counter;
 RISCVCPU *cpu = env_archcpu(env);
+uint32_t present_ctrs = cpu->pmu_avail_ctrs | COUNTEREN_CY | COUNTEREN_IR;
+target_ulong updated_ctrs = (env->mcountinhibit ^ val) & present_ctrs;
+uint64_t mhpmctr_val, prev_count, curr_count;
 
 /* WARL register - disable unavailable counters; TM bit is always 0 */
-env->mcountinhibit =
-val & (cpu->pmu_avail_ctrs | COUNTEREN_CY | COUNTEREN_IR);
+env->mcountinhibit = val & present_ctrs;
 
 /* Check if any other counter is also monitoring cycles/instructions */
 for (cidx = 0; cidx < RV_MAX_MHPMCOUNTERS; cidx++) {
-counter = >pmu_ctrs[cidx];
-if (get_field(env->mcountinhibit, BIT(cidx)) && (val & BIT(cidx))) {
-/*
- * Update the counter value for cycle/instret as we can't stop the
- * host ticks. But we should show the current value at this moment.
- */
-if (riscv_pmu_ctr_monitor_cycles(env, cidx) ||
-riscv_pmu_ctr_monitor_instructions(env, cidx)) {
-counter->mhpmcounter_val =
-riscv_pmu_ctr_get_fixed_counters_val(env, cidx, false) -
-   counter->mhpmcounter_prev +
-   counter->mhpmcounter_val;
+if (!(updated_ctrs & BIT(cidx)) ||
+(!riscv_pmu_ctr_monitor_cycles(env, cidx) &&
+!riscv_pmu_ctr_monitor_instructions(env, cidx))) {
+continue;
+}
+
+counter = >pmu_ctrs[cidx];
+
+if (!get_field(env->mcountinhibit, BIT(cidx))) {
+counter->mhpmcounter_prev =
+riscv_pmu_ctr_get_fixed_counters_val(env, cidx, false);
+if (riscv_cpu_mxl(env) == MXL_RV32) {
+counter->mhpmcounterh_prev =
+riscv_pmu_ctr_get_fixed_counters_val(env, cidx, true);
+}
+
+if (cidx > 2) {
+mhpmctr_val = counter->mhpmcounter_val;
 if (riscv_cpu_mxl(env) == MXL_RV32) {
-counter->mhpmcounterh_val =
-riscv_pmu_ctr_get_fixed_counters_val(env, cidx, true) -
-counter->mhpmcounterh_prev +
-counter->mhpmcounterh_val;
+mhpmctr_val = mhpmctr_val |
+ 

[PULL 09/30] target/riscv: Add amocas.[b|h] for Zabha

2024-07-17 Thread Alistair Francis
From: LIU Zhiwei 

Signed-off-by: LIU Zhiwei 
Reviewed-by: Alistair Francis 
Message-ID: <20240709113652.1239-10-zhiwei_...@linux.alibaba.com>
Signed-off-by: Alistair Francis 
---
 target/riscv/insn32.decode  |  2 ++
 target/riscv/insn_trans/trans_rvzabha.c.inc | 14 ++
 2 files changed, 16 insertions(+)

diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index 3bad6372f2..c45b8fa1d8 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -1041,3 +1041,5 @@ amomin_h   1 . . . . 001 . 010 
@atom_st
 amomax_h   10100 . . . . 001 . 010 @atom_st
 amominu_h  11000 . . . . 001 . 010 @atom_st
 amomaxu_h  11100 . . . . 001 . 010 @atom_st
+amocas_b00101 . . . . 000 . 010 @atom_st
+amocas_h00101 . . . . 001 . 010 @atom_st
diff --git a/target/riscv/insn_trans/trans_rvzabha.c.inc 
b/target/riscv/insn_trans/trans_rvzabha.c.inc
index 9093a1cfc1..ce8edcba62 100644
--- a/target/riscv/insn_trans/trans_rvzabha.c.inc
+++ b/target/riscv/insn_trans/trans_rvzabha.c.inc
@@ -129,3 +129,17 @@ static bool trans_amomaxu_h(DisasContext *ctx, 
arg_amomaxu_h *a)
 REQUIRE_ZABHA(ctx);
 return gen_amo(ctx, a, _gen_atomic_fetch_umax_tl, MO_TESW);
 }
+
+static bool trans_amocas_b(DisasContext *ctx, arg_amocas_b *a)
+{
+REQUIRE_ZACAS(ctx);
+REQUIRE_ZABHA(ctx);
+return gen_cmpxchg(ctx, a, MO_SB);
+}
+
+static bool trans_amocas_h(DisasContext *ctx, arg_amocas_h *a)
+{
+REQUIRE_ZACAS(ctx);
+REQUIRE_ZABHA(ctx);
+return gen_cmpxchg(ctx, a, MO_ALIGN | MO_TESW);
+}
-- 
2.45.2




[PULL 25/30] target/riscv: More accurately model priv mode filtering.

2024-07-17 Thread Alistair Francis
From: Rajnesh Kanwal 

In case of programmable counters configured to count inst/cycles
we often end-up with counter not incrementing at all from kernel's
perspective.

For example:
- Kernel configures hpm3 to count instructions and sets hpmcounter
  to -1 and all modes except U mode are inhibited.
- In QEMU we configure a timer to expire after ~1 instructions.
- Problem is, it's often the case that kernel might not even schedule
  Umode task and we hit the timer callback in QEMU.
- In the timer callback we inject the interrupt into kernel, kernel
  runs the handler and reads hpmcounter3 value.
- Given QEMU maintains individual counters to count for each privilege
  mode, and given umode never ran, the umode counter didn't increment
  and QEMU returns same value as was programmed by the kernel when
  starting the counter.
- Kernel checks for overflow using previous and current value of the
  counter and reprograms the counter given there wasn't an overflow
  as per the counter value. (Which itself is a problem. We have QEMU
  telling kernel that counter3 overflowed but the counter value
  returned by QEMU doesn't seem to reflect that.).

This change makes sure that timer is reprogrammed from the handler
if the counter didn't overflow based on the counter value.

Second, this change makes sure that whenever the counter is read,
it's value is updated to reflect the latest count.

Signed-off-by: Rajnesh Kanwal 
Reviewed-by: Daniel Henrique Barboza 
Message-ID: <20240711-smcntrpmf_v7-v8-11-b7c38ae7b...@rivosinc.com>
Signed-off-by: Alistair Francis 
---
 target/riscv/pmu.h |  2 ++
 target/riscv/csr.c |  5 -
 target/riscv/pmu.c | 30 +++---
 3 files changed, 33 insertions(+), 4 deletions(-)

diff --git a/target/riscv/pmu.h b/target/riscv/pmu.h
index ca40cfeed6..3853d0e262 100644
--- a/target/riscv/pmu.h
+++ b/target/riscv/pmu.h
@@ -36,5 +36,7 @@ int riscv_pmu_setup_timer(CPURISCVState *env, uint64_t value,
   uint32_t ctr_idx);
 void riscv_pmu_update_fixed_ctrs(CPURISCVState *env, target_ulong newpriv,
  bool new_virt);
+RISCVException riscv_pmu_read_ctr(CPURISCVState *env, target_ulong *val,
+  bool upper_half, uint32_t ctr_idx);
 
 #endif /* RISCV_PMU_H */
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index bb6ac33ac2..781ef27eba 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -1039,6 +1039,9 @@ static target_ulong 
riscv_pmu_ctr_get_fixed_counters_val(CPURISCVState *env,
 goto done;
 }
 
+/* Update counter before reading. */
+riscv_pmu_update_fixed_ctrs(env, env->priv, env->virt_enabled);
+
 if (!(cfg_val & MCYCLECFG_BIT_MINH)) {
 curr_val += counter_arr[PRV_M];
 }
@@ -1122,7 +1125,7 @@ static RISCVException write_mhpmcounterh(CPURISCVState 
*env, int csrno,
 return RISCV_EXCP_NONE;
 }
 
-static RISCVException riscv_pmu_read_ctr(CPURISCVState *env, target_ulong *val,
+RISCVException riscv_pmu_read_ctr(CPURISCVState *env, target_ulong *val,
  bool upper_half, uint32_t ctr_idx)
 {
 PMUCTRState *counter = >pmu_ctrs[ctr_idx];
diff --git a/target/riscv/pmu.c b/target/riscv/pmu.c
index 63420d9f36..a4729f6c53 100644
--- a/target/riscv/pmu.c
+++ b/target/riscv/pmu.c
@@ -425,6 +425,8 @@ static void pmu_timer_trigger_irq(RISCVCPU *cpu,
 target_ulong *mhpmevent_val;
 uint64_t of_bit_mask;
 int64_t irq_trigger_at;
+uint64_t curr_ctr_val, curr_ctrh_val;
+uint64_t ctr_val;
 
 if (evt_idx != RISCV_PMU_EVENT_HW_CPU_CYCLES &&
 evt_idx != RISCV_PMU_EVENT_HW_INSTRUCTIONS) {
@@ -454,6 +456,26 @@ static void pmu_timer_trigger_irq(RISCVCPU *cpu,
 return;
 }
 
+riscv_pmu_read_ctr(env, (target_ulong *)_ctr_val, false, ctr_idx);
+ctr_val = counter->mhpmcounter_val;
+if (riscv_cpu_mxl(env) == MXL_RV32) {
+riscv_pmu_read_ctr(env, (target_ulong *)_ctrh_val, true, ctr_idx);
+curr_ctr_val = curr_ctr_val | (curr_ctrh_val << 32);
+ctr_val = ctr_val |
+((uint64_t)counter->mhpmcounterh_val << 32);
+}
+
+/*
+ * We can not accommodate for inhibited modes when setting up timer. Check
+ * if the counter has actually overflowed or not by comparing current
+ * counter value (accommodated for inhibited modes) with software written
+ * counter value.
+ */
+if (curr_ctr_val >= ctr_val) {
+riscv_pmu_setup_timer(env, curr_ctr_val, ctr_idx);
+return;
+}
+
 if (cpu->pmu_avail_ctrs & BIT(ctr_idx)) {
 /* Generate interrupt only if OF bit is clear */
 if (!(*mhpmevent_val & of_bit_mask)) {
@@ -475,7 +497,7 @@ void riscv_pmu_timer_cb(void *priv)
 
 int riscv_pmu_setup_timer(CPURISCVState *env, uint64_t value, uint32_t ctr_idx)
 {
-uint64_t overflow_delta, overflow_at;
+uint64_t overflow_delta, overfl

[PULL 04/30] disas/riscv: Support zcmop disassemble

2024-07-17 Thread Alistair Francis
From: LIU Zhiwei 

Although in QEMU disassemble, we usually lift compressed instruction
to an normal format when display the instruction name. For C.MOP.n,
it is more reasonable to directly display its compressed name, because
its behavior can be redefined by later extension.

Signed-off-by: LIU Zhiwei 
Acked-by: Alistair Francis 
Reviewed-by: Deepak Gupta 
Message-ID: <20240709113652.1239-5-zhiwei_...@linux.alibaba.com>
Signed-off-by: Alistair Francis 
---
 disas/riscv.c | 23 +++
 1 file changed, 23 insertions(+)

diff --git a/disas/riscv.c b/disas/riscv.c
index 0b82ab2322..d29cb1ff7d 100644
--- a/disas/riscv.c
+++ b/disas/riscv.c
@@ -946,6 +946,14 @@ typedef enum {
 rv_mop_rr_5= 915,
 rv_mop_rr_6= 916,
 rv_mop_rr_7= 917,
+rv_c_mop_1 = 918,
+rv_c_mop_3 = 919,
+rv_c_mop_5 = 920,
+rv_c_mop_7 = 921,
+rv_c_mop_9 = 922,
+rv_c_mop_11= 923,
+rv_c_mop_13= 924,
+rv_c_mop_15= 925,
 } rv_op;
 
 /* register names */
@@ -2176,6 +2184,14 @@ const rv_opcode_data rvi_opcode_data[] = {
 { "mop.rr.5", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
 { "mop.rr.6", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
 { "mop.rr.7", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
+{ "c.mop.1",  rv_codec_ci_none, rv_fmt_none, NULL, 0, 0, 0 },
+{ "c.mop.3",  rv_codec_ci_none, rv_fmt_none, NULL, 0, 0, 0 },
+{ "c.mop.5",  rv_codec_ci_none, rv_fmt_none, NULL, 0, 0, 0 },
+{ "c.mop.7",  rv_codec_ci_none, rv_fmt_none, NULL, 0, 0, 0 },
+{ "c.mop.9",  rv_codec_ci_none, rv_fmt_none, NULL, 0, 0, 0 },
+{ "c.mop.11", rv_codec_ci_none, rv_fmt_none, NULL, 0, 0, 0 },
+{ "c.mop.13", rv_codec_ci_none, rv_fmt_none, NULL, 0, 0, 0 },
+{ "c.mop.15", rv_codec_ci_none, rv_fmt_none, NULL, 0, 0, 0 },
 };
 
 /* CSR names */
@@ -2532,6 +2548,13 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa 
isa)
 break;
 case 2: op = rv_op_c_li; break;
 case 3:
+if (dec->cfg->ext_zcmop) {
+if inst >> 2) & 0b11) == 0b10) &&
+(((inst >> 11) & 0b11) == 0b0)) {
+op = rv_c_mop_1 + ((inst >> 8) & 0b111);
+break;
+}
+}
 switch ((inst >> 7) & 0b1) {
 case 2: op = rv_op_c_addi16sp; break;
 default: op = rv_op_c_lui; break;
-- 
2.45.2




[PULL 03/30] target/riscv: Add zcmop extension

2024-07-17 Thread Alistair Francis
From: LIU Zhiwei 

Zcmop defines eight 16-bit MOP instructions named C.MOP.n, where n is
an odd integer between 1 and 15, inclusive. C.MOP.n is encoded in
the reserved encoding space corresponding to C.LUI xn, 0.

Unlike the MOPs defined in the Zimop extension, the C.MOP.n instructions
are defined to not write any register.

In current implementation, C.MOP.n only has an check function, without any
other more behavior.

Signed-off-by: LIU Zhiwei 
Reviewed-by: Alistair Francis 
Reviewed-by: Deepak Gupta 
Message-ID: <20240709113652.1239-4-zhiwei_...@linux.alibaba.com>
Signed-off-by: Alistair Francis 
---
 target/riscv/cpu_cfg.h  |  1 +
 target/riscv/insn16.decode  |  1 +
 target/riscv/cpu.c  |  2 ++
 target/riscv/tcg/tcg-cpu.c  |  5 
 target/riscv/translate.c|  1 +
 target/riscv/insn_trans/trans_rvzcmop.c.inc | 29 +
 6 files changed, 39 insertions(+)
 create mode 100644 target/riscv/insn_trans/trans_rvzcmop.c.inc

diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h
index 9f53512053..d85e54b475 100644
--- a/target/riscv/cpu_cfg.h
+++ b/target/riscv/cpu_cfg.h
@@ -72,6 +72,7 @@ struct RISCVCPUConfig {
 bool ext_zihintpause;
 bool ext_zihpm;
 bool ext_zimop;
+bool ext_zcmop;
 bool ext_ztso;
 bool ext_smstateen;
 bool ext_sstc;
diff --git a/target/riscv/insn16.decode b/target/riscv/insn16.decode
index b96c534e73..3953bcf82d 100644
--- a/target/riscv/insn16.decode
+++ b/target/riscv/insn16.decode
@@ -140,6 +140,7 @@ sw110  ... ... .. ... 00 @cs_w
 addi  000 .  .  . 01 @ci
 addi  010 .  .  . 01 @c_li
 {
+  c_mop_n 011 0 0 n:3 1 0 01
   illegal 011 0  -  0 01 # c.addi16sp and c.lui, RES nzimm=0
   addi011 .  00010  . 01 @c_addi16sp
   lui 011 .  .  . 01 @c_lui
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index ac503826ce..f4f8287a6d 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -131,6 +131,7 @@ const RISCVIsaExtData isa_edata_arr[] = {
 ISA_EXT_DATA_ENTRY(zcf, PRIV_VERSION_1_12_0, ext_zcf),
 ISA_EXT_DATA_ENTRY(zcd, PRIV_VERSION_1_12_0, ext_zcd),
 ISA_EXT_DATA_ENTRY(zce, PRIV_VERSION_1_12_0, ext_zce),
+ISA_EXT_DATA_ENTRY(zcmop, PRIV_VERSION_1_13_0, ext_zcmop),
 ISA_EXT_DATA_ENTRY(zcmp, PRIV_VERSION_1_12_0, ext_zcmp),
 ISA_EXT_DATA_ENTRY(zcmt, PRIV_VERSION_1_12_0, ext_zcmt),
 ISA_EXT_DATA_ENTRY(zba, PRIV_VERSION_1_12_0, ext_zba),
@@ -1473,6 +1474,7 @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
 MULTI_EXT_CFG_BOOL("zihintntl", ext_zihintntl, true),
 MULTI_EXT_CFG_BOOL("zihintpause", ext_zihintpause, true),
 MULTI_EXT_CFG_BOOL("zimop", ext_zimop, false),
+MULTI_EXT_CFG_BOOL("zcmop", ext_zcmop, false),
 MULTI_EXT_CFG_BOOL("zacas", ext_zacas, false),
 MULTI_EXT_CFG_BOOL("zaamo", ext_zaamo, false),
 MULTI_EXT_CFG_BOOL("zalrsc", ext_zalrsc, false),
diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
index ecf366d6c7..b8814ab753 100644
--- a/target/riscv/tcg/tcg-cpu.c
+++ b/target/riscv/tcg/tcg-cpu.c
@@ -549,6 +549,11 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, 
Error **errp)
 }
 }
 
+if (cpu->cfg.ext_zcmop && !cpu->cfg.ext_zca) {
+error_setg(errp, "Zcmop extensions require Zca");
+return;
+}
+
 if (mcc->misa_mxl_max != MXL_RV32 && cpu->cfg.ext_zcf) {
 error_setg(errp, "Zcf extension is only relevant to RV32");
 return;
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 379b68289f..8a546f4ece 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -1114,6 +1114,7 @@ static uint32_t opcode_at(DisasContextBase *dcbase, 
target_ulong pc)
 /* Include the auto-generated decoder for 16 bit insn */
 #include "decode-insn16.c.inc"
 #include "insn_trans/trans_rvzce.c.inc"
+#include "insn_trans/trans_rvzcmop.c.inc"
 
 /* Include decoders for factored-out extensions */
 #include "decode-XVentanaCondOps.c.inc"
diff --git a/target/riscv/insn_trans/trans_rvzcmop.c.inc 
b/target/riscv/insn_trans/trans_rvzcmop.c.inc
new file mode 100644
index 00..7205586508
--- /dev/null
+++ b/target/riscv/insn_trans/trans_rvzcmop.c.inc
@@ -0,0 +1,29 @@
+/*
+ * RISC-V translation routines for compressed May-Be-Operation(zcmop).
+ *
+ * Copyright (c) 2024 Alibaba Group.
+ *
+ * This program is free software; you can redistribute it and/or modify it
+ * under the terms and conditions of the GNU General Public License,
+ * version 2 or later, as published by the Free Software Foundation.
+ *
+ * This program is distributed in the hope it will be useful, but WITHOUT
+ * ANY WARRANTY; without even the imp

[PULL 05/30] target/riscv: Support Zama16b extension

2024-07-17 Thread Alistair Francis
From: LIU Zhiwei 

Zama16b is the property that misaligned load/stores/atomics within
a naturally aligned 16-byte region are atomic.

According to the specification, Zama16b applies only to AMOs, loads
and stores defined in the base ISAs, and loads and stores of no more
than XLEN bits defined in the F, D, and Q extensions. Thus it should
not apply to zacas or RVC instructions.

For an instruction in that set, if all accessed bytes lie within 16B granule,
the instruction will not raise an exception for reasons of address alignment,
and the instruction will give rise to only one memory operation for the
purposes of RVWMO—i.e., it will execute atomically.

Signed-off-by: LIU Zhiwei 
Reviewed-by: Alistair Francis 
Message-ID: <20240709113652.1239-6-zhiwei_...@linux.alibaba.com>
Signed-off-by: Alistair Francis 
---
 target/riscv/cpu_cfg.h  |  1 +
 target/riscv/cpu.c  |  2 ++
 target/riscv/insn_trans/trans_rva.c.inc | 42 ++---
 target/riscv/insn_trans/trans_rvd.c.inc | 14 +++--
 target/riscv/insn_trans/trans_rvf.c.inc | 14 +++--
 target/riscv/insn_trans/trans_rvi.c.inc |  6 
 6 files changed, 57 insertions(+), 22 deletions(-)

diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h
index d85e54b475..ddbfae37e5 100644
--- a/target/riscv/cpu_cfg.h
+++ b/target/riscv/cpu_cfg.h
@@ -83,6 +83,7 @@ struct RISCVCPUConfig {
 bool ext_zdinx;
 bool ext_zaamo;
 bool ext_zacas;
+bool ext_zama16b;
 bool ext_zalrsc;
 bool ext_zawrs;
 bool ext_zfa;
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index f4f8287a6d..de9c06904f 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -118,6 +118,7 @@ const RISCVIsaExtData isa_edata_arr[] = {
 ISA_EXT_DATA_ENTRY(za64rs, PRIV_VERSION_1_12_0, has_priv_1_11),
 ISA_EXT_DATA_ENTRY(zaamo, PRIV_VERSION_1_12_0, ext_zaamo),
 ISA_EXT_DATA_ENTRY(zacas, PRIV_VERSION_1_12_0, ext_zacas),
+ISA_EXT_DATA_ENTRY(zama16b, PRIV_VERSION_1_13_0, ext_zama16b),
 ISA_EXT_DATA_ENTRY(zalrsc, PRIV_VERSION_1_12_0, ext_zalrsc),
 ISA_EXT_DATA_ENTRY(zawrs, PRIV_VERSION_1_12_0, ext_zawrs),
 ISA_EXT_DATA_ENTRY(zfa, PRIV_VERSION_1_12_0, ext_zfa),
@@ -1476,6 +1477,7 @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
 MULTI_EXT_CFG_BOOL("zimop", ext_zimop, false),
 MULTI_EXT_CFG_BOOL("zcmop", ext_zcmop, false),
 MULTI_EXT_CFG_BOOL("zacas", ext_zacas, false),
+MULTI_EXT_CFG_BOOL("zama16b", ext_zama16b, false),
 MULTI_EXT_CFG_BOOL("zaamo", ext_zaamo, false),
 MULTI_EXT_CFG_BOOL("zalrsc", ext_zalrsc, false),
 MULTI_EXT_CFG_BOOL("zawrs", ext_zawrs, true),
diff --git a/target/riscv/insn_trans/trans_rva.c.inc 
b/target/riscv/insn_trans/trans_rva.c.inc
index 4a9e4591d1..eb080baddd 100644
--- a/target/riscv/insn_trans/trans_rva.c.inc
+++ b/target/riscv/insn_trans/trans_rva.c.inc
@@ -103,6 +103,12 @@ static bool gen_amo(DisasContext *ctx, arg_atomic *a,
 TCGv dest = dest_gpr(ctx, a->rd);
 TCGv src1, src2 = get_gpr(ctx, a->rs2, EXT_NONE);
 
+if (ctx->cfg_ptr->ext_zama16b) {
+mop |= MO_ATOM_WITHIN16;
+} else {
+mop |= MO_ALIGN;
+}
+
 decode_save_opc(ctx);
 src1 = get_address(ctx, a->rs1, 0);
 func(dest, src1, src2, ctx->mem_idx, mop);
@@ -126,55 +132,55 @@ static bool trans_sc_w(DisasContext *ctx, arg_sc_w *a)
 static bool trans_amoswap_w(DisasContext *ctx, arg_amoswap_w *a)
 {
 REQUIRE_A_OR_ZAAMO(ctx);
-return gen_amo(ctx, a, _gen_atomic_xchg_tl, (MO_ALIGN | MO_TESL));
+return gen_amo(ctx, a, _gen_atomic_xchg_tl, MO_TESL);
 }
 
 static bool trans_amoadd_w(DisasContext *ctx, arg_amoadd_w *a)
 {
 REQUIRE_A_OR_ZAAMO(ctx);
-return gen_amo(ctx, a, _gen_atomic_fetch_add_tl, (MO_ALIGN | MO_TESL));
+return gen_amo(ctx, a, _gen_atomic_fetch_add_tl, MO_TESL);
 }
 
 static bool trans_amoxor_w(DisasContext *ctx, arg_amoxor_w *a)
 {
 REQUIRE_A_OR_ZAAMO(ctx);
-return gen_amo(ctx, a, _gen_atomic_fetch_xor_tl, (MO_ALIGN | MO_TESL));
+return gen_amo(ctx, a, _gen_atomic_fetch_xor_tl, MO_TESL);
 }
 
 static bool trans_amoand_w(DisasContext *ctx, arg_amoand_w *a)
 {
 REQUIRE_A_OR_ZAAMO(ctx);
-return gen_amo(ctx, a, _gen_atomic_fetch_and_tl, (MO_ALIGN | MO_TESL));
+return gen_amo(ctx, a, _gen_atomic_fetch_and_tl, MO_TESL);
 }
 
 static bool trans_amoor_w(DisasContext *ctx, arg_amoor_w *a)
 {
 REQUIRE_A_OR_ZAAMO(ctx);
-return gen_amo(ctx, a, _gen_atomic_fetch_or_tl, (MO_ALIGN | MO_TESL));
+return gen_amo(ctx, a, _gen_atomic_fetch_or_tl, MO_TESL);
 }
 
 static bool trans_amomin_w(DisasContext *ctx, arg_amomin_w *a)
 {
 REQUIRE_A_OR_ZAAMO(ctx);
-return gen_amo(ctx, a, _gen_atomic_fetch_smin_tl, (MO_ALIGN | 
MO_TESL));
+return gen_amo(ctx, a, _gen_atomic_fetch_smin_tl, MO_TESL);
 }
 
 static bool trans_amomax_w(DisasContext *ctx, arg_amomax_w *a)
 {
 REQUIR

[PULL 30/30] roms/opensbi: Update to v1.5

2024-07-17 Thread Alistair Francis
 of misaligned and access fault handlers
abea949 lib: sbi: Introduce trap context
60ffc15 include: sbi: Add trap_context pointer in struct sbi_scratch
ebb697a lib: sbi: Remove sbi_trap_exit() and related code
2e85178 lib: sbi: Remove epc from struct sbi_trap_info
86224ec docs/writing_tests: Update tests paths
5c992a1 lib: tests: Move tests to a separate directory
81e3ba7 lib: sbi: call platform load/store emulators
ddf3b64 include: sbi: add emulate_load/store handler to platform ops
4c11265 lib: sbi: abstract out insn decoding to unify mem fault handlers
9221fe5 lib: sbi: change prototype of sbi_misaligned_load/store_handler
a17600c lib: sbi: change prototype of sbi_trap_redirect
2471cf2 include: sbi: rename sbi_misaligned_ldst.h to sbi_trap_ldst.h
c0a6320 lib: sbi: rename sbi_misaligned_ldst.c to sbi_trap_ldst.c
e11025c lib: sbi: Add initial domain context management support
87d8fe7 lib: tests: Add sbi_console test
e5f53fd lib: tests: Add a test for sbi_bitmap
874fcef lib: Add SBIUnit testing macros and functions
b9e4de0 docs: Add documentation about tests and SBIUnit
526b9ce firmware: fw_base.S: fix _reset_regs
8151105 firmware: fw_base.S: Remove _relocate_lottery
187397f firmware: fw_dynamic.S: Remove _bad_dynamic_info
b27b7c6 firmware: fw_base: Simplified setup trap handler
fdf5589 firmware: fw_base.S: Simplify address get
748bef1 lib: sbi_misaligned_ldst: Add handling of C.LHU/C.LH and C.SH
bc36678 platform: andes: Drop andes_pmu_setup()
6bb6b61 lib: sbi: Add support for smcsrind and smcdeleg
322b598 lib: sbi_hsm: Restor hart state to stop when fails to start
96a35db docs/firmware: document new options for jump and payload firmwares
2cff7f3 platform: Apply relocatable address
f056939 firmware: Add relocatable FW_PAYLOAD_FDT_ADDR
7227cdd firmware: Add relocatable FW_JUMP_ADDR and FW_JUMP_FDT_ADDR
741e941 platform: starfive: call starfive_jh7110_inst_init() in pm_reset_init()
3edf044 platform: starfive: return error if needed devices are not present
80ae046 platform: starfive: rename "stf,axp15060-regulator" -> 
"x-powers,axp15060"
5335340 platform: starfive: remove redundant compatibility check in pmic_ops
4d8569d platform: starfive: get I2C offset address from clocks property
034af1f platform: starfive: correct system clock device tree node
88273fe lib: sbi_pmu: Before using we should ensure PMU init done
46c8c65 docs: move documentation of system suspend test.
8df836d platform: generic: Parse system suspend test from config node.
23e7e48 docs: Add OpenSBI DT configuration guide.
67ce5a7 platform: generic: Add support for specify coldboot harts in DT
9c8b18e firmware: fw_base.S: remove _runtime_offset
4c6b7cb firmware: fw_base.S: Improve loading u32
92e8aff firmware: always create dynsym section
d1dad07 Makefile: check for --exclude-libs
4a76f79 Makefile: don't pass -mstrict-align if not supported
21caaa3 fw_base.S: Fix comment errors
1ec353d lib: sbi: Use mask to check the free bit during trigger allocation
bb90a9e lib: sbi: Print number of debug triggers found
76a2a15 lib: sbi: Implement SBI debug trigger extension
fa87ec9 include: sbi: Add SBI debug trigger extension related defines
97f234f lib: sbi: Introduce the SBI debug triggers extension support
40dac6b lib: sbi: Detect support of debug triggers
2499769 include: sbi: Introduce debug trigger register encodings
20ca19a include: sbi: Add TINFO debug trigger CSR
b752099 include: sbi: Introduce common endianess conversion macro

Signed-off-by: Daniel Henrique Barboza 
Reviewed-by: Alistair Francis 
Message-ID: <20240715171521.179517-1-dbarb...@ventanamicro.com>
Signed-off-by: Alistair Francis 
---
 .../opensbi-riscv32-generic-fw_dynamic.bin| Bin 267416 -> 268312 bytes
 .../opensbi-riscv64-generic-fw_dynamic.bin| Bin 270808 -> 272504 bytes
 roms/opensbi  |   2 +-
 3 files changed, 1 insertion(+), 1 deletion(-)

diff --git a/pc-bios/opensbi-riscv32-generic-fw_dynamic.bin 
b/pc-bios/opensbi-riscv32-generic-fw_dynamic.bin
index 60ca1165c8..7ec260ff40 100644
Binary files a/pc-bios/opensbi-riscv32-generic-fw_dynamic.bin and 
b/pc-bios/opensbi-riscv32-generic-fw_dynamic.bin differ
diff --git a/pc-bios/opensbi-riscv64-generic-fw_dynamic.bin 
b/pc-bios/opensbi-riscv64-generic-fw_dynamic.bin
index bae158d457..090c0cf6ac 100644
Binary files a/pc-bios/opensbi-riscv64-generic-fw_dynamic.bin and 
b/pc-bios/opensbi-riscv64-generic-fw_dynamic.bin differ
diff --git a/roms/opensbi b/roms/opensbi
index a2b255b889..455de672dd 16
--- a/roms/opensbi
+++ b/roms/opensbi
@@ -1 +1 @@
-Subproject commit a2b255b88918715173942f2c5e1f97ac9e90c877
+Subproject commit 455de672dd7c2aa1992df54dfb08dc11abbc1b1a
-- 
2.45.2




[PULL 21/30] target/riscv: Implement privilege mode filtering for cycle/instret

2024-07-17 Thread Alistair Francis
From: Atish Patra 

Privilege mode filtering can also be emulated for cycle/instret by
tracking host_ticks/icount during each privilege mode switch. This
patch implements that for both cycle/instret and mhpmcounters. The
first one requires Smcntrpmf while the other one requires Sscofpmf
to be enabled.

The cycle/instret are still computed using host ticks when icount
is not enabled. Otherwise, they are computed using raw icount which
is more accurate in icount mode.

Co-Developed-by: Rajnesh Kanwal 
Signed-off-by: Rajnesh Kanwal 
Reviewed-by: Daniel Henrique Barboza 
Acked-by: Alistair Francis 
Signed-off-by: Atish Patra 
Message-ID: <20240711-smcntrpmf_v7-v8-7-b7c38ae7b...@rivosinc.com>
Signed-off-by: Alistair Francis 
---
 target/riscv/cpu.h|  11 
 target/riscv/pmu.h|   2 +
 target/riscv/cpu_helper.c |   9 ++-
 target/riscv/csr.c| 117 ++
 target/riscv/pmu.c|  92 ++
 5 files changed, 194 insertions(+), 37 deletions(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 980e2154cd..f515ad072b 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -181,6 +181,15 @@ typedef struct PMUCTRState {
 target_ulong irq_overflow_left;
 } PMUCTRState;
 
+typedef struct PMUFixedCtrState {
+/* Track cycle and icount for each privilege mode */
+uint64_t counter[4];
+uint64_t counter_prev[4];
+/* Track cycle and icount for each privilege mode when V = 1*/
+uint64_t counter_virt[2];
+uint64_t counter_virt_prev[2];
+} PMUFixedCtrState;
+
 struct CPUArchState {
 target_ulong gpr[32];
 target_ulong gprh[32]; /* 64 top bits of the 128-bit registers */
@@ -377,6 +386,8 @@ struct CPUArchState {
 /* PMU event selector configured values for RV32 */
 target_ulong mhpmeventh_val[RV_MAX_MHPMEVENTS];
 
+PMUFixedCtrState pmu_fixed_ctrs[2];
+
 target_ulong sscratch;
 target_ulong mscratch;
 
diff --git a/target/riscv/pmu.h b/target/riscv/pmu.h
index 7c0ad661e0..ca40cfeed6 100644
--- a/target/riscv/pmu.h
+++ b/target/riscv/pmu.h
@@ -34,5 +34,7 @@ int riscv_pmu_incr_ctr(RISCVCPU *cpu, enum 
riscv_pmu_event_idx event_idx);
 void riscv_pmu_generate_fdt_node(void *fdt, uint32_t cmask, char *pmu_name);
 int riscv_pmu_setup_timer(CPURISCVState *env, uint64_t value,
   uint32_t ctr_idx);
+void riscv_pmu_update_fixed_ctrs(CPURISCVState *env, target_ulong newpriv,
+ bool new_virt);
 
 #endif /* RISCV_PMU_H */
diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
index 10d3fdaed3..395a1d9140 100644
--- a/target/riscv/cpu_helper.c
+++ b/target/riscv/cpu_helper.c
@@ -695,9 +695,14 @@ void riscv_cpu_set_mode(CPURISCVState *env, target_ulong 
newpriv, bool virt_en)
 {
 g_assert(newpriv <= PRV_M && newpriv != PRV_RESERVED);
 
-if (icount_enabled() && newpriv != env->priv) {
-riscv_itrigger_update_priv(env);
+if (newpriv != env->priv || env->virt_enabled != virt_en) {
+if (icount_enabled()) {
+riscv_itrigger_update_priv(env);
+}
+
+riscv_pmu_update_fixed_ctrs(env, newpriv, virt_en);
 }
+
 /* tlb_flush is unnecessary as mode is contained in mmu_idx */
 env->priv = newpriv;
 env->xl = cpu_recompute_xl(env);
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 364583dc03..85d3f0aa3f 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -787,36 +787,16 @@ static RISCVException write_vcsr(CPURISCVState *env, int 
csrno,
 return RISCV_EXCP_NONE;
 }
 
+#if defined(CONFIG_USER_ONLY)
 /* User Timers and Counters */
-static target_ulong get_ticks(bool shift, bool instructions)
+static target_ulong get_ticks(bool shift)
 {
-int64_t val;
-target_ulong result;
-
-#if !defined(CONFIG_USER_ONLY)
-if (icount_enabled()) {
-if (instructions) {
-val = icount_get_raw();
-} else {
-val = icount_get();
-}
-} else {
-val = cpu_get_host_ticks();
-}
-#else
-val = cpu_get_host_ticks();
-#endif
-
-if (shift) {
-result = val >> 32;
-} else {
-result = val;
-}
+int64_t val = cpu_get_host_ticks();
+target_ulong result = shift ? val >> 32 : val;
 
 return result;
 }
 
-#if defined(CONFIG_USER_ONLY)
 static RISCVException read_time(CPURISCVState *env, int csrno,
 target_ulong *val)
 {
@@ -834,14 +814,14 @@ static RISCVException read_timeh(CPURISCVState *env, int 
csrno,
 static RISCVException read_hpmcounter(CPURISCVState *env, int csrno,
   target_ulong *val)
 {
-*val = get_ticks(false, (csrno == CSR_INSTRET));
+*val = get_ticks(false);
 return RISCV_EXCP_NONE;
 }
 
 static RISCVException read_hpmcounterh(CPURISCVState *env, int csrno,
targ

[PULL 18/30] target/riscv: Add cycle & instret privilege mode filtering definitions

2024-07-17 Thread Alistair Francis
From: Kaiwen Xue 

This adds the definitions for ISA extension smcntrpmf.

Signed-off-by: Kaiwen Xue 
Reviewed-by: Daniel Henrique Barboza 
Reviewed-by: Alistair Francis 
Signed-off-by: Atish Patra 
Message-ID: <20240711-smcntrpmf_v7-v8-4-b7c38ae7b...@rivosinc.com>
Signed-off-by: Alistair Francis 
---
 target/riscv/cpu.h  |  6 ++
 target/riscv/cpu_bits.h | 29 +
 2 files changed, 35 insertions(+)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index 6520e0f5d5..980e2154cd 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -362,6 +362,12 @@ struct CPUArchState {
 
 uint32_t mcountinhibit;
 
+/* PMU cycle & instret privilege mode filtering */
+target_ulong mcyclecfg;
+target_ulong mcyclecfgh;
+target_ulong minstretcfg;
+target_ulong minstretcfgh;
+
 /* PMU counter state */
 PMUCTRState pmu_ctrs[RV_MAX_MHPMCOUNTERS];
 
diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index c257c5ed7d..5faa817453 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -397,6 +397,10 @@
 /* Machine counter-inhibit register */
 #define CSR_MCOUNTINHIBIT   0x320
 
+/* Machine counter configuration registers */
+#define CSR_MCYCLECFG   0x321
+#define CSR_MINSTRETCFG 0x322
+
 #define CSR_MHPMEVENT3  0x323
 #define CSR_MHPMEVENT4  0x324
 #define CSR_MHPMEVENT5  0x325
@@ -427,6 +431,9 @@
 #define CSR_MHPMEVENT30 0x33e
 #define CSR_MHPMEVENT31 0x33f
 
+#define CSR_MCYCLECFGH  0x721
+#define CSR_MINSTRETCFGH0x722
+
 #define CSR_MHPMEVENT3H 0x723
 #define CSR_MHPMEVENT4H 0x724
 #define CSR_MHPMEVENT5H 0x725
@@ -884,6 +891,28 @@ typedef enum RISCVException {
 /* PMU related bits */
 #define MIE_LCOFIE (1 << IRQ_PMU_OVF)
 
+#define MCYCLECFG_BIT_MINH BIT_ULL(62)
+#define MCYCLECFGH_BIT_MINHBIT(30)
+#define MCYCLECFG_BIT_SINH BIT_ULL(61)
+#define MCYCLECFGH_BIT_SINHBIT(29)
+#define MCYCLECFG_BIT_UINH BIT_ULL(60)
+#define MCYCLECFGH_BIT_UINHBIT(28)
+#define MCYCLECFG_BIT_VSINHBIT_ULL(59)
+#define MCYCLECFGH_BIT_VSINH   BIT(27)
+#define MCYCLECFG_BIT_VUINHBIT_ULL(58)
+#define MCYCLECFGH_BIT_VUINH   BIT(26)
+
+#define MINSTRETCFG_BIT_MINH   BIT_ULL(62)
+#define MINSTRETCFGH_BIT_MINH  BIT(30)
+#define MINSTRETCFG_BIT_SINH   BIT_ULL(61)
+#define MINSTRETCFGH_BIT_SINH  BIT(29)
+#define MINSTRETCFG_BIT_UINH   BIT_ULL(60)
+#define MINSTRETCFGH_BIT_UINH  BIT(28)
+#define MINSTRETCFG_BIT_VSINH  BIT_ULL(59)
+#define MINSTRETCFGH_BIT_VSINH BIT(27)
+#define MINSTRETCFG_BIT_VUINH  BIT_ULL(58)
+#define MINSTRETCFGH_BIT_VUINH BIT(26)
+
 #define MHPMEVENT_BIT_OF   BIT_ULL(63)
 #define MHPMEVENTH_BIT_OF  BIT(31)
 #define MHPMEVENT_BIT_MINH BIT_ULL(62)
-- 
2.45.2




[PULL 22/30] target/riscv: Save counter values during countinhibit update

2024-07-17 Thread Alistair Francis
From: Atish Patra 

Currently, if a counter monitoring cycle/instret is stopped via
mcountinhibit we just update the state while the value is saved
during the next read. This is not accurate as the read may happen
many cycles after the counter is stopped. Ideally, the read should
return the value saved when the counter is stopped.

Thus, save the value of the counter during the inhibit update
operation and return that value during the read if corresponding bit
in mcountihibit is set.

Acked-by: Alistair Francis 
Reviewed-by: Daniel Henrique Barboza 
Signed-off-by: Atish Patra 
Message-ID: <20240711-smcntrpmf_v7-v8-8-b7c38ae7b...@rivosinc.com>
Signed-off-by: Alistair Francis 
---
 target/riscv/cpu.h |  1 -
 target/riscv/csr.c | 34 ++
 target/riscv/machine.c |  5 ++---
 3 files changed, 24 insertions(+), 16 deletions(-)

diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
index f515ad072b..093c86b8b9 100644
--- a/target/riscv/cpu.h
+++ b/target/riscv/cpu.h
@@ -176,7 +176,6 @@ typedef struct PMUCTRState {
 target_ulong mhpmcounter_prev;
 /* Snapshort value of a counter in RV32 */
 target_ulong mhpmcounterh_prev;
-bool started;
 /* Value beyond UINT32_MAX/UINT64_MAX before overflow interrupt trigger */
 target_ulong irq_overflow_left;
 } PMUCTRState;
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 85d3f0aa3f..b7a24f9c60 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -1131,17 +1131,11 @@ static RISCVException riscv_pmu_read_ctr(CPURISCVState 
*env, target_ulong *val,
 
 if (get_field(env->mcountinhibit, BIT(ctr_idx))) {
 /*
- * Counter should not increment if inhibit bit is set. We can't really
- * stop the icount counting. Just return the counter value written by
- * the supervisor to indicate that counter was not incremented.
+ * Counter should not increment if inhibit bit is set. Just return the
+ * current counter value.
  */
-if (!counter->started) {
-*val = ctr_val;
-return RISCV_EXCP_NONE;
-} else {
-/* Mark that the counter has been stopped */
-counter->started = false;
-}
+ *val = ctr_val;
+ return RISCV_EXCP_NONE;
 }
 
 /*
@@ -2183,9 +2177,25 @@ static RISCVException write_mcountinhibit(CPURISCVState 
*env, int csrno,
 
 /* Check if any other counter is also monitoring cycles/instructions */
 for (cidx = 0; cidx < RV_MAX_MHPMCOUNTERS; cidx++) {
-if (!get_field(env->mcountinhibit, BIT(cidx))) {
 counter = >pmu_ctrs[cidx];
-counter->started = true;
+if (get_field(env->mcountinhibit, BIT(cidx)) && (val & BIT(cidx))) {
+/*
+ * Update the counter value for cycle/instret as we can't stop the
+ * host ticks. But we should show the current value at this moment.
+ */
+if (riscv_pmu_ctr_monitor_cycles(env, cidx) ||
+riscv_pmu_ctr_monitor_instructions(env, cidx)) {
+counter->mhpmcounter_val =
+riscv_pmu_ctr_get_fixed_counters_val(env, cidx, false) -
+   counter->mhpmcounter_prev +
+   counter->mhpmcounter_val;
+if (riscv_cpu_mxl(env) == MXL_RV32) {
+counter->mhpmcounterh_val =
+riscv_pmu_ctr_get_fixed_counters_val(env, cidx, true) -
+counter->mhpmcounterh_prev +
+counter->mhpmcounterh_val;
+}
+}
 }
 }
 
diff --git a/target/riscv/machine.c b/target/riscv/machine.c
index 76f2150f78..492c2c6d9d 100644
--- a/target/riscv/machine.c
+++ b/target/riscv/machine.c
@@ -320,15 +320,14 @@ static bool pmu_needed(void *opaque)
 
 static const VMStateDescription vmstate_pmu_ctr_state = {
 .name = "cpu/pmu",
-.version_id = 1,
-.minimum_version_id = 1,
+.version_id = 2,
+.minimum_version_id = 2,
 .needed = pmu_needed,
 .fields = (const VMStateField[]) {
 VMSTATE_UINTTL(mhpmcounter_val, PMUCTRState),
 VMSTATE_UINTTL(mhpmcounterh_val, PMUCTRState),
 VMSTATE_UINTTL(mhpmcounter_prev, PMUCTRState),
 VMSTATE_UINTTL(mhpmcounterh_prev, PMUCTRState),
-VMSTATE_BOOL(started, PMUCTRState),
 VMSTATE_END_OF_LIST()
 }
 };
-- 
2.45.2




[PULL 16/30] target/riscv: Fix the predicate functions for mhpmeventhX CSRs

2024-07-17 Thread Alistair Francis
From: Atish Patra 

mhpmeventhX CSRs are available for RV32. The predicate function
should check that first before checking sscofpmf extension.

Fixes: 14664483457b ("target/riscv: Add sscofpmf extension support")
Reviewed-by: Daniel Henrique Barboza 
Reviewed-by: Alistair Francis 
Signed-off-by: Atish Patra 
Message-ID: <20240711-smcntrpmf_v7-v8-2-b7c38ae7b...@rivosinc.com>
Signed-off-by: Alistair Francis 
---
 target/riscv/csr.c | 67 ++
 1 file changed, 38 insertions(+), 29 deletions(-)

diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index f9229d92ab..1bcf75f91f 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -227,6 +227,15 @@ static RISCVException sscofpmf(CPURISCVState *env, int 
csrno)
 return RISCV_EXCP_NONE;
 }
 
+static RISCVException sscofpmf_32(CPURISCVState *env, int csrno)
+{
+if (riscv_cpu_mxl(env) != MXL_RV32) {
+return RISCV_EXCP_ILLEGAL_INST;
+}
+
+return sscofpmf(env, csrno);
+}
+
 static RISCVException any(CPURISCVState *env, int csrno)
 {
 return RISCV_EXCP_NONE;
@@ -5106,91 +5115,91 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
 [CSR_MHPMEVENT31]= { "mhpmevent31",any,read_mhpmevent,
  write_mhpmevent   },
 
-[CSR_MHPMEVENT3H]= { "mhpmevent3h",sscofpmf,  read_mhpmeventh,
+[CSR_MHPMEVENT3H]= { "mhpmevent3h",sscofpmf_32,  read_mhpmeventh,
  write_mhpmeventh,
  .min_priv_ver = PRIV_VERSION_1_12_0},
-[CSR_MHPMEVENT4H]= { "mhpmevent4h",sscofpmf,  read_mhpmeventh,
+[CSR_MHPMEVENT4H]= { "mhpmevent4h",sscofpmf_32,  read_mhpmeventh,
  write_mhpmeventh,
  .min_priv_ver = PRIV_VERSION_1_12_0},
-[CSR_MHPMEVENT5H]= { "mhpmevent5h",sscofpmf,  read_mhpmeventh,
+[CSR_MHPMEVENT5H]= { "mhpmevent5h",sscofpmf_32,  read_mhpmeventh,
  write_mhpmeventh,
  .min_priv_ver = PRIV_VERSION_1_12_0},
-[CSR_MHPMEVENT6H]= { "mhpmevent6h",sscofpmf,  read_mhpmeventh,
+[CSR_MHPMEVENT6H]= { "mhpmevent6h",sscofpmf_32,  read_mhpmeventh,
  write_mhpmeventh,
  .min_priv_ver = PRIV_VERSION_1_12_0},
-[CSR_MHPMEVENT7H]= { "mhpmevent7h",sscofpmf,  read_mhpmeventh,
+[CSR_MHPMEVENT7H]= { "mhpmevent7h",sscofpmf_32,  read_mhpmeventh,
  write_mhpmeventh,
  .min_priv_ver = PRIV_VERSION_1_12_0},
-[CSR_MHPMEVENT8H]= { "mhpmevent8h",sscofpmf,  read_mhpmeventh,
+[CSR_MHPMEVENT8H]= { "mhpmevent8h",sscofpmf_32,  read_mhpmeventh,
  write_mhpmeventh,
  .min_priv_ver = PRIV_VERSION_1_12_0},
-[CSR_MHPMEVENT9H]= { "mhpmevent9h",sscofpmf,  read_mhpmeventh,
+[CSR_MHPMEVENT9H]= { "mhpmevent9h",sscofpmf_32,  read_mhpmeventh,
  write_mhpmeventh,
  .min_priv_ver = PRIV_VERSION_1_12_0},
-[CSR_MHPMEVENT10H]   = { "mhpmevent10h",sscofpmf,  read_mhpmeventh,
+[CSR_MHPMEVENT10H]   = { "mhpmevent10h",sscofpmf_32,  read_mhpmeventh,
  write_mhpmeventh,
  .min_priv_ver = PRIV_VERSION_1_12_0},
-[CSR_MHPMEVENT11H]   = { "mhpmevent11h",sscofpmf,  read_mhpmeventh,
+[CSR_MHPMEVENT11H]   = { "mhpmevent11h",sscofpmf_32,  read_mhpmeventh,
  write_mhpmeventh,
  .min_priv_ver = PRIV_VERSION_1_12_0},
-[CSR_MHPMEVENT12H]   = { "mhpmevent12h",sscofpmf,  read_mhpmeventh,
+[CSR_MHPMEVENT12H]   = { "mhpmevent12h",sscofpmf_32,  read_mhpmeventh,
  write_mhpmeventh,
  .min_priv_ver = PRIV_VERSION_1_12_0},
-[CSR_MHPMEVENT13H]   = { "mhpmevent13h",sscofpmf,  read_mhpmeventh,
+[CSR_MHPMEVENT13H]   = { "mhpmevent13h",sscofpmf_32,  read_mhpmeventh,
  write_mhpmeventh,
  .min_priv_ver = PRIV_VERSION_1_12_0},
-[CSR_MHPMEVENT14H]   = { "mhpmevent14h",sscofpmf,  read_mhpmeventh,
+[CSR_MHPMEVENT14H]   = { "mhpmevent14h",sscofpmf_32,  read_mhpmeventh,
  write_mhpmeventh,
  .min_priv_ver = PRIV_VERSION_1_12_0},
-[CSR_MHPMEVENT15H]   = { "mhpmevent15h",   

[PULL 20/30] target/riscv: Only set INH fields if priv mode is available

2024-07-17 Thread Alistair Francis
From: Atish Patra 

Currently, the INH fields are set in mhpmevent uncoditionally
without checking if a particular priv mode is supported or not.

Suggested-by: Alistair Francis 
Signed-off-by: Atish Patra 
Acked-by: Alistair Francis 
Message-ID: <20240711-smcntrpmf_v7-v8-6-b7c38ae7b...@rivosinc.com>
Signed-off-by: Alistair Francis 
---
 target/riscv/csr.c | 29 +
 1 file changed, 25 insertions(+), 4 deletions(-)

diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 8831d4f5ec..364583dc03 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -967,13 +967,24 @@ static RISCVException write_mhpmevent(CPURISCVState *env, 
int csrno,
 {
 int evt_index = csrno - CSR_MCOUNTINHIBIT;
 uint64_t mhpmevt_val = val;
-
-env->mhpmevent_val[evt_index] = val;
+uint64_t inh_avail_mask;
 
 if (riscv_cpu_mxl(env) == MXL_RV32) {
+env->mhpmevent_val[evt_index] = val;
 mhpmevt_val = mhpmevt_val |
   ((uint64_t)env->mhpmeventh_val[evt_index] << 32);
+} else {
+inh_avail_mask = ~MHPMEVENT_FILTER_MASK | MHPMEVENT_BIT_MINH;
+inh_avail_mask |= riscv_has_ext(env, RVU) ? MHPMEVENT_BIT_UINH : 0;
+inh_avail_mask |= riscv_has_ext(env, RVS) ? MHPMEVENT_BIT_SINH : 0;
+inh_avail_mask |= (riscv_has_ext(env, RVH) &&
+   riscv_has_ext(env, RVU)) ? MHPMEVENT_BIT_VUINH : 0;
+inh_avail_mask |= (riscv_has_ext(env, RVH) &&
+   riscv_has_ext(env, RVS)) ? MHPMEVENT_BIT_VSINH : 0;
+mhpmevt_val = val & inh_avail_mask;
+env->mhpmevent_val[evt_index] = mhpmevt_val;
 }
+
 riscv_pmu_update_event_map(env, mhpmevt_val, evt_index);
 
 return RISCV_EXCP_NONE;
@@ -993,11 +1004,21 @@ static RISCVException write_mhpmeventh(CPURISCVState 
*env, int csrno,
target_ulong val)
 {
 int evt_index = csrno - CSR_MHPMEVENT3H + 3;
-uint64_t mhpmevth_val = val;
+uint64_t mhpmevth_val;
 uint64_t mhpmevt_val = env->mhpmevent_val[evt_index];
+target_ulong inh_avail_mask = (target_ulong)(~MHPMEVENTH_FILTER_MASK |
+  MHPMEVENTH_BIT_MINH);
+
+inh_avail_mask |= riscv_has_ext(env, RVU) ? MHPMEVENTH_BIT_UINH : 0;
+inh_avail_mask |= riscv_has_ext(env, RVS) ? MHPMEVENTH_BIT_SINH : 0;
+inh_avail_mask |= (riscv_has_ext(env, RVH) &&
+   riscv_has_ext(env, RVU)) ? MHPMEVENTH_BIT_VUINH : 0;
+inh_avail_mask |= (riscv_has_ext(env, RVH) &&
+   riscv_has_ext(env, RVS)) ? MHPMEVENTH_BIT_VSINH : 0;
 
+mhpmevth_val = val & inh_avail_mask;
 mhpmevt_val = mhpmevt_val | (mhpmevth_val << 32);
-env->mhpmeventh_val[evt_index] = val;
+env->mhpmeventh_val[evt_index] = mhpmevth_val;
 
 riscv_pmu_update_event_map(env, mhpmevt_val, evt_index);
 
-- 
2.45.2




[PULL 17/30] target/riscv: Add cycle & instret privilege mode filtering properties

2024-07-17 Thread Alistair Francis
From: Kaiwen Xue 

This adds the properties for ISA extension smcntrpmf. Patches
implementing it will follow.

Signed-off-by: Kaiwen Xue 
Reviewed-by: Daniel Henrique Barboza 
Signed-off-by: Atish Patra 
Reviewed-by: Alistair Francis 
Message-ID: <20240711-smcntrpmf_v7-v8-3-b7c38ae7b...@rivosinc.com>
Signed-off-by: Alistair Francis 
---
 target/riscv/cpu_cfg.h | 1 +
 target/riscv/cpu.c | 1 +
 2 files changed, 2 insertions(+)

diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h
index 120905a254..8b272fb826 100644
--- a/target/riscv/cpu_cfg.h
+++ b/target/riscv/cpu_cfg.h
@@ -76,6 +76,7 @@ struct RISCVCPUConfig {
 bool ext_ztso;
 bool ext_smstateen;
 bool ext_sstc;
+bool ext_smcntrpmf;
 bool ext_svadu;
 bool ext_svinval;
 bool ext_svnapot;
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index 33ef4eb795..4efe7ee3b0 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -182,6 +182,7 @@ const RISCVIsaExtData isa_edata_arr[] = {
 ISA_EXT_DATA_ENTRY(zhinx, PRIV_VERSION_1_12_0, ext_zhinx),
 ISA_EXT_DATA_ENTRY(zhinxmin, PRIV_VERSION_1_12_0, ext_zhinxmin),
 ISA_EXT_DATA_ENTRY(smaia, PRIV_VERSION_1_12_0, ext_smaia),
+ISA_EXT_DATA_ENTRY(smcntrpmf, PRIV_VERSION_1_12_0, ext_smcntrpmf),
 ISA_EXT_DATA_ENTRY(smepmp, PRIV_VERSION_1_12_0, ext_smepmp),
 ISA_EXT_DATA_ENTRY(smstateen, PRIV_VERSION_1_12_0, ext_smstateen),
 ISA_EXT_DATA_ENTRY(ssaia, PRIV_VERSION_1_12_0, ext_ssaia),
-- 
2.45.2




[PULL 13/30] disas/riscv: Add decode for Zawrs extension

2024-07-17 Thread Alistair Francis
From: Balaji Ravikumar 

Add disassembly support for these instructions from Zawrs:

* wrs.sto
* wrs.nto

Signed-off-by: Balaji Ravikumar 
Signed-off-by: Rob Bradford 
Acked-by: Alistair Francis 
Message-ID: <20240705165316.127494-1-rbradf...@rivosinc.com>
Signed-off-by: Alistair Francis 
---
 disas/riscv.c | 6 ++
 1 file changed, 6 insertions(+)

diff --git a/disas/riscv.c b/disas/riscv.c
index c8364c2b07..5965574d87 100644
--- a/disas/riscv.c
+++ b/disas/riscv.c
@@ -974,6 +974,8 @@ typedef enum {
 rv_op_amomaxu_h = 943,
 rv_op_amocas_b  = 944,
 rv_op_amocas_h  = 945,
+rv_op_wrs_sto = 946,
+rv_op_wrs_nto = 947,
 } rv_op;
 
 /* register names */
@@ -2232,6 +2234,8 @@ const rv_opcode_data rvi_opcode_data[] = {
 { "amomaxu.h", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
 { "amocas.b", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
 { "amocas.h", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "wrs.sto", rv_codec_none, rv_fmt_none, NULL, 0, 0, 0 },
+{ "wrs.nto", rv_codec_none, rv_fmt_none, NULL, 0, 0, 0 },
 };
 
 /* CSR names */
@@ -3980,6 +3984,8 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa isa)
 case 0: op = rv_op_ecall; break;
 case 32: op = rv_op_ebreak; break;
 case 64: op = rv_op_uret; break;
+case 416: op = rv_op_wrs_nto; break;
+case 928: op = rv_op_wrs_sto; break;
 }
 break;
 case 256:
-- 
2.45.2




[PULL 01/30] target/riscv: Add zimop extension

2024-07-17 Thread Alistair Francis
From: LIU Zhiwei 

Zimop extension defines an encoding space for 40 MOPs.The Zimop
extension defines 32 MOP instructions named MOP.R.n, where n is
an integer between 0 and 31, inclusive. The Zimop extension
additionally defines 8 MOP instructions named MOP.RR.n, where n
is an integer between 0 and 7.

These 40 MOPs initially are defined to simply write zero to x[rd],
but are designed to be redefined by later extensions to perform some
other action.

Signed-off-by: LIU Zhiwei 
Reviewed-by: Alistair Francis 
Reviewed-by: Deepak Gupta 
Message-ID: <20240709113652.1239-2-zhiwei_...@linux.alibaba.com>
Signed-off-by: Alistair Francis 
---
 target/riscv/cpu_cfg.h  |  1 +
 target/riscv/insn32.decode  | 11 ++
 target/riscv/cpu.c  |  2 ++
 target/riscv/translate.c|  1 +
 target/riscv/insn_trans/trans_rvzimop.c.inc | 37 +
 5 files changed, 52 insertions(+)
 create mode 100644 target/riscv/insn_trans/trans_rvzimop.c.inc

diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h
index fb7eebde52..9f53512053 100644
--- a/target/riscv/cpu_cfg.h
+++ b/target/riscv/cpu_cfg.h
@@ -71,6 +71,7 @@ struct RISCVCPUConfig {
 bool ext_zihintntl;
 bool ext_zihintpause;
 bool ext_zihpm;
+bool ext_zimop;
 bool ext_ztso;
 bool ext_smstateen;
 bool ext_sstc;
diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
index f22df04cfd..60da673153 100644
--- a/target/riscv/insn32.decode
+++ b/target/riscv/insn32.decode
@@ -38,6 +38,8 @@
 %imm_bs   30:2   !function=ex_shift_3
 %imm_rnum 20:4
 %imm_z6   26:1 15:5
+%imm_mop5 30:1 26:2 20:2
+%imm_mop3 30:1 26:2
 
 # Argument sets:
 
@@ -56,6 +58,8 @@
 vm rd rs1 nf
  vm rd rs1 rs2 nf
 _aes shamt rs2 rs1 rd
+ imm rd rs1
+ imm rd rs1 rs2
 
 # Formats 32:
 @r   ...   . . ... . ... %rs2 %rs1 
%rd
@@ -98,6 +102,9 @@
 @k_aes   .. . . .  ... . ... _aes  shamt=%imm_bs   %rs2 
%rs1 %rd
 @i_aes   .. . . .  ... . ...   imm=%imm_rnum
%rs1 %rd
 
+@mop5 . . .. ..  .. . ... . ...  imm=%imm_mop5 %rd %rs1
+@mop3 . . .. .. . . . ... . ...  imm=%imm_mop3 %rd %rs1 
%rs2
+
 # Formats 64:
 @sh5 ...  . .  ... . ...   shamt=%sh5  %rs1 
%rd
 
@@ -1010,3 +1017,7 @@ amocas_w00101 . . . . 010 . 010 
@atom_st
 amocas_d00101 . . . . 011 . 010 @atom_st
 # *** RV64 Zacas Standard Extension ***
 amocas_q00101 . . . . 100 . 010 @atom_st
+
+# *** Zimop may-be-operation extension ***
+mop_r_n 1 . 00 .. 0111 .. . 100 . 1110011 @mop5
+mop_rr_n1 . 00 .. 1 . . 100 . 1110011 @mop3
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index c53b0d5b40..ac503826ce 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -113,6 +113,7 @@ const RISCVIsaExtData isa_edata_arr[] = {
 ISA_EXT_DATA_ENTRY(zihintntl, PRIV_VERSION_1_10_0, ext_zihintntl),
 ISA_EXT_DATA_ENTRY(zihintpause, PRIV_VERSION_1_10_0, ext_zihintpause),
 ISA_EXT_DATA_ENTRY(zihpm, PRIV_VERSION_1_12_0, ext_zihpm),
+ISA_EXT_DATA_ENTRY(zimop, PRIV_VERSION_1_13_0, ext_zimop),
 ISA_EXT_DATA_ENTRY(zmmul, PRIV_VERSION_1_12_0, ext_zmmul),
 ISA_EXT_DATA_ENTRY(za64rs, PRIV_VERSION_1_12_0, has_priv_1_11),
 ISA_EXT_DATA_ENTRY(zaamo, PRIV_VERSION_1_12_0, ext_zaamo),
@@ -1471,6 +1472,7 @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
 MULTI_EXT_CFG_BOOL("zicsr", ext_zicsr, true),
 MULTI_EXT_CFG_BOOL("zihintntl", ext_zihintntl, true),
 MULTI_EXT_CFG_BOOL("zihintpause", ext_zihintpause, true),
+MULTI_EXT_CFG_BOOL("zimop", ext_zimop, false),
 MULTI_EXT_CFG_BOOL("zacas", ext_zacas, false),
 MULTI_EXT_CFG_BOOL("zaamo", ext_zaamo, false),
 MULTI_EXT_CFG_BOOL("zalrsc", ext_zalrsc, false),
diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 0569224e53..379b68289f 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -1099,6 +1099,7 @@ static uint32_t opcode_at(DisasContextBase *dcbase, 
target_ulong pc)
 #include "insn_trans/trans_rvzacas.c.inc"
 #include "insn_trans/trans_rvzawrs.c.inc"
 #include "insn_trans/trans_rvzicbo.c.inc"
+#include "insn_trans/trans_rvzimop.c.inc"
 #include "insn_trans/trans_rvzfa.c.inc"
 #include "insn_trans/trans_rvzfh.c.inc"
 #include "insn_trans/trans_rvk.c.inc"
diff --git a/target/riscv/insn_trans/trans_rvzimop.c.inc 
b/target/riscv/insn_trans/trans_rvzimop.c.inc
new file mode 100644
index 00..165aacd2b6
--- /dev/null
+++ b/target/riscv/insn_trans/trans_rvzimop.c.inc
@@ -0,0 +1,37 @@
+/*
+ * RISC-V translation routines for May-Be-Operation(zimop).
+ *
+ * Copyright (c) 2024 Alibaba Group.
+ *
+ * This prog

[PULL 10/30] target/riscv: Expose zabha extension as a cpu property

2024-07-17 Thread Alistair Francis
From: LIU Zhiwei 

Signed-off-by: LIU Zhiwei 
Reviewed-by: Alistair Francis 
Message-ID: <20240709113652.1239-11-zhiwei_...@linux.alibaba.com>
Signed-off-by: Alistair Francis 
---
 target/riscv/cpu.c | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
index de9c06904f..33ef4eb795 100644
--- a/target/riscv/cpu.c
+++ b/target/riscv/cpu.c
@@ -117,6 +117,7 @@ const RISCVIsaExtData isa_edata_arr[] = {
 ISA_EXT_DATA_ENTRY(zmmul, PRIV_VERSION_1_12_0, ext_zmmul),
 ISA_EXT_DATA_ENTRY(za64rs, PRIV_VERSION_1_12_0, has_priv_1_11),
 ISA_EXT_DATA_ENTRY(zaamo, PRIV_VERSION_1_12_0, ext_zaamo),
+ISA_EXT_DATA_ENTRY(zabha, PRIV_VERSION_1_13_0, ext_zabha),
 ISA_EXT_DATA_ENTRY(zacas, PRIV_VERSION_1_12_0, ext_zacas),
 ISA_EXT_DATA_ENTRY(zama16b, PRIV_VERSION_1_13_0, ext_zama16b),
 ISA_EXT_DATA_ENTRY(zalrsc, PRIV_VERSION_1_12_0, ext_zalrsc),
@@ -1478,6 +1479,7 @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
 MULTI_EXT_CFG_BOOL("zcmop", ext_zcmop, false),
 MULTI_EXT_CFG_BOOL("zacas", ext_zacas, false),
 MULTI_EXT_CFG_BOOL("zama16b", ext_zama16b, false),
+MULTI_EXT_CFG_BOOL("zabha", ext_zabha, false),
 MULTI_EXT_CFG_BOOL("zaamo", ext_zaamo, false),
 MULTI_EXT_CFG_BOOL("zalrsc", ext_zalrsc, false),
 MULTI_EXT_CFG_BOOL("zawrs", ext_zawrs, true),
-- 
2.45.2




[PULL 08/30] target/riscv: Move gen_cmpxchg before adding amocas.[b|h]

2024-07-17 Thread Alistair Francis
From: LIU Zhiwei 

Signed-off-by: LIU Zhiwei 
Acked-by: Alistair Francis 
Message-ID: <20240709113652.1239-9-zhiwei_...@linux.alibaba.com>
Signed-off-by: Alistair Francis 
---
 target/riscv/translate.c| 13 +
 target/riscv/insn_trans/trans_rvzacas.c.inc | 13 -
 2 files changed, 13 insertions(+), 13 deletions(-)

diff --git a/target/riscv/translate.c b/target/riscv/translate.c
index 4a3e786560..acba90f170 100644
--- a/target/riscv/translate.c
+++ b/target/riscv/translate.c
@@ -1099,6 +1099,19 @@ static bool gen_amo(DisasContext *ctx, arg_atomic *a,
 return true;
 }
 
+static bool gen_cmpxchg(DisasContext *ctx, arg_atomic *a, MemOp mop)
+{
+TCGv dest = get_gpr(ctx, a->rd, EXT_NONE);
+TCGv src1 = get_address(ctx, a->rs1, 0);
+TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE);
+
+decode_save_opc(ctx);
+tcg_gen_atomic_cmpxchg_tl(dest, src1, dest, src2, ctx->mem_idx, mop);
+
+gen_set_gpr(ctx, a->rd, dest);
+return true;
+}
+
 static uint32_t opcode_at(DisasContextBase *dcbase, target_ulong pc)
 {
 DisasContext *ctx = container_of(dcbase, DisasContext, base);
diff --git a/target/riscv/insn_trans/trans_rvzacas.c.inc 
b/target/riscv/insn_trans/trans_rvzacas.c.inc
index 5d274d4c08..fcced99fc7 100644
--- a/target/riscv/insn_trans/trans_rvzacas.c.inc
+++ b/target/riscv/insn_trans/trans_rvzacas.c.inc
@@ -22,19 +22,6 @@
 } \
 } while (0)
 
-static bool gen_cmpxchg(DisasContext *ctx, arg_atomic *a, MemOp mop)
-{
-TCGv dest = get_gpr(ctx, a->rd, EXT_NONE);
-TCGv src1 = get_address(ctx, a->rs1, 0);
-TCGv src2 = get_gpr(ctx, a->rs2, EXT_NONE);
-
-decode_save_opc(ctx);
-tcg_gen_atomic_cmpxchg_tl(dest, src1, dest, src2, ctx->mem_idx, mop);
-
-gen_set_gpr(ctx, a->rd, dest);
-return true;
-}
-
 static bool trans_amocas_w(DisasContext *ctx, arg_amocas_w *a)
 {
 REQUIRE_ZACAS(ctx);
-- 
2.45.2




[PULL 02/30] disas/riscv: Support zimop disassemble

2024-07-17 Thread Alistair Francis
From: LIU Zhiwei 

Signed-off-by: LIU Zhiwei 
Acked-by: Alistair Francis 
Reviewed-by: Deepak Gupta 
Message-ID: <20240709113652.1239-3-zhiwei_...@linux.alibaba.com>
Signed-off-by: Alistair Francis 
---
 disas/riscv.c | 98 +++
 1 file changed, 98 insertions(+)

diff --git a/disas/riscv.c b/disas/riscv.c
index 90d6b26de9..0b82ab2322 100644
--- a/disas/riscv.c
+++ b/disas/riscv.c
@@ -906,6 +906,46 @@ typedef enum {
 rv_op_amocas_w = 875,
 rv_op_amocas_d = 876,
 rv_op_amocas_q = 877,
+rv_mop_r_0 = 878,
+rv_mop_r_1 = 879,
+rv_mop_r_2 = 880,
+rv_mop_r_3 = 881,
+rv_mop_r_4 = 882,
+rv_mop_r_5 = 883,
+rv_mop_r_6 = 884,
+rv_mop_r_7 = 885,
+rv_mop_r_8 = 886,
+rv_mop_r_9 = 887,
+rv_mop_r_10= 888,
+rv_mop_r_11= 889,
+rv_mop_r_12= 890,
+rv_mop_r_13= 891,
+rv_mop_r_14= 892,
+rv_mop_r_15= 893,
+rv_mop_r_16= 894,
+rv_mop_r_17= 895,
+rv_mop_r_18= 896,
+rv_mop_r_19= 897,
+rv_mop_r_20= 898,
+rv_mop_r_21= 899,
+rv_mop_r_22= 900,
+rv_mop_r_23= 901,
+rv_mop_r_24= 902,
+rv_mop_r_25= 903,
+rv_mop_r_26= 904,
+rv_mop_r_27= 905,
+rv_mop_r_28= 906,
+rv_mop_r_29= 907,
+rv_mop_r_30= 908,
+rv_mop_r_31= 909,
+rv_mop_rr_0= 910,
+rv_mop_rr_1= 911,
+rv_mop_rr_2= 912,
+rv_mop_rr_3= 913,
+rv_mop_rr_4= 914,
+rv_mop_rr_5= 915,
+rv_mop_rr_6= 916,
+rv_mop_rr_7= 917,
 } rv_op;
 
 /* register names */
@@ -2096,6 +2136,46 @@ const rv_opcode_data rvi_opcode_data[] = {
 { "amocas.w", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
 { "amocas.d", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
 { "amocas.q", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "mop.r.0", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.1", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.2", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.3", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.4", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.5", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.6", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.7", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.8", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.9", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.10", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.11", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.12", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.13", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.14", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.15", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.16", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.17", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.18", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.19", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.20", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.21", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.22", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.23", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.24", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.25", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.26", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.27", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.28", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.29", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.30", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.r.31", rv_codec_r, rv_fmt_rd_rs1, NULL, 0, 0 },
+{ "mop.rr.0", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
+{ "mop.rr.1", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
+{ "mop.rr.2", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
+{ "mop.rr.3", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
+{ "mop.rr.4", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
+{ "mop.rr.5", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
+{ "mop.rr.6", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
+{ "mop.rr.7", rv_codec_r, rv_fmt_rd_rs1_rs2, NULL, 0, 0, 0 },
 };
 
 /* CSR names */
@@ -3855,6 +3935,24 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa 
isa)
 case 1: op = rv_op_csrrw; break;
 cas

[PULL 19/30] target/riscv: Add cycle & instret privilege mode filtering support

2024-07-17 Thread Alistair Francis
From: Kaiwen Xue 

QEMU only calculates dummy cycles and instructions, so there is no
actual means to stop the icount in QEMU. Hence this patch merely adds
the functionality of accessing the cfg registers, and cause no actual
effects on the counting of cycle and instret counters.

Signed-off-by: Atish Patra 
Reviewed-by: Daniel Henrique Barboza 
Signed-off-by: Kaiwen Xue 
Acked-by: Alistair Francis 
Message-ID: <20240711-smcntrpmf_v7-v8-5-b7c38ae7b...@rivosinc.com>
Signed-off-by: Alistair Francis 
---
 target/riscv/cpu_bits.h |  12 
 target/riscv/csr.c  | 138 +++-
 2 files changed, 149 insertions(+), 1 deletion(-)

diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
index 5faa817453..32b068f18a 100644
--- a/target/riscv/cpu_bits.h
+++ b/target/riscv/cpu_bits.h
@@ -926,6 +926,18 @@ typedef enum RISCVException {
 #define MHPMEVENT_BIT_VUINHBIT_ULL(58)
 #define MHPMEVENTH_BIT_VUINH   BIT(26)
 
+#define MHPMEVENT_FILTER_MASK  (MHPMEVENT_BIT_MINH  | \
+MHPMEVENT_BIT_SINH  | \
+MHPMEVENT_BIT_UINH  | \
+MHPMEVENT_BIT_VSINH | \
+MHPMEVENT_BIT_VUINH)
+
+#define MHPMEVENTH_FILTER_MASK  (MHPMEVENTH_BIT_MINH  | \
+MHPMEVENTH_BIT_SINH  | \
+MHPMEVENTH_BIT_UINH  | \
+MHPMEVENTH_BIT_VSINH | \
+MHPMEVENTH_BIT_VUINH)
+
 #define MHPMEVENT_SSCOF_MASK   _ULL(0x)
 #define MHPMEVENT_IDX_MASK 0xF
 #define MHPMEVENT_SSCOF_RESVD  16
diff --git a/target/riscv/csr.c b/target/riscv/csr.c
index 1bcf75f91f..8831d4f5ec 100644
--- a/target/riscv/csr.c
+++ b/target/riscv/csr.c
@@ -30,7 +30,6 @@
 #include "qemu/guest-random.h"
 #include "qapi/error.h"
 
-
 /* CSR function table public API */
 void riscv_get_csr_ops(int csrno, riscv_csr_operations *ops)
 {
@@ -236,6 +235,24 @@ static RISCVException sscofpmf_32(CPURISCVState *env, int 
csrno)
 return sscofpmf(env, csrno);
 }
 
+static RISCVException smcntrpmf(CPURISCVState *env, int csrno)
+{
+if (!riscv_cpu_cfg(env)->ext_smcntrpmf) {
+return RISCV_EXCP_ILLEGAL_INST;
+}
+
+return RISCV_EXCP_NONE;
+}
+
+static RISCVException smcntrpmf_32(CPURISCVState *env, int csrno)
+{
+if (riscv_cpu_mxl(env) != MXL_RV32) {
+return RISCV_EXCP_ILLEGAL_INST;
+}
+
+return smcntrpmf(env, csrno);
+}
+
 static RISCVException any(CPURISCVState *env, int csrno)
 {
 return RISCV_EXCP_NONE;
@@ -830,6 +847,111 @@ static RISCVException read_hpmcounterh(CPURISCVState 
*env, int csrno,
 
 #else /* CONFIG_USER_ONLY */
 
+static RISCVException read_mcyclecfg(CPURISCVState *env, int csrno,
+ target_ulong *val)
+{
+*val = env->mcyclecfg;
+return RISCV_EXCP_NONE;
+}
+
+static RISCVException write_mcyclecfg(CPURISCVState *env, int csrno,
+  target_ulong val)
+{
+uint64_t inh_avail_mask;
+
+if (riscv_cpu_mxl(env) == MXL_RV32) {
+env->mcyclecfg = val;
+} else {
+/* Set xINH fields if priv mode supported */
+inh_avail_mask = ~MHPMEVENT_FILTER_MASK | MCYCLECFG_BIT_MINH;
+inh_avail_mask |= riscv_has_ext(env, RVU) ? MCYCLECFG_BIT_UINH : 0;
+inh_avail_mask |= riscv_has_ext(env, RVS) ? MCYCLECFG_BIT_SINH : 0;
+inh_avail_mask |= (riscv_has_ext(env, RVH) &&
+   riscv_has_ext(env, RVU)) ? MCYCLECFG_BIT_VUINH : 0;
+inh_avail_mask |= (riscv_has_ext(env, RVH) &&
+   riscv_has_ext(env, RVS)) ? MCYCLECFG_BIT_VSINH : 0;
+env->mcyclecfg = val & inh_avail_mask;
+}
+
+return RISCV_EXCP_NONE;
+}
+
+static RISCVException read_mcyclecfgh(CPURISCVState *env, int csrno,
+  target_ulong *val)
+{
+*val = env->mcyclecfgh;
+return RISCV_EXCP_NONE;
+}
+
+static RISCVException write_mcyclecfgh(CPURISCVState *env, int csrno,
+   target_ulong val)
+{
+target_ulong inh_avail_mask = (target_ulong)(~MHPMEVENTH_FILTER_MASK |
+ MCYCLECFGH_BIT_MINH);
+
+/* Set xINH fields if priv mode supported */
+inh_avail_mask |= riscv_has_ext(env, RVU) ? MCYCLECFGH_BIT_UINH : 0;
+inh_avail_mask |= riscv_has_ext(env, RVS) ? MCYCLECFGH_BIT_SINH : 0;
+inh_avail_mask |= (riscv_has_ext(env, RVH) &&
+   riscv_has_ext(env, RVU)) ? MCYCLECFGH_BIT_VUINH : 0;
+inh_avail_mask |= (riscv_has_ext(env, RVH) &&
+   riscv_has_ext(env, RVS)) ? MCYCLECFGH_BIT_VSINH : 

[PULL 11/30] disas/riscv: Support zabha disassemble

2024-07-17 Thread Alistair Francis
From: LIU Zhiwei 

Signed-off-by: LIU Zhiwei 
Acked-by: Alistair Francis 
Message-ID: <20240709113652.1239-12-zhiwei_...@linux.alibaba.com>
Signed-off-by: Alistair Francis 
---
 disas/riscv.c | 60 +++
 1 file changed, 60 insertions(+)

diff --git a/disas/riscv.c b/disas/riscv.c
index d29cb1ff7d..c8364c2b07 100644
--- a/disas/riscv.c
+++ b/disas/riscv.c
@@ -954,6 +954,26 @@ typedef enum {
 rv_c_mop_11= 923,
 rv_c_mop_13= 924,
 rv_c_mop_15= 925,
+rv_op_amoswap_b = 926,
+rv_op_amoadd_b  = 927,
+rv_op_amoxor_b  = 928,
+rv_op_amoor_b   = 929,
+rv_op_amoand_b  = 930,
+rv_op_amomin_b  = 931,
+rv_op_amomax_b  = 932,
+rv_op_amominu_b = 933,
+rv_op_amomaxu_b = 934,
+rv_op_amoswap_h = 935,
+rv_op_amoadd_h  = 936,
+rv_op_amoxor_h  = 937,
+rv_op_amoor_h   = 938,
+rv_op_amoand_h  = 939,
+rv_op_amomin_h  = 940,
+rv_op_amomax_h  = 941,
+rv_op_amominu_h = 942,
+rv_op_amomaxu_h = 943,
+rv_op_amocas_b  = 944,
+rv_op_amocas_h  = 945,
 } rv_op;
 
 /* register names */
@@ -2192,6 +2212,26 @@ const rv_opcode_data rvi_opcode_data[] = {
 { "c.mop.11", rv_codec_ci_none, rv_fmt_none, NULL, 0, 0, 0 },
 { "c.mop.13", rv_codec_ci_none, rv_fmt_none, NULL, 0, 0, 0 },
 { "c.mop.15", rv_codec_ci_none, rv_fmt_none, NULL, 0, 0, 0 },
+{ "amoswap.b", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amoadd.b", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amoxor.b", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amoor.b", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amoand.b", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amomin.b", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amomax.b", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amominu.b", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amomaxu.b", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amoswap.h", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amoadd.h", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amoxor.h", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amoor.h", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amoand.h", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amomin.h", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amomax.h", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amominu.h", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amomaxu.h", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amocas.b", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
+{ "amocas.h", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
 };
 
 /* CSR names */
@@ -2986,9 +3026,13 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa 
isa)
 case 11:
 switch (((inst >> 24) & 0b1000) |
 ((inst >> 12) & 0b0111)) {
+case 0: op = rv_op_amoadd_b; break;
+case 1: op = rv_op_amoadd_h; break;
 case 2: op = rv_op_amoadd_w; break;
 case 3: op = rv_op_amoadd_d; break;
 case 4: op = rv_op_amoadd_q; break;
+case 8: op = rv_op_amoswap_b; break;
+case 9: op = rv_op_amoswap_h; break;
 case 10: op = rv_op_amoswap_w; break;
 case 11: op = rv_op_amoswap_d; break;
 case 12: op = rv_op_amoswap_q; break;
@@ -3010,27 +3054,43 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa 
isa)
 case 26: op = rv_op_sc_w; break;
 case 27: op = rv_op_sc_d; break;
 case 28: op = rv_op_sc_q; break;
+case 32: op = rv_op_amoxor_b; break;
+case 33: op = rv_op_amoxor_h; break;
 case 34: op = rv_op_amoxor_w; break;
 case 35: op = rv_op_amoxor_d; break;
 case 36: op = rv_op_amoxor_q; break;
+case 40: op = rv_op_amocas_b; break;
+case 41: op = rv_op_amocas_h; break;
 case 42: op = rv_op_amocas_w; break;
 case 43: op = rv_op_amocas_d; break;
 case 44: op = rv_op_amocas_q; break;
+case 64: op = rv_op_amoor_b; break;
+case 65: op = rv_op_amoor_h; break;
 case 66: op = rv_op_amoor_w; break;
 case 67: op = rv_op_amoor_d; break;
 case 68: op = rv_op_amoor_q; break;
+case 96: op = rv_op_amoand_b; break;
+case 97: op = rv_op_amoand_h; break;
 case 98: op = rv_op_amoand_w; break;
 case 99: o

[PULL 00/30] riscv-to-apply queue

2024-07-17 Thread Alistair Francis
The following changes since commit 58ee924b97d1c0898555647a31820c5a20d55a73:

  Merge tag 'for-upstream' of https://gitlab.com/bonzini/qemu into staging 
(2024-07-17 15:40:28 +1000)

are available in the Git repository at:

  https://github.com/alistair23/qemu.git tags/pull-riscv-to-apply-20240718-1

for you to fetch changes up to daff9f7f7a457f78ce455e6abf19c2a37dfe7630:

  roms/opensbi: Update to v1.5 (2024-07-18 12:08:45 +1000)


RISC-V PR for 9.1

* Support the zimop, zcmop, zama16b and zabha extensions
* Validate the mode when setting vstvec CSR
* Add decode support for Zawrs extension
* Update the KVM regs to Linux 6.10-rc5
* Add smcntrpmf extension support
* Raise an exception when CSRRS/CSRRC writes a read-only CSR
* Re-insert and deprecate 'riscv,delegate' in virt machine device tree
* roms/opensbi: Update to v1.5


Atish Patra (7):
  target/riscv: Fix the predicate functions for mhpmeventhX CSRs
  target/riscv: Only set INH fields if priv mode is available
  target/riscv: Implement privilege mode filtering for cycle/instret
  target/riscv: Save counter values during countinhibit update
  target/riscv: Enforce WARL behavior for scounteren/hcounteren
  target/riscv: Do not setup pmu timer if OF is disabled
  target/riscv: Expose the Smcntrpmf config

Balaji Ravikumar (1):
  disas/riscv: Add decode for Zawrs extension

Daniel Henrique Barboza (3):
  target/riscv/kvm: update KVM regs to Linux 6.10-rc5
  hw/riscv/virt.c: re-insert and deprecate 'riscv,delegate'
  roms/opensbi: Update to v1.5

Jiayi Li (1):
  target/riscv: Validate the mode in write_vstvec

Kaiwen Xue (3):
  target/riscv: Add cycle & instret privilege mode filtering properties
  target/riscv: Add cycle & instret privilege mode filtering definitions
  target/riscv: Add cycle & instret privilege mode filtering support

LIU Zhiwei (11):
  target/riscv: Add zimop extension
  disas/riscv: Support zimop disassemble
  target/riscv: Add zcmop extension
  disas/riscv: Support zcmop disassemble
  target/riscv: Support Zama16b extension
  target/riscv: Move gen_amo before implement Zabha
  target/riscv: Add AMO instructions for Zabha
  target/riscv: Move gen_cmpxchg before adding amocas.[b|h]
  target/riscv: Add amocas.[b|h] for Zabha
  target/riscv: Expose zabha extension as a cpu property
  disas/riscv: Support zabha disassemble

Rajnesh Kanwal (3):
  target/riscv: Combine set_mode and set_virt functions.
  target/riscv: Start counters from both mhpmcounter and mcountinhibit
  target/riscv: More accurately model priv mode filtering.

Yu-Ming Chang (1):
  target/riscv: raise an exception when CSRRS/CSRRC writes a read-only CSR

 docs/about/deprecated.rst  |  11 +
 target/riscv/cpu.h |  24 +-
 target/riscv/cpu_bits.h|  41 ++
 target/riscv/cpu_cfg.h |   5 +
 target/riscv/pmu.h |   4 +
 target/riscv/insn16.decode |   1 +
 target/riscv/insn32.decode |  33 ++
 disas/riscv.c  | 187 +
 hw/riscv/virt.c|   9 +
 target/riscv/cpu.c |  10 +
 target/riscv/cpu_helper.c  |  66 ++--
 target/riscv/csr.c | 501 -
 target/riscv/kvm/kvm-cpu.c |   2 +
 target/riscv/machine.c |   5 +-
 target/riscv/op_helper.c   |  23 +-
 target/riscv/pmu.c | 181 -
 target/riscv/tcg/tcg-cpu.c |   5 +
 target/riscv/translate.c   |  38 ++
 target/riscv/insn_trans/trans_rva.c.inc|  51 +--
 target/riscv/insn_trans/trans_rvd.c.inc|  14 +-
 target/riscv/insn_trans/trans_rvf.c.inc|  14 +-
 target/riscv/insn_trans/trans_rvi.c.inc|   6 +
 target/riscv/insn_trans/trans_rvzabha.c.inc| 145 +++
 target/riscv/insn_trans/trans_rvzacas.c.inc|  13 -
 target/riscv/insn_trans/trans_rvzcmop.c.inc|  29 ++
 target/riscv/insn_trans/trans_rvzimop.c.inc|  37 ++
 pc-bios/opensbi-riscv32-generic-fw_dynamic.bin | Bin 267416 -> 268312 bytes
 pc-bios/opensbi-riscv64-generic-fw_dynamic.bin | Bin 270808 -> 272504 bytes
 roms/opensbi   |   2 +-
 29 files changed, 1246 insertions(+), 211 deletions(-)
 create mode 100644 target/riscv/insn_trans/trans_rvzabha.c.inc
 create mode 100644 target/riscv/insn_trans/trans_rvzcmop.c.inc
 create mode 100644 target/riscv/insn_trans/trans_rvzimop.c.inc



Re: [PATCH v2] hw/riscv/virt.c: re-insert and deprecate 'riscv, delegate'

2024-07-15 Thread Alistair Francis
On Mon, Jul 15, 2024 at 7:05 PM Daniel Henrique Barboza
 wrote:
>
> Commit b1f1e9dcfa renamed 'riscv,delegate' to 'riscv,delegation' since
> it is the correct name as per dt-bindings, and the absence of the
> correct name will result in validation fails when dumping the dtb and
> using dt-validate.
>
> But this change has a side-effect: every other firmware available that
> is AIA capable is using 'riscv,delegate', and it will fault/misbehave if
> this property isn't present. The property was added back in QEMU 7.0,
> meaning we have 2 years of firmware development using the wrong
> property.
>
> Re-introducing 'riscv,delegate' while keeping 'riscv,delegation' allows
> older firmwares to keep booting with the 'virt' machine.
> 'riscv,delegate' is then marked for future deprecation with its use
> being discouraged from now on.
>
> Cc: Conor Dooley 
> Cc: Anup Patel 
> Fixes: b1f1e9dcfa ("hw/riscv/virt.c: aplic DT: rename prop to 'riscv, 
> delegation'")
> Signed-off-by: Daniel Henrique Barboza 
> Reviewed-by: Alistair Francis 

Thanks!

Applied to riscv-to-apply.next

Alistair

> ---
>
> v2:
>  - changed commit msg to remove the 'dt-validate won't complain about
>it' bit since that was incorrect.
>
>  docs/about/deprecated.rst | 11 +++
>  hw/riscv/virt.c   |  9 +
>  2 files changed, 20 insertions(+)
>
> diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst
> index 20b7a17cf0..88f0f03786 100644
> --- a/docs/about/deprecated.rst
> +++ b/docs/about/deprecated.rst
> @@ -479,6 +479,17 @@ versions, aliases will point to newer CPU model versions
>  depending on the machine type, so management software must
>  resolve CPU model aliases before starting a virtual machine.
>
> +RISC-V "virt" board "riscv,delegate" DT property (since 9.1)
> +
> +
> +The "riscv,delegate" DT property was added in QEMU 7.0 as part of
> +the AIA APLIC support.  The property changed name during the review
> +process in Linux and the correct name ended up being
> +"riscv,delegation".  Changing the DT property name will break all
> +available firmwares that are using the current (wrong) name.  The
> +property is kept as is in 9.1, together with "riscv,delegation", to
> +give more time for firmware developers to change their code.
> +
>  Migration
>  -
>
> diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
> index bc0893e087..9981e0f6c9 100644
> --- a/hw/riscv/virt.c
> +++ b/hw/riscv/virt.c
> @@ -651,6 +651,15 @@ static void create_fdt_one_aplic(RISCVVirtState *s, int 
> socket,
>  qemu_fdt_setprop_cells(ms->fdt, aplic_name, "riscv,delegation",
> aplic_child_phandle, 0x1,
> VIRT_IRQCHIP_NUM_SOURCES);
> +/*
> + * DEPRECATED_9.1: Compat property kept temporarily
> + * to allow old firmwares to work with AIA. Do *not*
> + * use 'riscv,delegate' in new code: use
> + * 'riscv,delegation' instead.
> + */
> +qemu_fdt_setprop_cells(ms->fdt, aplic_name, "riscv,delegate",
> +   aplic_child_phandle, 0x1,
> +   VIRT_IRQCHIP_NUM_SOURCES);
>  }
>
>  riscv_socket_fdt_write_id(ms, aplic_name, socket);
> --
> 2.45.2
>
>



Re: [PATCH v8 00/13] Add RISC-V ISA extension smcntrpmf support

2024-07-14 Thread Alistair Francis
On Fri, Jul 12, 2024 at 8:33 AM Atish Patra  wrote:
>
> This patch series adds the support for RISC-V ISA extension smcntrpmf (cycle 
> and
> privilege mode filtering) [1]. It is based on Kevin's earlier work but 
> improves
> it by actually implement privilege mode filtering by tracking the privilege
> mode switches. This enables the privilege mode filtering for mhpmcounters as
> well. However, Smcntrpmf/Sscofpmf must be enabled to leverage this.
>
> The series is also available at [2] as well.
>
> Changes in v8:
> - Moved the config option to a separate patch at the end of the series.
> - Fixed a comments recieved in v7 around setting INH bit based on available 
> priv modes.
> - Updated the RB/AB tags.
> - Link to v7: 
> https://lore.kernel.org/r/20240626-smcntrpmf_v7-v7-0-bb0f10af7...@rivosinc.com
>
> Changes from v6->v7:
> 1. Fixed a compilation issue.
>
> Changes from v5->v6:
> 1. Rebased on top of alister/riscv-to-apply.next (c50aabe132) and icount fix
>patch[4] which may cause conflicts.
> 2. Fixed a bug in pmf logic related to VS<->HS transition and same mode
>recording.
> 3. Merged assorted fixes PR as the changes are intertwined. [2]
> 4. Fix counter inhibit CSR behavior. This change now start counters from both
>mhpmcounter and mcountinhibit writes. Previously cycle/inst timer was
>only started on mhpmcounterx write.
> 5. Optimized the PMU timer setup code.
>
> Changes from v4->v5:
> 1. Rebased on top of master(158a054c4d1a).
> 2. Fixed a bug for VS<->HS transition.
>
> Changes from v3->v4:
> 1. Fixed the ordering of the ISA extension names in isa_edata_arr.
> 2. Added RB tags.
>
> Changes from v2->v3:
> 1. Fixed the rebasing error in PATCH2.
> 2. Added RB tags.
> 3. Addressed other review comments.
>
> Changes from v1->v2:
> 1. Implemented actual mode filtering for both icount and host ticks mode.
> 1. Addressed comments in v1.
> 2. Added Kevin's personal email address.
>
> [1] https://github.com/riscv/riscv-smcntrpmf
> [2] https://github.com/atishp04/qemu/tree/b4/smcntrpmf_v7
> [3] 
> https://lore.kernel.org/all/20240429-countinhibit_fix-v1-0-802ec1e99...@rivosinc.com/
> [4] 
> https://lore.kernel.org/qemu-riscv/20240618112649.76683-1-cle...@rivosinc.com/
>
> Cc: Rajnesh Kanwal 
>
> Signed-off-by: Atish Patra 
> ---
> Atish Patra (7):
>   target/riscv: Fix the predicate functions for mhpmeventhX CSRs
>   target/riscv: Only set INH fields if priv mode is available
>   target/riscv: Implement privilege mode filtering for cycle/instret
>   target/riscv: Save counter values during countinhibit update
>   target/riscv: Enforce WARL behavior for scounteren/hcounteren
>   target/riscv: Do not setup pmu timer if OF is disabled
>   target/riscv: Expose the Smcntrpmf config
>
> Kaiwen Xue (3):
>   target/riscv: Add cycle & instret privilege mode filtering properties
>   target/riscv: Add cycle & instret privilege mode filtering definitions
>   target/riscv: Add cycle & instret privilege mode filtering support
>
> Rajnesh Kanwal (3):
>   target/riscv: Combine set_mode and set_virt functions.
>   target/riscv: Start counters from both mhpmcounter and mcountinhibit
>   target/riscv: More accurately model priv mode filtering.
>
>  target/riscv/cpu.c|   2 +
>  target/riscv/cpu.h|  20 ++-
>  target/riscv/cpu_bits.h   |  41 +
>  target/riscv/cpu_cfg.h|   1 +
>  target/riscv/cpu_helper.c |  66 +++
>  target/riscv/csr.c| 437 
> +-
>  target/riscv/machine.c|   5 +-
>  target/riscv/op_helper.c  |  17 +-
>  target/riscv/pmu.c| 181 +--
>  target/riscv/pmu.h|   4 +
>  10 files changed, 624 insertions(+), 150 deletions(-)

Thanks!

Applied to riscv-to-apply.next

Alistair

> ---
> base-commit: 842a3d79a0e37cd3d685c4728308fac0d9bfd0bb
> change-id: 20240626-smcntrpmf_v7-3b275d1da117
> --
> Regards,
> Atish patra
>
>



Re: [PATCH v8 13/13] target/riscv: Expose the Smcntrpmf config

2024-07-14 Thread Alistair Francis
On Fri, Jul 12, 2024 at 8:34 AM Atish Patra  wrote:
>
> Create a new config for Smcntrpmf extension so that it can be enabled/
> disabled from the qemu commandline.
>
> Signed-off-by: Atish Patra 

Acked-by: Alistair Francis 

Alistair

> ---
>  target/riscv/cpu.c | 1 +
>  1 file changed, 1 insertion(+)
>
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index 63f553c92b00..ef50130a91e7 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -1468,6 +1468,7 @@ const char *riscv_get_misa_ext_description(uint32_t bit)
>  const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
>  /* Defaults for standard extensions */
>  MULTI_EXT_CFG_BOOL("sscofpmf", ext_sscofpmf, false),
> +MULTI_EXT_CFG_BOOL("smcntrpmf", ext_smcntrpmf, false),
>  MULTI_EXT_CFG_BOOL("zifencei", ext_zifencei, true),
>  MULTI_EXT_CFG_BOOL("zicsr", ext_zicsr, true),
>  MULTI_EXT_CFG_BOOL("zihintntl", ext_zihintntl, true),
>
> --
> 2.34.1
>
>



Re: [PATCH v8 06/13] target/riscv: Only set INH fields if priv mode is available

2024-07-14 Thread Alistair Francis
On Fri, Jul 12, 2024 at 8:34 AM Atish Patra  wrote:
>
> Currently, the INH fields are set in mhpmevent uncoditionally
> without checking if a particular priv mode is supported or not.
>
> Suggested-by: Alistair Francis 
> Signed-off-by: Atish Patra 

Thanks!

Acked-by: Alistair Francis 

Alistair

> ---
>  target/riscv/csr.c | 29 +
>  1 file changed, 25 insertions(+), 4 deletions(-)
>
> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> index b814d176cbb8..121996edab4b 100644
> --- a/target/riscv/csr.c
> +++ b/target/riscv/csr.c
> @@ -967,13 +967,24 @@ static RISCVException write_mhpmevent(CPURISCVState 
> *env, int csrno,
>  {
>  int evt_index = csrno - CSR_MCOUNTINHIBIT;
>  uint64_t mhpmevt_val = val;
> -
> -env->mhpmevent_val[evt_index] = val;
> +uint64_t inh_avail_mask;
>
>  if (riscv_cpu_mxl(env) == MXL_RV32) {
> +env->mhpmevent_val[evt_index] = val;
>  mhpmevt_val = mhpmevt_val |
>((uint64_t)env->mhpmeventh_val[evt_index] << 32);
> +} else {
> +inh_avail_mask = ~MHPMEVENT_FILTER_MASK | MHPMEVENT_BIT_MINH;
> +inh_avail_mask |= riscv_has_ext(env, RVU) ? MHPMEVENT_BIT_UINH : 0;
> +inh_avail_mask |= riscv_has_ext(env, RVS) ? MHPMEVENT_BIT_SINH : 0;
> +inh_avail_mask |= (riscv_has_ext(env, RVH) &&
> +   riscv_has_ext(env, RVU)) ? MHPMEVENT_BIT_VUINH : 
> 0;
> +inh_avail_mask |= (riscv_has_ext(env, RVH) &&
> +   riscv_has_ext(env, RVS)) ? MHPMEVENT_BIT_VSINH : 
> 0;
> +mhpmevt_val = val & inh_avail_mask;
> +env->mhpmevent_val[evt_index] = mhpmevt_val;
>  }
> +
>  riscv_pmu_update_event_map(env, mhpmevt_val, evt_index);
>
>  return RISCV_EXCP_NONE;
> @@ -993,11 +1004,21 @@ static RISCVException write_mhpmeventh(CPURISCVState 
> *env, int csrno,
> target_ulong val)
>  {
>  int evt_index = csrno - CSR_MHPMEVENT3H + 3;
> -uint64_t mhpmevth_val = val;
> +uint64_t mhpmevth_val;
>  uint64_t mhpmevt_val = env->mhpmevent_val[evt_index];
> +target_ulong inh_avail_mask = (target_ulong)(~MHPMEVENTH_FILTER_MASK |
> +  MHPMEVENTH_BIT_MINH);
> +
> +inh_avail_mask |= riscv_has_ext(env, RVU) ? MHPMEVENTH_BIT_UINH : 0;
> +inh_avail_mask |= riscv_has_ext(env, RVS) ? MHPMEVENTH_BIT_SINH : 0;
> +inh_avail_mask |= (riscv_has_ext(env, RVH) &&
> +   riscv_has_ext(env, RVU)) ? MHPMEVENTH_BIT_VUINH : 0;
> +inh_avail_mask |= (riscv_has_ext(env, RVH) &&
> +   riscv_has_ext(env, RVS)) ? MHPMEVENTH_BIT_VSINH : 0;
>
> +mhpmevth_val = val & inh_avail_mask;
>  mhpmevt_val = mhpmevt_val | (mhpmevth_val << 32);
> -env->mhpmeventh_val[evt_index] = val;
> +env->mhpmeventh_val[evt_index] = mhpmevth_val;
>
>  riscv_pmu_update_event_map(env, mhpmevt_val, evt_index);
>
>
> --
> 2.34.1
>
>



Re: [PATCH v8 05/13] target/riscv: Add cycle & instret privilege mode filtering support

2024-07-14 Thread Alistair Francis
On Fri, Jul 12, 2024 at 8:34 AM Atish Patra  wrote:
>
> From: Kaiwen Xue 
>
> QEMU only calculates dummy cycles and instructions, so there is no
> actual means to stop the icount in QEMU. Hence this patch merely adds
> the functionality of accessing the cfg registers, and cause no actual
> effects on the counting of cycle and instret counters.
>
> Signed-off-by: Atish Patra 
> Reviewed-by: Daniel Henrique Barboza 
> Signed-off-by: Kaiwen Xue 

Acked-by: Alistair Francis 

Alistair

> ---
>  target/riscv/cpu_bits.h |  12 +
>  target/riscv/csr.c  | 138 
> +++-
>  2 files changed, 149 insertions(+), 1 deletion(-)
>
> diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
> index 5faa817453bb..32b068f18aa5 100644
> --- a/target/riscv/cpu_bits.h
> +++ b/target/riscv/cpu_bits.h
> @@ -926,6 +926,18 @@ typedef enum RISCVException {
>  #define MHPMEVENT_BIT_VUINHBIT_ULL(58)
>  #define MHPMEVENTH_BIT_VUINH   BIT(26)
>
> +#define MHPMEVENT_FILTER_MASK  (MHPMEVENT_BIT_MINH  | \
> +MHPMEVENT_BIT_SINH  | \
> +MHPMEVENT_BIT_UINH  | \
> +MHPMEVENT_BIT_VSINH | \
> +MHPMEVENT_BIT_VUINH)
> +
> +#define MHPMEVENTH_FILTER_MASK  (MHPMEVENTH_BIT_MINH  | \
> +MHPMEVENTH_BIT_SINH  | \
> +MHPMEVENTH_BIT_UINH  | \
> +MHPMEVENTH_BIT_VSINH | \
> +MHPMEVENTH_BIT_VUINH)
> +
>  #define MHPMEVENT_SSCOF_MASK   _ULL(0x)
>  #define MHPMEVENT_IDX_MASK 0xF
>  #define MHPMEVENT_SSCOF_RESVD  16
> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> index 3ad851707e5c..b814d176cbb8 100644
> --- a/target/riscv/csr.c
> +++ b/target/riscv/csr.c
> @@ -30,7 +30,6 @@
>  #include "qemu/guest-random.h"
>  #include "qapi/error.h"
>
> -
>  /* CSR function table public API */
>  void riscv_get_csr_ops(int csrno, riscv_csr_operations *ops)
>  {
> @@ -236,6 +235,24 @@ static RISCVException sscofpmf_32(CPURISCVState *env, 
> int csrno)
>  return sscofpmf(env, csrno);
>  }
>
> +static RISCVException smcntrpmf(CPURISCVState *env, int csrno)
> +{
> +if (!riscv_cpu_cfg(env)->ext_smcntrpmf) {
> +return RISCV_EXCP_ILLEGAL_INST;
> +}
> +
> +return RISCV_EXCP_NONE;
> +}
> +
> +static RISCVException smcntrpmf_32(CPURISCVState *env, int csrno)
> +{
> +if (riscv_cpu_mxl(env) != MXL_RV32) {
> +return RISCV_EXCP_ILLEGAL_INST;
> +}
> +
> +return smcntrpmf(env, csrno);
> +}
> +
>  static RISCVException any(CPURISCVState *env, int csrno)
>  {
>  return RISCV_EXCP_NONE;
> @@ -830,6 +847,111 @@ static RISCVException read_hpmcounterh(CPURISCVState 
> *env, int csrno,
>
>  #else /* CONFIG_USER_ONLY */
>
> +static RISCVException read_mcyclecfg(CPURISCVState *env, int csrno,
> + target_ulong *val)
> +{
> +*val = env->mcyclecfg;
> +return RISCV_EXCP_NONE;
> +}
> +
> +static RISCVException write_mcyclecfg(CPURISCVState *env, int csrno,
> +  target_ulong val)
> +{
> +uint64_t inh_avail_mask;
> +
> +if (riscv_cpu_mxl(env) == MXL_RV32) {
> +env->mcyclecfg = val;
> +} else {
> +/* Set xINH fields if priv mode supported */
> +inh_avail_mask = ~MHPMEVENT_FILTER_MASK | MCYCLECFG_BIT_MINH;
> +inh_avail_mask |= riscv_has_ext(env, RVU) ? MCYCLECFG_BIT_UINH : 0;
> +inh_avail_mask |= riscv_has_ext(env, RVS) ? MCYCLECFG_BIT_SINH : 0;
> +inh_avail_mask |= (riscv_has_ext(env, RVH) &&
> +   riscv_has_ext(env, RVU)) ? MCYCLECFG_BIT_VUINH : 
> 0;
> +inh_avail_mask |= (riscv_has_ext(env, RVH) &&
> +   riscv_has_ext(env, RVS)) ? MCYCLECFG_BIT_VSINH : 
> 0;
> +env->mcyclecfg = val & inh_avail_mask;
> +}
> +
> +return RISCV_EXCP_NONE;
> +}
> +
> +static RISCVException read_mcyclecfgh(CPURISCVState *env, int csrno,
> +  target_ulong *val)
> +{
> +*val = env->mcyclecfgh;
> +return RISCV_EXCP_NONE;
> +}
> +
> +static RISCVException write_mcyclecfgh(CPURISCVState *env, int csrno,
> +   target_ulong val)
> +{
> +target_ulong inh_av

Re: [PATCH v8 03/13] target/riscv: Add cycle & instret privilege mode filtering properties

2024-07-14 Thread Alistair Francis
On Fri, Jul 12, 2024 at 8:33 AM Atish Patra  wrote:
>
> From: Kaiwen Xue 
>
> This adds the properties for ISA extension smcntrpmf. Patches
> implementing it will follow.
>
> Signed-off-by: Kaiwen Xue 
> Reviewed-by: Daniel Henrique Barboza 
> Signed-off-by: Atish Patra 

Reviewed-by: Alistair Francis 

Alistair

> ---
>  target/riscv/cpu.c | 1 +
>  target/riscv/cpu_cfg.h | 1 +
>  2 files changed, 2 insertions(+)
>
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index 4760cb2cc17f..63f553c92b00 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -178,6 +178,7 @@ const RISCVIsaExtData isa_edata_arr[] = {
>  ISA_EXT_DATA_ENTRY(zhinx, PRIV_VERSION_1_12_0, ext_zhinx),
>  ISA_EXT_DATA_ENTRY(zhinxmin, PRIV_VERSION_1_12_0, ext_zhinxmin),
>  ISA_EXT_DATA_ENTRY(smaia, PRIV_VERSION_1_12_0, ext_smaia),
> +ISA_EXT_DATA_ENTRY(smcntrpmf, PRIV_VERSION_1_12_0, ext_smcntrpmf),
>  ISA_EXT_DATA_ENTRY(smepmp, PRIV_VERSION_1_12_0, ext_smepmp),
>  ISA_EXT_DATA_ENTRY(smstateen, PRIV_VERSION_1_12_0, ext_smstateen),
>  ISA_EXT_DATA_ENTRY(ssaia, PRIV_VERSION_1_12_0, ext_ssaia),
> diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h
> index fb7eebde523b..b1376beb1dab 100644
> --- a/target/riscv/cpu_cfg.h
> +++ b/target/riscv/cpu_cfg.h
> @@ -74,6 +74,7 @@ struct RISCVCPUConfig {
>  bool ext_ztso;
>  bool ext_smstateen;
>  bool ext_sstc;
> +bool ext_smcntrpmf;
>  bool ext_svadu;
>  bool ext_svinval;
>  bool ext_svnapot;
>
> --
> 2.34.1
>
>



Re: [PATCH] hw/riscv/virt.c: re-insert and deprecate 'riscv, delegate'

2024-07-14 Thread Alistair Francis
On Sun, Jul 14, 2024 at 3:44 AM Daniel Henrique Barboza
 wrote:
>
> Commit b1f1e9dcfa renamed 'riscv,delegate' to 'riscv,delegation' since
> it is the correct name as per dt-bindings, and the absence of the
> correct name will result in validation fails when dumping the dtb and
> using dt-validate.
>
> But this change has a side-effect: every other firmware available that
> is AIA capable is using 'riscv,delegate', and it will fault/misbehave if
> this property isn't present. The property was added back in QEMU 7.0,
> meaning we have 2 years of firmware development using the wrong
> property.
>
> Re-introducing 'riscv,delegate' while keeping 'riscv,delegation' will
> make current firmwares to keep booting with the 'virt' machine and
> dt-validate won't complain about it since we're still using the expected
> property 'riscv,delegation'. 'riscv,delegate' is then marked for future
> deprecation and its use is being discouraged.
>
> Cc: Conor Dooley 
> Cc: Anup Patel 
> Fixes: b1f1e9dcfa ("hw/riscv/virt.c: aplic DT: rename prop to 'riscv, 
> delegation'")
> Signed-off-by: Daniel Henrique Barboza 

Thanks!

Applied to riscv-to-apply.next

Alistair

> ---
>  docs/about/deprecated.rst | 11 +++
>  hw/riscv/virt.c   |  9 +
>  2 files changed, 20 insertions(+)
>
> diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst
> index 20b7a17cf0..88f0f03786 100644
> --- a/docs/about/deprecated.rst
> +++ b/docs/about/deprecated.rst
> @@ -479,6 +479,17 @@ versions, aliases will point to newer CPU model versions
>  depending on the machine type, so management software must
>  resolve CPU model aliases before starting a virtual machine.
>
> +RISC-V "virt" board "riscv,delegate" DT property (since 9.1)
> +
> +
> +The "riscv,delegate" DT property was added in QEMU 7.0 as part of
> +the AIA APLIC support.  The property changed name during the review
> +process in Linux and the correct name ended up being
> +"riscv,delegation".  Changing the DT property name will break all
> +available firmwares that are using the current (wrong) name.  The
> +property is kept as is in 9.1, together with "riscv,delegation", to
> +give more time for firmware developers to change their code.
> +
>  Migration
>  -
>
> diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
> index bc0893e087..9981e0f6c9 100644
> --- a/hw/riscv/virt.c
> +++ b/hw/riscv/virt.c
> @@ -651,6 +651,15 @@ static void create_fdt_one_aplic(RISCVVirtState *s, int 
> socket,
>  qemu_fdt_setprop_cells(ms->fdt, aplic_name, "riscv,delegation",
> aplic_child_phandle, 0x1,
> VIRT_IRQCHIP_NUM_SOURCES);
> +/*
> + * DEPRECATED_9.1: Compat property kept temporarily
> + * to allow old firmwares to work with AIA. Do *not*
> + * use 'riscv,delegate' in new code: use
> + * 'riscv,delegation' instead.
> + */
> +qemu_fdt_setprop_cells(ms->fdt, aplic_name, "riscv,delegate",
> +   aplic_child_phandle, 0x1,
> +   VIRT_IRQCHIP_NUM_SOURCES);
>  }
>
>  riscv_socket_fdt_write_id(ms, aplic_name, socket);
> --
> 2.45.2
>
>



Re: [PATCH] hw/riscv/virt.c: re-insert and deprecate 'riscv, delegate'

2024-07-14 Thread Alistair Francis
On Sun, Jul 14, 2024 at 3:44 AM Daniel Henrique Barboza
 wrote:
>
> Commit b1f1e9dcfa renamed 'riscv,delegate' to 'riscv,delegation' since
> it is the correct name as per dt-bindings, and the absence of the
> correct name will result in validation fails when dumping the dtb and
> using dt-validate.
>
> But this change has a side-effect: every other firmware available that
> is AIA capable is using 'riscv,delegate', and it will fault/misbehave if
> this property isn't present. The property was added back in QEMU 7.0,
> meaning we have 2 years of firmware development using the wrong
> property.
>
> Re-introducing 'riscv,delegate' while keeping 'riscv,delegation' will
> make current firmwares to keep booting with the 'virt' machine and
> dt-validate won't complain about it since we're still using the expected
> property 'riscv,delegation'. 'riscv,delegate' is then marked for future
> deprecation and its use is being discouraged.
>
> Cc: Conor Dooley 
> Cc: Anup Patel 
> Fixes: b1f1e9dcfa ("hw/riscv/virt.c: aplic DT: rename prop to 'riscv, 
> delegation'")
> Signed-off-by: Daniel Henrique Barboza 

Reviewed-by: Alistair Francis 

Alistair

> ---
>  docs/about/deprecated.rst | 11 +++
>  hw/riscv/virt.c   |  9 +
>  2 files changed, 20 insertions(+)
>
> diff --git a/docs/about/deprecated.rst b/docs/about/deprecated.rst
> index 20b7a17cf0..88f0f03786 100644
> --- a/docs/about/deprecated.rst
> +++ b/docs/about/deprecated.rst
> @@ -479,6 +479,17 @@ versions, aliases will point to newer CPU model versions
>  depending on the machine type, so management software must
>  resolve CPU model aliases before starting a virtual machine.
>
> +RISC-V "virt" board "riscv,delegate" DT property (since 9.1)
> +
> +
> +The "riscv,delegate" DT property was added in QEMU 7.0 as part of
> +the AIA APLIC support.  The property changed name during the review
> +process in Linux and the correct name ended up being
> +"riscv,delegation".  Changing the DT property name will break all
> +available firmwares that are using the current (wrong) name.  The
> +property is kept as is in 9.1, together with "riscv,delegation", to
> +give more time for firmware developers to change their code.
> +
>  Migration
>  -
>
> diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
> index bc0893e087..9981e0f6c9 100644
> --- a/hw/riscv/virt.c
> +++ b/hw/riscv/virt.c
> @@ -651,6 +651,15 @@ static void create_fdt_one_aplic(RISCVVirtState *s, int 
> socket,
>  qemu_fdt_setprop_cells(ms->fdt, aplic_name, "riscv,delegation",
> aplic_child_phandle, 0x1,
> VIRT_IRQCHIP_NUM_SOURCES);
> +/*
> + * DEPRECATED_9.1: Compat property kept temporarily
> + * to allow old firmwares to work with AIA. Do *not*
> + * use 'riscv,delegate' in new code: use
> + * 'riscv,delegation' instead.
> + */
> +qemu_fdt_setprop_cells(ms->fdt, aplic_name, "riscv,delegate",
> +   aplic_child_phandle, 0x1,
> +   VIRT_IRQCHIP_NUM_SOURCES);
>  }
>
>  riscv_socket_fdt_write_id(ms, aplic_name, socket);
> --
> 2.45.2
>
>



Re: [PATCH v4] target/riscv: raise an exception when CSRRS/CSRRC writes a read-only CSR

2024-07-11 Thread Alistair Francis
On Tue, Jun 4, 2024 at 7:15 PM Yu-Ming Chang via  wrote:

Something is strange with your `From` email address.

This seems to be a common problem with the Andes emails, do you mind
fixing this?

Alistair

>
> Both CSRRS and CSRRC always read the addressed CSR and cause any read side
> effects regardless of rs1 and rd fields. Note that if rs1 specifies a register
> holding a zero value other than x0, the instruction will still attempt to 
> write
> the unmodified value back to the CSR and will cause any attendant side 
> effects.
>
> So if CSRRS or CSRRC tries to write a read-only CSR with rs1 which specifies
> a register holding a zero value, an illegal instruction exception should be
> raised.
>
> Signed-off-by: Yu-Ming Chang 
> Signed-off-by: Alvin Chang 
> ---
> Hi Alistair,
> This fixed the issue of riscv_csrrw_debug().
>
> Best regards,
> Yuming
>
>  target/riscv/cpu.h   |  4 +++
>  target/riscv/csr.c   | 57 
>  target/riscv/op_helper.c |  6 ++---
>  3 files changed, 58 insertions(+), 9 deletions(-)
>
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index 2d0c02c35b..72921bafc0 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -708,6 +708,8 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, vaddr *pc,
>  void riscv_cpu_update_mask(CPURISCVState *env);
>  bool riscv_cpu_is_32bit(RISCVCPU *cpu);
>
> +RISCVException riscv_csrr(CPURISCVState *env, int csrno,
> +  target_ulong *ret_value);
>  RISCVException riscv_csrrw(CPURISCVState *env, int csrno,
> target_ulong *ret_value,
> target_ulong new_value, target_ulong write_mask);
> @@ -740,6 +742,8 @@ typedef RISCVException (*riscv_csr_op_fn)(CPURISCVState 
> *env, int csrno,
>target_ulong new_value,
>target_ulong write_mask);
>
> +RISCVException riscv_csrr_i128(CPURISCVState *env, int csrno,
> +   Int128 *ret_value);
>  RISCVException riscv_csrrw_i128(CPURISCVState *env, int csrno,
>  Int128 *ret_value,
>  Int128 new_value, Int128 write_mask);
> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> index 726096444f..aa765678b9 100644
> --- a/target/riscv/csr.c
> +++ b/target/riscv/csr.c
> @@ -4312,7 +4312,7 @@ static RISCVException rmw_seed(CPURISCVState *env, int 
> csrno,
>
>  static inline RISCVException riscv_csrrw_check(CPURISCVState *env,
> int csrno,
> -   bool write_mask)
> +   bool write)
>  {
>  /* check privileges and return RISCV_EXCP_ILLEGAL_INST if check fails */
>  bool read_only = get_field(csrno, 0xC00) == 3;
> @@ -4334,7 +4334,7 @@ static inline RISCVException 
> riscv_csrrw_check(CPURISCVState *env,
>  }
>
>  /* read / write check */
> -if (write_mask && read_only) {
> +if (write && read_only) {
>  return RISCV_EXCP_ILLEGAL_INST;
>  }
>
> @@ -4421,11 +4421,22 @@ static RISCVException riscv_csrrw_do64(CPURISCVState 
> *env, int csrno,
>  return RISCV_EXCP_NONE;
>  }
>
> +RISCVException riscv_csrr(CPURISCVState *env, int csrno,
> +   target_ulong *ret_value)
> +{
> +RISCVException ret = riscv_csrrw_check(env, csrno, false);
> +if (ret != RISCV_EXCP_NONE) {
> +return ret;
> +}
> +
> +return riscv_csrrw_do64(env, csrno, ret_value, 0, 0);
> +}
> +
>  RISCVException riscv_csrrw(CPURISCVState *env, int csrno,
> target_ulong *ret_value,
> target_ulong new_value, target_ulong write_mask)
>  {
> -RISCVException ret = riscv_csrrw_check(env, csrno, write_mask);
> +RISCVException ret = riscv_csrrw_check(env, csrno, true);
>  if (ret != RISCV_EXCP_NONE) {
>  return ret;
>  }
> @@ -4473,13 +4484,45 @@ static RISCVException riscv_csrrw_do128(CPURISCVState 
> *env, int csrno,
>  return RISCV_EXCP_NONE;
>  }
>
> +RISCVException riscv_csrr_i128(CPURISCVState *env, int csrno,
> +   Int128 *ret_value)
> +{
> +RISCVException ret;
> +
> +ret = riscv_csrrw_check(env, csrno, false);
> +if (ret != RISCV_EXCP_NONE) {
> +return ret;
> +}
> +
> +if (csr_ops[csrno].read128) {
> +return riscv_csrrw_do128(env, csrno, ret_value,
> + int128_zero(), int128_zero());
> +}
> +
> +/*
> + * Fall back to 64-bit version for now, if the 128-bit alternative isn't
> + * at all defined.
> + * Note, some CSRs don't need to extend to MXLEN (64 upper bits non
> + * significant), for those, this fallback is correctly handling the
> + * accesses
> + */
> +target_ulong old_value;
> +ret = riscv_csrrw_do64(env, csrno, _value,

Re: [RFC PATCH 16/16] hw/riscv: virt: Add WorldGuard support

2024-07-11 Thread Alistair Francis
On Wed, Jun 12, 2024 at 6:18 PM Jim Shu  wrote:
>
> * Add 'wg=on' option to enable RISC-V WorldGuard
> * Add wgChecker to protect several resources:
>   DRAM, FLASH, UART.
>
> Signed-off-by: Jim Shu 
> ---
>  docs/system/riscv/virt.rst |  10 +++
>  hw/riscv/Kconfig   |   1 +
>  hw/riscv/virt.c| 163 -
>  include/hw/riscv/virt.h|  17 +++-
>  4 files changed, 186 insertions(+), 5 deletions(-)
>
> diff --git a/docs/system/riscv/virt.rst b/docs/system/riscv/virt.rst
> index 9a06f95a34..2d2992dc34 100644
> --- a/docs/system/riscv/virt.rst
> +++ b/docs/system/riscv/virt.rst
> @@ -116,6 +116,16 @@ The following machine-specific options are supported:
>having AIA IMSIC (i.e. "aia=aplic-imsic" selected). When not specified,
>the default number of per-HART VS-level AIA IMSIC pages is 0.
>
> +- wg=[on|off]
> +
> +  When this option is "on", RISC-V WorldGuard will be enabled in the system
> +  to provide the isolation of multiple worlds. RISC-V HARTS will enable WG
> +  extensions to have WID in memory transaction. wgCheckers in front of RAMs
> +  and device MMIO will be enabled to provide the access control of resources
> +  if the transaction contains WID. When not specified, this option is assumed
> +  to be "off".
> +  This option is restricted to the TCG accelerator.

We need a lot more documentation here.

The WID of M-mode for example is set by an external environment. How
are users going to set that in QEMU?

Are the Smwg, Smwgd, and Sswg extensions enabled? Or is it hard coded
one world per hart?

We should make it clear to users how this is setup as the spec leaves
a lot of this up to implementations. We also don't expect users to
read the code or commit messages to figure it out.

Alistair

> +
>  Running Linux kernel
>  
>
> diff --git a/hw/riscv/Kconfig b/hw/riscv/Kconfig
> index a2030e3a6f..7804fdbb7a 100644
> --- a/hw/riscv/Kconfig
> +++ b/hw/riscv/Kconfig
> @@ -56,6 +56,7 @@ config RISCV_VIRT
>  select PLATFORM_BUS
>  select ACPI
>  select ACPI_PCI
> +select RISCV_WORLDGUARD
>
>  config SHAKTI_C
>  bool
> diff --git a/hw/riscv/virt.c b/hw/riscv/virt.c
> index 4fdb660525..eed49ebd02 100644
> --- a/hw/riscv/virt.c
> +++ b/hw/riscv/virt.c
> @@ -55,6 +55,7 @@
>  #include "hw/acpi/aml-build.h"
>  #include "qapi/qapi-visit-common.h"
>  #include "hw/virtio/virtio-iommu.h"
> +#include "hw/misc/riscv_worldguard.h"
>
>  /* KVM AIA only supports APLIC MSI. APLIC Wired is always emulated by QEMU. 
> */
>  static bool virt_use_kvm_aia(RISCVVirtState *s)
> @@ -76,6 +77,9 @@ static const MemMapEntry virt_memmap[] = {
>  [VIRT_ACLINT_SSWI] =  {  0x2F0,0x4000 },
>  [VIRT_PCIE_PIO] = {  0x300,   0x1 },
>  [VIRT_PLATFORM_BUS] = {  0x400, 0x200 },
> +[VIRT_WGC_DRAM] = {  0x600,0x1000 },
> +[VIRT_WGC_FLASH] ={  0x6001000,0x1000 },
> +[VIRT_WGC_UART] = {  0x6002000,0x1000 },
>  [VIRT_PLIC] = {  0xc00, VIRT_PLIC_SIZE(VIRT_CPUS_MAX * 2) },
>  [VIRT_APLIC_M] =  {  0xc00, APLIC_SIZE(VIRT_CPUS_MAX) },
>  [VIRT_APLIC_S] =  {  0xd00, APLIC_SIZE(VIRT_CPUS_MAX) },
> @@ -101,6 +105,38 @@ static MemMapEntry virt_high_pcie_memmap;
>
>  #define VIRT_FLASH_SECTOR_SIZE (256 * KiB)
>
> +/* wgChecker helpers */
> +typedef struct WGCInfo {
> +int memmap_idx;
> +uint32_t irq_num;
> +uint32_t slot_count;
> +
> +int num_of_child;
> +MemoryRegion *c_region[WGC_NUM_REGIONS];
> +uint64_t c_offset[WGC_NUM_REGIONS];
> +} WGCInfo;
> +
> +enum {
> +WGC_DRAM,
> +WGC_FLASH,
> +WGC_UART,
> +WGC_NUM,
> +};
> +
> +static WGCInfo virt_wgcinfo[] = {
> +[WGC_DRAM]  = { VIRT_WGC_DRAM, WGC_DRAM_IRQ, 16 },
> +[WGC_FLASH] = { VIRT_WGC_FLASH, WGC_FLASH_IRQ, 16 },
> +[WGC_UART]  = { VIRT_WGC_UART, WGC_UART_IRQ, 1 },
> +};
> +
> +static void wgc_append_child(WGCInfo *info, MemoryRegion *region,
> + uint64_t offset)
> +{
> +info->c_region[info->num_of_child] = region;
> +info->c_offset[info->num_of_child] = offset;
> +info->num_of_child += 1;
> +}
> +
>  static PFlashCFI01 *virt_flash_create1(RISCVVirtState *s,
> const char *name,
> const char *alias_prop_name)
> @@ -151,7 +187,8 @@ static void virt_flash_map1(PFlashCFI01 *flash,
>  }
>
>  static void virt_flash_map(RISCVVirtState *s,
> -   MemoryRegion *sysmem)
> +   MemoryRegion *sysmem,
> +   WGCInfo *info)
>  {
>  hwaddr flashsize = virt_memmap[VIRT_FLASH].size / 2;
>  hwaddr flashbase = virt_memmap[VIRT_FLASH].base;
> @@ -160,6 +197,15 @@ static void virt_flash_map(RISCVVirtState *s,
>  sysmem);
>  virt_flash_map1(s->flash[1], flashbase + flashsize, flashsize,
>  sysmem);
> 

Re: [RFC PATCH 06/16] target/riscv: Add hard-coded CPU state of WG extension

2024-07-11 Thread Alistair Francis
On Wed, Jun 12, 2024 at 6:17 PM Jim Shu  wrote:
>
> Add hard-coded state of WG extension. 'mwid' is the M-mode WID of CPU.
> 'mwidlist' is the list of allowed WID value of 'mlwid' CSR.
>
> These CPU states can be set by CPU option, or can be set by machine code
> via newly added APIs. If we want different WG configs of CPUs, we should
> set it by machine code.
>
> Signed-off-by: Jim Shu 
> ---
>  target/riscv/cpu.c|  2 ++
>  target/riscv/cpu.h|  2 ++
>  target/riscv/cpu_cfg.h|  2 ++
>  target/riscv/cpu_helper.c | 18 ++
>  4 files changed, 24 insertions(+)
>
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index d70eedf957..4e87fa4d5b 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -2291,6 +2291,8 @@ static Property riscv_cpu_properties[] = {
>   * it with -x and default to 'false'.
>   */
>  DEFINE_PROP_BOOL("x-misa-w", RISCVCPU, cfg.misa_w, false),
> +DEFINE_PROP_UINT32("mwid", RISCVCPU, cfg.mwid, UINT32_MAX),
> +DEFINE_PROP_UINT32("mwidlist", RISCVCPU, cfg.mwidlist, UINT32_MAX),

These should be "x-" as well.

Also same comment about functionality and properties as previous patch

Alistair

>  DEFINE_PROP_END_OF_LIST(),
>  };
>
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index 6fe0d712b4..2d3bfedbba 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -540,6 +540,8 @@ void riscv_cpu_set_aia_ireg_rmw_fn(CPURISCVState *env, 
> uint32_t priv,
> void *rmw_fn_arg);
>
>  RISCVException smstateen_acc_ok(CPURISCVState *env, int index, uint64_t bit);
> +void riscv_cpu_set_wg_mwid(CPURISCVState *env, uint32_t mwid);
> +void riscv_cpu_set_wg_mwidlist(CPURISCVState *env, uint32_t mwidlist);
>  #endif /* !CONFIG_USER_ONLY */
>
>  void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv);
> diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h
> index 23e779ae08..de9c134b15 100644
> --- a/target/riscv/cpu_cfg.h
> +++ b/target/riscv/cpu_cfg.h
> @@ -166,6 +166,8 @@ struct RISCVCPUConfig {
>  bool pmp;
>  bool debug;
>  bool misa_w;
> +uint32_t mwid;
> +uint32_t mwidlist;
>
>  bool short_isa_string;
>
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index 161df34626..ff20ab6ab8 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -149,6 +149,24 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, vaddr *pc,
>  *pflags = flags;
>  }
>
> +#ifndef CONFIG_USER_ONLY
> +void riscv_cpu_set_wg_mwid(CPURISCVState *env, uint32_t mwid)
> +{
> +CPUState *cs = env_cpu(env);
> +RISCVCPU *cpu = RISCV_CPU(cs);
> +
> +cpu->cfg.mwid = mwid;
> +}
> +
> +void riscv_cpu_set_wg_mwidlist(CPURISCVState *env, uint32_t mwidlist)
> +{
> +CPUState *cs = env_cpu(env);
> +RISCVCPU *cpu = RISCV_CPU(cs);
> +
> +cpu->cfg.mwidlist = mwidlist;
> +}
> +#endif /* CONFIG_USER_ONLY */
> +
>  void riscv_cpu_update_mask(CPURISCVState *env)
>  {
>  target_ulong mask = 0, base = 0;
> --
> 2.17.1
>
>



Re: [RFC PATCH 05/16] target/riscv: Add CPU options of WorldGuard CPU extension

2024-07-11 Thread Alistair Francis
On Wed, Jun 12, 2024 at 6:17 PM Jim Shu  wrote:
>
> We define CPU options for WG CSR support in RISC-V CPUs which
> can be set by machine/device emulation. The RISC-V CSR emulation
> will also check this feature for emulating WG CSRs.
>
> Signed-off-by: Jim Shu 
> ---
>  target/riscv/cpu.c |  8 
>  target/riscv/cpu_cfg.h |  3 +++
>  target/riscv/tcg/tcg-cpu.c | 11 +++
>  3 files changed, 22 insertions(+)
>
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index 69a08e8c2c..d70eedf957 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -204,6 +204,9 @@ const RISCVIsaExtData isa_edata_arr[] = {
>  ISA_EXT_DATA_ENTRY(xtheadmempair, PRIV_VERSION_1_11_0, 
> ext_xtheadmempair),
>  ISA_EXT_DATA_ENTRY(xtheadsync, PRIV_VERSION_1_11_0, ext_xtheadsync),
>  ISA_EXT_DATA_ENTRY(xventanacondops, PRIV_VERSION_1_12_0, 
> ext_XVentanaCondOps),
> +ISA_EXT_DATA_ENTRY(smwg, PRIV_VERSION_1_12_0, ext_smwg),
> +ISA_EXT_DATA_ENTRY(smwgd, PRIV_VERSION_1_12_0, ext_smwgd),
> +ISA_EXT_DATA_ENTRY(sswg, PRIV_VERSION_1_12_0, ext_sswg),
>
>  DEFINE_PROP_END_OF_LIST(),
>  };
> @@ -1595,6 +1598,11 @@ const RISCVCPUMultiExtConfig 
> riscv_cpu_experimental_exts[] = {
>  const RISCVCPUMultiExtConfig riscv_cpu_named_features[] = {
>  MULTI_EXT_CFG_BOOL("zic64b", ext_zic64b, true),
>
> +/* RISC-V WorldGuard v0.4 */
> +MULTI_EXT_CFG_BOOL("x-smwg", ext_smwg, false),
> +MULTI_EXT_CFG_BOOL("x-smwgd", ext_smwgd, false),
> +MULTI_EXT_CFG_BOOL("x-sswg", ext_sswg, false),

We want to add the functionality then expose the properties, as this
is user accessible and we want to maintain bistability.

I understand this doesn't break the build, but it's a bit strange to
allow users to enable something when at this point it doesn't yet work

Alistair

> +
>  DEFINE_PROP_END_OF_LIST(),
>  };
>
> diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h
> index e1e4f32698..23e779ae08 100644
> --- a/target/riscv/cpu_cfg.h
> +++ b/target/riscv/cpu_cfg.h
> @@ -120,6 +120,9 @@ struct RISCVCPUConfig {
>  bool ext_ssaia;
>  bool ext_sscofpmf;
>  bool ext_smepmp;
> +bool ext_smwg;
> +bool ext_smwgd;
> +bool ext_sswg;
>  bool rvv_ta_all_1s;
>  bool rvv_ma_all_1s;
>
> diff --git a/target/riscv/tcg/tcg-cpu.c b/target/riscv/tcg/tcg-cpu.c
> index 683f604d9f..dc86e6e1d5 100644
> --- a/target/riscv/tcg/tcg-cpu.c
> +++ b/target/riscv/tcg/tcg-cpu.c
> @@ -726,6 +726,17 @@ void riscv_cpu_validate_set_extensions(RISCVCPU *cpu, 
> Error **errp)
>  cpu->pmu_avail_ctrs = 0;
>  }
>
> +/* RISC-V WorldGuard */
> +if (cpu->cfg.ext_sswg && !cpu->cfg.ext_smwg) {
> +error_setg(errp, "Sswg extension requires Smwg extension");
> +return;
> +}
> +
> +if (cpu->cfg.ext_smwgd != cpu->cfg.ext_sswg) {
> +error_setg(errp, "Smwgd/Sswg extensions should be enabled together");
> +return;
> +}
> +
>  /*
>   * Disable isa extensions based on priv spec after we
>   * validated and set everything we need.
> --
> 2.17.1
>
>



Re: [RFC PATCH 04/16] hw/misc: riscv_worldguard: Add RISC-V WorldGuard global config

2024-07-11 Thread Alistair Francis
On Wed, Jun 12, 2024 at 6:18 PM Jim Shu  wrote:
>
> Add a device for RISCV WG global config, which contains the number of
> worlds, reset value, and trusted WID ... etc.
>
> This global config is used by both CPU WG extension and wgChecker devices.
>
> Signed-off-by: Jim Shu 
> ---
>  hw/misc/Kconfig|   3 +
>  hw/misc/meson.build|   1 +
>  hw/misc/riscv_worldguard.c | 183 +
>  include/hw/misc/riscv_worldguard.h |  55 +
>  4 files changed, 242 insertions(+)
>  create mode 100644 hw/misc/riscv_worldguard.c
>  create mode 100644 include/hw/misc/riscv_worldguard.h
>
> diff --git a/hw/misc/Kconfig b/hw/misc/Kconfig
> index 1e08785b83..08fc0f2b8c 100644
> --- a/hw/misc/Kconfig
> +++ b/hw/misc/Kconfig
> @@ -213,4 +213,7 @@ config IOSB
>  config XLNX_VERSAL_TRNG
>  bool
>
> +config RISCV_WORLDGUARD
> +bool

We should ensure this is enabled as well so that it is built by default

Alistair

> +
>  source macio/Kconfig
> diff --git a/hw/misc/meson.build b/hw/misc/meson.build
> index 86596a3888..a75668ff86 100644
> --- a/hw/misc/meson.build
> +++ b/hw/misc/meson.build
> @@ -34,6 +34,7 @@ system_ss.add(when: 'CONFIG_SIFIVE_E_PRCI', if_true: 
> files('sifive_e_prci.c'))
>  system_ss.add(when: 'CONFIG_SIFIVE_E_AON', if_true: files('sifive_e_aon.c'))
>  system_ss.add(when: 'CONFIG_SIFIVE_U_OTP', if_true: files('sifive_u_otp.c'))
>  system_ss.add(when: 'CONFIG_SIFIVE_U_PRCI', if_true: 
> files('sifive_u_prci.c'))
> +specific_ss.add(when: 'CONFIG_RISCV_WORLDGUARD', if_true: 
> files('riscv_worldguard.c'))
>
>  subdir('macio')
>
> diff --git a/hw/misc/riscv_worldguard.c b/hw/misc/riscv_worldguard.c
> new file mode 100644
> index 00..c839cc4e87
> --- /dev/null
> +++ b/hw/misc/riscv_worldguard.c
> @@ -0,0 +1,183 @@
> +/*
> + * RISC-V WorldGuard Device
> + *
> + * Copyright (c) 2022 SiFive, Inc.
> + *
> + * This provides WorldGuard global config.
> + *
> + * 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 .
> + */
> +
> +#include "qemu/osdep.h"
> +#include "qapi/error.h"
> +#include "qemu/log.h"
> +#include "exec/hwaddr.h"
> +#include "hw/registerfields.h"
> +#include "hw/sysbus.h"
> +#include "hw/hw.h"
> +#include "hw/qdev-properties.h"
> +#include "hw/misc/riscv_worldguard.h"
> +#include "hw/core/cpu.h"
> +#include "target/riscv/cpu.h"
> +#include "trace.h"
> +
> +/*
> + * WorldGuard global config:
> + * List the global setting of WG, like num-of-worlds. It is unique in the 
> machine.
> + * All CPUs with WG extension and wgChecker devices will use it.
> + */
> +struct RISCVWorldGuardState *worldguard_config = NULL;
> +
> +static Property riscv_worldguard_properties[] = {
> +DEFINE_PROP_UINT32("nworlds", RISCVWorldGuardState, nworlds, 0),
> +
> +/* Only Trusted WID could access wgCheckers if it is enabled. */
> +DEFINE_PROP_UINT32("trustedwid", RISCVWorldGuardState, trustedwid, 
> NO_TRUSTEDWID),
> +
> +/*
> + * WG reset value is bypass mode in HW. All WG permission checkings are
> + * pass by default, so SW could correctly run on the machine w/o any WG
> + * programming.
> + */
> +DEFINE_PROP_BOOL("hw-bypass", RISCVWorldGuardState, hw_bypass, false),
> +
> +/*
> + * TrustZone compatible mode:
> + * This mode is only supported in 2 worlds system. It converts WorldGuard
> + * WID to TZ NS signal on the bus so WG could be cooperated with
> + * TZ components. In QEMU, it converts WID to 'MemTxAttrs.secure' bit 
> used
> + * by TZ.
> + */
> +DEFINE_PROP_BOOL("tz-compat", RISCVWorldGuardState, tz_compat, false),
> +DEFINE_PROP_END_OF_LIST(),
> +};
> +
> +/* WID to MemTxAttrs converter */
> +static void wid_to_mem_attrs(MemTxAttrs *attrs, uint32_t wid)
> +{
> +g_assert(wid < worldguard_config->nworlds);
> +
> +attrs->unspecified = 0;
> +if (worldguard_config->tz_compat) {
> +attrs->secure = wid;
> +} else {
> +attrs->world_id = wid;
> +}
> +}
> +
> +/* MemTxAttrs to WID converter */
> +uint32_t mem_attrs_to_wid(MemTxAttrs attrs)
> +{
> +if (attrs.unspecified) {
> +if (worldguard_config->trustedwid != NO_TRUSTEDWID) {
> +return worldguard_config->trustedwid;
> +} else {
> +return worldguard_config->nworlds - 1;
> +}
> +}
> +
> +if (worldguard_config->tz_compat) {
> +return attrs.secure;
> +

Re: [RFC PATCH 03/16] exec: Add RISC-V WorldGuard WID to MemTxAttrs

2024-07-11 Thread Alistair Francis
On Wed, Jun 12, 2024 at 6:15 PM Jim Shu  wrote:
>
> RISC-V WorldGuard will add 5-bit world_id (WID) to the each memory
> transaction on the bus. The wgChecker in front of RAM or peripherals
> MMIO could do the access control based on the WID. It is similar to ARM
> TrustZone NS bit, but the WID is 5-bit.
>
> The common implementation of WID is AXI4 AxUSER signal.
>
> Signed-off-by: Jim Shu 
> ---
>  include/exec/memattrs.h | 5 +
>  1 file changed, 5 insertions(+)
>
> diff --git a/include/exec/memattrs.h b/include/exec/memattrs.h
> index 14cdd8d582..d00f3c5500 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;
> +
> +/*
> + * RISC-V WorldGuard: the 5-bit WID of memory access.
> + */
> +uint8_t world_id;

Everything else is using `unsigned int` so I think we should as well

Alistair

>  } MemTxAttrs;
>
>  /* Bus masters which don't specify any attributes will get this,
> --
> 2.17.1
>
>



Re: [PATCH v5 0/7] target/riscv: Expose RV32 cpu to RV64 QEMU

2024-07-11 Thread Alistair Francis
On Wed, Jul 10, 2024 at 12:27 PM LIU Zhiwei
 wrote:
>
> From: 甲一 
>
> This patch set aims to expose 32-bit RISC-V cpu to RV64 QEMU. Thus
> qemu-system-riscv64 can directly boot a RV32 Linux.
>
> This patch set has been tested with 6.9.0 Linux Image.
> And add an avocado test in tests/avocado.
>
> # make check-avocado 
> AVOCADO_TESTS=/home/jenkins/git/qemu/tests/avocado/boot_linux_console.py:BootLinuxConsole.test_riscv64_virt_rv32i
>   VENVPIP install -e /home/jenkins/git/qemu/python/
> /home/jenkins/git/qemu/build/pyvenv/bin/python3 -B 
> /home/jenkins/git/qemu/python/scripts/mkvenv.py ensuregroup  --online 
> /home/jenkins/git/qemu/pythondeps.toml avocado
> mkvenv: checking for avocado-framework(>=88.1, <93.0)
> mkvenv: checking for pycdlib>=1.11.0
> mkvenv: installing avocado-framework==88.1, pycdlib>=1.11.0
>   AVOCADO tests/avocado
> Fetching asset from 
> /home/jenkins/git/qemu/tests/avocado/boot_linux_console.py:BootLinuxConsole.test_riscv64_virt_rv32i
> Fetching asset from 
> /home/jenkins/git/qemu/tests/avocado/boot_linux_console.py:BootLinuxConsole.test_riscv64_virt_rv32i
> JOB ID : 8c2e1ff918d3111d078a52eba9956893afaf9e1d
> JOB LOG: 
> /home/jenkins/git/qemu/build/tests/results/job-2024-07-10T09.55-8c2e1ff/job.log
>  (1/1) 
> /home/jenkins/git/qemu/tests/avocado/boot_linux_console.py:BootLinuxConsole.test_riscv64_virt_rv32i:
>  PASS (17.50 s)
> RESULTS: PASS 1 | ERROR 0 | FAIL 0 | SKIP 0 | WARN 0 | INTERRUPT 0 | 
> CANCEL 0
> JOB TIME   : 29.50 s
>
> v5:
>   Rebase to master and add tags
>
> v4:
>   Drop UL completely in PATCH v3 2/7, 4/7, 5/7.
>   Avocado: Add "if=none" to "-drive" option in QEMU command line
>
> v3:
>   Rebase to the master branch
>
> v2:
>   Remove the line that was inadvertently left in PATCH v1 4/6.
>   Add an avocado test.
>
> v1:
>   https://mail.gnu.org/archive/html/qemu-riscv/2024-06/msg00501.html
>
> TANG Tiancheng (7):
>   target/riscv: Add fw_dynamic_info32 for booting RV32 OpenSBI
>   target/riscv: Adjust PMP size for no-MMU RV64 QEMU running RV32
>   target/riscv: Correct SXL return value for RV32 in RV64 QEMU
>   target/riscv: Detect sxl to set bit width for RV32 in RV64
>   target/riscv: Correct mcause/scause bit width for RV32 in RV64 QEMU
>   target/riscv: Enable RV32 CPU support in RV64 QEMU
>   tests/avocado: Add an avocado test for riscv64

Acked-by: Alistair Francis 

Alistair

>
>  configs/targets/riscv64-softmmu.mak |  2 +-
>  hw/riscv/boot.c | 35 +-
>  hw/riscv/sifive_u.c |  3 ++-
>  include/hw/riscv/boot.h |  4 ++-
>  include/hw/riscv/boot_opensbi.h | 29 ++
>  target/riscv/cpu.c  | 17 ++---
>  target/riscv/cpu.h  |  5 +++-
>  target/riscv/cpu_helper.c   | 25 +--
>  target/riscv/pmp.c  |  2 +-
>  tests/avocado/boot_linux_console.py | 38 +
>  10 files changed, 132 insertions(+), 28 deletions(-)
>
> --
> 2.25.1
>
>



Re: [PATCH v2 13/13] target/riscv: Simplify probing in vext_ldff

2024-07-09 Thread Alistair Francis
On Wed, Jul 10, 2024 at 1:30 PM Richard Henderson
 wrote:
>
> The current pairing of tlb_vaddr_to_host with extra is either
> inefficient (user-only, with page_check_range) or incorrect
> (system, with probe_pages).
>
> For proper non-fault behaviour, use probe_access_flags with
> its nonfault parameter set to true.
>
> Signed-off-by: Richard Henderson 

Acked-by: Alistair Francis 

Alistair

> ---
>  target/riscv/vector_helper.c | 34 ++
>  1 file changed, 18 insertions(+), 16 deletions(-)
>
> diff --git a/target/riscv/vector_helper.c b/target/riscv/vector_helper.c
> index 1b4d5a8e37..4d72eb74d3 100644
> --- a/target/riscv/vector_helper.c
> +++ b/target/riscv/vector_helper.c
> @@ -474,7 +474,6 @@ vext_ldff(void *vd, void *v0, target_ulong base,
>vext_ldst_elem_fn *ldst_elem,
>uint32_t log2_esz, uintptr_t ra)
>  {
> -void *host;
>  uint32_t i, k, vl = 0;
>  uint32_t nf = vext_nf(desc);
>  uint32_t vm = vext_vm(desc);
> @@ -493,27 +492,31 @@ vext_ldff(void *vd, void *v0, target_ulong base,
>  }
>  addr = adjust_addr(env, base + i * (nf << log2_esz));
>  if (i == 0) {
> +/* Allow fault on first element. */
>  probe_pages(env, addr, nf << log2_esz, ra, MMU_DATA_LOAD);
>  } else {
> -/* if it triggers an exception, no need to check watchpoint */
>  remain = nf << log2_esz;
>  while (remain > 0) {
> +void *host;
> +int flags;
> +
>  offset = -(addr | TARGET_PAGE_MASK);
> -host = tlb_vaddr_to_host(env, addr, MMU_DATA_LOAD, 
> mmu_index);
> -if (host) {
> -#ifdef CONFIG_USER_ONLY
> -if (!page_check_range(addr, offset, PAGE_READ)) {
> -vl = i;
> -goto ProbeSuccess;
> -}
> -#else
> -probe_pages(env, addr, offset, ra, MMU_DATA_LOAD);
> -#endif
> -} else {
> +
> +/* Probe nonfault on subsequent elements. */
> +flags = probe_access_flags(env, addr, offset, MMU_DATA_LOAD,
> +   mmu_index, true, , 0);
> +if (flags) {
> +/*
> + * Stop any flag bit set:
> + *   invalid (unmapped)
> + *   mmio (transaction failed)
> + *   watchpoint (debug)
> + * In all cases, handle as the first load next time.
> + */
>  vl = i;
> -goto ProbeSuccess;
> +break;
>  }
> -if (remain <=  offset) {
> +if (remain <= offset) {
>  break;
>  }
>  remain -= offset;
> @@ -521,7 +524,6 @@ vext_ldff(void *vd, void *v0, target_ulong base,
>  }
>  }
>  }
> -ProbeSuccess:
>  /* load bytes from guest memory */
>  if (vl != 0) {
>  env->vl = vl;
> --
> 2.43.0
>
>



Re: [PATCH v4 00/11] target/riscv: Support zimop/zcmop/zama16b/zabha

2024-07-09 Thread Alistair Francis
On Tue, Jul 9, 2024 at 9:41 PM LIU Zhiwei  wrote:
>
> I once used a wrong major opcode for zimop. It should use 0x73 as major 
> opcode.
> This was detected after I got a toolchain with zimop support. Before that, I 
> tested
> this implementation with hardwire code instruction instead of assemble code.
>
> This patch set has been queued to alistair/riscv-to-apply.next, but it is 
> still not
> merged by the master branch. I think we had better fix it before merging into 
> the
> master.
>
> v3->v4:
> 1. Fix zimop opcode and disassemble
>
> v2->v3:
> 1. Add review tags.
> 2. Reword the patch 10 in commit log
>
> v1->v2:
> 1. Fix the isa orders.
> 2. Make zimop/zcmop/zama16b/zabha depend on priviledged 1.13
> 3. Add review tags.
>
> The v2 patch set is here
> https://mail.gnu.org/archive/html/qemu-riscv/2024-06/msg00489.html
>
> The v1 patch set is here
> 1. zimop/zcmop
> https://mail.gnu.org/archive/html/qemu-riscv/2024-05/msg00207.html
> 2. zama16b
> https://mail.gnu.org/archive/html/qemu-riscv/2024-05/msg00212.html
> 3. zabha
> https://mail.gnu.org/archive/html/qemu-riscv/2024-05/msg00214.html
>
> LIU Zhiwei (11):
>   target/riscv: Add zimop extension
>   disas/riscv: Support zimop disassemble
>   target/riscv: Add zcmop extension
>   disas/riscv: Support zcmop disassemble
>   target/riscv: Support Zama16b extension
>   target/riscv: Move gen_amo before implement Zabha
>   target/riscv: Add AMO instructions for Zabha
>   target/riscv: Move gen_cmpxchg before adding amocas.[b|h]
>   target/riscv: Add amocas.[b|h] for Zabha
>   target/riscv: Expose zabha extension as a cpu property
>   disas/riscv: Support zabha disassemble

Thanks!

Applied to riscv-to-apply.next

Alistair

>
>  disas/riscv.c   | 181 
>  target/riscv/cpu.c  |   8 +
>  target/riscv/cpu_cfg.h  |   4 +
>  target/riscv/insn16.decode  |   1 +
>  target/riscv/insn32.decode  |  33 
>  target/riscv/insn_trans/trans_rva.c.inc |  51 ++
>  target/riscv/insn_trans/trans_rvd.c.inc |  14 +-
>  target/riscv/insn_trans/trans_rvf.c.inc |  14 +-
>  target/riscv/insn_trans/trans_rvi.c.inc |   6 +
>  target/riscv/insn_trans/trans_rvzabha.c.inc | 145 
>  target/riscv/insn_trans/trans_rvzacas.c.inc |  13 --
>  target/riscv/insn_trans/trans_rvzcmop.c.inc |  29 
>  target/riscv/insn_trans/trans_rvzimop.c.inc |  37 
>  target/riscv/tcg/tcg-cpu.c  |   5 +
>  target/riscv/translate.c|  38 
>  15 files changed, 529 insertions(+), 50 deletions(-)
>  create mode 100644 target/riscv/insn_trans/trans_rvzabha.c.inc
>  create mode 100644 target/riscv/insn_trans/trans_rvzcmop.c.inc
>  create mode 100644 target/riscv/insn_trans/trans_rvzimop.c.inc
>
> --
> 2.25.1
>
>



Re: [PATCH v4 5/7] target/riscv: Correct mcause/scause bit width for RV32 in RV64 QEMU

2024-07-09 Thread Alistair Francis
On Mon, Jul 8, 2024 at 11:21 PM LIU Zhiwei  wrote:
>
> From: TANG Tiancheng 
>
> Ensure mcause high bit is correctly set by using 32-bit width for RV32
> mode and 64-bit width for RV64 mode.
>
> Signed-off-by: TANG Tiancheng 
> Reviewed-by: Liu Zhiwei 

Reviewed-by: Alistair Francis 

Alistair

> ---
>  target/riscv/cpu_helper.c | 8 ++--
>  1 file changed, 6 insertions(+), 2 deletions(-)
>
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index 4f0ab90ac7..3eedb26cd9 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -1673,6 +1673,8 @@ void riscv_cpu_do_interrupt(CPUState *cs)
>  target_ulong tinst = 0;
>  target_ulong htval = 0;
>  target_ulong mtval2 = 0;
> +int sxlen = 0;
> +int mxlen = 0;
>
>  if (!async) {
>  /* set tval to badaddr for traps with address information */
> @@ -1799,7 +1801,8 @@ void riscv_cpu_do_interrupt(CPUState *cs)
>  s = set_field(s, MSTATUS_SPP, env->priv);
>  s = set_field(s, MSTATUS_SIE, 0);
>  env->mstatus = s;
> -env->scause = cause | ((target_ulong)async << (TARGET_LONG_BITS - 
> 1));
> +sxlen = 16 << riscv_cpu_sxl(env);
> +env->scause = cause | ((target_ulong)async << (sxlen - 1));
>  env->sepc = env->pc;
>  env->stval = tval;
>  env->htval = htval;
> @@ -1830,7 +1833,8 @@ void riscv_cpu_do_interrupt(CPUState *cs)
>  s = set_field(s, MSTATUS_MPP, env->priv);
>  s = set_field(s, MSTATUS_MIE, 0);
>  env->mstatus = s;
> -env->mcause = cause | ~(((target_ulong)-1) >> async);
> +mxlen = 16 << riscv_cpu_mxl(env);
> +env->mcause = cause | ((target_ulong)async << (mxlen - 1));
>  env->mepc = env->pc;
>  env->mtval = tval;
>  env->mtval2 = mtval2;
> --
> 2.43.0
>
>



Re: [PATCH v4 7/7] tests/avocado: Add an avocado test for riscv64

2024-07-09 Thread Alistair Francis
On Mon, Jul 8, 2024 at 11:22 PM LIU Zhiwei  wrote:
>
> From: TANG Tiancheng 
>
> To regularly test booting Linux with rv32 on QEMU RV64,
> we have added a test to boot_linux_console.py to retrieve
> cpuinfo and verify if it shows 'rv32' when using RV64 to
> boot rv32 CPUs.
>
> Signed-off-by: TANG Tiancheng 
> Reviewed-by: Liu Zhiwei 
> Acked-by: Alistair Francis 
> Reviewed-by: Alistair Francis 

Something is wrong here, it should only be an Ack

Alistair



Re: [PATCH 2/2] target/riscv: Add textra matching condition for the triggers

2024-07-09 Thread Alistair Francis
On Thu, Jul 4, 2024 at 2:03 PM Alvin Chang via  wrote:
>
> According to RISC-V Debug specification, the optional textra32 and
> textra64 trigger CSRs can be used to configure additional matching
> conditions for the triggers. For example, if the textra.MHSELECT field
> is set to 4 (mcontext), this trigger will only match or fire if the low
> bits of mcontext/hcontext equal textra.MHVALUE field.
>
> This commit adds the aforementioned matching condition as common trigger
> matching conditions. Currently, the only legal values of textra.MHSELECT
> are 0 (ignore) and 4 (mcontext). When textra.MHSELECT is 0, we pass the
> checking. When textra.MHSELECT is 4, we compare textra.MHVALUE with
> mcontext CSR. The remaining fields, such as textra.SBYTEMASK,
> textra.SVALUE, and textra.SSELECT, are hardwired to zero for now. Thus,
> we skip checking them here.
>
> Signed-off-by: Alvin Chang 

Reviewed-by: Alistair Francis 

Alistair

> ---
>  target/riscv/debug.c | 63 +++-
>  target/riscv/debug.h |  3 +++
>  2 files changed, 65 insertions(+), 1 deletion(-)
>
> diff --git a/target/riscv/debug.c b/target/riscv/debug.c
> index f7d8f5e320..58dd2f25ae 100644
> --- a/target/riscv/debug.c
> +++ b/target/riscv/debug.c
> @@ -367,11 +367,72 @@ static bool trigger_priv_match(CPURISCVState *env, 
> trigger_type_t type,
>  return false;
>  }
>
> +static bool trigger_textra_match(CPURISCVState *env, trigger_type_t type,
> + int trigger_index)
> +{
> +target_ulong textra = env->tdata3[trigger_index];
> +target_ulong mhvalue, mhselect;
> +
> +if (type < TRIGGER_TYPE_AD_MATCH || type > TRIGGER_TYPE_AD_MATCH6) {
> +/* textra checking is only applicable when type is 2, 3, 4, 5, or 6 
> */
> +return true;
> +}
> +
> +switch (riscv_cpu_mxl(env)) {
> +case MXL_RV32:
> +mhvalue  = get_field(textra, TEXTRA32_MHVALUE);
> +mhselect = get_field(textra, TEXTRA32_MHSELECT);
> +break;
> +case MXL_RV64:
> +case MXL_RV128:
> +mhvalue  = get_field(textra, TEXTRA64_MHVALUE);
> +mhselect = get_field(textra, TEXTRA64_MHSELECT);
> +break;
> +default:
> +g_assert_not_reached();
> +}
> +
> +/* Check mhvalue and mhselect. */
> +switch (mhselect) {
> +case MHSELECT_IGNORE:
> +break;
> +case MHSELECT_MCONTEXT:
> +/* Match or fire if the low bits of mcontext/hcontext equal mhvalue. 
> */
> +if (riscv_has_ext(env, RVH)) {
> +if (mhvalue != env->mcontext) {
> +return false;
> +}
> +} else {
> +switch (riscv_cpu_mxl(env)) {
> +case MXL_RV32:
> +if (mhvalue != (env->mcontext & MCONTEXT32)) {
> +return false;
> +}
> +break;
> +case MXL_RV64:
> +case MXL_RV128:
> +if (mhvalue != (env->mcontext & MCONTEXT64)) {
> +return false;
> +}
> +break;
> +default:
> +g_assert_not_reached();
> +}
> +}
> +break;
> +default:
> +break;
> +}
> +
> +return true;
> +}
> +
>  /* Common matching conditions for all types of the triggers. */
>  static bool trigger_common_match(CPURISCVState *env, trigger_type_t type,
>   int trigger_index)
>  {
> -return trigger_priv_match(env, type, trigger_index);
> +return trigger_priv_match(env, type, trigger_index) &&
> +   trigger_textra_match(env, type, trigger_index);
>  }
>
>  /* type 2 trigger */
> diff --git a/target/riscv/debug.h b/target/riscv/debug.h
> index c347863578..f76b8f944a 100644
> --- a/target/riscv/debug.h
> +++ b/target/riscv/debug.h
> @@ -131,6 +131,9 @@ enum {
>  #define ITRIGGER_VU   BIT(25)
>  #define ITRIGGER_VS   BIT(26)
>
> +#define MHSELECT_IGNORE   0
> +#define MHSELECT_MCONTEXT 4
> +
>  bool tdata_available(CPURISCVState *env, int tdata_index);
>
>  target_ulong tselect_csr_read(CPURISCVState *env);
> --
> 2.34.1
>
>



Re: [PATCH 1/2] target/riscv: Preliminary textra trigger CSR writting support

2024-07-09 Thread Alistair Francis
On Thu, Jul 4, 2024 at 2:03 PM Alvin Chang via  wrote:
>
> This commit allows program to write textra trigger CSR for type 2, 3, 6
> triggers. In this preliminary patch, the textra.MHVALUE and the
> textra.MHSELECT fields are allowed to be configured. Other fields, such
> as textra.SBYTEMASK, textra.SVALUE, and textra.SSELECT, are hardwired to
> zero for now.
>
> For textra.MHSELECT field, the only legal values are 0 (ignore) and 4
> (mcontext). Writing 1~3 into textra.MHSELECT will be changed to 0, and
> writing 5~7 into textra.MHSELECT will be changed to 4. This behavior is
> aligned to RISC-V SPIKE simulator.
>
> Signed-off-by: Alvin Chang 
> ---
>  target/riscv/cpu_bits.h | 10 +
>  target/riscv/debug.c| 81 ++---
>  2 files changed, 85 insertions(+), 6 deletions(-)
>
> diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
> index c257c5ed7d..0530b4f9f4 100644
> --- a/target/riscv/cpu_bits.h
> +++ b/target/riscv/cpu_bits.h
> @@ -906,6 +906,16 @@ typedef enum RISCVException {
>  #define JVT_BASE   (~0x3F)
>
>  /* Debug Sdtrig CSR masks */
> +#define TEXTRA32_MHVALUE   0xFC00
> +#define TEXTRA32_MHSELECT  0x0380
> +#define TEXTRA32_SBYTEMASK 0x000C
> +#define TEXTRA32_SVALUE0x0003FFFC
> +#define TEXTRA32_SSELECT   0x0003
> +#define TEXTRA64_MHVALUE   0xFFF8ULL
> +#define TEXTRA64_MHSELECT  0x0007ULL
> +#define TEXTRA64_SBYTEMASK 0x00F0ULL
> +#define TEXTRA64_SVALUE0x0003FFFCULL
> +#define TEXTRA64_SSELECT   0x0003ULL
>  #define MCONTEXT32 0x003F
>  #define MCONTEXT64 0x1FFFULL
>  #define MCONTEXT32_HCONTEXT0x007F
> diff --git a/target/riscv/debug.c b/target/riscv/debug.c
> index 0b5099ff9a..f7d8f5e320 100644
> --- a/target/riscv/debug.c
> +++ b/target/riscv/debug.c
> @@ -217,6 +217,69 @@ static inline void warn_always_zero_bit(target_ulong 
> val, target_ulong mask,
>  }
>  }
>
> +static target_ulong textra_validate(CPURISCVState *env, target_ulong tdata3)
> +{
> +target_ulong mhvalue, mhselect;
> +target_ulong mhselect_new;
> +target_ulong textra;
> +const uint32_t mhselect_no_rvh[8] = { 0, 0, 0, 0, 4, 4, 4, 4 };
> +
> +switch (riscv_cpu_mxl(env)) {
> +case MXL_RV32:
> +mhvalue  = get_field(tdata3, TEXTRA32_MHVALUE);
> +mhselect = get_field(tdata3, TEXTRA32_MHSELECT);
> +/* Validate unimplemented (always zero) bits */
> +warn_always_zero_bit(tdata3, (target_ulong)TEXTRA32_SBYTEMASK,
> + "sbytemask");
> +warn_always_zero_bit(tdata3, (target_ulong)TEXTRA32_SVALUE,
> + "svalue");
> +warn_always_zero_bit(tdata3, (target_ulong)TEXTRA32_SSELECT,
> + "sselect");
> +break;
> +case MXL_RV64:
> +case MXL_RV128:
> +mhvalue  = get_field(tdata3, TEXTRA64_MHVALUE);
> +mhselect = get_field(tdata3, TEXTRA64_MHSELECT);
> +/* Validate unimplemented (always zero) bits */
> +warn_always_zero_bit(tdata3, (target_ulong)TEXTRA64_SBYTEMASK,
> + "sbytemask");
> +warn_always_zero_bit(tdata3, (target_ulong)TEXTRA64_SVALUE,
> + "svalue");
> +warn_always_zero_bit(tdata3, (target_ulong)TEXTRA64_SSELECT,
> + "sselect");
> +break;
> +default:
> +g_assert_not_reached();
> +}
> +
> +/* Validate mhselect. */
> +mhselect_new = mhselect_no_rvh[mhselect];

I don't follow, we don't check if the H extension is supported.

The spec states: "mhselect and sselect may only support 0 (ignore)" so
it sounds like we either support non or all of them (but that isn't
clear).

Either way we should at least log that we don't support
mcontext_select and vmid_select if the Hypervisor extension is enabled

> +
> +/* Write legal values into textra */
> +textra = 0;
> +switch (riscv_cpu_mxl(env)) {
> +case MXL_RV32:
> +textra = set_field(textra, TEXTRA32_MHVALUE,  mhvalue);
> +textra = set_field(textra, TEXTRA32_MHSELECT, mhselect_new);
> +break;
> +case MXL_RV64:
> +case MXL_RV128:
> +textra = set_field(textra, TEXTRA64_MHVALUE,  mhvalue);
> +textra = set_field(textra, TEXTRA64_MHSELECT, mhselect_new);
> +break;
> +default:
> +g_assert_not_reached();
> +}
> +
> +if (textra != tdata3) {
> +qemu_log_mask(LOG_GUEST_ERROR,
> +  "different value 0x" TARGET_FMT_lx " write to 
> tdata3\n",
> +  textra);
> +}
> +
> +return textra;
> +}
> +
>  static void do_trigger_action(CPURISCVState *env, 

Re: [PATCH v2 6/9] tests/qtest/bios-tables-test.c: Remove the fall back path

2024-07-09 Thread Alistair Francis
On Mon, Jul 8, 2024 at 9:50 PM Sunil V L  wrote:
>
> The expected ACPI AML files are moved now under ${arch}/{machine} path.
> Hence, there is no need to search in old path which didn't have ${arch}.
> Remove the code which searches for the expected AML files under old path
> as well.
>
> Suggested-by: Igor Mammedov 
> Signed-off-by: Sunil V L 

Acked-by: Alistair Francis 

Alistair

> ---
>  tests/qtest/bios-tables-test.c | 14 --
>  1 file changed, 14 deletions(-)
>
> diff --git a/tests/qtest/bios-tables-test.c b/tests/qtest/bios-tables-test.c
> index f4c4704bab..498e0e35d9 100644
> --- a/tests/qtest/bios-tables-test.c
> +++ b/tests/qtest/bios-tables-test.c
> @@ -267,15 +267,6 @@ static void dump_aml_files(test_data *data, bool rebuild)
> data->arch, data->machine,
> sdt->aml, ext);
>
> -/*
> - * To keep test cases not failing before the DATA files are 
> moved to
> - * ${arch}/${machine} folder, add this check as well.
> - */
> -if (!g_file_test(aml_file, G_FILE_TEST_EXISTS)) {
> -aml_file = g_strdup_printf("%s/%s/%.4s%s", data_dir,
> -   data->machine, sdt->aml, ext);
> -}
> -
>  if (!g_file_test(aml_file, G_FILE_TEST_EXISTS) &&
>  sdt->aml_len == exp_sdt->aml_len &&
>  !memcmp(sdt->aml, exp_sdt->aml, sdt->aml_len)) {
> @@ -412,11 +403,6 @@ static GArray *load_expected_aml(test_data *data)
>  try_again:
>  aml_file = g_strdup_printf("%s/%s/%s/%.4s%s", data_dir, data->arch,
> data->machine, sdt->aml, ext);
> -if (!g_file_test(aml_file, G_FILE_TEST_EXISTS)) {
> -aml_file = g_strdup_printf("%s/%s/%.4s%s", data_dir, 
> data->machine,
> -   sdt->aml, ext);
> -}
> -
>  if (verbosity_level >= 2) {
>  fprintf(stderr, "Looking for expected file '%s'\n", aml_file);
>  }
> --
> 2.43.0
>
>



Re: [PATCH] target/riscv/kvm: update KVM regs to Linux 6.10-rc5

2024-07-09 Thread Alistair Francis
On Tue, Jul 9, 2024 at 6:55 PM Daniel Henrique Barboza
 wrote:
>
> Two new regs added: ztso and zacas.
>
> Signed-off-by: Daniel Henrique Barboza 

Thanks!

Applied to riscv-to-apply.next

Alistair

> ---
>  target/riscv/kvm/kvm-cpu.c | 2 ++
>  1 file changed, 2 insertions(+)
>
> diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c
> index 1047961fed..f6e3156b8d 100644
> --- a/target/riscv/kvm/kvm-cpu.c
> +++ b/target/riscv/kvm/kvm-cpu.c
> @@ -281,6 +281,7 @@ static KVMCPUConfig kvm_multi_ext_cfgs[] = {
>  KVM_EXT_CFG("zihintntl", ext_zihintntl, KVM_RISCV_ISA_EXT_ZIHINTNTL),
>  KVM_EXT_CFG("zihintpause", ext_zihintpause, 
> KVM_RISCV_ISA_EXT_ZIHINTPAUSE),
>  KVM_EXT_CFG("zihpm", ext_zihpm, KVM_RISCV_ISA_EXT_ZIHPM),
> +KVM_EXT_CFG("zacas", ext_zacas, KVM_RISCV_ISA_EXT_ZACAS),
>  KVM_EXT_CFG("zfa", ext_zfa, KVM_RISCV_ISA_EXT_ZFA),
>  KVM_EXT_CFG("zfh", ext_zfh, KVM_RISCV_ISA_EXT_ZFH),
>  KVM_EXT_CFG("zfhmin", ext_zfhmin, KVM_RISCV_ISA_EXT_ZFHMIN),
> @@ -298,6 +299,7 @@ static KVMCPUConfig kvm_multi_ext_cfgs[] = {
>  KVM_EXT_CFG("zksed", ext_zksed, KVM_RISCV_ISA_EXT_ZKSED),
>  KVM_EXT_CFG("zksh", ext_zksh, KVM_RISCV_ISA_EXT_ZKSH),
>  KVM_EXT_CFG("zkt", ext_zkt, KVM_RISCV_ISA_EXT_ZKT),
> +KVM_EXT_CFG("ztso", ext_ztso, KVM_RISCV_ISA_EXT_ZTSO),
>  KVM_EXT_CFG("zvbb", ext_zvbb, KVM_RISCV_ISA_EXT_ZVBB),
>  KVM_EXT_CFG("zvbc", ext_zvbc, KVM_RISCV_ISA_EXT_ZVBC),
>  KVM_EXT_CFG("zvfh", ext_zvfh, KVM_RISCV_ISA_EXT_ZVFH),
> --
> 2.45.2
>
>



Re: [PATCH] target/riscv/kvm: update KVM regs to Linux 6.10-rc5

2024-07-09 Thread Alistair Francis
On Tue, Jul 9, 2024 at 6:55 PM Daniel Henrique Barboza
 wrote:
>
> Two new regs added: ztso and zacas.
>
> Signed-off-by: Daniel Henrique Barboza 

Reviewed-by: Alistair Francis 

Alistair

> ---
>  target/riscv/kvm/kvm-cpu.c | 2 ++
>  1 file changed, 2 insertions(+)
>
> diff --git a/target/riscv/kvm/kvm-cpu.c b/target/riscv/kvm/kvm-cpu.c
> index 1047961fed..f6e3156b8d 100644
> --- a/target/riscv/kvm/kvm-cpu.c
> +++ b/target/riscv/kvm/kvm-cpu.c
> @@ -281,6 +281,7 @@ static KVMCPUConfig kvm_multi_ext_cfgs[] = {
>  KVM_EXT_CFG("zihintntl", ext_zihintntl, KVM_RISCV_ISA_EXT_ZIHINTNTL),
>  KVM_EXT_CFG("zihintpause", ext_zihintpause, 
> KVM_RISCV_ISA_EXT_ZIHINTPAUSE),
>  KVM_EXT_CFG("zihpm", ext_zihpm, KVM_RISCV_ISA_EXT_ZIHPM),
> +KVM_EXT_CFG("zacas", ext_zacas, KVM_RISCV_ISA_EXT_ZACAS),
>  KVM_EXT_CFG("zfa", ext_zfa, KVM_RISCV_ISA_EXT_ZFA),
>  KVM_EXT_CFG("zfh", ext_zfh, KVM_RISCV_ISA_EXT_ZFH),
>  KVM_EXT_CFG("zfhmin", ext_zfhmin, KVM_RISCV_ISA_EXT_ZFHMIN),
> @@ -298,6 +299,7 @@ static KVMCPUConfig kvm_multi_ext_cfgs[] = {
>  KVM_EXT_CFG("zksed", ext_zksed, KVM_RISCV_ISA_EXT_ZKSED),
>  KVM_EXT_CFG("zksh", ext_zksh, KVM_RISCV_ISA_EXT_ZKSH),
>  KVM_EXT_CFG("zkt", ext_zkt, KVM_RISCV_ISA_EXT_ZKT),
> +KVM_EXT_CFG("ztso", ext_ztso, KVM_RISCV_ISA_EXT_ZTSO),
>  KVM_EXT_CFG("zvbb", ext_zvbb, KVM_RISCV_ISA_EXT_ZVBB),
>  KVM_EXT_CFG("zvbc", ext_zvbc, KVM_RISCV_ISA_EXT_ZVBC),
>  KVM_EXT_CFG("zvfh", ext_zvfh, KVM_RISCV_ISA_EXT_ZVFH),
> --
> 2.45.2
>
>



Re: [PATCH v7 2/2] hw/riscv/virt: Add IOPMP support

2024-07-07 Thread Alistair Francis
On Wed, Jun 26, 2024 at 3:53 PM Ethan Chen  wrote:
>
> On Wed, Jun 26, 2024 at 11:22:46AM +1000, Alistair Francis wrote:
> >
> > On Mon, Jun 24, 2024 at 11:47 AM Ethan Chen  wrote:
> > >
> > > Hi Alistair,
> > >
> > > IOPMP can applies all device. In this patch series, PCI devices on the 
> > > bridge
> > > can connect to IOPMP by pci_setup_iommu(), but other devices need change 
> > > their
> > > memory access address space from system memory to IOPMP by themself.
> >
> > We should be really clear about that then. The documentation and the
> > flag `iopmp=[on|off]` implies that either the IOPMP is on or off.
> >
> > For example, what happens in the future if we extend support to apply
> > to all devices? That will be a breaking change for anyone currently
> > using `iopmp=on`.
> >
> > Maybe we should have use something like `iopmp=[pci|off]` instead, and
> > then be really clear in the docs what is and isn't going through the
> > IOPMP.
> >
> > Alistair
>
> Hi Alistair,
>
> According to Zhiwei's suggestion in this patch series, we will remove
> iopmp_setup_pci because it will be exclusive with IOMMU integration.
>
> We are looking for an interface to make device memory access to be
> checked by IOPMP. After iopmp_setup_pci is removed, all devices need
> to change memory access target to iommu memory region in IOPMP
> themselves in current method. Therefore, by default, all devices won't
> go through the IOPMP even if iopmp=on.
>
> Another method is to replace the memory region of protected device
> in the system memory by iommu memory region in IOPMP (similar to
> MPC in arm/mps2-tz) when iopmp=on. With this method, all devices are
> going through the IOPMP by default when iopmp=on.
>
> Which method is more suitable for the RISC-V virt machine?

Sorry for the delay here, I missed this question.

I think if a user specifies `iopmp=on` we should run everything
through the IOPMP. If we don't we need to be really clear about what
does/does not go through the IOPMP.

It's unfortunately a little clunky, which isn't ideal, but I feel it's
better to properly support the IOPMP in this case. Maybe this is a
good reason for a "server" platform...

Alistair

>
> Thanks,
> Ethan
>
> >
> > >
> > > Thanks,
> > > Ethan
> > >
> > > On Fri, Jun 21, 2024 at 03:54:15PM +1000, Alistair Francis wrote:
> > > > On Wed, Jun 12, 2024 at 1:25 PM Ethan Chen via  
> > > > wrote:
> > > > >
> > > > > If a requestor device is connected to the IOPMP device, its memory 
> > > > > access will
> > > > > be checked by the IOPMP rule.
> > > > >
> > > > > - Add 'iopmp=on' option to add an iopmp device and make the Generic 
> > > > > PCI Express
> > > > >   Bridge connect to IOPMP.
> > > >
> > > > I have only had a chance to have a quick look at this series and the 
> > > > spec.
> > > >
> > > > But the IOPMP spec applies to all devices right, but this series seems
> > > > to only work with PCI. Am I missing something?
> > > >
> > > > Alistair
> > > >
> > > > >
> > > > > Signed-off-by: Ethan Chen 
> > > > > ---
> > > > >  docs/system/riscv/virt.rst |  6 
> > > > >  hw/riscv/Kconfig   |  1 +
> > > > >  hw/riscv/virt.c| 57 
> > > > > --
> > > > >  include/hw/riscv/virt.h|  5 +++-
> > > > >  4 files changed, 66 insertions(+), 3 deletions(-)
> > > > >
> > > > > diff --git a/docs/system/riscv/virt.rst b/docs/system/riscv/virt.rst
> > > > > index 9a06f95a34..3b2576f905 100644
> > > > > --- a/docs/system/riscv/virt.rst
> > > > > +++ b/docs/system/riscv/virt.rst
> > > > > @@ -116,6 +116,12 @@ The following machine-specific options are 
> > > > > supported:
> > > > >having AIA IMSIC (i.e. "aia=aplic-imsic" selected). When not 
> > > > > specified,
> > > > >the default number of per-HART VS-level AIA IMSIC pages is 0.
> > > > >
> > > > > +- iopmp=[on|off]
> > > > > +
> > > > > +  When this option is "on", an IOPMP device is added to machine. It 
> > > > > checks dma
> > > > > +  operations from the generic PCIe host bridge. This option is 
> > > >

Re: [PATCH] target/riscv: Fix the check with vector register multiples of LMUL

2024-07-07 Thread Alistair Francis
On Fri, Jun 28, 2024 at 7:46 PM Zhiwei Jiang  wrote:
>
> In the original extract32(val, 0, lmul) logic, when lmul is 2 and val is v10 
> or v12,
> there is an issue with this check condition. I think a simple mod operation 
> is sufficient.

Overall looks ok. Do you mind updating the commit message to describe
what exactly this fixes (as in what issue you had) and why this fixes
it

Alistair

>
> Signed-off-by: Zhiwei Jiang 
> ---
>  target/riscv/insn_trans/trans_rvv.c.inc | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/target/riscv/insn_trans/trans_rvv.c.inc 
> b/target/riscv/insn_trans/trans_rvv.c.inc
> index 3a3896ba06..e89b0f2b1e 100644
> --- a/target/riscv/insn_trans/trans_rvv.c.inc
> +++ b/target/riscv/insn_trans/trans_rvv.c.inc
> @@ -118,7 +118,7 @@ static bool require_nf(int vd, int nf, int lmul)
>   */
>  static bool require_align(const int8_t val, const int8_t lmul)
>  {
> -return lmul <= 0 || extract32(val, 0, lmul) == 0;
> +return lmul <= 0 || val % lmul == 0;
>  }
>
>  /*
> --
> 2.17.1
>
>



Re: [PATCH v4] target/riscv: raise an exception when CSRRS/CSRRC writes a read-only CSR

2024-07-07 Thread Alistair Francis
On Tue, Jun 4, 2024 at 7:15 PM Yu-Ming Chang via  wrote:
>
> Both CSRRS and CSRRC always read the addressed CSR and cause any read side
> effects regardless of rs1 and rd fields. Note that if rs1 specifies a register
> holding a zero value other than x0, the instruction will still attempt to 
> write
> the unmodified value back to the CSR and will cause any attendant side 
> effects.
>
> So if CSRRS or CSRRC tries to write a read-only CSR with rs1 which specifies
> a register holding a zero value, an illegal instruction exception should be
> raised.
>
> Signed-off-by: Yu-Ming Chang 
> Signed-off-by: Alvin Chang 

Thanks!

Applied to riscv-to-apply.next

Alistair

> ---
> Hi Alistair,
> This fixed the issue of riscv_csrrw_debug().
>
> Best regards,
> Yuming
>
>  target/riscv/cpu.h   |  4 +++
>  target/riscv/csr.c   | 57 
>  target/riscv/op_helper.c |  6 ++---
>  3 files changed, 58 insertions(+), 9 deletions(-)
>
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index 2d0c02c35b..72921bafc0 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -708,6 +708,8 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, vaddr *pc,
>  void riscv_cpu_update_mask(CPURISCVState *env);
>  bool riscv_cpu_is_32bit(RISCVCPU *cpu);
>
> +RISCVException riscv_csrr(CPURISCVState *env, int csrno,
> +  target_ulong *ret_value);
>  RISCVException riscv_csrrw(CPURISCVState *env, int csrno,
> target_ulong *ret_value,
> target_ulong new_value, target_ulong write_mask);
> @@ -740,6 +742,8 @@ typedef RISCVException (*riscv_csr_op_fn)(CPURISCVState 
> *env, int csrno,
>target_ulong new_value,
>target_ulong write_mask);
>
> +RISCVException riscv_csrr_i128(CPURISCVState *env, int csrno,
> +   Int128 *ret_value);
>  RISCVException riscv_csrrw_i128(CPURISCVState *env, int csrno,
>  Int128 *ret_value,
>  Int128 new_value, Int128 write_mask);
> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> index 726096444f..aa765678b9 100644
> --- a/target/riscv/csr.c
> +++ b/target/riscv/csr.c
> @@ -4312,7 +4312,7 @@ static RISCVException rmw_seed(CPURISCVState *env, int 
> csrno,
>
>  static inline RISCVException riscv_csrrw_check(CPURISCVState *env,
> int csrno,
> -   bool write_mask)
> +   bool write)
>  {
>  /* check privileges and return RISCV_EXCP_ILLEGAL_INST if check fails */
>  bool read_only = get_field(csrno, 0xC00) == 3;
> @@ -4334,7 +4334,7 @@ static inline RISCVException 
> riscv_csrrw_check(CPURISCVState *env,
>  }
>
>  /* read / write check */
> -if (write_mask && read_only) {
> +if (write && read_only) {
>  return RISCV_EXCP_ILLEGAL_INST;
>  }
>
> @@ -4421,11 +4421,22 @@ static RISCVException riscv_csrrw_do64(CPURISCVState 
> *env, int csrno,
>  return RISCV_EXCP_NONE;
>  }
>
> +RISCVException riscv_csrr(CPURISCVState *env, int csrno,
> +   target_ulong *ret_value)
> +{
> +RISCVException ret = riscv_csrrw_check(env, csrno, false);
> +if (ret != RISCV_EXCP_NONE) {
> +return ret;
> +}
> +
> +return riscv_csrrw_do64(env, csrno, ret_value, 0, 0);
> +}
> +
>  RISCVException riscv_csrrw(CPURISCVState *env, int csrno,
> target_ulong *ret_value,
> target_ulong new_value, target_ulong write_mask)
>  {
> -RISCVException ret = riscv_csrrw_check(env, csrno, write_mask);
> +RISCVException ret = riscv_csrrw_check(env, csrno, true);
>  if (ret != RISCV_EXCP_NONE) {
>  return ret;
>  }
> @@ -4473,13 +4484,45 @@ static RISCVException riscv_csrrw_do128(CPURISCVState 
> *env, int csrno,
>  return RISCV_EXCP_NONE;
>  }
>
> +RISCVException riscv_csrr_i128(CPURISCVState *env, int csrno,
> +   Int128 *ret_value)
> +{
> +RISCVException ret;
> +
> +ret = riscv_csrrw_check(env, csrno, false);
> +if (ret != RISCV_EXCP_NONE) {
> +return ret;
> +}
> +
> +if (csr_ops[csrno].read128) {
> +return riscv_csrrw_do128(env, csrno, ret_value,
> + int128_zero(), int128_zero());
> +}
> +
> +/*
> + * Fall back to 64-bit version for now, if the 128-bit alternative isn't
> + * at all defined.
> + * Note, some CSRs don't need to extend to MXLEN (64 upper bits non
> + * significant), for those, this fallback is correctly handling the
> + * accesses
> + */
> +target_ulong old_value;
> +ret = riscv_csrrw_do64(env, csrno, _value,
> +   (target_ulong)0,
> +   (target_ulong)0);
> 

Re: [PATCH v4] target/riscv: raise an exception when CSRRS/CSRRC writes a read-only CSR

2024-07-07 Thread Alistair Francis
On Tue, Jun 4, 2024 at 7:15 PM Yu-Ming Chang via  wrote:
>
> Both CSRRS and CSRRC always read the addressed CSR and cause any read side
> effects regardless of rs1 and rd fields. Note that if rs1 specifies a register
> holding a zero value other than x0, the instruction will still attempt to 
> write
> the unmodified value back to the CSR and will cause any attendant side 
> effects.
>
> So if CSRRS or CSRRC tries to write a read-only CSR with rs1 which specifies
> a register holding a zero value, an illegal instruction exception should be
> raised.
>
> Signed-off-by: Yu-Ming Chang 
> Signed-off-by: Alvin Chang 

Reviewed-by: Alistair Francis 

Alistair

> ---
> Hi Alistair,
> This fixed the issue of riscv_csrrw_debug().
>
> Best regards,
> Yuming
>
>  target/riscv/cpu.h   |  4 +++
>  target/riscv/csr.c   | 57 
>  target/riscv/op_helper.c |  6 ++---
>  3 files changed, 58 insertions(+), 9 deletions(-)
>
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index 2d0c02c35b..72921bafc0 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -708,6 +708,8 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, vaddr *pc,
>  void riscv_cpu_update_mask(CPURISCVState *env);
>  bool riscv_cpu_is_32bit(RISCVCPU *cpu);
>
> +RISCVException riscv_csrr(CPURISCVState *env, int csrno,
> +  target_ulong *ret_value);
>  RISCVException riscv_csrrw(CPURISCVState *env, int csrno,
> target_ulong *ret_value,
> target_ulong new_value, target_ulong write_mask);
> @@ -740,6 +742,8 @@ typedef RISCVException (*riscv_csr_op_fn)(CPURISCVState 
> *env, int csrno,
>target_ulong new_value,
>target_ulong write_mask);
>
> +RISCVException riscv_csrr_i128(CPURISCVState *env, int csrno,
> +   Int128 *ret_value);
>  RISCVException riscv_csrrw_i128(CPURISCVState *env, int csrno,
>  Int128 *ret_value,
>  Int128 new_value, Int128 write_mask);
> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> index 726096444f..aa765678b9 100644
> --- a/target/riscv/csr.c
> +++ b/target/riscv/csr.c
> @@ -4312,7 +4312,7 @@ static RISCVException rmw_seed(CPURISCVState *env, int 
> csrno,
>
>  static inline RISCVException riscv_csrrw_check(CPURISCVState *env,
> int csrno,
> -   bool write_mask)
> +   bool write)
>  {
>  /* check privileges and return RISCV_EXCP_ILLEGAL_INST if check fails */
>  bool read_only = get_field(csrno, 0xC00) == 3;
> @@ -4334,7 +4334,7 @@ static inline RISCVException 
> riscv_csrrw_check(CPURISCVState *env,
>  }
>
>  /* read / write check */
> -if (write_mask && read_only) {
> +if (write && read_only) {
>  return RISCV_EXCP_ILLEGAL_INST;
>  }
>
> @@ -4421,11 +4421,22 @@ static RISCVException riscv_csrrw_do64(CPURISCVState 
> *env, int csrno,
>  return RISCV_EXCP_NONE;
>  }
>
> +RISCVException riscv_csrr(CPURISCVState *env, int csrno,
> +   target_ulong *ret_value)
> +{
> +RISCVException ret = riscv_csrrw_check(env, csrno, false);
> +if (ret != RISCV_EXCP_NONE) {
> +return ret;
> +}
> +
> +return riscv_csrrw_do64(env, csrno, ret_value, 0, 0);
> +}
> +
>  RISCVException riscv_csrrw(CPURISCVState *env, int csrno,
> target_ulong *ret_value,
> target_ulong new_value, target_ulong write_mask)
>  {
> -RISCVException ret = riscv_csrrw_check(env, csrno, write_mask);
> +RISCVException ret = riscv_csrrw_check(env, csrno, true);
>  if (ret != RISCV_EXCP_NONE) {
>  return ret;
>  }
> @@ -4473,13 +4484,45 @@ static RISCVException riscv_csrrw_do128(CPURISCVState 
> *env, int csrno,
>  return RISCV_EXCP_NONE;
>  }
>
> +RISCVException riscv_csrr_i128(CPURISCVState *env, int csrno,
> +   Int128 *ret_value)
> +{
> +RISCVException ret;
> +
> +ret = riscv_csrrw_check(env, csrno, false);
> +if (ret != RISCV_EXCP_NONE) {
> +return ret;
> +}
> +
> +if (csr_ops[csrno].read128) {
> +return riscv_csrrw_do128(env, csrno, ret_value,
> + int128_zero(), int128_zero());
> +}
> +
> +/*
> + * Fall back to 64-bit version for now, if the 128-bit alternative isn't
>

Re: [PATCH qemu] target/riscv: Add Zilsd and Zcmlsd extension support

2024-07-07 Thread Alistair Francis
On Wed, Jul 3, 2024 at 1:29 PM ~liuxu  wrote:
>
> From: lxx <1733205...@qq.com>
>
> This patch adds support for the Zilsd and Zcmlsd extension,
> which is documented at 
> https://github.com/riscv/riscv-zilsd/releases/tag/v0.9.0
>
> Co-developed-by: SUN Dongya 
> Co-developed-by: LIU Xu 
> Co-developed-by: ZHAO Fujin 
> ---
>  target/riscv/cpu.c |  4 +
>  target/riscv/cpu_cfg.h |  2 +
>  target/riscv/insn16.decode |  8 ++
>  target/riscv/insn32.decode | 12 ++-
>  target/riscv/insn_trans/trans_zcmlsd.c.inc | 98 ++
>  target/riscv/insn_trans/trans_zilsd.c.inc  | 97 +
>  target/riscv/tcg/tcg-cpu.c | 13 +++
>  target/riscv/translate.c   |  2 +
>  8 files changed, 234 insertions(+), 2 deletions(-)
>  create mode 100644 target/riscv/insn_trans/trans_zcmlsd.c.inc
>  create mode 100644 target/riscv/insn_trans/trans_zilsd.c.inc
>
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index 36e3e5fdaf..71274e36f8 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -113,6 +113,7 @@ const RISCVIsaExtData isa_edata_arr[] = {
>  ISA_EXT_DATA_ENTRY(zihintntl, PRIV_VERSION_1_10_0, ext_zihintntl),
>  ISA_EXT_DATA_ENTRY(zihintpause, PRIV_VERSION_1_10_0, ext_zihintpause),
>  ISA_EXT_DATA_ENTRY(zihpm, PRIV_VERSION_1_12_0, ext_zihpm),
> +ISA_EXT_DATA_ENTRY(zilsd, PRIV_VERSION_1_12_0, ext_zilsd),
>  ISA_EXT_DATA_ENTRY(zmmul, PRIV_VERSION_1_12_0, ext_zmmul),
>  ISA_EXT_DATA_ENTRY(za64rs, PRIV_VERSION_1_12_0, has_priv_1_11),
>  ISA_EXT_DATA_ENTRY(zaamo, PRIV_VERSION_1_12_0, ext_zaamo),
> @@ -132,6 +133,7 @@ const RISCVIsaExtData isa_edata_arr[] = {
>  ISA_EXT_DATA_ENTRY(zce, PRIV_VERSION_1_12_0, ext_zce),
>  ISA_EXT_DATA_ENTRY(zcmp, PRIV_VERSION_1_12_0, ext_zcmp),
>  ISA_EXT_DATA_ENTRY(zcmt, PRIV_VERSION_1_12_0, ext_zcmt),
> +ISA_EXT_DATA_ENTRY(zcmlsd, PRIV_VERSION_1_12_0, ext_zcmlsd),
>  ISA_EXT_DATA_ENTRY(zba, PRIV_VERSION_1_12_0, ext_zba),
>  ISA_EXT_DATA_ENTRY(zbb, PRIV_VERSION_1_12_0, ext_zbb),
>  ISA_EXT_DATA_ENTRY(zbc, PRIV_VERSION_1_12_0, ext_zbc),
> @@ -1492,6 +1494,7 @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
>
>  MULTI_EXT_CFG_BOOL("zicntr", ext_zicntr, true),
>  MULTI_EXT_CFG_BOOL("zihpm", ext_zihpm, true),
> +MULTI_EXT_CFG_BOOL("zilsd", ext_zilsd, false),
>
>  MULTI_EXT_CFG_BOOL("zba", ext_zba, true),
>  MULTI_EXT_CFG_BOOL("zbb", ext_zbb, true),
> @@ -1531,6 +1534,7 @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
>  MULTI_EXT_CFG_BOOL("zcmp", ext_zcmp, false),
>  MULTI_EXT_CFG_BOOL("zcmt", ext_zcmt, false),
>  MULTI_EXT_CFG_BOOL("zicond", ext_zicond, false),
> +MULTI_EXT_CFG_BOOL("zcmlsd", ext_zcmlsd, false),
>
>  /* Vector cryptography extensions */
>  MULTI_EXT_CFG_BOOL("zvbb", ext_zvbb, false),
> diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h
> index cb750154bd..54e93897ee 100644
> --- a/target/riscv/cpu_cfg.h
> +++ b/target/riscv/cpu_cfg.h
> @@ -51,6 +51,7 @@ struct RISCVCPUConfig {
>  bool ext_zcf;
>  bool ext_zcmp;
>  bool ext_zcmt;
> +bool ext_zcmlsd;
>  bool ext_zk;
>  bool ext_zkn;
>  bool ext_zknd;
> @@ -71,6 +72,7 @@ struct RISCVCPUConfig {
>  bool ext_zihintntl;
>  bool ext_zihintpause;
>  bool ext_zihpm;
> +bool ext_zilsd;
>  bool ext_ztso;
>  bool ext_smstateen;
>  bool ext_sstc;
> diff --git a/target/riscv/insn16.decode b/target/riscv/insn16.decode
> index b96c534e73..5014caa128 100644
> --- a/target/riscv/insn16.decode
> +++ b/target/riscv/insn16.decode
> @@ -130,10 +130,14 @@ sw110  ... ... .. ... 00 @cs_w
>  {
>ld  011  ... ... .. ... 00 @cl_d
>c_flw   011  ... ... .. ... 00 @cl_w
> +  # *** Zcmlsd Extension ***
> +  zcmlsd_ld   011  ... ... .. ... 00 @cl_d
>  }
>  {
>sd  111  ... ... .. ... 00 @cs_d
>c_fsw   111  ... ... .. ... 00 @cs_w
> +  # *** Zcmlsd Extension ***
> +  zcmlsd_sd   111  ... ... .. ... 00 @cs_d
>  }
>
>  # *** RV32/64C Standard Extension (Quadrant 1) ***
> @@ -207,10 +211,14 @@ sw110 .  .  . 10 @c_swsp
>c64_illegal 011 -  0  - 10 # c.ldsp, RES rd=0
>ld  011 .  .  . 10 @c_ldsp
>c_flw   011 .  .  . 10 @c_lwsp
> +  # *** Zcmlsd Extension ***
> +  zcmlsd_ldsp 011 .  .  . 10 @c_ldsp
>  }
>  {
>sd  111 .  .  . 10 @c_sdsp
>c_fsw   111 .  .  . 10 @c_swsp
> +  # *** Zcmlsd Extension ***
> +  zcmlsd_sdsp 111 .  .  . 10 @c_sdsp
>  }
>
>  # *** RV64 and RV32 Zcb Extension ***
> diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode
> index f22df04cfd..f6f4b7950b 100644
> --- a/target/riscv/insn32.decode
> +++ b/target/riscv/insn32.decode
> @@ -169,8 +169,16 @@ csrrci    . 111 

Re: [PATCH v4 16/16] tests/qtest/bios-tables-test: Add expected ACPI data files for RISC-V

2024-07-07 Thread Alistair Francis
On Thu, Jul 4, 2024 at 12:57 AM Sunil V L  wrote:
>
> On Wed, Jul 03, 2024 at 03:53:08PM +0530, Sunil V L wrote:
> > On Tue, Jul 02, 2024 at 03:02:36PM +0100, Jonathan Cameron wrote:
> > > On Mon, 1 Jul 2024 17:03:43 -0400
> > > "Michael S. Tsirkin"  wrote:
> > >
> > > > On Thu, Jun 27, 2024 at 02:18:03PM +0200, Igor Mammedov wrote:
> > > > > On Tue, 25 Jun 2024 20:38:39 +0530
> > > > > Sunil V L  wrote:
> > > > >
> > > > > > As per the step 5 in the process documented in bios-tables-test.c,
> > > > > > generate the expected ACPI AML data files for RISC-V using the
> > > > > > rebuild-expected-aml.sh script and update the
> > > > > > bios-tables-test-allowed-diff.h.
> > > > > >
> > > > > > These are all new files being added for the first time. Hence, iASL 
> > > > > > diff
> > > > > > output is not added.
> > > > > >
> > > > > > Signed-off-by: Sunil V L 
> > > > > > Acked-by: Alistair Francis 
> > > > > > Acked-by: Igor Mammedov 
> > > > >
> > > > > Michael,
> > > > > can it go via risc-v tree or
> > > > > do you plan to merge it via your tree?
> > > >
> > > > given patch 1 is merged, I took the rest.
> > >
> > > Looks like your CI runs are catching this as well but
> > > RHCT here is failing.  I rebased the GI/GP set on top of this
> > > and ignored that failure by skipping riscv64 tests.
> > >
> > > Jonathan
> > >
> > Hi Jonathan, Michael,
> >
> > Looks like a recent RISC-V PR updated the rva22s64 ISA string affecting
> > the RHCT I had in my series. I see that Michael dropped those 3 RISC-V
> > patches from the PR. So, let me update the expected RHCT AML file in a
> > new series. I will also include Igor's feedback to remove fallback path
> > in that series.
> >
> Hi Alistair,
>
> This issue is because, below 3 extensions are present in the ISA string
> for rva22s64 profile cpu after recent RISC-V PR.
>
> zmmul_zaamo_zalrsc

zmmul (multiply) is implied by M (multiply and divide). The other two
are similar.

>
> However, IIUC, they are not mentioned in the RVA22S64 profile spec. Because of
> this change, my AML files are having a difference and failing CI. The
> question is, is this correct behavior? If so, I can update the AML files
> and resubmit the patches. Let me know.

This does feel correct. Is software only needed zmmul for multiplying
then reporting zmmul when we support M feels like the right thing to
do.

I can't find a spec that says either way though. So unless anyone else
knows of one I think this current approach is correct

Alistair



Re: [PATCH v3 7/7] tests/avocado: Add an avocado test for riscv64

2024-07-07 Thread Alistair Francis
On Thu, Jul 4, 2024 at 12:55 AM LIU Zhiwei  wrote:
>
> From: TANG Tiancheng 
>
> To regularly test booting Linux with rv32 on QEMU RV64,
> we have added a test to boot_linux_console.py to retrieve
> cpuinfo and verify if it shows 'rv32' when using RV64 to
> boot rv32 CPUs.
>
> Signed-off-by: TANG Tiancheng 
> Reviewed-by: Liu Zhiwei 

Acked-by: Alistair Francis 

Alistair

> ---
>  tests/avocado/boot_linux_console.py | 37 +
>  1 file changed, 37 insertions(+)
>
> diff --git a/tests/avocado/boot_linux_console.py 
> b/tests/avocado/boot_linux_console.py
> index c35fc5e9ba..193b03d970 100644
> --- a/tests/avocado/boot_linux_console.py
> +++ b/tests/avocado/boot_linux_console.py
> @@ -12,6 +12,7 @@
>  import lzma
>  import gzip
>  import shutil
> +import time
>
>  from avocado import skip
>  from avocado import skipUnless
> @@ -1545,3 +1546,39 @@ def test_xtensa_lx60(self):
>  """
>  tar_hash = '49e88d9933742f0164b60839886c9739cb7a0d34'
>  self.do_test_advcal_2018('02', tar_hash, 'santas-sleigh-ride.elf')
> +
> +def test_riscv64_virt_rv32i(self):
> +"""
> +:avocado: tags=arch:riscv64
> +:avocado: tags=machine:virt
> +:avocado: tags=cpu:rv32
> +"""
> +kernel_url = ('https://github.com/romanheros/rv32-linux/raw'
> +  '/master/Image32.xz')
> +kernel_hash = 'a7ced5c38722481e0821b7cd70719cf53e46c13b'
> +kernel_path_xz = self.fetch_asset(kernel_url, asset_hash=kernel_hash)
> +
> +kernel_path =  os.path.join(self.workdir, 'kernel.riscv32')
> +archive.lzma_uncompress(kernel_path_xz, kernel_path)
> +
> +rootfs_url = ('https://github.com/romanheros/rv32-linux/raw'
> +  '/master/rootfs.ext2.xz')
> +rootfs_hash = 'dc25ab9d4b233e8e0bcf7eb220d56fd2008fe263'
> +rootfs_path_xz = self.fetch_asset(rootfs_url, asset_hash=rootfs_hash)
> +
> +rootfs_path =  os.path.join(self.workdir, 'rootfs.riscv32')
> +archive.lzma_uncompress(rootfs_path_xz, rootfs_path)
> +
> +self.vm.set_console()
> +kernel_command_line = 'root=/dev/vda ro console=ttyS0'
> +self.vm.add_args('-kernel', kernel_path,
> + '-append', kernel_command_line,
> + '-drive', f'file={rootfs_path},format=raw,id=hd0',
> + '-device', 'virtio-blk-device,drive=hd0',)
> +self.vm.launch()
> +
> +console_pattern = 'Welcome to Buildroot'
> +self.wait_for_console_pattern(console_pattern)
> +exec_command(self, 'root')
> +time.sleep(0.1)
> +exec_command_and_wait_for_pattern(self, 'cat /proc/cpuinfo', 'rv32i')
> --
> 2.25.1
>
>



Re: [PATCH v3 6/7] target/riscv: Enable RV32 CPU support in RV64 QEMU

2024-07-07 Thread Alistair Francis
On Thu, Jul 4, 2024 at 12:55 AM LIU Zhiwei  wrote:
>
> From: TANG Tiancheng 
>
> Add gdb XML files and adjust CPU initialization to allow running RV32 CPUs
> in RV64 QEMU.
>
> Signed-off-by: TANG Tiancheng 
> Reviewed-by: Liu Zhiwei 

Reviewed-by: Alistair Francis 

Alistair

> ---
>  configs/targets/riscv64-softmmu.mak |  2 +-
>  target/riscv/cpu.c  | 17 +
>  2 files changed, 14 insertions(+), 5 deletions(-)
>
> diff --git a/configs/targets/riscv64-softmmu.mak 
> b/configs/targets/riscv64-softmmu.mak
> index 917980e63e..6c5de72e03 100644
> --- a/configs/targets/riscv64-softmmu.mak
> +++ b/configs/targets/riscv64-softmmu.mak
> @@ -2,6 +2,6 @@ TARGET_ARCH=riscv64
>  TARGET_BASE_ARCH=riscv
>  TARGET_SUPPORTS_MTTCG=y
>  TARGET_KVM_HAVE_GUEST_DEBUG=y
> -TARGET_XML_FILES= gdb-xml/riscv-64bit-cpu.xml gdb-xml/riscv-32bit-fpu.xml 
> gdb-xml/riscv-64bit-fpu.xml gdb-xml/riscv-64bit-virtual.xml
> +TARGET_XML_FILES= gdb-xml/riscv-64bit-cpu.xml gdb-xml/riscv-32bit-fpu.xml 
> gdb-xml/riscv-64bit-fpu.xml gdb-xml/riscv-64bit-virtual.xml 
> gdb-xml/riscv-32bit-cpu.xml gdb-xml/riscv-32bit-virtual.xml
>  # needed by boot.c
>  TARGET_NEED_FDT=y
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index a2640cf259..fdd0f10aa5 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -630,8 +630,10 @@ static void rv64e_bare_cpu_init(Object *obj)
>  riscv_cpu_set_misa_ext(env, RVE);
>  }
>
> -#else /* !TARGET_RISCV64 */
> +#endif /* !TARGET_RISCV64 */
>
> +#if defined(TARGET_RISCV32) || \
> +(defined(TARGET_RISCV64) && !defined(CONFIG_USER_ONLY))
>  static void rv32_base_cpu_init(Object *obj)
>  {
>  RISCVCPU *cpu = RISCV_CPU(obj);
> @@ -2944,6 +2946,13 @@ static const TypeInfo riscv_cpu_type_infos[] = {
>  #if defined(TARGET_RISCV32)
>  DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_ANY,   MXL_RV32,  
> riscv_any_cpu_init),
>  DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_MAX,   MXL_RV32,  
> riscv_max_cpu_init),
> +#elif defined(TARGET_RISCV64)
> +DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_ANY,   MXL_RV64,  
> riscv_any_cpu_init),
> +DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_MAX,   MXL_RV64,  
> riscv_max_cpu_init),
> +#endif
> +
> +#if defined(TARGET_RISCV32) || \
> +(defined(TARGET_RISCV64) && !defined(CONFIG_USER_ONLY))
>  DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_BASE32,MXL_RV32,  
> rv32_base_cpu_init),
>  DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_IBEX,   MXL_RV32,  
> rv32_ibex_cpu_init),
>  DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SIFIVE_E31, MXL_RV32,  
> rv32_sifive_e_cpu_init),
> @@ -2951,9 +2960,9 @@ static const TypeInfo riscv_cpu_type_infos[] = {
>  DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SIFIVE_U34, MXL_RV32,  
> rv32_sifive_u_cpu_init),
>  DEFINE_BARE_CPU(TYPE_RISCV_CPU_RV32I,MXL_RV32,  
> rv32i_bare_cpu_init),
>  DEFINE_BARE_CPU(TYPE_RISCV_CPU_RV32E,MXL_RV32,  
> rv32e_bare_cpu_init),
> -#elif defined(TARGET_RISCV64)
> -DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_ANY,   MXL_RV64,  
> riscv_any_cpu_init),
> -DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_MAX,   MXL_RV64,  
> riscv_max_cpu_init),
> +#endif
> +
> +#if defined(TARGET_RISCV64)
>  DEFINE_DYNAMIC_CPU(TYPE_RISCV_CPU_BASE64,MXL_RV64,  
> rv64_base_cpu_init),
>  DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SIFIVE_E51, MXL_RV64,  
> rv64_sifive_e_cpu_init),
>  DEFINE_VENDOR_CPU(TYPE_RISCV_CPU_SIFIVE_U54, MXL_RV64,  
> rv64_sifive_u_cpu_init),
> --
> 2.25.1
>
>



Re: [PATCH v3 4/7] target/riscv: Detect sxl to set bit width for RV32 in RV64

2024-07-07 Thread Alistair Francis
On Thu, Jul 4, 2024 at 12:54 AM LIU Zhiwei  wrote:
>
> From: TANG Tiancheng 
>
> Ensure correct bit width based on sxl when running RV32 on RV64 QEMU.
> This is required as MMU address translations run in S-mode.
>
> Signed-off-by: TANG Tiancheng 
> Reviewed-by: Liu Zhiwei 
> ---
>  target/riscv/cpu_helper.c | 17 -
>  1 file changed, 12 insertions(+), 5 deletions(-)
>
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index 6709622dd3..fa3b845c85 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -887,12 +887,14 @@ static int get_physical_address(CPURISCVState *env, 
> hwaddr *physical,
>
>  CPUState *cs = env_cpu(env);
>  int va_bits = PGSHIFT + levels * ptidxbits + widened;
> +int sxlen = 16UL << riscv_cpu_sxl(env);

A leftover UL here

Otherwise:

Reviewed-by: Alistair Francis 

Alistair

> +int sxlen_bytes = sxlen / 8;
>
>  if (first_stage == true) {
>  target_ulong mask, masked_msbs;
>
> -if (TARGET_LONG_BITS > (va_bits - 1)) {
> -mask = (1L << (TARGET_LONG_BITS - (va_bits - 1))) - 1;
> +if (sxlen > (va_bits - 1)) {
> +mask = (1L << (sxlen - (va_bits - 1))) - 1;
>  } else {
>  mask = 0;
>  }
> @@ -961,7 +963,7 @@ restart:
>
>  int pmp_prot;
>  int pmp_ret = get_physical_address_pmp(env, _prot, pte_addr,
> -   sizeof(target_ulong),
> +   sxlen_bytes,
> MMU_DATA_LOAD, PRV_S);
>  if (pmp_ret != TRANSLATE_SUCCESS) {
>  return TRANSLATE_PMP_FAIL;
> @@ -1113,7 +1115,7 @@ restart:
>   *   it is no longer valid and we must re-walk the page table.
>   */
>  MemoryRegion *mr;
> -hwaddr l = sizeof(target_ulong), addr1;
> +hwaddr l = sxlen_bytes, addr1;
>  mr = address_space_translate(cs->as, pte_addr, , ,
>   false, MEMTXATTRS_UNSPECIFIED);
>  if (memory_region_is_ram(mr)) {
> @@ -1125,7 +1127,12 @@ restart:
>   */
>  *pte_pa = pte = updated_pte;
>  #else
> -target_ulong old_pte = qatomic_cmpxchg(pte_pa, pte, updated_pte);
> +target_ulong old_pte;
> +if (riscv_cpu_sxl(env) == MXL_RV32) {
> +old_pte = qatomic_cmpxchg((uint32_t *)pte_pa, pte, 
> updated_pte);
> +} else {
> +old_pte = qatomic_cmpxchg(pte_pa, pte, updated_pte);
> +}
>  if (old_pte != pte) {
>  goto restart;
>  }
> --
> 2.25.1
>
>



Re: [PATCH v2] disas/riscv: Add decode for Zawrs extension

2024-07-07 Thread Alistair Francis
On Sat, Jul 6, 2024 at 2:54 AM Rob Bradford  wrote:
>
> From: Balaji Ravikumar 
>
> Add disassembly support for these instructions from Zawrs:
>
> * wrs.sto
> * wrs.nto
>
> Signed-off-by: Balaji Ravikumar 
> Signed-off-by: Rob Bradford 

Thanks!

Applied to riscv-to-apply.next

Alistair

> ---
>  disas/riscv.c | 6 ++
>  1 file changed, 6 insertions(+)
>
> diff --git a/disas/riscv.c b/disas/riscv.c
> index 05b663ebfe..ff0323f0dd 100644
> --- a/disas/riscv.c
> +++ b/disas/riscv.c
> @@ -974,6 +974,8 @@ typedef enum {
>  rv_op_amomaxu_h = 943,
>  rv_op_amocas_b  = 944,
>  rv_op_amocas_h  = 945,
> +rv_op_wrs_sto = 946,
> +rv_op_wrs_nto = 947,
>  } rv_op;
>
>  /* register names */
> @@ -2232,6 +2234,8 @@ const rv_opcode_data rvi_opcode_data[] = {
>  { "amomaxu.h", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
>  { "amocas.b", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
>  { "amocas.h", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
> +{ "wrs.sto", rv_codec_none, rv_fmt_none, NULL, 0, 0, 0 },
> +{ "wrs.nto", rv_codec_none, rv_fmt_none, NULL, 0, 0, 0 },
>  };
>
>  /* CSR names */
> @@ -4000,6 +4004,8 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa 
> isa)
>  case 0: op = rv_op_ecall; break;
>  case 32: op = rv_op_ebreak; break;
>  case 64: op = rv_op_uret; break;
> +case 416: op = rv_op_wrs_nto; break;
> +case 928: op = rv_op_wrs_sto; break;
>  }
>  break;
>  case 256:
> --
> 2.45.2
>
>



Re: [PATCH v2] disas/riscv: Add decode for Zawrs extension

2024-07-07 Thread Alistair Francis
On Sat, Jul 6, 2024 at 2:54 AM Rob Bradford  wrote:
>
> From: Balaji Ravikumar 
>
> Add disassembly support for these instructions from Zawrs:
>
> * wrs.sto
> * wrs.nto
>
> Signed-off-by: Balaji Ravikumar 
> Signed-off-by: Rob Bradford 

Acked-by: Alistair Francis 

Alistair

> ---
>  disas/riscv.c | 6 ++
>  1 file changed, 6 insertions(+)
>
> diff --git a/disas/riscv.c b/disas/riscv.c
> index 05b663ebfe..ff0323f0dd 100644
> --- a/disas/riscv.c
> +++ b/disas/riscv.c
> @@ -974,6 +974,8 @@ typedef enum {
>  rv_op_amomaxu_h = 943,
>  rv_op_amocas_b  = 944,
>  rv_op_amocas_h  = 945,
> +rv_op_wrs_sto = 946,
> +rv_op_wrs_nto = 947,
>  } rv_op;
>
>  /* register names */
> @@ -2232,6 +2234,8 @@ const rv_opcode_data rvi_opcode_data[] = {
>  { "amomaxu.h", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
>  { "amocas.b", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
>  { "amocas.h", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
> +{ "wrs.sto", rv_codec_none, rv_fmt_none, NULL, 0, 0, 0 },
> +{ "wrs.nto", rv_codec_none, rv_fmt_none, NULL, 0, 0, 0 },
>  };
>
>  /* CSR names */
> @@ -4000,6 +4004,8 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa 
> isa)
>  case 0: op = rv_op_ecall; break;
>  case 32: op = rv_op_ebreak; break;
>  case 64: op = rv_op_uret; break;
> +case 416: op = rv_op_wrs_nto; break;
> +case 928: op = rv_op_wrs_sto; break;
>  }
>  break;
>  case 256:
> --
> 2.45.2
>
>



Re: [PATCH v4 00/14] riscv: QEMU RISC-V IOMMU Support

2024-07-07 Thread Alistair Francis
On Sat, Jul 6, 2024 at 7:26 AM Daniel Henrique Barboza
 wrote:
>
> Hi,
>
> Would it make it easier for review if we squash patch 3:
>
> [PATCH v4 03/14] hw/riscv: add RISC-V IOMMU base emulation
>
> and patch 8:
>
> [PATCH v4 09/14] hw/riscv/riscv-iommu: add s-stage and g-stage support
>
> In the same patch?
>
> I'm asking because I've been noticing since the first versions that some 
> reviews
> on patch 3 seems to refer to context that are s-stage and g-stage related, 
> i.e.
> added later. Perhaps squashing them together makes it easier to review since
> we'll have a more complete picture. Patch 3 will end up gaining +381 lines
> though.

Squashing is probably the way to go

Alistair



Re: [PATCH] hw/intc: sifive_plic: Fix heap-buffer-overflow in SiFive PLIC read operation

2024-07-07 Thread Alistair Francis
On Thu, Jul 4, 2024 at 7:33 PM Peter Maydell  wrote:
>
> On Wed, 3 Jul 2024 at 22:32, Zheyu Ma  wrote:
> >
> > The sifive_plic_read function in hw/intc/sifive_plic.c had a potential
> > heap-buffer-overflow issue when reading from the pending_base region.
> > This occurred because the code did not check if the calculated word index
> > was within valid bounds before accessing the pending array.
> >
> > This fix prevents out-of-bounds memory access, ensuring safer and more
> > robust handling of PLIC reads.
> >
> > ASAN log:
> > ==78800==ERROR: AddressSanitizer: heap-buffer-overflow on address 
> > 0x60238a14 at pc 0x5baf49d0d6cb bp 0x7ffc2ea4e180 sp 0x7ffc2ea4e178
> > READ of size 4 at 0x60238a14 thread T0
> > #0 0x5baf49d0d6ca in sifive_plic_read hw/intc/sifive_plic.c:151:16
> > #1 0x5baf49f7f3bb in memory_region_read_accessor system/memory.c:445:11
> >
> > Reproducer:
> > cat << EOF | qemu-system-riscv64  -display \
> > none -machine accel=qtest, -m 512M -machine shakti_c -m 2G -qtest stdio
> > readl 0xc001004
> > EOF
> >
> > Signed-off-by: Zheyu Ma 
> > ---
> >  hw/intc/sifive_plic.c | 9 -
> >  1 file changed, 8 insertions(+), 1 deletion(-)
> >
> > diff --git a/hw/intc/sifive_plic.c b/hw/intc/sifive_plic.c
> > index e559f11805..d2a90dfd3a 100644
> > --- a/hw/intc/sifive_plic.c
> > +++ b/hw/intc/sifive_plic.c
> > @@ -147,7 +147,14 @@ static uint64_t sifive_plic_read(void *opaque, hwaddr 
> > addr, unsigned size)
> >  (plic->num_sources + 31) >> 3)) {
> >  uint32_t word = (addr - plic->pending_base) >> 2;
> >
> > -return plic->pending[word];
> > +if (word < plic->bitfield_words) {
> > +return plic->pending[word];
> > +} else {
> > +qemu_log_mask(LOG_GUEST_ERROR,
> > +  "sifive_plic_read: Word out of bounds for 
> > pending_base read: word=%u\n",
> > +  word);
> > +return 0;
> > +}
>
> This seems a bit odd. This part of the code is guarded by
>
> } else if (addr_between(addr, plic->pending_base,
> (plic->num_sources + 31) >> 3)) {
>
> and we calculate plic->bitfield_words in realize based on
> plic->num_sources:
> s->bitfield_words = (s->num_sources + 31) >> 5;
>
> so presumably the intention was that we put enough words
> in the bitfield for the number of sources we have, so that
> the array access wouldn't overrun. Maybe we got the
> calculation wrong?

Yeah, the calculation is wrong here.

We have

s->bitfield_words = (s->num_sources + 31) >> 5;
...
s->pending = g_new0(uint32_t, s->bitfield_words);

But then the check is

} else if (addr_between(addr, plic->pending_base,
(plic->num_sources + 31) >> 3)) {

So when we allocate we shift by 5, but then when we check we only shift by 3.

So that's the bug. It's not immediately obvious what the correct fix
is though, do you mind having a look?

Alistair

>
> thanks
> -- PMM
>



Re: [PATCH v3 3/7] target/riscv: Correct SXL return value for RV32 in RV64 QEMU

2024-07-07 Thread Alistair Francis
On Thu, Jul 4, 2024 at 12:53 AM LIU Zhiwei  wrote:
>
> From: TANG Tiancheng 
>
> Ensure that riscv_cpu_sxl returns MXL_RV32 when runningRV32 in an
> RV64 QEMU.
>
> Signed-off-by: TANG Tiancheng 
> Fixes: 05e6ca5e156 ("target/riscv: Ignore reserved bits in PTE for RV64")
> Reviewed-by: Liu Zhiwei 

Reviewed-by: Alistair Francis 

Alistair

> ---
>  target/riscv/cpu.h | 5 -
>  1 file changed, 4 insertions(+), 1 deletion(-)
>
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index 87742047ce..49de81be7e 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -693,8 +693,11 @@ static inline RISCVMXL riscv_cpu_sxl(CPURISCVState *env)
>  #ifdef CONFIG_USER_ONLY
>  return env->misa_mxl;
>  #else
> -return get_field(env->mstatus, MSTATUS64_SXL);
> +if (env->misa_mxl != MXL_RV32) {
> +return get_field(env->mstatus, MSTATUS64_SXL);
> +}
>  #endif
> +return MXL_RV32;
>  }
>  #endif
>
> --
> 2.25.1
>
>



Re: [PATCH] target/riscv: Validate the mode in write_vstvec

2024-07-07 Thread Alistair Francis
On Mon, Jul 1, 2024 at 3:42 PM Jiayi Li  wrote:
>
> Base on the riscv-privileged spec, vstvec substitutes for the usual stvec.
> Therefore, the encoding of the MODE should also be restricted to 0 and 1.
>
> Signed-off-by: Jiayi Li 

Thanks!

Applied to riscv-to-apply.next

Alistair

> ---
>  target/riscv/csr.c | 7 ++-
>  1 file changed, 6 insertions(+), 1 deletion(-)
>
> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> index 432c59dc66..f9229d92ab 100644
> --- a/target/riscv/csr.c
> +++ b/target/riscv/csr.c
> @@ -3791,7 +3791,12 @@ static RISCVException read_vstvec(CPURISCVState *env, 
> int csrno,
>  static RISCVException write_vstvec(CPURISCVState *env, int csrno,
> target_ulong val)
>  {
> -env->vstvec = val;
> +/* bits [1:0] encode mode; 0 = direct, 1 = vectored, 2 >= reserved */
> +if ((val & 3) < 2) {
> +env->vstvec = val;
> +} else {
> +qemu_log_mask(LOG_UNIMP, "CSR_VSTVEC: reserved mode not 
> supported\n");
> +}
>  return RISCV_EXCP_NONE;
>  }
>
> --
> 2.25.1
>
>



Re: [PATCH] target/riscv: Validate the mode in write_vstvec

2024-07-07 Thread Alistair Francis
On Mon, Jul 1, 2024 at 3:42 PM Jiayi Li  wrote:
>
> Base on the riscv-privileged spec, vstvec substitutes for the usual stvec.
> Therefore, the encoding of the MODE should also be restricted to 0 and 1.
>
> Signed-off-by: Jiayi Li 

Reviewed-by: Alistair Francis 

Alistair

> ---
>  target/riscv/csr.c | 7 ++-
>  1 file changed, 6 insertions(+), 1 deletion(-)
>
> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> index 432c59dc66..f9229d92ab 100644
> --- a/target/riscv/csr.c
> +++ b/target/riscv/csr.c
> @@ -3791,7 +3791,12 @@ static RISCVException read_vstvec(CPURISCVState *env, 
> int csrno,
>  static RISCVException write_vstvec(CPURISCVState *env, int csrno,
> target_ulong val)
>  {
> -env->vstvec = val;
> +/* bits [1:0] encode mode; 0 = direct, 1 = vectored, 2 >= reserved */
> +if ((val & 3) < 2) {
> +env->vstvec = val;
> +} else {
> +qemu_log_mask(LOG_UNIMP, "CSR_VSTVEC: reserved mode not 
> supported\n");
> +}
>  return RISCV_EXCP_NONE;
>  }
>
> --
> 2.25.1
>
>



[PATCH v8 0/3] Initial support for SPDM Responders

2024-07-03 Thread Alistair Francis
The Security Protocol and Data Model (SPDM) Specification defines
messages, data objects, and sequences for performing message exchanges
over a variety of transport and physical media.
 - 
https://www.dmtf.org/sites/default/files/standards/documents/DSP0274_1.3.0.pdf

SPDM currently supports PCIe DOE and MCTP transports, but it can be
extended to support others in the future. This series adds
support to QEMU to connect to an external SPDM instance.

SPDM support can be added to any QEMU device by exposing a
TCP socket to a SPDM server. The server can then implement the SPDM
decoding/encoding support, generally using libspdm [1].

This is similar to how the current TPM implementation works and means
that the heavy lifting of setting up certificate chains, capabilities,
measurements and complex crypto can be done outside QEMU by a well
supported and tested library.

This series implements socket support and exposes SPDM for a NVMe device.

1: https://github.com/DMTF/libspdm

v8:
 - Fixup i386 failures (thanks to Wilfred)
 - Passes CI on GitLab: 
https://gitlab.com/alistair23/qemu/-/tree/mainline/alistair/spdm-socket.next?ref_type=heads
v7:
 - Fixup checkpatch failures
 - Fixup test failures
 - Rename port name to be clearer
v6:
 - Add documentation to public functions
 - Rename socket variable to spdm_socket
 - Don't override errp
 - Correctly return false from nvme_init_pci() on error
v5:
 - Update MAINTAINERS
v4:
 - Rebase
v3:
 - Spelling fixes
 - Support for SPDM-Utils
v2:
 - Add cover letter
 - A few code fixes based on comments
 - Document SPDM-Utils
 - A few tweaks and clarifications to the documentation

Alistair Francis (1):
  hw/pci: Add all Data Object Types defined in PCIe r6.0

Huai-Cheng Kuo (1):
  backends: Initial support for SPDM socket support

Wilfred Mallawa (1):
  hw/nvme: Add SPDM over DOE support

 MAINTAINERS  |   6 +
 docs/specs/index.rst |   1 +
 docs/specs/spdm.rst  | 134 ++
 include/hw/pci/pci_device.h  |   7 ++
 include/hw/pci/pcie_doe.h|   5 +
 include/sysemu/spdm-socket.h |  74 
 backends/spdm-socket.c   | 216 +++
 hw/nvme/ctrl.c   |  62 ++
 backends/Kconfig |   4 +
 backends/meson.build |   2 +
 10 files changed, 511 insertions(+)
 create mode 100644 docs/specs/spdm.rst
 create mode 100644 include/sysemu/spdm-socket.h
 create mode 100644 backends/spdm-socket.c

-- 
2.45.2




[PATCH v8 3/3] hw/nvme: Add SPDM over DOE support

2024-07-03 Thread Alistair Francis
From: Wilfred Mallawa 

Setup Data Object Exchange (DOE) as an extended capability for the NVME
controller and connect SPDM to it (CMA) to it.

Signed-off-by: Wilfred Mallawa 
Signed-off-by: Alistair Francis 
Reviewed-by: Jonathan Cameron 
Acked-by: Klaus Jensen 
---
 docs/specs/index.rst|   1 +
 docs/specs/spdm.rst | 134 
 include/hw/pci/pci_device.h |   7 ++
 include/hw/pci/pcie_doe.h   |   3 +
 hw/nvme/ctrl.c  |  62 +
 5 files changed, 207 insertions(+)
 create mode 100644 docs/specs/spdm.rst

diff --git a/docs/specs/index.rst b/docs/specs/index.rst
index 1484e3e760..e2d907959a 100644
--- a/docs/specs/index.rst
+++ b/docs/specs/index.rst
@@ -29,6 +29,7 @@ guest hardware that is specific to QEMU.
edu
ivshmem-spec
pvpanic
+   spdm
standard-vga
virt-ctlr
vmcoreinfo
diff --git a/docs/specs/spdm.rst b/docs/specs/spdm.rst
new file mode 100644
index 00..f7de080ff0
--- /dev/null
+++ b/docs/specs/spdm.rst
@@ -0,0 +1,134 @@
+==
+QEMU Security Protocols and Data Models (SPDM) Support
+==
+
+SPDM enables authentication, attestation and key exchange to assist in
+providing infrastructure security enablement. It's a standard published
+by the `DMTF`_.
+
+QEMU supports connecting to a SPDM responder implementation. This allows an
+external application to emulate the SPDM responder logic for an SPDM device.
+
+Setting up a SPDM server
+
+
+When using QEMU with SPDM devices QEMU will connect to a server which
+implements the SPDM functionality.
+
+SPDM-Utils
+--
+
+You can use `SPDM Utils`_ to emulate a responder. This is the simplest method.
+
+SPDM-Utils is a Linux applications to manage, test and develop devices
+supporting DMTF Security Protocol and Data Model (SPDM). It is written in Rust
+and utilises libspdm.
+
+To use SPDM-Utils you will need to do the following steps. Details are included
+in the SPDM-Utils README.
+
+ 1. `Build libspdm`_
+ 2. `Build SPDM Utils`_
+ 3. `Run it as a server`_
+
+spdm-emu
+
+
+You can use `spdm emu`_ to model the
+SPDM responder.
+
+.. code-block:: shell
+
+$ cd spdm-emu
+$ git submodule init; git submodule update --recursive
+$ mkdir build; cd build
+$ cmake -DARCH=x64 -DTOOLCHAIN=GCC -DTARGET=Debug -DCRYPTO=openssl ..
+$ make -j32
+$ make copy_sample_key # Build certificates, required for SPDM 
authentication.
+
+It is worth noting that the certificates should be in compliance with
+PCIe r6.1 sec 6.31.3. This means you will need to add the following to
+openssl.cnf
+
+.. code-block::
+
+subjectAltName = 
otherName:2.23.147;UTF8:Vendor=1b36:Device=0010:CC=010802:REV=02:SSVID=1af4:SSID=1100
+2.23.147 = ASN1:OID:2.23.147
+
+and then manually regenerate some certificates with:
+
+.. code-block:: shell
+
+$ openssl req -nodes -newkey ec:param.pem -keyout end_responder.key \
+-out end_responder.req -sha384 -batch \
+-subj "/CN=DMTF libspdm ECP384 responder cert"
+
+$ openssl x509 -req -in end_responder.req -out end_responder.cert \
+-CA inter.cert -CAkey inter.key -sha384 -days 3650 -set_serial 3 \
+-extensions v3_end -extfile ../openssl.cnf
+
+$ openssl asn1parse -in end_responder.cert -out end_responder.cert.der
+
+$ cat ca.cert.der inter.cert.der end_responder.cert.der > 
bundle_responder.certchain.der
+
+You can use SPDM-Utils instead as it will generate the correct certificates
+automatically.
+
+The responder can then be launched with
+
+.. code-block:: shell
+
+$ cd bin
+$ ./spdm_responder_emu --trans PCI_DOE
+
+Connecting an SPDM NVMe device
+==
+
+Once a SPDM server is running we can start QEMU and connect to the server.
+
+For an NVMe device first let's setup a block we can use
+
+.. code-block:: shell
+
+$ cd qemu-spdm/linux/image
+$ dd if=/dev/zero of=blknvme bs=1M count=2096 # 2GB NNMe Drive
+
+Then you can add this to your QEMU command line:
+
+.. code-block:: shell
+
+-drive file=blknvme,if=none,id=mynvme,format=raw \
+-device nvme,drive=mynvme,serial=deadbeef,spdm_port=2323
+
+At which point QEMU will try to connect to the SPDM server.
+
+Note that if using x64-64 you will want to use the q35 machine instead
+of the default. So the entire QEMU command might look like this
+
+.. code-block:: shell
+
+qemu-system-x86_64 -M q35 \
+--kernel bzImage \
+-drive file=rootfs.ext2,if=virtio,format=raw \
+-append "root=/dev/vda console=ttyS0" \
+-net none -nographic \
+-drive file=blknvme,if=none,id=mynvme,format=raw \
+-device nvme,drive=mynvme,serial=deadbeef,spdm_port=2323
+
+.. _DMTF:
+   https://www.dmtf.org/standards/SPDM
+
+.. _SPDM Utils:
+   https://github.com/westerndigitalcorporation/spdm-utils
+
+.. _spdm emu:

[PATCH v8 2/3] backends: Initial support for SPDM socket support

2024-07-03 Thread Alistair Francis
From: Huai-Cheng Kuo 

SPDM enables authentication, attestation and key exchange to assist in
providing infrastructure security enablement. It's a standard published
by the DMTF [1].

SPDM supports multiple transports, including PCIe DOE and MCTP.
This patch adds support to QEMU to connect to an external SPDM
instance.

SPDM support can be added to any QEMU device by exposing a
TCP socket to a SPDM server. The server can then implement the SPDM
decoding/encoding support, generally using libspdm [2].

This is similar to how the current TPM implementation works and means
that the heavy lifting of setting up certificate chains, capabilities,
measurements and complex crypto can be done outside QEMU by a well
supported and tested library.

1: https://www.dmtf.org/standards/SPDM
2: https://github.com/DMTF/libspdm

Signed-off-by: Huai-Cheng Kuo 
Signed-off-by: Chris Browy 
Co-developed-by: Jonathan Cameron 
Signed-off-by: Jonathan Cameron 
[ Changes by WM
 - Bug fixes from testing
]
Signed-off-by: Wilfred Mallawa 
[ Changes by AF:
 - Convert to be more QEMU-ified
 - Move to backends as it isn't PCIe specific
]
Signed-off-by: Alistair Francis 
---
 MAINTAINERS  |   6 +
 include/sysemu/spdm-socket.h |  74 
 backends/spdm-socket.c   | 216 +++
 backends/Kconfig |   4 +
 backends/meson.build |   2 +
 5 files changed, 302 insertions(+)
 create mode 100644 include/sysemu/spdm-socket.h
 create mode 100644 backends/spdm-socket.c

diff --git a/MAINTAINERS b/MAINTAINERS
index 6725913c8b..c76a0cfe12 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -3397,6 +3397,12 @@ F: tests/qtest/*tpm*
 F: docs/specs/tpm.rst
 T: git https://github.com/stefanberger/qemu-tpm.git tpm-next
 
+SPDM
+M: Alistair Francis 
+S: Maintained
+F: backends/spdm-socket.c
+F: include/sysemu/spdm-socket.h
+
 Checkpatch
 S: Odd Fixes
 F: scripts/checkpatch.pl
diff --git a/include/sysemu/spdm-socket.h b/include/sysemu/spdm-socket.h
new file mode 100644
index 00..5d8bd9aa4e
--- /dev/null
+++ b/include/sysemu/spdm-socket.h
@@ -0,0 +1,74 @@
+/*
+ * QEMU SPDM socket support
+ *
+ * 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.
+ */
+
+#ifndef SPDM_REQUESTER_H
+#define SPDM_REQUESTER_H
+
+/**
+ * spdm_socket_connect: connect to an external SPDM socket
+ * @port: port to connect to
+ * @errp: error object handle
+ *
+ * This will connect to an external SPDM socket server. On error
+ * it will return -1 and errp will be set. On success this function
+ * will return the socket number.
+ */
+int spdm_socket_connect(uint16_t port, Error **errp);
+
+/**
+ * spdm_socket_rsp: send and receive a message to a SPDM server
+ * @socket: socket returned from spdm_socket_connect()
+ * @transport_type: SPDM_SOCKET_TRANSPORT_TYPE_* macro
+ * @req: request buffer
+ * @req_len: request buffer length
+ * @rsp: response buffer
+ * @rsp_len: response buffer length
+ *
+ * Send platform data to a SPDM server on socket and then receive
+ * a response.
+ */
+uint32_t spdm_socket_rsp(const int socket, uint32_t transport_type,
+ void *req, uint32_t req_len,
+ void *rsp, uint32_t rsp_len);
+
+/**
+ * spdm_socket_close: send a shutdown command to the server
+ * @socket: socket returned from spdm_socket_connect()
+ * @transport_type: SPDM_SOCKET_TRANSPORT_TYPE_* macro
+ *
+ * This will issue a shutdown command to the server.
+ */
+void spdm_socket_close(const int socket, uint32_t transport_type);
+
+#define SPDM_SOCKET_COMMAND_NORMAL0x0001
+#define SPDM_SOCKET_COMMAND_OOB_ENCAP_KEY_UPDATE  0x8001
+#define SPDM_SOCKET_COMMAND_CONTINUE  0xFFFD
+#define SPDM_SOCKET_COMMAND_SHUTDOWN  0xFFFE
+#define SPDM_SOCKET_COMMAND_UNKOWN0x
+#define SPDM_SOCKET_COMMAND_TEST  0xDEAD
+
+#define SPDM_SOCKET_TRANSPORT_TYPE_MCTP

[PATCH v8 1/3] hw/pci: Add all Data Object Types defined in PCIe r6.0

2024-07-03 Thread Alistair Francis
Add all of the defined protocols/features from the PCIe-SIG r6.0
"Table 6-32 PCI-SIG defined Data Object Types (Vendor ID = 0001h)"
table.

Signed-off-by: Alistair Francis 
Reviewed-by: Jonathan Cameron 
Reviewed-by: Wilfred Mallawa 
---
 include/hw/pci/pcie_doe.h | 2 ++
 1 file changed, 2 insertions(+)

diff --git a/include/hw/pci/pcie_doe.h b/include/hw/pci/pcie_doe.h
index 87dc17dcef..15d94661f9 100644
--- a/include/hw/pci/pcie_doe.h
+++ b/include/hw/pci/pcie_doe.h
@@ -46,6 +46,8 @@ REG32(PCI_DOE_CAP_STATUS, 0)
 
 /* PCI-SIG defined Data Object Types - r6.0 Table 6-32 */
 #define PCI_SIG_DOE_DISCOVERY   0x00
+#define PCI_SIG_DOE_CMA 0x01
+#define PCI_SIG_DOE_SECURED_CMA 0x02
 
 #define PCI_DOE_DW_SIZE_MAX (1 << 18)
 #define PCI_DOE_PROTOCOL_NUM_MAX256
-- 
2.45.2




Re: [PATCH 0/6] target/riscv: Expose RV32 cpu to RV64 QEMU

2024-07-02 Thread Alistair Francis
On Wed, Jul 3, 2024 at 12:25 AM Philippe Mathieu-Daudé
 wrote:
>
> Hi Zhiwei,
>
> On 1/7/24 05:37, LIU Zhiwei wrote:
> > From: TANG Tiancheng 
> >
> > This patch set aims to expose 32-bit RISC-V cpu to RV64 QEMU. Thus
> > qemu-system-riscv64 can directly boot a RV32 Linux.
> >
> > This patch set has been tested with 6.9.0 Linux Image.
> >
> > - Run RV64 QEMU with RV32 CPU
> > qemu-system-riscv64 -cpu rv32 -M virt -nographic \
> >  -kernel Image \
> >  -append "root=/dev/vda ro console=ttyS0" \
> >  -drive file=rootfs.ext2,format=raw,id=hd0 \
> >  -device virtio-blk-device,drive=hd0 -netdev user,id=net0 \
> >  -device virtio-net-device,netdev=net0
> >
> > OpenSBI v1.4
> > QEMU emulator version 9.0.50 (v9.0.0-1132-g7799dc2e3b)
> > [0.00] Linux version 6.9.0 (developer@11109ca35736) 
> > (riscv32-unknown-linux-gnu-gcc (gc891d8dc23e-dirty) 13.2.0, GNU ld (GNU 
> > Binutils) 2.42) #3 SMP Fri May 31 08:42:15 UTC 2024
> > [0.00] random: crng init done
> > [0.00] OF: fdt: Ignoring memory range 0x8000 - 0x8040
> > [0.00] Machine model: riscv-virtio,qemu
> > [0.00] SBI specification v2.0 detected
> > [0.00] SBI implementation ID=0x1 Version=0x10004
> > [0.00] SBI TIME extension detected
> > [0.00] SBI IPI extension detected
> > [0.00] SBI RFENCE extension detected
> > [0.00] SBI SRST extension detected
> > [0.00] SBI DBCN extension detected
> > [0.00] efi: UEFI not found.
> > [0.00] OF: reserved mem: 0x8000..0x8003 (256 KiB) nomap 
> > non-reusable mmode_resv1@8000
> > [0.00] OF: reserved mem: 0x8004..0x8004 (64 KiB) nomap 
> > non-reusable mmode_resv0@8004
> > [0.00] Zone ranges:
> > [0.00]   Normal   [mem 0x8040-0x87ff]
> > [0.00] Movable zone start for each node
> > [0.00] Early memory node ranges
> > [0.00]   node   0: [mem 0x8040-0x87ff]
> > [0.00] Initmem setup node 0 [mem 
> > 0x8040-0x87ff]
> > [0.00] On node 0, zone Normal: 1024 pages in unavailable ranges
> > [0.00] SBI HSM extension detected
> > [0.00] riscv: base ISA extensions acdfhim
> > [0.00] riscv: ELF capabilities acdfim
> > [0.00] percpu: Embedded 17 pages/cpu s37728 r8192 d23712 u69632
> > [0.00] Kernel command line: root=/dev/vda ro console=ttyS0
> > [0.00] Dentry cache hash table entries: 16384 (order: 4, 65536 
> > bytes, linear)
> > [0.00] Inode-cache hash table entries: 8192 (order: 3, 32768 bytes, 
> > linear)
> > [0.00] Built 1 zonelists, mobility grouping on.  Total pages: 31465
> > [0.00] mem auto-init: stack:all(zero), heap alloc:off, heap free:off
> > [0.00] Virtual kernel memory layout:
> > [0.00]   fixmap : 0x9c80 - 0x9d00   (8192 kB)
> > [0.00]   pci io : 0x9d00 - 0x9e00   (  16 MB)
> > [0.00]  vmemmap : 0x9e00 - 0xa000   (  32 MB)
> > [0.00]  vmalloc : 0xa000 - 0xc000   ( 512 MB)
> > [0.00]   lowmem : 0xc000 - 0xc7c0   ( 124 MB)
> > [0.00] Memory: 95700K/126976K available (9090K kernel code, 8845K 
> > rwdata, 4096K rodata, 4231K init, 341K bss, 31276K reserved, 0K 
> > cma-reserved)
> > ...
> > Welcome to Buildroot
> > buildroot login: root
> > # cat /proc/cpuinfo
> > processor   : 0
> > hart: 0
> > isa : 
> > rv32imafdch_zicbom_zicboz_zicntr_zicsr_zifencei_zihintntl_zihintpause_zihpm_zfa_zba_zbb_zbc_zbs_sstc
> > mmu : sv32
>
> Please provide an Avocado test (i.e. checking /proc/cpuinfo
> contains "isa : rv32"). See for reference
> tests/avocado/boot_linux_console.py.

Awesome! Thanks for this, this is very exciting.

I agree we should add an Avacado test, that way this will be regularly
tested as it's something that seems prone to breakage.

Alistair

>
> Thanks!
>



Re: [PATCH 4/6] target/riscv: Detect sxl to set bit width for RV32 in RV64

2024-07-02 Thread Alistair Francis
On Mon, Jul 1, 2024 at 1:41 PM LIU Zhiwei  wrote:
>
> From: TANG Tiancheng 
>
> Ensure correct bit width based on sxl when running RV32 on RV64 QEMU.
> This is required as MMU address translations run in S-mode.
>
> Signed-off-by: TANG Tiancheng 
> Reviewed-by: Liu Zhiwei 
> ---
>  target/riscv/cpu_helper.c | 15 +++
>  1 file changed, 11 insertions(+), 4 deletions(-)
>
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index 6709622dd3..1af83a0a36 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -887,12 +887,14 @@ static int get_physical_address(CPURISCVState *env, 
> hwaddr *physical,
>
>  CPUState *cs = env_cpu(env);
>  int va_bits = PGSHIFT + levels * ptidxbits + widened;
> +int sxlen = 16UL << riscv_cpu_sxl(env);
> +int sxlen_bytes = sxlen / 8;
>
>  if (first_stage == true) {
>  target_ulong mask, masked_msbs;
>
> -if (TARGET_LONG_BITS > (va_bits - 1)) {
> -mask = (1L << (TARGET_LONG_BITS - (va_bits - 1))) - 1;
> +if (sxlen > (va_bits - 1)) {
> +mask = (1L << (sxlen - (va_bits - 1))) - 1;
>  } else {
>  mask = 0;
>  }
> @@ -961,7 +963,7 @@ restart:
>
>  int pmp_prot;
>  int pmp_ret = get_physical_address_pmp(env, _prot, pte_addr,
> -   sizeof(target_ulong),
> +   sxlen_bytes,
> MMU_DATA_LOAD, PRV_S);
>  if (pmp_ret != TRANSLATE_SUCCESS) {
>  return TRANSLATE_PMP_FAIL;
> @@ -1113,7 +1115,7 @@ restart:
>   *   it is no longer valid and we must re-walk the page table.
>   */
>  MemoryRegion *mr;
> -hwaddr l = sizeof(target_ulong), addr1;
> +hwaddr l = sxlen_bytes, addr1;
>  mr = address_space_translate(cs->as, pte_addr, , ,
>   false, MEMTXATTRS_UNSPECIFIED);
>  if (memory_region_is_ram(mr)) {
> @@ -1126,6 +1128,11 @@ restart:
>  *pte_pa = pte = updated_pte;
>  #else
>  target_ulong old_pte = qatomic_cmpxchg(pte_pa, pte, updated_pte);

I think you missed removing this line

Alistair

> +if (riscv_cpu_sxl(env) == MXL_RV32) {
> +old_pte = qatomic_cmpxchg((uint32_t *)pte_pa, pte, 
> updated_pte);
> +} else {
> +old_pte = qatomic_cmpxchg(pte_pa, pte, updated_pte);
> +}
>  if (old_pte != pte) {
>  goto restart;
>  }
> --
> 2.43.0
>
>



Re: [PATCH 2/6] target/riscv: Adjust PMP size for no-MMU RV64 QEMU running RV32

2024-07-02 Thread Alistair Francis
On Mon, Jul 1, 2024 at 1:40 PM LIU Zhiwei  wrote:
>
> From: TANG Tiancheng 
>
> Ensure pmp_size is correctly determined using mxl for RV32
> in RV64 QEMU.
>
> Signed-off-by: TANG Tiancheng 
> Reviewed-by: Liu Zhiwei 

Reviewed-by: Alistair Francis 

Alistair

> ---
>  target/riscv/pmp.c | 2 +-
>  1 file changed, 1 insertion(+), 1 deletion(-)
>
> diff --git a/target/riscv/pmp.c b/target/riscv/pmp.c
> index 9eea397e72..f65aa3dba7 100644
> --- a/target/riscv/pmp.c
> +++ b/target/riscv/pmp.c
> @@ -326,7 +326,7 @@ bool pmp_hart_has_privs(CPURISCVState *env, hwaddr addr,
>   */
>  pmp_size = -(addr | TARGET_PAGE_MASK);
>  } else {
> -pmp_size = sizeof(target_ulong);
> +pmp_size = 2UL << riscv_cpu_mxl(env);
>  }
>  } else {
>  pmp_size = size;
> --
> 2.43.0
>
>



Re: [PATCH 1/6] target/riscv: Add fw_dynamic_info32 for booting RV32 OpenSBI

2024-07-02 Thread Alistair Francis
On Mon, Jul 1, 2024 at 1:40 PM LIU Zhiwei  wrote:
>
> From: TANG Tiancheng 
>
> RV32 OpenSBI need a fw_dynamic_info parameter with 32-bit fields instead
> of target_ulong.
>
> In RV64 QEMU, target_ulong is 64. So it is not right for booting RV32 OpenSBI.
> We create a fw_dynmaic_info32 struct for this purpose.
>
> Signed-off-by: TANG Tiancheng 
> Reviewed-by: Liu Zhiwei 

Reviewed-by: Alistair Francis 

Alistair

> ---
>  hw/riscv/boot.c | 35 ++---
>  hw/riscv/sifive_u.c |  3 ++-
>  include/hw/riscv/boot.h |  4 +++-
>  include/hw/riscv/boot_opensbi.h | 29 +++
>  4 files changed, 57 insertions(+), 14 deletions(-)
>
> diff --git a/hw/riscv/boot.c b/hw/riscv/boot.c
> index 47281ca853..1a2c1ff9e0 100644
> --- a/hw/riscv/boot.c
> +++ b/hw/riscv/boot.c
> @@ -342,27 +342,33 @@ void riscv_load_fdt(hwaddr fdt_addr, void *fdt)
>  rom_ptr_for_as(_space_memory, fdt_addr, 
> fdtsize));
>  }
>
> -void riscv_rom_copy_firmware_info(MachineState *machine, hwaddr rom_base,
> -  hwaddr rom_size, uint32_t reset_vec_size,
> +void riscv_rom_copy_firmware_info(MachineState *machine,
> +  RISCVHartArrayState *harts,
> +  hwaddr rom_base, hwaddr rom_size,
> +  uint32_t reset_vec_size,
>uint64_t kernel_entry)
>  {
> +struct fw_dynamic_info32 dinfo32;
>  struct fw_dynamic_info dinfo;
>  size_t dinfo_len;
>
> -if (sizeof(dinfo.magic) == 4) {
> -dinfo.magic = cpu_to_le32(FW_DYNAMIC_INFO_MAGIC_VALUE);
> -dinfo.version = cpu_to_le32(FW_DYNAMIC_INFO_VERSION);
> -dinfo.next_mode = cpu_to_le32(FW_DYNAMIC_INFO_NEXT_MODE_S);
> -dinfo.next_addr = cpu_to_le32(kernel_entry);
> +if (riscv_is_32bit(harts)) {
> +dinfo32.magic = cpu_to_le32(FW_DYNAMIC_INFO_MAGIC_VALUE);
> +dinfo32.version = cpu_to_le32(FW_DYNAMIC_INFO_VERSION);
> +dinfo32.next_mode = cpu_to_le32(FW_DYNAMIC_INFO_NEXT_MODE_S);
> +dinfo32.next_addr = cpu_to_le32(kernel_entry);
> +dinfo32.options = 0;
> +dinfo32.boot_hart = 0;
> +dinfo_len = sizeof(dinfo32);
>  } else {
>  dinfo.magic = cpu_to_le64(FW_DYNAMIC_INFO_MAGIC_VALUE);
>  dinfo.version = cpu_to_le64(FW_DYNAMIC_INFO_VERSION);
>  dinfo.next_mode = cpu_to_le64(FW_DYNAMIC_INFO_NEXT_MODE_S);
>  dinfo.next_addr = cpu_to_le64(kernel_entry);
> +dinfo.options = 0;
> +dinfo.boot_hart = 0;
> +dinfo_len = sizeof(dinfo);
>  }
> -dinfo.options = 0;
> -dinfo.boot_hart = 0;
> -dinfo_len = sizeof(dinfo);
>
>  /**
>   * copy the dynamic firmware info. This information is specific to
> @@ -374,7 +380,10 @@ void riscv_rom_copy_firmware_info(MachineState *machine, 
> hwaddr rom_base,
>  exit(1);
>  }
>
> -rom_add_blob_fixed_as("mrom.finfo", , dinfo_len,
> +rom_add_blob_fixed_as("mrom.finfo",
> +   riscv_is_32bit(harts) ?
> +   (void *) : (void *),
> +   dinfo_len,
> rom_base + reset_vec_size,
> _space_memory);
>  }
> @@ -430,7 +439,9 @@ void riscv_setup_rom_reset_vec(MachineState *machine, 
> RISCVHartArrayState *harts
>  }
>  rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
>rom_base, _space_memory);
> -riscv_rom_copy_firmware_info(machine, rom_base, rom_size, 
> sizeof(reset_vec),
> +riscv_rom_copy_firmware_info(machine, harts,
> + rom_base, rom_size,
> + sizeof(reset_vec),
>   kernel_entry);
>  }
>
> diff --git a/hw/riscv/sifive_u.c b/hw/riscv/sifive_u.c
> index af5f923f54..5010c3eadb 100644
> --- a/hw/riscv/sifive_u.c
> +++ b/hw/riscv/sifive_u.c
> @@ -646,7 +646,8 @@ static void sifive_u_machine_init(MachineState *machine)
>  rom_add_blob_fixed_as("mrom.reset", reset_vec, sizeof(reset_vec),
>memmap[SIFIVE_U_DEV_MROM].base, 
> _space_memory);
>
> -riscv_rom_copy_firmware_info(machine, memmap[SIFIVE_U_DEV_MROM].base,
> +riscv_rom_copy_firmware_info(machine, >soc.u_cpus,
> + memmap[SIFIVE_U_DEV_MROM].base,
>   memmap[SIFIVE_U_DEV_MROM].size,
>   sizeof(re

Re: [PATCH] disas/riscv: Add decode for Zawrs extension

2024-07-02 Thread Alistair Francis
On Wed, Jun 26, 2024 at 7:43 PM Rob Bradford  wrote:
>
> From: Balaji Ravikumar 
>
> Add disassembly support for these instructions from Zawrs:
>
> * wrs.sto
> * wrs.nto
>
> Signed-off-by: Balaji Ravikumar 
> Signed-off-by: Rob Bradford 

Thanks for the patch. Do you mind rebasing on
https://github.com/alistair23/qemu/tree/riscv-to-apply.next and
re-sending

Alistair

> ---
>  disas/riscv.c | 6 ++
>  1 file changed, 6 insertions(+)
>
> diff --git a/disas/riscv.c b/disas/riscv.c
> index 90d6b26de9..e79788ea0a 100644
> --- a/disas/riscv.c
> +++ b/disas/riscv.c
> @@ -906,6 +906,8 @@ typedef enum {
>  rv_op_amocas_w = 875,
>  rv_op_amocas_d = 876,
>  rv_op_amocas_q = 877,
> +rv_op_wrs_sto = 878,
> +rv_op_wrs_nto = 879,
>  } rv_op;
>
>  /* register names */
> @@ -2096,6 +2098,8 @@ const rv_opcode_data rvi_opcode_data[] = {
>  { "amocas.w", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
>  { "amocas.d", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
>  { "amocas.q", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
> +{ "wrs.sto", rv_codec_none, rv_fmt_none, NULL, 0, 0, 0 },
> +{ "wrs.nto", rv_codec_none, rv_fmt_none, NULL, 0, 0, 0 },
>  };
>
>  /* CSR names */
> @@ -3817,6 +3821,8 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa 
> isa)
>  case 0: op = rv_op_ecall; break;
>  case 32: op = rv_op_ebreak; break;
>  case 64: op = rv_op_uret; break;
> +case 416: op = rv_op_wrs_nto; break;
> +case 928: op = rv_op_wrs_sto; break;
>  }
>  break;
>  case 256:
> --
> 2.45.2
>
>



Re: [PATCH] disas/riscv: Add decode for Zawrs extension

2024-07-02 Thread Alistair Francis
On Wed, Jun 26, 2024 at 7:43 PM Rob Bradford  wrote:
>
> From: Balaji Ravikumar 
>
> Add disassembly support for these instructions from Zawrs:
>
> * wrs.sto
> * wrs.nto
>
> Signed-off-by: Balaji Ravikumar 
> Signed-off-by: Rob Bradford 

Acked-by: Alistair Francis 

Alistair

> ---
>  disas/riscv.c | 6 ++
>  1 file changed, 6 insertions(+)
>
> diff --git a/disas/riscv.c b/disas/riscv.c
> index 90d6b26de9..e79788ea0a 100644
> --- a/disas/riscv.c
> +++ b/disas/riscv.c
> @@ -906,6 +906,8 @@ typedef enum {
>  rv_op_amocas_w = 875,
>  rv_op_amocas_d = 876,
>  rv_op_amocas_q = 877,
> +rv_op_wrs_sto = 878,
> +rv_op_wrs_nto = 879,
>  } rv_op;
>
>  /* register names */
> @@ -2096,6 +2098,8 @@ const rv_opcode_data rvi_opcode_data[] = {
>  { "amocas.w", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
>  { "amocas.d", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
>  { "amocas.q", rv_codec_r_a, rv_fmt_aqrl_rd_rs2_rs1, NULL, 0, 0, 0 },
> +{ "wrs.sto", rv_codec_none, rv_fmt_none, NULL, 0, 0, 0 },
> +{ "wrs.nto", rv_codec_none, rv_fmt_none, NULL, 0, 0, 0 },
>  };
>
>  /* CSR names */
> @@ -3817,6 +3821,8 @@ static void decode_inst_opcode(rv_decode *dec, rv_isa 
> isa)
>  case 0: op = rv_op_ecall; break;
>  case 32: op = rv_op_ebreak; break;
>  case 64: op = rv_op_uret; break;
> +case 416: op = rv_op_wrs_nto; break;
> +case 928: op = rv_op_wrs_sto; break;
>  }
>  break;
>  case 256:
> --
> 2.45.2
>
>



Re: [PATCH v3 00/11] target/riscv: Support zimop/zcmop/zama16b/zabha

2024-07-02 Thread Alistair Francis
On Wed, Jul 3, 2024 at 11:48 AM LIU Zhiwei  wrote:
>
> All the patches in this patch set have been reviewed or acked.
>
> v2->v3:
> 1. Add review tags.
> 2. Reword the patch 10 in commit log
>
> v1->v2:
> 1. Fix the isa orders.
> 2. Make zimop/zcmop/zama16b/zabha depend on priviledged 1.13
> 3. Add review tags.
>
> The v2 patch set is here
> https://mail.gnu.org/archive/html/qemu-riscv/2024-06/msg00489.html
>
> The v1 patch set is here
> 1. zimop/zcmop
> https://mail.gnu.org/archive/html/qemu-riscv/2024-05/msg00207.html
> 2. zama16b
> https://mail.gnu.org/archive/html/qemu-riscv/2024-05/msg00212.html
> 3. zabha
> https://mail.gnu.org/archive/html/qemu-riscv/2024-05/msg00214.html
>
> LIU Zhiwei (11):
>   target/riscv: Add zimop extension
>   disas/riscv: Support zimop disassemble
>   target/riscv: Add zcmop extension
>   disas/riscv: Support zcmop disassemble
>   target/riscv: Support Zama16b extension
>   target/riscv: Move gen_amo before implement Zabha
>   target/riscv: Add AMO instructions for Zabha
>   target/riscv: Move gen_cmpxchg before adding amocas.[b|h]
>   target/riscv: Add amocas.[b|h] for Zabha
>   target/riscv: Expose zabha extension as a cpu property
>   disas/riscv: Support zabha disassemble

Thanks!

Applied to riscv-to-apply.next

Alistair

>
>  disas/riscv.c   | 183 
>  target/riscv/cpu.c  |   8 +
>  target/riscv/cpu_cfg.h  |   4 +
>  target/riscv/insn16.decode  |   1 +
>  target/riscv/insn32.decode  |  33 
>  target/riscv/insn_trans/trans_rva.c.inc |  51 ++
>  target/riscv/insn_trans/trans_rvd.c.inc |  14 +-
>  target/riscv/insn_trans/trans_rvf.c.inc |  14 +-
>  target/riscv/insn_trans/trans_rvi.c.inc |   6 +
>  target/riscv/insn_trans/trans_rvzabha.c.inc | 145 
>  target/riscv/insn_trans/trans_rvzacas.c.inc |  13 --
>  target/riscv/insn_trans/trans_rvzcmop.c.inc |  29 
>  target/riscv/insn_trans/trans_rvzimop.c.inc |  37 
>  target/riscv/tcg/tcg-cpu.c  |   5 +
>  target/riscv/translate.c|  38 
>  15 files changed, 531 insertions(+), 50 deletions(-)
>  create mode 100644 target/riscv/insn_trans/trans_rvzabha.c.inc
>  create mode 100644 target/riscv/insn_trans/trans_rvzcmop.c.inc
>  create mode 100644 target/riscv/insn_trans/trans_rvzimop.c.inc
>
> --
> 2.25.1
>
>



Re: [PATCH v7 07/11] target/riscv: Save counter values during countinhibit update

2024-07-02 Thread Alistair Francis
On Thu, Jun 27, 2024 at 9:58 AM Atish Patra  wrote:
>
> Currently, if a counter monitoring cycle/instret is stopped via
> mcountinhibit we just update the state while the value is saved
> during the next read. This is not accurate as the read may happen
> many cycles after the counter is stopped. Ideally, the read should
> return the value saved when the counter is stopped.
>
> Thus, save the value of the counter during the inhibit update
> operation and return that value during the read if corresponding bit
> in mcountihibit is set.
>
> Signed-off-by: Atish Patra 

Acked-by: Alistair Francis 

Alistair

> ---
>  target/riscv/cpu.h |  1 -
>  target/riscv/csr.c | 34 ++
>  target/riscv/machine.c |  5 ++---
>  3 files changed, 24 insertions(+), 16 deletions(-)
>
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index d56d640b06be..91fe2a46ba35 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -153,7 +153,6 @@ typedef struct PMUCTRState {
>  target_ulong mhpmcounter_prev;
>  /* Snapshort value of a counter in RV32 */
>  target_ulong mhpmcounterh_prev;
> -bool started;
>  /* Value beyond UINT32_MAX/UINT64_MAX before overflow interrupt trigger 
> */
>  target_ulong irq_overflow_left;
>  } PMUCTRState;
> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> index c292d036bcb2..e4adfa324efe 100644
> --- a/target/riscv/csr.c
> +++ b/target/riscv/csr.c
> @@ -1062,17 +1062,11 @@ static RISCVException 
> riscv_pmu_read_ctr(CPURISCVState *env, target_ulong *val,
>
>  if (get_field(env->mcountinhibit, BIT(ctr_idx))) {
>  /*
> - * Counter should not increment if inhibit bit is set. We can't 
> really
> - * stop the icount counting. Just return the counter value written by
> - * the supervisor to indicate that counter was not incremented.
> + * Counter should not increment if inhibit bit is set. Just return 
> the
> + * current counter value.
>   */
> -if (!counter->started) {
> -*val = ctr_val;
> -return RISCV_EXCP_NONE;
> -} else {
> -/* Mark that the counter has been stopped */
> -counter->started = false;
> -}
> + *val = ctr_val;
> + return RISCV_EXCP_NONE;
>  }
>
>  /*
> @@ -2114,9 +2108,25 @@ static RISCVException 
> write_mcountinhibit(CPURISCVState *env, int csrno,
>
>  /* Check if any other counter is also monitoring cycles/instructions */
>  for (cidx = 0; cidx < RV_MAX_MHPMCOUNTERS; cidx++) {
> -if (!get_field(env->mcountinhibit, BIT(cidx))) {
>  counter = >pmu_ctrs[cidx];
> -counter->started = true;
> +if (get_field(env->mcountinhibit, BIT(cidx)) && (val & BIT(cidx))) {
> +/*
> + * Update the counter value for cycle/instret as we can't stop 
> the
> + * host ticks. But we should show the current value at this 
> moment.
> + */
> +if (riscv_pmu_ctr_monitor_cycles(env, cidx) ||
> +riscv_pmu_ctr_monitor_instructions(env, cidx)) {
> +counter->mhpmcounter_val =
> +riscv_pmu_ctr_get_fixed_counters_val(env, cidx, false) -
> +   counter->mhpmcounter_prev +
> +   counter->mhpmcounter_val;
> +if (riscv_cpu_mxl(env) == MXL_RV32) {
> +counter->mhpmcounterh_val =
> +riscv_pmu_ctr_get_fixed_counters_val(env, cidx, 
> true) -
> +counter->mhpmcounterh_prev +
> +counter->mhpmcounterh_val;
> +}
> +}
>  }
>  }
>
> diff --git a/target/riscv/machine.c b/target/riscv/machine.c
> index 76f2150f78b5..492c2c6d9d79 100644
> --- a/target/riscv/machine.c
> +++ b/target/riscv/machine.c
> @@ -320,15 +320,14 @@ static bool pmu_needed(void *opaque)
>
>  static const VMStateDescription vmstate_pmu_ctr_state = {
>  .name = "cpu/pmu",
> -.version_id = 1,
> -.minimum_version_id = 1,
> +.version_id = 2,
> +.minimum_version_id = 2,
>  .needed = pmu_needed,
>  .fields = (const VMStateField[]) {
>  VMSTATE_UINTTL(mhpmcounter_val, PMUCTRState),
>  VMSTATE_UINTTL(mhpmcounterh_val, PMUCTRState),
>  VMSTATE_UINTTL(mhpmcounter_prev, PMUCTRState),
>  VMSTATE_UINTTL(mhpmcounterh_prev, PMUCTRState),
> -VMSTATE_BOOL(started, PMUCTRState),
>  VMSTATE_END_OF_LIST()
>  }
>  };
>
> --
> 2.34.1
>
>



Re: [PATCH v7 03/11] target/riscv: Add cycle & instret privilege mode filtering properties

2024-07-02 Thread Alistair Francis
On Thu, Jun 27, 2024 at 9:59 AM Atish Patra  wrote:
>
> From: Kaiwen Xue 
>
> This adds the properties for ISA extension smcntrpmf. Patches
> implementing it will follow.
>
> Signed-off-by: Atish Patra 
> Signed-off-by: Kaiwen Xue 
> ---
>  target/riscv/cpu.c | 2 ++
>  target/riscv/cpu_cfg.h | 1 +
>  2 files changed, 3 insertions(+)
>
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index 4760cb2cc17f..ef50130a91e7 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -178,6 +178,7 @@ const RISCVIsaExtData isa_edata_arr[] = {
>  ISA_EXT_DATA_ENTRY(zhinx, PRIV_VERSION_1_12_0, ext_zhinx),
>  ISA_EXT_DATA_ENTRY(zhinxmin, PRIV_VERSION_1_12_0, ext_zhinxmin),
>  ISA_EXT_DATA_ENTRY(smaia, PRIV_VERSION_1_12_0, ext_smaia),
> +ISA_EXT_DATA_ENTRY(smcntrpmf, PRIV_VERSION_1_12_0, ext_smcntrpmf),
>  ISA_EXT_DATA_ENTRY(smepmp, PRIV_VERSION_1_12_0, ext_smepmp),
>  ISA_EXT_DATA_ENTRY(smstateen, PRIV_VERSION_1_12_0, ext_smstateen),
>  ISA_EXT_DATA_ENTRY(ssaia, PRIV_VERSION_1_12_0, ext_ssaia),
> @@ -1467,6 +1468,7 @@ const char *riscv_get_misa_ext_description(uint32_t bit)
>  const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
>  /* Defaults for standard extensions */
>  MULTI_EXT_CFG_BOOL("sscofpmf", ext_sscofpmf, false),
> +MULTI_EXT_CFG_BOOL("smcntrpmf", ext_smcntrpmf, false),

Exposing the config should be at the end of the series. Implement then expose

Alistair

>  MULTI_EXT_CFG_BOOL("zifencei", ext_zifencei, true),
>  MULTI_EXT_CFG_BOOL("zicsr", ext_zicsr, true),
>  MULTI_EXT_CFG_BOOL("zihintntl", ext_zihintntl, true),
> diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h
> index fb7eebde523b..b1376beb1dab 100644
> --- a/target/riscv/cpu_cfg.h
> +++ b/target/riscv/cpu_cfg.h
> @@ -74,6 +74,7 @@ struct RISCVCPUConfig {
>  bool ext_ztso;
>  bool ext_smstateen;
>  bool ext_sstc;
> +bool ext_smcntrpmf;
>  bool ext_svadu;
>  bool ext_svinval;
>  bool ext_svnapot;
>
> --
> 2.34.1
>
>



Re: [PATCH v7 06/11] target/riscv: Implement privilege mode filtering for cycle/instret

2024-07-02 Thread Alistair Francis
On Thu, Jun 27, 2024 at 9:59 AM Atish Patra  wrote:
>
> Privilege mode filtering can also be emulated for cycle/instret by
> tracking host_ticks/icount during each privilege mode switch. This
> patch implements that for both cycle/instret and mhpmcounters. The
> first one requires Smcntrpmf while the other one requires Sscofpmf
> to be enabled.
>
> The cycle/instret are still computed using host ticks when icount
> is not enabled. Otherwise, they are computed using raw icount which
> is more accurate in icount mode.
>
> Co-Developed-by: Rajnesh Kanwal 
> Signed-off-by: Atish Patra 
> Signed-off-by: Rajnesh Kanwal 

Acked-by: Alistair Francis 

Alistair

> ---
>  target/riscv/cpu.h|  11 +
>  target/riscv/cpu_bits.h   |   5 ++
>  target/riscv/cpu_helper.c |   9 +++-
>  target/riscv/csr.c| 117 
> --
>  target/riscv/pmu.c|  92 
>  target/riscv/pmu.h|   2 +
>  6 files changed, 199 insertions(+), 37 deletions(-)
>
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index c5d289e5f4b9..d56d640b06be 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -158,6 +158,15 @@ typedef struct PMUCTRState {
>  target_ulong irq_overflow_left;
>  } PMUCTRState;
>
> +typedef struct PMUFixedCtrState {
> +/* Track cycle and icount for each privilege mode */
> +uint64_t counter[4];
> +uint64_t counter_prev[4];
> +/* Track cycle and icount for each privilege mode when V = 1*/
> +uint64_t counter_virt[2];
> +uint64_t counter_virt_prev[2];
> +} PMUFixedCtrState;
> +
>  struct CPUArchState {
>  target_ulong gpr[32];
>  target_ulong gprh[32]; /* 64 top bits of the 128-bit registers */
> @@ -354,6 +363,8 @@ struct CPUArchState {
>  /* PMU event selector configured values for RV32 */
>  target_ulong mhpmeventh_val[RV_MAX_MHPMEVENTS];
>
> +PMUFixedCtrState pmu_fixed_ctrs[2];
> +
>  target_ulong sscratch;
>  target_ulong mscratch;
>
> diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
> index 5faa817453bb..18f19615e4fe 100644
> --- a/target/riscv/cpu_bits.h
> +++ b/target/riscv/cpu_bits.h
> @@ -926,6 +926,11 @@ typedef enum RISCVException {
>  #define MHPMEVENT_BIT_VUINHBIT_ULL(58)
>  #define MHPMEVENTH_BIT_VUINH   BIT(26)
>
> +#define MHPMEVENT_FILTER_MASK  (MHPMEVENT_BIT_MINH  | \
> +MHPMEVENT_BIT_SINH  | \
> +MHPMEVENT_BIT_UINH  | \
> +MHPMEVENT_BIT_VSINH | \
> +MHPMEVENT_BIT_VUINH)
>  #define MHPMEVENT_SSCOF_MASK   _ULL(0x)
>  #define MHPMEVENT_IDX_MASK 0xF
>  #define MHPMEVENT_SSCOF_RESVD  16
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index 10d3fdaed376..395a1d914061 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -695,9 +695,14 @@ void riscv_cpu_set_mode(CPURISCVState *env, target_ulong 
> newpriv, bool virt_en)
>  {
>  g_assert(newpriv <= PRV_M && newpriv != PRV_RESERVED);
>
> -if (icount_enabled() && newpriv != env->priv) {
> -riscv_itrigger_update_priv(env);
> +if (newpriv != env->priv || env->virt_enabled != virt_en) {
> +if (icount_enabled()) {
> +riscv_itrigger_update_priv(env);
> +}
> +
> +riscv_pmu_update_fixed_ctrs(env, newpriv, virt_en);
>  }
> +
>  /* tlb_flush is unnecessary as mode is contained in mmu_idx */
>  env->priv = newpriv;
>  env->xl = cpu_recompute_xl(env);
> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> index 665c534db1a0..c292d036bcb2 100644
> --- a/target/riscv/csr.c
> +++ b/target/riscv/csr.c
> @@ -788,36 +788,16 @@ static RISCVException write_vcsr(CPURISCVState *env, 
> int csrno,
>  return RISCV_EXCP_NONE;
>  }
>
> +#if defined(CONFIG_USER_ONLY)
>  /* User Timers and Counters */
> -static target_ulong get_ticks(bool shift, bool instructions)
> +static target_ulong get_ticks(bool shift)
>  {
> -int64_t val;
> -target_ulong result;
> -
> -#if !defined(CONFIG_USER_ONLY)
> -if (icount_enabled()) {
> -if (instructions) {
> -val = icount_get_raw();
> -} else {
> -val = icount_get();
> -}
> -} else {
> -val = cpu_get_host_ticks();
> -}
> -#else
> -val = cpu_get_host_ticks();
> -#endif
> -
> - 

Re: [PATCH v7 05/11] target/riscv: Add cycle & instret privilege mode filtering support

2024-07-02 Thread Alistair Francis
On Thu, Jun 27, 2024 at 10:00 AM Atish Patra  wrote:
>
> From: Kaiwen Xue 
>
> QEMU only calculates dummy cycles and instructions, so there is no
> actual means to stop the icount in QEMU. Hence this patch merely adds
> the functionality of accessing the cfg registers, and cause no actual
> effects on the counting of cycle and instret counters.
>
> Signed-off-by: Atish Patra 
> Reviewed-by: Daniel Henrique Barboza 
> Signed-off-by: Kaiwen Xue 
> ---
>  target/riscv/csr.c | 88 
> ++
>  1 file changed, 88 insertions(+)
>
> diff --git a/target/riscv/csr.c b/target/riscv/csr.c
> index 3ad851707e5c..665c534db1a0 100644
> --- a/target/riscv/csr.c
> +++ b/target/riscv/csr.c
> @@ -236,6 +236,24 @@ static RISCVException sscofpmf_32(CPURISCVState *env, 
> int csrno)
>  return sscofpmf(env, csrno);
>  }
>
> +static RISCVException smcntrpmf(CPURISCVState *env, int csrno)
> +{
> +if (!riscv_cpu_cfg(env)->ext_smcntrpmf) {
> +return RISCV_EXCP_ILLEGAL_INST;
> +}
> +
> +return RISCV_EXCP_NONE;
> +}
> +
> +static RISCVException smcntrpmf_32(CPURISCVState *env, int csrno)
> +{
> +if (riscv_cpu_mxl(env) != MXL_RV32) {
> +return RISCV_EXCP_ILLEGAL_INST;
> +}
> +
> +return smcntrpmf(env, csrno);
> +}
> +
>  static RISCVException any(CPURISCVState *env, int csrno)
>  {
>  return RISCV_EXCP_NONE;
> @@ -830,6 +848,62 @@ static RISCVException read_hpmcounterh(CPURISCVState 
> *env, int csrno,
>
>  #else /* CONFIG_USER_ONLY */
>
> +static RISCVException read_mcyclecfg(CPURISCVState *env, int csrno,
> + target_ulong *val)
> +{
> +*val = env->mcyclecfg;

We don't do a good job of this in other places, but we should check
for RVU and RVS to determine if the bits can actually be set.

This is especially important for Hypervisor support (VS/VU-modes), as
that is often not supported so we should report that here

Alistair

> +return RISCV_EXCP_NONE;
> +}
> +
> +static RISCVException write_mcyclecfg(CPURISCVState *env, int csrno,
> +  target_ulong val)
> +{
> +env->mcyclecfg = val;
> +return RISCV_EXCP_NONE;
> +}
> +
> +static RISCVException read_mcyclecfgh(CPURISCVState *env, int csrno,
> +  target_ulong *val)
> +{
> +*val = env->mcyclecfgh;
> +return RISCV_EXCP_NONE;
> +}
> +
> +static RISCVException write_mcyclecfgh(CPURISCVState *env, int csrno,
> +   target_ulong val)
> +{
> +env->mcyclecfgh = val;
> +return RISCV_EXCP_NONE;
> +}
> +
> +static RISCVException read_minstretcfg(CPURISCVState *env, int csrno,
> +   target_ulong *val)
> +{
> +*val = env->minstretcfg;
> +return RISCV_EXCP_NONE;
> +}
> +
> +static RISCVException write_minstretcfg(CPURISCVState *env, int csrno,
> +target_ulong val)
> +{
> +env->minstretcfg = val;
> +return RISCV_EXCP_NONE;
> +}
> +
> +static RISCVException read_minstretcfgh(CPURISCVState *env, int csrno,
> +target_ulong *val)
> +{
> +*val = env->minstretcfgh;
> +return RISCV_EXCP_NONE;
> +}
> +
> +static RISCVException write_minstretcfgh(CPURISCVState *env, int csrno,
> + target_ulong val)
> +{
> +env->minstretcfgh = val;
> +return RISCV_EXCP_NONE;
> +}
> +
>  static RISCVException read_mhpmevent(CPURISCVState *env, int csrno,
>   target_ulong *val)
>  {
> @@ -5051,6 +5125,13 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
>   write_mcountinhibit,
>   .min_priv_ver = PRIV_VERSION_1_11_0   },
>
> +[CSR_MCYCLECFG]  = { "mcyclecfg",   smcntrpmf, read_mcyclecfg,
> + write_mcyclecfg,
> + .min_priv_ver = PRIV_VERSION_1_12_0   },
> +[CSR_MINSTRETCFG]= { "minstretcfg", smcntrpmf, read_minstretcfg,
> + write_minstretcfg,
> + .min_priv_ver = PRIV_VERSION_1_12_0   },
> +
>  [CSR_MHPMEVENT3] = { "mhpmevent3", any,read_mhpmevent,
>   write_mhpmevent   },
>  [CSR_MHPMEVENT4] = { "mhpmevent4", any,read_mhpmevent,
> @@ -5110,6 +5191,13 @@ riscv_csr_operations csr_ops[CSR_TABLE_SIZE] = {
>  [CSR_MHPMEVENT31]= { "mhpmevent31",any,read_mhpmevent,
>   write_mhpmevent   },
>
> +[CSR_MCYCLECFGH] = { "mcyclecfgh",   smcntrpmf_32, read_mcyclecfgh,
> + write_mcyclecfgh,
> + .min_priv_ver = PRIV_VERSION_1_12_0},
> +[CSR_MINSTRETCFGH]   = { "minstretcfgh", smcntrpmf_32, read_minstretcfgh,
> + 

Re: [PATCH v7 04/11] target/riscv: Add cycle & instret privilege mode filtering definitions

2024-07-02 Thread Alistair Francis
On Thu, Jun 27, 2024 at 9:58 AM Atish Patra  wrote:
>
> From: Kaiwen Xue 
>
> This adds the definitions for ISA extension smcntrpmf.
>
> Signed-off-by: Kaiwen Xue 
> Reviewed-by: Daniel Henrique Barboza 
> Signed-off-by: Atish Patra 

Reviewed-by: Alistair Francis 

Alistair

> ---
>  target/riscv/cpu.h  |  6 ++
>  target/riscv/cpu_bits.h | 29 +
>  2 files changed, 35 insertions(+)
>
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index 46faefd24e09..c5d289e5f4b9 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -339,6 +339,12 @@ struct CPUArchState {
>
>  uint32_t mcountinhibit;
>
> +/* PMU cycle & instret privilege mode filtering */
> +target_ulong mcyclecfg;
> +target_ulong mcyclecfgh;
> +target_ulong minstretcfg;
> +target_ulong minstretcfgh;
> +
>  /* PMU counter state */
>  PMUCTRState pmu_ctrs[RV_MAX_MHPMCOUNTERS];
>
> diff --git a/target/riscv/cpu_bits.h b/target/riscv/cpu_bits.h
> index c257c5ed7dc9..5faa817453bb 100644
> --- a/target/riscv/cpu_bits.h
> +++ b/target/riscv/cpu_bits.h
> @@ -397,6 +397,10 @@
>  /* Machine counter-inhibit register */
>  #define CSR_MCOUNTINHIBIT   0x320
>
> +/* Machine counter configuration registers */
> +#define CSR_MCYCLECFG   0x321
> +#define CSR_MINSTRETCFG 0x322
> +
>  #define CSR_MHPMEVENT3  0x323
>  #define CSR_MHPMEVENT4  0x324
>  #define CSR_MHPMEVENT5  0x325
> @@ -427,6 +431,9 @@
>  #define CSR_MHPMEVENT30 0x33e
>  #define CSR_MHPMEVENT31 0x33f
>
> +#define CSR_MCYCLECFGH  0x721
> +#define CSR_MINSTRETCFGH0x722
> +
>  #define CSR_MHPMEVENT3H 0x723
>  #define CSR_MHPMEVENT4H 0x724
>  #define CSR_MHPMEVENT5H 0x725
> @@ -884,6 +891,28 @@ typedef enum RISCVException {
>  /* PMU related bits */
>  #define MIE_LCOFIE (1 << IRQ_PMU_OVF)
>
> +#define MCYCLECFG_BIT_MINH BIT_ULL(62)
> +#define MCYCLECFGH_BIT_MINHBIT(30)
> +#define MCYCLECFG_BIT_SINH BIT_ULL(61)
> +#define MCYCLECFGH_BIT_SINHBIT(29)
> +#define MCYCLECFG_BIT_UINH BIT_ULL(60)
> +#define MCYCLECFGH_BIT_UINHBIT(28)
> +#define MCYCLECFG_BIT_VSINHBIT_ULL(59)
> +#define MCYCLECFGH_BIT_VSINH   BIT(27)
> +#define MCYCLECFG_BIT_VUINHBIT_ULL(58)
> +#define MCYCLECFGH_BIT_VUINH   BIT(26)
> +
> +#define MINSTRETCFG_BIT_MINH   BIT_ULL(62)
> +#define MINSTRETCFGH_BIT_MINH  BIT(30)
> +#define MINSTRETCFG_BIT_SINH   BIT_ULL(61)
> +#define MINSTRETCFGH_BIT_SINH  BIT(29)
> +#define MINSTRETCFG_BIT_UINH   BIT_ULL(60)
> +#define MINSTRETCFGH_BIT_UINH  BIT(28)
> +#define MINSTRETCFG_BIT_VSINH  BIT_ULL(59)
> +#define MINSTRETCFGH_BIT_VSINH BIT(27)
> +#define MINSTRETCFG_BIT_VUINH  BIT_ULL(58)
> +#define MINSTRETCFGH_BIT_VUINH BIT(26)
> +
>  #define MHPMEVENT_BIT_OF   BIT_ULL(63)
>  #define MHPMEVENTH_BIT_OF  BIT(31)
>  #define MHPMEVENT_BIT_MINH BIT_ULL(62)
>
> --
> 2.34.1
>
>



Re: [PATCH v7 01/11] target/riscv: Combine set_mode and set_virt functions.

2024-07-02 Thread Alistair Francis
On Thu, Jun 27, 2024 at 10:02 AM Atish Patra  wrote:
>
> From: Rajnesh Kanwal 
>
> Combining riscv_cpu_set_virt_enabled() and riscv_cpu_set_mode()
> functions. This is to make complete mode change information
> available through a single function.
>
> This allows to easily differentiate between HS->VS, VS->HS
> and VS->VS transitions when executing state update codes.
> For example: One use-case which inspired this change is
> to update mode-specific instruction and cycle counters
> which requires information of both prev mode and current
> mode.
>
> Signed-off-by: Rajnesh Kanwal 

Reviewed-by: Alistair Francis 

Alistair

> ---
>  target/riscv/cpu.h|  2 +-
>  target/riscv/cpu_helper.c | 57 
> +++
>  target/riscv/op_helper.c  | 17 +-
>  3 files changed, 35 insertions(+), 41 deletions(-)
>
> diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h
> index 90b8f1b08f83..46faefd24e09 100644
> --- a/target/riscv/cpu.h
> +++ b/target/riscv/cpu.h
> @@ -544,7 +544,7 @@ void riscv_cpu_set_aia_ireg_rmw_fn(CPURISCVState *env, 
> uint32_t priv,
>  RISCVException smstateen_acc_ok(CPURISCVState *env, int index, uint64_t bit);
>  #endif /* !CONFIG_USER_ONLY */
>
> -void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv);
> +void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv, bool 
> virt_en);
>
>  void riscv_translate_init(void);
>  G_NORETURN void riscv_raise_exception(CPURISCVState *env,
> diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c
> index 6709622dd3ab..10d3fdaed376 100644
> --- a/target/riscv/cpu_helper.c
> +++ b/target/riscv/cpu_helper.c
> @@ -619,30 +619,6 @@ void riscv_cpu_set_geilen(CPURISCVState *env, 
> target_ulong geilen)
>  env->geilen = geilen;
>  }
>
> -/* This function can only be called to set virt when RVH is enabled */
> -void riscv_cpu_set_virt_enabled(CPURISCVState *env, bool enable)
> -{
> -/* Flush the TLB on all virt mode changes. */
> -if (env->virt_enabled != enable) {
> -tlb_flush(env_cpu(env));
> -}
> -
> -env->virt_enabled = enable;
> -
> -if (enable) {
> -/*
> - * The guest external interrupts from an interrupt controller are
> - * delivered only when the Guest/VM is running (i.e. V=1). This means
> - * any guest external interrupt which is triggered while the Guest/VM
> - * is not running (i.e. V=0) will be missed on QEMU resulting in 
> guest
> - * with sluggish response to serial console input and other I/O 
> events.
> - *
> - * To solve this, we check and inject interrupt after setting V=1.
> - */
> -riscv_cpu_update_mip(env, 0, 0);
> -}
> -}
> -
>  int riscv_cpu_claim_interrupts(RISCVCPU *cpu, uint64_t interrupts)
>  {
>  CPURISCVState *env = >env;
> @@ -715,7 +691,7 @@ void riscv_cpu_set_aia_ireg_rmw_fn(CPURISCVState *env, 
> uint32_t priv,
>  }
>  }
>
> -void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv)
> +void riscv_cpu_set_mode(CPURISCVState *env, target_ulong newpriv, bool 
> virt_en)
>  {
>  g_assert(newpriv <= PRV_M && newpriv != PRV_RESERVED);
>
> @@ -736,6 +712,28 @@ void riscv_cpu_set_mode(CPURISCVState *env, target_ulong 
> newpriv)
>   * preemptive context switch. As a result, do both.
>   */
>  env->load_res = -1;
> +
> +if (riscv_has_ext(env, RVH)) {
> +/* Flush the TLB on all virt mode changes. */
> +if (env->virt_enabled != virt_en) {
> +tlb_flush(env_cpu(env));
> +}
> +
> +env->virt_enabled = virt_en;
> +if (virt_en) {
> +/*
> + * The guest external interrupts from an interrupt controller are
> + * delivered only when the Guest/VM is running (i.e. V=1). This
> + * means any guest external interrupt which is triggered while 
> the
> + * Guest/VM is not running (i.e. V=0) will be missed on QEMU
> + * resulting in guest with sluggish response to serial console
> + * input and other I/O events.
> + *
> + * To solve this, we check and inject interrupt after setting 
> V=1.
> + */
> +riscv_cpu_update_mip(env, 0, 0);
> +}
> +}
>  }
>
>  /*
> @@ -1648,6 +1646,7 @@ void riscv_cpu_do_interrupt(CPUState *cs)
>  {
>  RISCVCPU *cpu = RISCV_CPU(cs);
>  CPURISCVState *env = >env;
> +bool virt = env->virt_enabled;
>  bool write_gva = false;
>  uint64_t s;
>
> @@ -1778,7 +1777,7 @@ voi

Re: [PATCH v2 10/11] target/riscv: Enable zabha for max cpu

2024-07-02 Thread Alistair Francis
On Sun, Jun 30, 2024 at 1:13 PM LIU Zhiwei  wrote:
>
> Signed-off-by: LIU Zhiwei 

This isn't really max CPU specific, it's just exposing the extension.
Do you mind updating the title?

Otherwise

Reviewed-by: Alistair Francis 

Alistair

> ---
>  target/riscv/cpu.c | 2 ++
>  1 file changed, 2 insertions(+)
>
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index 5219b44176..8cd52e6801 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -117,6 +117,7 @@ const RISCVIsaExtData isa_edata_arr[] = {
>  ISA_EXT_DATA_ENTRY(zmmul, PRIV_VERSION_1_12_0, ext_zmmul),
>  ISA_EXT_DATA_ENTRY(za64rs, PRIV_VERSION_1_12_0, has_priv_1_11),
>  ISA_EXT_DATA_ENTRY(zaamo, PRIV_VERSION_1_12_0, ext_zaamo),
> +ISA_EXT_DATA_ENTRY(zabha, PRIV_VERSION_1_13_0, ext_zabha),
>  ISA_EXT_DATA_ENTRY(zacas, PRIV_VERSION_1_12_0, ext_zacas),
>  ISA_EXT_DATA_ENTRY(zama16b, PRIV_VERSION_1_13_0, ext_zama16b),
>  ISA_EXT_DATA_ENTRY(zalrsc, PRIV_VERSION_1_12_0, ext_zalrsc),
> @@ -1478,6 +1479,7 @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
>  MULTI_EXT_CFG_BOOL("zcmop", ext_zcmop, false),
>  MULTI_EXT_CFG_BOOL("zacas", ext_zacas, false),
>  MULTI_EXT_CFG_BOOL("zama16b", ext_zama16b, false),
> +MULTI_EXT_CFG_BOOL("zabha", ext_zabha, false),
>  MULTI_EXT_CFG_BOOL("zaamo", ext_zaamo, false),
>  MULTI_EXT_CFG_BOOL("zalrsc", ext_zalrsc, false),
>  MULTI_EXT_CFG_BOOL("zawrs", ext_zawrs, true),
> --
> 2.25.1
>
>



Re: [PATCH v2 05/11] target/riscv: Support Zama16b extension

2024-07-02 Thread Alistair Francis
On Sun, Jun 30, 2024 at 1:11 PM LIU Zhiwei  wrote:
>
> Zama16b is the property that misaligned load/stores/atomics within
> a naturally aligned 16-byte region are atomic.
>
> According to the specification, Zama16b applies only to AMOs, loads
> and stores defined in the base ISAs, and loads and stores of no more
> than XLEN bits defined in the F, D, and Q extensions. Thus it should
> not apply to zacas or RVC instructions.
>
> For an instruction in that set, if all accessed bytes lie within 16B granule,
> the instruction will not raise an exception for reasons of address alignment,
> and the instruction will give rise to only one memory operation for the
> purposes of RVWMO—i.e., it will execute atomically.
>
> Signed-off-by: LIU Zhiwei 

Reviewed-by: Alistair Francis 

Alistair

> ---
>  target/riscv/cpu.c  |  2 ++
>  target/riscv/cpu_cfg.h  |  1 +
>  target/riscv/insn_trans/trans_rva.c.inc | 42 ++---
>  target/riscv/insn_trans/trans_rvd.c.inc | 14 +++--
>  target/riscv/insn_trans/trans_rvf.c.inc | 14 +++--
>  target/riscv/insn_trans/trans_rvi.c.inc |  6 
>  6 files changed, 57 insertions(+), 22 deletions(-)
>
> diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c
> index 1d1402775a..5219b44176 100644
> --- a/target/riscv/cpu.c
> +++ b/target/riscv/cpu.c
> @@ -118,6 +118,7 @@ const RISCVIsaExtData isa_edata_arr[] = {
>  ISA_EXT_DATA_ENTRY(za64rs, PRIV_VERSION_1_12_0, has_priv_1_11),
>  ISA_EXT_DATA_ENTRY(zaamo, PRIV_VERSION_1_12_0, ext_zaamo),
>  ISA_EXT_DATA_ENTRY(zacas, PRIV_VERSION_1_12_0, ext_zacas),
> +ISA_EXT_DATA_ENTRY(zama16b, PRIV_VERSION_1_13_0, ext_zama16b),
>  ISA_EXT_DATA_ENTRY(zalrsc, PRIV_VERSION_1_12_0, ext_zalrsc),
>  ISA_EXT_DATA_ENTRY(zawrs, PRIV_VERSION_1_12_0, ext_zawrs),
>  ISA_EXT_DATA_ENTRY(zfa, PRIV_VERSION_1_12_0, ext_zfa),
> @@ -1476,6 +1477,7 @@ const RISCVCPUMultiExtConfig riscv_cpu_extensions[] = {
>  MULTI_EXT_CFG_BOOL("zimop", ext_zimop, false),
>  MULTI_EXT_CFG_BOOL("zcmop", ext_zcmop, false),
>  MULTI_EXT_CFG_BOOL("zacas", ext_zacas, false),
> +MULTI_EXT_CFG_BOOL("zama16b", ext_zama16b, false),
>  MULTI_EXT_CFG_BOOL("zaamo", ext_zaamo, false),
>  MULTI_EXT_CFG_BOOL("zalrsc", ext_zalrsc, false),
>  MULTI_EXT_CFG_BOOL("zawrs", ext_zawrs, true),
> diff --git a/target/riscv/cpu_cfg.h b/target/riscv/cpu_cfg.h
> index d85e54b475..ddbfae37e5 100644
> --- a/target/riscv/cpu_cfg.h
> +++ b/target/riscv/cpu_cfg.h
> @@ -83,6 +83,7 @@ struct RISCVCPUConfig {
>  bool ext_zdinx;
>  bool ext_zaamo;
>  bool ext_zacas;
> +bool ext_zama16b;
>  bool ext_zalrsc;
>  bool ext_zawrs;
>  bool ext_zfa;
> diff --git a/target/riscv/insn_trans/trans_rva.c.inc 
> b/target/riscv/insn_trans/trans_rva.c.inc
> index 4a9e4591d1..eb080baddd 100644
> --- a/target/riscv/insn_trans/trans_rva.c.inc
> +++ b/target/riscv/insn_trans/trans_rva.c.inc
> @@ -103,6 +103,12 @@ static bool gen_amo(DisasContext *ctx, arg_atomic *a,
>  TCGv dest = dest_gpr(ctx, a->rd);
>  TCGv src1, src2 = get_gpr(ctx, a->rs2, EXT_NONE);
>
> +if (ctx->cfg_ptr->ext_zama16b) {
> +mop |= MO_ATOM_WITHIN16;
> +} else {
> +mop |= MO_ALIGN;
> +}
> +
>  decode_save_opc(ctx);
>  src1 = get_address(ctx, a->rs1, 0);
>  func(dest, src1, src2, ctx->mem_idx, mop);
> @@ -126,55 +132,55 @@ static bool trans_sc_w(DisasContext *ctx, arg_sc_w *a)
>  static bool trans_amoswap_w(DisasContext *ctx, arg_amoswap_w *a)
>  {
>  REQUIRE_A_OR_ZAAMO(ctx);
> -return gen_amo(ctx, a, _gen_atomic_xchg_tl, (MO_ALIGN | MO_TESL));
> +return gen_amo(ctx, a, _gen_atomic_xchg_tl, MO_TESL);
>  }
>
>  static bool trans_amoadd_w(DisasContext *ctx, arg_amoadd_w *a)
>  {
>  REQUIRE_A_OR_ZAAMO(ctx);
> -return gen_amo(ctx, a, _gen_atomic_fetch_add_tl, (MO_ALIGN | 
> MO_TESL));
> +return gen_amo(ctx, a, _gen_atomic_fetch_add_tl, MO_TESL);
>  }
>
>  static bool trans_amoxor_w(DisasContext *ctx, arg_amoxor_w *a)
>  {
>  REQUIRE_A_OR_ZAAMO(ctx);
> -return gen_amo(ctx, a, _gen_atomic_fetch_xor_tl, (MO_ALIGN | 
> MO_TESL));
> +return gen_amo(ctx, a, _gen_atomic_fetch_xor_tl, MO_TESL);
>  }
>
>  static bool trans_amoand_w(DisasContext *ctx, arg_amoand_w *a)
>  {
>  REQUIRE_A_OR_ZAAMO(ctx);
> -return gen_amo(ctx, a, _gen_atomic_fetch_and_tl, (MO_ALIGN | 
> MO_TESL));
> +return gen_amo(ctx, a, _gen_atomic_fetch_and_tl, MO_TESL);
>  }
>
>  static bool trans_amoor_w(DisasContext *ctx, arg_amoor_w *a)
>  {
>  REQUIRE_A_OR_ZAAMO(ctx);
> - 

Re: [PATCH 3/3] util/cpuinfo-riscv: Use linux __riscv_hwprobe syscall

2024-07-02 Thread Alistair Francis
On Fri, Jun 28, 2024 at 4:06 AM Richard Henderson
 wrote:
>
> With recent linux kernels, there is a syscall to probe for various
> ISA extensions.  These bits were phased in over several kernel
> releases, so we still require checks for symbol availability.
>
> Signed-off-by: Richard Henderson 

Acked-by: Alistair Francis 

Alistair

> ---
>  meson.build  |  6 ++
>  util/cpuinfo-riscv.c | 26 ++
>  2 files changed, 32 insertions(+)
>
> diff --git a/meson.build b/meson.build
> index 97e00d6f59..58afd0125d 100644
> --- a/meson.build
> +++ b/meson.build
> @@ -2837,6 +2837,12 @@ have_cpuid_h = cc.links('''
>}''')
>  config_host_data.set('CONFIG_CPUID_H', have_cpuid_h)
>
> +# Don't bother to advertise asm/hwprobe.h for old versions that do
> +# not contain RISCV_HWPROBE_EXT_ZBA.
> +config_host_data.set('CONFIG_ASM_HWPROBE_H',
> + cc.has_header_symbol('asm/hwprobe.h',
> +  'RISCV_HWPROBE_EXT_ZBA'))
> +
>  config_host_data.set('CONFIG_AVX2_OPT', get_option('avx2') \
>.require(have_cpuid_h, error_message: 'cpuid.h not available, cannot 
> enable AVX2') \
>.require(cc.links('''
> diff --git a/util/cpuinfo-riscv.c b/util/cpuinfo-riscv.c
> index abf799794f..cf59ce83a3 100644
> --- a/util/cpuinfo-riscv.c
> +++ b/util/cpuinfo-riscv.c
> @@ -6,6 +6,11 @@
>  #include "qemu/osdep.h"
>  #include "host/cpuinfo.h"
>
> +#ifdef CONFIG_ASM_HWPROBE_H
> +#include 
> +#include 
> +#endif
> +
>  unsigned cpuinfo;
>  static volatile sig_atomic_t got_sigill;
>
> @@ -47,6 +52,27 @@ unsigned __attribute__((constructor)) cpuinfo_init(void)
>  #endif
>  left &= ~info;
>
> +#ifdef CONFIG_ASM_HWPROBE_H
> +if (left) {
> +/*
> + * TODO: glibc 2.40 will introduce , which
> + * provides __riscv_hwprobe and __riscv_hwprobe_one,
> + * which is a slightly cleaner interface.
> + */
> +struct riscv_hwprobe pair = { .key = RISCV_HWPROBE_KEY_IMA_EXT_0 };
> +if (syscall(__NR_riscv_hwprobe, , 1, 0, NULL, 0) == 0
> +&& pair.key >= 0) {
> +info |= pair.value & RISCV_HWPROBE_EXT_ZBA ? CPUINFO_ZBA : 0;
> +info |= pair.value & RISCV_HWPROBE_EXT_ZBB ? CPUINFO_ZBB : 0;
> +left &= ~(CPUINFO_ZBA | CPUINFO_ZBB);
> +#ifdef RISCV_HWPROBE_EXT_ZICOND
> +info |= pair.value & RISCV_HWPROBE_EXT_ZICOND ? CPUINFO_ZICOND : 
> 0;
> +left &= ~CPUINFO_ZICOND;
> +#endif
> +}
> +}
> +#endif /* CONFIG_ASM_HWPROBE_H */
> +
>  if (left) {
>  struct sigaction sa_old, sa_new;
>
> --
> 2.34.1
>
>



Re: [PATCH 2/3] util/cpuinfo-riscv: Support OpenBSD signal frame

2024-07-02 Thread Alistair Francis
On Fri, Jun 28, 2024 at 4:06 AM Richard Henderson
 wrote:
>
> Reported-by: Brad Smith 
> Signed-off-by: Richard Henderson 

Acked-by: Alistair Francis 

Alistair

> ---
>  util/cpuinfo-riscv.c | 7 +++
>  1 file changed, 7 insertions(+)
>
> diff --git a/util/cpuinfo-riscv.c b/util/cpuinfo-riscv.c
> index 6b97100620..abf799794f 100644
> --- a/util/cpuinfo-riscv.c
> +++ b/util/cpuinfo-riscv.c
> @@ -13,7 +13,14 @@ static void sigill_handler(int signo, siginfo_t *si, void 
> *data)
>  {
>  /* Skip the faulty instruction */
>  ucontext_t *uc = (ucontext_t *)data;
> +
> +#ifdef __linux__
>  uc->uc_mcontext.__gregs[REG_PC] += 4;
> +#elif defined(__OpenBSD__)
> +uc->sc_sepc += 4;
> +#else
> +# error Unsupported OS
> +#endif
>
>  got_sigill = 1;
>  }
> --
> 2.34.1
>
>



Re: [PATCH 1/3] util/cpuinfo-riscv: Support host/cpuinfo.h for riscv

2024-07-02 Thread Alistair Francis
On Fri, Jun 28, 2024 at 4:06 AM Richard Henderson
 wrote:
>
> Move detection code out of tcg, similar to other hosts.
>
> Signed-off-by: Richard Henderson 

Reviewed-by: Alistair Francis 

Alistair

> ---
>  host/include/riscv/host/cpuinfo.h | 23 +
>  tcg/riscv/tcg-target.h| 46 -
>  util/cpuinfo-riscv.c  | 85 +++
>  tcg/riscv/tcg-target.c.inc| 84 +++---
>  util/meson.build  |  2 +
>  5 files changed, 139 insertions(+), 101 deletions(-)
>  create mode 100644 host/include/riscv/host/cpuinfo.h
>  create mode 100644 util/cpuinfo-riscv.c
>
> diff --git a/host/include/riscv/host/cpuinfo.h 
> b/host/include/riscv/host/cpuinfo.h
> new file mode 100644
> index 00..2b00660e36
> --- /dev/null
> +++ b/host/include/riscv/host/cpuinfo.h
> @@ -0,0 +1,23 @@
> +/*
> + * SPDX-License-Identifier: GPL-2.0-or-later
> + * Host specific cpu identification for RISC-V.
> + */
> +
> +#ifndef HOST_CPUINFO_H
> +#define HOST_CPUINFO_H
> +
> +#define CPUINFO_ALWAYS  (1u << 0)  /* so cpuinfo is nonzero */
> +#define CPUINFO_ZBA (1u << 1)
> +#define CPUINFO_ZBB (1u << 2)
> +#define CPUINFO_ZICOND  (1u << 3)
> +
> +/* Initialized with a constructor. */
> +extern unsigned cpuinfo;
> +
> +/*
> + * We cannot rely on constructor ordering, so other constructors must
> + * use the function interface rather than the variable above.
> + */
> +unsigned cpuinfo_init(void);
> +
> +#endif /* HOST_CPUINFO_H */
> diff --git a/tcg/riscv/tcg-target.h b/tcg/riscv/tcg-target.h
> index 2c1b680b93..1a347eaf6e 100644
> --- a/tcg/riscv/tcg-target.h
> +++ b/tcg/riscv/tcg-target.h
> @@ -25,6 +25,8 @@
>  #ifndef RISCV_TCG_TARGET_H
>  #define RISCV_TCG_TARGET_H
>
> +#include "host/cpuinfo.h"
> +
>  #define TCG_TARGET_INSN_UNIT_SIZE 4
>  #define TCG_TARGET_NB_REGS 32
>  #define MAX_CODE_GEN_BUFFER_SIZE  ((size_t)-1)
> @@ -80,18 +82,12 @@ typedef enum {
>  #define TCG_TARGET_CALL_ARG_I128TCG_CALL_ARG_NORMAL
>  #define TCG_TARGET_CALL_RET_I128TCG_CALL_RET_NORMAL
>
> -#if defined(__riscv_arch_test) && defined(__riscv_zbb)
> -# define have_zbb true
> -#else
> -extern bool have_zbb;
> -#endif
> -
>  /* optional instructions */
>  #define TCG_TARGET_HAS_negsetcond_i32   1
>  #define TCG_TARGET_HAS_div_i32  1
>  #define TCG_TARGET_HAS_rem_i32  1
>  #define TCG_TARGET_HAS_div2_i32 0
> -#define TCG_TARGET_HAS_rot_i32  have_zbb
> +#define TCG_TARGET_HAS_rot_i32  (cpuinfo & CPUINFO_ZBB)
>  #define TCG_TARGET_HAS_deposit_i32  0
>  #define TCG_TARGET_HAS_extract_i32  0
>  #define TCG_TARGET_HAS_sextract_i32 0
> @@ -106,17 +102,17 @@ extern bool have_zbb;
>  #define TCG_TARGET_HAS_ext16s_i32   1
>  #define TCG_TARGET_HAS_ext8u_i321
>  #define TCG_TARGET_HAS_ext16u_i32   1
> -#define TCG_TARGET_HAS_bswap16_i32  have_zbb
> -#define TCG_TARGET_HAS_bswap32_i32  have_zbb
> +#define TCG_TARGET_HAS_bswap16_i32  (cpuinfo & CPUINFO_ZBB)
> +#define TCG_TARGET_HAS_bswap32_i32  (cpuinfo & CPUINFO_ZBB)
>  #define TCG_TARGET_HAS_not_i32  1
> -#define TCG_TARGET_HAS_andc_i32 have_zbb
> -#define TCG_TARGET_HAS_orc_i32  have_zbb
> -#define TCG_TARGET_HAS_eqv_i32  have_zbb
> +#define TCG_TARGET_HAS_andc_i32 (cpuinfo & CPUINFO_ZBB)
> +#define TCG_TARGET_HAS_orc_i32  (cpuinfo & CPUINFO_ZBB)
> +#define TCG_TARGET_HAS_eqv_i32  (cpuinfo & CPUINFO_ZBB)
>  #define TCG_TARGET_HAS_nand_i32 0
>  #define TCG_TARGET_HAS_nor_i32  0
> -#define TCG_TARGET_HAS_clz_i32  have_zbb
> -#define TCG_TARGET_HAS_ctz_i32  have_zbb
> -#define TCG_TARGET_HAS_ctpop_i32have_zbb
> +#define TCG_TARGET_HAS_clz_i32  (cpuinfo & CPUINFO_ZBB)
> +#define TCG_TARGET_HAS_ctz_i32  (cpuinfo & CPUINFO_ZBB)
> +#define TCG_TARGET_HAS_ctpop_i32(cpuinfo & CPUINFO_ZBB)
>  #define TCG_TARGET_HAS_brcond2  1
>  #define TCG_TARGET_HAS_setcond2 1
>  #define TCG_TARGET_HAS_qemu_st8_i32 0
> @@ -125,7 +121,7 @@ extern bool have_zbb;
>  #define TCG_TARGET_HAS_div_i64  1
>  #define TCG_TARGET_HAS_rem_i64  1
>  #define TCG_TARGET_HAS_div2_i64 0
> -#define TCG_TARGET_HAS_rot_i64  have_zbb
> +#define TCG_TARGET_HAS_rot_i64  (cpuinfo & CPUINFO_ZBB)
>  #define TCG_TARGET_HAS_deposit_i64  0
>  #define TCG_TARGET_HAS_extract_i64  0
>  #define TCG_TARGET_HAS_sextract_i64   

  1   2   3   4   5   6   7   8   9   10   >