[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]
[PATCH for-10.0 05/11] hw/riscv/riscv-iommu: instantiate hpm_timer
From: |
Daniel Henrique Barboza |
Subject: |
[PATCH for-10.0 05/11] hw/riscv/riscv-iommu: instantiate hpm_timer |
Date: |
Thu, 5 Dec 2024 10:29:57 -0300 |
From: Tomasz Jeznach <tjeznach@rivosinc.com>
The next HPM related changes requires the HPM overflow timer to be
initialized by the riscv-iommu base emulation.
Signed-off-by: Tomasz Jeznach <tjeznach@rivosinc.com>
Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
---
hw/riscv/riscv-iommu-hpm.c | 36 ++++++++++++++++++++++++++++++++++++
hw/riscv/riscv-iommu-hpm.h | 1 +
hw/riscv/riscv-iommu.c | 3 +++
hw/riscv/riscv-iommu.h | 2 ++
4 files changed, 42 insertions(+)
diff --git a/hw/riscv/riscv-iommu-hpm.c b/hw/riscv/riscv-iommu-hpm.c
index 8eca5ee17e..325088333e 100644
--- a/hw/riscv/riscv-iommu-hpm.c
+++ b/hw/riscv/riscv-iommu-hpm.c
@@ -166,3 +166,39 @@ void riscv_iommu_hpm_incr_ctr(RISCVIOMMUState *s,
RISCVIOMMUContext *ctx,
hpm_incr_ctr(s, ctr_idx);
}
}
+
+/* Timer callback for cycle counter overflow. */
+void riscv_iommu_hpm_timer_cb(void *priv)
+{
+ RISCVIOMMUState *s = priv;
+ const uint32_t inhibit = riscv_iommu_reg_get32(
+ s, RISCV_IOMMU_REG_IOCOUNTINH);
+ uint32_t ovf;
+
+ if (get_field(inhibit, RISCV_IOMMU_IOCOUNTINH_CY)) {
+ return;
+ }
+
+ if (s->irq_overflow_left > 0) {
+ uint64_t irq_trigger_at =
+ qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + s->irq_overflow_left;
+ timer_mod_anticipate_ns(s->hpm_timer, irq_trigger_at);
+ s->irq_overflow_left = 0;
+ return;
+ }
+
+ ovf = riscv_iommu_reg_get32(s, RISCV_IOMMU_REG_IOCOUNTOVF);
+ if (!get_field(ovf, RISCV_IOMMU_IOCOUNTOVF_CY)) {
+ /*
+ * We don't need to set hpmcycle_val to zero and update hpmcycle_prev
to
+ * current clock value. The way we calculate iohpmcycs will overflow
+ * and return the correct value. This avoids the need to synchronize
+ * timer callback and write callback.
+ */
+ riscv_iommu_reg_mod32(s, RISCV_IOMMU_REG_IOCOUNTOVF,
+ RISCV_IOMMU_IOCOUNTOVF_CY, 0);
+ riscv_iommu_reg_mod64(s, RISCV_IOMMU_REG_IOHPMCYCLES,
+ RISCV_IOMMU_IOHPMCYCLES_OVF, 0);
+ riscv_iommu_notify(s, RISCV_IOMMU_INTR_PM);
+ }
+}
diff --git a/hw/riscv/riscv-iommu-hpm.h b/hw/riscv/riscv-iommu-hpm.h
index 411d869dce..cd896d3b7c 100644
--- a/hw/riscv/riscv-iommu-hpm.h
+++ b/hw/riscv/riscv-iommu-hpm.h
@@ -25,5 +25,6 @@
uint64_t riscv_iommu_hpmcycle_read(RISCVIOMMUState *s);
void riscv_iommu_hpm_incr_ctr(RISCVIOMMUState *s, RISCVIOMMUContext *ctx,
unsigned event_id);
+void riscv_iommu_hpm_timer_cb(void *priv);
#endif
diff --git a/hw/riscv/riscv-iommu.c b/hw/riscv/riscv-iommu.c
index 5ce0d24359..2ec388ff3d 100644
--- a/hw/riscv/riscv-iommu.c
+++ b/hw/riscv/riscv-iommu.c
@@ -2281,6 +2281,8 @@ static void riscv_iommu_realize(DeviceState *dev, Error
**errp)
address_space_init(&s->trap_as, &s->trap_mr, "riscv-iommu-trap-as");
if (s->cap & RISCV_IOMMU_CAP_HPM) {
+ s->hpm_timer =
+ timer_new_ns(QEMU_CLOCK_VIRTUAL, riscv_iommu_hpm_timer_cb, s);
s->hpm_event_ctr_map = g_hash_table_new(g_direct_hash, g_direct_equal);
}
}
@@ -2294,6 +2296,7 @@ static void riscv_iommu_unrealize(DeviceState *dev)
if (s->cap & RISCV_IOMMU_CAP_HPM) {
g_hash_table_unref(s->hpm_event_ctr_map);
+ timer_free(s->hpm_timer);
}
}
diff --git a/hw/riscv/riscv-iommu.h b/hw/riscv/riscv-iommu.h
index a21ab51491..6ddc59f474 100644
--- a/hw/riscv/riscv-iommu.h
+++ b/hw/riscv/riscv-iommu.h
@@ -88,8 +88,10 @@ struct RISCVIOMMUState {
QLIST_HEAD(, RISCVIOMMUSpace) spaces;
/* HPM cycle counter */
+ QEMUTimer *hpm_timer;
uint64_t hpmcycle_val; /* Current value of cycle register */
uint64_t hpmcycle_prev; /* Saved value of QEMU_CLOCK_VIRTUAL clock */
+ uint64_t irq_overflow_left; /* Value beyond INT64_MAX after overflow */
/* HPM event counters */
GHashTable *hpm_event_ctr_map; /* Mapping of events to counters */
--
2.47.1
- [PATCH for-10.0 01/11] hw/riscv/riscv-iommu.h: add missing headers, (continued)
- [PATCH for-10.0 01/11] hw/riscv/riscv-iommu.h: add missing headers, Daniel Henrique Barboza, 2024/12/05
- [PATCH for-10.0 08/11] hw/riscv/riscv-iommu: add hpm events mmio write, Daniel Henrique Barboza, 2024/12/05
- [PATCH for-10.0 02/11] hw/riscv/riscv-iommu-bits.h: HPM bits, Daniel Henrique Barboza, 2024/12/05
- [PATCH for-10.0 06/11] hw/riscv/riscv-iommu: add IOCOUNTINH mmio writes, Daniel Henrique Barboza, 2024/12/05
- [PATCH for-10.0 07/11] hw/riscv/riscv-iommu: add IOHPMCYCLES mmio write, Daniel Henrique Barboza, 2024/12/05
- [PATCH for-10.0 04/11] hw/riscv/riscv-iommu: add riscv_iommu_hpm_incr_ctr(), Daniel Henrique Barboza, 2024/12/05
- [PATCH for-10.0 10/11] hw/riscv: add IOMMU HPM trace events, Daniel Henrique Barboza, 2024/12/05
- [PATCH for-10.0 09/11] hw/riscv/riscv-iommu.c: add RISCV_IOMMU_CAP_HPM cap, Daniel Henrique Barboza, 2024/12/05
- [PATCH for-10.0 03/11] hw/riscv/riscv-iommu: add riscv-iommu-hpm file, Daniel Henrique Barboza, 2024/12/05
- [PATCH for-10.0 11/11] docs/specs/riscv-iommu.rst: add HPM support info, Daniel Henrique Barboza, 2024/12/05
- [PATCH for-10.0 05/11] hw/riscv/riscv-iommu: instantiate hpm_timer,
Daniel Henrique Barboza <=