@@ -93,6 +93,93 @@ uint32_t mem_attrs_to_wid(MemTxAttrs attrs)
}
}
+static void riscv_cpu_wg_reset(CPURISCVState *env)
+{
+ CPUState *cs = env_cpu(env);
+ RISCVCPU *cpu = RISCV_CPU(cs);
+ uint32_t mlwid, slwid, mwiddeleg;
+ uint32_t trustedwid;
+
+ if (!riscv_cpu_cfg(env)->ext_smwg) {
+ return;
+ }
+
+ if (worldguard_config == NULL) {
+ /*
+ * Note: This reset is dummy now and WG CSRs will be reset again
+ * after worldguard_config is realized.
+ */
+ return;
+ }
+
+ trustedwid = worldguard_config->trustedwid;
+ if (trustedwid == NO_TRUSTEDWID) {
+ trustedwid = worldguard_config->nworlds - 1;
+ }
+
+ /* Reset mlwid, slwid, mwiddeleg CSRs */
+ if (worldguard_config->hw_bypass) {
+ /* HW bypass mode */
+ mlwid = trustedwid;
+ } else {
+ mlwid = 0;
+ }
+ slwid = 0;
+ mwiddeleg = 0;
+
+ env->mlwid = mlwid;
+ if (riscv_cpu_cfg(env)->ext_sswg) {
+ env->slwid = slwid;
+ env->mwiddeleg = mwiddeleg;
+ }
+
+ /* Check mwid, mwidlist config */
+ if (worldguard_config != NULL) {
+ uint32_t valid_widlist = MAKE_64BIT_MASK(0, worldguard_config->nworlds);
+
+ /* CPU use default mwid / mwidlist config if not set */
+ if (cpu->cfg.mwidlist == UINT32_MAX) {
+ /* mwidlist contains all WIDs */
+ cpu->cfg.mwidlist = valid_widlist;
+ }
+ if (cpu->cfg.mwid == UINT32_MAX) {
+ cpu->cfg.mwid = trustedwid;
+ }
+
+ /* Check if mwid/mwidlist HW config is valid in NWorld. */
+ g_assert((cpu->cfg.mwidlist & ~valid_widlist) == 0);
+ g_assert(cpu->cfg.mwid < worldguard_config->nworlds);
+ }
+}
+
+/*
+ * riscv_worldguard_apply_cpu - Enable WG extension of CPU
+ *
+ * Note: This API should be used after global WG device is created
+ * (riscv_worldguard_realize()).
+ */
+void riscv_worldguard_apply_cpu(uint32_t hartid)
+{
+ /* WG global config should exist */
+ g_assert(worldguard_config);
+
+ CPUState *cpu = qemu_get_cpu(hartid);
+ RISCVCPU *rcpu = RISCV_CPU(cpu);
+ CPURISCVState *env = cpu ? cpu_env(cpu) : NULL;
+
+ rcpu->cfg.ext_smwg = true;
+ if (riscv_has_ext(env, RVS) && riscv_has_ext(env, RVU)) {
+ rcpu->cfg.ext_sswg = true;
+ }
+
+ /* Set machine specific WorldGuard callback */
+ env->wg_reset = riscv_cpu_wg_reset;
+ env->wid_to_mem_attrs = wid_to_mem_attrs;
+
+ /* Reset WG CSRs in CPU */
+ env->wg_reset(env);
+}
+
bool could_access_wgblocks(MemTxAttrs attrs, const char *wgblock)
{
uint32_t wid = mem_attrs_to_wid(attrs);
@@ -48,6 +48,7 @@ extern struct RISCVWorldGuardState *worldguard_config;
DeviceState *riscv_worldguard_create(uint32_t nworlds, uint32_t trustedwid,
bool hw_bypass, bool tz_compat);
+void riscv_worldguard_apply_cpu(uint32_t hartid);
uint32_t mem_attrs_to_wid(MemTxAttrs attrs);
bool could_access_wgblocks(MemTxAttrs attrs, const char *wgblock);
riscv_worldguard_apply_cpu() could enable WG CPU extension and set WG callback to CPUs. It is used by machine code after realizing global WG device. Signed-off-by: Jim Shu <jim.shu@sifive.com> --- hw/misc/riscv_worldguard.c | 87 ++++++++++++++++++++++++++++++ include/hw/misc/riscv_worldguard.h | 1 + 2 files changed, 88 insertions(+)