diff options
author | Paolo Bonzini <pbonzini@redhat.com> | 2016-12-21 00:31:36 +0800 |
---|---|---|
committer | Paolo Bonzini <pbonzini@redhat.com> | 2017-01-16 17:52:35 +0100 |
commit | 0987d735a3a42c92f6e7e0caa8bab1b0139e3b54 (patch) | |
tree | 82eee4bc187b2e03305b67b89c0476142d88431b /include/exec/ram_addr.h | |
parent | fb5e19d2e1472e96d72d5e4d89c20033f8ab345c (diff) |
ramblock-notifier: new
This adds a notify interface of ram block additions and removals.
Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
Diffstat (limited to 'include/exec/ram_addr.h')
-rw-r--r-- | include/exec/ram_addr.h | 46 |
1 files changed, 2 insertions, 44 deletions
diff --git a/include/exec/ram_addr.h b/include/exec/ram_addr.h index 54d7108a9e..3e79466a44 100644 --- a/include/exec/ram_addr.h +++ b/include/exec/ram_addr.h @@ -21,6 +21,7 @@ #ifndef CONFIG_USER_ONLY #include "hw/xen/xen.h" +#include "exec/ramlist.h" struct RAMBlock { struct rcu_head rcu; @@ -35,6 +36,7 @@ struct RAMBlock { char idstr[256]; /* RCU-enabled, writes protected by the ramlist lock */ QLIST_ENTRY(RAMBlock) next; + QLIST_HEAD(, RAMBlockNotifier) ramblock_notifiers; int fd; size_t page_size; }; @@ -50,51 +52,7 @@ static inline void *ramblock_ptr(RAMBlock *block, ram_addr_t offset) return (char *)block->host + offset; } -/* The dirty memory bitmap is split into fixed-size blocks to allow growth - * under RCU. The bitmap for a block can be accessed as follows: - * - * rcu_read_lock(); - * - * DirtyMemoryBlocks *blocks = - * atomic_rcu_read(&ram_list.dirty_memory[DIRTY_MEMORY_MIGRATION]); - * - * ram_addr_t idx = (addr >> TARGET_PAGE_BITS) / DIRTY_MEMORY_BLOCK_SIZE; - * unsigned long *block = blocks.blocks[idx]; - * ...access block bitmap... - * - * rcu_read_unlock(); - * - * Remember to check for the end of the block when accessing a range of - * addresses. Move on to the next block if you reach the end. - * - * Organization into blocks allows dirty memory to grow (but not shrink) under - * RCU. When adding new RAMBlocks requires the dirty memory to grow, a new - * DirtyMemoryBlocks array is allocated with pointers to existing blocks kept - * the same. Other threads can safely access existing blocks while dirty - * memory is being grown. When no threads are using the old DirtyMemoryBlocks - * anymore it is freed by RCU (but the underlying blocks stay because they are - * pointed to from the new DirtyMemoryBlocks). - */ -#define DIRTY_MEMORY_BLOCK_SIZE ((ram_addr_t)256 * 1024 * 8) -typedef struct { - struct rcu_head rcu; - unsigned long *blocks[]; -} DirtyMemoryBlocks; - -typedef struct RAMList { - QemuMutex mutex; - RAMBlock *mru_block; - /* RCU-enabled, writes protected by the ramlist lock. */ - QLIST_HEAD(, RAMBlock) blocks; - DirtyMemoryBlocks *dirty_memory[DIRTY_MEMORY_NUM]; - uint32_t version; -} RAMList; -extern RAMList ram_list; - ram_addr_t last_ram_offset(void); -void qemu_mutex_lock_ramlist(void); -void qemu_mutex_unlock_ramlist(void); - RAMBlock *qemu_ram_alloc_from_file(ram_addr_t size, MemoryRegion *mr, bool share, const char *mem_path, Error **errp); |