TCG: 0.991 risc-v: 0.945 performance: 0.867 architecture: 0.854 ppc: 0.847 graphic: 0.841 semantic: 0.795 PID: 0.759 device: 0.758 kernel: 0.737 i386: 0.728 mistranslation: 0.728 user-level: 0.727 register: 0.727 network: 0.714 peripherals: 0.706 permissions: 0.706 VMM: 0.702 vnc: 0.685 arm: 0.639 x86: 0.635 hypervisor: 0.634 socket: 0.632 KVM: 0.630 assembly: 0.629 debug: 0.602 files: 0.573 boot: 0.479 virtual: 0.432 -------------------- TCG: 0.942 risc-v: 0.533 kernel: 0.316 debug: 0.145 semantic: 0.116 performance: 0.104 files: 0.070 assembly: 0.039 architecture: 0.025 register: 0.024 hypervisor: 0.019 virtual: 0.014 user-level: 0.007 device: 0.005 PID: 0.004 boot: 0.004 VMM: 0.003 KVM: 0.002 peripherals: 0.002 permissions: 0.002 network: 0.002 socket: 0.002 ppc: 0.002 arm: 0.001 vnc: 0.001 x86: 0.001 mistranslation: 0.001 graphic: 0.001 i386: 0.001 TCG: probe_access() has inconsistent behavior Description of problem: In full-system mode, probe_access() will return NULL when the flag is TLB_MMIO. accel/tcg/cputlb.c: probe_access_internal() ``` if (unlikely(flags & ~(TLB_WATCHPOINT | TLB_NOTDIRTY | TLB_CHECK_ALIGNED)) || (access_type != MMU_INST_FETCH && force_mmio)) { *phost = NULL; return TLB_MMIO; } ``` But in linux-user mode, it will return correct address when the flag is TLB_MMIO. accel/tcg/user-exec.c: probe_access() ``` return size ? g2h(env_cpu(env), addr) : NULL; ``` This will lead to some different behaviors, like cbo.zero in RISC-V. target/riscv/op_helper.c: helper_cbo_zero() ``` mem = probe_write(env, address, cbozlen, mmu_idx, ra); if (likely(mem)) { memset(mem, 0, cbozlen); } else { for (int i = 0; i < cbozlen; i++) { cpu_stb_mmuidx_ra(env, address + i, 0, mmu_idx, ra); } } ``` When the current instruction has memory callback by plugin: Full-system mode uses slow-path(cpu_stb_mmuidx_ra) and inject mem_cbs correctly. Linux-user mode uses fast-path(memset) and doesn't inject callbacks. To ensure consistent results, probe_access() should return NULL when the flag is TLB_MMIO in linux-user mode.