VS-stage translation at get_physical_address needs to translate pte address by G-stage translation. But the G-stage translation error can not be distinguished from VS-stage translation error in riscv_cpu_tlb_fill. On migration, destination needs to rebuild pte, and this G-stage translation error must be handled by HS-mode. So introduce TRANSLATE_STAGE2_FAIL so that riscv_cpu_tlb_fill could distinguish and raise it to HS-mode.
Signed-off-by: Yifei Jiang <jiangyi...@huawei.com> Signed-off-by: Yipeng Yin <yinyipe...@huawei.com> --- target/riscv/cpu.h | 1 + target/riscv/cpu_helper.c | 17 +++++++++++++++-- 2 files changed, 16 insertions(+), 2 deletions(-) diff --git a/target/riscv/cpu.h b/target/riscv/cpu.h index de275782e6..8b856d518e 100644 --- a/target/riscv/cpu.h +++ b/target/riscv/cpu.h @@ -86,6 +86,7 @@ enum { #define TRANSLATE_FAIL 1 #define TRANSLATE_SUCCESS 0 #define MMU_USER_IDX 3 +#define TRANSLATE_G_STAGE_FAIL 4 #define MAX_RISCV_PMPS (16) diff --git a/target/riscv/cpu_helper.c b/target/riscv/cpu_helper.c index 904899054d..096006dc00 100644 --- a/target/riscv/cpu_helper.c +++ b/target/riscv/cpu_helper.c @@ -451,7 +451,10 @@ restart: mmu_idx, false, true); if (vbase_ret != TRANSLATE_SUCCESS) { - return vbase_ret; + env->guest_phys_fault_addr = (base | + (addr & + (TARGET_PAGE_SIZE - 1))) >> 2; + return TRANSLATE_G_STAGE_FAIL; } pte_addr = vbase + idx * ptesize; @@ -730,12 +733,22 @@ bool riscv_cpu_tlb_fill(CPUState *cs, vaddr address, int size, ret = get_physical_address(env, &pa, &prot, address, access_type, mmu_idx, true, true); + /* + * A G-stage exception may be triggered during VS-stage translation. + * And the env->guest_phys_fault_addr has already been set in + * get_physical_address(). + */ + if (ret == TRANSLATE_G_STAGE_FAIL) { + first_stage_error = false; + access_type = MMU_DATA_LOAD; + } + qemu_log_mask(CPU_LOG_MMU, "%s 1st-stage address=%" VADDR_PRIx " ret %d physical " TARGET_FMT_plx " prot %d\n", __func__, address, ret, pa, prot); - if (ret != TRANSLATE_FAIL) { + if (ret != TRANSLATE_FAIL && ret != TRANSLATE_G_STAGE_FAIL) { /* Second stage lookup */ im_address = pa; -- 2.19.1