]>
Commit | Line | Data |
---|---|---|
0987d735 PB |
1 | #ifndef RAMLIST_H |
2 | #define RAMLIST_H | |
3 | ||
4 | #include "qemu/queue.h" | |
5 | #include "qemu/thread.h" | |
6 | #include "qemu/rcu.h" | |
99e15582 | 7 | #include "qemu/rcu_queue.h" |
0987d735 PB |
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 = | |
d73415a3 | 22 | * qatomic_rcu_read(&ram_list.dirty_memory[DIRTY_MEMORY_MIGRATION]); |
0987d735 PB |
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 | ||
99e15582 | 58 | /* Should be holding either ram_list.mutex, or the RCU lock. */ |
343f632c | 59 | #define INTERNAL_RAMBLOCK_FOREACH(block) \ |
99e15582 | 60 | QLIST_FOREACH_RCU(block, &ram_list.blocks, next) |
343f632c DDAG |
61 | /* Never use the INTERNAL_ version except for defining other macros */ |
62 | #define RAMBLOCK_FOREACH(block) INTERNAL_RAMBLOCK_FOREACH(block) | |
99e15582 | 63 | |
0987d735 PB |
64 | void qemu_mutex_lock_ramlist(void); |
65 | void qemu_mutex_unlock_ramlist(void); | |
66 | ||
67 | struct RAMBlockNotifier { | |
8f44304c DH |
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); | |
0987d735 PB |
74 | QLIST_ENTRY(RAMBlockNotifier) next; |
75 | }; | |
76 | ||
77 | void ram_block_notifier_add(RAMBlockNotifier *n); | |
78 | void ram_block_notifier_remove(RAMBlockNotifier *n); | |
8f44304c DH |
79 | void ram_block_notify_add(void *host, size_t size, size_t max_size); |
80 | void ram_block_notify_remove(void *host, size_t size, size_t max_size); | |
81 | void ram_block_notify_resize(void *host, size_t old_size, size_t new_size); | |
0987d735 | 82 | |
ca411b7c | 83 | GString *ram_block_format(void); |
0987d735 PB |
84 | |
85 | #endif /* RAMLIST_H */ |