[PATCH for-10.0 6/7] hw/riscv/riscv-iommu: implement reset protocol

Daniel Henrique Barboza posted 7 patches 2 weeks, 3 days ago
[PATCH for-10.0 6/7] hw/riscv/riscv-iommu: implement reset protocol
Posted by Daniel Henrique Barboza 2 weeks, 3 days ago
Add a riscv_iommu_reset() helper in the base emulation code that
implements the expected reset behavior as defined by the riscv-iommu
spec.

Devices can then use this helper in their own reset callbacks.

Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
---
 hw/riscv/riscv-iommu-pci.c | 20 ++++++++++++++++++++
 hw/riscv/riscv-iommu-sys.c | 20 ++++++++++++++++++++
 hw/riscv/riscv-iommu.c     | 35 +++++++++++++++++++++++++++++++++++
 hw/riscv/riscv-iommu.h     |  1 +
 hw/riscv/trace-events      |  2 ++
 include/hw/riscv/iommu.h   |  6 ++++--
 6 files changed, 82 insertions(+), 2 deletions(-)

diff --git a/hw/riscv/riscv-iommu-pci.c b/hw/riscv/riscv-iommu-pci.c
index 4ce9bf6b78..51226c4877 100644
--- a/hw/riscv/riscv-iommu-pci.c
+++ b/hw/riscv/riscv-iommu-pci.c
@@ -31,6 +31,7 @@
 #include "cpu_bits.h"
 #include "riscv-iommu.h"
 #include "riscv-iommu-bits.h"
+#include "trace.h"
 
 /* RISC-V IOMMU PCI Device Emulation */
 #define RISCV_PCI_CLASS_SYSTEM_IOMMU     0x0806
@@ -66,6 +67,12 @@ typedef struct RISCVIOMMUStatePci {
     RISCVIOMMUState  iommu;   /* common IOMMU state */
 } RISCVIOMMUStatePci;
 
+struct RISCVIOMMUPciClass {
+    /*< public >*/
+    DeviceRealize parent_realize;
+    ResettablePhases parent_phases;
+};
+
 /* interrupt delivery callback */
 static void riscv_iommu_pci_notify(RISCVIOMMUState *iommu, unsigned vector)
 {
@@ -167,10 +174,23 @@ static Property riscv_iommu_pci_properties[] = {
     DEFINE_PROP_END_OF_LIST(),
 };
 
+static void riscv_iommu_pci_reset_hold(Object *obj, ResetType type)
+{
+    RISCVIOMMUStatePci *pci = RISCV_IOMMU_PCI(obj);
+    RISCVIOMMUState *iommu = &pci->iommu;
+
+    riscv_iommu_reset(iommu);
+
+    trace_riscv_iommu_pci_reset_hold(type);
+}
+
 static void riscv_iommu_pci_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
     PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
+    ResettableClass *rc = RESETTABLE_CLASS(klass);
+
+    rc->phases.hold = riscv_iommu_pci_reset_hold;
 
     k->realize = riscv_iommu_pci_realize;
     k->exit = riscv_iommu_pci_exit;
diff --git a/hw/riscv/riscv-iommu-sys.c b/hw/riscv/riscv-iommu-sys.c
index a0ef67a20b..605979a0ac 100644
--- a/hw/riscv/riscv-iommu-sys.c
+++ b/hw/riscv/riscv-iommu-sys.c
@@ -54,6 +54,12 @@ struct RISCVIOMMUStateSys {
     uint8_t *msix_pba;
 };
 
+struct RISCVIOMMUSysClass {
+    /*< public >*/
+    DeviceRealize parent_realize;
+    ResettablePhases parent_phases;
+};
+
 static uint64_t msix_table_mmio_read(void *opaque, hwaddr addr,
                                      unsigned size)
 {
@@ -212,9 +218,23 @@ static Property riscv_iommu_sys_properties[] = {
     DEFINE_PROP_END_OF_LIST(),
 };
 
+static void riscv_iommu_sys_reset_hold(Object *obj, ResetType type)
+{
+    RISCVIOMMUStateSys *sys = RISCV_IOMMU_SYS(obj);
+    RISCVIOMMUState *iommu = &sys->iommu;
+
+    riscv_iommu_reset(iommu);
+
+    trace_riscv_iommu_sys_reset_hold(type);
+}
+
 static void riscv_iommu_sys_class_init(ObjectClass *klass, void *data)
 {
     DeviceClass *dc = DEVICE_CLASS(klass);
+    ResettableClass *rc = RESETTABLE_CLASS(klass);
+
+    rc->phases.hold = riscv_iommu_sys_reset_hold;
+
     dc->realize = riscv_iommu_sys_realize;
     set_bit(DEVICE_CATEGORY_MISC, dc->categories);
     device_class_set_props(dc, riscv_iommu_sys_properties);
diff --git a/hw/riscv/riscv-iommu.c b/hw/riscv/riscv-iommu.c
index 239f83f5bd..cf2019d6aa 100644
--- a/hw/riscv/riscv-iommu.c
+++ b/hw/riscv/riscv-iommu.c
@@ -2228,6 +2228,41 @@ static void riscv_iommu_unrealize(DeviceState *dev)
     g_hash_table_unref(s->ctx_cache);
 }
 
+void riscv_iommu_reset(RISCVIOMMUState *s)
+{
+    uint32_t reg_clr;
+    int ddtp_mode;
+
+    /*
+     * Clear DDTP while setting DDTP_mode back to user
+     * initial setting.
+     */
+    ddtp_mode = s->enable_off ?
+                RISCV_IOMMU_DDTP_MODE_OFF : RISCV_IOMMU_DDTP_MODE_BARE;
+    s->ddtp = set_field(0, RISCV_IOMMU_DDTP_MODE, ddtp_mode);
+    riscv_iommu_reg_set64(s, RISCV_IOMMU_REG_DDTP, s->ddtp);
+
+    reg_clr = RISCV_IOMMU_CQCSR_CQEN | RISCV_IOMMU_CQCSR_CIE |
+              RISCV_IOMMU_CQCSR_CQON | RISCV_IOMMU_CQCSR_BUSY;
+    riscv_iommu_reg_mod32(s, RISCV_IOMMU_REG_CQCSR, 0, reg_clr);
+
+    reg_clr = RISCV_IOMMU_FQCSR_FQEN | RISCV_IOMMU_FQCSR_FIE |
+              RISCV_IOMMU_FQCSR_FQON | RISCV_IOMMU_FQCSR_BUSY;
+    riscv_iommu_reg_mod32(s, RISCV_IOMMU_REG_FQCSR, 0, reg_clr);
+
+    reg_clr = RISCV_IOMMU_PQCSR_PQEN | RISCV_IOMMU_PQCSR_PIE |
+              RISCV_IOMMU_PQCSR_PQON | RISCV_IOMMU_PQCSR_BUSY;
+    riscv_iommu_reg_mod32(s, RISCV_IOMMU_REG_PQCSR, 0, reg_clr);
+
+    riscv_iommu_reg_mod64(s, RISCV_IOMMU_REG_TR_REQ_CTL, 0,
+                          RISCV_IOMMU_TR_REQ_CTL_GO_BUSY);
+
+    riscv_iommu_reg_set32(s, RISCV_IOMMU_REG_IPSR, 0);
+
+    g_hash_table_remove_all(s->ctx_cache);
+    g_hash_table_remove_all(s->iot_cache);
+}
+
 static Property riscv_iommu_properties[] = {
     DEFINE_PROP_UINT32("version", RISCVIOMMUState, version,
         RISCV_IOMMU_SPEC_DOT_VER),
diff --git a/hw/riscv/riscv-iommu.h b/hw/riscv/riscv-iommu.h
index f9f2827808..9424989df4 100644
--- a/hw/riscv/riscv-iommu.h
+++ b/hw/riscv/riscv-iommu.h
@@ -89,6 +89,7 @@ struct RISCVIOMMUState {
 void riscv_iommu_pci_setup_iommu(RISCVIOMMUState *iommu, PCIBus *bus,
          Error **errp);
 void riscv_iommu_set_cap_igs(RISCVIOMMUState *s, riscv_iommu_igs_mode mode);
+void riscv_iommu_reset(RISCVIOMMUState *s);
 
 /* private helpers */
 
diff --git a/hw/riscv/trace-events b/hw/riscv/trace-events
index 94facbb8b1..aaa2c0eb94 100644
--- a/hw/riscv/trace-events
+++ b/hw/riscv/trace-events
@@ -17,3 +17,5 @@ riscv_iommu_ats_inval(const char *id) "%s: dev-iotlb invalidate"
 riscv_iommu_ats_prgr(const char *id) "%s: dev-iotlb page request group response"
 riscv_iommu_sys_irq_sent(uint32_t vector) "IRQ sent to vector %u"
 riscv_iommu_sys_msi_sent(uint32_t vector, uint64_t msi_addr, uint32_t msi_data, uint32_t result) "MSI sent to vector %u msi_addr 0x%lx msi_data 0x%x result %u"
+riscv_iommu_sys_reset_hold(int reset_type) "reset type %d"
+riscv_iommu_pci_reset_hold(int reset_type) "reset type %d"
diff --git a/include/hw/riscv/iommu.h b/include/hw/riscv/iommu.h
index 8a8acfc3f0..b03339d75c 100644
--- a/include/hw/riscv/iommu.h
+++ b/include/hw/riscv/iommu.h
@@ -30,12 +30,14 @@ typedef struct RISCVIOMMUState RISCVIOMMUState;
 typedef struct RISCVIOMMUSpace RISCVIOMMUSpace;
 
 #define TYPE_RISCV_IOMMU_PCI "riscv-iommu-pci"
-OBJECT_DECLARE_SIMPLE_TYPE(RISCVIOMMUStatePci, RISCV_IOMMU_PCI)
+OBJECT_DECLARE_TYPE(RISCVIOMMUStatePci, RISCVIOMMUPciClass, RISCV_IOMMU_PCI)
 typedef struct RISCVIOMMUStatePci RISCVIOMMUStatePci;
+typedef struct RISCVIOMMUPciClass RISCVIOMMUPciClass;
 
 #define TYPE_RISCV_IOMMU_SYS "riscv-iommu-device"
-OBJECT_DECLARE_SIMPLE_TYPE(RISCVIOMMUStateSys, RISCV_IOMMU_SYS)
+OBJECT_DECLARE_TYPE(RISCVIOMMUStateSys, RISCVIOMMUSysClass, RISCV_IOMMU_SYS)
 typedef struct RISCVIOMMUStateSys RISCVIOMMUStateSys;
+typedef struct RISCVIOMMUSysClass RISCVIOMMUSysClass;
 
 #define FDT_IRQ_TYPE_EDGE_LOW 1
 
-- 
2.45.2
Re: [PATCH for-10.0 6/7] hw/riscv/riscv-iommu: implement reset protocol
Posted by Alistair Francis 4 days, 18 hours ago
On Wed, Nov 6, 2024 at 11:35 PM Daniel Henrique Barboza
<dbarboza@ventanamicro.com> wrote:
>
> Add a riscv_iommu_reset() helper in the base emulation code that
> implements the expected reset behavior as defined by the riscv-iommu
> spec.
>
> Devices can then use this helper in their own reset callbacks.
>
> Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>

Acked-by: Alistair Francis <alistair.francis@wdc.com>

Alistair

> ---
>  hw/riscv/riscv-iommu-pci.c | 20 ++++++++++++++++++++
>  hw/riscv/riscv-iommu-sys.c | 20 ++++++++++++++++++++
>  hw/riscv/riscv-iommu.c     | 35 +++++++++++++++++++++++++++++++++++
>  hw/riscv/riscv-iommu.h     |  1 +
>  hw/riscv/trace-events      |  2 ++
>  include/hw/riscv/iommu.h   |  6 ++++--
>  6 files changed, 82 insertions(+), 2 deletions(-)
>
> diff --git a/hw/riscv/riscv-iommu-pci.c b/hw/riscv/riscv-iommu-pci.c
> index 4ce9bf6b78..51226c4877 100644
> --- a/hw/riscv/riscv-iommu-pci.c
> +++ b/hw/riscv/riscv-iommu-pci.c
> @@ -31,6 +31,7 @@
>  #include "cpu_bits.h"
>  #include "riscv-iommu.h"
>  #include "riscv-iommu-bits.h"
> +#include "trace.h"
>
>  /* RISC-V IOMMU PCI Device Emulation */
>  #define RISCV_PCI_CLASS_SYSTEM_IOMMU     0x0806
> @@ -66,6 +67,12 @@ typedef struct RISCVIOMMUStatePci {
>      RISCVIOMMUState  iommu;   /* common IOMMU state */
>  } RISCVIOMMUStatePci;
>
> +struct RISCVIOMMUPciClass {
> +    /*< public >*/
> +    DeviceRealize parent_realize;
> +    ResettablePhases parent_phases;
> +};
> +
>  /* interrupt delivery callback */
>  static void riscv_iommu_pci_notify(RISCVIOMMUState *iommu, unsigned vector)
>  {
> @@ -167,10 +174,23 @@ static Property riscv_iommu_pci_properties[] = {
>      DEFINE_PROP_END_OF_LIST(),
>  };
>
> +static void riscv_iommu_pci_reset_hold(Object *obj, ResetType type)
> +{
> +    RISCVIOMMUStatePci *pci = RISCV_IOMMU_PCI(obj);
> +    RISCVIOMMUState *iommu = &pci->iommu;
> +
> +    riscv_iommu_reset(iommu);
> +
> +    trace_riscv_iommu_pci_reset_hold(type);
> +}
> +
>  static void riscv_iommu_pci_class_init(ObjectClass *klass, void *data)
>  {
>      DeviceClass *dc = DEVICE_CLASS(klass);
>      PCIDeviceClass *k = PCI_DEVICE_CLASS(klass);
> +    ResettableClass *rc = RESETTABLE_CLASS(klass);
> +
> +    rc->phases.hold = riscv_iommu_pci_reset_hold;
>
>      k->realize = riscv_iommu_pci_realize;
>      k->exit = riscv_iommu_pci_exit;
> diff --git a/hw/riscv/riscv-iommu-sys.c b/hw/riscv/riscv-iommu-sys.c
> index a0ef67a20b..605979a0ac 100644
> --- a/hw/riscv/riscv-iommu-sys.c
> +++ b/hw/riscv/riscv-iommu-sys.c
> @@ -54,6 +54,12 @@ struct RISCVIOMMUStateSys {
>      uint8_t *msix_pba;
>  };
>
> +struct RISCVIOMMUSysClass {
> +    /*< public >*/
> +    DeviceRealize parent_realize;
> +    ResettablePhases parent_phases;
> +};
> +
>  static uint64_t msix_table_mmio_read(void *opaque, hwaddr addr,
>                                       unsigned size)
>  {
> @@ -212,9 +218,23 @@ static Property riscv_iommu_sys_properties[] = {
>      DEFINE_PROP_END_OF_LIST(),
>  };
>
> +static void riscv_iommu_sys_reset_hold(Object *obj, ResetType type)
> +{
> +    RISCVIOMMUStateSys *sys = RISCV_IOMMU_SYS(obj);
> +    RISCVIOMMUState *iommu = &sys->iommu;
> +
> +    riscv_iommu_reset(iommu);
> +
> +    trace_riscv_iommu_sys_reset_hold(type);
> +}
> +
>  static void riscv_iommu_sys_class_init(ObjectClass *klass, void *data)
>  {
>      DeviceClass *dc = DEVICE_CLASS(klass);
> +    ResettableClass *rc = RESETTABLE_CLASS(klass);
> +
> +    rc->phases.hold = riscv_iommu_sys_reset_hold;
> +
>      dc->realize = riscv_iommu_sys_realize;
>      set_bit(DEVICE_CATEGORY_MISC, dc->categories);
>      device_class_set_props(dc, riscv_iommu_sys_properties);
> diff --git a/hw/riscv/riscv-iommu.c b/hw/riscv/riscv-iommu.c
> index 239f83f5bd..cf2019d6aa 100644
> --- a/hw/riscv/riscv-iommu.c
> +++ b/hw/riscv/riscv-iommu.c
> @@ -2228,6 +2228,41 @@ static void riscv_iommu_unrealize(DeviceState *dev)
>      g_hash_table_unref(s->ctx_cache);
>  }
>
> +void riscv_iommu_reset(RISCVIOMMUState *s)
> +{
> +    uint32_t reg_clr;
> +    int ddtp_mode;
> +
> +    /*
> +     * Clear DDTP while setting DDTP_mode back to user
> +     * initial setting.
> +     */
> +    ddtp_mode = s->enable_off ?
> +                RISCV_IOMMU_DDTP_MODE_OFF : RISCV_IOMMU_DDTP_MODE_BARE;
> +    s->ddtp = set_field(0, RISCV_IOMMU_DDTP_MODE, ddtp_mode);
> +    riscv_iommu_reg_set64(s, RISCV_IOMMU_REG_DDTP, s->ddtp);
> +
> +    reg_clr = RISCV_IOMMU_CQCSR_CQEN | RISCV_IOMMU_CQCSR_CIE |
> +              RISCV_IOMMU_CQCSR_CQON | RISCV_IOMMU_CQCSR_BUSY;
> +    riscv_iommu_reg_mod32(s, RISCV_IOMMU_REG_CQCSR, 0, reg_clr);
> +
> +    reg_clr = RISCV_IOMMU_FQCSR_FQEN | RISCV_IOMMU_FQCSR_FIE |
> +              RISCV_IOMMU_FQCSR_FQON | RISCV_IOMMU_FQCSR_BUSY;
> +    riscv_iommu_reg_mod32(s, RISCV_IOMMU_REG_FQCSR, 0, reg_clr);
> +
> +    reg_clr = RISCV_IOMMU_PQCSR_PQEN | RISCV_IOMMU_PQCSR_PIE |
> +              RISCV_IOMMU_PQCSR_PQON | RISCV_IOMMU_PQCSR_BUSY;
> +    riscv_iommu_reg_mod32(s, RISCV_IOMMU_REG_PQCSR, 0, reg_clr);
> +
> +    riscv_iommu_reg_mod64(s, RISCV_IOMMU_REG_TR_REQ_CTL, 0,
> +                          RISCV_IOMMU_TR_REQ_CTL_GO_BUSY);
> +
> +    riscv_iommu_reg_set32(s, RISCV_IOMMU_REG_IPSR, 0);
> +
> +    g_hash_table_remove_all(s->ctx_cache);
> +    g_hash_table_remove_all(s->iot_cache);
> +}
> +
>  static Property riscv_iommu_properties[] = {
>      DEFINE_PROP_UINT32("version", RISCVIOMMUState, version,
>          RISCV_IOMMU_SPEC_DOT_VER),
> diff --git a/hw/riscv/riscv-iommu.h b/hw/riscv/riscv-iommu.h
> index f9f2827808..9424989df4 100644
> --- a/hw/riscv/riscv-iommu.h
> +++ b/hw/riscv/riscv-iommu.h
> @@ -89,6 +89,7 @@ struct RISCVIOMMUState {
>  void riscv_iommu_pci_setup_iommu(RISCVIOMMUState *iommu, PCIBus *bus,
>           Error **errp);
>  void riscv_iommu_set_cap_igs(RISCVIOMMUState *s, riscv_iommu_igs_mode mode);
> +void riscv_iommu_reset(RISCVIOMMUState *s);
>
>  /* private helpers */
>
> diff --git a/hw/riscv/trace-events b/hw/riscv/trace-events
> index 94facbb8b1..aaa2c0eb94 100644
> --- a/hw/riscv/trace-events
> +++ b/hw/riscv/trace-events
> @@ -17,3 +17,5 @@ riscv_iommu_ats_inval(const char *id) "%s: dev-iotlb invalidate"
>  riscv_iommu_ats_prgr(const char *id) "%s: dev-iotlb page request group response"
>  riscv_iommu_sys_irq_sent(uint32_t vector) "IRQ sent to vector %u"
>  riscv_iommu_sys_msi_sent(uint32_t vector, uint64_t msi_addr, uint32_t msi_data, uint32_t result) "MSI sent to vector %u msi_addr 0x%lx msi_data 0x%x result %u"
> +riscv_iommu_sys_reset_hold(int reset_type) "reset type %d"
> +riscv_iommu_pci_reset_hold(int reset_type) "reset type %d"
> diff --git a/include/hw/riscv/iommu.h b/include/hw/riscv/iommu.h
> index 8a8acfc3f0..b03339d75c 100644
> --- a/include/hw/riscv/iommu.h
> +++ b/include/hw/riscv/iommu.h
> @@ -30,12 +30,14 @@ typedef struct RISCVIOMMUState RISCVIOMMUState;
>  typedef struct RISCVIOMMUSpace RISCVIOMMUSpace;
>
>  #define TYPE_RISCV_IOMMU_PCI "riscv-iommu-pci"
> -OBJECT_DECLARE_SIMPLE_TYPE(RISCVIOMMUStatePci, RISCV_IOMMU_PCI)
> +OBJECT_DECLARE_TYPE(RISCVIOMMUStatePci, RISCVIOMMUPciClass, RISCV_IOMMU_PCI)
>  typedef struct RISCVIOMMUStatePci RISCVIOMMUStatePci;
> +typedef struct RISCVIOMMUPciClass RISCVIOMMUPciClass;
>
>  #define TYPE_RISCV_IOMMU_SYS "riscv-iommu-device"
> -OBJECT_DECLARE_SIMPLE_TYPE(RISCVIOMMUStateSys, RISCV_IOMMU_SYS)
> +OBJECT_DECLARE_TYPE(RISCVIOMMUStateSys, RISCVIOMMUSysClass, RISCV_IOMMU_SYS)
>  typedef struct RISCVIOMMUStateSys RISCVIOMMUStateSys;
> +typedef struct RISCVIOMMUSysClass RISCVIOMMUSysClass;
>
>  #define FDT_IRQ_TYPE_EDGE_LOW 1
>
> --
> 2.45.2
>
>