The while loop in flatview_add_to_dispatch can only be executed twice and it will go through different paths on each execution (in fact one of the "if" branches is dead). Remove the loop completely, the code becomes clearer at the cost of a handful of duplicated lines.
Reported-by: Wei Yang <richardw.y...@linux.intel.com> Signed-off-by: Paolo Bonzini <pbonz...@redhat.com> --- exec.c | 34 +++++++++++++++++++--------------- 1 file changed, 19 insertions(+), 15 deletions(-) diff --git a/exec.c b/exec.c index 1d4f378..9647593 100644 --- a/exec.c +++ b/exec.c @@ -1601,33 +1601,37 @@ static void register_multipage(FlatView *fv, void flatview_add_to_dispatch(FlatView *fv, MemoryRegionSection *section) { - MemoryRegionSection now = *section, remain = *section; + MemoryRegionSection remain = *section; Int128 page_size = int128_make64(TARGET_PAGE_SIZE); - if (now.offset_within_address_space & ~TARGET_PAGE_MASK) { + if (remain.offset_within_address_space & ~TARGET_PAGE_MASK) { + MemoryRegionSection now = remain; uint64_t left = TARGET_PAGE_ALIGN(now.offset_within_address_space) - now.offset_within_address_space; now.size = int128_min(int128_make64(left), now.size); register_subpage(fv, &now); - } else { - now.size = int128_zero(); - } - while (int128_ne(remain.size, now.size)) { + if (int128_eq(remain.size, now.size)) { + return; + } remain.size = int128_sub(remain.size, now.size); remain.offset_within_address_space += int128_get64(now.size); remain.offset_within_region += int128_get64(now.size); - now = remain; - if (int128_lt(remain.size, page_size)) { - register_subpage(fv, &now); - } else if (remain.offset_within_address_space & ~TARGET_PAGE_MASK) { - now.size = page_size; - register_subpage(fv, &now); - } else { - now.size = int128_and(now.size, int128_neg(page_size)); - register_multipage(fv, &now); + } + + if (int128_ge(remain.size, page_size)) { + MemoryRegionSection now = remain; + now.size = int128_and(now.size, int128_neg(page_size)); + register_multipage(fv, &now); + if (int128_eq(remain.size, now.size)) { + return; } + remain.size = int128_sub(remain.size, now.size); + remain.offset_within_address_space += int128_get64(now.size); + remain.offset_within_region += int128_get64(now.size); } + + register_subpage(fv, &remain); } void qemu_flush_coalesced_mmio_buffer(void) -- 1.8.3.1