@@ -2343,7 +2343,7 @@ static int64_t riscv_get_arch_id(CPUState *cs)
#include "hw/core/sysemu-cpu-ops.h"
static const struct SysemuCPUOps riscv_sysemu_ops = {
- .get_phys_page_debug = riscv_cpu_get_phys_page_debug,
+ .get_phys_page_attrs_debug = riscv_cpu_get_phys_page_attrs_debug,
.write_elf64_note = riscv_cpu_write_elf64_note,
.write_elf32_note = riscv_cpu_write_elf32_note,
.legacy_vmsd = &vmstate_riscv_cpu,
@@ -512,6 +512,7 @@ void riscv_cpu_set_geilen(CPURISCVState *env, target_ulong geilen);
bool riscv_cpu_vector_enabled(CPURISCVState *env);
void riscv_cpu_set_virt_enabled(CPURISCVState *env, bool enable);
int riscv_env_mmu_index(CPURISCVState *env, bool ifetch);
+hwaddr riscv_cpu_get_phys_page_attrs_debug(CPUState *cpu, vaddr addr, MemTxAttrs *attrs);
G_NORETURN void riscv_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
MMUAccessType access_type,
int mmu_idx, uintptr_t retaddr);
@@ -150,6 +150,34 @@ void cpu_get_tb_cpu_state(CPURISCVState *env, vaddr *pc,
}
#ifndef CONFIG_USER_ONLY
+static uint32_t riscv_cpu_wg_get_wid(CPURISCVState *env, int mode)
+{
+ CPUState *cs = env_cpu(env);
+ RISCVCPU *cpu = RISCV_CPU(cs);
+ bool virt = env->virt_enabled;
+
+ if (mode == PRV_M) {
+ return cpu->cfg.mwid;
+ } else if (mode == PRV_S) {
+ if (!virt || !env->mwiddeleg) {
+ /* HS-mode, S-mode w/o RVH, or VS-mode but mwiddeleg = 0 */
+ return env->mlwid;
+ } else {
+ /* VS-mode */
+ return env->slwid;
+ }
+ } else if (mode == PRV_U) {
+ if (!riscv_has_ext(env, RVS) || !env->mwiddeleg) {
+ /* M/U mode CPU or mwiddeleg = 0 */
+ return env->mlwid;
+ } else {
+ return env->slwid;
+ }
+ }
+
+ return cpu->cfg.mwid;
+}
+
void riscv_cpu_set_wg_mwid(CPURISCVState *env, uint32_t mwid)
{
CPUState *cs = env_cpu(env);
@@ -1229,13 +1257,22 @@ static void raise_mmu_exception(CPURISCVState *env, target_ulong address,
env->two_stage_indirect_lookup = two_stage_indirect;
}
-hwaddr riscv_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
+hwaddr riscv_cpu_get_phys_page_attrs_debug(CPUState *cs, vaddr addr, MemTxAttrs *attrs)
{
RISCVCPU *cpu = RISCV_CPU(cs);
CPURISCVState *env = &cpu->env;
hwaddr phys_addr;
int prot;
int mmu_idx = riscv_env_mmu_index(&cpu->env, false);
+ int mode = mmuidx_priv(mmu_idx);
+ uint32_t wid;
+
+ if (riscv_cpu_cfg(env)->ext_smwg && env->wid_to_mem_attrs) {
+ wid = riscv_cpu_wg_get_wid(env, mode);
+ env->wid_to_mem_attrs(attrs, wid);
+ } else {
+ *attrs = MEMTXATTRS_UNSPECIFIED;
+ }
if (get_physical_address(env, &phys_addr, &prot, addr, NULL, 0, mmu_idx,
true, env->virt_enabled, true)) {
@@ -1339,12 +1376,20 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
int mode = mmuidx_priv(mmu_idx);
/* default TLB page size */
target_ulong tlb_size = TARGET_PAGE_SIZE;
+ uint32_t wid;
+ MemTxAttrs attrs = MEMTXATTRS_UNSPECIFIED;
env->guest_phys_fault_addr = 0;
qemu_log_mask(CPU_LOG_MMU, "%s ad %" VADDR_PRIx " rw %d mmu_idx %d\n",
__func__, address, access_type, mmu_idx);
+ if (riscv_cpu_cfg(env)->ext_smwg && env->wid_to_mem_attrs) {
+ mode = mmuidx_priv(mmu_idx);
+ wid = riscv_cpu_wg_get_wid(env, mode);
+ env->wid_to_mem_attrs(&attrs, wid);
+ }
+
pmu_tlb_fill_incr_ctr(cpu, access_type);
if (two_stage_lookup) {
/* Two stage lookup */
@@ -1436,8 +1481,8 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
}
if (ret == TRANSLATE_SUCCESS) {
- tlb_set_page(cs, address & ~(tlb_size - 1), pa & ~(tlb_size - 1),
- prot, access_type, mmu_idx, tlb_size);
+ tlb_set_page_with_attrs(cs, address & ~(tlb_size - 1), pa & ~(tlb_size - 1),
+ attrs, prot, access_type, mmu_idx, tlb_size);
return true;
} else if (probe) {
return false;
When a RISC-V HART has WG extension, their memory transactions will contain WID. Support MemTxAttrs in RISC-V target and add WID inside if a HART has WG extension. Signed-off-by: Jim Shu <jim.shu@sifive.com> --- target/riscv/cpu.c | 2 +- target/riscv/cpu.h | 1 + target/riscv/cpu_helper.c | 51 ++++++++++++++++++++++++++++++++++++--- 3 files changed, 50 insertions(+), 4 deletions(-)