|
@@ -262,3 +262,22 @@ void riscv_iommu_process_iocntinh_cy(RISCVIOMMUState *s, bool prev_cy_inh)
|
|
|
timer_del(s->hpm_timer);
|
|
|
}
|
|
|
}
|
|
|
+
|
|
|
+void riscv_iommu_process_hpmcycle_write(RISCVIOMMUState *s)
|
|
|
+{
|
|
|
+ const uint64_t val = riscv_iommu_reg_get64(s, RISCV_IOMMU_REG_IOHPMCYCLES);
|
|
|
+ const uint32_t ovf = riscv_iommu_reg_get32(s, RISCV_IOMMU_REG_IOCOUNTOVF);
|
|
|
+
|
|
|
+ /*
|
|
|
+ * Clear OF bit in IOCNTOVF if it's being cleared in IOHPMCYCLES register.
|
|
|
+ */
|
|
|
+ if (get_field(ovf, RISCV_IOMMU_IOCOUNTOVF_CY) &&
|
|
|
+ !get_field(val, RISCV_IOMMU_IOHPMCYCLES_OVF)) {
|
|
|
+ riscv_iommu_reg_mod32(s, RISCV_IOMMU_REG_IOCOUNTOVF, 0,
|
|
|
+ RISCV_IOMMU_IOCOUNTOVF_CY);
|
|
|
+ }
|
|
|
+
|
|
|
+ s->hpmcycle_val = val & ~RISCV_IOMMU_IOHPMCYCLES_OVF;
|
|
|
+ s->hpmcycle_prev = get_cycles();
|
|
|
+ hpm_setup_timer(s, s->hpmcycle_val);
|
|
|
+}
|