aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBibo Mao <maobibo@loongson.cn>2025-07-29 16:10:02 +0800
committerBibo Mao <maobibo@loongson.cn>2025-08-29 10:05:02 +0800
commit3dd4a2d0fc339c3cb321d69a0372cb9433786105 (patch)
treef31dfd8b5ed8f546c0adf991a38a457842cdc1be
parent7392cb1c7b24e34987b6f2bbff00c39fe0829cc9 (diff)
downloadqemu-3dd4a2d0fc339c3cb321d69a0372cb9433786105.zip
qemu-3dd4a2d0fc339c3cb321d69a0372cb9433786105.tar.gz
qemu-3dd4a2d0fc339c3cb321d69a0372cb9433786105.tar.bz2
target/loongarch: Use loongarch_check_pte in loongarch_page_table_walker
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 <maobibo@loongson.cn> Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
-rw-r--r--target/loongarch/cpu_helper.c42
1 files changed, 16 insertions, 26 deletions
diff --git a/target/loongarch/cpu_helper.c b/target/loongarch/cpu_helper.c
index 739cdab..cd61b33 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;