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