diff options
Diffstat (limited to 'target/riscv/op_helper.c')
-rw-r--r-- | target/riscv/op_helper.c | 67 |
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) |