Extract ram block list update to a new function ram_block_add_list(). This is done to support grant mappings which adds a memory region for granted memory and updates the ram_block list.
Signed-off-by: Juergen Gross <jgr...@suse.com> Signed-off-by: Vikram Garhwal <vikram.garh...@amd.com> Reviewed-by: Stefano Stabellini <sstabell...@kernel.org> --- include/exec/ram_addr.h | 1 + system/physmem.c | 62 ++++++++++++++++++++++++++--------------- 2 files changed, 40 insertions(+), 23 deletions(-) diff --git a/include/exec/ram_addr.h b/include/exec/ram_addr.h index 90676093f5..c0b5f9a7d0 100644 --- a/include/exec/ram_addr.h +++ b/include/exec/ram_addr.h @@ -139,6 +139,7 @@ void qemu_ram_free(RAMBlock *block); int qemu_ram_resize(RAMBlock *block, ram_addr_t newsize, Error **errp); void qemu_ram_msync(RAMBlock *block, ram_addr_t start, ram_addr_t length); +void ram_block_add_list(RAMBlock *new_block); /* Clear whole block of mem */ static inline void qemu_ram_block_writeback(RAMBlock *block) diff --git a/system/physmem.c b/system/physmem.c index e3ebc19eef..84f3022099 100644 --- a/system/physmem.c +++ b/system/physmem.c @@ -1803,12 +1803,47 @@ static void dirty_memory_extend(ram_addr_t old_ram_size, } } +static void ram_block_add_list_locked(RAMBlock *new_block) + { + RAMBlock *block; + RAMBlock *last_block = NULL; + + /* + * Keep the list sorted from biggest to smallest block. Unlike QTAILQ, + * QLIST (which has an RCU-friendly variant) does not have insertion at + * tail, so save the last element in last_block. + */ + RAMBLOCK_FOREACH(block) { + last_block = block; + if (block->max_length < new_block->max_length) { + break; + } + } + if (block) { + QLIST_INSERT_BEFORE_RCU(block, new_block, next); + } else if (last_block) { + QLIST_INSERT_AFTER_RCU(last_block, new_block, next); + } else { /* list is empty */ + QLIST_INSERT_HEAD_RCU(&ram_list.blocks, new_block, next); + } + ram_list.mru_block = NULL; + + /* Write list before version */ + smp_wmb(); + ram_list.version++; +} + +void ram_block_add_list(RAMBlock *new_block) +{ + qemu_mutex_lock_ramlist(); + ram_block_add_list_locked(new_block); + qemu_mutex_unlock_ramlist(); +} + static void ram_block_add(RAMBlock *new_block, Error **errp) { const bool noreserve = qemu_ram_is_noreserve(new_block); const bool shared = qemu_ram_is_shared(new_block); - RAMBlock *block; - RAMBlock *last_block = NULL; ram_addr_t old_ram_size, new_ram_size; Error *err = NULL; @@ -1846,28 +1881,9 @@ static void ram_block_add(RAMBlock *new_block, Error **errp) if (new_ram_size > old_ram_size) { dirty_memory_extend(old_ram_size, new_ram_size); } - /* Keep the list sorted from biggest to smallest block. Unlike QTAILQ, - * QLIST (which has an RCU-friendly variant) does not have insertion at - * tail, so save the last element in last_block. - */ - RAMBLOCK_FOREACH(block) { - last_block = block; - if (block->max_length < new_block->max_length) { - break; - } - } - if (block) { - QLIST_INSERT_BEFORE_RCU(block, new_block, next); - } else if (last_block) { - QLIST_INSERT_AFTER_RCU(last_block, new_block, next); - } else { /* list is empty */ - QLIST_INSERT_HEAD_RCU(&ram_list.blocks, new_block, next); - } - ram_list.mru_block = NULL; - /* Write list before version */ - smp_wmb(); - ram_list.version++; + ram_block_add_list_locked(new_block); + qemu_mutex_unlock_ramlist(); cpu_physical_memory_set_dirty_range(new_block->offset, -- 2.17.1