aboutsummaryrefslogtreecommitdiff
path: root/target/loongarch/tlb_helper.c
diff options
context:
space:
mode:
Diffstat (limited to 'target/loongarch/tlb_helper.c')
-rw-r--r--target/loongarch/tlb_helper.c66
1 files changed, 53 insertions, 13 deletions
diff --git a/target/loongarch/tlb_helper.c b/target/loongarch/tlb_helper.c
index 6e00190547..c8b8b0497f 100644
--- a/target/loongarch/tlb_helper.c
+++ b/target/loongarch/tlb_helper.c
@@ -48,10 +48,17 @@ static int loongarch_map_tlb_entry(CPULoongArchState *env, hwaddr *physical,
tlb_v = FIELD_EX64(tlb_entry, TLBENTRY, V);
tlb_d = FIELD_EX64(tlb_entry, TLBENTRY, D);
tlb_plv = FIELD_EX64(tlb_entry, TLBENTRY, PLV);
- tlb_ppn = FIELD_EX64(tlb_entry, TLBENTRY, PPN);
- tlb_nx = FIELD_EX64(tlb_entry, TLBENTRY, NX);
- tlb_nr = FIELD_EX64(tlb_entry, TLBENTRY, NR);
- tlb_rplv = FIELD_EX64(tlb_entry, TLBENTRY, RPLV);
+ if (is_la64(env)) {
+ tlb_ppn = FIELD_EX64(tlb_entry, TLBENTRY_64, PPN);
+ tlb_nx = FIELD_EX64(tlb_entry, TLBENTRY_64, NX);
+ tlb_nr = FIELD_EX64(tlb_entry, TLBENTRY_64, NR);
+ tlb_rplv = FIELD_EX64(tlb_entry, TLBENTRY_64, RPLV);
+ } else {
+ tlb_ppn = FIELD_EX64(tlb_entry, TLBENTRY_32, PPN);
+ tlb_nx = 0;
+ tlb_nr = 0;
+ tlb_rplv = 0;
+ }
/* Check access rights */
if (!tlb_v) {
@@ -79,7 +86,7 @@ static int loongarch_map_tlb_entry(CPULoongArchState *env, hwaddr *physical,
* tlb_entry contains ppn[47:12] while 16KiB ppn is [47:15]
* need adjust.
*/
- *physical = (tlb_ppn << R_TLBENTRY_PPN_SHIFT) |
+ *physical = (tlb_ppn << R_TLBENTRY_64_PPN_SHIFT) |
(address & MAKE_64BIT_MASK(0, tlb_ps));
*prot = PAGE_READ;
if (tlb_d) {
@@ -166,6 +173,18 @@ static int loongarch_map_address(CPULoongArchState *env, hwaddr *physical,
return TLBRET_NOMATCH;
}
+static hwaddr dmw_va2pa(CPULoongArchState *env, target_ulong va,
+ target_ulong dmw)
+{
+ if (is_la64(env)) {
+ return va & TARGET_VIRT_MASK;
+ } else {
+ uint32_t pseg = FIELD_EX32(dmw, CSR_DMW_32, PSEG);
+ return (va & MAKE_64BIT_MASK(0, R_CSR_DMW_32_VSEG_SHIFT)) | \
+ (pseg << R_CSR_DMW_32_VSEG_SHIFT);
+ }
+}
+
static int get_physical_address(CPULoongArchState *env, hwaddr *physical,
int *prot, target_ulong address,
MMUAccessType access_type, int mmu_idx)
@@ -185,12 +204,20 @@ static int get_physical_address(CPULoongArchState *env, hwaddr *physical,
}
plv = kernel_mode | (user_mode << R_CSR_DMW_PLV3_SHIFT);
- base_v = address >> R_CSR_DMW_VSEG_SHIFT;
+ if (is_la64(env)) {
+ base_v = address >> R_CSR_DMW_64_VSEG_SHIFT;
+ } else {
+ base_v = address >> R_CSR_DMW_32_VSEG_SHIFT;
+ }
/* Check direct map window */
for (int i = 0; i < 4; i++) {
- base_c = FIELD_EX64(env->CSR_DMW[i], CSR_DMW, VSEG);
+ if (is_la64(env)) {
+ base_c = FIELD_EX64(env->CSR_DMW[i], CSR_DMW_64, VSEG);
+ } else {
+ base_c = FIELD_EX64(env->CSR_DMW[i], CSR_DMW_32, VSEG);
+ }
if ((plv & env->CSR_DMW[i]) && (base_c == base_v)) {
- *physical = dmw_va2pa(address);
+ *physical = dmw_va2pa(env, address, env->CSR_DMW[i]);
*prot = PAGE_READ | PAGE_WRITE | PAGE_EXEC;
return TLBRET_MATCH;
}
@@ -273,8 +300,13 @@ static void raise_mmu_exception(CPULoongArchState *env, target_ulong address,
if (tlb_error == TLBRET_NOMATCH) {
env->CSR_TLBRBADV = address;
- env->CSR_TLBREHI = FIELD_DP64(env->CSR_TLBREHI, CSR_TLBREHI, VPPN,
- extract64(address, 13, 35));
+ if (is_la64(env)) {
+ env->CSR_TLBREHI = FIELD_DP64(env->CSR_TLBREHI, CSR_TLBREHI_64,
+ VPPN, extract64(address, 13, 35));
+ } else {
+ env->CSR_TLBREHI = FIELD_DP64(env->CSR_TLBREHI, CSR_TLBREHI_32,
+ VPPN, extract64(address, 13, 19));
+ }
} else {
if (!FIELD_EX64(env->CSR_DBG, CSR_DBG, DST)) {
env->CSR_BADV = address;
@@ -339,12 +371,20 @@ static void fill_tlb_entry(CPULoongArchState *env, int index)
if (FIELD_EX64(env->CSR_TLBRERA, CSR_TLBRERA, ISTLBR)) {
csr_ps = FIELD_EX64(env->CSR_TLBREHI, CSR_TLBREHI, PS);
- csr_vppn = FIELD_EX64(env->CSR_TLBREHI, CSR_TLBREHI, VPPN);
+ if (is_la64(env)) {
+ csr_vppn = FIELD_EX64(env->CSR_TLBREHI, CSR_TLBREHI_64, VPPN);
+ } else {
+ csr_vppn = FIELD_EX64(env->CSR_TLBREHI, CSR_TLBREHI_32, VPPN);
+ }
lo0 = env->CSR_TLBRELO0;
lo1 = env->CSR_TLBRELO1;
} else {
csr_ps = FIELD_EX64(env->CSR_TLBIDX, CSR_TLBIDX, PS);
- csr_vppn = FIELD_EX64(env->CSR_TLBEHI, CSR_TLBEHI, VPPN);
+ if (is_la64(env)) {
+ csr_vppn = FIELD_EX64(env->CSR_TLBEHI, CSR_TLBEHI_64, VPPN);
+ } else {
+ csr_vppn = FIELD_EX64(env->CSR_TLBEHI, CSR_TLBEHI_32, VPPN);
+ }
lo0 = env->CSR_TLBELO0;
lo1 = env->CSR_TLBELO1;
}
@@ -464,7 +504,7 @@ void helper_tlbfill(CPULoongArchState *env)
if (pagesize == stlb_ps) {
/* Only write into STLB bits [47:13] */
- address = entryhi & ~MAKE_64BIT_MASK(0, R_CSR_TLBEHI_VPPN_SHIFT);
+ address = entryhi & ~MAKE_64BIT_MASK(0, R_CSR_TLBEHI_64_VPPN_SHIFT);
/* Choose one set ramdomly */
set = get_random_tlb(0, 7);