Function loongarch_check_pte() can get physical address and access
priviledge, it works on both TLB entry and pte entry. It can be used
at page table walking.
Signed-off-by: Bibo Mao <maobibo@loongson.cn>
---
target/loongarch/cpu_helper.c | 35 ++++++++++-------------------------
1 file changed, 10 insertions(+), 25 deletions(-)
diff --git a/target/loongarch/cpu_helper.c b/target/loongarch/cpu_helper.c
index c90e260566..84191b5852 100644
--- a/target/loongarch/cpu_helper.c
+++ b/target/loongarch/cpu_helper.c
@@ -107,13 +107,15 @@ int loongarch_check_pte(CPULoongArchState *env, hwaddr *physical, int *prot,
}
static int loongarch_page_table_walker(CPULoongArchState *env, hwaddr *physical,
- int *prot, target_ulong address)
+ int *prot, target_ulong address,
+ 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;
+ mmu_context context;
if ((address >> 63) & 0x1) {
base = env->CSR_PGDH;
@@ -156,29 +158,11 @@ static int loongarch_page_table_walker(CPULoongArchState *env, hwaddr *physical,
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 0;
+ context.vaddr = address;
+ context.ps = dir_base;
+ context.pte = base;
+ return loongarch_check_pte(env, physical, prot, &context, access_type,
+ mmu_idx);
}
static int loongarch_map_address(CPULoongArchState *env, hwaddr *physical,
@@ -202,7 +186,8 @@ static int 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);
+ return loongarch_page_table_walker(env, physical, prot, address,
+ access_type, mmu_idx);
}
return TLBRET_NOMATCH;
--
2.39.3