@@ -104,6 +104,7 @@ DEF_HELPER_2(csrwr_estat, i64, env, tl)
DEF_HELPER_2(csrwr_asid, i64, env, tl)
DEF_HELPER_2(csrwr_tcfg, i64, env, tl)
DEF_HELPER_2(csrwr_ticlr, i64, env, tl)
+DEF_HELPER_2(csrwr_pwcl, i64, env, tl)
DEF_HELPER_2(iocsrrd_b, i64, env, tl)
DEF_HELPER_2(iocsrrd_h, i64, env, tl)
DEF_HELPER_2(iocsrrd_w, i64, env, tl)
@@ -6,6 +6,7 @@
*/
#include "qemu/osdep.h"
+#include "qemu/log.h"
#include "qemu/main-loop.h"
#include "cpu.h"
#include "internals.h"
@@ -95,3 +96,23 @@ target_ulong helper_csrwr_ticlr(CPULoongArchState *env, target_ulong val)
}
return old_v;
}
+
+target_ulong helper_csrwr_pwcl(CPULoongArchState *env, target_ulong val)
+{
+ int shift;
+ int64_t old_v = env->CSR_PWCL;
+
+ /*
+ * The real hardware only supports 64bit PTE width now, 128bit or others
+ * treated as illegal.
+ */
+ shift = FIELD_EX64(val, CSR_PWCL, PTEWIDTH);
+ if (shift) {
+ qemu_log_mask(LOG_GUEST_ERROR,
+ "Attempted set pte width with %d bit\n", 64 << shift);
+ val = FIELD_DP64(val, CSR_PWCL, PTEWIDTH, 0);
+ }
+
+ env->CSR_PWCL = val;
+ return old_v;
+}
@@ -95,7 +95,7 @@ static const CSRInfo csr_info[] = {
CSR_OFF(PGDL),
CSR_OFF(PGDH),
CSR_OFF_FUNCS(PGD, CSRFL_READONLY, gen_helper_csrrd_pgd, NULL),
- CSR_OFF(PWCL),
+ CSR_OFF_FUNCS(PWCL, 0, NULL, gen_helper_csrwr_pwcl),
CSR_OFF(PWCH),
CSR_OFF(STLBPS),
CSR_OFF(RVACFG),
@@ -512,7 +512,6 @@ target_ulong helper_lddir(CPULoongArchState *env, target_ulong base,
{
CPUState *cs = env_cpu(env);
target_ulong badvaddr, index, phys, ret;
- int shift;
uint64_t dir_base, dir_width;
if (unlikely((level == 0) || (level > 4))) {
@@ -537,14 +536,9 @@ target_ulong helper_lddir(CPULoongArchState *env, target_ulong base,
badvaddr = env->CSR_TLBRBADV;
base = base & TARGET_PHYS_MASK;
-
- /* 0:64bit, 1:128bit, 2:192bit, 3:256bit */
- shift = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, PTEWIDTH);
- shift = (shift + 1) * 3;
-
get_dir_base_width(env, &dir_base, &dir_width, level);
index = (badvaddr >> dir_base) & ((1 << dir_width) - 1);
- phys = base | index << shift;
+ phys = base | index << 3;
ret = ldq_phys(cs->as, phys) & TARGET_PHYS_MASK;
return ret;
}
@@ -554,7 +548,6 @@ void helper_ldpte(CPULoongArchState *env, target_ulong base, target_ulong odd,
{
CPUState *cs = env_cpu(env);
target_ulong phys, tmp0, ptindex, ptoffset0, ptoffset1, ps, badv;
- int shift;
uint64_t ptbase = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, PTBASE);
uint64_t ptwidth = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, PTWIDTH);
uint64_t dir_base, dir_width;
@@ -595,16 +588,12 @@ void helper_ldpte(CPULoongArchState *env, target_ulong base, target_ulong odd,
tmp0 += MAKE_64BIT_MASK(ps, 1);
}
} else {
- /* 0:64bit, 1:128bit, 2:192bit, 3:256bit */
- shift = FIELD_EX64(env->CSR_PWCL, CSR_PWCL, PTEWIDTH);
- shift = (shift + 1) * 3;
badv = env->CSR_TLBRBADV;
ptindex = (badv >> ptbase) & ((1 << ptwidth) - 1);
ptindex = ptindex & ~0x1; /* clear bit 0 */
- ptoffset0 = ptindex << shift;
- ptoffset1 = (ptindex + 1) << shift;
-
+ ptoffset0 = ptindex << 3;
+ ptoffset1 = (ptindex + 1) << 3;
phys = base | (odd ? ptoffset1 : ptoffset0);
tmp0 = ldq_phys(cs->as, phys) & TARGET_PHYS_MASK;
ps = ptbase;