Statistics
| Branch: | Revision:

root / memory.c @ feature-archipelago

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