ramlist.h (3157B)
1#ifndef RAMLIST_H 2#define RAMLIST_H 3 4#include "qemu/queue.h" 5#include "qemu/thread.h" 6#include "qemu/rcu.h" 7#include "qemu/rcu_queue.h" 8 9typedef struct RAMBlockNotifier RAMBlockNotifier; 10 11#define DIRTY_MEMORY_VGA 0 12#define DIRTY_MEMORY_CODE 1 13#define DIRTY_MEMORY_MIGRATION 2 14#define DIRTY_MEMORY_NUM 3 /* num of dirty bits */ 15 16/* The dirty memory bitmap is split into fixed-size blocks to allow growth 17 * under RCU. The bitmap for a block can be accessed as follows: 18 * 19 * rcu_read_lock(); 20 * 21 * DirtyMemoryBlocks *blocks = 22 * qatomic_rcu_read(&ram_list.dirty_memory[DIRTY_MEMORY_MIGRATION]); 23 * 24 * ram_addr_t idx = (addr >> TARGET_PAGE_BITS) / DIRTY_MEMORY_BLOCK_SIZE; 25 * unsigned long *block = blocks.blocks[idx]; 26 * ...access block bitmap... 27 * 28 * rcu_read_unlock(); 29 * 30 * Remember to check for the end of the block when accessing a range of 31 * addresses. Move on to the next block if you reach the end. 32 * 33 * Organization into blocks allows dirty memory to grow (but not shrink) under 34 * RCU. When adding new RAMBlocks requires the dirty memory to grow, a new 35 * DirtyMemoryBlocks array is allocated with pointers to existing blocks kept 36 * the same. Other threads can safely access existing blocks while dirty 37 * memory is being grown. When no threads are using the old DirtyMemoryBlocks 38 * anymore it is freed by RCU (but the underlying blocks stay because they are 39 * pointed to from the new DirtyMemoryBlocks). 40 */ 41#define DIRTY_MEMORY_BLOCK_SIZE ((ram_addr_t)256 * 1024 * 8) 42typedef struct { 43 struct rcu_head rcu; 44 unsigned long *blocks[]; 45} DirtyMemoryBlocks; 46 47typedef struct RAMList { 48 QemuMutex mutex; 49 RAMBlock *mru_block; 50 /* RCU-enabled, writes protected by the ramlist lock. */ 51 QLIST_HEAD(, RAMBlock) blocks; 52 DirtyMemoryBlocks *dirty_memory[DIRTY_MEMORY_NUM]; 53 uint32_t version; 54 QLIST_HEAD(, RAMBlockNotifier) ramblock_notifiers; 55} RAMList; 56extern RAMList ram_list; 57 58/* Should be holding either ram_list.mutex, or the RCU lock. */ 59#define INTERNAL_RAMBLOCK_FOREACH(block) \ 60 QLIST_FOREACH_RCU(block, &ram_list.blocks, next) 61/* Never use the INTERNAL_ version except for defining other macros */ 62#define RAMBLOCK_FOREACH(block) INTERNAL_RAMBLOCK_FOREACH(block) 63 64void qemu_mutex_lock_ramlist(void); 65void qemu_mutex_unlock_ramlist(void); 66 67struct RAMBlockNotifier { 68 void (*ram_block_added)(RAMBlockNotifier *n, void *host, size_t size, 69 size_t max_size); 70 void (*ram_block_removed)(RAMBlockNotifier *n, void *host, size_t size, 71 size_t max_size); 72 void (*ram_block_resized)(RAMBlockNotifier *n, void *host, size_t old_size, 73 size_t new_size); 74 QLIST_ENTRY(RAMBlockNotifier) next; 75}; 76 77void ram_block_notifier_add(RAMBlockNotifier *n); 78void ram_block_notifier_remove(RAMBlockNotifier *n); 79void ram_block_notify_add(void *host, size_t size, size_t max_size); 80void ram_block_notify_remove(void *host, size_t size, size_t max_size); 81void ram_block_notify_resize(void *host, size_t old_size, size_t new_size); 82 83void ram_block_dump(Monitor *mon); 84 85#endif /* RAMLIST_H */