qemu-ppc
[Top][All Lists]
Advanced

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

[RFC PATCH 16/17] target/ppc: Avoid flushing HV real translations


From: Nicholas Piggin
Subject: [RFC PATCH 16/17] target/ppc: Avoid flushing HV real translations
Date: Tue, 1 Apr 2025 00:46:50 +1000

Most TLB invalidations do not flush the HV real translation. HRMOR is
the only way to change the translation, so changing that register must
flush the full TLB, all others can get away without flushing the HV
real translation. This could help performance for real-mode firmware
and operating systems.

Signed-off-by: Nicholas Piggin <npiggin@gmail.com>
---
 target/ppc/cpu.h         | 12 +++++++-----
 target/ppc/cpu.c         |  2 +-
 target/ppc/helper_regs.c |  2 +-
 target/ppc/misc_helper.c |  8 ++++----
 target/ppc/mmu-hash64.c  |  8 +++++++-
 target/ppc/mmu_helper.c  | 10 ++++++----
 6 files changed, 26 insertions(+), 16 deletions(-)

diff --git a/target/ppc/cpu.h b/target/ppc/cpu.h
index cb0adba2ae7..ff14f5b8a7f 100644
--- a/target/ppc/cpu.h
+++ b/target/ppc/cpu.h
@@ -263,11 +263,13 @@ static inline bool mmu_is_64bit(powerpc_mmu_t mmu_model)
     return mmu_model & POWERPC_MMU_64;
 }
 
-#define USER_VIRT_MMUIDX_BITS   0x1
-#define PRIV_VIRT_MMUIDX_BITS   0x2
-#define VIRT_MMUIDX_BITS        (USER_VIRT_MMUIDX_BITS | PRIV_VIRT_MMUIDX_BITS)
-#define SV_REAL_MMUIDX_BITS     0x4
-#define HV_REAL_MMUIDX_BITS     0x8
+#define USER_VIRT_MMUIDX_BITS        0x1
+#define PRIV_VIRT_MMUIDX_BITS        0x2
+#define VIRT_MMUIDX_BITS             (USER_VIRT_MMUIDX_BITS |     \
+                                      PRIV_VIRT_MMUIDX_BITS)
+#define SV_REAL_MMUIDX_BITS          0x4
+#define HV_REAL_MMUIDX_BITS          0x8
+#define ALLBUT_HV_REAL_MMUIDX_BITS   0x7
 
 /*****************************************************************************/
 /* Input pins model                                                          */
diff --git a/target/ppc/cpu.c b/target/ppc/cpu.c
index 55f1d1c9830..73e5537740f 100644
--- a/target/ppc/cpu.c
+++ b/target/ppc/cpu.c
@@ -109,7 +109,7 @@ void ppc_store_lpcr(PowerPCCPU *cpu, target_ulong val)
     hreg_compute_hflags(env);
 
     if ((old ^ new) & LPCR_MMU_BITS) {
-        tlb_flush(env_cpu(env));
+        tlb_flush_by_mmuidx(env_cpu(env), ALLBUT_HV_REAL_MMUIDX_BITS);
     }
 
     ppc_maybe_interrupt(env);
diff --git a/target/ppc/helper_regs.c b/target/ppc/helper_regs.c
index b64eb59edf6..137620991c4 100644
--- a/target/ppc/helper_regs.c
+++ b/target/ppc/helper_regs.c
@@ -431,7 +431,7 @@ void check_tlb_flush(CPUPPCState *env, bool global)
     if (env->tlb_need_flush & TLB_NEED_LOCAL_FLUSH) {
         env->tlb_need_flush &= ~TLB_NEED_LOCAL_FLUSH;
         slb_destroy_rmaps(env);
-        tlb_flush(cs);
+        tlb_flush_by_mmuidx(cs, VIRT_MMUIDX_BITS);
     }
 }
 #endif /* !CONFIG_USER_ONLY */
diff --git a/target/ppc/misc_helper.c b/target/ppc/misc_helper.c
index 669bfbfda32..641f07eeb7e 100644
--- a/target/ppc/misc_helper.c
+++ b/target/ppc/misc_helper.c
@@ -220,7 +220,7 @@ void helper_store_ptcr(CPUPPCState *env, target_ulong val)
 
         if (ppc_cpu_lpar_single_threaded(cs)) {
             env->spr[SPR_PTCR] = val;
-            tlb_flush(cs);
+            tlb_flush_by_mmuidx(cs, ALLBUT_HV_REAL_MMUIDX_BITS);
         } else {
             CPUState *ccs;
 
@@ -228,7 +228,7 @@ void helper_store_ptcr(CPUPPCState *env, target_ulong val)
                 PowerPCCPU *ccpu = POWERPC_CPU(ccs);
                 CPUPPCState *cenv = &ccpu->env;
                 cenv->spr[SPR_PTCR] = val;
-                tlb_flush(ccs);
+                tlb_flush_by_mmuidx(ccs, ALLBUT_HV_REAL_MMUIDX_BITS);
             }
         }
     }
@@ -482,7 +482,7 @@ void helper_store_pidr(CPUPPCState *env, target_ulong val)
 
     if (env->spr[SPR_LPCR] & LPCR_HR) {
         /* PID is only relevant to CPU translations when LPCR[HR]=1 */
-        tlb_flush(env_cpu(env));
+        tlb_flush_by_mmuidx(env_cpu(env), ALLBUT_HV_REAL_MMUIDX_BITS);
     }
 }
 
@@ -500,7 +500,7 @@ void helper_store_lpidr(CPUPPCState *env, target_ulong val)
      * potentially access and cache entries for the current LPID as
      * well.
      */
-    tlb_flush(env_cpu(env));
+    tlb_flush_by_mmuidx(env_cpu(env), ALLBUT_HV_REAL_MMUIDX_BITS);
 }
 
 void helper_store_40x_dbcr0(CPUPPCState *env, target_ulong val)
diff --git a/target/ppc/mmu-hash64.c b/target/ppc/mmu-hash64.c
index d42d2cd4a6f..ccee4fb6036 100644
--- a/target/ppc/mmu-hash64.c
+++ b/target/ppc/mmu-hash64.c
@@ -208,6 +208,7 @@ static bool slb_get_clear_rmap(CPUPPCState *env, ppc_slb_t 
*slb)
 void helper_SLBIA(CPUPPCState *env, uint32_t ih)
 {
     PowerPCCPU *cpu = env_archcpu(env);
+    CPUState *cs = CPU(cpu);
     int starting_entry;
     int n;
 
@@ -232,7 +233,12 @@ void helper_SLBIA(CPUPPCState *env, uint32_t ih)
      * invalidated.
      */
 
-    env->tlb_need_flush |= TLB_NEED_LOCAL_FLUSH;
+    if (env->mmu_model == POWERPC_MMU_3_00 &&
+        env->spr[SPR_LPCR] & LPCR_HR) {
+        /* Radix mode does not flush */
+    } else {
+        tlb_flush_by_mmuidx(cs, VIRT_MMUIDX_BITS);
+    }
 
     starting_entry = 1; /* default for IH=0,1,2,6 */
 
diff --git a/target/ppc/mmu_helper.c b/target/ppc/mmu_helper.c
index 8e95fda4d0f..e1590091102 100644
--- a/target/ppc/mmu_helper.c
+++ b/target/ppc/mmu_helper.c
@@ -432,6 +432,7 @@ typedef struct TLBIEParams {
     uint32_t is;
     uint32_t ric;
     uint32_t prs;
+    uint16_t mmuidx;
     bool local;
     bool radix;
 } TLBIEParams;
@@ -475,11 +476,11 @@ static void tlb_do_flush_async_free_data(CPUState *cpu, 
run_on_cpu_data data)
      */
     if (!tlb_skip_flush(env, p)) {
         if (p->addr == 0 && p->len == (target_ulong)-1) {
-            do_tlb_flush_by_mmuidx_async(cpu, ALL_MMUIDX_BITS);
+            do_tlb_flush_by_mmuidx_async(cpu, p->mmuidx);
             slb_destroy_rmaps(env);
         } else {
             do_tlb_flush_range_by_mmuidx_async(cpu, p->addr, p->len,
-                                               ALL_MMUIDX_BITS,
+                                               p->mmuidx,
                                                TARGET_LONG_BITS);
         }
     }
@@ -495,11 +496,11 @@ static void tlb_do_flush(CPUPPCState *env, TLBIEParams *p)
     if (p->local) {
         if (!tlb_skip_flush(env, p)) {
             if (p->addr == 0 && p->len == (target_ulong)-1) {
-                do_tlb_flush_by_mmuidx_async(cpu, ALL_MMUIDX_BITS);
+                do_tlb_flush_by_mmuidx_async(cpu, p->mmuidx);
                 slb_destroy_rmaps(env);
             } else {
                 do_tlb_flush_range_by_mmuidx_async(cpu, p->addr, p->len,
-                                                   ALL_MMUIDX_BITS,
+                                                   p->mmuidx,
                                                    TARGET_LONG_BITS);
             }
         }
@@ -723,6 +724,7 @@ void helper_tlbie_isa300(CPUPPCState *env, target_ulong rb, 
target_ulong rs,
         .ric = (flags & TLBIE_F_RIC_MASK) >> TLBIE_F_RIC_SHIFT,
         .prs = flags & TLBIE_F_PRS,
         .local = flags & TLBIE_F_LOCAL,
+        .mmuidx = ALLBUT_HV_REAL_MMUIDX_BITS,
     };
     bool hv = FIELD_EX64(env->msr, MSR, HV);
     bool ret;
-- 
2.47.1




reply via email to

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