aboutsummaryrefslogtreecommitdiff
path: root/target/riscv/op_helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'target/riscv/op_helper.c')
-rw-r--r--target/riscv/op_helper.c67
1 files changed, 67 insertions, 0 deletions
diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c
index d0217b6..84ee018 100644
--- a/target/riscv/op_helper.c
+++ b/target/riscv/op_helper.c
@@ -191,6 +191,73 @@ void helper_cbo_zero(CPURISCVState *env, target_ulong address)
}
}
+/*
+ * check_zicbom_access
+ *
+ * Check access permissions (LOAD, STORE or FETCH as specified in
+ * section 2.5.2 of the CMO specification) for Zicbom, raising
+ * either store page-fault (non-virtualized) or store guest-page
+ * fault (virtualized).
+ */
+static void check_zicbom_access(CPURISCVState *env,
+ target_ulong address,
+ uintptr_t ra)
+{
+ RISCVCPU *cpu = env_archcpu(env);
+ int mmu_idx = cpu_mmu_index(env, false);
+ uint16_t cbomlen = cpu->cfg.cbom_blocksize;
+ void *phost;
+ int ret;
+
+ /* Mask off low-bits to align-down to the cache-block. */
+ address &= ~(cbomlen - 1);
+
+ /*
+ * Section 2.5.2 of cmobase v1.0.1:
+ *
+ * "A cache-block management instruction is permitted to
+ * access the specified cache block whenever a load instruction
+ * or store instruction is permitted to access the corresponding
+ * physical addresses. If neither a load instruction nor store
+ * instruction is permitted to access the physical addresses,
+ * but an instruction fetch is permitted to access the physical
+ * addresses, whether a cache-block management instruction is
+ * permitted to access the cache block is UNSPECIFIED."
+ */
+ ret = probe_access_flags(env, address, cbomlen, MMU_DATA_LOAD,
+ mmu_idx, true, &phost, ra);
+ if (ret != TLB_INVALID_MASK) {
+ /* Success: readable */
+ return;
+ }
+
+ /*
+ * Since not readable, must be writable. On failure, store
+ * fault/store guest amo fault will be raised by
+ * riscv_cpu_tlb_fill(). PMP exceptions will be caught
+ * there as well.
+ */
+ probe_write(env, address, cbomlen, mmu_idx, ra);
+}
+
+void helper_cbo_clean_flush(CPURISCVState *env, target_ulong address)
+{
+ uintptr_t ra = GETPC();
+ check_zicbo_envcfg(env, MENVCFG_CBCFE, ra);
+ check_zicbom_access(env, address, ra);
+
+ /* We don't emulate the cache-hierarchy, so we're done. */
+}
+
+void helper_cbo_inval(CPURISCVState *env, target_ulong address)
+{
+ uintptr_t ra = GETPC();
+ check_zicbo_envcfg(env, MENVCFG_CBIE, ra);
+ check_zicbom_access(env, address, ra);
+
+ /* We don't emulate the cache-hierarchy, so we're done. */
+}
+
#ifndef CONFIG_USER_ONLY
target_ulong helper_sret(CPURISCVState *env)