qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

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


From: Daniel Henrique Barboza
Subject: Re: [PATCH v4 03/14] hw/riscv: add RISC-V IOMMU base emulation
Date: Fri, 5 Jul 2024 18:11:45 -0300
User-agent: Mozilla Thunderbird

Hi,

On 7/4/24 11:20 AM, Jason Chien wrote:
Hi Danial,

On 2024/6/25 上午 04:18, Daniel Henrique Barboza wrote:
From: Tomasz Jeznach <tjeznach@rivosinc.com>

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, which
includes an IOMMU that has no capabilities but MSI interrupt support and
fault queue interfaces. We'll add more features incrementally in the
next patches.

Co-developed-by: Sebastien Boeuf <seb@rivosinc.com>
Signed-off-by: Sebastien Boeuf <seb@rivosinc.com>
Signed-off-by: Tomasz Jeznach <tjeznach@rivosinc.com>
Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
---
  hw/riscv/Kconfig            |    4 +
  hw/riscv/meson.build        |    1 +
  hw/riscv/riscv-iommu-bits.h |    2 +
  hw/riscv/riscv-iommu.c      | 1641 +++++++++++++++++++++++++++++++++++
  hw/riscv/riscv-iommu.h      |  142 +++
  hw/riscv/trace-events       |   11 +
  hw/riscv/trace.h            |    1 +
  include/hw/riscv/iommu.h    |   36 +
  meson.build                 |    1 +
  9 files changed, 1839 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

(...)


+/* IOMMU index for transactions without process_id specified. */
+#define RISCV_IOMMU_NOPROCID 0
+
+static void riscv_iommu_notify(RISCVIOMMUState *s, int vec)
+{
+    const uint32_t fctl = riscv_iommu_reg_get32(s, RISCV_IOMMU_REG_FCTL);
+    uint32_t ipsr, ivec;
+
+    if (fctl & RISCV_IOMMU_FCTL_WSI || !s->notify) {
For WSI, we can assert INTx by invoking pci_set_irq().

For now we're not advertising WSI support because we don't have a way to test it
(riscv-iommu-pci only supports MSI). In fact riscv_iommu_notify() isn't called
for any WSI capable device, at least for now.

I'm finishing some patches where we'll re-introduce riscv-iommu-sys in the 
'virt'
machine with WSI. At that point we'll pay more attention with the WSI bits that
we're ignoring for now.

+        return;
+    }
+
+    ipsr = riscv_iommu_reg_mod32(s, RISCV_IOMMU_REG_IPSR, (1 << vec), 0);
+    ivec = riscv_iommu_reg_get32(s, RISCV_IOMMU_REG_IVEC);
+
+    if (!(ipsr & (1 << vec))) {
+        s->notify(s, (ivec >> (vec * 4)) & 0x0F);
+    }
+}
+

(...)

+
+/* Check if GPA matches MSI/MRIF pattern. */
+static bool riscv_iommu_msi_check(RISCVIOMMUState *s, RISCVIOMMUContext *ctx,
+    dma_addr_t gpa)
+{

If IOMMU does not support MSI, that is, s->enable_msi is false, we can return 
false.


Done.

+    if (get_field(ctx->msiptp, RISCV_IOMMU_DC_MSIPTP_MODE) !=
+        RISCV_IOMMU_DC_MSIPTP_MODE_FLAT) {
+        return false; /* Invalid MSI/MRIF mode */
+    }
+
+    if ((PPN_DOWN(gpa) ^ ctx->msi_addr_pattern) & ~ctx->msi_addr_mask) {
+        return false; /* GPA not in MSI range defined by AIA IMSIC rules. */
+    }
+
+    return true;
+}
+
+/* RISCV IOMMU Address Translation Lookup - Page Table Walk */
+static int riscv_iommu_spa_fetch(RISCVIOMMUState *s, RISCVIOMMUContext *ctx,
+    IOMMUTLBEntry *iotlb)
+{
+    /* Early check for MSI address match when IOVA == GPA */
+    if (iotlb->perm & IOMMU_WO &&
+        riscv_iommu_msi_check(s, ctx, iotlb->iova)) {
+        iotlb->target_as = &s->trap_as;
+        iotlb->translated_addr = iotlb->iova;
+        iotlb->addr_mask = ~TARGET_PAGE_MASK;
+        return 0;
+    }
 From spec 2.3, step 17 and step 18 state that the MSI address translation is 
always done after the first stage translation is done.

This piece of code isn't doing MSI addr translation. It's preventing the lookup
process by doing an early exit if IOVA==GPA, i.e. there's nothing to translate.

What you described is being done in patch 8 with s-stage and g-stage support.

(...)

+/* Redirect MSI write for given GPA. */
+static MemTxResult riscv_iommu_msi_write(RISCVIOMMUState *s,
+    RISCVIOMMUContext *ctx, uint64_t gpa, uint64_t data,
+    unsigned size, MemTxAttrs attrs)
+{
+    MemTxResult res;
+    dma_addr_t addr;
+    uint64_t intn;
+    uint32_t n190;
+    uint64_t pte[2];
+    int fault_type = RISCV_IOMMU_FQ_TTYPE_UADDR_WR;
+    int cause;
+
+    if (!riscv_iommu_msi_check(s, ctx, gpa)) {
I think we have invoked riscv_iommu_msi_check() before writing to s->trap_as. 
Do we need this check?


You're right. Removed.

(...)

+
+    if (data & RISCV_IOMMU_IPSR_PIP) {
+        pqcsr = riscv_iommu_reg_get32(s, RISCV_IOMMU_REG_PQCSR);
+
+        if (pqcsr & RISCV_IOMMU_PQCSR_PIE &&
+            (pqcsr & RISCV_IOMMU_PQCSR_PQOF ||
+             pqcsr & RISCV_IOMMU_PQCSR_PQMF)) {
+            ipsr_set |= RISCV_IOMMU_IPSR_PIP;
+        } else {
+            ipsr_clr |= RISCV_IOMMU_IPSR_PIP;
+        }
+    } else {
+        ipsr_clr |= RISCV_IOMMU_IPSR_PIP;
+    }
+
+    riscv_iommu_reg_mod32(s, RISCV_IOMMU_REG_IPSR, ipsr_set, ipsr_clr);
If the pending bit is cleared, we can deassert the WSI.


I'll make a note to remind about this later when we add WSI support.


(...)


+#ifndef HW_RISCV_IOMMU_STATE_H
+#define HW_RISCV_IOMMU_STATE_H
+
+#include "qemu/osdep.h"
+#include "qom/object.h"
+
+#include "hw/riscv/iommu.h"
+
+struct RISCVIOMMUState {
+    /*< private >*/
+    DeviceState parent_obj;
+
+    /*< public >*/
+    uint32_t version;     /* Reported interface version number */
+    uint32_t pasid_bits;  /* process identifier width */
Do you mind renaming pasid_bits to something like pid_bits to remain 
consistency?


Done. In fact I also renamed 'pasid' from the first patch to 'pid' as well.


Thanks,

Daniel



reply via email to

[Prev in Thread] Current Thread [Next in Thread]