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
