Function loongarch_check_pte() can get physical address and access priviledge, it works on both TLB entry and pte entry. It can be used in function loongarch_page_table_walker() also.
Signed-off-by: Bibo Mao <maob...@loongson.cn> Reviewed-by: Richard Henderson <richard.hender...@linaro.org> --- target/loongarch/cpu_helper.c | 42 +++++++++++++---------------------- 1 file changed, 16 insertions(+), 26 deletions(-) diff --git a/target/loongarch/cpu_helper.c b/target/loongarch/cpu_helper.c index 5b140316bc..2cd43cd51d 100644 --- a/target/loongarch/cpu_helper.c +++ b/target/loongarch/cpu_helper.c @@ -106,15 +106,17 @@ TLBRet loongarch_check_pte(CPULoongArchState *env, MMUContext *context, } static TLBRet loongarch_page_table_walker(CPULoongArchState *env, - hwaddr *physical, - int *prot, vaddr address) + MMUContext *context, + int access_type, int mmu_idx) { CPUState *cs = env_cpu(env); target_ulong index, phys; uint64_t dir_base, dir_width; uint64_t base; int level; + vaddr address; + address = context->addr; if ((address >> 63) & 0x1) { base = env->CSR_PGDH; } else { @@ -156,29 +158,9 @@ static TLBRet loongarch_page_table_walker(CPULoongArchState *env, base = ldq_phys(cs->as, phys); } - /* TODO: check plv and other bits? */ - - /* base is pte, in normal pte format */ - if (!FIELD_EX64(base, TLBENTRY, V)) { - return TLBRET_NOMATCH; - } - - if (!FIELD_EX64(base, TLBENTRY, D)) { - *prot = PAGE_READ; - } else { - *prot = PAGE_READ | PAGE_WRITE; - } - - /* get TARGET_PAGE_SIZE aligned physical address */ - base += (address & TARGET_PHYS_MASK) & ((1 << dir_base) - 1); - /* mask RPLV, NX, NR bits */ - base = FIELD_DP64(base, TLBENTRY_64, RPLV, 0); - base = FIELD_DP64(base, TLBENTRY_64, NX, 0); - base = FIELD_DP64(base, TLBENTRY_64, NR, 0); - /* mask other attribute bits */ - *physical = base & TARGET_PAGE_MASK; - - return TLBRET_MATCH; + context->ps = dir_base; + context->pte = base; + return loongarch_check_pte(env, context, access_type, mmu_idx); } static TLBRet loongarch_map_address(CPULoongArchState *env, hwaddr *physical, @@ -187,7 +169,9 @@ static TLBRet loongarch_map_address(CPULoongArchState *env, hwaddr *physical, int is_debug) { TLBRet ret; + MMUContext context; + context.addr = address; if (tcg_enabled()) { ret = loongarch_get_addr_from_tlb(env, physical, prot, address, access_type, mmu_idx); @@ -202,7 +186,13 @@ static TLBRet loongarch_map_address(CPULoongArchState *env, hwaddr *physical, * legal mapping, even if the mapping is not yet in TLB. return 0 if * there is a valid map, else none zero. */ - return loongarch_page_table_walker(env, physical, prot, address); + ret = loongarch_page_table_walker(env, &context, access_type, mmu_idx); + if (ret == TLBRET_MATCH) { + *physical = context.physical; + *prot = context.prot; + } + + return ret; } return TLBRET_NOMATCH; -- 2.39.3