summaryrefslogtreecommitdiffstats
path: root/include
diff options
context:
space:
mode:
authorPaolo Bonzini <pbonzini@redhat.com>2016-02-10 15:11:45 +0100
committerTimothy Pearson <tpearson@raptorengineering.com>2019-11-29 19:41:57 -0600
commit2b398894c5a6ce752681fc79777ed72962c7ce88 (patch)
tree69d30f1e2345d13ef3f7872dfdfa80b7d516f696 /include
parent485f992e5e17302a60624f307bf6aee480968af4 (diff)
downloadhqemu-2b398894c5a6ce752681fc79777ed72962c7ce88.zip
hqemu-2b398894c5a6ce752681fc79777ed72962c7ce88.tar.gz
memory: fix usage of find_next_bit and find_next_zero_bit
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> Reviewed-by: Stefan Hajnoczi <stefanha@redhat.com> Tested-by: Leon Alrae <leon.alrae@imgtec.com> Tested-by: Thomas Huth <thuth@redhat.com> Message-id: 1455113505-11237-1-git-send-email-pbonzini@redhat.com Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Diffstat (limited to 'include')
-rw-r--r--include/exec/ram_addr.h55
1 files changed, 36 insertions, 19 deletions
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();
OpenPOWER on IntegriCloud