Change from addr/len to addr/last in the implementation.

Signed-off-by: Richard Henderson <[email protected]>
---
 accel/tcg/cputlb.c | 71 +++++++++++++++++++++++++---------------------
 1 file changed, 38 insertions(+), 33 deletions(-)

diff --git a/accel/tcg/cputlb.c b/accel/tcg/cputlb.c
index c8ba727859..2c0f7bed52 100644
--- a/accel/tcg/cputlb.c
+++ b/accel/tcg/cputlb.c
@@ -655,7 +655,7 @@ void tlb_flush_page_all_cpus_synced(CPUState *src, vaddr 
addr)
 }
 
 static void tlb_flush_range_locked(CPUState *cpu, int midx,
-                                   vaddr addr, vaddr len,
+                                   vaddr addr, vaddr last,
                                    unsigned bits)
 {
     CPUTLBDesc *d = &cpu->neg.tlb.d[midx];
@@ -669,13 +669,13 @@ static void tlb_flush_range_locked(CPUState *cpu, int 
midx,
      * TODO: Perhaps allow bits to be a few bits less than the size.
      * For now, just flush the entire TLB.
      *
-     * If @len is larger than the tlb size, then it will take longer to
+     * If [addr:last] is larger than the tlb size, then it will take longer to
      * test all of the entries in the TLB than it will to flush it all.
      */
-    if (mask < f->mask || len > f->mask) {
+    if (mask < f->mask || ((addr ^ last) & ~f->mask) != 0) {
         tlb_debug("forcing full flush midx %d ("
-                  "%016" VADDR_PRIx "/%016" VADDR_PRIx "+%016" VADDR_PRIx 
")\n",
-                  midx, addr, mask, len);
+                  "%016" VADDR_PRIx "/%016" VADDR_PRIx "-%016" VADDR_PRIx 
")\n",
+                  midx, addr, mask, last);
         tlb_flush_one_mmuidx_locked(cpu, midx, get_clock_realtime());
         return;
     }
@@ -685,7 +685,7 @@ static void tlb_flush_range_locked(CPUState *cpu, int midx,
      * Because large_page_mask contains all 1's from the msb,
      * we only need to test the end of the range.
      */
-    if (((addr + len - 1) & d->large_page_mask) == d->large_page_addr) {
+    if ((last & d->large_page_mask) == d->large_page_addr) {
         tlb_debug("forcing full flush midx %d ("
                   "%016" VADDR_PRIx "/%016" VADDR_PRIx ")\n",
                   midx, d->large_page_addr, d->large_page_mask);
@@ -693,20 +693,23 @@ static void tlb_flush_range_locked(CPUState *cpu, int 
midx,
         return;
     }
 
-    for (vaddr i = 0; i < len; i += TARGET_PAGE_SIZE) {
-        vaddr page = addr + i;
+    for (vaddr page = addr; ; page += TARGET_PAGE_SIZE) {
         CPUTLBEntry *entry = tlb_entry(cpu, midx, page);
 
         if (tlb_flush_entry_mask_locked(entry, page, mask)) {
             tlb_n_used_entries_dec(cpu, midx);
         }
         tlb_flush_vtlb_page_mask_locked(cpu, midx, page, mask);
+
+        if (page == last) {
+            break;
+        }
     }
 }
 
 typedef struct {
     vaddr addr;
-    vaddr len;
+    vaddr last;
     MMUIdxMap idxmap;
     unsigned bits;
 } TLBFlushRangeData;
@@ -718,13 +721,13 @@ static void tlb_flush_range_by_mmuidx_async_0(CPUState 
*cpu,
 
     assert_cpu_is_self(cpu);
 
-    tlb_debug("range: %016" VADDR_PRIx "/%u+%016" VADDR_PRIx " mmu_map:0x%x\n",
-              d.addr, d.bits, d.len, d.idxmap);
+    tlb_debug("range: %016" VADDR_PRIx "/%u-%016" VADDR_PRIx " mmu_map:0x%x\n",
+              d.addr, d.bits, d.last, d.idxmap);
 
     qemu_spin_lock(&cpu->neg.tlb.c.lock);
     for (mmu_idx = 0; mmu_idx < NB_MMU_MODES; mmu_idx++) {
         if ((d.idxmap >> mmu_idx) & 1) {
-            tlb_flush_range_locked(cpu, mmu_idx, d.addr, d.len, d.bits);
+            tlb_flush_range_locked(cpu, mmu_idx, d.addr, d.last, d.bits);
         }
     }
     qemu_spin_unlock(&cpu->neg.tlb.c.lock);
@@ -733,7 +736,7 @@ static void tlb_flush_range_by_mmuidx_async_0(CPUState *cpu,
      * If the length is larger than the jump cache size, then it will take
      * longer to clear each entry individually than it will to clear it all.
      */
-    if (d.len >= (TARGET_PAGE_SIZE * TB_JMP_CACHE_SIZE)) {
+    if (((d.last - d.addr) >> TARGET_PAGE_SIZE) + 1 >= TB_JMP_CACHE_SIZE) {
         tcg_flush_jmp_cache(cpu);
         return;
     }
@@ -742,10 +745,11 @@ static void tlb_flush_range_by_mmuidx_async_0(CPUState 
*cpu,
      * Discard jump cache entries for any tb which might potentially
      * overlap the flushed pages, which includes the previous.
      */
-    d.addr -= TARGET_PAGE_SIZE;
-    for (vaddr i = 0, n = d.len / TARGET_PAGE_SIZE + 1; i < n; i++) {
-        tb_jmp_cache_clear_page(cpu, d.addr);
-        d.addr += TARGET_PAGE_SIZE;
+    tb_jmp_cache_clear_page(cpu, d.addr - TARGET_PAGE_SIZE);
+    for (vaddr page = d.addr; ; page += TARGET_PAGE_SIZE) {
+        if (page == d.last) {
+            break;
+        }
     }
 }
 
@@ -761,7 +765,12 @@ void tlb_flush_range_by_mmuidx(CPUState *cpu, vaddr addr,
                                vaddr len, MMUIdxMap idxmap,
                                unsigned bits)
 {
-    TLBFlushRangeData d;
+    TLBFlushRangeData d = {
+        .addr = addr & TARGET_PAGE_MASK,
+        .last = (addr + len - 1) & TARGET_PAGE_MASK,
+        .idxmap = idxmap,
+        .bits = bits,
+    };
 
     assert_cpu_is_self(cpu);
 
@@ -770,21 +779,16 @@ void tlb_flush_range_by_mmuidx(CPUState *cpu, vaddr addr,
         tlb_flush_by_mmuidx(cpu, idxmap);
         return;
     }
+
     /*
      * If all bits are significant, and len is small,
      * this devolves to tlb_flush_page.
      */
-    if (len <= TARGET_PAGE_SIZE && bits >= target_long_bits()) {
+    if (d.addr == d.last && bits >= target_long_bits()) {
         tlb_flush_page_by_mmuidx(cpu, addr, idxmap);
         return;
     }
 
-    /* This should already be page aligned */
-    d.addr = addr & TARGET_PAGE_MASK;
-    d.len = len;
-    d.idxmap = idxmap;
-    d.bits = bits;
-
     tlb_flush_range_by_mmuidx_async_0(cpu, d);
 }
 
@@ -800,7 +804,13 @@ void tlb_flush_range_by_mmuidx_all_cpus_synced(CPUState 
*src_cpu,
                                                MMUIdxMap idxmap,
                                                unsigned bits)
 {
-    TLBFlushRangeData d, *p;
+    TLBFlushRangeData d = {
+        .addr = addr & TARGET_PAGE_MASK,
+        .last = (addr + len - 1) & TARGET_PAGE_MASK,
+        .idxmap = idxmap,
+        .bits = bits,
+    };
+    TLBFlushRangeData *p;
     CPUState *dst_cpu;
 
     /* If no page bits are significant, this devolves to tlb_flush. */
@@ -808,21 +818,16 @@ void tlb_flush_range_by_mmuidx_all_cpus_synced(CPUState 
*src_cpu,
         tlb_flush_by_mmuidx_all_cpus_synced(src_cpu, idxmap);
         return;
     }
+
     /*
      * If all bits are significant, and len is small,
      * this devolves to tlb_flush_page.
      */
-    if (len <= TARGET_PAGE_SIZE && bits >= target_long_bits()) {
+    if (d.addr == d.last && bits >= target_long_bits()) {
         tlb_flush_page_by_mmuidx_all_cpus_synced(src_cpu, addr, idxmap);
         return;
     }
 
-    /* This should already be page aligned */
-    d.addr = addr & TARGET_PAGE_MASK;
-    d.len = len;
-    d.idxmap = idxmap;
-    d.bits = bits;
-
     /* Allocate a separate data block for each destination cpu.  */
     CPU_FOREACH(dst_cpu) {
         if (dst_cpu != src_cpu) {
-- 
2.43.0


Reply via email to