target/loongarch: Introduce loongarch_palen_mask()

In preparation for dropping TARGET_PHYS_ADDR_SPACE_BITS, define a
runtime function to construct a mask from the PALEN cpucfg field.
The mask is then used when converting from virtual to physical
addresses.

Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Signed-off-by: Anton Johansson <anjo@rev.ng>
Message-ID: <20260218-phys_addr-v6-4-a603bf363218@rev.ng>
Signed-off-by: Philippe Mathieu-Daudé <philmd@linaro.org>
This commit is contained in:
Anton Johansson
2025-12-09 14:56:05 +01:00
committed by Philippe Mathieu-Daudé
parent ab7a864082
commit 56599a705f
4 changed files with 21 additions and 8 deletions

View File

@@ -98,5 +98,6 @@ TLBRet loongarch_ptw(CPULoongArchState *env, MMUContext *context,
void get_dir_base_width(CPULoongArchState *env, uint64_t *dir_base,
uint64_t *dir_width, unsigned int level);
hwaddr loongarch_cpu_get_phys_page_debug(CPUState *cpu, vaddr addr);
uint64_t loongarch_palen_mask(CPULoongArchState *env);
#endif /* LOONGARCH_CPU_MMU_H */

View File

@@ -147,6 +147,7 @@ TLBRet loongarch_ptw(CPULoongArchState *env, MMUContext *context,
{
CPUState *cs = env_cpu(env);
hwaddr index = 0, phys = 0;
uint64_t palen_mask = loongarch_palen_mask(env);
uint64_t dir_base, dir_width;
uint64_t base, pte;
int level;
@@ -154,13 +155,14 @@ TLBRet loongarch_ptw(CPULoongArchState *env, MMUContext *context,
TLBRet ret;
MemTxResult ret1;
address = context->addr;
if ((address >> 63) & 0x1) {
base = env->CSR_PGDH;
} else {
base = env->CSR_PGDL;
}
base &= TARGET_PHYS_MASK;
base &= palen_mask;
for (level = 4; level >= 0; level--) {
get_dir_base_width(env, &dir_base, &dir_width, level);
@@ -181,7 +183,7 @@ TLBRet loongarch_ptw(CPULoongArchState *env, MMUContext *context,
break;
} else {
/* Discard high bits with page directory table */
base &= TARGET_PHYS_MASK;
base &= palen_mask;
}
}
}
@@ -315,7 +317,7 @@ TLBRet get_physical_address(CPULoongArchState *env, MMUContext *context,
/* Check PG and DA */
address = context->addr;
if (da & !pg) {
context->physical = address & TARGET_PHYS_MASK;
context->physical = address & loongarch_palen_mask(env);
context->prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
context->mmu_index = MMU_DA_IDX;
return TLBRET_MATCH;
@@ -364,3 +366,10 @@ hwaddr loongarch_cpu_get_phys_page_debug(CPUState *cs, vaddr addr)
}
return context.physical;
}
uint64_t loongarch_palen_mask(CPULoongArchState *env)
{
/* PALEN stores physical address bits - 1 */
uint64_t phys_bits = FIELD_EX32(env->cpucfg[1], CPUCFG1, PALEN) + 1;
return MAKE_64BIT_MASK(0, phys_bits);
}

View File

@@ -13,7 +13,6 @@
#define FCMP_UN 0b0100 /* unordered */
#define FCMP_GT 0b1000 /* fp0 > fp1 */
#define TARGET_PHYS_MASK MAKE_64BIT_MASK(0, TARGET_PHYS_ADDR_SPACE_BITS)
#define TARGET_VIRT_MASK MAKE_64BIT_MASK(0, TARGET_VIRT_ADDR_SPACE_BITS)
void loongarch_translate_init(void);

View File

@@ -692,8 +692,10 @@ target_ulong helper_lddir(CPULoongArchState *env, target_ulong base,
CPUState *cs = env_cpu(env);
uint64_t badvaddr;
hwaddr index, phys;
uint64_t palen_mask = loongarch_palen_mask(env);
uint64_t dir_base, dir_width;
if (unlikely((level == 0) || (level > 4))) {
qemu_log_mask(LOG_GUEST_ERROR,
"Attepted LDDIR with level %u\n", level);
@@ -715,11 +717,11 @@ target_ulong helper_lddir(CPULoongArchState *env, target_ulong base,
}
badvaddr = env->CSR_TLBRBADV;
base = base & TARGET_PHYS_MASK;
base = base & palen_mask;
get_dir_base_width(env, &dir_base, &dir_width, level);
index = (badvaddr >> dir_base) & ((1 << dir_width) - 1);
phys = base | index << 3;
return ldq_le_phys(cs->as, phys) & TARGET_PHYS_MASK;
return ldq_le_phys(cs->as, phys) & palen_mask;
}
void helper_ldpte(CPULoongArchState *env, target_ulong base, target_ulong odd,
@@ -730,9 +732,11 @@ void helper_ldpte(CPULoongArchState *env, target_ulong base, target_ulong odd,
uint64_t badv;
uint64_t ptbase = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, PTBASE);
uint64_t ptwidth = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, PTWIDTH);
uint64_t palen_mask = loongarch_palen_mask(env);
uint64_t dir_base, dir_width;
uint8_t ps;
/*
* The parameter "base" has only two types,
* one is the page table base address,
@@ -740,7 +744,7 @@ void helper_ldpte(CPULoongArchState *env, target_ulong base, target_ulong odd,
* and the other is the huge page entry,
* whose bit 6 should be 1.
*/
base = base & TARGET_PHYS_MASK;
base = base & palen_mask;
if (FIELD_EX64(base, TLBENTRY, HUGE)) {
/*
* Gets the huge page level and Gets huge page size.
@@ -781,7 +785,7 @@ void helper_ldpte(CPULoongArchState *env, target_ulong base, target_ulong odd,
ptoffset0 = ptindex << 3;
ptoffset1 = (ptindex + 1) << 3;
phys = base | (odd ? ptoffset1 : ptoffset0);
tmp0 = ldq_le_phys(cs->as, phys) & TARGET_PHYS_MASK;
tmp0 = ldq_le_phys(cs->as, phys) & palen_mask;
ps = ptbase;
}