]>
Commit | Line | Data |
---|---|---|
220c3ebd JQ |
1 | /* |
2 | * Declarations for cpu physical memory functions | |
3 | * | |
4 | * Copyright 2011 Red Hat, Inc. and/or its affiliates | |
5 | * | |
6 | * Authors: | |
7 | * Avi Kivity <avi@redhat.com> | |
8 | * | |
9 | * This work is licensed under the terms of the GNU GPL, version 2 or | |
10 | * later. See the COPYING file in the top-level directory. | |
11 | * | |
12 | */ | |
13 | ||
14 | /* | |
15 | * This header is for use by exec.c and memory.c ONLY. Do not include it. | |
16 | * The functions declared here will be removed soon. | |
17 | */ | |
18 | ||
19 | #ifndef RAM_ADDR_H | |
20 | #define RAM_ADDR_H | |
21 | ||
22 | #ifndef CONFIG_USER_ONLY | |
23 | #include "hw/xen/xen.h" | |
24 | ||
e1c57ab8 | 25 | ram_addr_t qemu_ram_alloc_from_file(ram_addr_t size, MemoryRegion *mr, |
dbcb8981 PB |
26 | bool share, const char *mem_path, |
27 | Error **errp); | |
220c3ebd | 28 | ram_addr_t qemu_ram_alloc_from_ptr(ram_addr_t size, void *host, |
ef701d7b HT |
29 | MemoryRegion *mr, Error **errp); |
30 | ram_addr_t qemu_ram_alloc(ram_addr_t size, MemoryRegion *mr, Error **errp); | |
62be4e3a MT |
31 | ram_addr_t qemu_ram_alloc_resizeable(ram_addr_t size, ram_addr_t max_size, |
32 | void (*resized)(const char*, | |
33 | uint64_t length, | |
34 | void *host), | |
35 | MemoryRegion *mr, Error **errp); | |
a35ba7be | 36 | int qemu_get_ram_fd(ram_addr_t addr); |
3fd74b84 | 37 | void *qemu_get_ram_block_host_ptr(ram_addr_t addr); |
220c3ebd JQ |
38 | void *qemu_get_ram_ptr(ram_addr_t addr); |
39 | void qemu_ram_free(ram_addr_t addr); | |
40 | void qemu_ram_free_from_ptr(ram_addr_t addr); | |
41 | ||
62be4e3a MT |
42 | int qemu_ram_resize(ram_addr_t base, ram_addr_t newsize, Error **errp); |
43 | ||
58d2707e PB |
44 | #define DIRTY_CLIENTS_ALL ((1 << DIRTY_MEMORY_NUM) - 1) |
45 | #define DIRTY_CLIENTS_NOCODE (DIRTY_CLIENTS_ALL & ~(1 << DIRTY_MEMORY_CODE)) | |
46 | ||
220c3ebd JQ |
47 | static inline bool cpu_physical_memory_get_dirty(ram_addr_t start, |
48 | ram_addr_t length, | |
49 | unsigned client) | |
50 | { | |
51 | unsigned long end, page, next; | |
52 | ||
53 | assert(client < DIRTY_MEMORY_NUM); | |
54 | ||
55 | end = TARGET_PAGE_ALIGN(start + length) >> TARGET_PAGE_BITS; | |
56 | page = start >> TARGET_PAGE_BITS; | |
57 | next = find_next_bit(ram_list.dirty_memory[client], end, page); | |
58 | ||
59 | return next < end; | |
60 | } | |
61 | ||
f874bf90 PM |
62 | static inline bool cpu_physical_memory_get_clean(ram_addr_t start, |
63 | ram_addr_t length, | |
64 | unsigned client) | |
65 | { | |
66 | unsigned long end, page, next; | |
67 | ||
68 | assert(client < DIRTY_MEMORY_NUM); | |
69 | ||
70 | end = TARGET_PAGE_ALIGN(start + length) >> TARGET_PAGE_BITS; | |
71 | page = start >> TARGET_PAGE_BITS; | |
72 | next = find_next_zero_bit(ram_list.dirty_memory[client], end, page); | |
73 | ||
74 | return next < end; | |
75 | } | |
76 | ||
220c3ebd JQ |
77 | static inline bool cpu_physical_memory_get_dirty_flag(ram_addr_t addr, |
78 | unsigned client) | |
79 | { | |
80 | return cpu_physical_memory_get_dirty(addr, 1, client); | |
81 | } | |
82 | ||
83 | static inline bool cpu_physical_memory_is_clean(ram_addr_t addr) | |
84 | { | |
85 | bool vga = cpu_physical_memory_get_dirty_flag(addr, DIRTY_MEMORY_VGA); | |
86 | bool code = cpu_physical_memory_get_dirty_flag(addr, DIRTY_MEMORY_CODE); | |
87 | bool migration = | |
88 | cpu_physical_memory_get_dirty_flag(addr, DIRTY_MEMORY_MIGRATION); | |
89 | return !(vga && code && migration); | |
90 | } | |
91 | ||
f874bf90 PM |
92 | static inline bool cpu_physical_memory_range_includes_clean(ram_addr_t start, |
93 | ram_addr_t length) | |
94 | { | |
95 | bool vga = cpu_physical_memory_get_clean(start, length, DIRTY_MEMORY_VGA); | |
96 | bool code = cpu_physical_memory_get_clean(start, length, DIRTY_MEMORY_CODE); | |
97 | bool migration = | |
98 | cpu_physical_memory_get_clean(start, length, DIRTY_MEMORY_MIGRATION); | |
99 | return vga || code || migration; | |
100 | } | |
101 | ||
220c3ebd JQ |
102 | static inline void cpu_physical_memory_set_dirty_flag(ram_addr_t addr, |
103 | unsigned client) | |
104 | { | |
105 | assert(client < DIRTY_MEMORY_NUM); | |
106 | set_bit(addr >> TARGET_PAGE_BITS, ram_list.dirty_memory[client]); | |
107 | } | |
108 | ||
109 | static inline void cpu_physical_memory_set_dirty_range(ram_addr_t start, | |
58d2707e PB |
110 | ram_addr_t length, |
111 | uint8_t mask) | |
220c3ebd JQ |
112 | { |
113 | unsigned long end, page; | |
114 | ||
115 | end = TARGET_PAGE_ALIGN(start + length) >> TARGET_PAGE_BITS; | |
116 | page = start >> TARGET_PAGE_BITS; | |
58d2707e PB |
117 | if (likely(mask & (1 << DIRTY_MEMORY_MIGRATION))) { |
118 | bitmap_set(ram_list.dirty_memory[DIRTY_MEMORY_MIGRATION], page, end - page); | |
119 | } | |
120 | if (unlikely(mask & (1 << DIRTY_MEMORY_VGA))) { | |
121 | bitmap_set(ram_list.dirty_memory[DIRTY_MEMORY_VGA], page, end - page); | |
122 | } | |
123 | if (unlikely(mask & (1 << DIRTY_MEMORY_CODE))) { | |
124 | bitmap_set(ram_list.dirty_memory[DIRTY_MEMORY_CODE], page, end - page); | |
125 | } | |
220c3ebd JQ |
126 | xen_modified_memory(start, length); |
127 | } | |
128 | ||
fb3ecb7e | 129 | #if !defined(_WIN32) |
5ff7fb77 JQ |
130 | static inline void cpu_physical_memory_set_dirty_lebitmap(unsigned long *bitmap, |
131 | ram_addr_t start, | |
132 | ram_addr_t pages) | |
133 | { | |
ae2810c4 | 134 | unsigned long i, j; |
5ff7fb77 JQ |
135 | unsigned long page_number, c; |
136 | hwaddr addr; | |
137 | ram_addr_t ram_addr; | |
ae2810c4 | 138 | unsigned long len = (pages + HOST_LONG_BITS - 1) / HOST_LONG_BITS; |
5ff7fb77 | 139 | unsigned long hpratio = getpagesize() / TARGET_PAGE_SIZE; |
ae2810c4 | 140 | unsigned long page = BIT_WORD(start >> TARGET_PAGE_BITS); |
5ff7fb77 | 141 | |
ae2810c4 | 142 | /* start address is aligned at the start of a word? */ |
f9ee9f9a AK |
143 | if ((((page * BITS_PER_LONG) << TARGET_PAGE_BITS) == start) && |
144 | (hpratio == 1)) { | |
ae2810c4 JQ |
145 | long k; |
146 | long nr = BITS_TO_LONGS(pages); | |
147 | ||
148 | for (k = 0; k < nr; k++) { | |
149 | if (bitmap[k]) { | |
150 | unsigned long temp = leul_to_cpu(bitmap[k]); | |
151 | ||
152 | ram_list.dirty_memory[DIRTY_MEMORY_MIGRATION][page + k] |= temp; | |
153 | ram_list.dirty_memory[DIRTY_MEMORY_VGA][page + k] |= temp; | |
154 | ram_list.dirty_memory[DIRTY_MEMORY_CODE][page + k] |= temp; | |
155 | } | |
156 | } | |
49dfcec4 | 157 | xen_modified_memory(start, pages << TARGET_PAGE_BITS); |
ae2810c4 JQ |
158 | } else { |
159 | /* | |
160 | * bitmap-traveling is faster than memory-traveling (for addr...) | |
161 | * especially when most of the memory is not dirty. | |
162 | */ | |
163 | for (i = 0; i < len; i++) { | |
164 | if (bitmap[i] != 0) { | |
165 | c = leul_to_cpu(bitmap[i]); | |
166 | do { | |
7224f66e | 167 | j = ctzl(c); |
ae2810c4 JQ |
168 | c &= ~(1ul << j); |
169 | page_number = (i * HOST_LONG_BITS + j) * hpratio; | |
170 | addr = page_number * TARGET_PAGE_SIZE; | |
171 | ram_addr = start + addr; | |
172 | cpu_physical_memory_set_dirty_range(ram_addr, | |
58d2707e PB |
173 | TARGET_PAGE_SIZE * hpratio, |
174 | DIRTY_CLIENTS_ALL); | |
ae2810c4 JQ |
175 | } while (c != 0); |
176 | } | |
5ff7fb77 JQ |
177 | } |
178 | } | |
179 | } | |
fb3ecb7e | 180 | #endif /* not _WIN32 */ |
5ff7fb77 | 181 | |
c8d6f66a MT |
182 | static inline void cpu_physical_memory_clear_dirty_range_type(ram_addr_t start, |
183 | ram_addr_t length, | |
184 | unsigned client) | |
220c3ebd JQ |
185 | { |
186 | unsigned long end, page; | |
187 | ||
188 | assert(client < DIRTY_MEMORY_NUM); | |
189 | end = TARGET_PAGE_ALIGN(start + length) >> TARGET_PAGE_BITS; | |
190 | page = start >> TARGET_PAGE_BITS; | |
191 | bitmap_clear(ram_list.dirty_memory[client], page, end - page); | |
192 | } | |
193 | ||
c8d6f66a MT |
194 | static inline void cpu_physical_memory_clear_dirty_range(ram_addr_t start, |
195 | ram_addr_t length) | |
196 | { | |
197 | cpu_physical_memory_clear_dirty_range_type(start, length, DIRTY_MEMORY_MIGRATION); | |
198 | cpu_physical_memory_clear_dirty_range_type(start, length, DIRTY_MEMORY_VGA); | |
199 | cpu_physical_memory_clear_dirty_range_type(start, length, DIRTY_MEMORY_CODE); | |
200 | } | |
201 | ||
202 | ||
220c3ebd JQ |
203 | void cpu_physical_memory_reset_dirty(ram_addr_t start, ram_addr_t length, |
204 | unsigned client); | |
205 | ||
206 | #endif | |
207 | #endif |