Message ID | 1455113505-11237-1-git-send-email-pbonzini@redhat.com (mailing list archive) |
---|---|
State | New, archived |
Headers | show |
On Wed, Feb 10, 2016 at 03:11:45PM +0100, Paolo Bonzini wrote: > The last two arguments to these functions are the last and first bit to > check relative to the base. The code was using incorrectly the first > bit and the number of bits. Fix this in cpu_physical_memory_get_dirty > and cpu_physical_memory_all_dirty. This requires a few changes in the > iteration; change the code in cpu_physical_memory_set_dirty_range to > match. > > Fixes: 5b82b70 > Cc: Stefan Hajnoczi <stefanha@redhat.com> > Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> > --- > include/exec/ram_addr.h | 55 ++++++++++++++++++++++++++++++++----------------- > 1 file changed, 36 insertions(+), 19 deletions(-) Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com>
On 10/02/16 14:11, Paolo Bonzini wrote: > The last two arguments to these functions are the last and first bit to > check relative to the base. The code was using incorrectly the first > bit and the number of bits. Fix this in cpu_physical_memory_get_dirty > and cpu_physical_memory_all_dirty. This requires a few changes in the > iteration; change the code in cpu_physical_memory_set_dirty_range to > match. > > Fixes: 5b82b70 > Cc: Stefan Hajnoczi <stefanha@redhat.com> > Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> > --- > include/exec/ram_addr.h | 55 ++++++++++++++++++++++++++++++++----------------- > 1 file changed, 36 insertions(+), 19 deletions(-) It fixes the performance problem I was seeing: Tested-by: Leon Alrae <leon.alrae@imgtec.com> Thanks, Leon
On 10.02.2016 15:11, Paolo Bonzini wrote: > The last two arguments to these functions are the last and first bit to > check relative to the base. The code was using incorrectly the first > bit and the number of bits. Fix this in cpu_physical_memory_get_dirty > and cpu_physical_memory_all_dirty. This requires a few changes in the > iteration; change the code in cpu_physical_memory_set_dirty_range to > match. > > Fixes: 5b82b70 > Cc: Stefan Hajnoczi <stefanha@redhat.com> > Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> That commit 5b82b70 also broke the pseries machine on qemu-ppc64: --------------------------------- 8< -------------------------------------- $ ppc64-softmmu/qemu-system-ppc64 -net none -nographic -vga none SLOF ********************************************************************** QEMU Starting Build Date = Nov 5 2015 15:23:31 FW Version = git-b4c93802a5b2c72f Press "s" to enter Open Firmware. SLOF ********************************************************************** QEMU Starting Build Date = Nov 5 2015 15:23:31 FW Version = git-b4c93802a5b2c72f ERROR: Flatten device tree not available! Press "s" to enter Open Firmware. !!! roomfs lookup(bootinfo) = 1 Cannot find romfs file xvect !!! roomfs lookup(bootinfo) = 1 ERROR: Not enough memory for Open Firmware qemu: fatal: Trying to execute code outside RAM or ROM at 0xffffffffffbf0000 --------------------------------- 8< -------------------------------------- With your patch here applied, SLOF boots fine again, so: Tested-by: Thomas Huth <thuth@redhat.com>
On 10 February 2016 at 14:11, Paolo Bonzini <pbonzini@redhat.com> wrote: > The last two arguments to these functions are the last and first bit to > check relative to the base. The code was using incorrectly the first > bit and the number of bits. Fix this in cpu_physical_memory_get_dirty > and cpu_physical_memory_all_dirty. This requires a few changes in the > iteration; change the code in cpu_physical_memory_set_dirty_range to > match. > > Fixes: 5b82b70 > Cc: Stefan Hajnoczi <stefanha@redhat.com> > Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> I've set the pre-merge tests running so I should be able to commit this to master first thing tomorrow. Was this the only patch that needs applying to fix your pullreq? thanks -- PMM
On 10/02/2016 23:40, Peter Maydell wrote: > On 10 February 2016 at 14:11, Paolo Bonzini <pbonzini@redhat.com> wrote: >> The last two arguments to these functions are the last and first bit to >> check relative to the base. The code was using incorrectly the first >> bit and the number of bits. Fix this in cpu_physical_memory_get_dirty >> and cpu_physical_memory_all_dirty. This requires a few changes in the >> iteration; change the code in cpu_physical_memory_set_dirty_range to >> match. >> >> Fixes: 5b82b70 >> Cc: Stefan Hajnoczi <stefanha@redhat.com> >> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> > > I've set the pre-merge tests running so I should be able > to commit this to master first thing tomorrow. Was this > the only patch that needs applying to fix your pullreq? Nothing else. Paolo
On 10 February 2016 at 22:40, Peter Maydell <peter.maydell@linaro.org> wrote: > On 10 February 2016 at 14:11, Paolo Bonzini <pbonzini@redhat.com> wrote: >> The last two arguments to these functions are the last and first bit to >> check relative to the base. The code was using incorrectly the first >> bit and the number of bits. Fix this in cpu_physical_memory_get_dirty >> and cpu_physical_memory_all_dirty. This requires a few changes in the >> iteration; change the code in cpu_physical_memory_set_dirty_range to >> match. >> >> Fixes: 5b82b70 >> Cc: Stefan Hajnoczi <stefanha@redhat.com> >> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> > > I've set the pre-merge tests running so I should be able > to commit this to master first thing tomorrow. Applied to master, thanks. -- PMM
diff --git a/include/exec/ram_addr.h b/include/exec/ram_addr.h index b1413a1..5d33def 100644 --- a/include/exec/ram_addr.h +++ b/include/exec/ram_addr.h @@ -121,6 +121,7 @@ static inline bool cpu_physical_memory_get_dirty(ram_addr_t start, { DirtyMemoryBlocks *blocks; unsigned long end, page; + unsigned long idx, offset, base; bool dirty = false; assert(client < DIRTY_MEMORY_NUM); @@ -132,17 +133,22 @@ static inline bool cpu_physical_memory_get_dirty(ram_addr_t start, blocks = atomic_rcu_read(&ram_list.dirty_memory[client]); + idx = page / DIRTY_MEMORY_BLOCK_SIZE; + offset = page % DIRTY_MEMORY_BLOCK_SIZE; + base = page - offset; while (page < end) { - unsigned long idx = page / DIRTY_MEMORY_BLOCK_SIZE; - unsigned long offset = page % DIRTY_MEMORY_BLOCK_SIZE; - unsigned long num = MIN(end - page, DIRTY_MEMORY_BLOCK_SIZE - offset); - - if (find_next_bit(blocks->blocks[idx], offset, num) < num) { + unsigned long next = MIN(end, base + DIRTY_MEMORY_BLOCK_SIZE); + unsigned long num = next - base; + unsigned long found = find_next_bit(blocks->blocks[idx], num, offset); + if (found < num) { dirty = true; break; } - page += num; + page = next; + idx++; + offset = 0; + base += DIRTY_MEMORY_BLOCK_SIZE; } rcu_read_unlock(); @@ -156,6 +162,7 @@ static inline bool cpu_physical_memory_all_dirty(ram_addr_t start, { DirtyMemoryBlocks *blocks; unsigned long end, page; + unsigned long idx, offset, base; bool dirty = true; assert(client < DIRTY_MEMORY_NUM); @@ -167,17 +174,22 @@ static inline bool cpu_physical_memory_all_dirty(ram_addr_t start, blocks = atomic_rcu_read(&ram_list.dirty_memory[client]); + idx = page / DIRTY_MEMORY_BLOCK_SIZE; + offset = page % DIRTY_MEMORY_BLOCK_SIZE; + base = page - offset; while (page < end) { - unsigned long idx = page / DIRTY_MEMORY_BLOCK_SIZE; - unsigned long offset = page % DIRTY_MEMORY_BLOCK_SIZE; - unsigned long num = MIN(end - page, DIRTY_MEMORY_BLOCK_SIZE - offset); - - if (find_next_zero_bit(blocks->blocks[idx], offset, num) < num) { + unsigned long next = MIN(end, base + DIRTY_MEMORY_BLOCK_SIZE); + unsigned long num = next - base; + unsigned long found = find_next_zero_bit(blocks->blocks[idx], num, offset); + if (found < num) { dirty = false; break; } - page += num; + page = next; + idx++; + offset = 0; + base += DIRTY_MEMORY_BLOCK_SIZE; } rcu_read_unlock(); @@ -248,6 +260,7 @@ static inline void cpu_physical_memory_set_dirty_range(ram_addr_t start, { DirtyMemoryBlocks *blocks[DIRTY_MEMORY_NUM]; unsigned long end, page; + unsigned long idx, offset, base; int i; if (!mask && !xen_enabled()) { @@ -263,25 +276,29 @@ static inline void cpu_physical_memory_set_dirty_range(ram_addr_t start, blocks[i] = atomic_rcu_read(&ram_list.dirty_memory[i]); } + idx = page / DIRTY_MEMORY_BLOCK_SIZE; + offset = page % DIRTY_MEMORY_BLOCK_SIZE; + base = page - offset; while (page < end) { - unsigned long idx = page / DIRTY_MEMORY_BLOCK_SIZE; - unsigned long offset = page % DIRTY_MEMORY_BLOCK_SIZE; - unsigned long num = MIN(end - page, DIRTY_MEMORY_BLOCK_SIZE - offset); + unsigned long next = MIN(end, base + DIRTY_MEMORY_BLOCK_SIZE); if (likely(mask & (1 << DIRTY_MEMORY_MIGRATION))) { bitmap_set_atomic(blocks[DIRTY_MEMORY_MIGRATION]->blocks[idx], - offset, num); + offset, next - page); } if (unlikely(mask & (1 << DIRTY_MEMORY_VGA))) { bitmap_set_atomic(blocks[DIRTY_MEMORY_VGA]->blocks[idx], - offset, num); + offset, next - page); } if (unlikely(mask & (1 << DIRTY_MEMORY_CODE))) { bitmap_set_atomic(blocks[DIRTY_MEMORY_CODE]->blocks[idx], - offset, num); + offset, next - page); } - page += num; + page = next; + idx++; + offset = 0; + base += DIRTY_MEMORY_BLOCK_SIZE; } rcu_read_unlock();
The last two arguments to these functions are the last and first bit to check relative to the base. The code was using incorrectly the first bit and the number of bits. Fix this in cpu_physical_memory_get_dirty and cpu_physical_memory_all_dirty. This requires a few changes in the iteration; change the code in cpu_physical_memory_set_dirty_range to match. Fixes: 5b82b70 Cc: Stefan Hajnoczi <stefanha@redhat.com> Signed-off-by: Paolo Bonzini <pbonzini@redhat.com> --- include/exec/ram_addr.h | 55 ++++++++++++++++++++++++++++++++----------------- 1 file changed, 36 insertions(+), 19 deletions(-)