mirror of
https://github.com/qemu/qemu.git
synced 2026-07-09 01:56:21 +00:00
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:
committed by
Philippe Mathieu-Daudé
parent
ab7a864082
commit
56599a705f
@@ -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 */
|
||||
|
||||
@@ -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);
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user