xref: /openbmc/qemu/include/exec/ramlist.h (revision 429d3ae2)
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