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 | |
9 | typedef 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 | * atomic_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) |
42 | typedef struct { |
43 | struct rcu_head rcu; |
44 | unsigned long *blocks[]; |
45 | } DirtyMemoryBlocks; |
46 | |
47 | typedef 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; |
56 | extern 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 | |
64 | void qemu_mutex_lock_ramlist(void); |
65 | void qemu_mutex_unlock_ramlist(void); |
66 | |
67 | struct RAMBlockNotifier { |
68 | void (*ram_block_added)(RAMBlockNotifier *n, void *host, size_t size); |
69 | void (*ram_block_removed)(RAMBlockNotifier *n, void *host, size_t size); |
70 | QLIST_ENTRY(RAMBlockNotifier) next; |
71 | }; |
72 | |
73 | void ram_block_notifier_add(RAMBlockNotifier *n); |
74 | void ram_block_notifier_remove(RAMBlockNotifier *n); |
75 | void ram_block_notify_add(void *host, size_t size); |
76 | void ram_block_notify_remove(void *host, size_t size); |
77 | |
78 | void ram_block_dump(Monitor *mon); |
79 | |
80 | #endif /* RAMLIST_H */ |
81 | |