Created
October 17, 2022 13:37
-
-
Save luhenry/fd6f44f98582755d56f73b08dd10e7dd to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
diff --git a/target/riscv/cpu.c b/target/riscv/cpu.c | |
index 4d0c178479..f559026e2c 100644 | |
--- a/target/riscv/cpu.c | |
+++ b/target/riscv/cpu.c | |
@@ -74,6 +74,8 @@ static const struct isa_ext_data isa_edata_arr[] = { | |
ISA_EXT_DATA_ENTRY(h, false, PRIV_VERSION_1_12_0, ext_h), | |
ISA_EXT_DATA_ENTRY(v, false, PRIV_VERSION_1_12_0, ext_v), | |
ISA_EXT_DATA_ENTRY(zicsr, true, PRIV_VERSION_1_10_0, ext_icsr), | |
+ ISA_EXT_DATA_ENTRY(zicbom, true, PRIV_VERSION_1_10_0, ext_icbom), | |
+ ISA_EXT_DATA_ENTRY(zicboz, true, PRIV_VERSION_1_10_0, ext_icboz), | |
ISA_EXT_DATA_ENTRY(zifencei, true, PRIV_VERSION_1_10_0, ext_ifencei), | |
ISA_EXT_DATA_ENTRY(zihintpause, true, PRIV_VERSION_1_10_0, ext_zihintpause), | |
ISA_EXT_DATA_ENTRY(zfh, true, PRIV_VERSION_1_12_0, ext_zfh), | |
@@ -1039,6 +1041,9 @@ static Property riscv_cpu_extensions[] = { | |
DEFINE_PROP_BOOL("sscofpmf", RISCVCPU, cfg.ext_sscofpmf, false), | |
DEFINE_PROP_BOOL("Zifencei", RISCVCPU, cfg.ext_ifencei, true), | |
DEFINE_PROP_BOOL("Zicsr", RISCVCPU, cfg.ext_icsr, true), | |
+ DEFINE_PROP_BOOL("Zicbom", RISCVCPU, cfg.ext_icbom, true), | |
+ DEFINE_PROP_BOOL("Zicboz", RISCVCPU, cfg.ext_icboz, true), | |
+ DEFINE_PROP_UINT16("cbozlen", RISCVCPU, cfg.cbozlen, 64), | |
DEFINE_PROP_BOOL("Zihintpause", RISCVCPU, cfg.ext_zihintpause, true), | |
DEFINE_PROP_BOOL("Zfh", RISCVCPU, cfg.ext_zfh, false), | |
DEFINE_PROP_BOOL("Zfhmin", RISCVCPU, cfg.ext_zfhmin, false), | |
diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h | |
index 8079e17cfb..ef2dac9b8e 100644 | |
--- a/target/riscv/cpu.h | |
+++ b/target/riscv/cpu.h | |
@@ -464,6 +464,8 @@ struct RISCVCPUConfig { | |
bool ext_zkt; | |
bool ext_ifencei; | |
bool ext_icsr; | |
+ bool ext_icbom; | |
+ bool ext_icboz; | |
bool ext_zihintpause; | |
bool ext_sstc; | |
bool ext_svinval; | |
@@ -499,6 +501,7 @@ struct RISCVCPUConfig { | |
char *vext_spec; | |
uint16_t vlen; | |
uint16_t elen; | |
+ uint16_t cbozlen; | |
bool mmu; | |
bool pmp; | |
bool epmp; | |
diff --git a/target/riscv/helper.h b/target/riscv/helper.h | |
index f760b3bb56..ea7d3d2b5c 100644 | |
--- a/target/riscv/helper.h | |
+++ b/target/riscv/helper.h | |
@@ -97,6 +97,11 @@ DEF_HELPER_FLAGS_2(fcvt_h_l, TCG_CALL_NO_RWG, i64, env, tl) | |
DEF_HELPER_FLAGS_2(fcvt_h_lu, TCG_CALL_NO_RWG, i64, env, tl) | |
DEF_HELPER_FLAGS_2(fclass_h, TCG_CALL_NO_RWG_SE, tl, env, i64) | |
+/* Cache-block operations */ | |
+DEF_HELPER_2(cbo_clean_flush, void, env, tl) | |
+DEF_HELPER_2(cbo_inval, void, env, tl) | |
+DEF_HELPER_2(cbo_zero, void, env, tl) | |
+ | |
/* Special functions */ | |
DEF_HELPER_2(csrr, tl, env, int) | |
DEF_HELPER_3(csrw, void, env, int, tl) | |
diff --git a/target/riscv/insn32.decode b/target/riscv/insn32.decode | |
index 595fdcdad8..d53cbbc44c 100644 | |
--- a/target/riscv/insn32.decode | |
+++ b/target/riscv/insn32.decode | |
@@ -177,9 +177,22 @@ sllw 0000000 ..... ..... 001 ..... 0111011 @r | |
srlw 0000000 ..... ..... 101 ..... 0111011 @r | |
sraw 0100000 ..... ..... 101 ..... 0111011 @r | |
+{ | |
+ lq ............ ..... 010 ..... 0001111 @i | |
+ | |
+ # *** RV32 Zicbom Standard Extension *** | |
+ cbo_inval 0000000 00000 ..... 010 00000 0001111 @sfence_vm | |
+ cbo_clean 0000000 00001 ..... 010 00000 0001111 @sfence_vm | |
+ cbo_flush 0000000 00010 ..... 010 00000 0001111 @sfence_vm | |
+ | |
+ # *** RV32 Zicboz Standard Extension *** | |
+ cbo_zero 0000000 01000 ..... 010 00000 0001111 @sfence_vm | |
+ | |
+ # cbo.prefetch_{i,r,m} instructions are ori with rd=x0 and not decoded. | |
+} | |
+ | |
# *** RV128I Base Instruction Set (in addition to RV64I) *** | |
ldu ............ ..... 111 ..... 0000011 @i | |
-lq ............ ..... 010 ..... 0001111 @i | |
sq ............ ..... 100 ..... 0100011 @s | |
addid ............ ..... 000 ..... 1011011 @i | |
sllid 000000 ...... ..... 001 ..... 1011011 @sh6 | |
diff --git a/target/riscv/insn_trans/trans_rvzicbo.c.inc b/target/riscv/insn_trans/trans_rvzicbo.c.inc | |
new file mode 100644 | |
index 0000000000..35c277261f | |
--- /dev/null | |
+++ b/target/riscv/insn_trans/trans_rvzicbo.c.inc | |
@@ -0,0 +1,57 @@ | |
+/* | |
+ * RISC-V translation routines for the RISC-V CBO Extension. | |
+ * | |
+ * Copyright (c) 2021 Philipp Tomsich, philipp.tomsich@vrull.eu | |
+ * | |
+ * This program is free software; you can redistribute it and/or modify it | |
+ * under the terms and conditions of the GNU General Public License, | |
+ * version 2 or later, as published by the Free Software Foundation. | |
+ * | |
+ * This program is distributed in the hope it will be useful, but WITHOUT | |
+ * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or | |
+ * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for | |
+ * more details. | |
+ * | |
+ * You should have received a copy of the GNU General Public License along with | |
+ * this program. If not, see <http://www.gnu.org/licenses/>. | |
+ */ | |
+ | |
+#define REQUIRE_ZICBOM(ctx) do { \ | |
+ if (!RISCV_CPU(ctx->cs)->cfg.ext_icbom) { \ | |
+ return false; \ | |
+ } \ | |
+} while (0) | |
+ | |
+#define REQUIRE_ZICBOZ(ctx) do { \ | |
+ if (!RISCV_CPU(ctx->cs)->cfg.ext_icboz) { \ | |
+ return false; \ | |
+ } \ | |
+} while (0) | |
+ | |
+static bool trans_cbo_clean(DisasContext *ctx, arg_cbo_clean *a) | |
+{ | |
+ REQUIRE_ZICBOM(ctx); | |
+ gen_helper_cbo_clean_flush(cpu_env, cpu_gpr[a->rs1]); | |
+ return true; | |
+} | |
+ | |
+static bool trans_cbo_flush(DisasContext *ctx, arg_cbo_flush *a) | |
+{ | |
+ REQUIRE_ZICBOM(ctx); | |
+ gen_helper_cbo_clean_flush(cpu_env, cpu_gpr[a->rs1]); | |
+ return true; | |
+} | |
+ | |
+static bool trans_cbo_inval(DisasContext *ctx, arg_cbo_inval *a) | |
+{ | |
+ REQUIRE_ZICBOM(ctx); | |
+ gen_helper_cbo_inval(cpu_env, cpu_gpr[a->rs1]); | |
+ return true; | |
+} | |
+ | |
+static bool trans_cbo_zero(DisasContext *ctx, arg_cbo_zero *a) | |
+{ | |
+ REQUIRE_ZICBOZ(ctx); | |
+ gen_helper_cbo_zero(cpu_env, cpu_gpr[a->rs1]); | |
+ return true; | |
+} | |
diff --git a/target/riscv/op_helper.c b/target/riscv/op_helper.c | |
index 452125c4ab..ec11923be8 100644 | |
--- a/target/riscv/op_helper.c | |
+++ b/target/riscv/op_helper.c | |
@@ -123,6 +123,99 @@ target_ulong helper_csrrw_i128(CPURISCVState *env, int csr, | |
return int128_getlo(rv); | |
} | |
+/* helper_zicbo_envcfg | |
+ * | |
+ * Raise virtual exceptions and illegal instruction exceptions for | |
+ * Zicbo[mz] instructions based on the settings of [mhs]envcfg as | |
+ * specified in section 2.5.1 of the CMO specification. | |
+ */ | |
+static void helper_zicbo_envcfg(CPURISCVState *env, target_ulong envbits, | |
+ uintptr_t ra) | |
+{ | |
+#ifndef CONFIG_USER_ONLY | |
+ /* Check for virtual instruction exceptions first, as we don't see | |
+ * VU and VS reflected in env->priv (these are just the translated | |
+ * U and S stated with virtualisation enabled. | |
+ */ | |
+ if (riscv_cpu_virt_enabled(env) && | |
+ (((env->priv < PRV_H) && !get_field(env->henvcfg, envbits)) || | |
+ ((env->priv < PRV_S) && !get_field(env->senvcfg, envbits)))) { | |
+ riscv_raise_exception(env, RISCV_EXCP_VIRT_INSTRUCTION_FAULT, ra); | |
+ } | |
+ | |
+ if (((env->priv < PRV_M) && !get_field(env->menvcfg, envbits)) || | |
+ ((env->priv < PRV_S) && !get_field(env->senvcfg, envbits))) { | |
+ riscv_raise_exception(env, RISCV_EXCP_ILLEGAL_INST, ra); | |
+ } | |
+#endif | |
+} | |
+ | |
+/* helper_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-virtualised) or store guest-page fault (virtualised). | |
+ */ | |
+static void helper_zicbom_access(CPURISCVState *env, target_ulong address, | |
+ uintptr_t ra) | |
+{ | |
+ void* phost; | |
+ int ret = TLB_INVALID_MASK; | |
+ MMUAccessType access_type = MMU_DATA_LOAD; | |
+ | |
+ while (ret == TLB_INVALID_MASK && access_type <= MMU_INST_FETCH) { | |
+ ret = probe_access_flags(env, address, access_type++, | |
+ cpu_mmu_index(env, false), | |
+ true, &phost, ra); | |
+ } | |
+ | |
+ if (ret == TLB_INVALID_MASK) { | |
+ uint32_t exc = RISCV_EXCP_STORE_PAGE_FAULT; | |
+ | |
+#ifndef CONFIG_USER_ONLY | |
+ /* User-mode emulation does not have virtualisation. */ | |
+ if (riscv_cpu_virt_enabled(env)) { | |
+ exc = RISCV_EXCP_STORE_GUEST_AMO_ACCESS_FAULT; | |
+ } | |
+#endif | |
+ riscv_raise_exception(env, exc, ra); | |
+ } | |
+} | |
+ | |
+void helper_cbo_clean_flush(CPURISCVState *env, target_ulong address) | |
+{ | |
+ uintptr_t ra = GETPC(); | |
+ helper_zicbo_envcfg(env, MENVCFG_CBCFE, ra); | |
+ helper_zicbom_access(env, address, ra); | |
+} | |
+ | |
+void helper_cbo_inval(CPURISCVState *env, target_ulong address) | |
+{ | |
+ uintptr_t ra = GETPC(); | |
+ helper_zicbo_envcfg(env, MENVCFG_CBIE, ra); | |
+ helper_zicbom_access(env, address, ra); | |
+} | |
+ | |
+void helper_cbo_zero(CPURISCVState *env, target_ulong address) | |
+{ | |
+ uintptr_t ra = GETPC(); | |
+ helper_zicbo_envcfg(env, MENVCFG_CBZE, ra); | |
+ | |
+ /* Get the size of the cache block for zero instructions. */ | |
+ RISCVCPU *cpu = env_archcpu(env); | |
+ uint16_t cbozlen = cpu->cfg.cbozlen; | |
+ | |
+ /* Mask off low-bits to align-down to the cache-block. */ | |
+ address &= ~(cbozlen - 1); | |
+ | |
+ void* mem = probe_access(env, address, cbozlen, MMU_DATA_STORE, | |
+ cpu_mmu_index(env, false), GETPC()); | |
+ | |
+ /* Zero the block */ | |
+ memset(mem, 0, cbozlen); | |
+} | |
+ | |
+ | |
#ifndef CONFIG_USER_ONLY | |
static target_ulong check_rcode_privilege_intercept(CPURISCVState *env, | |
diff --git a/target/riscv/translate.c b/target/riscv/translate.c | |
index dd9c916652..ee15f63174 100644 | |
--- a/target/riscv/translate.c | |
+++ b/target/riscv/translate.c | |
@@ -1032,6 +1032,7 @@ static uint32_t opcode_at(DisasContextBase *dcbase, target_ulong pc) | |
#include "insn_trans/trans_rvv.c.inc" | |
#include "insn_trans/trans_rvb.c.inc" | |
#include "insn_trans/trans_rvzfh.c.inc" | |
+#include "insn_trans/trans_rvzicbo.c.inc" | |
#include "insn_trans/trans_rvk.c.inc" | |
#include "insn_trans/trans_privileged.c.inc" | |
#include "insn_trans/trans_svinval.c.inc" |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment