diff mbox

[2/14] target/mips: Fix TLBWI shadow flush for EHINV, XI, RI

Message ID cdee8fc6142bf90381edff96edc5773fd53f530d.1500378931.git-series.james.hogan@imgtec.com
State New
Headers show

Commit Message

James Hogan July 18, 2017, 11:55 a.m. UTC
Writing specific TLB entries with TLBWI flushes shadow TLB entries
unless an existing entry is having its access permissions upgraded. This
is necessary as software would from then on expect the previous mapping
in that entry to no longer be in effect (even if QEMU has quietly
evicted it to the shadow TLB on a TLBWR).

However it won't do this if only EHINV, XI, or RI bits have been set,
even if that results in a reduction of permissions, so add the necessary
checks to invoke the flush when these bits are set.

Fixes: 2fb58b73746e ("target-mips: add RI and XI fields to TLB entry")
Fixes: 9456c2fbcd82 ("target-mips: add TLBINV support")
Signed-off-by: James Hogan <james.hogan@imgtec.com>
Cc: Yongbok Kim <yongbok.kim@imgtec.com>
Cc: Aurelien Jarno <aurelien@aurel32.net>
---
Changes in v2:
- New patch.
---
 target/mips/op_helper.c | 12 ++++++++++--
 1 file changed, 10 insertions(+), 2 deletions(-)

Comments

Yongbok Kim July 20, 2017, 3:16 p.m. UTC | #1
On 18/07/2017 12:55, James Hogan wrote:
> Writing specific TLB entries with TLBWI flushes shadow TLB entries
> unless an existing entry is having its access permissions upgraded. This
> is necessary as software would from then on expect the previous mapping
> in that entry to no longer be in effect (even if QEMU has quietly
> evicted it to the shadow TLB on a TLBWR).
> 
> However it won't do this if only EHINV, XI, or RI bits have been set,
> even if that results in a reduction of permissions, so add the necessary
> checks to invoke the flush when these bits are set.
> 
> Fixes: 2fb58b73746e ("target-mips: add RI and XI fields to TLB entry")
> Fixes: 9456c2fbcd82 ("target-mips: add TLBINV support")
> Signed-off-by: James Hogan <james.hogan@imgtec.com>
> Cc: Yongbok Kim <yongbok.kim@imgtec.com>
> Cc: Aurelien Jarno <aurelien@aurel32.net>
> ---
> Changes in v2:
> - New patch.
> ---
>  target/mips/op_helper.c | 12 ++++++++++--
>  1 file changed, 10 insertions(+), 2 deletions(-)
> 
> diff --git a/target/mips/op_helper.c b/target/mips/op_helper.c
> index e5f3ea40420e..1961cacfab18 100644
> --- a/target/mips/op_helper.c
> +++ b/target/mips/op_helper.c
> @@ -2029,7 +2029,7 @@ void r4k_helper_tlbwi(CPUMIPSState *env)
>      int idx;
>      target_ulong VPN;
>      uint16_t ASID;
> -    bool G, V0, D0, V1, D1;
> +    bool EHINV, G, V0, D0, V1, D1, XI0, XI1, RI0, RI1;
>  
>      idx = (env->CP0_Index & ~0x80000000) % env->tlb->nb_tlb;
>      tlb = &env->tlb->mmu.r4k.tlb[idx];
> @@ -2038,17 +2038,25 @@ void r4k_helper_tlbwi(CPUMIPSState *env)
>      VPN &= env->SEGMask;
>  #endif
>      ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask;
> +    EHINV = (env->CP0_EntryHi & (1 << CP0EnHi_EHINV)) != 0;
>      G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1;
>      V0 = (env->CP0_EntryLo0 & 2) != 0;
>      D0 = (env->CP0_EntryLo0 & 4) != 0;
> +    XI0 = (env->CP0_EntryLo0 >> CP0EnLo_XI) & 1;
> +    RI0 = (env->CP0_EntryLo0 >> CP0EnLo_RI) & 1;
>      V1 = (env->CP0_EntryLo1 & 2) != 0;
>      D1 = (env->CP0_EntryLo1 & 4) != 0;
> +    XI1 = (env->CP0_EntryLo1 >> CP0EnLo_XI) & 1;
> +    RI1 = (env->CP0_EntryLo1 >> CP0EnLo_RI) & 1;
>  
>      /* Discard cached TLB entries, unless tlbwi is just upgrading access
>         permissions on the current entry. */
>      if (tlb->VPN != VPN || tlb->ASID != ASID || tlb->G != G ||
> +        (!tlb->EHINV && EHINV) ||
>          (tlb->V0 && !V0) || (tlb->D0 && !D0) ||
> -        (tlb->V1 && !V1) || (tlb->D1 && !D1)) {
> +        (!tlb->XI0 && XI0) || (!tlb->RI0 && RI0) ||
> +        (tlb->V1 && !V1) || (tlb->D1 && !D1) ||
> +        (!tlb->XI1 && XI1) || (!tlb->RI1 && RI1)) {
>          r4k_mips_tlb_flush_extra(env, env->tlb->nb_tlb);
>      }
>  
> 

Tested-by: Yongbok Kim <yongbok.kim@imgtec.com>

Regards,
Yongbok
diff mbox

Patch

diff --git a/target/mips/op_helper.c b/target/mips/op_helper.c
index e5f3ea40420e..1961cacfab18 100644
--- a/target/mips/op_helper.c
+++ b/target/mips/op_helper.c
@@ -2029,7 +2029,7 @@  void r4k_helper_tlbwi(CPUMIPSState *env)
     int idx;
     target_ulong VPN;
     uint16_t ASID;
-    bool G, V0, D0, V1, D1;
+    bool EHINV, G, V0, D0, V1, D1, XI0, XI1, RI0, RI1;
 
     idx = (env->CP0_Index & ~0x80000000) % env->tlb->nb_tlb;
     tlb = &env->tlb->mmu.r4k.tlb[idx];
@@ -2038,17 +2038,25 @@  void r4k_helper_tlbwi(CPUMIPSState *env)
     VPN &= env->SEGMask;
 #endif
     ASID = env->CP0_EntryHi & env->CP0_EntryHi_ASID_mask;
+    EHINV = (env->CP0_EntryHi & (1 << CP0EnHi_EHINV)) != 0;
     G = env->CP0_EntryLo0 & env->CP0_EntryLo1 & 1;
     V0 = (env->CP0_EntryLo0 & 2) != 0;
     D0 = (env->CP0_EntryLo0 & 4) != 0;
+    XI0 = (env->CP0_EntryLo0 >> CP0EnLo_XI) & 1;
+    RI0 = (env->CP0_EntryLo0 >> CP0EnLo_RI) & 1;
     V1 = (env->CP0_EntryLo1 & 2) != 0;
     D1 = (env->CP0_EntryLo1 & 4) != 0;
+    XI1 = (env->CP0_EntryLo1 >> CP0EnLo_XI) & 1;
+    RI1 = (env->CP0_EntryLo1 >> CP0EnLo_RI) & 1;
 
     /* Discard cached TLB entries, unless tlbwi is just upgrading access
        permissions on the current entry. */
     if (tlb->VPN != VPN || tlb->ASID != ASID || tlb->G != G ||
+        (!tlb->EHINV && EHINV) ||
         (tlb->V0 && !V0) || (tlb->D0 && !D0) ||
-        (tlb->V1 && !V1) || (tlb->D1 && !D1)) {
+        (!tlb->XI0 && XI0) || (!tlb->RI0 && RI0) ||
+        (tlb->V1 && !V1) || (tlb->D1 && !D1) ||
+        (!tlb->XI1 && XI1) || (!tlb->RI1 && RI1)) {
         r4k_mips_tlb_flush_extra(env, env->tlb->nb_tlb);
     }