Plugs a hole in the API by which one cannot flush the
entire address space with one range.  There are only a
few users, so it's easy to update them all at once.

Signed-off-by: Richard Henderson <[email protected]>
---
 include/exec/cputlb.h             | 12 ++++++------
 accel/tcg/cputlb.c                | 27 ++++++++++++++++-----------
 target/arm/tcg/tlb-insns.c        | 21 +++++++++++----------
 target/hppa/mem_helper.c          |  3 +--
 target/loongarch/tcg/tlb_helper.c |  5 +++--
 target/ppc/mmu_helper.c           |  4 ++--
 6 files changed, 39 insertions(+), 33 deletions(-)

diff --git a/include/exec/cputlb.h b/include/exec/cputlb.h
index f7f7020382..30e1d1f93e 100644
--- a/include/exec/cputlb.h
+++ b/include/exec/cputlb.h
@@ -209,21 +209,21 @@ void 
tlb_flush_page_bits_by_mmuidx_all_cpus_synced(CPUState *cpu, vaddr addr,
  * tlb_flush_range_by_mmuidx
  * @cpu: CPU whose TLB should be flushed
  * @addr: virtual address of the start of the range to be flushed
- * @len: length of range to be flushed
+ * @last: virtual address of the end of the range to be flushed, inclusive
  * @idxmap: bitmap of mmu indexes to flush
  * @bits: number of significant bits in address
  *
- * For each mmuidx in @idxmap, flush all pages within [@addr,@addr+@len),
+ * For each mmuidx in @idxmap, flush all pages within [@addr,@last]
  * comparing only the low @bits worth of each virtual page.
  */
 void tlb_flush_range_by_mmuidx(CPUState *cpu, vaddr addr,
-                               vaddr len, MMUIdxMap idxmap,
+                               vaddr last, MMUIdxMap idxmap,
                                unsigned bits);
 
 /* Similarly, with broadcast and syncing. */
 void tlb_flush_range_by_mmuidx_all_cpus_synced(CPUState *cpu,
                                                vaddr addr,
-                                               vaddr len,
+                                               vaddr last,
                                                MMUIdxMap idxmap,
                                                unsigned bits);
 #else
@@ -268,13 +268,13 @@ tlb_flush_page_bits_by_mmuidx_all_cpus_synced(CPUState 
*cpu, vaddr addr,
 {
 }
 static inline void tlb_flush_range_by_mmuidx(CPUState *cpu, vaddr addr,
-                                             vaddr len, MMUIdxMap idxmap,
+                                             vaddr last, MMUIdxMap idxmap,
                                              unsigned bits)
 {
 }
 static inline void tlb_flush_range_by_mmuidx_all_cpus_synced(CPUState *cpu,
                                                              vaddr addr,
-                                                             vaddr len,
+                                                             vaddr last,
                                                              MMUIdxMap idxmap,
                                                              unsigned bits)
 {
diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
index 2c0f7bed52..0a49b87bcb 100644
--- a/accel/tcg/cputlb.c
+++ b/accel/tcg/cputlb.c
@@ -761,13 +761,12 @@ static void tlb_flush_range_by_mmuidx_async_1(CPUState 
*cpu,
     g_free(d);
 }
 
-void tlb_flush_range_by_mmuidx(CPUState *cpu, vaddr addr,
-                               vaddr len, MMUIdxMap idxmap,
-                               unsigned bits)
+void tlb_flush_range_by_mmuidx(CPUState *cpu, vaddr addr, vaddr last,
+                               MMUIdxMap idxmap, unsigned bits)
 {
     TLBFlushRangeData d = {
         .addr = addr & TARGET_PAGE_MASK,
-        .last = (addr + len - 1) & TARGET_PAGE_MASK,
+        .last = last & TARGET_PAGE_MASK,
         .idxmap = idxmap,
         .bits = bits,
     };
@@ -795,18 +794,20 @@ void tlb_flush_range_by_mmuidx(CPUState *cpu, vaddr addr,
 void tlb_flush_page_bits_by_mmuidx(CPUState *cpu, vaddr addr,
                                    MMUIdxMap idxmap, unsigned bits)
 {
-    tlb_flush_range_by_mmuidx(cpu, addr, TARGET_PAGE_SIZE, idxmap, bits);
+    /*
+     * The implementation above only cares about the page of @last,
+     * so we don't need to find the end of the page for @addr.
+     */
+    tlb_flush_range_by_mmuidx(cpu, addr, addr, idxmap, bits);
 }
 
 void tlb_flush_range_by_mmuidx_all_cpus_synced(CPUState *src_cpu,
-                                               vaddr addr,
-                                               vaddr len,
-                                               MMUIdxMap idxmap,
-                                               unsigned bits)
+                                               vaddr addr, vaddr last,
+                                               MMUIdxMap idxmap, unsigned bits)
 {
     TLBFlushRangeData d = {
         .addr = addr & TARGET_PAGE_MASK,
-        .last = (addr + len - 1) & TARGET_PAGE_MASK,
+        .last = last & TARGET_PAGE_MASK,
         .idxmap = idxmap,
         .bits = bits,
     };
@@ -847,7 +848,11 @@ void 
tlb_flush_page_bits_by_mmuidx_all_cpus_synced(CPUState *src_cpu,
                                                    MMUIdxMap idxmap,
                                                    unsigned bits)
 {
-    tlb_flush_range_by_mmuidx_all_cpus_synced(src_cpu, addr, TARGET_PAGE_SIZE,
+    /*
+     * The implementation above only cares about the page of @last,
+     * so we don't need to find the end of the page for @addr.
+     */
+    tlb_flush_range_by_mmuidx_all_cpus_synced(src_cpu, addr, addr,
                                               idxmap, bits);
 }
 
diff --git a/target/arm/tcg/tlb-insns.c b/target/arm/tcg/tlb-insns.c
index b24eb57788..cf1698941c 100644
--- a/target/arm/tcg/tlb-insns.c
+++ b/target/arm/tcg/tlb-insns.c
@@ -819,7 +819,7 @@ static const ARMCPRegInfo tlbi_el3_cp_reginfo[] = {
 
 typedef struct {
     uint64_t base;
-    uint64_t length;
+    uint64_t last;
 } TLBIRange;
 
 static ARMGranuleSize tlbi_range_tg_to_gran_size(int tg)
@@ -847,8 +847,8 @@ static TLBIRange tlbi_aa64_get_range(CPUARMState *env, 
ARMMMUIdx mmuidx,
     /* Extract one bit to represent the va selector in use. */
     uint64_t select = sextract64(value, 36, 1);
     ARMVAParameters param = aa64_va_parameters(env, select, mmuidx, true, 
false);
-    TLBIRange ret = { };
     ARMGranuleSize gran;
+    uint64_t base, length;
 
     page_size_granule = extract64(value, 46, 2);
     gran = tlbi_range_tg_to_gran_size(page_size_granule);
@@ -857,7 +857,8 @@ static TLBIRange tlbi_aa64_get_range(CPUARMState *env, 
ARMMMUIdx mmuidx,
     if (gran != param.gran || gran == GranInvalid) {
         qemu_log_mask(LOG_GUEST_ERROR, "Invalid tlbi page size granule %d\n",
                       page_size_granule);
-        return ret;
+        /* The behaviour of the insn is undefined. */
+        return (TLBIRange) { 0, 0 };
     }
 
     page_shift = arm_granule_bits(gran);
@@ -865,12 +866,12 @@ static TLBIRange tlbi_aa64_get_range(CPUARMState *env, 
ARMMMUIdx mmuidx,
     scale = extract64(value, 44, 2);
     exponent = (5 * scale) + 1;
 
-    ret.length = (num + 1) << (exponent + page_shift);
+    length = (num + 1) << (exponent + page_shift);
 
     if (param.select) {
-        ret.base = sextract64(value, 0, 37);
+        base = sextract64(value, 0, 37);
     } else {
-        ret.base = extract64(value, 0, 37);
+        base = extract64(value, 0, 37);
     }
     if (param.ds) {
         /*
@@ -880,9 +881,9 @@ static TLBIRange tlbi_aa64_get_range(CPUARMState *env, 
ARMMMUIdx mmuidx,
          */
         page_shift = 16;
     }
-    ret.base <<= page_shift;
+    base <<= page_shift;
 
-    return ret;
+    return (TLBIRange){ .base = base, .last = base + length - 1 };
 }
 
 static void do_rvae_write(CPUARMState *env, uint64_t value,
@@ -898,12 +899,12 @@ static void do_rvae_write(CPUARMState *env, uint64_t 
value,
     if (synced) {
         tlb_flush_range_by_mmuidx_all_cpus_synced(env_cpu(env),
                                                   range.base,
-                                                  range.length,
+                                                  range.last,
                                                   idxmap,
                                                   bits);
     } else {
         tlb_flush_range_by_mmuidx(env_cpu(env), range.base,
-                                  range.length, idxmap, bits);
+                                  range.last, idxmap, bits);
     }
 }
 
diff --git a/target/hppa/mem_helper.c b/target/hppa/mem_helper.c
index 01e6149c81..394e975533 100644
--- a/target/hppa/mem_helper.c
+++ b/target/hppa/mem_helper.c
@@ -106,8 +106,7 @@ static void hppa_flush_tlb_ent(CPUHPPAState *env, 
HPPATLBEntry *ent,
     trace_hppa_tlb_flush_ent(env, ent, ent->itree.start,
                              ent->itree.last, ent->pa);
 
-    tlb_flush_range_by_mmuidx(cs, ent->itree.start,
-                              ent->itree.last - ent->itree.start + 1,
+    tlb_flush_range_by_mmuidx(cs, ent->itree.start, ent->itree.last,
                               HPPA_MMU_FLUSH_MASK, TARGET_LONG_BITS);
 
     /* Never clear BTLBs, unless forced to do so. */
diff --git a/target/loongarch/tcg/tlb_helper.c 
b/target/loongarch/tcg/tlb_helper.c
index a4b90beca6..3a708ebf3a 100644
--- a/target/loongarch/tcg/tlb_helper.c
+++ b/target/loongarch/tcg/tlb_helper.c
@@ -130,13 +130,14 @@ static void invalidate_tlb_entry(CPULoongArchState *env, 
int index)
 
     tlb_v = pte_present(env, tlb->tlb_entry0);
     if (tlb_v) {
-        tlb_flush_range_by_mmuidx(env_cpu(env), addr, pagesize,
+        tlb_flush_range_by_mmuidx(env_cpu(env), addr, addr + pagesize - 1,
                                   idxmap, TARGET_LONG_BITS);
     }
 
     tlb_v = pte_present(env, tlb->tlb_entry1);
     if (tlb_v) {
-        tlb_flush_range_by_mmuidx(env_cpu(env), addr + pagesize, pagesize,
+        tlb_flush_range_by_mmuidx(env_cpu(env), addr + pagesize,
+                                  addr + 2 * pagesize - 1,
                                   idxmap, TARGET_LONG_BITS);
     }
 }
diff --git a/target/ppc/mmu_helper.c b/target/ppc/mmu_helper.c
index ac60705402..c881191749 100644
--- a/target/ppc/mmu_helper.c
+++ b/target/ppc/mmu_helper.c
@@ -734,8 +734,8 @@ static void ppcemb_tlb_flush(CPUState *cs, ppcemb_tlb_t 
*tlb)
         mmu_idx <<= 2;
     }
 
-    tlb_flush_range_by_mmuidx(cs, tlb->EPN, tlb->size, mmu_idx,
-                              TARGET_LONG_BITS);
+    tlb_flush_range_by_mmuidx(cs, tlb->EPN, tlb->EPN + tlb->size - 1,
+                              mmu_idx, TARGET_LONG_BITS);
 }
 
 void helper_4xx_tlbwe_hi(CPUPPCState *env, target_ulong entry,
-- 
2.43.0


Reply via email to