mirror of https://github.com/xqemu/xqemu.git
ram: Use page number instead of an address for the bitmap operations
We use an unsigned long for the page number. Notice that our bitmaps already got that for the index, so we have that limit. Signed-off-by: Juan Quintela <quintela@redhat.com> Reviewed-by: Dr. David Alan Gilbert <dgilbert@redhat.com> -- rename page to page_abs everywhere. fix trace types for pages
This commit is contained in:
parent
2479569466
commit
06b106889a
|
@ -609,13 +609,12 @@ static int save_xbzrle_page(RAMState *rs, uint8_t **current_data,
|
||||||
* @rs: current RAM state
|
* @rs: current RAM state
|
||||||
* @rb: RAMBlock where to search for dirty pages
|
* @rb: RAMBlock where to search for dirty pages
|
||||||
* @start: starting address (typically so we can continue from previous page)
|
* @start: starting address (typically so we can continue from previous page)
|
||||||
* @ram_addr_abs: pointer into which to store the address of the dirty page
|
* @page_abs: pointer into where to store the dirty page
|
||||||
* within the global ram_addr space
|
|
||||||
*/
|
*/
|
||||||
static inline
|
static inline
|
||||||
ram_addr_t migration_bitmap_find_dirty(RAMState *rs, RAMBlock *rb,
|
ram_addr_t migration_bitmap_find_dirty(RAMState *rs, RAMBlock *rb,
|
||||||
ram_addr_t start,
|
ram_addr_t start,
|
||||||
ram_addr_t *ram_addr_abs)
|
unsigned long *page_abs)
|
||||||
{
|
{
|
||||||
unsigned long base = rb->offset >> TARGET_PAGE_BITS;
|
unsigned long base = rb->offset >> TARGET_PAGE_BITS;
|
||||||
unsigned long nr = base + (start >> TARGET_PAGE_BITS);
|
unsigned long nr = base + (start >> TARGET_PAGE_BITS);
|
||||||
|
@ -632,17 +631,17 @@ ram_addr_t migration_bitmap_find_dirty(RAMState *rs, RAMBlock *rb,
|
||||||
next = find_next_bit(bitmap, size, nr);
|
next = find_next_bit(bitmap, size, nr);
|
||||||
}
|
}
|
||||||
|
|
||||||
*ram_addr_abs = next << TARGET_PAGE_BITS;
|
*page_abs = next;
|
||||||
return (next - base) << TARGET_PAGE_BITS;
|
return (next - base) << TARGET_PAGE_BITS;
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline bool migration_bitmap_clear_dirty(RAMState *rs, ram_addr_t addr)
|
static inline bool migration_bitmap_clear_dirty(RAMState *rs,
|
||||||
|
unsigned long page_abs)
|
||||||
{
|
{
|
||||||
bool ret;
|
bool ret;
|
||||||
int nr = addr >> TARGET_PAGE_BITS;
|
|
||||||
unsigned long *bitmap = atomic_rcu_read(&rs->ram_bitmap)->bmap;
|
unsigned long *bitmap = atomic_rcu_read(&rs->ram_bitmap)->bmap;
|
||||||
|
|
||||||
ret = test_and_clear_bit(nr, bitmap);
|
ret = test_and_clear_bit(page_abs, bitmap);
|
||||||
|
|
||||||
if (ret) {
|
if (ret) {
|
||||||
rs->migration_dirty_pages--;
|
rs->migration_dirty_pages--;
|
||||||
|
@ -1054,14 +1053,13 @@ static int ram_save_compressed_page(RAMState *rs, PageSearchStatus *pss,
|
||||||
* @rs: current RAM state
|
* @rs: current RAM state
|
||||||
* @pss: data about the state of the current dirty page scan
|
* @pss: data about the state of the current dirty page scan
|
||||||
* @again: set to false if the search has scanned the whole of RAM
|
* @again: set to false if the search has scanned the whole of RAM
|
||||||
* @ram_addr_abs: pointer into which to store the address of the dirty page
|
* @page_abs: pointer into where to store the dirty page
|
||||||
* within the global ram_addr space
|
|
||||||
*/
|
*/
|
||||||
static bool find_dirty_block(RAMState *rs, PageSearchStatus *pss,
|
static bool find_dirty_block(RAMState *rs, PageSearchStatus *pss,
|
||||||
bool *again, ram_addr_t *ram_addr_abs)
|
bool *again, unsigned long *page_abs)
|
||||||
{
|
{
|
||||||
pss->offset = migration_bitmap_find_dirty(rs, pss->block, pss->offset,
|
pss->offset = migration_bitmap_find_dirty(rs, pss->block, pss->offset,
|
||||||
ram_addr_abs);
|
page_abs);
|
||||||
if (pss->complete_round && pss->block == rs->last_seen_block &&
|
if (pss->complete_round && pss->block == rs->last_seen_block &&
|
||||||
pss->offset >= rs->last_offset) {
|
pss->offset >= rs->last_offset) {
|
||||||
/*
|
/*
|
||||||
|
@ -1108,11 +1106,10 @@ static bool find_dirty_block(RAMState *rs, PageSearchStatus *pss,
|
||||||
*
|
*
|
||||||
* @rs: current RAM state
|
* @rs: current RAM state
|
||||||
* @offset: used to return the offset within the RAMBlock
|
* @offset: used to return the offset within the RAMBlock
|
||||||
* @ram_addr_abs: pointer into which to store the address of the dirty page
|
* @page_abs: pointer into where to store the dirty page
|
||||||
* within the global ram_addr space
|
|
||||||
*/
|
*/
|
||||||
static RAMBlock *unqueue_page(RAMState *rs, ram_addr_t *offset,
|
static RAMBlock *unqueue_page(RAMState *rs, ram_addr_t *offset,
|
||||||
ram_addr_t *ram_addr_abs)
|
unsigned long *page_abs)
|
||||||
{
|
{
|
||||||
RAMBlock *block = NULL;
|
RAMBlock *block = NULL;
|
||||||
|
|
||||||
|
@ -1122,8 +1119,7 @@ static RAMBlock *unqueue_page(RAMState *rs, ram_addr_t *offset,
|
||||||
QSIMPLEQ_FIRST(&rs->src_page_requests);
|
QSIMPLEQ_FIRST(&rs->src_page_requests);
|
||||||
block = entry->rb;
|
block = entry->rb;
|
||||||
*offset = entry->offset;
|
*offset = entry->offset;
|
||||||
*ram_addr_abs = (entry->offset + entry->rb->offset) &
|
*page_abs = (entry->offset + entry->rb->offset) >> TARGET_PAGE_BITS;
|
||||||
TARGET_PAGE_MASK;
|
|
||||||
|
|
||||||
if (entry->len > TARGET_PAGE_SIZE) {
|
if (entry->len > TARGET_PAGE_SIZE) {
|
||||||
entry->len -= TARGET_PAGE_SIZE;
|
entry->len -= TARGET_PAGE_SIZE;
|
||||||
|
@ -1148,18 +1144,17 @@ static RAMBlock *unqueue_page(RAMState *rs, ram_addr_t *offset,
|
||||||
*
|
*
|
||||||
* @rs: current RAM state
|
* @rs: current RAM state
|
||||||
* @pss: data about the state of the current dirty page scan
|
* @pss: data about the state of the current dirty page scan
|
||||||
* @ram_addr_abs: pointer into which to store the address of the dirty page
|
* @page_abs: pointer into where to store the dirty page
|
||||||
* within the global ram_addr space
|
|
||||||
*/
|
*/
|
||||||
static bool get_queued_page(RAMState *rs, PageSearchStatus *pss,
|
static bool get_queued_page(RAMState *rs, PageSearchStatus *pss,
|
||||||
ram_addr_t *ram_addr_abs)
|
unsigned long *page_abs)
|
||||||
{
|
{
|
||||||
RAMBlock *block;
|
RAMBlock *block;
|
||||||
ram_addr_t offset;
|
ram_addr_t offset;
|
||||||
bool dirty;
|
bool dirty;
|
||||||
|
|
||||||
do {
|
do {
|
||||||
block = unqueue_page(rs, &offset, ram_addr_abs);
|
block = unqueue_page(rs, &offset, page_abs);
|
||||||
/*
|
/*
|
||||||
* We're sending this page, and since it's postcopy nothing else
|
* We're sending this page, and since it's postcopy nothing else
|
||||||
* will dirty it, and we must make sure it doesn't get sent again
|
* will dirty it, and we must make sure it doesn't get sent again
|
||||||
|
@ -1169,17 +1164,15 @@ static bool get_queued_page(RAMState *rs, PageSearchStatus *pss,
|
||||||
if (block) {
|
if (block) {
|
||||||
unsigned long *bitmap;
|
unsigned long *bitmap;
|
||||||
bitmap = atomic_rcu_read(&rs->ram_bitmap)->bmap;
|
bitmap = atomic_rcu_read(&rs->ram_bitmap)->bmap;
|
||||||
dirty = test_bit(*ram_addr_abs >> TARGET_PAGE_BITS, bitmap);
|
dirty = test_bit(*page_abs, bitmap);
|
||||||
if (!dirty) {
|
if (!dirty) {
|
||||||
trace_get_queued_page_not_dirty(
|
trace_get_queued_page_not_dirty(block->idstr, (uint64_t)offset,
|
||||||
block->idstr, (uint64_t)offset,
|
*page_abs,
|
||||||
(uint64_t)*ram_addr_abs,
|
test_bit(*page_abs,
|
||||||
test_bit(*ram_addr_abs >> TARGET_PAGE_BITS,
|
|
||||||
atomic_rcu_read(&rs->ram_bitmap)->unsentmap));
|
atomic_rcu_read(&rs->ram_bitmap)->unsentmap));
|
||||||
} else {
|
} else {
|
||||||
trace_get_queued_page(block->idstr,
|
trace_get_queued_page(block->idstr, (uint64_t)offset,
|
||||||
(uint64_t)offset,
|
*page_abs);
|
||||||
(uint64_t)*ram_addr_abs);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1307,15 +1300,15 @@ err:
|
||||||
* @ms: current migration state
|
* @ms: current migration state
|
||||||
* @pss: data about the page we want to send
|
* @pss: data about the page we want to send
|
||||||
* @last_stage: if we are at the completion stage
|
* @last_stage: if we are at the completion stage
|
||||||
* @dirty_ram_abs: address of the start of the dirty page in ram_addr_t space
|
* @page_abs: page number of the dirty page
|
||||||
*/
|
*/
|
||||||
static int ram_save_target_page(RAMState *rs, PageSearchStatus *pss,
|
static int ram_save_target_page(RAMState *rs, PageSearchStatus *pss,
|
||||||
bool last_stage, ram_addr_t dirty_ram_abs)
|
bool last_stage, unsigned long page_abs)
|
||||||
{
|
{
|
||||||
int res = 0;
|
int res = 0;
|
||||||
|
|
||||||
/* Check the pages is dirty and if it is send it */
|
/* Check the pages is dirty and if it is send it */
|
||||||
if (migration_bitmap_clear_dirty(rs, dirty_ram_abs)) {
|
if (migration_bitmap_clear_dirty(rs, page_abs)) {
|
||||||
unsigned long *unsentmap;
|
unsigned long *unsentmap;
|
||||||
/*
|
/*
|
||||||
* If xbzrle is on, stop using the data compression after first
|
* If xbzrle is on, stop using the data compression after first
|
||||||
|
@ -1335,7 +1328,7 @@ static int ram_save_target_page(RAMState *rs, PageSearchStatus *pss,
|
||||||
}
|
}
|
||||||
unsentmap = atomic_rcu_read(&rs->ram_bitmap)->unsentmap;
|
unsentmap = atomic_rcu_read(&rs->ram_bitmap)->unsentmap;
|
||||||
if (unsentmap) {
|
if (unsentmap) {
|
||||||
clear_bit(dirty_ram_abs >> TARGET_PAGE_BITS, unsentmap);
|
clear_bit(page_abs, unsentmap);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -1357,24 +1350,24 @@ static int ram_save_target_page(RAMState *rs, PageSearchStatus *pss,
|
||||||
* @ms: current migration state
|
* @ms: current migration state
|
||||||
* @pss: data about the page we want to send
|
* @pss: data about the page we want to send
|
||||||
* @last_stage: if we are at the completion stage
|
* @last_stage: if we are at the completion stage
|
||||||
* @dirty_ram_abs: Address of the start of the dirty page in ram_addr_t space
|
* @page_abs: Page number of the dirty page
|
||||||
*/
|
*/
|
||||||
static int ram_save_host_page(RAMState *rs, PageSearchStatus *pss,
|
static int ram_save_host_page(RAMState *rs, PageSearchStatus *pss,
|
||||||
bool last_stage,
|
bool last_stage,
|
||||||
ram_addr_t dirty_ram_abs)
|
unsigned long page_abs)
|
||||||
{
|
{
|
||||||
int tmppages, pages = 0;
|
int tmppages, pages = 0;
|
||||||
size_t pagesize = qemu_ram_pagesize(pss->block);
|
size_t pagesize = qemu_ram_pagesize(pss->block);
|
||||||
|
|
||||||
do {
|
do {
|
||||||
tmppages = ram_save_target_page(rs, pss, last_stage, dirty_ram_abs);
|
tmppages = ram_save_target_page(rs, pss, last_stage, page_abs);
|
||||||
if (tmppages < 0) {
|
if (tmppages < 0) {
|
||||||
return tmppages;
|
return tmppages;
|
||||||
}
|
}
|
||||||
|
|
||||||
pages += tmppages;
|
pages += tmppages;
|
||||||
pss->offset += TARGET_PAGE_SIZE;
|
pss->offset += TARGET_PAGE_SIZE;
|
||||||
dirty_ram_abs += TARGET_PAGE_SIZE;
|
page_abs++;
|
||||||
} while (pss->offset & (pagesize - 1));
|
} while (pss->offset & (pagesize - 1));
|
||||||
|
|
||||||
/* The offset we leave with is the last one we looked at */
|
/* The offset we leave with is the last one we looked at */
|
||||||
|
@ -1401,8 +1394,7 @@ static int ram_find_and_save_block(RAMState *rs, bool last_stage)
|
||||||
PageSearchStatus pss;
|
PageSearchStatus pss;
|
||||||
int pages = 0;
|
int pages = 0;
|
||||||
bool again, found;
|
bool again, found;
|
||||||
ram_addr_t dirty_ram_abs; /* Address of the start of the dirty page in
|
unsigned long page_abs; /* Page number of the dirty page */
|
||||||
ram_addr_t space */
|
|
||||||
|
|
||||||
/* No dirty page as there is zero RAM */
|
/* No dirty page as there is zero RAM */
|
||||||
if (!ram_bytes_total()) {
|
if (!ram_bytes_total()) {
|
||||||
|
@ -1419,15 +1411,15 @@ static int ram_find_and_save_block(RAMState *rs, bool last_stage)
|
||||||
|
|
||||||
do {
|
do {
|
||||||
again = true;
|
again = true;
|
||||||
found = get_queued_page(rs, &pss, &dirty_ram_abs);
|
found = get_queued_page(rs, &pss, &page_abs);
|
||||||
|
|
||||||
if (!found) {
|
if (!found) {
|
||||||
/* priority queue empty, so just search for something dirty */
|
/* priority queue empty, so just search for something dirty */
|
||||||
found = find_dirty_block(rs, &pss, &again, &dirty_ram_abs);
|
found = find_dirty_block(rs, &pss, &again, &page_abs);
|
||||||
}
|
}
|
||||||
|
|
||||||
if (found) {
|
if (found) {
|
||||||
pages = ram_save_host_page(rs, &pss, last_stage, dirty_ram_abs);
|
pages = ram_save_host_page(rs, &pss, last_stage, page_abs);
|
||||||
}
|
}
|
||||||
} while (!pages && again);
|
} while (!pages && again);
|
||||||
|
|
||||||
|
|
|
@ -63,8 +63,8 @@ put_qtailq_end(const char *name, const char *reason) "%s %s"
|
||||||
qemu_file_fclose(void) ""
|
qemu_file_fclose(void) ""
|
||||||
|
|
||||||
# migration/ram.c
|
# migration/ram.c
|
||||||
get_queued_page(const char *block_name, uint64_t tmp_offset, uint64_t ram_addr) "%s/%" PRIx64 " ram_addr=%" PRIx64
|
get_queued_page(const char *block_name, uint64_t tmp_offset, unsigned long page_abs) "%s/%" PRIx64 " page_abs=%lx"
|
||||||
get_queued_page_not_dirty(const char *block_name, uint64_t tmp_offset, uint64_t ram_addr, int sent) "%s/%" PRIx64 " ram_addr=%" PRIx64 " (sent=%d)"
|
get_queued_page_not_dirty(const char *block_name, uint64_t tmp_offset, unsigned long page_abs, int sent) "%s/%" PRIx64 " page_abs=%lx (sent=%d)"
|
||||||
migration_bitmap_sync_start(void) ""
|
migration_bitmap_sync_start(void) ""
|
||||||
migration_bitmap_sync_end(uint64_t dirty_pages) "dirty_pages %" PRIu64
|
migration_bitmap_sync_end(uint64_t dirty_pages) "dirty_pages %" PRIu64
|
||||||
migration_throttle(void) ""
|
migration_throttle(void) ""
|
||||||
|
|
Loading…
Reference in New Issue