diff mbox series

[V10,2/8] target/mips: Fix PageMask with variable page size

Message ID 1600742967-12933-3-git-send-email-chenhc@lemote.com
State New
Headers show
Series mips: Add Loongson-3 machine support | expand

Commit Message

Huacai Chen Sept. 22, 2020, 2:49 a.m. UTC
From: Jiaxun Yang <jiaxun.yang@flygoat.com>

Our current code assumed the target page size is always 4k
when handling PageMask and VPN2, however, variable page size
was just added to mips target and that's nolonger true.

Signed-off-by: Huacai Chen <chenhc@lemote.com>
Signed-off-by: Jiaxun Yang <jiaxun.yang@flygoat.com>
---
 target/mips/cp0_helper.c | 36 +++++++++++++++++++++++++++++-------
 target/mips/cpu.h        |  1 +
 2 files changed, 30 insertions(+), 7 deletions(-)

Comments

Carlo Arenas Sept. 22, 2020, 8 a.m. UTC | #1
On Mon, Sep 21, 2020 at 7:53 PM Huacai Chen <zltjiangshi@gmail.com> wrote:
> was just added to mips target and that's nolonger true.
s/nolonger/no longer/

IMHO might be worth also mentioning that it was added with ee3863b9d4
(target/mips: Support variable page size, 2020-04-08) to give a little
more context.

some other typos below might have been raised earlier as well.

> +     * When invalid, ensure the value is bigger tan or equel to

s/bigger tan or equel/bigger than or equal

> +     * the minimal but smaller than or equel to the maxium.

s/equel to the maxium/equal to the maximum

Carlo
Huacai Chen Sept. 22, 2020, 11:27 a.m. UTC | #2
Hi Carlo,

On Tue, Sep 22, 2020 at 4:00 PM Carlo Arenas <carenas@gmail.com> wrote:
>
> On Mon, Sep 21, 2020 at 7:53 PM Huacai Chen <zltjiangshi@gmail.com> wrote:
> > was just added to mips target and that's nolonger true.
> s/nolonger/no longer/
>
> IMHO might be worth also mentioning that it was added with ee3863b9d4
> (target/mips: Support variable page size, 2020-04-08) to give a little
> more context.
>
> some other typos below might have been raised earlier as well.
>
> > +     * When invalid, ensure the value is bigger tan or equel to
>
> s/bigger tan or equel/bigger than or equal
>
> > +     * the minimal but smaller than or equel to the maxium.
>
> s/equel to the maxium/equal to the maximum
OK, this will be improved.

>
> Carlo
diff mbox series

Patch

diff --git a/target/mips/cp0_helper.c b/target/mips/cp0_helper.c
index de64add038..62bcb9707e 100644
--- a/target/mips/cp0_helper.c
+++ b/target/mips/cp0_helper.c
@@ -867,13 +867,35 @@  void helper_mtc0_memorymapid(CPUMIPSState *env, target_ulong arg1)
 
 void update_pagemask(CPUMIPSState *env, target_ulong arg1, int32_t *pagemask)
 {
-    uint64_t mask = arg1 >> (TARGET_PAGE_BITS + 1);
-    if (!(env->insn_flags & ISA_MIPS32R6) || (arg1 == ~0) ||
-        (mask == 0x0000 || mask == 0x0003 || mask == 0x000F ||
-         mask == 0x003F || mask == 0x00FF || mask == 0x03FF ||
-         mask == 0x0FFF || mask == 0x3FFF || mask == 0xFFFF)) {
-        env->CP0_PageMask = arg1 & (0x1FFFFFFF & (TARGET_PAGE_MASK << 1));
+    unsigned long mask;
+    int maskbits;
+
+    if (env->insn_flags & ISA_MIPS32R6) {
+        return;
+    }
+    /* Don't care MASKX as we don't support 1KB page */
+    mask = extract32((uint32_t)arg1, CP0PM_MASK, 16);
+    maskbits = find_first_zero_bit(&mask, 32);
+
+    /* Ensure no more set bit after first zero */
+    if (mask >> maskbits) {
+        goto invalid;
+    }
+    /* We don't support VTLB entry smaller than target page */
+    if ((maskbits + 12) < TARGET_PAGE_BITS) {
+        goto invalid;
     }
+    env->CP0_PageMask = mask << CP0PM_MASK;
+
+    return;
+
+invalid:
+    /*
+     * When invalid, ensure the value is bigger tan or equel to
+     * the minimal but smaller than or equel to the maxium.
+     */
+    maskbits = MIN(16, MAX(maskbits, TARGET_PAGE_BITS - 12));
+    env->CP0_PageMask = ((1 << (16 + 1)) - 1) << CP0PM_MASK;
 }
 
 void helper_mtc0_pagemask(CPUMIPSState *env, target_ulong arg1)
@@ -1104,7 +1126,7 @@  void helper_mthc0_saar(CPUMIPSState *env, target_ulong arg1)
 void helper_mtc0_entryhi(CPUMIPSState *env, target_ulong arg1)
 {
     target_ulong old, val, mask;
-    mask = (TARGET_PAGE_MASK << 1) | env->CP0_EntryHi_ASID_mask;
+    mask = ~((1 << 14) - 1) | env->CP0_EntryHi_ASID_mask;
     if (((env->CP0_Config4 >> CP0C4_IE) & 0x3) >= 2) {
         mask |= 1 << CP0EnHi_EHINV;
     }
diff --git a/target/mips/cpu.h b/target/mips/cpu.h
index 7cf7f5239f..9c8bb23807 100644
--- a/target/mips/cpu.h
+++ b/target/mips/cpu.h
@@ -618,6 +618,7 @@  struct CPUMIPSState {
  * CP0 Register 5
  */
     int32_t CP0_PageMask;
+#define CP0PM_MASK 13
     int32_t CP0_PageGrain_rw_bitmask;
     int32_t CP0_PageGrain;
 #define CP0PG_RIE 31