target/riscv: implement Zicbom extension

Zicbom is the Cache-Block Management extension defined in the already
ratified RISC-V Base Cache Management Operation (CBO) ISA extension [1].

The extension contains three instructions: cbo.clean, cbo.flush and
cbo.inval. All of them must be implemented in the same group as LQ and
cbo.zero due to overlapping patterns.

All these instructions can throw a Illegal Instruction/Virtual
Instruction exception, similar to the existing cbo.zero. The same
check_zicbo_envcfg() is used to handle these exceptions.

Aside from that, these instructions also need to handle page faults and
guest page faults. This is done in a new check_zicbom_access() helper.

As with Zicboz, the cache block size for Zicbom is also configurable.
Note that the spec determines that Zicbo[mp] and Zicboz can have
different cache sizes (Section 2.7 of [1]), so we also include a
'cbom_blocksize' to go along with the existing 'cboz_blocksize'. They
are set to the same size, so unless users want to play around with the
settings both sizes will be the same.

[1] https://github.com/riscv/riscv-CMOs/blob/master/specifications/cmobase-v1.0.1.pdf

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Weiwei Li <liweiwei@iscas.ac.cn>
Co-developed-by: Philipp Tomsich <philipp.tomsich@vrull.eu>
Signed-off-by: Christoph Muellner <cmuellner@linux.com>
Signed-off-by: Daniel Henrique Barboza <dbarboza@ventanamicro.com>
Message-ID: <20230224132536.552293-4-dbarboza@ventanamicro.com>
Signed-off-by: Palmer Dabbelt <palmer@rivosinc.com>
This commit is contained in:
Christoph Muellner 2023-02-24 10:25:35 -03:00 committed by Palmer Dabbelt
parent a939c50079
commit e05da09b7c
No known key found for this signature in database
GPG key ID: 2E1319F35FBB1889
6 changed files with 106 additions and 0 deletions

View file

@ -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)