Statistics
| Branch: | Revision:

root / memory.c @ ce5d2f33

History | View | Annotate | Download (55.8 kB)

1 093bc2cd Avi Kivity
/*
2 093bc2cd Avi Kivity
 * Physical memory management
3 093bc2cd Avi Kivity
 *
4 093bc2cd Avi Kivity
 * Copyright 2011 Red Hat, Inc. and/or its affiliates
5 093bc2cd Avi Kivity
 *
6 093bc2cd Avi Kivity
 * Authors:
7 093bc2cd Avi Kivity
 *  Avi Kivity <avi@redhat.com>
8 093bc2cd Avi Kivity
 *
9 093bc2cd Avi Kivity
 * This work is licensed under the terms of the GNU GPL, version 2.  See
10 093bc2cd Avi Kivity
 * the COPYING file in the top-level directory.
11 093bc2cd Avi Kivity
 *
12 6b620ca3 Paolo Bonzini
 * Contributions after 2012-01-13 are licensed under the terms of the
13 6b620ca3 Paolo Bonzini
 * GNU GPL, version 2 or (at your option) any later version.
14 093bc2cd Avi Kivity
 */
15 093bc2cd Avi Kivity
16 022c62cb Paolo Bonzini
#include "exec/memory.h"
17 022c62cb Paolo Bonzini
#include "exec/address-spaces.h"
18 022c62cb Paolo Bonzini
#include "exec/ioport.h"
19 1de7afc9 Paolo Bonzini
#include "qemu/bitops.h"
20 9c17d615 Paolo Bonzini
#include "sysemu/kvm.h"
21 093bc2cd Avi Kivity
#include <assert.h>
22 093bc2cd Avi Kivity
23 022c62cb Paolo Bonzini
#include "exec/memory-internal.h"
24 67d95c15 Avi Kivity
25 d197063f Paolo Bonzini
//#define DEBUG_UNASSIGNED
26 d197063f Paolo Bonzini
27 22bde714 Jan Kiszka
static unsigned memory_region_transaction_depth;
28 22bde714 Jan Kiszka
static bool memory_region_update_pending;
29 7664e80c Avi Kivity
static bool global_dirty_log = false;
30 7664e80c Avi Kivity
31 72e22d2f Avi Kivity
static QTAILQ_HEAD(memory_listeners, MemoryListener) memory_listeners
32 72e22d2f Avi Kivity
    = QTAILQ_HEAD_INITIALIZER(memory_listeners);
33 4ef4db86 Avi Kivity
34 0d673e36 Avi Kivity
static QTAILQ_HEAD(, AddressSpace) address_spaces
35 0d673e36 Avi Kivity
    = QTAILQ_HEAD_INITIALIZER(address_spaces);
36 0d673e36 Avi Kivity
37 093bc2cd Avi Kivity
typedef struct AddrRange AddrRange;
38 093bc2cd Avi Kivity
39 8417cebf Avi Kivity
/*
40 8417cebf Avi Kivity
 * Note using signed integers limits us to physical addresses at most
41 8417cebf Avi Kivity
 * 63 bits wide.  They are needed for negative offsetting in aliases
42 8417cebf Avi Kivity
 * (large MemoryRegion::alias_offset).
43 8417cebf Avi Kivity
 */
44 093bc2cd Avi Kivity
struct AddrRange {
45 08dafab4 Avi Kivity
    Int128 start;
46 08dafab4 Avi Kivity
    Int128 size;
47 093bc2cd Avi Kivity
};
48 093bc2cd Avi Kivity
49 08dafab4 Avi Kivity
static AddrRange addrrange_make(Int128 start, Int128 size)
50 093bc2cd Avi Kivity
{
51 093bc2cd Avi Kivity
    return (AddrRange) { start, size };
52 093bc2cd Avi Kivity
}
53 093bc2cd Avi Kivity
54 093bc2cd Avi Kivity
static bool addrrange_equal(AddrRange r1, AddrRange r2)
55 093bc2cd Avi Kivity
{
56 08dafab4 Avi Kivity
    return int128_eq(r1.start, r2.start) && int128_eq(r1.size, r2.size);
57 093bc2cd Avi Kivity
}
58 093bc2cd Avi Kivity
59 08dafab4 Avi Kivity
static Int128 addrrange_end(AddrRange r)
60 093bc2cd Avi Kivity
{
61 08dafab4 Avi Kivity
    return int128_add(r.start, r.size);
62 093bc2cd Avi Kivity
}
63 093bc2cd Avi Kivity
64 08dafab4 Avi Kivity
static AddrRange addrrange_shift(AddrRange range, Int128 delta)
65 093bc2cd Avi Kivity
{
66 08dafab4 Avi Kivity
    int128_addto(&range.start, delta);
67 093bc2cd Avi Kivity
    return range;
68 093bc2cd Avi Kivity
}
69 093bc2cd Avi Kivity
70 08dafab4 Avi Kivity
static bool addrrange_contains(AddrRange range, Int128 addr)
71 08dafab4 Avi Kivity
{
72 08dafab4 Avi Kivity
    return int128_ge(addr, range.start)
73 08dafab4 Avi Kivity
        && int128_lt(addr, addrrange_end(range));
74 08dafab4 Avi Kivity
}
75 08dafab4 Avi Kivity
76 093bc2cd Avi Kivity
static bool addrrange_intersects(AddrRange r1, AddrRange r2)
77 093bc2cd Avi Kivity
{
78 08dafab4 Avi Kivity
    return addrrange_contains(r1, r2.start)
79 08dafab4 Avi Kivity
        || addrrange_contains(r2, r1.start);
80 093bc2cd Avi Kivity
}
81 093bc2cd Avi Kivity
82 093bc2cd Avi Kivity
static AddrRange addrrange_intersection(AddrRange r1, AddrRange r2)
83 093bc2cd Avi Kivity
{
84 08dafab4 Avi Kivity
    Int128 start = int128_max(r1.start, r2.start);
85 08dafab4 Avi Kivity
    Int128 end = int128_min(addrrange_end(r1), addrrange_end(r2));
86 08dafab4 Avi Kivity
    return addrrange_make(start, int128_sub(end, start));
87 093bc2cd Avi Kivity
}
88 093bc2cd Avi Kivity
89 0e0d36b4 Avi Kivity
enum ListenerDirection { Forward, Reverse };
90 0e0d36b4 Avi Kivity
91 7376e582 Avi Kivity
static bool memory_listener_match(MemoryListener *listener,
92 7376e582 Avi Kivity
                                  MemoryRegionSection *section)
93 7376e582 Avi Kivity
{
94 7376e582 Avi Kivity
    return !listener->address_space_filter
95 7376e582 Avi Kivity
        || listener->address_space_filter == section->address_space;
96 7376e582 Avi Kivity
}
97 7376e582 Avi Kivity
98 7376e582 Avi Kivity
#define MEMORY_LISTENER_CALL_GLOBAL(_callback, _direction, _args...)    \
99 0e0d36b4 Avi Kivity
    do {                                                                \
100 0e0d36b4 Avi Kivity
        MemoryListener *_listener;                                      \
101 0e0d36b4 Avi Kivity
                                                                        \
102 0e0d36b4 Avi Kivity
        switch (_direction) {                                           \
103 0e0d36b4 Avi Kivity
        case Forward:                                                   \
104 0e0d36b4 Avi Kivity
            QTAILQ_FOREACH(_listener, &memory_listeners, link) {        \
105 975aefe0 Avi Kivity
                if (_listener->_callback) {                             \
106 975aefe0 Avi Kivity
                    _listener->_callback(_listener, ##_args);           \
107 975aefe0 Avi Kivity
                }                                                       \
108 0e0d36b4 Avi Kivity
            }                                                           \
109 0e0d36b4 Avi Kivity
            break;                                                      \
110 0e0d36b4 Avi Kivity
        case Reverse:                                                   \
111 0e0d36b4 Avi Kivity
            QTAILQ_FOREACH_REVERSE(_listener, &memory_listeners,        \
112 0e0d36b4 Avi Kivity
                                   memory_listeners, link) {            \
113 975aefe0 Avi Kivity
                if (_listener->_callback) {                             \
114 975aefe0 Avi Kivity
                    _listener->_callback(_listener, ##_args);           \
115 975aefe0 Avi Kivity
                }                                                       \
116 0e0d36b4 Avi Kivity
            }                                                           \
117 0e0d36b4 Avi Kivity
            break;                                                      \
118 0e0d36b4 Avi Kivity
        default:                                                        \
119 0e0d36b4 Avi Kivity
            abort();                                                    \
120 0e0d36b4 Avi Kivity
        }                                                               \
121 0e0d36b4 Avi Kivity
    } while (0)
122 0e0d36b4 Avi Kivity
123 7376e582 Avi Kivity
#define MEMORY_LISTENER_CALL(_callback, _direction, _section, _args...) \
124 7376e582 Avi Kivity
    do {                                                                \
125 7376e582 Avi Kivity
        MemoryListener *_listener;                                      \
126 7376e582 Avi Kivity
                                                                        \
127 7376e582 Avi Kivity
        switch (_direction) {                                           \
128 7376e582 Avi Kivity
        case Forward:                                                   \
129 7376e582 Avi Kivity
            QTAILQ_FOREACH(_listener, &memory_listeners, link) {        \
130 975aefe0 Avi Kivity
                if (_listener->_callback                                \
131 975aefe0 Avi Kivity
                    && memory_listener_match(_listener, _section)) {    \
132 7376e582 Avi Kivity
                    _listener->_callback(_listener, _section, ##_args); \
133 7376e582 Avi Kivity
                }                                                       \
134 7376e582 Avi Kivity
            }                                                           \
135 7376e582 Avi Kivity
            break;                                                      \
136 7376e582 Avi Kivity
        case Reverse:                                                   \
137 7376e582 Avi Kivity
            QTAILQ_FOREACH_REVERSE(_listener, &memory_listeners,        \
138 7376e582 Avi Kivity
                                   memory_listeners, link) {            \
139 975aefe0 Avi Kivity
                if (_listener->_callback                                \
140 975aefe0 Avi Kivity
                    && memory_listener_match(_listener, _section)) {    \
141 7376e582 Avi Kivity
                    _listener->_callback(_listener, _section, ##_args); \
142 7376e582 Avi Kivity
                }                                                       \
143 7376e582 Avi Kivity
            }                                                           \
144 7376e582 Avi Kivity
            break;                                                      \
145 7376e582 Avi Kivity
        default:                                                        \
146 7376e582 Avi Kivity
            abort();                                                    \
147 7376e582 Avi Kivity
        }                                                               \
148 7376e582 Avi Kivity
    } while (0)
149 7376e582 Avi Kivity
150 0e0d36b4 Avi Kivity
#define MEMORY_LISTENER_UPDATE_REGION(fr, as, dir, callback)            \
151 7376e582 Avi Kivity
    MEMORY_LISTENER_CALL(callback, dir, (&(MemoryRegionSection) {       \
152 0e0d36b4 Avi Kivity
        .mr = (fr)->mr,                                                 \
153 f6790af6 Avi Kivity
        .address_space = (as),                                          \
154 0e0d36b4 Avi Kivity
        .offset_within_region = (fr)->offset_in_region,                 \
155 0e0d36b4 Avi Kivity
        .size = int128_get64((fr)->addr.size),                          \
156 0e0d36b4 Avi Kivity
        .offset_within_address_space = int128_get64((fr)->addr.start),  \
157 7a8499e8 Avi Kivity
        .readonly = (fr)->readonly,                                     \
158 7376e582 Avi Kivity
              }))
159 0e0d36b4 Avi Kivity
160 093bc2cd Avi Kivity
struct CoalescedMemoryRange {
161 093bc2cd Avi Kivity
    AddrRange addr;
162 093bc2cd Avi Kivity
    QTAILQ_ENTRY(CoalescedMemoryRange) link;
163 093bc2cd Avi Kivity
};
164 093bc2cd Avi Kivity
165 3e9d69e7 Avi Kivity
struct MemoryRegionIoeventfd {
166 3e9d69e7 Avi Kivity
    AddrRange addr;
167 3e9d69e7 Avi Kivity
    bool match_data;
168 3e9d69e7 Avi Kivity
    uint64_t data;
169 753d5e14 Paolo Bonzini
    EventNotifier *e;
170 3e9d69e7 Avi Kivity
};
171 3e9d69e7 Avi Kivity
172 3e9d69e7 Avi Kivity
static bool memory_region_ioeventfd_before(MemoryRegionIoeventfd a,
173 3e9d69e7 Avi Kivity
                                           MemoryRegionIoeventfd b)
174 3e9d69e7 Avi Kivity
{
175 08dafab4 Avi Kivity
    if (int128_lt(a.addr.start, b.addr.start)) {
176 3e9d69e7 Avi Kivity
        return true;
177 08dafab4 Avi Kivity
    } else if (int128_gt(a.addr.start, b.addr.start)) {
178 3e9d69e7 Avi Kivity
        return false;
179 08dafab4 Avi Kivity
    } else if (int128_lt(a.addr.size, b.addr.size)) {
180 3e9d69e7 Avi Kivity
        return true;
181 08dafab4 Avi Kivity
    } else if (int128_gt(a.addr.size, b.addr.size)) {
182 3e9d69e7 Avi Kivity
        return false;
183 3e9d69e7 Avi Kivity
    } else if (a.match_data < b.match_data) {
184 3e9d69e7 Avi Kivity
        return true;
185 3e9d69e7 Avi Kivity
    } else  if (a.match_data > b.match_data) {
186 3e9d69e7 Avi Kivity
        return false;
187 3e9d69e7 Avi Kivity
    } else if (a.match_data) {
188 3e9d69e7 Avi Kivity
        if (a.data < b.data) {
189 3e9d69e7 Avi Kivity
            return true;
190 3e9d69e7 Avi Kivity
        } else if (a.data > b.data) {
191 3e9d69e7 Avi Kivity
            return false;
192 3e9d69e7 Avi Kivity
        }
193 3e9d69e7 Avi Kivity
    }
194 753d5e14 Paolo Bonzini
    if (a.e < b.e) {
195 3e9d69e7 Avi Kivity
        return true;
196 753d5e14 Paolo Bonzini
    } else if (a.e > b.e) {
197 3e9d69e7 Avi Kivity
        return false;
198 3e9d69e7 Avi Kivity
    }
199 3e9d69e7 Avi Kivity
    return false;
200 3e9d69e7 Avi Kivity
}
201 3e9d69e7 Avi Kivity
202 3e9d69e7 Avi Kivity
static bool memory_region_ioeventfd_equal(MemoryRegionIoeventfd a,
203 3e9d69e7 Avi Kivity
                                          MemoryRegionIoeventfd b)
204 3e9d69e7 Avi Kivity
{
205 3e9d69e7 Avi Kivity
    return !memory_region_ioeventfd_before(a, b)
206 3e9d69e7 Avi Kivity
        && !memory_region_ioeventfd_before(b, a);
207 3e9d69e7 Avi Kivity
}
208 3e9d69e7 Avi Kivity
209 093bc2cd Avi Kivity
typedef struct FlatRange FlatRange;
210 093bc2cd Avi Kivity
typedef struct FlatView FlatView;
211 093bc2cd Avi Kivity
212 093bc2cd Avi Kivity
/* Range of memory in the global map.  Addresses are absolute. */
213 093bc2cd Avi Kivity
struct FlatRange {
214 093bc2cd Avi Kivity
    MemoryRegion *mr;
215 a8170e5e Avi Kivity
    hwaddr offset_in_region;
216 093bc2cd Avi Kivity
    AddrRange addr;
217 5a583347 Avi Kivity
    uint8_t dirty_log_mask;
218 5f9a5ea1 Jan Kiszka
    bool romd_mode;
219 fb1cd6f9 Avi Kivity
    bool readonly;
220 093bc2cd Avi Kivity
};
221 093bc2cd Avi Kivity
222 093bc2cd Avi Kivity
/* Flattened global view of current active memory hierarchy.  Kept in sorted
223 093bc2cd Avi Kivity
 * order.
224 093bc2cd Avi Kivity
 */
225 093bc2cd Avi Kivity
struct FlatView {
226 093bc2cd Avi Kivity
    FlatRange *ranges;
227 093bc2cd Avi Kivity
    unsigned nr;
228 093bc2cd Avi Kivity
    unsigned nr_allocated;
229 093bc2cd Avi Kivity
};
230 093bc2cd Avi Kivity
231 cc31e6e7 Avi Kivity
typedef struct AddressSpaceOps AddressSpaceOps;
232 cc31e6e7 Avi Kivity
233 093bc2cd Avi Kivity
#define FOR_EACH_FLAT_RANGE(var, view)          \
234 093bc2cd Avi Kivity
    for (var = (view)->ranges; var < (view)->ranges + (view)->nr; ++var)
235 093bc2cd Avi Kivity
236 093bc2cd Avi Kivity
static bool flatrange_equal(FlatRange *a, FlatRange *b)
237 093bc2cd Avi Kivity
{
238 093bc2cd Avi Kivity
    return a->mr == b->mr
239 093bc2cd Avi Kivity
        && addrrange_equal(a->addr, b->addr)
240 d0a9b5bc Avi Kivity
        && a->offset_in_region == b->offset_in_region
241 5f9a5ea1 Jan Kiszka
        && a->romd_mode == b->romd_mode
242 fb1cd6f9 Avi Kivity
        && a->readonly == b->readonly;
243 093bc2cd Avi Kivity
}
244 093bc2cd Avi Kivity
245 093bc2cd Avi Kivity
static void flatview_init(FlatView *view)
246 093bc2cd Avi Kivity
{
247 093bc2cd Avi Kivity
    view->ranges = NULL;
248 093bc2cd Avi Kivity
    view->nr = 0;
249 093bc2cd Avi Kivity
    view->nr_allocated = 0;
250 093bc2cd Avi Kivity
}
251 093bc2cd Avi Kivity
252 093bc2cd Avi Kivity
/* Insert a range into a given position.  Caller is responsible for maintaining
253 093bc2cd Avi Kivity
 * sorting order.
254 093bc2cd Avi Kivity
 */
255 093bc2cd Avi Kivity
static void flatview_insert(FlatView *view, unsigned pos, FlatRange *range)
256 093bc2cd Avi Kivity
{
257 093bc2cd Avi Kivity
    if (view->nr == view->nr_allocated) {
258 093bc2cd Avi Kivity
        view->nr_allocated = MAX(2 * view->nr, 10);
259 7267c094 Anthony Liguori
        view->ranges = g_realloc(view->ranges,
260 093bc2cd Avi Kivity
                                    view->nr_allocated * sizeof(*view->ranges));
261 093bc2cd Avi Kivity
    }
262 093bc2cd Avi Kivity
    memmove(view->ranges + pos + 1, view->ranges + pos,
263 093bc2cd Avi Kivity
            (view->nr - pos) * sizeof(FlatRange));
264 093bc2cd Avi Kivity
    view->ranges[pos] = *range;
265 093bc2cd Avi Kivity
    ++view->nr;
266 093bc2cd Avi Kivity
}
267 093bc2cd Avi Kivity
268 093bc2cd Avi Kivity
static void flatview_destroy(FlatView *view)
269 093bc2cd Avi Kivity
{
270 7267c094 Anthony Liguori
    g_free(view->ranges);
271 093bc2cd Avi Kivity
}
272 093bc2cd Avi Kivity
273 3d8e6bf9 Avi Kivity
static bool can_merge(FlatRange *r1, FlatRange *r2)
274 3d8e6bf9 Avi Kivity
{
275 08dafab4 Avi Kivity
    return int128_eq(addrrange_end(r1->addr), r2->addr.start)
276 3d8e6bf9 Avi Kivity
        && r1->mr == r2->mr
277 08dafab4 Avi Kivity
        && int128_eq(int128_add(int128_make64(r1->offset_in_region),
278 08dafab4 Avi Kivity
                                r1->addr.size),
279 08dafab4 Avi Kivity
                     int128_make64(r2->offset_in_region))
280 d0a9b5bc Avi Kivity
        && r1->dirty_log_mask == r2->dirty_log_mask
281 5f9a5ea1 Jan Kiszka
        && r1->romd_mode == r2->romd_mode
282 fb1cd6f9 Avi Kivity
        && r1->readonly == r2->readonly;
283 3d8e6bf9 Avi Kivity
}
284 3d8e6bf9 Avi Kivity
285 3d8e6bf9 Avi Kivity
/* Attempt to simplify a view by merging ajacent ranges */
286 3d8e6bf9 Avi Kivity
static void flatview_simplify(FlatView *view)
287 3d8e6bf9 Avi Kivity
{
288 3d8e6bf9 Avi Kivity
    unsigned i, j;
289 3d8e6bf9 Avi Kivity
290 3d8e6bf9 Avi Kivity
    i = 0;
291 3d8e6bf9 Avi Kivity
    while (i < view->nr) {
292 3d8e6bf9 Avi Kivity
        j = i + 1;
293 3d8e6bf9 Avi Kivity
        while (j < view->nr
294 3d8e6bf9 Avi Kivity
               && can_merge(&view->ranges[j-1], &view->ranges[j])) {
295 08dafab4 Avi Kivity
            int128_addto(&view->ranges[i].addr.size, view->ranges[j].addr.size);
296 3d8e6bf9 Avi Kivity
            ++j;
297 3d8e6bf9 Avi Kivity
        }
298 3d8e6bf9 Avi Kivity
        ++i;
299 3d8e6bf9 Avi Kivity
        memmove(&view->ranges[i], &view->ranges[j],
300 3d8e6bf9 Avi Kivity
                (view->nr - j) * sizeof(view->ranges[j]));
301 3d8e6bf9 Avi Kivity
        view->nr -= j - i;
302 3d8e6bf9 Avi Kivity
    }
303 3d8e6bf9 Avi Kivity
}
304 3d8e6bf9 Avi Kivity
305 ce5d2f33 Paolo Bonzini
static void memory_region_oldmmio_read_accessor(void *opaque,
306 ce5d2f33 Paolo Bonzini
                                                hwaddr addr,
307 ce5d2f33 Paolo Bonzini
                                                uint64_t *value,
308 ce5d2f33 Paolo Bonzini
                                                unsigned size,
309 ce5d2f33 Paolo Bonzini
                                                unsigned shift,
310 ce5d2f33 Paolo Bonzini
                                                uint64_t mask)
311 ce5d2f33 Paolo Bonzini
{
312 ce5d2f33 Paolo Bonzini
    MemoryRegion *mr = opaque;
313 ce5d2f33 Paolo Bonzini
    uint64_t tmp;
314 ce5d2f33 Paolo Bonzini
315 ce5d2f33 Paolo Bonzini
    tmp = mr->ops->old_mmio.read[ctz32(size)](mr->opaque, addr);
316 ce5d2f33 Paolo Bonzini
    *value |= (tmp & mask) << shift;
317 ce5d2f33 Paolo Bonzini
}
318 ce5d2f33 Paolo Bonzini
319 164a4dcd Avi Kivity
static void memory_region_read_accessor(void *opaque,
320 a8170e5e Avi Kivity
                                        hwaddr addr,
321 164a4dcd Avi Kivity
                                        uint64_t *value,
322 164a4dcd Avi Kivity
                                        unsigned size,
323 164a4dcd Avi Kivity
                                        unsigned shift,
324 164a4dcd Avi Kivity
                                        uint64_t mask)
325 164a4dcd Avi Kivity
{
326 164a4dcd Avi Kivity
    MemoryRegion *mr = opaque;
327 164a4dcd Avi Kivity
    uint64_t tmp;
328 164a4dcd Avi Kivity
329 d410515e Jan Kiszka
    if (mr->flush_coalesced_mmio) {
330 d410515e Jan Kiszka
        qemu_flush_coalesced_mmio_buffer();
331 d410515e Jan Kiszka
    }
332 164a4dcd Avi Kivity
    tmp = mr->ops->read(mr->opaque, addr, size);
333 164a4dcd Avi Kivity
    *value |= (tmp & mask) << shift;
334 164a4dcd Avi Kivity
}
335 164a4dcd Avi Kivity
336 ce5d2f33 Paolo Bonzini
static void memory_region_oldmmio_write_accessor(void *opaque,
337 ce5d2f33 Paolo Bonzini
                                                 hwaddr addr,
338 ce5d2f33 Paolo Bonzini
                                                 uint64_t *value,
339 ce5d2f33 Paolo Bonzini
                                                 unsigned size,
340 ce5d2f33 Paolo Bonzini
                                                 unsigned shift,
341 ce5d2f33 Paolo Bonzini
                                                 uint64_t mask)
342 ce5d2f33 Paolo Bonzini
{
343 ce5d2f33 Paolo Bonzini
    MemoryRegion *mr = opaque;
344 ce5d2f33 Paolo Bonzini
    uint64_t tmp;
345 ce5d2f33 Paolo Bonzini
346 ce5d2f33 Paolo Bonzini
    tmp = (*value >> shift) & mask;
347 ce5d2f33 Paolo Bonzini
    mr->ops->old_mmio.write[ctz32(size)](mr->opaque, addr, tmp);
348 ce5d2f33 Paolo Bonzini
}
349 ce5d2f33 Paolo Bonzini
350 164a4dcd Avi Kivity
static void memory_region_write_accessor(void *opaque,
351 a8170e5e Avi Kivity
                                         hwaddr addr,
352 164a4dcd Avi Kivity
                                         uint64_t *value,
353 164a4dcd Avi Kivity
                                         unsigned size,
354 164a4dcd Avi Kivity
                                         unsigned shift,
355 164a4dcd Avi Kivity
                                         uint64_t mask)
356 164a4dcd Avi Kivity
{
357 164a4dcd Avi Kivity
    MemoryRegion *mr = opaque;
358 164a4dcd Avi Kivity
    uint64_t tmp;
359 164a4dcd Avi Kivity
360 d410515e Jan Kiszka
    if (mr->flush_coalesced_mmio) {
361 d410515e Jan Kiszka
        qemu_flush_coalesced_mmio_buffer();
362 d410515e Jan Kiszka
    }
363 164a4dcd Avi Kivity
    tmp = (*value >> shift) & mask;
364 164a4dcd Avi Kivity
    mr->ops->write(mr->opaque, addr, tmp, size);
365 164a4dcd Avi Kivity
}
366 164a4dcd Avi Kivity
367 a8170e5e Avi Kivity
static void access_with_adjusted_size(hwaddr addr,
368 164a4dcd Avi Kivity
                                      uint64_t *value,
369 164a4dcd Avi Kivity
                                      unsigned size,
370 164a4dcd Avi Kivity
                                      unsigned access_size_min,
371 164a4dcd Avi Kivity
                                      unsigned access_size_max,
372 164a4dcd Avi Kivity
                                      void (*access)(void *opaque,
373 a8170e5e Avi Kivity
                                                     hwaddr addr,
374 164a4dcd Avi Kivity
                                                     uint64_t *value,
375 164a4dcd Avi Kivity
                                                     unsigned size,
376 164a4dcd Avi Kivity
                                                     unsigned shift,
377 164a4dcd Avi Kivity
                                                     uint64_t mask),
378 164a4dcd Avi Kivity
                                      void *opaque)
379 164a4dcd Avi Kivity
{
380 164a4dcd Avi Kivity
    uint64_t access_mask;
381 164a4dcd Avi Kivity
    unsigned access_size;
382 164a4dcd Avi Kivity
    unsigned i;
383 164a4dcd Avi Kivity
384 164a4dcd Avi Kivity
    if (!access_size_min) {
385 164a4dcd Avi Kivity
        access_size_min = 1;
386 164a4dcd Avi Kivity
    }
387 164a4dcd Avi Kivity
    if (!access_size_max) {
388 164a4dcd Avi Kivity
        access_size_max = 4;
389 164a4dcd Avi Kivity
    }
390 ce5d2f33 Paolo Bonzini
391 ce5d2f33 Paolo Bonzini
    /* FIXME: support unaligned access? */
392 164a4dcd Avi Kivity
    access_size = MAX(MIN(size, access_size_max), access_size_min);
393 164a4dcd Avi Kivity
    access_mask = -1ULL >> (64 - access_size * 8);
394 164a4dcd Avi Kivity
    for (i = 0; i < size; i += access_size) {
395 08521e28 Paolo Bonzini
#ifdef TARGET_WORDS_BIGENDIAN
396 08521e28 Paolo Bonzini
        access(opaque, addr + i, value, access_size,
397 08521e28 Paolo Bonzini
               (size - access_size - i) * 8, access_mask);
398 08521e28 Paolo Bonzini
#else
399 164a4dcd Avi Kivity
        access(opaque, addr + i, value, access_size, i * 8, access_mask);
400 08521e28 Paolo Bonzini
#endif
401 164a4dcd Avi Kivity
    }
402 164a4dcd Avi Kivity
}
403 164a4dcd Avi Kivity
404 627a0e90 Avi Kivity
static const MemoryRegionPortio *find_portio(MemoryRegion *mr, uint64_t offset,
405 627a0e90 Avi Kivity
                                             unsigned width, bool write)
406 627a0e90 Avi Kivity
{
407 627a0e90 Avi Kivity
    const MemoryRegionPortio *mrp;
408 627a0e90 Avi Kivity
409 627a0e90 Avi Kivity
    for (mrp = mr->ops->old_portio; mrp->size; ++mrp) {
410 627a0e90 Avi Kivity
        if (offset >= mrp->offset && offset < mrp->offset + mrp->len
411 627a0e90 Avi Kivity
            && width == mrp->size
412 627a0e90 Avi Kivity
            && (write ? (bool)mrp->write : (bool)mrp->read)) {
413 627a0e90 Avi Kivity
            return mrp;
414 627a0e90 Avi Kivity
        }
415 627a0e90 Avi Kivity
    }
416 627a0e90 Avi Kivity
    return NULL;
417 627a0e90 Avi Kivity
}
418 627a0e90 Avi Kivity
419 658b2224 Avi Kivity
static void memory_region_iorange_read(IORange *iorange,
420 658b2224 Avi Kivity
                                       uint64_t offset,
421 658b2224 Avi Kivity
                                       unsigned width,
422 658b2224 Avi Kivity
                                       uint64_t *data)
423 658b2224 Avi Kivity
{
424 a2d33521 Avi Kivity
    MemoryRegionIORange *mrio
425 a2d33521 Avi Kivity
        = container_of(iorange, MemoryRegionIORange, iorange);
426 a2d33521 Avi Kivity
    MemoryRegion *mr = mrio->mr;
427 658b2224 Avi Kivity
428 a2d33521 Avi Kivity
    offset += mrio->offset;
429 627a0e90 Avi Kivity
    if (mr->ops->old_portio) {
430 a2d33521 Avi Kivity
        const MemoryRegionPortio *mrp = find_portio(mr, offset - mrio->offset,
431 a2d33521 Avi Kivity
                                                    width, false);
432 627a0e90 Avi Kivity
433 627a0e90 Avi Kivity
        *data = ((uint64_t)1 << (width * 8)) - 1;
434 627a0e90 Avi Kivity
        if (mrp) {
435 2b50aa1f Avi Kivity
            *data = mrp->read(mr->opaque, offset);
436 03808f58 Jan Kiszka
        } else if (width == 2) {
437 a2d33521 Avi Kivity
            mrp = find_portio(mr, offset - mrio->offset, 1, false);
438 03808f58 Jan Kiszka
            assert(mrp);
439 2b50aa1f Avi Kivity
            *data = mrp->read(mr->opaque, offset) |
440 2b50aa1f Avi Kivity
                    (mrp->read(mr->opaque, offset + 1) << 8);
441 627a0e90 Avi Kivity
        }
442 627a0e90 Avi Kivity
        return;
443 627a0e90 Avi Kivity
    }
444 3a130f4e Avi Kivity
    *data = 0;
445 2b50aa1f Avi Kivity
    access_with_adjusted_size(offset, data, width,
446 3a130f4e Avi Kivity
                              mr->ops->impl.min_access_size,
447 3a130f4e Avi Kivity
                              mr->ops->impl.max_access_size,
448 3a130f4e Avi Kivity
                              memory_region_read_accessor, mr);
449 658b2224 Avi Kivity
}
450 658b2224 Avi Kivity
451 658b2224 Avi Kivity
static void memory_region_iorange_write(IORange *iorange,
452 658b2224 Avi Kivity
                                        uint64_t offset,
453 658b2224 Avi Kivity
                                        unsigned width,
454 658b2224 Avi Kivity
                                        uint64_t data)
455 658b2224 Avi Kivity
{
456 a2d33521 Avi Kivity
    MemoryRegionIORange *mrio
457 a2d33521 Avi Kivity
        = container_of(iorange, MemoryRegionIORange, iorange);
458 a2d33521 Avi Kivity
    MemoryRegion *mr = mrio->mr;
459 658b2224 Avi Kivity
460 a2d33521 Avi Kivity
    offset += mrio->offset;
461 627a0e90 Avi Kivity
    if (mr->ops->old_portio) {
462 a2d33521 Avi Kivity
        const MemoryRegionPortio *mrp = find_portio(mr, offset - mrio->offset,
463 a2d33521 Avi Kivity
                                                    width, true);
464 627a0e90 Avi Kivity
465 627a0e90 Avi Kivity
        if (mrp) {
466 2b50aa1f Avi Kivity
            mrp->write(mr->opaque, offset, data);
467 03808f58 Jan Kiszka
        } else if (width == 2) {
468 7e2a62d8 Jan Kiszka
            mrp = find_portio(mr, offset - mrio->offset, 1, true);
469 03808f58 Jan Kiszka
            assert(mrp);
470 2b50aa1f Avi Kivity
            mrp->write(mr->opaque, offset, data & 0xff);
471 2b50aa1f Avi Kivity
            mrp->write(mr->opaque, offset + 1, data >> 8);
472 627a0e90 Avi Kivity
        }
473 627a0e90 Avi Kivity
        return;
474 627a0e90 Avi Kivity
    }
475 2b50aa1f Avi Kivity
    access_with_adjusted_size(offset, &data, width,
476 3a130f4e Avi Kivity
                              mr->ops->impl.min_access_size,
477 3a130f4e Avi Kivity
                              mr->ops->impl.max_access_size,
478 3a130f4e Avi Kivity
                              memory_region_write_accessor, mr);
479 658b2224 Avi Kivity
}
480 658b2224 Avi Kivity
481 a2d33521 Avi Kivity
static void memory_region_iorange_destructor(IORange *iorange)
482 a2d33521 Avi Kivity
{
483 a2d33521 Avi Kivity
    g_free(container_of(iorange, MemoryRegionIORange, iorange));
484 a2d33521 Avi Kivity
}
485 a2d33521 Avi Kivity
486 93632747 Avi Kivity
const IORangeOps memory_region_iorange_ops = {
487 658b2224 Avi Kivity
    .read = memory_region_iorange_read,
488 658b2224 Avi Kivity
    .write = memory_region_iorange_write,
489 a2d33521 Avi Kivity
    .destructor = memory_region_iorange_destructor,
490 658b2224 Avi Kivity
};
491 658b2224 Avi Kivity
492 e2177955 Avi Kivity
static AddressSpace *memory_region_to_address_space(MemoryRegion *mr)
493 e2177955 Avi Kivity
{
494 0d673e36 Avi Kivity
    AddressSpace *as;
495 0d673e36 Avi Kivity
496 e2177955 Avi Kivity
    while (mr->parent) {
497 e2177955 Avi Kivity
        mr = mr->parent;
498 e2177955 Avi Kivity
    }
499 0d673e36 Avi Kivity
    QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) {
500 0d673e36 Avi Kivity
        if (mr == as->root) {
501 0d673e36 Avi Kivity
            return as;
502 0d673e36 Avi Kivity
        }
503 e2177955 Avi Kivity
    }
504 e2177955 Avi Kivity
    abort();
505 e2177955 Avi Kivity
}
506 e2177955 Avi Kivity
507 093bc2cd Avi Kivity
/* Render a memory region into the global view.  Ranges in @view obscure
508 093bc2cd Avi Kivity
 * ranges in @mr.
509 093bc2cd Avi Kivity
 */
510 093bc2cd Avi Kivity
static void render_memory_region(FlatView *view,
511 093bc2cd Avi Kivity
                                 MemoryRegion *mr,
512 08dafab4 Avi Kivity
                                 Int128 base,
513 fb1cd6f9 Avi Kivity
                                 AddrRange clip,
514 fb1cd6f9 Avi Kivity
                                 bool readonly)
515 093bc2cd Avi Kivity
{
516 093bc2cd Avi Kivity
    MemoryRegion *subregion;
517 093bc2cd Avi Kivity
    unsigned i;
518 a8170e5e Avi Kivity
    hwaddr offset_in_region;
519 08dafab4 Avi Kivity
    Int128 remain;
520 08dafab4 Avi Kivity
    Int128 now;
521 093bc2cd Avi Kivity
    FlatRange fr;
522 093bc2cd Avi Kivity
    AddrRange tmp;
523 093bc2cd Avi Kivity
524 6bba19ba Avi Kivity
    if (!mr->enabled) {
525 6bba19ba Avi Kivity
        return;
526 6bba19ba Avi Kivity
    }
527 6bba19ba Avi Kivity
528 08dafab4 Avi Kivity
    int128_addto(&base, int128_make64(mr->addr));
529 fb1cd6f9 Avi Kivity
    readonly |= mr->readonly;
530 093bc2cd Avi Kivity
531 093bc2cd Avi Kivity
    tmp = addrrange_make(base, mr->size);
532 093bc2cd Avi Kivity
533 093bc2cd Avi Kivity
    if (!addrrange_intersects(tmp, clip)) {
534 093bc2cd Avi Kivity
        return;
535 093bc2cd Avi Kivity
    }
536 093bc2cd Avi Kivity
537 093bc2cd Avi Kivity
    clip = addrrange_intersection(tmp, clip);
538 093bc2cd Avi Kivity
539 093bc2cd Avi Kivity
    if (mr->alias) {
540 08dafab4 Avi Kivity
        int128_subfrom(&base, int128_make64(mr->alias->addr));
541 08dafab4 Avi Kivity
        int128_subfrom(&base, int128_make64(mr->alias_offset));
542 fb1cd6f9 Avi Kivity
        render_memory_region(view, mr->alias, base, clip, readonly);
543 093bc2cd Avi Kivity
        return;
544 093bc2cd Avi Kivity
    }
545 093bc2cd Avi Kivity
546 093bc2cd Avi Kivity
    /* Render subregions in priority order. */
547 093bc2cd Avi Kivity
    QTAILQ_FOREACH(subregion, &mr->subregions, subregions_link) {
548 fb1cd6f9 Avi Kivity
        render_memory_region(view, subregion, base, clip, readonly);
549 093bc2cd Avi Kivity
    }
550 093bc2cd Avi Kivity
551 14a3c10a Avi Kivity
    if (!mr->terminates) {
552 093bc2cd Avi Kivity
        return;
553 093bc2cd Avi Kivity
    }
554 093bc2cd Avi Kivity
555 08dafab4 Avi Kivity
    offset_in_region = int128_get64(int128_sub(clip.start, base));
556 093bc2cd Avi Kivity
    base = clip.start;
557 093bc2cd Avi Kivity
    remain = clip.size;
558 093bc2cd Avi Kivity
559 093bc2cd Avi Kivity
    /* Render the region itself into any gaps left by the current view. */
560 08dafab4 Avi Kivity
    for (i = 0; i < view->nr && int128_nz(remain); ++i) {
561 08dafab4 Avi Kivity
        if (int128_ge(base, addrrange_end(view->ranges[i].addr))) {
562 093bc2cd Avi Kivity
            continue;
563 093bc2cd Avi Kivity
        }
564 08dafab4 Avi Kivity
        if (int128_lt(base, view->ranges[i].addr.start)) {
565 08dafab4 Avi Kivity
            now = int128_min(remain,
566 08dafab4 Avi Kivity
                             int128_sub(view->ranges[i].addr.start, base));
567 093bc2cd Avi Kivity
            fr.mr = mr;
568 093bc2cd Avi Kivity
            fr.offset_in_region = offset_in_region;
569 093bc2cd Avi Kivity
            fr.addr = addrrange_make(base, now);
570 5a583347 Avi Kivity
            fr.dirty_log_mask = mr->dirty_log_mask;
571 5f9a5ea1 Jan Kiszka
            fr.romd_mode = mr->romd_mode;
572 fb1cd6f9 Avi Kivity
            fr.readonly = readonly;
573 093bc2cd Avi Kivity
            flatview_insert(view, i, &fr);
574 093bc2cd Avi Kivity
            ++i;
575 08dafab4 Avi Kivity
            int128_addto(&base, now);
576 08dafab4 Avi Kivity
            offset_in_region += int128_get64(now);
577 08dafab4 Avi Kivity
            int128_subfrom(&remain, now);
578 093bc2cd Avi Kivity
        }
579 d26a8cae Avi Kivity
        now = int128_sub(int128_min(int128_add(base, remain),
580 d26a8cae Avi Kivity
                                    addrrange_end(view->ranges[i].addr)),
581 d26a8cae Avi Kivity
                         base);
582 d26a8cae Avi Kivity
        int128_addto(&base, now);
583 d26a8cae Avi Kivity
        offset_in_region += int128_get64(now);
584 d26a8cae Avi Kivity
        int128_subfrom(&remain, now);
585 093bc2cd Avi Kivity
    }
586 08dafab4 Avi Kivity
    if (int128_nz(remain)) {
587 093bc2cd Avi Kivity
        fr.mr = mr;
588 093bc2cd Avi Kivity
        fr.offset_in_region = offset_in_region;
589 093bc2cd Avi Kivity
        fr.addr = addrrange_make(base, remain);
590 5a583347 Avi Kivity
        fr.dirty_log_mask = mr->dirty_log_mask;
591 5f9a5ea1 Jan Kiszka
        fr.romd_mode = mr->romd_mode;
592 fb1cd6f9 Avi Kivity
        fr.readonly = readonly;
593 093bc2cd Avi Kivity
        flatview_insert(view, i, &fr);
594 093bc2cd Avi Kivity
    }
595 093bc2cd Avi Kivity
}
596 093bc2cd Avi Kivity
597 093bc2cd Avi Kivity
/* Render a memory topology into a list of disjoint absolute ranges. */
598 093bc2cd Avi Kivity
static FlatView generate_memory_topology(MemoryRegion *mr)
599 093bc2cd Avi Kivity
{
600 093bc2cd Avi Kivity
    FlatView view;
601 093bc2cd Avi Kivity
602 093bc2cd Avi Kivity
    flatview_init(&view);
603 093bc2cd Avi Kivity
604 83f3c251 Avi Kivity
    if (mr) {
605 83f3c251 Avi Kivity
        render_memory_region(&view, mr, int128_zero(),
606 83f3c251 Avi Kivity
                             addrrange_make(int128_zero(), int128_2_64()), false);
607 83f3c251 Avi Kivity
    }
608 3d8e6bf9 Avi Kivity
    flatview_simplify(&view);
609 093bc2cd Avi Kivity
610 093bc2cd Avi Kivity
    return view;
611 093bc2cd Avi Kivity
}
612 093bc2cd Avi Kivity
613 3e9d69e7 Avi Kivity
static void address_space_add_del_ioeventfds(AddressSpace *as,
614 3e9d69e7 Avi Kivity
                                             MemoryRegionIoeventfd *fds_new,
615 3e9d69e7 Avi Kivity
                                             unsigned fds_new_nb,
616 3e9d69e7 Avi Kivity
                                             MemoryRegionIoeventfd *fds_old,
617 3e9d69e7 Avi Kivity
                                             unsigned fds_old_nb)
618 3e9d69e7 Avi Kivity
{
619 3e9d69e7 Avi Kivity
    unsigned iold, inew;
620 80a1ea37 Avi Kivity
    MemoryRegionIoeventfd *fd;
621 80a1ea37 Avi Kivity
    MemoryRegionSection section;
622 3e9d69e7 Avi Kivity
623 3e9d69e7 Avi Kivity
    /* Generate a symmetric difference of the old and new fd sets, adding
624 3e9d69e7 Avi Kivity
     * and deleting as necessary.
625 3e9d69e7 Avi Kivity
     */
626 3e9d69e7 Avi Kivity
627 3e9d69e7 Avi Kivity
    iold = inew = 0;
628 3e9d69e7 Avi Kivity
    while (iold < fds_old_nb || inew < fds_new_nb) {
629 3e9d69e7 Avi Kivity
        if (iold < fds_old_nb
630 3e9d69e7 Avi Kivity
            && (inew == fds_new_nb
631 3e9d69e7 Avi Kivity
                || memory_region_ioeventfd_before(fds_old[iold],
632 3e9d69e7 Avi Kivity
                                                  fds_new[inew]))) {
633 80a1ea37 Avi Kivity
            fd = &fds_old[iold];
634 80a1ea37 Avi Kivity
            section = (MemoryRegionSection) {
635 f6790af6 Avi Kivity
                .address_space = as,
636 80a1ea37 Avi Kivity
                .offset_within_address_space = int128_get64(fd->addr.start),
637 80a1ea37 Avi Kivity
                .size = int128_get64(fd->addr.size),
638 80a1ea37 Avi Kivity
            };
639 80a1ea37 Avi Kivity
            MEMORY_LISTENER_CALL(eventfd_del, Forward, &section,
640 753d5e14 Paolo Bonzini
                                 fd->match_data, fd->data, fd->e);
641 3e9d69e7 Avi Kivity
            ++iold;
642 3e9d69e7 Avi Kivity
        } else if (inew < fds_new_nb
643 3e9d69e7 Avi Kivity
                   && (iold == fds_old_nb
644 3e9d69e7 Avi Kivity
                       || memory_region_ioeventfd_before(fds_new[inew],
645 3e9d69e7 Avi Kivity
                                                         fds_old[iold]))) {
646 80a1ea37 Avi Kivity
            fd = &fds_new[inew];
647 80a1ea37 Avi Kivity
            section = (MemoryRegionSection) {
648 f6790af6 Avi Kivity
                .address_space = as,
649 80a1ea37 Avi Kivity
                .offset_within_address_space = int128_get64(fd->addr.start),
650 80a1ea37 Avi Kivity
                .size = int128_get64(fd->addr.size),
651 80a1ea37 Avi Kivity
            };
652 80a1ea37 Avi Kivity
            MEMORY_LISTENER_CALL(eventfd_add, Reverse, &section,
653 753d5e14 Paolo Bonzini
                                 fd->match_data, fd->data, fd->e);
654 3e9d69e7 Avi Kivity
            ++inew;
655 3e9d69e7 Avi Kivity
        } else {
656 3e9d69e7 Avi Kivity
            ++iold;
657 3e9d69e7 Avi Kivity
            ++inew;
658 3e9d69e7 Avi Kivity
        }
659 3e9d69e7 Avi Kivity
    }
660 3e9d69e7 Avi Kivity
}
661 3e9d69e7 Avi Kivity
662 3e9d69e7 Avi Kivity
static void address_space_update_ioeventfds(AddressSpace *as)
663 3e9d69e7 Avi Kivity
{
664 3e9d69e7 Avi Kivity
    FlatRange *fr;
665 3e9d69e7 Avi Kivity
    unsigned ioeventfd_nb = 0;
666 3e9d69e7 Avi Kivity
    MemoryRegionIoeventfd *ioeventfds = NULL;
667 3e9d69e7 Avi Kivity
    AddrRange tmp;
668 3e9d69e7 Avi Kivity
    unsigned i;
669 3e9d69e7 Avi Kivity
670 8786db7c Avi Kivity
    FOR_EACH_FLAT_RANGE(fr, as->current_map) {
671 3e9d69e7 Avi Kivity
        for (i = 0; i < fr->mr->ioeventfd_nb; ++i) {
672 3e9d69e7 Avi Kivity
            tmp = addrrange_shift(fr->mr->ioeventfds[i].addr,
673 08dafab4 Avi Kivity
                                  int128_sub(fr->addr.start,
674 08dafab4 Avi Kivity
                                             int128_make64(fr->offset_in_region)));
675 3e9d69e7 Avi Kivity
            if (addrrange_intersects(fr->addr, tmp)) {
676 3e9d69e7 Avi Kivity
                ++ioeventfd_nb;
677 7267c094 Anthony Liguori
                ioeventfds = g_realloc(ioeventfds,
678 3e9d69e7 Avi Kivity
                                          ioeventfd_nb * sizeof(*ioeventfds));
679 3e9d69e7 Avi Kivity
                ioeventfds[ioeventfd_nb-1] = fr->mr->ioeventfds[i];
680 3e9d69e7 Avi Kivity
                ioeventfds[ioeventfd_nb-1].addr = tmp;
681 3e9d69e7 Avi Kivity
            }
682 3e9d69e7 Avi Kivity
        }
683 3e9d69e7 Avi Kivity
    }
684 3e9d69e7 Avi Kivity
685 3e9d69e7 Avi Kivity
    address_space_add_del_ioeventfds(as, ioeventfds, ioeventfd_nb,
686 3e9d69e7 Avi Kivity
                                     as->ioeventfds, as->ioeventfd_nb);
687 3e9d69e7 Avi Kivity
688 7267c094 Anthony Liguori
    g_free(as->ioeventfds);
689 3e9d69e7 Avi Kivity
    as->ioeventfds = ioeventfds;
690 3e9d69e7 Avi Kivity
    as->ioeventfd_nb = ioeventfd_nb;
691 3e9d69e7 Avi Kivity
}
692 3e9d69e7 Avi Kivity
693 b8af1afb Avi Kivity
static void address_space_update_topology_pass(AddressSpace *as,
694 b8af1afb Avi Kivity
                                               FlatView old_view,
695 b8af1afb Avi Kivity
                                               FlatView new_view,
696 b8af1afb Avi Kivity
                                               bool adding)
697 093bc2cd Avi Kivity
{
698 093bc2cd Avi Kivity
    unsigned iold, inew;
699 093bc2cd Avi Kivity
    FlatRange *frold, *frnew;
700 093bc2cd Avi Kivity
701 093bc2cd Avi Kivity
    /* Generate a symmetric difference of the old and new memory maps.
702 093bc2cd Avi Kivity
     * Kill ranges in the old map, and instantiate ranges in the new map.
703 093bc2cd Avi Kivity
     */
704 093bc2cd Avi Kivity
    iold = inew = 0;
705 093bc2cd Avi Kivity
    while (iold < old_view.nr || inew < new_view.nr) {
706 093bc2cd Avi Kivity
        if (iold < old_view.nr) {
707 093bc2cd Avi Kivity
            frold = &old_view.ranges[iold];
708 093bc2cd Avi Kivity
        } else {
709 093bc2cd Avi Kivity
            frold = NULL;
710 093bc2cd Avi Kivity
        }
711 093bc2cd Avi Kivity
        if (inew < new_view.nr) {
712 093bc2cd Avi Kivity
            frnew = &new_view.ranges[inew];
713 093bc2cd Avi Kivity
        } else {
714 093bc2cd Avi Kivity
            frnew = NULL;
715 093bc2cd Avi Kivity
        }
716 093bc2cd Avi Kivity
717 093bc2cd Avi Kivity
        if (frold
718 093bc2cd Avi Kivity
            && (!frnew
719 08dafab4 Avi Kivity
                || int128_lt(frold->addr.start, frnew->addr.start)
720 08dafab4 Avi Kivity
                || (int128_eq(frold->addr.start, frnew->addr.start)
721 093bc2cd Avi Kivity
                    && !flatrange_equal(frold, frnew)))) {
722 093bc2cd Avi Kivity
            /* In old, but (not in new, or in new but attributes changed). */
723 093bc2cd Avi Kivity
724 b8af1afb Avi Kivity
            if (!adding) {
725 72e22d2f Avi Kivity
                MEMORY_LISTENER_UPDATE_REGION(frold, as, Reverse, region_del);
726 b8af1afb Avi Kivity
            }
727 b8af1afb Avi Kivity
728 093bc2cd Avi Kivity
            ++iold;
729 093bc2cd Avi Kivity
        } else if (frold && frnew && flatrange_equal(frold, frnew)) {
730 093bc2cd Avi Kivity
            /* In both (logging may have changed) */
731 093bc2cd Avi Kivity
732 b8af1afb Avi Kivity
            if (adding) {
733 50c1e149 Avi Kivity
                MEMORY_LISTENER_UPDATE_REGION(frnew, as, Forward, region_nop);
734 b8af1afb Avi Kivity
                if (frold->dirty_log_mask && !frnew->dirty_log_mask) {
735 72e22d2f Avi Kivity
                    MEMORY_LISTENER_UPDATE_REGION(frnew, as, Reverse, log_stop);
736 b8af1afb Avi Kivity
                } else if (frnew->dirty_log_mask && !frold->dirty_log_mask) {
737 72e22d2f Avi Kivity
                    MEMORY_LISTENER_UPDATE_REGION(frnew, as, Forward, log_start);
738 b8af1afb Avi Kivity
                }
739 5a583347 Avi Kivity
            }
740 5a583347 Avi Kivity
741 093bc2cd Avi Kivity
            ++iold;
742 093bc2cd Avi Kivity
            ++inew;
743 093bc2cd Avi Kivity
        } else {
744 093bc2cd Avi Kivity
            /* In new */
745 093bc2cd Avi Kivity
746 b8af1afb Avi Kivity
            if (adding) {
747 72e22d2f Avi Kivity
                MEMORY_LISTENER_UPDATE_REGION(frnew, as, Forward, region_add);
748 b8af1afb Avi Kivity
            }
749 b8af1afb Avi Kivity
750 093bc2cd Avi Kivity
            ++inew;
751 093bc2cd Avi Kivity
        }
752 093bc2cd Avi Kivity
    }
753 b8af1afb Avi Kivity
}
754 b8af1afb Avi Kivity
755 b8af1afb Avi Kivity
756 b8af1afb Avi Kivity
static void address_space_update_topology(AddressSpace *as)
757 b8af1afb Avi Kivity
{
758 8786db7c Avi Kivity
    FlatView old_view = *as->current_map;
759 b8af1afb Avi Kivity
    FlatView new_view = generate_memory_topology(as->root);
760 b8af1afb Avi Kivity
761 b8af1afb Avi Kivity
    address_space_update_topology_pass(as, old_view, new_view, false);
762 b8af1afb Avi Kivity
    address_space_update_topology_pass(as, old_view, new_view, true);
763 b8af1afb Avi Kivity
764 8786db7c Avi Kivity
    *as->current_map = new_view;
765 093bc2cd Avi Kivity
    flatview_destroy(&old_view);
766 3e9d69e7 Avi Kivity
    address_space_update_ioeventfds(as);
767 093bc2cd Avi Kivity
}
768 093bc2cd Avi Kivity
769 4ef4db86 Avi Kivity
void memory_region_transaction_begin(void)
770 4ef4db86 Avi Kivity
{
771 bb880ded Jan Kiszka
    qemu_flush_coalesced_mmio_buffer();
772 4ef4db86 Avi Kivity
    ++memory_region_transaction_depth;
773 4ef4db86 Avi Kivity
}
774 4ef4db86 Avi Kivity
775 4ef4db86 Avi Kivity
void memory_region_transaction_commit(void)
776 4ef4db86 Avi Kivity
{
777 0d673e36 Avi Kivity
    AddressSpace *as;
778 0d673e36 Avi Kivity
779 4ef4db86 Avi Kivity
    assert(memory_region_transaction_depth);
780 4ef4db86 Avi Kivity
    --memory_region_transaction_depth;
781 22bde714 Jan Kiszka
    if (!memory_region_transaction_depth && memory_region_update_pending) {
782 22bde714 Jan Kiszka
        memory_region_update_pending = false;
783 02e2b95f Jan Kiszka
        MEMORY_LISTENER_CALL_GLOBAL(begin, Forward);
784 02e2b95f Jan Kiszka
785 0d673e36 Avi Kivity
        QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) {
786 0d673e36 Avi Kivity
            address_space_update_topology(as);
787 02e2b95f Jan Kiszka
        }
788 02e2b95f Jan Kiszka
789 02e2b95f Jan Kiszka
        MEMORY_LISTENER_CALL_GLOBAL(commit, Forward);
790 e87c099f Avi Kivity
    }
791 4ef4db86 Avi Kivity
}
792 4ef4db86 Avi Kivity
793 545e92e0 Avi Kivity
static void memory_region_destructor_none(MemoryRegion *mr)
794 545e92e0 Avi Kivity
{
795 545e92e0 Avi Kivity
}
796 545e92e0 Avi Kivity
797 545e92e0 Avi Kivity
static void memory_region_destructor_ram(MemoryRegion *mr)
798 545e92e0 Avi Kivity
{
799 545e92e0 Avi Kivity
    qemu_ram_free(mr->ram_addr);
800 545e92e0 Avi Kivity
}
801 545e92e0 Avi Kivity
802 545e92e0 Avi Kivity
static void memory_region_destructor_ram_from_ptr(MemoryRegion *mr)
803 545e92e0 Avi Kivity
{
804 545e92e0 Avi Kivity
    qemu_ram_free_from_ptr(mr->ram_addr);
805 545e92e0 Avi Kivity
}
806 545e92e0 Avi Kivity
807 d0a9b5bc Avi Kivity
static void memory_region_destructor_rom_device(MemoryRegion *mr)
808 d0a9b5bc Avi Kivity
{
809 d0a9b5bc Avi Kivity
    qemu_ram_free(mr->ram_addr & TARGET_PAGE_MASK);
810 d0a9b5bc Avi Kivity
}
811 d0a9b5bc Avi Kivity
812 be675c97 Avi Kivity
static bool memory_region_wrong_endianness(MemoryRegion *mr)
813 be675c97 Avi Kivity
{
814 2c3579ab Andreas Fรคrber
#ifdef TARGET_WORDS_BIGENDIAN
815 be675c97 Avi Kivity
    return mr->ops->endianness == DEVICE_LITTLE_ENDIAN;
816 be675c97 Avi Kivity
#else
817 be675c97 Avi Kivity
    return mr->ops->endianness == DEVICE_BIG_ENDIAN;
818 be675c97 Avi Kivity
#endif
819 be675c97 Avi Kivity
}
820 be675c97 Avi Kivity
821 093bc2cd Avi Kivity
void memory_region_init(MemoryRegion *mr,
822 093bc2cd Avi Kivity
                        const char *name,
823 093bc2cd Avi Kivity
                        uint64_t size)
824 093bc2cd Avi Kivity
{
825 2cdfcf27 Paolo Bonzini
    mr->ops = &unassigned_mem_ops;
826 2cdfcf27 Paolo Bonzini
    mr->opaque = NULL;
827 093bc2cd Avi Kivity
    mr->parent = NULL;
828 08dafab4 Avi Kivity
    mr->size = int128_make64(size);
829 08dafab4 Avi Kivity
    if (size == UINT64_MAX) {
830 08dafab4 Avi Kivity
        mr->size = int128_2_64();
831 08dafab4 Avi Kivity
    }
832 093bc2cd Avi Kivity
    mr->addr = 0;
833 b3b00c78 Avi Kivity
    mr->subpage = false;
834 6bba19ba Avi Kivity
    mr->enabled = true;
835 14a3c10a Avi Kivity
    mr->terminates = false;
836 8ea9252a Avi Kivity
    mr->ram = false;
837 5f9a5ea1 Jan Kiszka
    mr->romd_mode = true;
838 fb1cd6f9 Avi Kivity
    mr->readonly = false;
839 75c578dc Avi Kivity
    mr->rom_device = false;
840 545e92e0 Avi Kivity
    mr->destructor = memory_region_destructor_none;
841 093bc2cd Avi Kivity
    mr->priority = 0;
842 093bc2cd Avi Kivity
    mr->may_overlap = false;
843 093bc2cd Avi Kivity
    mr->alias = NULL;
844 093bc2cd Avi Kivity
    QTAILQ_INIT(&mr->subregions);
845 093bc2cd Avi Kivity
    memset(&mr->subregions_link, 0, sizeof mr->subregions_link);
846 093bc2cd Avi Kivity
    QTAILQ_INIT(&mr->coalesced);
847 7267c094 Anthony Liguori
    mr->name = g_strdup(name);
848 5a583347 Avi Kivity
    mr->dirty_log_mask = 0;
849 3e9d69e7 Avi Kivity
    mr->ioeventfd_nb = 0;
850 3e9d69e7 Avi Kivity
    mr->ioeventfds = NULL;
851 d410515e Jan Kiszka
    mr->flush_coalesced_mmio = false;
852 093bc2cd Avi Kivity
}
853 093bc2cd Avi Kivity
854 b018ddf6 Paolo Bonzini
static uint64_t unassigned_mem_read(void *opaque, hwaddr addr,
855 b018ddf6 Paolo Bonzini
                                    unsigned size)
856 b018ddf6 Paolo Bonzini
{
857 b018ddf6 Paolo Bonzini
#ifdef DEBUG_UNASSIGNED
858 b018ddf6 Paolo Bonzini
    printf("Unassigned mem read " TARGET_FMT_plx "\n", addr);
859 b018ddf6 Paolo Bonzini
#endif
860 b018ddf6 Paolo Bonzini
#if defined(TARGET_ALPHA) || defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
861 b018ddf6 Paolo Bonzini
    cpu_unassigned_access(cpu_single_env, addr, 0, 0, 0, size);
862 b018ddf6 Paolo Bonzini
#endif
863 b018ddf6 Paolo Bonzini
    return 0;
864 b018ddf6 Paolo Bonzini
}
865 b018ddf6 Paolo Bonzini
866 b018ddf6 Paolo Bonzini
static void unassigned_mem_write(void *opaque, hwaddr addr,
867 b018ddf6 Paolo Bonzini
                                 uint64_t val, unsigned size)
868 b018ddf6 Paolo Bonzini
{
869 b018ddf6 Paolo Bonzini
#ifdef DEBUG_UNASSIGNED
870 b018ddf6 Paolo Bonzini
    printf("Unassigned mem write " TARGET_FMT_plx " = 0x%"PRIx64"\n", addr, val);
871 b018ddf6 Paolo Bonzini
#endif
872 b018ddf6 Paolo Bonzini
#if defined(TARGET_ALPHA) || defined(TARGET_SPARC) || defined(TARGET_MICROBLAZE)
873 b018ddf6 Paolo Bonzini
    cpu_unassigned_access(cpu_single_env, addr, 1, 0, 0, size);
874 b018ddf6 Paolo Bonzini
#endif
875 b018ddf6 Paolo Bonzini
}
876 b018ddf6 Paolo Bonzini
877 d197063f Paolo Bonzini
static bool unassigned_mem_accepts(void *opaque, hwaddr addr,
878 d197063f Paolo Bonzini
                                   unsigned size, bool is_write)
879 d197063f Paolo Bonzini
{
880 d197063f Paolo Bonzini
    return false;
881 d197063f Paolo Bonzini
}
882 d197063f Paolo Bonzini
883 d197063f Paolo Bonzini
const MemoryRegionOps unassigned_mem_ops = {
884 d197063f Paolo Bonzini
    .valid.accepts = unassigned_mem_accepts,
885 d197063f Paolo Bonzini
    .endianness = DEVICE_NATIVE_ENDIAN,
886 d197063f Paolo Bonzini
};
887 d197063f Paolo Bonzini
888 d2702032 Paolo Bonzini
bool memory_region_access_valid(MemoryRegion *mr,
889 d2702032 Paolo Bonzini
                                hwaddr addr,
890 d2702032 Paolo Bonzini
                                unsigned size,
891 d2702032 Paolo Bonzini
                                bool is_write)
892 093bc2cd Avi Kivity
{
893 a014ed07 Paolo Bonzini
    int access_size_min, access_size_max;
894 a014ed07 Paolo Bonzini
    int access_size, i;
895 897fa7cf Avi Kivity
896 093bc2cd Avi Kivity
    if (!mr->ops->valid.unaligned && (addr & (size - 1))) {
897 093bc2cd Avi Kivity
        return false;
898 093bc2cd Avi Kivity
    }
899 093bc2cd Avi Kivity
900 a014ed07 Paolo Bonzini
    if (!mr->ops->valid.accepts) {
901 093bc2cd Avi Kivity
        return true;
902 093bc2cd Avi Kivity
    }
903 093bc2cd Avi Kivity
904 a014ed07 Paolo Bonzini
    access_size_min = mr->ops->valid.min_access_size;
905 a014ed07 Paolo Bonzini
    if (!mr->ops->valid.min_access_size) {
906 a014ed07 Paolo Bonzini
        access_size_min = 1;
907 a014ed07 Paolo Bonzini
    }
908 a014ed07 Paolo Bonzini
909 a014ed07 Paolo Bonzini
    access_size_max = mr->ops->valid.max_access_size;
910 a014ed07 Paolo Bonzini
    if (!mr->ops->valid.max_access_size) {
911 a014ed07 Paolo Bonzini
        access_size_max = 4;
912 a014ed07 Paolo Bonzini
    }
913 a014ed07 Paolo Bonzini
914 a014ed07 Paolo Bonzini
    access_size = MAX(MIN(size, access_size_max), access_size_min);
915 a014ed07 Paolo Bonzini
    for (i = 0; i < size; i += access_size) {
916 a014ed07 Paolo Bonzini
        if (!mr->ops->valid.accepts(mr->opaque, addr + i, access_size,
917 a014ed07 Paolo Bonzini
                                    is_write)) {
918 a014ed07 Paolo Bonzini
            return false;
919 a014ed07 Paolo Bonzini
        }
920 093bc2cd Avi Kivity
    }
921 a014ed07 Paolo Bonzini
922 093bc2cd Avi Kivity
    return true;
923 093bc2cd Avi Kivity
}
924 093bc2cd Avi Kivity
925 a621f38d Avi Kivity
static uint64_t memory_region_dispatch_read1(MemoryRegion *mr,
926 a8170e5e Avi Kivity
                                             hwaddr addr,
927 a621f38d Avi Kivity
                                             unsigned size)
928 093bc2cd Avi Kivity
{
929 164a4dcd Avi Kivity
    uint64_t data = 0;
930 093bc2cd Avi Kivity
931 897fa7cf Avi Kivity
    if (!memory_region_access_valid(mr, addr, size, false)) {
932 b018ddf6 Paolo Bonzini
        return unassigned_mem_read(mr, addr, size);
933 093bc2cd Avi Kivity
    }
934 093bc2cd Avi Kivity
935 ce5d2f33 Paolo Bonzini
    if (mr->ops->read) {
936 ce5d2f33 Paolo Bonzini
        access_with_adjusted_size(addr, &data, size,
937 ce5d2f33 Paolo Bonzini
                                  mr->ops->impl.min_access_size,
938 ce5d2f33 Paolo Bonzini
                                  mr->ops->impl.max_access_size,
939 ce5d2f33 Paolo Bonzini
                                  memory_region_read_accessor, mr);
940 ce5d2f33 Paolo Bonzini
    } else {
941 ce5d2f33 Paolo Bonzini
        access_with_adjusted_size(addr, &data, size, 1, 4,
942 ce5d2f33 Paolo Bonzini
                                  memory_region_oldmmio_read_accessor, mr);
943 74901c3b Avi Kivity
    }
944 74901c3b Avi Kivity
945 093bc2cd Avi Kivity
    return data;
946 093bc2cd Avi Kivity
}
947 093bc2cd Avi Kivity
948 a621f38d Avi Kivity
static void adjust_endianness(MemoryRegion *mr, uint64_t *data, unsigned size)
949 093bc2cd Avi Kivity
{
950 a621f38d Avi Kivity
    if (memory_region_wrong_endianness(mr)) {
951 a621f38d Avi Kivity
        switch (size) {
952 a621f38d Avi Kivity
        case 1:
953 a621f38d Avi Kivity
            break;
954 a621f38d Avi Kivity
        case 2:
955 a621f38d Avi Kivity
            *data = bswap16(*data);
956 a621f38d Avi Kivity
            break;
957 a621f38d Avi Kivity
        case 4:
958 a621f38d Avi Kivity
            *data = bswap32(*data);
959 1470a0cd Andreas Fรคrber
            break;
960 a621f38d Avi Kivity
        default:
961 a621f38d Avi Kivity
            abort();
962 a621f38d Avi Kivity
        }
963 a621f38d Avi Kivity
    }
964 a621f38d Avi Kivity
}
965 a621f38d Avi Kivity
966 a621f38d Avi Kivity
static uint64_t memory_region_dispatch_read(MemoryRegion *mr,
967 a8170e5e Avi Kivity
                                            hwaddr addr,
968 a621f38d Avi Kivity
                                            unsigned size)
969 a621f38d Avi Kivity
{
970 a621f38d Avi Kivity
    uint64_t ret;
971 a621f38d Avi Kivity
972 a621f38d Avi Kivity
    ret = memory_region_dispatch_read1(mr, addr, size);
973 a621f38d Avi Kivity
    adjust_endianness(mr, &ret, size);
974 a621f38d Avi Kivity
    return ret;
975 a621f38d Avi Kivity
}
976 093bc2cd Avi Kivity
977 a621f38d Avi Kivity
static void memory_region_dispatch_write(MemoryRegion *mr,
978 a8170e5e Avi Kivity
                                         hwaddr addr,
979 a621f38d Avi Kivity
                                         uint64_t data,
980 a621f38d Avi Kivity
                                         unsigned size)
981 a621f38d Avi Kivity
{
982 897fa7cf Avi Kivity
    if (!memory_region_access_valid(mr, addr, size, true)) {
983 b018ddf6 Paolo Bonzini
        unassigned_mem_write(mr, addr, data, size);
984 b018ddf6 Paolo Bonzini
        return;
985 093bc2cd Avi Kivity
    }
986 093bc2cd Avi Kivity
987 a621f38d Avi Kivity
    adjust_endianness(mr, &data, size);
988 a621f38d Avi Kivity
989 ce5d2f33 Paolo Bonzini
    if (mr->ops->write) {
990 ce5d2f33 Paolo Bonzini
        access_with_adjusted_size(addr, &data, size,
991 ce5d2f33 Paolo Bonzini
                                  mr->ops->impl.min_access_size,
992 ce5d2f33 Paolo Bonzini
                                  mr->ops->impl.max_access_size,
993 ce5d2f33 Paolo Bonzini
                                  memory_region_write_accessor, mr);
994 ce5d2f33 Paolo Bonzini
    } else {
995 ce5d2f33 Paolo Bonzini
        access_with_adjusted_size(addr, &data, size, 1, 4,
996 ce5d2f33 Paolo Bonzini
                                  memory_region_oldmmio_write_accessor, mr);
997 74901c3b Avi Kivity
    }
998 093bc2cd Avi Kivity
}
999 093bc2cd Avi Kivity
1000 093bc2cd Avi Kivity
void memory_region_init_io(MemoryRegion *mr,
1001 093bc2cd Avi Kivity
                           const MemoryRegionOps *ops,
1002 093bc2cd Avi Kivity
                           void *opaque,
1003 093bc2cd Avi Kivity
                           const char *name,
1004 093bc2cd Avi Kivity
                           uint64_t size)
1005 093bc2cd Avi Kivity
{
1006 093bc2cd Avi Kivity
    memory_region_init(mr, name, size);
1007 093bc2cd Avi Kivity
    mr->ops = ops;
1008 093bc2cd Avi Kivity
    mr->opaque = opaque;
1009 14a3c10a Avi Kivity
    mr->terminates = true;
1010 97161e17 Avi Kivity
    mr->ram_addr = ~(ram_addr_t)0;
1011 093bc2cd Avi Kivity
}
1012 093bc2cd Avi Kivity
1013 093bc2cd Avi Kivity
void memory_region_init_ram(MemoryRegion *mr,
1014 093bc2cd Avi Kivity
                            const char *name,
1015 093bc2cd Avi Kivity
                            uint64_t size)
1016 093bc2cd Avi Kivity
{
1017 093bc2cd Avi Kivity
    memory_region_init(mr, name, size);
1018 8ea9252a Avi Kivity
    mr->ram = true;
1019 14a3c10a Avi Kivity
    mr->terminates = true;
1020 545e92e0 Avi Kivity
    mr->destructor = memory_region_destructor_ram;
1021 c5705a77 Avi Kivity
    mr->ram_addr = qemu_ram_alloc(size, mr);
1022 093bc2cd Avi Kivity
}
1023 093bc2cd Avi Kivity
1024 093bc2cd Avi Kivity
void memory_region_init_ram_ptr(MemoryRegion *mr,
1025 093bc2cd Avi Kivity
                                const char *name,
1026 093bc2cd Avi Kivity
                                uint64_t size,
1027 093bc2cd Avi Kivity
                                void *ptr)
1028 093bc2cd Avi Kivity
{
1029 093bc2cd Avi Kivity
    memory_region_init(mr, name, size);
1030 8ea9252a Avi Kivity
    mr->ram = true;
1031 14a3c10a Avi Kivity
    mr->terminates = true;
1032 545e92e0 Avi Kivity
    mr->destructor = memory_region_destructor_ram_from_ptr;
1033 c5705a77 Avi Kivity
    mr->ram_addr = qemu_ram_alloc_from_ptr(size, ptr, mr);
1034 093bc2cd Avi Kivity
}
1035 093bc2cd Avi Kivity
1036 093bc2cd Avi Kivity
void memory_region_init_alias(MemoryRegion *mr,
1037 093bc2cd Avi Kivity
                              const char *name,
1038 093bc2cd Avi Kivity
                              MemoryRegion *orig,
1039 a8170e5e Avi Kivity
                              hwaddr offset,
1040 093bc2cd Avi Kivity
                              uint64_t size)
1041 093bc2cd Avi Kivity
{
1042 093bc2cd Avi Kivity
    memory_region_init(mr, name, size);
1043 093bc2cd Avi Kivity
    mr->alias = orig;
1044 093bc2cd Avi Kivity
    mr->alias_offset = offset;
1045 093bc2cd Avi Kivity
}
1046 093bc2cd Avi Kivity
1047 d0a9b5bc Avi Kivity
void memory_region_init_rom_device(MemoryRegion *mr,
1048 d0a9b5bc Avi Kivity
                                   const MemoryRegionOps *ops,
1049 75f5941c Avi Kivity
                                   void *opaque,
1050 d0a9b5bc Avi Kivity
                                   const char *name,
1051 d0a9b5bc Avi Kivity
                                   uint64_t size)
1052 d0a9b5bc Avi Kivity
{
1053 d0a9b5bc Avi Kivity
    memory_region_init(mr, name, size);
1054 7bc2b9cd Avi Kivity
    mr->ops = ops;
1055 75f5941c Avi Kivity
    mr->opaque = opaque;
1056 d0a9b5bc Avi Kivity
    mr->terminates = true;
1057 75c578dc Avi Kivity
    mr->rom_device = true;
1058 d0a9b5bc Avi Kivity
    mr->destructor = memory_region_destructor_rom_device;
1059 c5705a77 Avi Kivity
    mr->ram_addr = qemu_ram_alloc(size, mr);
1060 d0a9b5bc Avi Kivity
}
1061 d0a9b5bc Avi Kivity
1062 1660e72d Jan Kiszka
void memory_region_init_reservation(MemoryRegion *mr,
1063 1660e72d Jan Kiszka
                                    const char *name,
1064 1660e72d Jan Kiszka
                                    uint64_t size)
1065 1660e72d Jan Kiszka
{
1066 d197063f Paolo Bonzini
    memory_region_init_io(mr, &unassigned_mem_ops, mr, name, size);
1067 1660e72d Jan Kiszka
}
1068 1660e72d Jan Kiszka
1069 093bc2cd Avi Kivity
void memory_region_destroy(MemoryRegion *mr)
1070 093bc2cd Avi Kivity
{
1071 093bc2cd Avi Kivity
    assert(QTAILQ_EMPTY(&mr->subregions));
1072 2be0e25f Avi Kivity
    assert(memory_region_transaction_depth == 0);
1073 545e92e0 Avi Kivity
    mr->destructor(mr);
1074 093bc2cd Avi Kivity
    memory_region_clear_coalescing(mr);
1075 7267c094 Anthony Liguori
    g_free((char *)mr->name);
1076 7267c094 Anthony Liguori
    g_free(mr->ioeventfds);
1077 093bc2cd Avi Kivity
}
1078 093bc2cd Avi Kivity
1079 093bc2cd Avi Kivity
uint64_t memory_region_size(MemoryRegion *mr)
1080 093bc2cd Avi Kivity
{
1081 08dafab4 Avi Kivity
    if (int128_eq(mr->size, int128_2_64())) {
1082 08dafab4 Avi Kivity
        return UINT64_MAX;
1083 08dafab4 Avi Kivity
    }
1084 08dafab4 Avi Kivity
    return int128_get64(mr->size);
1085 093bc2cd Avi Kivity
}
1086 093bc2cd Avi Kivity
1087 8991c79b Avi Kivity
const char *memory_region_name(MemoryRegion *mr)
1088 8991c79b Avi Kivity
{
1089 8991c79b Avi Kivity
    return mr->name;
1090 8991c79b Avi Kivity
}
1091 8991c79b Avi Kivity
1092 8ea9252a Avi Kivity
bool memory_region_is_ram(MemoryRegion *mr)
1093 8ea9252a Avi Kivity
{
1094 8ea9252a Avi Kivity
    return mr->ram;
1095 8ea9252a Avi Kivity
}
1096 8ea9252a Avi Kivity
1097 55043ba3 Avi Kivity
bool memory_region_is_logging(MemoryRegion *mr)
1098 55043ba3 Avi Kivity
{
1099 55043ba3 Avi Kivity
    return mr->dirty_log_mask;
1100 55043ba3 Avi Kivity
}
1101 55043ba3 Avi Kivity
1102 ce7923da Avi Kivity
bool memory_region_is_rom(MemoryRegion *mr)
1103 ce7923da Avi Kivity
{
1104 ce7923da Avi Kivity
    return mr->ram && mr->readonly;
1105 ce7923da Avi Kivity
}
1106 ce7923da Avi Kivity
1107 093bc2cd Avi Kivity
void memory_region_set_log(MemoryRegion *mr, bool log, unsigned client)
1108 093bc2cd Avi Kivity
{
1109 5a583347 Avi Kivity
    uint8_t mask = 1 << client;
1110 5a583347 Avi Kivity
1111 59023ef4 Jan Kiszka
    memory_region_transaction_begin();
1112 5a583347 Avi Kivity
    mr->dirty_log_mask = (mr->dirty_log_mask & ~mask) | (log * mask);
1113 22bde714 Jan Kiszka
    memory_region_update_pending |= mr->enabled;
1114 59023ef4 Jan Kiszka
    memory_region_transaction_commit();
1115 093bc2cd Avi Kivity
}
1116 093bc2cd Avi Kivity
1117 a8170e5e Avi Kivity
bool memory_region_get_dirty(MemoryRegion *mr, hwaddr addr,
1118 a8170e5e Avi Kivity
                             hwaddr size, unsigned client)
1119 093bc2cd Avi Kivity
{
1120 14a3c10a Avi Kivity
    assert(mr->terminates);
1121 cd7a45c9 Blue Swirl
    return cpu_physical_memory_get_dirty(mr->ram_addr + addr, size,
1122 cd7a45c9 Blue Swirl
                                         1 << client);
1123 093bc2cd Avi Kivity
}
1124 093bc2cd Avi Kivity
1125 a8170e5e Avi Kivity
void memory_region_set_dirty(MemoryRegion *mr, hwaddr addr,
1126 a8170e5e Avi Kivity
                             hwaddr size)
1127 093bc2cd Avi Kivity
{
1128 14a3c10a Avi Kivity
    assert(mr->terminates);
1129 fd4aa979 Blue Swirl
    return cpu_physical_memory_set_dirty_range(mr->ram_addr + addr, size, -1);
1130 093bc2cd Avi Kivity
}
1131 093bc2cd Avi Kivity
1132 6c279db8 Juan Quintela
bool memory_region_test_and_clear_dirty(MemoryRegion *mr, hwaddr addr,
1133 6c279db8 Juan Quintela
                                        hwaddr size, unsigned client)
1134 6c279db8 Juan Quintela
{
1135 6c279db8 Juan Quintela
    bool ret;
1136 6c279db8 Juan Quintela
    assert(mr->terminates);
1137 6c279db8 Juan Quintela
    ret = cpu_physical_memory_get_dirty(mr->ram_addr + addr, size,
1138 6c279db8 Juan Quintela
                                        1 << client);
1139 6c279db8 Juan Quintela
    if (ret) {
1140 6c279db8 Juan Quintela
        cpu_physical_memory_reset_dirty(mr->ram_addr + addr,
1141 6c279db8 Juan Quintela
                                        mr->ram_addr + addr + size,
1142 6c279db8 Juan Quintela
                                        1 << client);
1143 6c279db8 Juan Quintela
    }
1144 6c279db8 Juan Quintela
    return ret;
1145 6c279db8 Juan Quintela
}
1146 6c279db8 Juan Quintela
1147 6c279db8 Juan Quintela
1148 093bc2cd Avi Kivity
void memory_region_sync_dirty_bitmap(MemoryRegion *mr)
1149 093bc2cd Avi Kivity
{
1150 0d673e36 Avi Kivity
    AddressSpace *as;
1151 5a583347 Avi Kivity
    FlatRange *fr;
1152 5a583347 Avi Kivity
1153 0d673e36 Avi Kivity
    QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) {
1154 0d673e36 Avi Kivity
        FOR_EACH_FLAT_RANGE(fr, as->current_map) {
1155 0d673e36 Avi Kivity
            if (fr->mr == mr) {
1156 0d673e36 Avi Kivity
                MEMORY_LISTENER_UPDATE_REGION(fr, as, Forward, log_sync);
1157 0d673e36 Avi Kivity
            }
1158 5a583347 Avi Kivity
        }
1159 5a583347 Avi Kivity
    }
1160 093bc2cd Avi Kivity
}
1161 093bc2cd Avi Kivity
1162 093bc2cd Avi Kivity
void memory_region_set_readonly(MemoryRegion *mr, bool readonly)
1163 093bc2cd Avi Kivity
{
1164 fb1cd6f9 Avi Kivity
    if (mr->readonly != readonly) {
1165 59023ef4 Jan Kiszka
        memory_region_transaction_begin();
1166 fb1cd6f9 Avi Kivity
        mr->readonly = readonly;
1167 22bde714 Jan Kiszka
        memory_region_update_pending |= mr->enabled;
1168 59023ef4 Jan Kiszka
        memory_region_transaction_commit();
1169 fb1cd6f9 Avi Kivity
    }
1170 093bc2cd Avi Kivity
}
1171 093bc2cd Avi Kivity
1172 5f9a5ea1 Jan Kiszka
void memory_region_rom_device_set_romd(MemoryRegion *mr, bool romd_mode)
1173 d0a9b5bc Avi Kivity
{
1174 5f9a5ea1 Jan Kiszka
    if (mr->romd_mode != romd_mode) {
1175 59023ef4 Jan Kiszka
        memory_region_transaction_begin();
1176 5f9a5ea1 Jan Kiszka
        mr->romd_mode = romd_mode;
1177 22bde714 Jan Kiszka
        memory_region_update_pending |= mr->enabled;
1178 59023ef4 Jan Kiszka
        memory_region_transaction_commit();
1179 d0a9b5bc Avi Kivity
    }
1180 d0a9b5bc Avi Kivity
}
1181 d0a9b5bc Avi Kivity
1182 a8170e5e Avi Kivity
void memory_region_reset_dirty(MemoryRegion *mr, hwaddr addr,
1183 a8170e5e Avi Kivity
                               hwaddr size, unsigned client)
1184 093bc2cd Avi Kivity
{
1185 14a3c10a Avi Kivity
    assert(mr->terminates);
1186 5a583347 Avi Kivity
    cpu_physical_memory_reset_dirty(mr->ram_addr + addr,
1187 5a583347 Avi Kivity
                                    mr->ram_addr + addr + size,
1188 5a583347 Avi Kivity
                                    1 << client);
1189 093bc2cd Avi Kivity
}
1190 093bc2cd Avi Kivity
1191 093bc2cd Avi Kivity
void *memory_region_get_ram_ptr(MemoryRegion *mr)
1192 093bc2cd Avi Kivity
{
1193 093bc2cd Avi Kivity
    if (mr->alias) {
1194 093bc2cd Avi Kivity
        return memory_region_get_ram_ptr(mr->alias) + mr->alias_offset;
1195 093bc2cd Avi Kivity
    }
1196 093bc2cd Avi Kivity
1197 14a3c10a Avi Kivity
    assert(mr->terminates);
1198 093bc2cd Avi Kivity
1199 021d26d1 Jan Kiszka
    return qemu_get_ram_ptr(mr->ram_addr & TARGET_PAGE_MASK);
1200 093bc2cd Avi Kivity
}
1201 093bc2cd Avi Kivity
1202 0d673e36 Avi Kivity
static void memory_region_update_coalesced_range_as(MemoryRegion *mr, AddressSpace *as)
1203 093bc2cd Avi Kivity
{
1204 093bc2cd Avi Kivity
    FlatRange *fr;
1205 093bc2cd Avi Kivity
    CoalescedMemoryRange *cmr;
1206 093bc2cd Avi Kivity
    AddrRange tmp;
1207 95d2994a Avi Kivity
    MemoryRegionSection section;
1208 093bc2cd Avi Kivity
1209 0d673e36 Avi Kivity
    FOR_EACH_FLAT_RANGE(fr, as->current_map) {
1210 093bc2cd Avi Kivity
        if (fr->mr == mr) {
1211 95d2994a Avi Kivity
            section = (MemoryRegionSection) {
1212 f6790af6 Avi Kivity
                .address_space = as,
1213 95d2994a Avi Kivity
                .offset_within_address_space = int128_get64(fr->addr.start),
1214 95d2994a Avi Kivity
                .size = int128_get64(fr->addr.size),
1215 95d2994a Avi Kivity
            };
1216 95d2994a Avi Kivity
1217 95d2994a Avi Kivity
            MEMORY_LISTENER_CALL(coalesced_mmio_del, Reverse, &section,
1218 95d2994a Avi Kivity
                                 int128_get64(fr->addr.start),
1219 95d2994a Avi Kivity
                                 int128_get64(fr->addr.size));
1220 093bc2cd Avi Kivity
            QTAILQ_FOREACH(cmr, &mr->coalesced, link) {
1221 093bc2cd Avi Kivity
                tmp = addrrange_shift(cmr->addr,
1222 08dafab4 Avi Kivity
                                      int128_sub(fr->addr.start,
1223 08dafab4 Avi Kivity
                                                 int128_make64(fr->offset_in_region)));
1224 093bc2cd Avi Kivity
                if (!addrrange_intersects(tmp, fr->addr)) {
1225 093bc2cd Avi Kivity
                    continue;
1226 093bc2cd Avi Kivity
                }
1227 093bc2cd Avi Kivity
                tmp = addrrange_intersection(tmp, fr->addr);
1228 95d2994a Avi Kivity
                MEMORY_LISTENER_CALL(coalesced_mmio_add, Forward, &section,
1229 95d2994a Avi Kivity
                                     int128_get64(tmp.start),
1230 95d2994a Avi Kivity
                                     int128_get64(tmp.size));
1231 093bc2cd Avi Kivity
            }
1232 093bc2cd Avi Kivity
        }
1233 093bc2cd Avi Kivity
    }
1234 093bc2cd Avi Kivity
}
1235 093bc2cd Avi Kivity
1236 0d673e36 Avi Kivity
static void memory_region_update_coalesced_range(MemoryRegion *mr)
1237 0d673e36 Avi Kivity
{
1238 0d673e36 Avi Kivity
    AddressSpace *as;
1239 0d673e36 Avi Kivity
1240 0d673e36 Avi Kivity
    QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) {
1241 0d673e36 Avi Kivity
        memory_region_update_coalesced_range_as(mr, as);
1242 0d673e36 Avi Kivity
    }
1243 0d673e36 Avi Kivity
}
1244 0d673e36 Avi Kivity
1245 093bc2cd Avi Kivity
void memory_region_set_coalescing(MemoryRegion *mr)
1246 093bc2cd Avi Kivity
{
1247 093bc2cd Avi Kivity
    memory_region_clear_coalescing(mr);
1248 08dafab4 Avi Kivity
    memory_region_add_coalescing(mr, 0, int128_get64(mr->size));
1249 093bc2cd Avi Kivity
}
1250 093bc2cd Avi Kivity
1251 093bc2cd Avi Kivity
void memory_region_add_coalescing(MemoryRegion *mr,
1252 a8170e5e Avi Kivity
                                  hwaddr offset,
1253 093bc2cd Avi Kivity
                                  uint64_t size)
1254 093bc2cd Avi Kivity
{
1255 7267c094 Anthony Liguori
    CoalescedMemoryRange *cmr = g_malloc(sizeof(*cmr));
1256 093bc2cd Avi Kivity
1257 08dafab4 Avi Kivity
    cmr->addr = addrrange_make(int128_make64(offset), int128_make64(size));
1258 093bc2cd Avi Kivity
    QTAILQ_INSERT_TAIL(&mr->coalesced, cmr, link);
1259 093bc2cd Avi Kivity
    memory_region_update_coalesced_range(mr);
1260 d410515e Jan Kiszka
    memory_region_set_flush_coalesced(mr);
1261 093bc2cd Avi Kivity
}
1262 093bc2cd Avi Kivity
1263 093bc2cd Avi Kivity
void memory_region_clear_coalescing(MemoryRegion *mr)
1264 093bc2cd Avi Kivity
{
1265 093bc2cd Avi Kivity
    CoalescedMemoryRange *cmr;
1266 093bc2cd Avi Kivity
1267 d410515e Jan Kiszka
    qemu_flush_coalesced_mmio_buffer();
1268 d410515e Jan Kiszka
    mr->flush_coalesced_mmio = false;
1269 d410515e Jan Kiszka
1270 093bc2cd Avi Kivity
    while (!QTAILQ_EMPTY(&mr->coalesced)) {
1271 093bc2cd Avi Kivity
        cmr = QTAILQ_FIRST(&mr->coalesced);
1272 093bc2cd Avi Kivity
        QTAILQ_REMOVE(&mr->coalesced, cmr, link);
1273 7267c094 Anthony Liguori
        g_free(cmr);
1274 093bc2cd Avi Kivity
    }
1275 093bc2cd Avi Kivity
    memory_region_update_coalesced_range(mr);
1276 093bc2cd Avi Kivity
}
1277 093bc2cd Avi Kivity
1278 d410515e Jan Kiszka
void memory_region_set_flush_coalesced(MemoryRegion *mr)
1279 d410515e Jan Kiszka
{
1280 d410515e Jan Kiszka
    mr->flush_coalesced_mmio = true;
1281 d410515e Jan Kiszka
}
1282 d410515e Jan Kiszka
1283 d410515e Jan Kiszka
void memory_region_clear_flush_coalesced(MemoryRegion *mr)
1284 d410515e Jan Kiszka
{
1285 d410515e Jan Kiszka
    qemu_flush_coalesced_mmio_buffer();
1286 d410515e Jan Kiszka
    if (QTAILQ_EMPTY(&mr->coalesced)) {
1287 d410515e Jan Kiszka
        mr->flush_coalesced_mmio = false;
1288 d410515e Jan Kiszka
    }
1289 d410515e Jan Kiszka
}
1290 d410515e Jan Kiszka
1291 3e9d69e7 Avi Kivity
void memory_region_add_eventfd(MemoryRegion *mr,
1292 a8170e5e Avi Kivity
                               hwaddr addr,
1293 3e9d69e7 Avi Kivity
                               unsigned size,
1294 3e9d69e7 Avi Kivity
                               bool match_data,
1295 3e9d69e7 Avi Kivity
                               uint64_t data,
1296 753d5e14 Paolo Bonzini
                               EventNotifier *e)
1297 3e9d69e7 Avi Kivity
{
1298 3e9d69e7 Avi Kivity
    MemoryRegionIoeventfd mrfd = {
1299 08dafab4 Avi Kivity
        .addr.start = int128_make64(addr),
1300 08dafab4 Avi Kivity
        .addr.size = int128_make64(size),
1301 3e9d69e7 Avi Kivity
        .match_data = match_data,
1302 3e9d69e7 Avi Kivity
        .data = data,
1303 753d5e14 Paolo Bonzini
        .e = e,
1304 3e9d69e7 Avi Kivity
    };
1305 3e9d69e7 Avi Kivity
    unsigned i;
1306 3e9d69e7 Avi Kivity
1307 28f362be Alexander Graf
    adjust_endianness(mr, &mrfd.data, size);
1308 59023ef4 Jan Kiszka
    memory_region_transaction_begin();
1309 3e9d69e7 Avi Kivity
    for (i = 0; i < mr->ioeventfd_nb; ++i) {
1310 3e9d69e7 Avi Kivity
        if (memory_region_ioeventfd_before(mrfd, mr->ioeventfds[i])) {
1311 3e9d69e7 Avi Kivity
            break;
1312 3e9d69e7 Avi Kivity
        }
1313 3e9d69e7 Avi Kivity
    }
1314 3e9d69e7 Avi Kivity
    ++mr->ioeventfd_nb;
1315 7267c094 Anthony Liguori
    mr->ioeventfds = g_realloc(mr->ioeventfds,
1316 3e9d69e7 Avi Kivity
                                  sizeof(*mr->ioeventfds) * mr->ioeventfd_nb);
1317 3e9d69e7 Avi Kivity
    memmove(&mr->ioeventfds[i+1], &mr->ioeventfds[i],
1318 3e9d69e7 Avi Kivity
            sizeof(*mr->ioeventfds) * (mr->ioeventfd_nb-1 - i));
1319 3e9d69e7 Avi Kivity
    mr->ioeventfds[i] = mrfd;
1320 22bde714 Jan Kiszka
    memory_region_update_pending |= mr->enabled;
1321 59023ef4 Jan Kiszka
    memory_region_transaction_commit();
1322 3e9d69e7 Avi Kivity
}
1323 3e9d69e7 Avi Kivity
1324 3e9d69e7 Avi Kivity
void memory_region_del_eventfd(MemoryRegion *mr,
1325 a8170e5e Avi Kivity
                               hwaddr addr,
1326 3e9d69e7 Avi Kivity
                               unsigned size,
1327 3e9d69e7 Avi Kivity
                               bool match_data,
1328 3e9d69e7 Avi Kivity
                               uint64_t data,
1329 753d5e14 Paolo Bonzini
                               EventNotifier *e)
1330 3e9d69e7 Avi Kivity
{
1331 3e9d69e7 Avi Kivity
    MemoryRegionIoeventfd mrfd = {
1332 08dafab4 Avi Kivity
        .addr.start = int128_make64(addr),
1333 08dafab4 Avi Kivity
        .addr.size = int128_make64(size),
1334 3e9d69e7 Avi Kivity
        .match_data = match_data,
1335 3e9d69e7 Avi Kivity
        .data = data,
1336 753d5e14 Paolo Bonzini
        .e = e,
1337 3e9d69e7 Avi Kivity
    };
1338 3e9d69e7 Avi Kivity
    unsigned i;
1339 3e9d69e7 Avi Kivity
1340 28f362be Alexander Graf
    adjust_endianness(mr, &mrfd.data, size);
1341 59023ef4 Jan Kiszka
    memory_region_transaction_begin();
1342 3e9d69e7 Avi Kivity
    for (i = 0; i < mr->ioeventfd_nb; ++i) {
1343 3e9d69e7 Avi Kivity
        if (memory_region_ioeventfd_equal(mrfd, mr->ioeventfds[i])) {
1344 3e9d69e7 Avi Kivity
            break;
1345 3e9d69e7 Avi Kivity
        }
1346 3e9d69e7 Avi Kivity
    }
1347 3e9d69e7 Avi Kivity
    assert(i != mr->ioeventfd_nb);
1348 3e9d69e7 Avi Kivity
    memmove(&mr->ioeventfds[i], &mr->ioeventfds[i+1],
1349 3e9d69e7 Avi Kivity
            sizeof(*mr->ioeventfds) * (mr->ioeventfd_nb - (i+1)));
1350 3e9d69e7 Avi Kivity
    --mr->ioeventfd_nb;
1351 7267c094 Anthony Liguori
    mr->ioeventfds = g_realloc(mr->ioeventfds,
1352 3e9d69e7 Avi Kivity
                                  sizeof(*mr->ioeventfds)*mr->ioeventfd_nb + 1);
1353 22bde714 Jan Kiszka
    memory_region_update_pending |= mr->enabled;
1354 59023ef4 Jan Kiszka
    memory_region_transaction_commit();
1355 3e9d69e7 Avi Kivity
}
1356 3e9d69e7 Avi Kivity
1357 093bc2cd Avi Kivity
static void memory_region_add_subregion_common(MemoryRegion *mr,
1358 a8170e5e Avi Kivity
                                               hwaddr offset,
1359 093bc2cd Avi Kivity
                                               MemoryRegion *subregion)
1360 093bc2cd Avi Kivity
{
1361 093bc2cd Avi Kivity
    MemoryRegion *other;
1362 093bc2cd Avi Kivity
1363 59023ef4 Jan Kiszka
    memory_region_transaction_begin();
1364 59023ef4 Jan Kiszka
1365 093bc2cd Avi Kivity
    assert(!subregion->parent);
1366 093bc2cd Avi Kivity
    subregion->parent = mr;
1367 093bc2cd Avi Kivity
    subregion->addr = offset;
1368 093bc2cd Avi Kivity
    QTAILQ_FOREACH(other, &mr->subregions, subregions_link) {
1369 093bc2cd Avi Kivity
        if (subregion->may_overlap || other->may_overlap) {
1370 093bc2cd Avi Kivity
            continue;
1371 093bc2cd Avi Kivity
        }
1372 2c7cfd65 Hu Tao
        if (int128_ge(int128_make64(offset),
1373 08dafab4 Avi Kivity
                      int128_add(int128_make64(other->addr), other->size))
1374 08dafab4 Avi Kivity
            || int128_le(int128_add(int128_make64(offset), subregion->size),
1375 08dafab4 Avi Kivity
                         int128_make64(other->addr))) {
1376 093bc2cd Avi Kivity
            continue;
1377 093bc2cd Avi Kivity
        }
1378 a5e1cbc8 Anthony Liguori
#if 0
1379 860329b2 Michael Walle
        printf("warning: subregion collision %llx/%llx (%s) "
1380 860329b2 Michael Walle
               "vs %llx/%llx (%s)\n",
1381 093bc2cd Avi Kivity
               (unsigned long long)offset,
1382 08dafab4 Avi Kivity
               (unsigned long long)int128_get64(subregion->size),
1383 860329b2 Michael Walle
               subregion->name,
1384 860329b2 Michael Walle
               (unsigned long long)other->addr,
1385 08dafab4 Avi Kivity
               (unsigned long long)int128_get64(other->size),
1386 860329b2 Michael Walle
               other->name);
1387 a5e1cbc8 Anthony Liguori
#endif
1388 093bc2cd Avi Kivity
    }
1389 093bc2cd Avi Kivity
    QTAILQ_FOREACH(other, &mr->subregions, subregions_link) {
1390 093bc2cd Avi Kivity
        if (subregion->priority >= other->priority) {
1391 093bc2cd Avi Kivity
            QTAILQ_INSERT_BEFORE(other, subregion, subregions_link);
1392 093bc2cd Avi Kivity
            goto done;
1393 093bc2cd Avi Kivity
        }
1394 093bc2cd Avi Kivity
    }
1395 093bc2cd Avi Kivity
    QTAILQ_INSERT_TAIL(&mr->subregions, subregion, subregions_link);
1396 093bc2cd Avi Kivity
done:
1397 22bde714 Jan Kiszka
    memory_region_update_pending |= mr->enabled && subregion->enabled;
1398 59023ef4 Jan Kiszka
    memory_region_transaction_commit();
1399 093bc2cd Avi Kivity
}
1400 093bc2cd Avi Kivity
1401 093bc2cd Avi Kivity
1402 093bc2cd Avi Kivity
void memory_region_add_subregion(MemoryRegion *mr,
1403 a8170e5e Avi Kivity
                                 hwaddr offset,
1404 093bc2cd Avi Kivity
                                 MemoryRegion *subregion)
1405 093bc2cd Avi Kivity
{
1406 093bc2cd Avi Kivity
    subregion->may_overlap = false;
1407 093bc2cd Avi Kivity
    subregion->priority = 0;
1408 093bc2cd Avi Kivity
    memory_region_add_subregion_common(mr, offset, subregion);
1409 093bc2cd Avi Kivity
}
1410 093bc2cd Avi Kivity
1411 093bc2cd Avi Kivity
void memory_region_add_subregion_overlap(MemoryRegion *mr,
1412 a8170e5e Avi Kivity
                                         hwaddr offset,
1413 093bc2cd Avi Kivity
                                         MemoryRegion *subregion,
1414 093bc2cd Avi Kivity
                                         unsigned priority)
1415 093bc2cd Avi Kivity
{
1416 093bc2cd Avi Kivity
    subregion->may_overlap = true;
1417 093bc2cd Avi Kivity
    subregion->priority = priority;
1418 093bc2cd Avi Kivity
    memory_region_add_subregion_common(mr, offset, subregion);
1419 093bc2cd Avi Kivity
}
1420 093bc2cd Avi Kivity
1421 093bc2cd Avi Kivity
void memory_region_del_subregion(MemoryRegion *mr,
1422 093bc2cd Avi Kivity
                                 MemoryRegion *subregion)
1423 093bc2cd Avi Kivity
{
1424 59023ef4 Jan Kiszka
    memory_region_transaction_begin();
1425 093bc2cd Avi Kivity
    assert(subregion->parent == mr);
1426 093bc2cd Avi Kivity
    subregion->parent = NULL;
1427 093bc2cd Avi Kivity
    QTAILQ_REMOVE(&mr->subregions, subregion, subregions_link);
1428 22bde714 Jan Kiszka
    memory_region_update_pending |= mr->enabled && subregion->enabled;
1429 59023ef4 Jan Kiszka
    memory_region_transaction_commit();
1430 6bba19ba Avi Kivity
}
1431 6bba19ba Avi Kivity
1432 6bba19ba Avi Kivity
void memory_region_set_enabled(MemoryRegion *mr, bool enabled)
1433 6bba19ba Avi Kivity
{
1434 6bba19ba Avi Kivity
    if (enabled == mr->enabled) {
1435 6bba19ba Avi Kivity
        return;
1436 6bba19ba Avi Kivity
    }
1437 59023ef4 Jan Kiszka
    memory_region_transaction_begin();
1438 6bba19ba Avi Kivity
    mr->enabled = enabled;
1439 22bde714 Jan Kiszka
    memory_region_update_pending = true;
1440 59023ef4 Jan Kiszka
    memory_region_transaction_commit();
1441 093bc2cd Avi Kivity
}
1442 1c0ffa58 Avi Kivity
1443 a8170e5e Avi Kivity
void memory_region_set_address(MemoryRegion *mr, hwaddr addr)
1444 2282e1af Avi Kivity
{
1445 2282e1af Avi Kivity
    MemoryRegion *parent = mr->parent;
1446 2282e1af Avi Kivity
    unsigned priority = mr->priority;
1447 2282e1af Avi Kivity
    bool may_overlap = mr->may_overlap;
1448 2282e1af Avi Kivity
1449 2282e1af Avi Kivity
    if (addr == mr->addr || !parent) {
1450 2282e1af Avi Kivity
        mr->addr = addr;
1451 2282e1af Avi Kivity
        return;
1452 2282e1af Avi Kivity
    }
1453 2282e1af Avi Kivity
1454 2282e1af Avi Kivity
    memory_region_transaction_begin();
1455 2282e1af Avi Kivity
    memory_region_del_subregion(parent, mr);
1456 2282e1af Avi Kivity
    if (may_overlap) {
1457 2282e1af Avi Kivity
        memory_region_add_subregion_overlap(parent, addr, mr, priority);
1458 2282e1af Avi Kivity
    } else {
1459 2282e1af Avi Kivity
        memory_region_add_subregion(parent, addr, mr);
1460 2282e1af Avi Kivity
    }
1461 2282e1af Avi Kivity
    memory_region_transaction_commit();
1462 2282e1af Avi Kivity
}
1463 2282e1af Avi Kivity
1464 a8170e5e Avi Kivity
void memory_region_set_alias_offset(MemoryRegion *mr, hwaddr offset)
1465 4703359e Avi Kivity
{
1466 4703359e Avi Kivity
    assert(mr->alias);
1467 4703359e Avi Kivity
1468 59023ef4 Jan Kiszka
    if (offset == mr->alias_offset) {
1469 4703359e Avi Kivity
        return;
1470 4703359e Avi Kivity
    }
1471 4703359e Avi Kivity
1472 59023ef4 Jan Kiszka
    memory_region_transaction_begin();
1473 59023ef4 Jan Kiszka
    mr->alias_offset = offset;
1474 22bde714 Jan Kiszka
    memory_region_update_pending |= mr->enabled;
1475 59023ef4 Jan Kiszka
    memory_region_transaction_commit();
1476 4703359e Avi Kivity
}
1477 4703359e Avi Kivity
1478 e34911c4 Avi Kivity
ram_addr_t memory_region_get_ram_addr(MemoryRegion *mr)
1479 e34911c4 Avi Kivity
{
1480 e34911c4 Avi Kivity
    return mr->ram_addr;
1481 e34911c4 Avi Kivity
}
1482 e34911c4 Avi Kivity
1483 e2177955 Avi Kivity
static int cmp_flatrange_addr(const void *addr_, const void *fr_)
1484 e2177955 Avi Kivity
{
1485 e2177955 Avi Kivity
    const AddrRange *addr = addr_;
1486 e2177955 Avi Kivity
    const FlatRange *fr = fr_;
1487 e2177955 Avi Kivity
1488 e2177955 Avi Kivity
    if (int128_le(addrrange_end(*addr), fr->addr.start)) {
1489 e2177955 Avi Kivity
        return -1;
1490 e2177955 Avi Kivity
    } else if (int128_ge(addr->start, addrrange_end(fr->addr))) {
1491 e2177955 Avi Kivity
        return 1;
1492 e2177955 Avi Kivity
    }
1493 e2177955 Avi Kivity
    return 0;
1494 e2177955 Avi Kivity
}
1495 e2177955 Avi Kivity
1496 e2177955 Avi Kivity
static FlatRange *address_space_lookup(AddressSpace *as, AddrRange addr)
1497 e2177955 Avi Kivity
{
1498 8786db7c Avi Kivity
    return bsearch(&addr, as->current_map->ranges, as->current_map->nr,
1499 e2177955 Avi Kivity
                   sizeof(FlatRange), cmp_flatrange_addr);
1500 e2177955 Avi Kivity
}
1501 e2177955 Avi Kivity
1502 73034e9e Paolo Bonzini
MemoryRegionSection memory_region_find(MemoryRegion *mr,
1503 a8170e5e Avi Kivity
                                       hwaddr addr, uint64_t size)
1504 e2177955 Avi Kivity
{
1505 e2177955 Avi Kivity
    MemoryRegionSection ret = { .mr = NULL, .size = 0 };
1506 73034e9e Paolo Bonzini
    MemoryRegion *root;
1507 73034e9e Paolo Bonzini
    AddressSpace *as;
1508 73034e9e Paolo Bonzini
    AddrRange range;
1509 73034e9e Paolo Bonzini
    FlatRange *fr;
1510 73034e9e Paolo Bonzini
1511 73034e9e Paolo Bonzini
    addr += mr->addr;
1512 73034e9e Paolo Bonzini
    for (root = mr; root->parent; ) {
1513 73034e9e Paolo Bonzini
        root = root->parent;
1514 73034e9e Paolo Bonzini
        addr += root->addr;
1515 73034e9e Paolo Bonzini
    }
1516 e2177955 Avi Kivity
1517 73034e9e Paolo Bonzini
    as = memory_region_to_address_space(root);
1518 73034e9e Paolo Bonzini
    range = addrrange_make(int128_make64(addr), int128_make64(size));
1519 73034e9e Paolo Bonzini
    fr = address_space_lookup(as, range);
1520 e2177955 Avi Kivity
    if (!fr) {
1521 e2177955 Avi Kivity
        return ret;
1522 e2177955 Avi Kivity
    }
1523 e2177955 Avi Kivity
1524 8786db7c Avi Kivity
    while (fr > as->current_map->ranges
1525 e2177955 Avi Kivity
           && addrrange_intersects(fr[-1].addr, range)) {
1526 e2177955 Avi Kivity
        --fr;
1527 e2177955 Avi Kivity
    }
1528 e2177955 Avi Kivity
1529 e2177955 Avi Kivity
    ret.mr = fr->mr;
1530 73034e9e Paolo Bonzini
    ret.address_space = as;
1531 e2177955 Avi Kivity
    range = addrrange_intersection(range, fr->addr);
1532 e2177955 Avi Kivity
    ret.offset_within_region = fr->offset_in_region;
1533 e2177955 Avi Kivity
    ret.offset_within_region += int128_get64(int128_sub(range.start,
1534 e2177955 Avi Kivity
                                                        fr->addr.start));
1535 e2177955 Avi Kivity
    ret.size = int128_get64(range.size);
1536 e2177955 Avi Kivity
    ret.offset_within_address_space = int128_get64(range.start);
1537 7a8499e8 Avi Kivity
    ret.readonly = fr->readonly;
1538 e2177955 Avi Kivity
    return ret;
1539 e2177955 Avi Kivity
}
1540 e2177955 Avi Kivity
1541 1d671369 Paolo Bonzini
void address_space_sync_dirty_bitmap(AddressSpace *as)
1542 86e775c6 Avi Kivity
{
1543 7664e80c Avi Kivity
    FlatRange *fr;
1544 7664e80c Avi Kivity
1545 8786db7c Avi Kivity
    FOR_EACH_FLAT_RANGE(fr, as->current_map) {
1546 72e22d2f Avi Kivity
        MEMORY_LISTENER_UPDATE_REGION(fr, as, Forward, log_sync);
1547 7664e80c Avi Kivity
    }
1548 7664e80c Avi Kivity
}
1549 7664e80c Avi Kivity
1550 7664e80c Avi Kivity
void memory_global_dirty_log_start(void)
1551 7664e80c Avi Kivity
{
1552 7664e80c Avi Kivity
    global_dirty_log = true;
1553 7376e582 Avi Kivity
    MEMORY_LISTENER_CALL_GLOBAL(log_global_start, Forward);
1554 7664e80c Avi Kivity
}
1555 7664e80c Avi Kivity
1556 7664e80c Avi Kivity
void memory_global_dirty_log_stop(void)
1557 7664e80c Avi Kivity
{
1558 7664e80c Avi Kivity
    global_dirty_log = false;
1559 7376e582 Avi Kivity
    MEMORY_LISTENER_CALL_GLOBAL(log_global_stop, Reverse);
1560 7664e80c Avi Kivity
}
1561 7664e80c Avi Kivity
1562 7664e80c Avi Kivity
static void listener_add_address_space(MemoryListener *listener,
1563 7664e80c Avi Kivity
                                       AddressSpace *as)
1564 7664e80c Avi Kivity
{
1565 7664e80c Avi Kivity
    FlatRange *fr;
1566 7664e80c Avi Kivity
1567 221b3a3f Julien Grall
    if (listener->address_space_filter
1568 f6790af6 Avi Kivity
        && listener->address_space_filter != as) {
1569 221b3a3f Julien Grall
        return;
1570 221b3a3f Julien Grall
    }
1571 221b3a3f Julien Grall
1572 7664e80c Avi Kivity
    if (global_dirty_log) {
1573 975aefe0 Avi Kivity
        if (listener->log_global_start) {
1574 975aefe0 Avi Kivity
            listener->log_global_start(listener);
1575 975aefe0 Avi Kivity
        }
1576 7664e80c Avi Kivity
    }
1577 975aefe0 Avi Kivity
1578 8786db7c Avi Kivity
    FOR_EACH_FLAT_RANGE(fr, as->current_map) {
1579 7664e80c Avi Kivity
        MemoryRegionSection section = {
1580 7664e80c Avi Kivity
            .mr = fr->mr,
1581 f6790af6 Avi Kivity
            .address_space = as,
1582 7664e80c Avi Kivity
            .offset_within_region = fr->offset_in_region,
1583 7664e80c Avi Kivity
            .size = int128_get64(fr->addr.size),
1584 7664e80c Avi Kivity
            .offset_within_address_space = int128_get64(fr->addr.start),
1585 7a8499e8 Avi Kivity
            .readonly = fr->readonly,
1586 7664e80c Avi Kivity
        };
1587 975aefe0 Avi Kivity
        if (listener->region_add) {
1588 975aefe0 Avi Kivity
            listener->region_add(listener, &section);
1589 975aefe0 Avi Kivity
        }
1590 7664e80c Avi Kivity
    }
1591 7664e80c Avi Kivity
}
1592 7664e80c Avi Kivity
1593 f6790af6 Avi Kivity
void memory_listener_register(MemoryListener *listener, AddressSpace *filter)
1594 7664e80c Avi Kivity
{
1595 72e22d2f Avi Kivity
    MemoryListener *other = NULL;
1596 0d673e36 Avi Kivity
    AddressSpace *as;
1597 72e22d2f Avi Kivity
1598 7376e582 Avi Kivity
    listener->address_space_filter = filter;
1599 72e22d2f Avi Kivity
    if (QTAILQ_EMPTY(&memory_listeners)
1600 72e22d2f Avi Kivity
        || listener->priority >= QTAILQ_LAST(&memory_listeners,
1601 72e22d2f Avi Kivity
                                             memory_listeners)->priority) {
1602 72e22d2f Avi Kivity
        QTAILQ_INSERT_TAIL(&memory_listeners, listener, link);
1603 72e22d2f Avi Kivity
    } else {
1604 72e22d2f Avi Kivity
        QTAILQ_FOREACH(other, &memory_listeners, link) {
1605 72e22d2f Avi Kivity
            if (listener->priority < other->priority) {
1606 72e22d2f Avi Kivity
                break;
1607 72e22d2f Avi Kivity
            }
1608 72e22d2f Avi Kivity
        }
1609 72e22d2f Avi Kivity
        QTAILQ_INSERT_BEFORE(other, listener, link);
1610 72e22d2f Avi Kivity
    }
1611 0d673e36 Avi Kivity
1612 0d673e36 Avi Kivity
    QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) {
1613 0d673e36 Avi Kivity
        listener_add_address_space(listener, as);
1614 0d673e36 Avi Kivity
    }
1615 7664e80c Avi Kivity
}
1616 7664e80c Avi Kivity
1617 7664e80c Avi Kivity
void memory_listener_unregister(MemoryListener *listener)
1618 7664e80c Avi Kivity
{
1619 72e22d2f Avi Kivity
    QTAILQ_REMOVE(&memory_listeners, listener, link);
1620 86e775c6 Avi Kivity
}
1621 e2177955 Avi Kivity
1622 9ad2bbc1 Avi Kivity
void address_space_init(AddressSpace *as, MemoryRegion *root)
1623 1c0ffa58 Avi Kivity
{
1624 59023ef4 Jan Kiszka
    memory_region_transaction_begin();
1625 8786db7c Avi Kivity
    as->root = root;
1626 8786db7c Avi Kivity
    as->current_map = g_new(FlatView, 1);
1627 8786db7c Avi Kivity
    flatview_init(as->current_map);
1628 4c19eb72 Avi Kivity
    as->ioeventfd_nb = 0;
1629 4c19eb72 Avi Kivity
    as->ioeventfds = NULL;
1630 0d673e36 Avi Kivity
    QTAILQ_INSERT_TAIL(&address_spaces, as, address_spaces_link);
1631 0d673e36 Avi Kivity
    as->name = NULL;
1632 ac1970fb Avi Kivity
    address_space_init_dispatch(as);
1633 f43793c7 Paolo Bonzini
    memory_region_update_pending |= root->enabled;
1634 f43793c7 Paolo Bonzini
    memory_region_transaction_commit();
1635 1c0ffa58 Avi Kivity
}
1636 658b2224 Avi Kivity
1637 83f3c251 Avi Kivity
void address_space_destroy(AddressSpace *as)
1638 83f3c251 Avi Kivity
{
1639 83f3c251 Avi Kivity
    /* Flush out anything from MemoryListeners listening in on this */
1640 83f3c251 Avi Kivity
    memory_region_transaction_begin();
1641 83f3c251 Avi Kivity
    as->root = NULL;
1642 83f3c251 Avi Kivity
    memory_region_transaction_commit();
1643 83f3c251 Avi Kivity
    QTAILQ_REMOVE(&address_spaces, as, address_spaces_link);
1644 83f3c251 Avi Kivity
    address_space_destroy_dispatch(as);
1645 83f3c251 Avi Kivity
    flatview_destroy(as->current_map);
1646 83f3c251 Avi Kivity
    g_free(as->current_map);
1647 4c19eb72 Avi Kivity
    g_free(as->ioeventfds);
1648 83f3c251 Avi Kivity
}
1649 83f3c251 Avi Kivity
1650 a8170e5e Avi Kivity
uint64_t io_mem_read(MemoryRegion *mr, hwaddr addr, unsigned size)
1651 acbbec5d Avi Kivity
{
1652 37ec01d4 Avi Kivity
    return memory_region_dispatch_read(mr, addr, size);
1653 acbbec5d Avi Kivity
}
1654 acbbec5d Avi Kivity
1655 a8170e5e Avi Kivity
void io_mem_write(MemoryRegion *mr, hwaddr addr,
1656 acbbec5d Avi Kivity
                  uint64_t val, unsigned size)
1657 acbbec5d Avi Kivity
{
1658 37ec01d4 Avi Kivity
    memory_region_dispatch_write(mr, addr, val, size);
1659 acbbec5d Avi Kivity
}
1660 acbbec5d Avi Kivity
1661 314e2987 Blue Swirl
typedef struct MemoryRegionList MemoryRegionList;
1662 314e2987 Blue Swirl
1663 314e2987 Blue Swirl
struct MemoryRegionList {
1664 314e2987 Blue Swirl
    const MemoryRegion *mr;
1665 314e2987 Blue Swirl
    bool printed;
1666 314e2987 Blue Swirl
    QTAILQ_ENTRY(MemoryRegionList) queue;
1667 314e2987 Blue Swirl
};
1668 314e2987 Blue Swirl
1669 314e2987 Blue Swirl
typedef QTAILQ_HEAD(queue, MemoryRegionList) MemoryRegionListHead;
1670 314e2987 Blue Swirl
1671 314e2987 Blue Swirl
static void mtree_print_mr(fprintf_function mon_printf, void *f,
1672 314e2987 Blue Swirl
                           const MemoryRegion *mr, unsigned int level,
1673 a8170e5e Avi Kivity
                           hwaddr base,
1674 9479c57a Jan Kiszka
                           MemoryRegionListHead *alias_print_queue)
1675 314e2987 Blue Swirl
{
1676 9479c57a Jan Kiszka
    MemoryRegionList *new_ml, *ml, *next_ml;
1677 9479c57a Jan Kiszka
    MemoryRegionListHead submr_print_queue;
1678 314e2987 Blue Swirl
    const MemoryRegion *submr;
1679 314e2987 Blue Swirl
    unsigned int i;
1680 314e2987 Blue Swirl
1681 7ea692b2 Jan Kiszka
    if (!mr || !mr->enabled) {
1682 314e2987 Blue Swirl
        return;
1683 314e2987 Blue Swirl
    }
1684 314e2987 Blue Swirl
1685 314e2987 Blue Swirl
    for (i = 0; i < level; i++) {
1686 314e2987 Blue Swirl
        mon_printf(f, "  ");
1687 314e2987 Blue Swirl
    }
1688 314e2987 Blue Swirl
1689 314e2987 Blue Swirl
    if (mr->alias) {
1690 314e2987 Blue Swirl
        MemoryRegionList *ml;
1691 314e2987 Blue Swirl
        bool found = false;
1692 314e2987 Blue Swirl
1693 314e2987 Blue Swirl
        /* check if the alias is already in the queue */
1694 9479c57a Jan Kiszka
        QTAILQ_FOREACH(ml, alias_print_queue, queue) {
1695 314e2987 Blue Swirl
            if (ml->mr == mr->alias && !ml->printed) {
1696 314e2987 Blue Swirl
                found = true;
1697 314e2987 Blue Swirl
            }
1698 314e2987 Blue Swirl
        }
1699 314e2987 Blue Swirl
1700 314e2987 Blue Swirl
        if (!found) {
1701 314e2987 Blue Swirl
            ml = g_new(MemoryRegionList, 1);
1702 314e2987 Blue Swirl
            ml->mr = mr->alias;
1703 314e2987 Blue Swirl
            ml->printed = false;
1704 9479c57a Jan Kiszka
            QTAILQ_INSERT_TAIL(alias_print_queue, ml, queue);
1705 314e2987 Blue Swirl
        }
1706 4896d74b Jan Kiszka
        mon_printf(f, TARGET_FMT_plx "-" TARGET_FMT_plx
1707 4896d74b Jan Kiszka
                   " (prio %d, %c%c): alias %s @%s " TARGET_FMT_plx
1708 4896d74b Jan Kiszka
                   "-" TARGET_FMT_plx "\n",
1709 314e2987 Blue Swirl
                   base + mr->addr,
1710 08dafab4 Avi Kivity
                   base + mr->addr
1711 a8170e5e Avi Kivity
                   + (hwaddr)int128_get64(mr->size) - 1,
1712 4b474ba7 Jan Kiszka
                   mr->priority,
1713 5f9a5ea1 Jan Kiszka
                   mr->romd_mode ? 'R' : '-',
1714 5f9a5ea1 Jan Kiszka
                   !mr->readonly && !(mr->rom_device && mr->romd_mode) ? 'W'
1715 5f9a5ea1 Jan Kiszka
                                                                       : '-',
1716 314e2987 Blue Swirl
                   mr->name,
1717 314e2987 Blue Swirl
                   mr->alias->name,
1718 314e2987 Blue Swirl
                   mr->alias_offset,
1719 08dafab4 Avi Kivity
                   mr->alias_offset
1720 a8170e5e Avi Kivity
                   + (hwaddr)int128_get64(mr->size) - 1);
1721 314e2987 Blue Swirl
    } else {
1722 4896d74b Jan Kiszka
        mon_printf(f,
1723 4896d74b Jan Kiszka
                   TARGET_FMT_plx "-" TARGET_FMT_plx " (prio %d, %c%c): %s\n",
1724 314e2987 Blue Swirl
                   base + mr->addr,
1725 08dafab4 Avi Kivity
                   base + mr->addr
1726 a8170e5e Avi Kivity
                   + (hwaddr)int128_get64(mr->size) - 1,
1727 4b474ba7 Jan Kiszka
                   mr->priority,
1728 5f9a5ea1 Jan Kiszka
                   mr->romd_mode ? 'R' : '-',
1729 5f9a5ea1 Jan Kiszka
                   !mr->readonly && !(mr->rom_device && mr->romd_mode) ? 'W'
1730 5f9a5ea1 Jan Kiszka
                                                                       : '-',
1731 314e2987 Blue Swirl
                   mr->name);
1732 314e2987 Blue Swirl
    }
1733 9479c57a Jan Kiszka
1734 9479c57a Jan Kiszka
    QTAILQ_INIT(&submr_print_queue);
1735 9479c57a Jan Kiszka
1736 314e2987 Blue Swirl
    QTAILQ_FOREACH(submr, &mr->subregions, subregions_link) {
1737 9479c57a Jan Kiszka
        new_ml = g_new(MemoryRegionList, 1);
1738 9479c57a Jan Kiszka
        new_ml->mr = submr;
1739 9479c57a Jan Kiszka
        QTAILQ_FOREACH(ml, &submr_print_queue, queue) {
1740 9479c57a Jan Kiszka
            if (new_ml->mr->addr < ml->mr->addr ||
1741 9479c57a Jan Kiszka
                (new_ml->mr->addr == ml->mr->addr &&
1742 9479c57a Jan Kiszka
                 new_ml->mr->priority > ml->mr->priority)) {
1743 9479c57a Jan Kiszka
                QTAILQ_INSERT_BEFORE(ml, new_ml, queue);
1744 9479c57a Jan Kiszka
                new_ml = NULL;
1745 9479c57a Jan Kiszka
                break;
1746 9479c57a Jan Kiszka
            }
1747 9479c57a Jan Kiszka
        }
1748 9479c57a Jan Kiszka
        if (new_ml) {
1749 9479c57a Jan Kiszka
            QTAILQ_INSERT_TAIL(&submr_print_queue, new_ml, queue);
1750 9479c57a Jan Kiszka
        }
1751 9479c57a Jan Kiszka
    }
1752 9479c57a Jan Kiszka
1753 9479c57a Jan Kiszka
    QTAILQ_FOREACH(ml, &submr_print_queue, queue) {
1754 9479c57a Jan Kiszka
        mtree_print_mr(mon_printf, f, ml->mr, level + 1, base + mr->addr,
1755 9479c57a Jan Kiszka
                       alias_print_queue);
1756 9479c57a Jan Kiszka
    }
1757 9479c57a Jan Kiszka
1758 88365e47 Avi Kivity
    QTAILQ_FOREACH_SAFE(ml, &submr_print_queue, queue, next_ml) {
1759 9479c57a Jan Kiszka
        g_free(ml);
1760 314e2987 Blue Swirl
    }
1761 314e2987 Blue Swirl
}
1762 314e2987 Blue Swirl
1763 314e2987 Blue Swirl
void mtree_info(fprintf_function mon_printf, void *f)
1764 314e2987 Blue Swirl
{
1765 314e2987 Blue Swirl
    MemoryRegionListHead ml_head;
1766 314e2987 Blue Swirl
    MemoryRegionList *ml, *ml2;
1767 0d673e36 Avi Kivity
    AddressSpace *as;
1768 314e2987 Blue Swirl
1769 314e2987 Blue Swirl
    QTAILQ_INIT(&ml_head);
1770 314e2987 Blue Swirl
1771 0d673e36 Avi Kivity
    QTAILQ_FOREACH(as, &address_spaces, address_spaces_link) {
1772 0d673e36 Avi Kivity
        if (!as->name) {
1773 0d673e36 Avi Kivity
            continue;
1774 0d673e36 Avi Kivity
        }
1775 0d673e36 Avi Kivity
        mon_printf(f, "%s\n", as->name);
1776 0d673e36 Avi Kivity
        mtree_print_mr(mon_printf, f, as->root, 0, 0, &ml_head);
1777 b9f9be88 Blue Swirl
    }
1778 b9f9be88 Blue Swirl
1779 b9f9be88 Blue Swirl
    mon_printf(f, "aliases\n");
1780 314e2987 Blue Swirl
    /* print aliased regions */
1781 314e2987 Blue Swirl
    QTAILQ_FOREACH(ml, &ml_head, queue) {
1782 314e2987 Blue Swirl
        if (!ml->printed) {
1783 314e2987 Blue Swirl
            mon_printf(f, "%s\n", ml->mr->name);
1784 314e2987 Blue Swirl
            mtree_print_mr(mon_printf, f, ml->mr, 0, 0, &ml_head);
1785 314e2987 Blue Swirl
        }
1786 314e2987 Blue Swirl
    }
1787 314e2987 Blue Swirl
1788 314e2987 Blue Swirl
    QTAILQ_FOREACH_SAFE(ml, &ml_head, queue, ml2) {
1789 88365e47 Avi Kivity
        g_free(ml);
1790 314e2987 Blue Swirl
    }
1791 314e2987 Blue Swirl
}