qemu-devel
[Top][All Lists]
Advanced

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

[Qemu-devel] [PATCH 6/6] PPC: booke206: Implement tlbilx


From: Alexander Graf
Subject: [Qemu-devel] [PATCH 6/6] PPC: booke206: Implement tlbilx
Date: Fri, 20 Jan 2012 04:17:29 +0100

The PowerPC 2.06 BookE ISA defines an opcode called "tlbilx" which is used
to flush TLB entries. It's the recommended way of flushing in virtualized
environments.

So far we got away without implementing it, but Linux for e500mc uses this
instruction, so we better add it :).

Signed-off-by: Alexander Graf <address@hidden>
---
 target-ppc/helper.h    |    1 +
 target-ppc/op_helper.c |   59 ++++++++++++++++++++++++++++++++++++++++++++++++
 target-ppc/translate.c |   25 ++++++++++++++++++++
 3 files changed, 85 insertions(+), 0 deletions(-)

diff --git a/target-ppc/helper.h b/target-ppc/helper.h
index 470e42f..1635767 100644
--- a/target-ppc/helper.h
+++ b/target-ppc/helper.h
@@ -336,6 +336,7 @@ DEF_HELPER_0(booke206_tlbre, void)
 DEF_HELPER_0(booke206_tlbwe, void)
 DEF_HELPER_1(booke206_tlbsx, void, tl)
 DEF_HELPER_1(booke206_tlbivax, void, tl)
+DEF_HELPER_2(booke206_tlbilx, void, tl, i32)
 DEF_HELPER_1(booke206_tlbflush, void, i32)
 DEF_HELPER_2(booke_setpid, void, i32, tl)
 DEF_HELPER_1(6xx_tlbd, void, tl)
diff --git a/target-ppc/op_helper.c b/target-ppc/op_helper.c
index 0a88bf4..7ae920a 100644
--- a/target-ppc/op_helper.c
+++ b/target-ppc/op_helper.c
@@ -4406,6 +4406,65 @@ void helper_booke206_tlbivax(target_ulong address)
     }
 }
 
+void helper_booke206_tlbilx(target_ulong address, uint32_t t)
+{
+    int tlb_size;
+    int i, j;
+    ppcmas_tlb_t *tlb = env->tlb.tlbm;
+    int tid = (env->spr[SPR_BOOKE_MAS6] & MAS6_SPID);
+    int pid = tid >> MAS6_SPID_SHIFT;
+    int sgs = env->spr[SPR_BOOKE_MAS5] & MAS5_SGS;
+    int ts = (env->spr[SPR_BOOKE_MAS6] & MAS6_SAS) ? MAS1_TS : 0;
+    int ind = (env->spr[SPR_BOOKE_MAS6] & MAS6_SIND) ? MAS1_IND : 0;
+    int size = env->spr[SPR_BOOKE_MAS6] & MAS6_ISIZE_MASK;
+
+    /* XXX missing LPID handling */
+    switch (t) {
+    case 0:
+        /* flush all */
+        booke206_flush_tlb(env, -1, 1);
+        break;
+    case 1:
+        /* flush by pid */
+        for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
+            tlb_size = booke206_tlb_size(env, i);
+            for (j = 0; j < tlb_size; j++) {
+                if (!(tlb[j].mas1 & MAS1_IPROT) &&
+                    ((tlb[j].mas1 & MAS1_TID_MASK) == tid)) {
+                    tlb[j].mas1 &= ~MAS1_VALID;
+                }
+            }
+            tlb += booke206_tlb_size(env, i);
+        }
+        tlb_flush(env, 1);
+        break;
+    case 3:
+        /* flush by pid and ea */
+        for (i = 0; i < BOOKE206_MAX_TLBN; i++) {
+            int ways = booke206_tlb_ways(env, i);
+
+            for (j = 0; j < ways; j++) {
+                tlb = booke206_get_tlbm(env, i, address, j);
+                if ((ppcmas_tlb_check(env, tlb, NULL, address, pid) != 0) ||
+                    (tlb->mas1 & MAS1_IPROT) ||
+                    ((tlb->mas1 & MAS1_TS) != ts) ||
+                    ((tlb->mas1 & MAS1_IND) != ind) ||
+                    ((tlb->mas1 & MAS1_TSIZE_MASK) != size) ||
+                    ((tlb->mas8 & MAS8_TGS) != sgs)) {
+                        continue;
+                }
+                tlb->mas1 &= ~MAS1_VALID;
+            }
+        }
+        tlb_flush(env, 1);
+        break;
+    default:
+        helper_raise_exception_err(POWERPC_EXCP_PROGRAM,
+                                   POWERPC_EXCP_INVAL |
+                                   POWERPC_EXCP_INVAL_INVAL);
+    }
+}
+
 void helper_booke206_tlbflush(uint32_t type)
 {
     int flags = 0;
diff --git a/target-ppc/translate.c b/target-ppc/translate.c
index 18d52a9..3cf4cce 100644
--- a/target-ppc/translate.c
+++ b/target-ppc/translate.c
@@ -6110,6 +6110,29 @@ static void gen_tlbivax_booke206(DisasContext *ctx)
 #endif
 }
 
+static void gen_tlbilx_booke206(DisasContext *ctx)
+{
+#if defined(CONFIG_USER_ONLY)
+    gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
+#else
+    TCGv t0;
+    TCGv_i32 t1;
+    if (unlikely(!ctx->mem_idx)) {
+        gen_inval_exception(ctx, POWERPC_EXCP_PRIV_OPC);
+        return;
+    }
+
+    t0 = tcg_temp_new();
+    t1 = tcg_const_i32((ctx->opcode >> 21) & 0x3);
+    gen_addr_reg_index(ctx, t0);
+
+    gen_helper_booke206_tlbilx(t0, t1);
+
+    tcg_temp_free(t0);
+    tcg_temp_free_i32(t1);
+#endif
+}
+
 
 /* wrtee */
 static void gen_wrtee(DisasContext *ctx)
@@ -8574,6 +8597,8 @@ GEN_HANDLER2_E(tlbwe_booke206, "tlbwe", 0x1F, 0x12, 0x1E, 
0x00000001,
                PPC_NONE, PPC2_BOOKE206),
 GEN_HANDLER2_E(tlbivax_booke206, "tlbivax", 0x1F, 0x12, 0x18, 0x00000001,
                PPC_NONE, PPC2_BOOKE206),
+GEN_HANDLER2_E(tlbilx_booke206, "tlbilx", 0x1F, 0x12, 0x00, 0x03800001,
+               PPC_NONE, PPC2_BOOKE206),
 GEN_HANDLER(wrtee, 0x1F, 0x03, 0x04, 0x000FFC01, PPC_WRTEE),
 GEN_HANDLER(wrteei, 0x1F, 0x03, 0x05, 0x000E7C01, PPC_WRTEE),
 GEN_HANDLER(dlmzb, 0x1F, 0x0E, 0x02, 0x00000000, PPC_440_SPEC),
-- 
1.6.0.2




reply via email to

[Prev in Thread] Current Thread [Next in Thread]