Statistics
| Branch: | Revision:

root / memory.c @ be637f74

History | View | Annotate | Download (40.7 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 093bc2cd Avi Kivity
 */
13 093bc2cd Avi Kivity
14 093bc2cd Avi Kivity
#include "memory.h"
15 1c0ffa58 Avi Kivity
#include "exec-memory.h"
16 658b2224 Avi Kivity
#include "ioport.h"
17 74901c3b Avi Kivity
#include "bitops.h"
18 3e9d69e7 Avi Kivity
#include "kvm.h"
19 093bc2cd Avi Kivity
#include <assert.h>
20 093bc2cd Avi Kivity
21 4ef4db86 Avi Kivity
unsigned memory_region_transaction_depth = 0;
22 4ef4db86 Avi Kivity
23 093bc2cd Avi Kivity
typedef struct AddrRange AddrRange;
24 093bc2cd Avi Kivity
25 8417cebf Avi Kivity
/*
26 8417cebf Avi Kivity
 * Note using signed integers limits us to physical addresses at most
27 8417cebf Avi Kivity
 * 63 bits wide.  They are needed for negative offsetting in aliases
28 8417cebf Avi Kivity
 * (large MemoryRegion::alias_offset).
29 8417cebf Avi Kivity
 */
30 093bc2cd Avi Kivity
struct AddrRange {
31 8417cebf Avi Kivity
    int64_t start;
32 8417cebf Avi Kivity
    int64_t size;
33 093bc2cd Avi Kivity
};
34 093bc2cd Avi Kivity
35 8417cebf Avi Kivity
static AddrRange addrrange_make(int64_t start, int64_t size)
36 093bc2cd Avi Kivity
{
37 093bc2cd Avi Kivity
    return (AddrRange) { start, size };
38 093bc2cd Avi Kivity
}
39 093bc2cd Avi Kivity
40 093bc2cd Avi Kivity
static bool addrrange_equal(AddrRange r1, AddrRange r2)
41 093bc2cd Avi Kivity
{
42 093bc2cd Avi Kivity
    return r1.start == r2.start && r1.size == r2.size;
43 093bc2cd Avi Kivity
}
44 093bc2cd Avi Kivity
45 8417cebf Avi Kivity
static int64_t addrrange_end(AddrRange r)
46 093bc2cd Avi Kivity
{
47 093bc2cd Avi Kivity
    return r.start + r.size;
48 093bc2cd Avi Kivity
}
49 093bc2cd Avi Kivity
50 093bc2cd Avi Kivity
static AddrRange addrrange_shift(AddrRange range, int64_t delta)
51 093bc2cd Avi Kivity
{
52 093bc2cd Avi Kivity
    range.start += delta;
53 093bc2cd Avi Kivity
    return range;
54 093bc2cd Avi Kivity
}
55 093bc2cd Avi Kivity
56 093bc2cd Avi Kivity
static bool addrrange_intersects(AddrRange r1, AddrRange r2)
57 093bc2cd Avi Kivity
{
58 d2963631 David Gibson
    return (r1.start >= r2.start && (r1.start - r2.start) < r2.size)
59 d2963631 David Gibson
        || (r2.start >= r1.start && (r2.start - r1.start) < r1.size);
60 093bc2cd Avi Kivity
}
61 093bc2cd Avi Kivity
62 093bc2cd Avi Kivity
static AddrRange addrrange_intersection(AddrRange r1, AddrRange r2)
63 093bc2cd Avi Kivity
{
64 8417cebf Avi Kivity
    int64_t start = MAX(r1.start, r2.start);
65 093bc2cd Avi Kivity
    /* off-by-one arithmetic to prevent overflow */
66 8417cebf Avi Kivity
    int64_t end = MIN(addrrange_end(r1) - 1, addrrange_end(r2) - 1);
67 093bc2cd Avi Kivity
    return addrrange_make(start, end - start + 1);
68 093bc2cd Avi Kivity
}
69 093bc2cd Avi Kivity
70 093bc2cd Avi Kivity
struct CoalescedMemoryRange {
71 093bc2cd Avi Kivity
    AddrRange addr;
72 093bc2cd Avi Kivity
    QTAILQ_ENTRY(CoalescedMemoryRange) link;
73 093bc2cd Avi Kivity
};
74 093bc2cd Avi Kivity
75 3e9d69e7 Avi Kivity
struct MemoryRegionIoeventfd {
76 3e9d69e7 Avi Kivity
    AddrRange addr;
77 3e9d69e7 Avi Kivity
    bool match_data;
78 3e9d69e7 Avi Kivity
    uint64_t data;
79 3e9d69e7 Avi Kivity
    int fd;
80 3e9d69e7 Avi Kivity
};
81 3e9d69e7 Avi Kivity
82 3e9d69e7 Avi Kivity
static bool memory_region_ioeventfd_before(MemoryRegionIoeventfd a,
83 3e9d69e7 Avi Kivity
                                           MemoryRegionIoeventfd b)
84 3e9d69e7 Avi Kivity
{
85 3e9d69e7 Avi Kivity
    if (a.addr.start < b.addr.start) {
86 3e9d69e7 Avi Kivity
        return true;
87 3e9d69e7 Avi Kivity
    } else if (a.addr.start > b.addr.start) {
88 3e9d69e7 Avi Kivity
        return false;
89 3e9d69e7 Avi Kivity
    } else if (a.addr.size < b.addr.size) {
90 3e9d69e7 Avi Kivity
        return true;
91 3e9d69e7 Avi Kivity
    } else if (a.addr.size > b.addr.size) {
92 3e9d69e7 Avi Kivity
        return false;
93 3e9d69e7 Avi Kivity
    } else if (a.match_data < b.match_data) {
94 3e9d69e7 Avi Kivity
        return true;
95 3e9d69e7 Avi Kivity
    } else  if (a.match_data > b.match_data) {
96 3e9d69e7 Avi Kivity
        return false;
97 3e9d69e7 Avi Kivity
    } else if (a.match_data) {
98 3e9d69e7 Avi Kivity
        if (a.data < b.data) {
99 3e9d69e7 Avi Kivity
            return true;
100 3e9d69e7 Avi Kivity
        } else if (a.data > b.data) {
101 3e9d69e7 Avi Kivity
            return false;
102 3e9d69e7 Avi Kivity
        }
103 3e9d69e7 Avi Kivity
    }
104 3e9d69e7 Avi Kivity
    if (a.fd < b.fd) {
105 3e9d69e7 Avi Kivity
        return true;
106 3e9d69e7 Avi Kivity
    } else if (a.fd > b.fd) {
107 3e9d69e7 Avi Kivity
        return false;
108 3e9d69e7 Avi Kivity
    }
109 3e9d69e7 Avi Kivity
    return false;
110 3e9d69e7 Avi Kivity
}
111 3e9d69e7 Avi Kivity
112 3e9d69e7 Avi Kivity
static bool memory_region_ioeventfd_equal(MemoryRegionIoeventfd a,
113 3e9d69e7 Avi Kivity
                                          MemoryRegionIoeventfd b)
114 3e9d69e7 Avi Kivity
{
115 3e9d69e7 Avi Kivity
    return !memory_region_ioeventfd_before(a, b)
116 3e9d69e7 Avi Kivity
        && !memory_region_ioeventfd_before(b, a);
117 3e9d69e7 Avi Kivity
}
118 3e9d69e7 Avi Kivity
119 093bc2cd Avi Kivity
typedef struct FlatRange FlatRange;
120 093bc2cd Avi Kivity
typedef struct FlatView FlatView;
121 093bc2cd Avi Kivity
122 093bc2cd Avi Kivity
/* Range of memory in the global map.  Addresses are absolute. */
123 093bc2cd Avi Kivity
struct FlatRange {
124 093bc2cd Avi Kivity
    MemoryRegion *mr;
125 093bc2cd Avi Kivity
    target_phys_addr_t offset_in_region;
126 093bc2cd Avi Kivity
    AddrRange addr;
127 5a583347 Avi Kivity
    uint8_t dirty_log_mask;
128 d0a9b5bc Avi Kivity
    bool readable;
129 fb1cd6f9 Avi Kivity
    bool readonly;
130 093bc2cd Avi Kivity
};
131 093bc2cd Avi Kivity
132 093bc2cd Avi Kivity
/* Flattened global view of current active memory hierarchy.  Kept in sorted
133 093bc2cd Avi Kivity
 * order.
134 093bc2cd Avi Kivity
 */
135 093bc2cd Avi Kivity
struct FlatView {
136 093bc2cd Avi Kivity
    FlatRange *ranges;
137 093bc2cd Avi Kivity
    unsigned nr;
138 093bc2cd Avi Kivity
    unsigned nr_allocated;
139 093bc2cd Avi Kivity
};
140 093bc2cd Avi Kivity
141 cc31e6e7 Avi Kivity
typedef struct AddressSpace AddressSpace;
142 cc31e6e7 Avi Kivity
typedef struct AddressSpaceOps AddressSpaceOps;
143 cc31e6e7 Avi Kivity
144 cc31e6e7 Avi Kivity
/* A system address space - I/O, memory, etc. */
145 cc31e6e7 Avi Kivity
struct AddressSpace {
146 cc31e6e7 Avi Kivity
    const AddressSpaceOps *ops;
147 cc31e6e7 Avi Kivity
    MemoryRegion *root;
148 cc31e6e7 Avi Kivity
    FlatView current_map;
149 3e9d69e7 Avi Kivity
    int ioeventfd_nb;
150 3e9d69e7 Avi Kivity
    MemoryRegionIoeventfd *ioeventfds;
151 cc31e6e7 Avi Kivity
};
152 cc31e6e7 Avi Kivity
153 cc31e6e7 Avi Kivity
struct AddressSpaceOps {
154 cc31e6e7 Avi Kivity
    void (*range_add)(AddressSpace *as, FlatRange *fr);
155 cc31e6e7 Avi Kivity
    void (*range_del)(AddressSpace *as, FlatRange *fr);
156 cc31e6e7 Avi Kivity
    void (*log_start)(AddressSpace *as, FlatRange *fr);
157 cc31e6e7 Avi Kivity
    void (*log_stop)(AddressSpace *as, FlatRange *fr);
158 3e9d69e7 Avi Kivity
    void (*ioeventfd_add)(AddressSpace *as, MemoryRegionIoeventfd *fd);
159 3e9d69e7 Avi Kivity
    void (*ioeventfd_del)(AddressSpace *as, MemoryRegionIoeventfd *fd);
160 cc31e6e7 Avi Kivity
};
161 cc31e6e7 Avi Kivity
162 093bc2cd Avi Kivity
#define FOR_EACH_FLAT_RANGE(var, view)          \
163 093bc2cd Avi Kivity
    for (var = (view)->ranges; var < (view)->ranges + (view)->nr; ++var)
164 093bc2cd Avi Kivity
165 093bc2cd Avi Kivity
static bool flatrange_equal(FlatRange *a, FlatRange *b)
166 093bc2cd Avi Kivity
{
167 093bc2cd Avi Kivity
    return a->mr == b->mr
168 093bc2cd Avi Kivity
        && addrrange_equal(a->addr, b->addr)
169 d0a9b5bc Avi Kivity
        && a->offset_in_region == b->offset_in_region
170 fb1cd6f9 Avi Kivity
        && a->readable == b->readable
171 fb1cd6f9 Avi Kivity
        && a->readonly == b->readonly;
172 093bc2cd Avi Kivity
}
173 093bc2cd Avi Kivity
174 093bc2cd Avi Kivity
static void flatview_init(FlatView *view)
175 093bc2cd Avi Kivity
{
176 093bc2cd Avi Kivity
    view->ranges = NULL;
177 093bc2cd Avi Kivity
    view->nr = 0;
178 093bc2cd Avi Kivity
    view->nr_allocated = 0;
179 093bc2cd Avi Kivity
}
180 093bc2cd Avi Kivity
181 093bc2cd Avi Kivity
/* Insert a range into a given position.  Caller is responsible for maintaining
182 093bc2cd Avi Kivity
 * sorting order.
183 093bc2cd Avi Kivity
 */
184 093bc2cd Avi Kivity
static void flatview_insert(FlatView *view, unsigned pos, FlatRange *range)
185 093bc2cd Avi Kivity
{
186 093bc2cd Avi Kivity
    if (view->nr == view->nr_allocated) {
187 093bc2cd Avi Kivity
        view->nr_allocated = MAX(2 * view->nr, 10);
188 7267c094 Anthony Liguori
        view->ranges = g_realloc(view->ranges,
189 093bc2cd Avi Kivity
                                    view->nr_allocated * sizeof(*view->ranges));
190 093bc2cd Avi Kivity
    }
191 093bc2cd Avi Kivity
    memmove(view->ranges + pos + 1, view->ranges + pos,
192 093bc2cd Avi Kivity
            (view->nr - pos) * sizeof(FlatRange));
193 093bc2cd Avi Kivity
    view->ranges[pos] = *range;
194 093bc2cd Avi Kivity
    ++view->nr;
195 093bc2cd Avi Kivity
}
196 093bc2cd Avi Kivity
197 093bc2cd Avi Kivity
static void flatview_destroy(FlatView *view)
198 093bc2cd Avi Kivity
{
199 7267c094 Anthony Liguori
    g_free(view->ranges);
200 093bc2cd Avi Kivity
}
201 093bc2cd Avi Kivity
202 3d8e6bf9 Avi Kivity
static bool can_merge(FlatRange *r1, FlatRange *r2)
203 3d8e6bf9 Avi Kivity
{
204 3d8e6bf9 Avi Kivity
    return addrrange_end(r1->addr) == r2->addr.start
205 3d8e6bf9 Avi Kivity
        && r1->mr == r2->mr
206 3d8e6bf9 Avi Kivity
        && r1->offset_in_region + r1->addr.size == r2->offset_in_region
207 d0a9b5bc Avi Kivity
        && r1->dirty_log_mask == r2->dirty_log_mask
208 fb1cd6f9 Avi Kivity
        && r1->readable == r2->readable
209 fb1cd6f9 Avi Kivity
        && r1->readonly == r2->readonly;
210 3d8e6bf9 Avi Kivity
}
211 3d8e6bf9 Avi Kivity
212 3d8e6bf9 Avi Kivity
/* Attempt to simplify a view by merging ajacent ranges */
213 3d8e6bf9 Avi Kivity
static void flatview_simplify(FlatView *view)
214 3d8e6bf9 Avi Kivity
{
215 3d8e6bf9 Avi Kivity
    unsigned i, j;
216 3d8e6bf9 Avi Kivity
217 3d8e6bf9 Avi Kivity
    i = 0;
218 3d8e6bf9 Avi Kivity
    while (i < view->nr) {
219 3d8e6bf9 Avi Kivity
        j = i + 1;
220 3d8e6bf9 Avi Kivity
        while (j < view->nr
221 3d8e6bf9 Avi Kivity
               && can_merge(&view->ranges[j-1], &view->ranges[j])) {
222 3d8e6bf9 Avi Kivity
            view->ranges[i].addr.size += view->ranges[j].addr.size;
223 3d8e6bf9 Avi Kivity
            ++j;
224 3d8e6bf9 Avi Kivity
        }
225 3d8e6bf9 Avi Kivity
        ++i;
226 3d8e6bf9 Avi Kivity
        memmove(&view->ranges[i], &view->ranges[j],
227 3d8e6bf9 Avi Kivity
                (view->nr - j) * sizeof(view->ranges[j]));
228 3d8e6bf9 Avi Kivity
        view->nr -= j - i;
229 3d8e6bf9 Avi Kivity
    }
230 3d8e6bf9 Avi Kivity
}
231 3d8e6bf9 Avi Kivity
232 164a4dcd Avi Kivity
static void memory_region_read_accessor(void *opaque,
233 164a4dcd Avi Kivity
                                        target_phys_addr_t addr,
234 164a4dcd Avi Kivity
                                        uint64_t *value,
235 164a4dcd Avi Kivity
                                        unsigned size,
236 164a4dcd Avi Kivity
                                        unsigned shift,
237 164a4dcd Avi Kivity
                                        uint64_t mask)
238 164a4dcd Avi Kivity
{
239 164a4dcd Avi Kivity
    MemoryRegion *mr = opaque;
240 164a4dcd Avi Kivity
    uint64_t tmp;
241 164a4dcd Avi Kivity
242 164a4dcd Avi Kivity
    tmp = mr->ops->read(mr->opaque, addr, size);
243 164a4dcd Avi Kivity
    *value |= (tmp & mask) << shift;
244 164a4dcd Avi Kivity
}
245 164a4dcd Avi Kivity
246 164a4dcd Avi Kivity
static void memory_region_write_accessor(void *opaque,
247 164a4dcd Avi Kivity
                                         target_phys_addr_t addr,
248 164a4dcd Avi Kivity
                                         uint64_t *value,
249 164a4dcd Avi Kivity
                                         unsigned size,
250 164a4dcd Avi Kivity
                                         unsigned shift,
251 164a4dcd Avi Kivity
                                         uint64_t mask)
252 164a4dcd Avi Kivity
{
253 164a4dcd Avi Kivity
    MemoryRegion *mr = opaque;
254 164a4dcd Avi Kivity
    uint64_t tmp;
255 164a4dcd Avi Kivity
256 164a4dcd Avi Kivity
    tmp = (*value >> shift) & mask;
257 164a4dcd Avi Kivity
    mr->ops->write(mr->opaque, addr, tmp, size);
258 164a4dcd Avi Kivity
}
259 164a4dcd Avi Kivity
260 164a4dcd Avi Kivity
static void access_with_adjusted_size(target_phys_addr_t addr,
261 164a4dcd Avi Kivity
                                      uint64_t *value,
262 164a4dcd Avi Kivity
                                      unsigned size,
263 164a4dcd Avi Kivity
                                      unsigned access_size_min,
264 164a4dcd Avi Kivity
                                      unsigned access_size_max,
265 164a4dcd Avi Kivity
                                      void (*access)(void *opaque,
266 164a4dcd Avi Kivity
                                                     target_phys_addr_t addr,
267 164a4dcd Avi Kivity
                                                     uint64_t *value,
268 164a4dcd Avi Kivity
                                                     unsigned size,
269 164a4dcd Avi Kivity
                                                     unsigned shift,
270 164a4dcd Avi Kivity
                                                     uint64_t mask),
271 164a4dcd Avi Kivity
                                      void *opaque)
272 164a4dcd Avi Kivity
{
273 164a4dcd Avi Kivity
    uint64_t access_mask;
274 164a4dcd Avi Kivity
    unsigned access_size;
275 164a4dcd Avi Kivity
    unsigned i;
276 164a4dcd Avi Kivity
277 164a4dcd Avi Kivity
    if (!access_size_min) {
278 164a4dcd Avi Kivity
        access_size_min = 1;
279 164a4dcd Avi Kivity
    }
280 164a4dcd Avi Kivity
    if (!access_size_max) {
281 164a4dcd Avi Kivity
        access_size_max = 4;
282 164a4dcd Avi Kivity
    }
283 164a4dcd Avi Kivity
    access_size = MAX(MIN(size, access_size_max), access_size_min);
284 164a4dcd Avi Kivity
    access_mask = -1ULL >> (64 - access_size * 8);
285 164a4dcd Avi Kivity
    for (i = 0; i < size; i += access_size) {
286 164a4dcd Avi Kivity
        /* FIXME: big-endian support */
287 164a4dcd Avi Kivity
        access(opaque, addr + i, value, access_size, i * 8, access_mask);
288 164a4dcd Avi Kivity
    }
289 164a4dcd Avi Kivity
}
290 164a4dcd Avi Kivity
291 16ef61c9 Avi Kivity
static void memory_region_prepare_ram_addr(MemoryRegion *mr);
292 16ef61c9 Avi Kivity
293 cc31e6e7 Avi Kivity
static void as_memory_range_add(AddressSpace *as, FlatRange *fr)
294 cc31e6e7 Avi Kivity
{
295 cc31e6e7 Avi Kivity
    ram_addr_t phys_offset, region_offset;
296 cc31e6e7 Avi Kivity
297 16ef61c9 Avi Kivity
    memory_region_prepare_ram_addr(fr->mr);
298 16ef61c9 Avi Kivity
299 cc31e6e7 Avi Kivity
    phys_offset = fr->mr->ram_addr;
300 cc31e6e7 Avi Kivity
    region_offset = fr->offset_in_region;
301 cc31e6e7 Avi Kivity
    /* cpu_register_physical_memory_log() wants region_offset for
302 cc31e6e7 Avi Kivity
     * mmio, but prefers offseting phys_offset for RAM.  Humour it.
303 cc31e6e7 Avi Kivity
     */
304 cc31e6e7 Avi Kivity
    if ((phys_offset & ~TARGET_PAGE_MASK) <= IO_MEM_ROM) {
305 cc31e6e7 Avi Kivity
        phys_offset += region_offset;
306 cc31e6e7 Avi Kivity
        region_offset = 0;
307 cc31e6e7 Avi Kivity
    }
308 cc31e6e7 Avi Kivity
309 d0a9b5bc Avi Kivity
    if (!fr->readable) {
310 b5fe14cc Avi Kivity
        phys_offset &= ~TARGET_PAGE_MASK & ~IO_MEM_ROMD;
311 d0a9b5bc Avi Kivity
    }
312 d0a9b5bc Avi Kivity
313 fb1cd6f9 Avi Kivity
    if (fr->readonly) {
314 fb1cd6f9 Avi Kivity
        phys_offset |= IO_MEM_ROM;
315 fb1cd6f9 Avi Kivity
    }
316 fb1cd6f9 Avi Kivity
317 cc31e6e7 Avi Kivity
    cpu_register_physical_memory_log(fr->addr.start,
318 cc31e6e7 Avi Kivity
                                     fr->addr.size,
319 cc31e6e7 Avi Kivity
                                     phys_offset,
320 cc31e6e7 Avi Kivity
                                     region_offset,
321 cc31e6e7 Avi Kivity
                                     fr->dirty_log_mask);
322 cc31e6e7 Avi Kivity
}
323 cc31e6e7 Avi Kivity
324 cc31e6e7 Avi Kivity
static void as_memory_range_del(AddressSpace *as, FlatRange *fr)
325 cc31e6e7 Avi Kivity
{
326 39b796f2 Avi Kivity
    if (fr->dirty_log_mask) {
327 39b796f2 Avi Kivity
        cpu_physical_sync_dirty_bitmap(fr->addr.start,
328 39b796f2 Avi Kivity
                                       fr->addr.start + fr->addr.size);
329 39b796f2 Avi Kivity
    }
330 cc31e6e7 Avi Kivity
    cpu_register_physical_memory(fr->addr.start, fr->addr.size,
331 cc31e6e7 Avi Kivity
                                 IO_MEM_UNASSIGNED);
332 cc31e6e7 Avi Kivity
}
333 cc31e6e7 Avi Kivity
334 cc31e6e7 Avi Kivity
static void as_memory_log_start(AddressSpace *as, FlatRange *fr)
335 cc31e6e7 Avi Kivity
{
336 cc31e6e7 Avi Kivity
    cpu_physical_log_start(fr->addr.start, fr->addr.size);
337 cc31e6e7 Avi Kivity
}
338 cc31e6e7 Avi Kivity
339 cc31e6e7 Avi Kivity
static void as_memory_log_stop(AddressSpace *as, FlatRange *fr)
340 cc31e6e7 Avi Kivity
{
341 cc31e6e7 Avi Kivity
    cpu_physical_log_stop(fr->addr.start, fr->addr.size);
342 cc31e6e7 Avi Kivity
}
343 cc31e6e7 Avi Kivity
344 3e9d69e7 Avi Kivity
static void as_memory_ioeventfd_add(AddressSpace *as, MemoryRegionIoeventfd *fd)
345 3e9d69e7 Avi Kivity
{
346 3e9d69e7 Avi Kivity
    int r;
347 3e9d69e7 Avi Kivity
348 3e9d69e7 Avi Kivity
    assert(fd->match_data && fd->addr.size == 4);
349 3e9d69e7 Avi Kivity
350 3e9d69e7 Avi Kivity
    r = kvm_set_ioeventfd_mmio_long(fd->fd, fd->addr.start, fd->data, true);
351 3e9d69e7 Avi Kivity
    if (r < 0) {
352 3e9d69e7 Avi Kivity
        abort();
353 3e9d69e7 Avi Kivity
    }
354 3e9d69e7 Avi Kivity
}
355 3e9d69e7 Avi Kivity
356 3e9d69e7 Avi Kivity
static void as_memory_ioeventfd_del(AddressSpace *as, MemoryRegionIoeventfd *fd)
357 3e9d69e7 Avi Kivity
{
358 3e9d69e7 Avi Kivity
    int r;
359 3e9d69e7 Avi Kivity
360 3e9d69e7 Avi Kivity
    r = kvm_set_ioeventfd_mmio_long(fd->fd, fd->addr.start, fd->data, false);
361 3e9d69e7 Avi Kivity
    if (r < 0) {
362 3e9d69e7 Avi Kivity
        abort();
363 3e9d69e7 Avi Kivity
    }
364 3e9d69e7 Avi Kivity
}
365 3e9d69e7 Avi Kivity
366 cc31e6e7 Avi Kivity
static const AddressSpaceOps address_space_ops_memory = {
367 cc31e6e7 Avi Kivity
    .range_add = as_memory_range_add,
368 cc31e6e7 Avi Kivity
    .range_del = as_memory_range_del,
369 cc31e6e7 Avi Kivity
    .log_start = as_memory_log_start,
370 cc31e6e7 Avi Kivity
    .log_stop = as_memory_log_stop,
371 3e9d69e7 Avi Kivity
    .ioeventfd_add = as_memory_ioeventfd_add,
372 3e9d69e7 Avi Kivity
    .ioeventfd_del = as_memory_ioeventfd_del,
373 cc31e6e7 Avi Kivity
};
374 cc31e6e7 Avi Kivity
375 cc31e6e7 Avi Kivity
static AddressSpace address_space_memory = {
376 cc31e6e7 Avi Kivity
    .ops = &address_space_ops_memory,
377 cc31e6e7 Avi Kivity
};
378 cc31e6e7 Avi Kivity
379 627a0e90 Avi Kivity
static const MemoryRegionPortio *find_portio(MemoryRegion *mr, uint64_t offset,
380 627a0e90 Avi Kivity
                                             unsigned width, bool write)
381 627a0e90 Avi Kivity
{
382 627a0e90 Avi Kivity
    const MemoryRegionPortio *mrp;
383 627a0e90 Avi Kivity
384 627a0e90 Avi Kivity
    for (mrp = mr->ops->old_portio; mrp->size; ++mrp) {
385 627a0e90 Avi Kivity
        if (offset >= mrp->offset && offset < mrp->offset + mrp->len
386 627a0e90 Avi Kivity
            && width == mrp->size
387 627a0e90 Avi Kivity
            && (write ? (bool)mrp->write : (bool)mrp->read)) {
388 627a0e90 Avi Kivity
            return mrp;
389 627a0e90 Avi Kivity
        }
390 627a0e90 Avi Kivity
    }
391 627a0e90 Avi Kivity
    return NULL;
392 627a0e90 Avi Kivity
}
393 627a0e90 Avi Kivity
394 658b2224 Avi Kivity
static void memory_region_iorange_read(IORange *iorange,
395 658b2224 Avi Kivity
                                       uint64_t offset,
396 658b2224 Avi Kivity
                                       unsigned width,
397 658b2224 Avi Kivity
                                       uint64_t *data)
398 658b2224 Avi Kivity
{
399 658b2224 Avi Kivity
    MemoryRegion *mr = container_of(iorange, MemoryRegion, iorange);
400 658b2224 Avi Kivity
401 627a0e90 Avi Kivity
    if (mr->ops->old_portio) {
402 627a0e90 Avi Kivity
        const MemoryRegionPortio *mrp = find_portio(mr, offset, width, false);
403 627a0e90 Avi Kivity
404 627a0e90 Avi Kivity
        *data = ((uint64_t)1 << (width * 8)) - 1;
405 627a0e90 Avi Kivity
        if (mrp) {
406 563ea489 Richard Henderson
            *data = mrp->read(mr->opaque, offset);
407 627a0e90 Avi Kivity
        }
408 627a0e90 Avi Kivity
        return;
409 627a0e90 Avi Kivity
    }
410 3a130f4e Avi Kivity
    *data = 0;
411 3a130f4e Avi Kivity
    access_with_adjusted_size(offset, data, width,
412 3a130f4e Avi Kivity
                              mr->ops->impl.min_access_size,
413 3a130f4e Avi Kivity
                              mr->ops->impl.max_access_size,
414 3a130f4e Avi Kivity
                              memory_region_read_accessor, mr);
415 658b2224 Avi Kivity
}
416 658b2224 Avi Kivity
417 658b2224 Avi Kivity
static void memory_region_iorange_write(IORange *iorange,
418 658b2224 Avi Kivity
                                        uint64_t offset,
419 658b2224 Avi Kivity
                                        unsigned width,
420 658b2224 Avi Kivity
                                        uint64_t data)
421 658b2224 Avi Kivity
{
422 658b2224 Avi Kivity
    MemoryRegion *mr = container_of(iorange, MemoryRegion, iorange);
423 658b2224 Avi Kivity
424 627a0e90 Avi Kivity
    if (mr->ops->old_portio) {
425 627a0e90 Avi Kivity
        const MemoryRegionPortio *mrp = find_portio(mr, offset, width, true);
426 627a0e90 Avi Kivity
427 627a0e90 Avi Kivity
        if (mrp) {
428 563ea489 Richard Henderson
            mrp->write(mr->opaque, offset, data);
429 627a0e90 Avi Kivity
        }
430 627a0e90 Avi Kivity
        return;
431 627a0e90 Avi Kivity
    }
432 3a130f4e Avi Kivity
    access_with_adjusted_size(offset, &data, width,
433 3a130f4e Avi Kivity
                              mr->ops->impl.min_access_size,
434 3a130f4e Avi Kivity
                              mr->ops->impl.max_access_size,
435 3a130f4e Avi Kivity
                              memory_region_write_accessor, mr);
436 658b2224 Avi Kivity
}
437 658b2224 Avi Kivity
438 658b2224 Avi Kivity
static const IORangeOps memory_region_iorange_ops = {
439 658b2224 Avi Kivity
    .read = memory_region_iorange_read,
440 658b2224 Avi Kivity
    .write = memory_region_iorange_write,
441 658b2224 Avi Kivity
};
442 658b2224 Avi Kivity
443 658b2224 Avi Kivity
static void as_io_range_add(AddressSpace *as, FlatRange *fr)
444 658b2224 Avi Kivity
{
445 658b2224 Avi Kivity
    iorange_init(&fr->mr->iorange, &memory_region_iorange_ops,
446 658b2224 Avi Kivity
                 fr->addr.start,fr->addr.size);
447 658b2224 Avi Kivity
    ioport_register(&fr->mr->iorange);
448 658b2224 Avi Kivity
}
449 658b2224 Avi Kivity
450 658b2224 Avi Kivity
static void as_io_range_del(AddressSpace *as, FlatRange *fr)
451 658b2224 Avi Kivity
{
452 658b2224 Avi Kivity
    isa_unassign_ioport(fr->addr.start, fr->addr.size);
453 658b2224 Avi Kivity
}
454 658b2224 Avi Kivity
455 3e9d69e7 Avi Kivity
static void as_io_ioeventfd_add(AddressSpace *as, MemoryRegionIoeventfd *fd)
456 3e9d69e7 Avi Kivity
{
457 3e9d69e7 Avi Kivity
    int r;
458 3e9d69e7 Avi Kivity
459 3e9d69e7 Avi Kivity
    assert(fd->match_data && fd->addr.size == 2);
460 3e9d69e7 Avi Kivity
461 3e9d69e7 Avi Kivity
    r = kvm_set_ioeventfd_pio_word(fd->fd, fd->addr.start, fd->data, true);
462 3e9d69e7 Avi Kivity
    if (r < 0) {
463 3e9d69e7 Avi Kivity
        abort();
464 3e9d69e7 Avi Kivity
    }
465 3e9d69e7 Avi Kivity
}
466 3e9d69e7 Avi Kivity
467 3e9d69e7 Avi Kivity
static void as_io_ioeventfd_del(AddressSpace *as, MemoryRegionIoeventfd *fd)
468 3e9d69e7 Avi Kivity
{
469 3e9d69e7 Avi Kivity
    int r;
470 3e9d69e7 Avi Kivity
471 3e9d69e7 Avi Kivity
    r = kvm_set_ioeventfd_pio_word(fd->fd, fd->addr.start, fd->data, false);
472 3e9d69e7 Avi Kivity
    if (r < 0) {
473 3e9d69e7 Avi Kivity
        abort();
474 3e9d69e7 Avi Kivity
    }
475 3e9d69e7 Avi Kivity
}
476 3e9d69e7 Avi Kivity
477 658b2224 Avi Kivity
static const AddressSpaceOps address_space_ops_io = {
478 658b2224 Avi Kivity
    .range_add = as_io_range_add,
479 658b2224 Avi Kivity
    .range_del = as_io_range_del,
480 3e9d69e7 Avi Kivity
    .ioeventfd_add = as_io_ioeventfd_add,
481 3e9d69e7 Avi Kivity
    .ioeventfd_del = as_io_ioeventfd_del,
482 658b2224 Avi Kivity
};
483 658b2224 Avi Kivity
484 658b2224 Avi Kivity
static AddressSpace address_space_io = {
485 658b2224 Avi Kivity
    .ops = &address_space_ops_io,
486 658b2224 Avi Kivity
};
487 658b2224 Avi Kivity
488 093bc2cd Avi Kivity
/* Render a memory region into the global view.  Ranges in @view obscure
489 093bc2cd Avi Kivity
 * ranges in @mr.
490 093bc2cd Avi Kivity
 */
491 093bc2cd Avi Kivity
static void render_memory_region(FlatView *view,
492 093bc2cd Avi Kivity
                                 MemoryRegion *mr,
493 093bc2cd Avi Kivity
                                 target_phys_addr_t base,
494 fb1cd6f9 Avi Kivity
                                 AddrRange clip,
495 fb1cd6f9 Avi Kivity
                                 bool readonly)
496 093bc2cd Avi Kivity
{
497 093bc2cd Avi Kivity
    MemoryRegion *subregion;
498 093bc2cd Avi Kivity
    unsigned i;
499 093bc2cd Avi Kivity
    target_phys_addr_t offset_in_region;
500 8417cebf Avi Kivity
    int64_t remain;
501 8417cebf Avi Kivity
    int64_t now;
502 093bc2cd Avi Kivity
    FlatRange fr;
503 093bc2cd Avi Kivity
    AddrRange tmp;
504 093bc2cd Avi Kivity
505 093bc2cd Avi Kivity
    base += mr->addr;
506 fb1cd6f9 Avi Kivity
    readonly |= mr->readonly;
507 093bc2cd Avi Kivity
508 093bc2cd Avi Kivity
    tmp = addrrange_make(base, mr->size);
509 093bc2cd Avi Kivity
510 093bc2cd Avi Kivity
    if (!addrrange_intersects(tmp, clip)) {
511 093bc2cd Avi Kivity
        return;
512 093bc2cd Avi Kivity
    }
513 093bc2cd Avi Kivity
514 093bc2cd Avi Kivity
    clip = addrrange_intersection(tmp, clip);
515 093bc2cd Avi Kivity
516 093bc2cd Avi Kivity
    if (mr->alias) {
517 093bc2cd Avi Kivity
        base -= mr->alias->addr;
518 093bc2cd Avi Kivity
        base -= mr->alias_offset;
519 fb1cd6f9 Avi Kivity
        render_memory_region(view, mr->alias, base, clip, readonly);
520 093bc2cd Avi Kivity
        return;
521 093bc2cd Avi Kivity
    }
522 093bc2cd Avi Kivity
523 093bc2cd Avi Kivity
    /* Render subregions in priority order. */
524 093bc2cd Avi Kivity
    QTAILQ_FOREACH(subregion, &mr->subregions, subregions_link) {
525 fb1cd6f9 Avi Kivity
        render_memory_region(view, subregion, base, clip, readonly);
526 093bc2cd Avi Kivity
    }
527 093bc2cd Avi Kivity
528 14a3c10a Avi Kivity
    if (!mr->terminates) {
529 093bc2cd Avi Kivity
        return;
530 093bc2cd Avi Kivity
    }
531 093bc2cd Avi Kivity
532 093bc2cd Avi Kivity
    offset_in_region = clip.start - base;
533 093bc2cd Avi Kivity
    base = clip.start;
534 093bc2cd Avi Kivity
    remain = clip.size;
535 093bc2cd Avi Kivity
536 093bc2cd Avi Kivity
    /* Render the region itself into any gaps left by the current view. */
537 093bc2cd Avi Kivity
    for (i = 0; i < view->nr && remain; ++i) {
538 093bc2cd Avi Kivity
        if (base >= addrrange_end(view->ranges[i].addr)) {
539 093bc2cd Avi Kivity
            continue;
540 093bc2cd Avi Kivity
        }
541 093bc2cd Avi Kivity
        if (base < view->ranges[i].addr.start) {
542 093bc2cd Avi Kivity
            now = MIN(remain, view->ranges[i].addr.start - base);
543 093bc2cd Avi Kivity
            fr.mr = mr;
544 093bc2cd Avi Kivity
            fr.offset_in_region = offset_in_region;
545 093bc2cd Avi Kivity
            fr.addr = addrrange_make(base, now);
546 5a583347 Avi Kivity
            fr.dirty_log_mask = mr->dirty_log_mask;
547 d0a9b5bc Avi Kivity
            fr.readable = mr->readable;
548 fb1cd6f9 Avi Kivity
            fr.readonly = readonly;
549 093bc2cd Avi Kivity
            flatview_insert(view, i, &fr);
550 093bc2cd Avi Kivity
            ++i;
551 093bc2cd Avi Kivity
            base += now;
552 093bc2cd Avi Kivity
            offset_in_region += now;
553 093bc2cd Avi Kivity
            remain -= now;
554 093bc2cd Avi Kivity
        }
555 093bc2cd Avi Kivity
        if (base == view->ranges[i].addr.start) {
556 093bc2cd Avi Kivity
            now = MIN(remain, view->ranges[i].addr.size);
557 093bc2cd Avi Kivity
            base += now;
558 093bc2cd Avi Kivity
            offset_in_region += now;
559 093bc2cd Avi Kivity
            remain -= now;
560 093bc2cd Avi Kivity
        }
561 093bc2cd Avi Kivity
    }
562 093bc2cd Avi Kivity
    if (remain) {
563 093bc2cd Avi Kivity
        fr.mr = mr;
564 093bc2cd Avi Kivity
        fr.offset_in_region = offset_in_region;
565 093bc2cd Avi Kivity
        fr.addr = addrrange_make(base, remain);
566 5a583347 Avi Kivity
        fr.dirty_log_mask = mr->dirty_log_mask;
567 d0a9b5bc Avi Kivity
        fr.readable = mr->readable;
568 fb1cd6f9 Avi Kivity
        fr.readonly = readonly;
569 093bc2cd Avi Kivity
        flatview_insert(view, i, &fr);
570 093bc2cd Avi Kivity
    }
571 093bc2cd Avi Kivity
}
572 093bc2cd Avi Kivity
573 093bc2cd Avi Kivity
/* Render a memory topology into a list of disjoint absolute ranges. */
574 093bc2cd Avi Kivity
static FlatView generate_memory_topology(MemoryRegion *mr)
575 093bc2cd Avi Kivity
{
576 093bc2cd Avi Kivity
    FlatView view;
577 093bc2cd Avi Kivity
578 093bc2cd Avi Kivity
    flatview_init(&view);
579 093bc2cd Avi Kivity
580 fb1cd6f9 Avi Kivity
    render_memory_region(&view, mr, 0, addrrange_make(0, INT64_MAX), false);
581 3d8e6bf9 Avi Kivity
    flatview_simplify(&view);
582 093bc2cd Avi Kivity
583 093bc2cd Avi Kivity
    return view;
584 093bc2cd Avi Kivity
}
585 093bc2cd Avi Kivity
586 3e9d69e7 Avi Kivity
static void address_space_add_del_ioeventfds(AddressSpace *as,
587 3e9d69e7 Avi Kivity
                                             MemoryRegionIoeventfd *fds_new,
588 3e9d69e7 Avi Kivity
                                             unsigned fds_new_nb,
589 3e9d69e7 Avi Kivity
                                             MemoryRegionIoeventfd *fds_old,
590 3e9d69e7 Avi Kivity
                                             unsigned fds_old_nb)
591 3e9d69e7 Avi Kivity
{
592 3e9d69e7 Avi Kivity
    unsigned iold, inew;
593 3e9d69e7 Avi Kivity
594 3e9d69e7 Avi Kivity
    /* Generate a symmetric difference of the old and new fd sets, adding
595 3e9d69e7 Avi Kivity
     * and deleting as necessary.
596 3e9d69e7 Avi Kivity
     */
597 3e9d69e7 Avi Kivity
598 3e9d69e7 Avi Kivity
    iold = inew = 0;
599 3e9d69e7 Avi Kivity
    while (iold < fds_old_nb || inew < fds_new_nb) {
600 3e9d69e7 Avi Kivity
        if (iold < fds_old_nb
601 3e9d69e7 Avi Kivity
            && (inew == fds_new_nb
602 3e9d69e7 Avi Kivity
                || memory_region_ioeventfd_before(fds_old[iold],
603 3e9d69e7 Avi Kivity
                                                  fds_new[inew]))) {
604 3e9d69e7 Avi Kivity
            as->ops->ioeventfd_del(as, &fds_old[iold]);
605 3e9d69e7 Avi Kivity
            ++iold;
606 3e9d69e7 Avi Kivity
        } else if (inew < fds_new_nb
607 3e9d69e7 Avi Kivity
                   && (iold == fds_old_nb
608 3e9d69e7 Avi Kivity
                       || memory_region_ioeventfd_before(fds_new[inew],
609 3e9d69e7 Avi Kivity
                                                         fds_old[iold]))) {
610 3e9d69e7 Avi Kivity
            as->ops->ioeventfd_add(as, &fds_new[inew]);
611 3e9d69e7 Avi Kivity
            ++inew;
612 3e9d69e7 Avi Kivity
        } else {
613 3e9d69e7 Avi Kivity
            ++iold;
614 3e9d69e7 Avi Kivity
            ++inew;
615 3e9d69e7 Avi Kivity
        }
616 3e9d69e7 Avi Kivity
    }
617 3e9d69e7 Avi Kivity
}
618 3e9d69e7 Avi Kivity
619 3e9d69e7 Avi Kivity
static void address_space_update_ioeventfds(AddressSpace *as)
620 3e9d69e7 Avi Kivity
{
621 3e9d69e7 Avi Kivity
    FlatRange *fr;
622 3e9d69e7 Avi Kivity
    unsigned ioeventfd_nb = 0;
623 3e9d69e7 Avi Kivity
    MemoryRegionIoeventfd *ioeventfds = NULL;
624 3e9d69e7 Avi Kivity
    AddrRange tmp;
625 3e9d69e7 Avi Kivity
    unsigned i;
626 3e9d69e7 Avi Kivity
627 3e9d69e7 Avi Kivity
    FOR_EACH_FLAT_RANGE(fr, &as->current_map) {
628 3e9d69e7 Avi Kivity
        for (i = 0; i < fr->mr->ioeventfd_nb; ++i) {
629 3e9d69e7 Avi Kivity
            tmp = addrrange_shift(fr->mr->ioeventfds[i].addr,
630 3e9d69e7 Avi Kivity
                                  fr->addr.start - fr->offset_in_region);
631 3e9d69e7 Avi Kivity
            if (addrrange_intersects(fr->addr, tmp)) {
632 3e9d69e7 Avi Kivity
                ++ioeventfd_nb;
633 7267c094 Anthony Liguori
                ioeventfds = g_realloc(ioeventfds,
634 3e9d69e7 Avi Kivity
                                          ioeventfd_nb * sizeof(*ioeventfds));
635 3e9d69e7 Avi Kivity
                ioeventfds[ioeventfd_nb-1] = fr->mr->ioeventfds[i];
636 3e9d69e7 Avi Kivity
                ioeventfds[ioeventfd_nb-1].addr = tmp;
637 3e9d69e7 Avi Kivity
            }
638 3e9d69e7 Avi Kivity
        }
639 3e9d69e7 Avi Kivity
    }
640 3e9d69e7 Avi Kivity
641 3e9d69e7 Avi Kivity
    address_space_add_del_ioeventfds(as, ioeventfds, ioeventfd_nb,
642 3e9d69e7 Avi Kivity
                                     as->ioeventfds, as->ioeventfd_nb);
643 3e9d69e7 Avi Kivity
644 7267c094 Anthony Liguori
    g_free(as->ioeventfds);
645 3e9d69e7 Avi Kivity
    as->ioeventfds = ioeventfds;
646 3e9d69e7 Avi Kivity
    as->ioeventfd_nb = ioeventfd_nb;
647 3e9d69e7 Avi Kivity
}
648 3e9d69e7 Avi Kivity
649 b8af1afb Avi Kivity
static void address_space_update_topology_pass(AddressSpace *as,
650 b8af1afb Avi Kivity
                                               FlatView old_view,
651 b8af1afb Avi Kivity
                                               FlatView new_view,
652 b8af1afb Avi Kivity
                                               bool adding)
653 093bc2cd Avi Kivity
{
654 093bc2cd Avi Kivity
    unsigned iold, inew;
655 093bc2cd Avi Kivity
    FlatRange *frold, *frnew;
656 093bc2cd Avi Kivity
657 093bc2cd Avi Kivity
    /* Generate a symmetric difference of the old and new memory maps.
658 093bc2cd Avi Kivity
     * Kill ranges in the old map, and instantiate ranges in the new map.
659 093bc2cd Avi Kivity
     */
660 093bc2cd Avi Kivity
    iold = inew = 0;
661 093bc2cd Avi Kivity
    while (iold < old_view.nr || inew < new_view.nr) {
662 093bc2cd Avi Kivity
        if (iold < old_view.nr) {
663 093bc2cd Avi Kivity
            frold = &old_view.ranges[iold];
664 093bc2cd Avi Kivity
        } else {
665 093bc2cd Avi Kivity
            frold = NULL;
666 093bc2cd Avi Kivity
        }
667 093bc2cd Avi Kivity
        if (inew < new_view.nr) {
668 093bc2cd Avi Kivity
            frnew = &new_view.ranges[inew];
669 093bc2cd Avi Kivity
        } else {
670 093bc2cd Avi Kivity
            frnew = NULL;
671 093bc2cd Avi Kivity
        }
672 093bc2cd Avi Kivity
673 093bc2cd Avi Kivity
        if (frold
674 093bc2cd Avi Kivity
            && (!frnew
675 093bc2cd Avi Kivity
                || frold->addr.start < frnew->addr.start
676 093bc2cd Avi Kivity
                || (frold->addr.start == frnew->addr.start
677 093bc2cd Avi Kivity
                    && !flatrange_equal(frold, frnew)))) {
678 093bc2cd Avi Kivity
            /* In old, but (not in new, or in new but attributes changed). */
679 093bc2cd Avi Kivity
680 b8af1afb Avi Kivity
            if (!adding) {
681 b8af1afb Avi Kivity
                as->ops->range_del(as, frold);
682 b8af1afb Avi Kivity
            }
683 b8af1afb Avi Kivity
684 093bc2cd Avi Kivity
            ++iold;
685 093bc2cd Avi Kivity
        } else if (frold && frnew && flatrange_equal(frold, frnew)) {
686 093bc2cd Avi Kivity
            /* In both (logging may have changed) */
687 093bc2cd Avi Kivity
688 b8af1afb Avi Kivity
            if (adding) {
689 b8af1afb Avi Kivity
                if (frold->dirty_log_mask && !frnew->dirty_log_mask) {
690 b8af1afb Avi Kivity
                    as->ops->log_stop(as, frnew);
691 b8af1afb Avi Kivity
                } else if (frnew->dirty_log_mask && !frold->dirty_log_mask) {
692 b8af1afb Avi Kivity
                    as->ops->log_start(as, frnew);
693 b8af1afb Avi Kivity
                }
694 5a583347 Avi Kivity
            }
695 5a583347 Avi Kivity
696 093bc2cd Avi Kivity
            ++iold;
697 093bc2cd Avi Kivity
            ++inew;
698 093bc2cd Avi Kivity
        } else {
699 093bc2cd Avi Kivity
            /* In new */
700 093bc2cd Avi Kivity
701 b8af1afb Avi Kivity
            if (adding) {
702 b8af1afb Avi Kivity
                as->ops->range_add(as, frnew);
703 b8af1afb Avi Kivity
            }
704 b8af1afb Avi Kivity
705 093bc2cd Avi Kivity
            ++inew;
706 093bc2cd Avi Kivity
        }
707 093bc2cd Avi Kivity
    }
708 b8af1afb Avi Kivity
}
709 b8af1afb Avi Kivity
710 b8af1afb Avi Kivity
711 b8af1afb Avi Kivity
static void address_space_update_topology(AddressSpace *as)
712 b8af1afb Avi Kivity
{
713 b8af1afb Avi Kivity
    FlatView old_view = as->current_map;
714 b8af1afb Avi Kivity
    FlatView new_view = generate_memory_topology(as->root);
715 b8af1afb Avi Kivity
716 b8af1afb Avi Kivity
    address_space_update_topology_pass(as, old_view, new_view, false);
717 b8af1afb Avi Kivity
    address_space_update_topology_pass(as, old_view, new_view, true);
718 b8af1afb Avi Kivity
719 cc31e6e7 Avi Kivity
    as->current_map = new_view;
720 093bc2cd Avi Kivity
    flatview_destroy(&old_view);
721 3e9d69e7 Avi Kivity
    address_space_update_ioeventfds(as);
722 093bc2cd Avi Kivity
}
723 093bc2cd Avi Kivity
724 cc31e6e7 Avi Kivity
static void memory_region_update_topology(void)
725 cc31e6e7 Avi Kivity
{
726 4ef4db86 Avi Kivity
    if (memory_region_transaction_depth) {
727 4ef4db86 Avi Kivity
        return;
728 4ef4db86 Avi Kivity
    }
729 4ef4db86 Avi Kivity
730 658b2224 Avi Kivity
    if (address_space_memory.root) {
731 658b2224 Avi Kivity
        address_space_update_topology(&address_space_memory);
732 658b2224 Avi Kivity
    }
733 658b2224 Avi Kivity
    if (address_space_io.root) {
734 658b2224 Avi Kivity
        address_space_update_topology(&address_space_io);
735 658b2224 Avi Kivity
    }
736 cc31e6e7 Avi Kivity
}
737 cc31e6e7 Avi Kivity
738 4ef4db86 Avi Kivity
void memory_region_transaction_begin(void)
739 4ef4db86 Avi Kivity
{
740 4ef4db86 Avi Kivity
    ++memory_region_transaction_depth;
741 4ef4db86 Avi Kivity
}
742 4ef4db86 Avi Kivity
743 4ef4db86 Avi Kivity
void memory_region_transaction_commit(void)
744 4ef4db86 Avi Kivity
{
745 4ef4db86 Avi Kivity
    assert(memory_region_transaction_depth);
746 4ef4db86 Avi Kivity
    --memory_region_transaction_depth;
747 4ef4db86 Avi Kivity
    memory_region_update_topology();
748 4ef4db86 Avi Kivity
}
749 4ef4db86 Avi Kivity
750 545e92e0 Avi Kivity
static void memory_region_destructor_none(MemoryRegion *mr)
751 545e92e0 Avi Kivity
{
752 545e92e0 Avi Kivity
}
753 545e92e0 Avi Kivity
754 545e92e0 Avi Kivity
static void memory_region_destructor_ram(MemoryRegion *mr)
755 545e92e0 Avi Kivity
{
756 545e92e0 Avi Kivity
    qemu_ram_free(mr->ram_addr);
757 545e92e0 Avi Kivity
}
758 545e92e0 Avi Kivity
759 545e92e0 Avi Kivity
static void memory_region_destructor_ram_from_ptr(MemoryRegion *mr)
760 545e92e0 Avi Kivity
{
761 545e92e0 Avi Kivity
    qemu_ram_free_from_ptr(mr->ram_addr);
762 545e92e0 Avi Kivity
}
763 545e92e0 Avi Kivity
764 545e92e0 Avi Kivity
static void memory_region_destructor_iomem(MemoryRegion *mr)
765 545e92e0 Avi Kivity
{
766 545e92e0 Avi Kivity
    cpu_unregister_io_memory(mr->ram_addr);
767 545e92e0 Avi Kivity
}
768 545e92e0 Avi Kivity
769 d0a9b5bc Avi Kivity
static void memory_region_destructor_rom_device(MemoryRegion *mr)
770 d0a9b5bc Avi Kivity
{
771 d0a9b5bc Avi Kivity
    qemu_ram_free(mr->ram_addr & TARGET_PAGE_MASK);
772 d0a9b5bc Avi Kivity
    cpu_unregister_io_memory(mr->ram_addr & ~(TARGET_PAGE_MASK | IO_MEM_ROMD));
773 d0a9b5bc Avi Kivity
}
774 d0a9b5bc Avi Kivity
775 093bc2cd Avi Kivity
void memory_region_init(MemoryRegion *mr,
776 093bc2cd Avi Kivity
                        const char *name,
777 093bc2cd Avi Kivity
                        uint64_t size)
778 093bc2cd Avi Kivity
{
779 093bc2cd Avi Kivity
    mr->ops = NULL;
780 093bc2cd Avi Kivity
    mr->parent = NULL;
781 093bc2cd Avi Kivity
    mr->size = size;
782 093bc2cd Avi Kivity
    mr->addr = 0;
783 093bc2cd Avi Kivity
    mr->offset = 0;
784 14a3c10a Avi Kivity
    mr->terminates = false;
785 d0a9b5bc Avi Kivity
    mr->readable = true;
786 fb1cd6f9 Avi Kivity
    mr->readonly = false;
787 545e92e0 Avi Kivity
    mr->destructor = memory_region_destructor_none;
788 093bc2cd Avi Kivity
    mr->priority = 0;
789 093bc2cd Avi Kivity
    mr->may_overlap = false;
790 093bc2cd Avi Kivity
    mr->alias = NULL;
791 093bc2cd Avi Kivity
    QTAILQ_INIT(&mr->subregions);
792 093bc2cd Avi Kivity
    memset(&mr->subregions_link, 0, sizeof mr->subregions_link);
793 093bc2cd Avi Kivity
    QTAILQ_INIT(&mr->coalesced);
794 7267c094 Anthony Liguori
    mr->name = g_strdup(name);
795 5a583347 Avi Kivity
    mr->dirty_log_mask = 0;
796 3e9d69e7 Avi Kivity
    mr->ioeventfd_nb = 0;
797 3e9d69e7 Avi Kivity
    mr->ioeventfds = NULL;
798 093bc2cd Avi Kivity
}
799 093bc2cd Avi Kivity
800 093bc2cd Avi Kivity
static bool memory_region_access_valid(MemoryRegion *mr,
801 093bc2cd Avi Kivity
                                       target_phys_addr_t addr,
802 093bc2cd Avi Kivity
                                       unsigned size)
803 093bc2cd Avi Kivity
{
804 093bc2cd Avi Kivity
    if (!mr->ops->valid.unaligned && (addr & (size - 1))) {
805 093bc2cd Avi Kivity
        return false;
806 093bc2cd Avi Kivity
    }
807 093bc2cd Avi Kivity
808 093bc2cd Avi Kivity
    /* Treat zero as compatibility all valid */
809 093bc2cd Avi Kivity
    if (!mr->ops->valid.max_access_size) {
810 093bc2cd Avi Kivity
        return true;
811 093bc2cd Avi Kivity
    }
812 093bc2cd Avi Kivity
813 093bc2cd Avi Kivity
    if (size > mr->ops->valid.max_access_size
814 093bc2cd Avi Kivity
        || size < mr->ops->valid.min_access_size) {
815 093bc2cd Avi Kivity
        return false;
816 093bc2cd Avi Kivity
    }
817 093bc2cd Avi Kivity
    return true;
818 093bc2cd Avi Kivity
}
819 093bc2cd Avi Kivity
820 093bc2cd Avi Kivity
static uint32_t memory_region_read_thunk_n(void *_mr,
821 093bc2cd Avi Kivity
                                           target_phys_addr_t addr,
822 093bc2cd Avi Kivity
                                           unsigned size)
823 093bc2cd Avi Kivity
{
824 093bc2cd Avi Kivity
    MemoryRegion *mr = _mr;
825 164a4dcd Avi Kivity
    uint64_t data = 0;
826 093bc2cd Avi Kivity
827 093bc2cd Avi Kivity
    if (!memory_region_access_valid(mr, addr, size)) {
828 093bc2cd Avi Kivity
        return -1U; /* FIXME: better signalling */
829 093bc2cd Avi Kivity
    }
830 093bc2cd Avi Kivity
831 74901c3b Avi Kivity
    if (!mr->ops->read) {
832 74901c3b Avi Kivity
        return mr->ops->old_mmio.read[bitops_ffsl(size)](mr->opaque, addr);
833 74901c3b Avi Kivity
    }
834 74901c3b Avi Kivity
835 093bc2cd Avi Kivity
    /* FIXME: support unaligned access */
836 164a4dcd Avi Kivity
    access_with_adjusted_size(addr + mr->offset, &data, size,
837 164a4dcd Avi Kivity
                              mr->ops->impl.min_access_size,
838 164a4dcd Avi Kivity
                              mr->ops->impl.max_access_size,
839 164a4dcd Avi Kivity
                              memory_region_read_accessor, mr);
840 093bc2cd Avi Kivity
841 093bc2cd Avi Kivity
    return data;
842 093bc2cd Avi Kivity
}
843 093bc2cd Avi Kivity
844 093bc2cd Avi Kivity
static void memory_region_write_thunk_n(void *_mr,
845 093bc2cd Avi Kivity
                                        target_phys_addr_t addr,
846 093bc2cd Avi Kivity
                                        unsigned size,
847 093bc2cd Avi Kivity
                                        uint64_t data)
848 093bc2cd Avi Kivity
{
849 093bc2cd Avi Kivity
    MemoryRegion *mr = _mr;
850 093bc2cd Avi Kivity
851 093bc2cd Avi Kivity
    if (!memory_region_access_valid(mr, addr, size)) {
852 093bc2cd Avi Kivity
        return; /* FIXME: better signalling */
853 093bc2cd Avi Kivity
    }
854 093bc2cd Avi Kivity
855 74901c3b Avi Kivity
    if (!mr->ops->write) {
856 74901c3b Avi Kivity
        mr->ops->old_mmio.write[bitops_ffsl(size)](mr->opaque, addr, data);
857 74901c3b Avi Kivity
        return;
858 74901c3b Avi Kivity
    }
859 74901c3b Avi Kivity
860 093bc2cd Avi Kivity
    /* FIXME: support unaligned access */
861 164a4dcd Avi Kivity
    access_with_adjusted_size(addr + mr->offset, &data, size,
862 164a4dcd Avi Kivity
                              mr->ops->impl.min_access_size,
863 164a4dcd Avi Kivity
                              mr->ops->impl.max_access_size,
864 164a4dcd Avi Kivity
                              memory_region_write_accessor, mr);
865 093bc2cd Avi Kivity
}
866 093bc2cd Avi Kivity
867 093bc2cd Avi Kivity
static uint32_t memory_region_read_thunk_b(void *mr, target_phys_addr_t addr)
868 093bc2cd Avi Kivity
{
869 093bc2cd Avi Kivity
    return memory_region_read_thunk_n(mr, addr, 1);
870 093bc2cd Avi Kivity
}
871 093bc2cd Avi Kivity
872 093bc2cd Avi Kivity
static uint32_t memory_region_read_thunk_w(void *mr, target_phys_addr_t addr)
873 093bc2cd Avi Kivity
{
874 093bc2cd Avi Kivity
    return memory_region_read_thunk_n(mr, addr, 2);
875 093bc2cd Avi Kivity
}
876 093bc2cd Avi Kivity
877 093bc2cd Avi Kivity
static uint32_t memory_region_read_thunk_l(void *mr, target_phys_addr_t addr)
878 093bc2cd Avi Kivity
{
879 093bc2cd Avi Kivity
    return memory_region_read_thunk_n(mr, addr, 4);
880 093bc2cd Avi Kivity
}
881 093bc2cd Avi Kivity
882 093bc2cd Avi Kivity
static void memory_region_write_thunk_b(void *mr, target_phys_addr_t addr,
883 093bc2cd Avi Kivity
                                        uint32_t data)
884 093bc2cd Avi Kivity
{
885 093bc2cd Avi Kivity
    memory_region_write_thunk_n(mr, addr, 1, data);
886 093bc2cd Avi Kivity
}
887 093bc2cd Avi Kivity
888 093bc2cd Avi Kivity
static void memory_region_write_thunk_w(void *mr, target_phys_addr_t addr,
889 093bc2cd Avi Kivity
                                        uint32_t data)
890 093bc2cd Avi Kivity
{
891 093bc2cd Avi Kivity
    memory_region_write_thunk_n(mr, addr, 2, data);
892 093bc2cd Avi Kivity
}
893 093bc2cd Avi Kivity
894 093bc2cd Avi Kivity
static void memory_region_write_thunk_l(void *mr, target_phys_addr_t addr,
895 093bc2cd Avi Kivity
                                        uint32_t data)
896 093bc2cd Avi Kivity
{
897 093bc2cd Avi Kivity
    memory_region_write_thunk_n(mr, addr, 4, data);
898 093bc2cd Avi Kivity
}
899 093bc2cd Avi Kivity
900 093bc2cd Avi Kivity
static CPUReadMemoryFunc * const memory_region_read_thunk[] = {
901 093bc2cd Avi Kivity
    memory_region_read_thunk_b,
902 093bc2cd Avi Kivity
    memory_region_read_thunk_w,
903 093bc2cd Avi Kivity
    memory_region_read_thunk_l,
904 093bc2cd Avi Kivity
};
905 093bc2cd Avi Kivity
906 093bc2cd Avi Kivity
static CPUWriteMemoryFunc * const memory_region_write_thunk[] = {
907 093bc2cd Avi Kivity
    memory_region_write_thunk_b,
908 093bc2cd Avi Kivity
    memory_region_write_thunk_w,
909 093bc2cd Avi Kivity
    memory_region_write_thunk_l,
910 093bc2cd Avi Kivity
};
911 093bc2cd Avi Kivity
912 16ef61c9 Avi Kivity
static void memory_region_prepare_ram_addr(MemoryRegion *mr)
913 16ef61c9 Avi Kivity
{
914 16ef61c9 Avi Kivity
    if (mr->backend_registered) {
915 16ef61c9 Avi Kivity
        return;
916 16ef61c9 Avi Kivity
    }
917 16ef61c9 Avi Kivity
918 545e92e0 Avi Kivity
    mr->destructor = memory_region_destructor_iomem;
919 16ef61c9 Avi Kivity
    mr->ram_addr = cpu_register_io_memory(memory_region_read_thunk,
920 16ef61c9 Avi Kivity
                                          memory_region_write_thunk,
921 16ef61c9 Avi Kivity
                                          mr,
922 16ef61c9 Avi Kivity
                                          mr->ops->endianness);
923 16ef61c9 Avi Kivity
    mr->backend_registered = true;
924 16ef61c9 Avi Kivity
}
925 16ef61c9 Avi Kivity
926 093bc2cd Avi Kivity
void memory_region_init_io(MemoryRegion *mr,
927 093bc2cd Avi Kivity
                           const MemoryRegionOps *ops,
928 093bc2cd Avi Kivity
                           void *opaque,
929 093bc2cd Avi Kivity
                           const char *name,
930 093bc2cd Avi Kivity
                           uint64_t size)
931 093bc2cd Avi Kivity
{
932 093bc2cd Avi Kivity
    memory_region_init(mr, name, size);
933 093bc2cd Avi Kivity
    mr->ops = ops;
934 093bc2cd Avi Kivity
    mr->opaque = opaque;
935 14a3c10a Avi Kivity
    mr->terminates = true;
936 16ef61c9 Avi Kivity
    mr->backend_registered = false;
937 093bc2cd Avi Kivity
}
938 093bc2cd Avi Kivity
939 093bc2cd Avi Kivity
void memory_region_init_ram(MemoryRegion *mr,
940 093bc2cd Avi Kivity
                            DeviceState *dev,
941 093bc2cd Avi Kivity
                            const char *name,
942 093bc2cd Avi Kivity
                            uint64_t size)
943 093bc2cd Avi Kivity
{
944 093bc2cd Avi Kivity
    memory_region_init(mr, name, size);
945 14a3c10a Avi Kivity
    mr->terminates = true;
946 545e92e0 Avi Kivity
    mr->destructor = memory_region_destructor_ram;
947 093bc2cd Avi Kivity
    mr->ram_addr = qemu_ram_alloc(dev, name, size);
948 16ef61c9 Avi Kivity
    mr->backend_registered = true;
949 093bc2cd Avi Kivity
}
950 093bc2cd Avi Kivity
951 093bc2cd Avi Kivity
void memory_region_init_ram_ptr(MemoryRegion *mr,
952 093bc2cd Avi Kivity
                                DeviceState *dev,
953 093bc2cd Avi Kivity
                                const char *name,
954 093bc2cd Avi Kivity
                                uint64_t size,
955 093bc2cd Avi Kivity
                                void *ptr)
956 093bc2cd Avi Kivity
{
957 093bc2cd Avi Kivity
    memory_region_init(mr, name, size);
958 14a3c10a Avi Kivity
    mr->terminates = true;
959 545e92e0 Avi Kivity
    mr->destructor = memory_region_destructor_ram_from_ptr;
960 093bc2cd Avi Kivity
    mr->ram_addr = qemu_ram_alloc_from_ptr(dev, name, size, ptr);
961 16ef61c9 Avi Kivity
    mr->backend_registered = true;
962 093bc2cd Avi Kivity
}
963 093bc2cd Avi Kivity
964 093bc2cd Avi Kivity
void memory_region_init_alias(MemoryRegion *mr,
965 093bc2cd Avi Kivity
                              const char *name,
966 093bc2cd Avi Kivity
                              MemoryRegion *orig,
967 093bc2cd Avi Kivity
                              target_phys_addr_t offset,
968 093bc2cd Avi Kivity
                              uint64_t size)
969 093bc2cd Avi Kivity
{
970 093bc2cd Avi Kivity
    memory_region_init(mr, name, size);
971 093bc2cd Avi Kivity
    mr->alias = orig;
972 093bc2cd Avi Kivity
    mr->alias_offset = offset;
973 093bc2cd Avi Kivity
}
974 093bc2cd Avi Kivity
975 d0a9b5bc Avi Kivity
void memory_region_init_rom_device(MemoryRegion *mr,
976 d0a9b5bc Avi Kivity
                                   const MemoryRegionOps *ops,
977 75f5941c Avi Kivity
                                   void *opaque,
978 d0a9b5bc Avi Kivity
                                   DeviceState *dev,
979 d0a9b5bc Avi Kivity
                                   const char *name,
980 d0a9b5bc Avi Kivity
                                   uint64_t size)
981 d0a9b5bc Avi Kivity
{
982 d0a9b5bc Avi Kivity
    memory_region_init(mr, name, size);
983 7bc2b9cd Avi Kivity
    mr->ops = ops;
984 75f5941c Avi Kivity
    mr->opaque = opaque;
985 d0a9b5bc Avi Kivity
    mr->terminates = true;
986 d0a9b5bc Avi Kivity
    mr->destructor = memory_region_destructor_rom_device;
987 d0a9b5bc Avi Kivity
    mr->ram_addr = qemu_ram_alloc(dev, name, size);
988 d0a9b5bc Avi Kivity
    mr->ram_addr |= cpu_register_io_memory(memory_region_read_thunk,
989 d0a9b5bc Avi Kivity
                                           memory_region_write_thunk,
990 d0a9b5bc Avi Kivity
                                           mr,
991 d0a9b5bc Avi Kivity
                                           mr->ops->endianness);
992 d0a9b5bc Avi Kivity
    mr->ram_addr |= IO_MEM_ROMD;
993 d0a9b5bc Avi Kivity
    mr->backend_registered = true;
994 d0a9b5bc Avi Kivity
}
995 d0a9b5bc Avi Kivity
996 093bc2cd Avi Kivity
void memory_region_destroy(MemoryRegion *mr)
997 093bc2cd Avi Kivity
{
998 093bc2cd Avi Kivity
    assert(QTAILQ_EMPTY(&mr->subregions));
999 545e92e0 Avi Kivity
    mr->destructor(mr);
1000 093bc2cd Avi Kivity
    memory_region_clear_coalescing(mr);
1001 7267c094 Anthony Liguori
    g_free((char *)mr->name);
1002 7267c094 Anthony Liguori
    g_free(mr->ioeventfds);
1003 093bc2cd Avi Kivity
}
1004 093bc2cd Avi Kivity
1005 093bc2cd Avi Kivity
uint64_t memory_region_size(MemoryRegion *mr)
1006 093bc2cd Avi Kivity
{
1007 093bc2cd Avi Kivity
    return mr->size;
1008 093bc2cd Avi Kivity
}
1009 093bc2cd Avi Kivity
1010 093bc2cd Avi Kivity
void memory_region_set_offset(MemoryRegion *mr, target_phys_addr_t offset)
1011 093bc2cd Avi Kivity
{
1012 093bc2cd Avi Kivity
    mr->offset = offset;
1013 093bc2cd Avi Kivity
}
1014 093bc2cd Avi Kivity
1015 093bc2cd Avi Kivity
void memory_region_set_log(MemoryRegion *mr, bool log, unsigned client)
1016 093bc2cd Avi Kivity
{
1017 5a583347 Avi Kivity
    uint8_t mask = 1 << client;
1018 5a583347 Avi Kivity
1019 5a583347 Avi Kivity
    mr->dirty_log_mask = (mr->dirty_log_mask & ~mask) | (log * mask);
1020 5a583347 Avi Kivity
    memory_region_update_topology();
1021 093bc2cd Avi Kivity
}
1022 093bc2cd Avi Kivity
1023 093bc2cd Avi Kivity
bool memory_region_get_dirty(MemoryRegion *mr, target_phys_addr_t addr,
1024 093bc2cd Avi Kivity
                             unsigned client)
1025 093bc2cd Avi Kivity
{
1026 14a3c10a Avi Kivity
    assert(mr->terminates);
1027 5a583347 Avi Kivity
    return cpu_physical_memory_get_dirty(mr->ram_addr + addr, 1 << client);
1028 093bc2cd Avi Kivity
}
1029 093bc2cd Avi Kivity
1030 093bc2cd Avi Kivity
void memory_region_set_dirty(MemoryRegion *mr, target_phys_addr_t addr)
1031 093bc2cd Avi Kivity
{
1032 14a3c10a Avi Kivity
    assert(mr->terminates);
1033 5a583347 Avi Kivity
    return cpu_physical_memory_set_dirty(mr->ram_addr + addr);
1034 093bc2cd Avi Kivity
}
1035 093bc2cd Avi Kivity
1036 093bc2cd Avi Kivity
void memory_region_sync_dirty_bitmap(MemoryRegion *mr)
1037 093bc2cd Avi Kivity
{
1038 5a583347 Avi Kivity
    FlatRange *fr;
1039 5a583347 Avi Kivity
1040 cc31e6e7 Avi Kivity
    FOR_EACH_FLAT_RANGE(fr, &address_space_memory.current_map) {
1041 5a583347 Avi Kivity
        if (fr->mr == mr) {
1042 5a583347 Avi Kivity
            cpu_physical_sync_dirty_bitmap(fr->addr.start,
1043 5a583347 Avi Kivity
                                           fr->addr.start + fr->addr.size);
1044 5a583347 Avi Kivity
        }
1045 5a583347 Avi Kivity
    }
1046 093bc2cd Avi Kivity
}
1047 093bc2cd Avi Kivity
1048 093bc2cd Avi Kivity
void memory_region_set_readonly(MemoryRegion *mr, bool readonly)
1049 093bc2cd Avi Kivity
{
1050 fb1cd6f9 Avi Kivity
    if (mr->readonly != readonly) {
1051 fb1cd6f9 Avi Kivity
        mr->readonly = readonly;
1052 fb1cd6f9 Avi Kivity
        memory_region_update_topology();
1053 fb1cd6f9 Avi Kivity
    }
1054 093bc2cd Avi Kivity
}
1055 093bc2cd Avi Kivity
1056 d0a9b5bc Avi Kivity
void memory_region_rom_device_set_readable(MemoryRegion *mr, bool readable)
1057 d0a9b5bc Avi Kivity
{
1058 d0a9b5bc Avi Kivity
    if (mr->readable != readable) {
1059 d0a9b5bc Avi Kivity
        mr->readable = readable;
1060 d0a9b5bc Avi Kivity
        memory_region_update_topology();
1061 d0a9b5bc Avi Kivity
    }
1062 d0a9b5bc Avi Kivity
}
1063 d0a9b5bc Avi Kivity
1064 093bc2cd Avi Kivity
void memory_region_reset_dirty(MemoryRegion *mr, target_phys_addr_t addr,
1065 093bc2cd Avi Kivity
                               target_phys_addr_t size, unsigned client)
1066 093bc2cd Avi Kivity
{
1067 14a3c10a Avi Kivity
    assert(mr->terminates);
1068 5a583347 Avi Kivity
    cpu_physical_memory_reset_dirty(mr->ram_addr + addr,
1069 5a583347 Avi Kivity
                                    mr->ram_addr + addr + size,
1070 5a583347 Avi Kivity
                                    1 << client);
1071 093bc2cd Avi Kivity
}
1072 093bc2cd Avi Kivity
1073 093bc2cd Avi Kivity
void *memory_region_get_ram_ptr(MemoryRegion *mr)
1074 093bc2cd Avi Kivity
{
1075 093bc2cd Avi Kivity
    if (mr->alias) {
1076 093bc2cd Avi Kivity
        return memory_region_get_ram_ptr(mr->alias) + mr->alias_offset;
1077 093bc2cd Avi Kivity
    }
1078 093bc2cd Avi Kivity
1079 14a3c10a Avi Kivity
    assert(mr->terminates);
1080 093bc2cd Avi Kivity
1081 021d26d1 Jan Kiszka
    return qemu_get_ram_ptr(mr->ram_addr & TARGET_PAGE_MASK);
1082 093bc2cd Avi Kivity
}
1083 093bc2cd Avi Kivity
1084 093bc2cd Avi Kivity
static void memory_region_update_coalesced_range(MemoryRegion *mr)
1085 093bc2cd Avi Kivity
{
1086 093bc2cd Avi Kivity
    FlatRange *fr;
1087 093bc2cd Avi Kivity
    CoalescedMemoryRange *cmr;
1088 093bc2cd Avi Kivity
    AddrRange tmp;
1089 093bc2cd Avi Kivity
1090 cc31e6e7 Avi Kivity
    FOR_EACH_FLAT_RANGE(fr, &address_space_memory.current_map) {
1091 093bc2cd Avi Kivity
        if (fr->mr == mr) {
1092 093bc2cd Avi Kivity
            qemu_unregister_coalesced_mmio(fr->addr.start, fr->addr.size);
1093 093bc2cd Avi Kivity
            QTAILQ_FOREACH(cmr, &mr->coalesced, link) {
1094 093bc2cd Avi Kivity
                tmp = addrrange_shift(cmr->addr,
1095 093bc2cd Avi Kivity
                                      fr->addr.start - fr->offset_in_region);
1096 093bc2cd Avi Kivity
                if (!addrrange_intersects(tmp, fr->addr)) {
1097 093bc2cd Avi Kivity
                    continue;
1098 093bc2cd Avi Kivity
                }
1099 093bc2cd Avi Kivity
                tmp = addrrange_intersection(tmp, fr->addr);
1100 093bc2cd Avi Kivity
                qemu_register_coalesced_mmio(tmp.start, tmp.size);
1101 093bc2cd Avi Kivity
            }
1102 093bc2cd Avi Kivity
        }
1103 093bc2cd Avi Kivity
    }
1104 093bc2cd Avi Kivity
}
1105 093bc2cd Avi Kivity
1106 093bc2cd Avi Kivity
void memory_region_set_coalescing(MemoryRegion *mr)
1107 093bc2cd Avi Kivity
{
1108 093bc2cd Avi Kivity
    memory_region_clear_coalescing(mr);
1109 093bc2cd Avi Kivity
    memory_region_add_coalescing(mr, 0, mr->size);
1110 093bc2cd Avi Kivity
}
1111 093bc2cd Avi Kivity
1112 093bc2cd Avi Kivity
void memory_region_add_coalescing(MemoryRegion *mr,
1113 093bc2cd Avi Kivity
                                  target_phys_addr_t offset,
1114 093bc2cd Avi Kivity
                                  uint64_t size)
1115 093bc2cd Avi Kivity
{
1116 7267c094 Anthony Liguori
    CoalescedMemoryRange *cmr = g_malloc(sizeof(*cmr));
1117 093bc2cd Avi Kivity
1118 093bc2cd Avi Kivity
    cmr->addr = addrrange_make(offset, size);
1119 093bc2cd Avi Kivity
    QTAILQ_INSERT_TAIL(&mr->coalesced, cmr, link);
1120 093bc2cd Avi Kivity
    memory_region_update_coalesced_range(mr);
1121 093bc2cd Avi Kivity
}
1122 093bc2cd Avi Kivity
1123 093bc2cd Avi Kivity
void memory_region_clear_coalescing(MemoryRegion *mr)
1124 093bc2cd Avi Kivity
{
1125 093bc2cd Avi Kivity
    CoalescedMemoryRange *cmr;
1126 093bc2cd Avi Kivity
1127 093bc2cd Avi Kivity
    while (!QTAILQ_EMPTY(&mr->coalesced)) {
1128 093bc2cd Avi Kivity
        cmr = QTAILQ_FIRST(&mr->coalesced);
1129 093bc2cd Avi Kivity
        QTAILQ_REMOVE(&mr->coalesced, cmr, link);
1130 7267c094 Anthony Liguori
        g_free(cmr);
1131 093bc2cd Avi Kivity
    }
1132 093bc2cd Avi Kivity
    memory_region_update_coalesced_range(mr);
1133 093bc2cd Avi Kivity
}
1134 093bc2cd Avi Kivity
1135 3e9d69e7 Avi Kivity
void memory_region_add_eventfd(MemoryRegion *mr,
1136 3e9d69e7 Avi Kivity
                               target_phys_addr_t addr,
1137 3e9d69e7 Avi Kivity
                               unsigned size,
1138 3e9d69e7 Avi Kivity
                               bool match_data,
1139 3e9d69e7 Avi Kivity
                               uint64_t data,
1140 3e9d69e7 Avi Kivity
                               int fd)
1141 3e9d69e7 Avi Kivity
{
1142 3e9d69e7 Avi Kivity
    MemoryRegionIoeventfd mrfd = {
1143 3e9d69e7 Avi Kivity
        .addr.start = addr,
1144 3e9d69e7 Avi Kivity
        .addr.size = size,
1145 3e9d69e7 Avi Kivity
        .match_data = match_data,
1146 3e9d69e7 Avi Kivity
        .data = data,
1147 3e9d69e7 Avi Kivity
        .fd = fd,
1148 3e9d69e7 Avi Kivity
    };
1149 3e9d69e7 Avi Kivity
    unsigned i;
1150 3e9d69e7 Avi Kivity
1151 3e9d69e7 Avi Kivity
    for (i = 0; i < mr->ioeventfd_nb; ++i) {
1152 3e9d69e7 Avi Kivity
        if (memory_region_ioeventfd_before(mrfd, mr->ioeventfds[i])) {
1153 3e9d69e7 Avi Kivity
            break;
1154 3e9d69e7 Avi Kivity
        }
1155 3e9d69e7 Avi Kivity
    }
1156 3e9d69e7 Avi Kivity
    ++mr->ioeventfd_nb;
1157 7267c094 Anthony Liguori
    mr->ioeventfds = g_realloc(mr->ioeventfds,
1158 3e9d69e7 Avi Kivity
                                  sizeof(*mr->ioeventfds) * mr->ioeventfd_nb);
1159 3e9d69e7 Avi Kivity
    memmove(&mr->ioeventfds[i+1], &mr->ioeventfds[i],
1160 3e9d69e7 Avi Kivity
            sizeof(*mr->ioeventfds) * (mr->ioeventfd_nb-1 - i));
1161 3e9d69e7 Avi Kivity
    mr->ioeventfds[i] = mrfd;
1162 3e9d69e7 Avi Kivity
    memory_region_update_topology();
1163 3e9d69e7 Avi Kivity
}
1164 3e9d69e7 Avi Kivity
1165 3e9d69e7 Avi Kivity
void memory_region_del_eventfd(MemoryRegion *mr,
1166 3e9d69e7 Avi Kivity
                               target_phys_addr_t addr,
1167 3e9d69e7 Avi Kivity
                               unsigned size,
1168 3e9d69e7 Avi Kivity
                               bool match_data,
1169 3e9d69e7 Avi Kivity
                               uint64_t data,
1170 3e9d69e7 Avi Kivity
                               int fd)
1171 3e9d69e7 Avi Kivity
{
1172 3e9d69e7 Avi Kivity
    MemoryRegionIoeventfd mrfd = {
1173 3e9d69e7 Avi Kivity
        .addr.start = addr,
1174 3e9d69e7 Avi Kivity
        .addr.size = size,
1175 3e9d69e7 Avi Kivity
        .match_data = match_data,
1176 3e9d69e7 Avi Kivity
        .data = data,
1177 3e9d69e7 Avi Kivity
        .fd = fd,
1178 3e9d69e7 Avi Kivity
    };
1179 3e9d69e7 Avi Kivity
    unsigned i;
1180 3e9d69e7 Avi Kivity
1181 3e9d69e7 Avi Kivity
    for (i = 0; i < mr->ioeventfd_nb; ++i) {
1182 3e9d69e7 Avi Kivity
        if (memory_region_ioeventfd_equal(mrfd, mr->ioeventfds[i])) {
1183 3e9d69e7 Avi Kivity
            break;
1184 3e9d69e7 Avi Kivity
        }
1185 3e9d69e7 Avi Kivity
    }
1186 3e9d69e7 Avi Kivity
    assert(i != mr->ioeventfd_nb);
1187 3e9d69e7 Avi Kivity
    memmove(&mr->ioeventfds[i], &mr->ioeventfds[i+1],
1188 3e9d69e7 Avi Kivity
            sizeof(*mr->ioeventfds) * (mr->ioeventfd_nb - (i+1)));
1189 3e9d69e7 Avi Kivity
    --mr->ioeventfd_nb;
1190 7267c094 Anthony Liguori
    mr->ioeventfds = g_realloc(mr->ioeventfds,
1191 3e9d69e7 Avi Kivity
                                  sizeof(*mr->ioeventfds)*mr->ioeventfd_nb + 1);
1192 3e9d69e7 Avi Kivity
    memory_region_update_topology();
1193 3e9d69e7 Avi Kivity
}
1194 3e9d69e7 Avi Kivity
1195 093bc2cd Avi Kivity
static void memory_region_add_subregion_common(MemoryRegion *mr,
1196 093bc2cd Avi Kivity
                                               target_phys_addr_t offset,
1197 093bc2cd Avi Kivity
                                               MemoryRegion *subregion)
1198 093bc2cd Avi Kivity
{
1199 093bc2cd Avi Kivity
    MemoryRegion *other;
1200 093bc2cd Avi Kivity
1201 093bc2cd Avi Kivity
    assert(!subregion->parent);
1202 093bc2cd Avi Kivity
    subregion->parent = mr;
1203 093bc2cd Avi Kivity
    subregion->addr = offset;
1204 093bc2cd Avi Kivity
    QTAILQ_FOREACH(other, &mr->subregions, subregions_link) {
1205 093bc2cd Avi Kivity
        if (subregion->may_overlap || other->may_overlap) {
1206 093bc2cd Avi Kivity
            continue;
1207 093bc2cd Avi Kivity
        }
1208 860329b2 Michael Walle
        if (offset >= other->addr + other->size
1209 860329b2 Michael Walle
            || offset + subregion->size <= other->addr) {
1210 093bc2cd Avi Kivity
            continue;
1211 093bc2cd Avi Kivity
        }
1212 a5e1cbc8 Anthony Liguori
#if 0
1213 860329b2 Michael Walle
        printf("warning: subregion collision %llx/%llx (%s) "
1214 860329b2 Michael Walle
               "vs %llx/%llx (%s)\n",
1215 093bc2cd Avi Kivity
               (unsigned long long)offset,
1216 093bc2cd Avi Kivity
               (unsigned long long)subregion->size,
1217 860329b2 Michael Walle
               subregion->name,
1218 860329b2 Michael Walle
               (unsigned long long)other->addr,
1219 860329b2 Michael Walle
               (unsigned long long)other->size,
1220 860329b2 Michael Walle
               other->name);
1221 a5e1cbc8 Anthony Liguori
#endif
1222 093bc2cd Avi Kivity
    }
1223 093bc2cd Avi Kivity
    QTAILQ_FOREACH(other, &mr->subregions, subregions_link) {
1224 093bc2cd Avi Kivity
        if (subregion->priority >= other->priority) {
1225 093bc2cd Avi Kivity
            QTAILQ_INSERT_BEFORE(other, subregion, subregions_link);
1226 093bc2cd Avi Kivity
            goto done;
1227 093bc2cd Avi Kivity
        }
1228 093bc2cd Avi Kivity
    }
1229 093bc2cd Avi Kivity
    QTAILQ_INSERT_TAIL(&mr->subregions, subregion, subregions_link);
1230 093bc2cd Avi Kivity
done:
1231 093bc2cd Avi Kivity
    memory_region_update_topology();
1232 093bc2cd Avi Kivity
}
1233 093bc2cd Avi Kivity
1234 093bc2cd Avi Kivity
1235 093bc2cd Avi Kivity
void memory_region_add_subregion(MemoryRegion *mr,
1236 093bc2cd Avi Kivity
                                 target_phys_addr_t offset,
1237 093bc2cd Avi Kivity
                                 MemoryRegion *subregion)
1238 093bc2cd Avi Kivity
{
1239 093bc2cd Avi Kivity
    subregion->may_overlap = false;
1240 093bc2cd Avi Kivity
    subregion->priority = 0;
1241 093bc2cd Avi Kivity
    memory_region_add_subregion_common(mr, offset, subregion);
1242 093bc2cd Avi Kivity
}
1243 093bc2cd Avi Kivity
1244 093bc2cd Avi Kivity
void memory_region_add_subregion_overlap(MemoryRegion *mr,
1245 093bc2cd Avi Kivity
                                         target_phys_addr_t offset,
1246 093bc2cd Avi Kivity
                                         MemoryRegion *subregion,
1247 093bc2cd Avi Kivity
                                         unsigned priority)
1248 093bc2cd Avi Kivity
{
1249 093bc2cd Avi Kivity
    subregion->may_overlap = true;
1250 093bc2cd Avi Kivity
    subregion->priority = priority;
1251 093bc2cd Avi Kivity
    memory_region_add_subregion_common(mr, offset, subregion);
1252 093bc2cd Avi Kivity
}
1253 093bc2cd Avi Kivity
1254 093bc2cd Avi Kivity
void memory_region_del_subregion(MemoryRegion *mr,
1255 093bc2cd Avi Kivity
                                 MemoryRegion *subregion)
1256 093bc2cd Avi Kivity
{
1257 093bc2cd Avi Kivity
    assert(subregion->parent == mr);
1258 093bc2cd Avi Kivity
    subregion->parent = NULL;
1259 093bc2cd Avi Kivity
    QTAILQ_REMOVE(&mr->subregions, subregion, subregions_link);
1260 093bc2cd Avi Kivity
    memory_region_update_topology();
1261 093bc2cd Avi Kivity
}
1262 1c0ffa58 Avi Kivity
1263 1c0ffa58 Avi Kivity
void set_system_memory_map(MemoryRegion *mr)
1264 1c0ffa58 Avi Kivity
{
1265 cc31e6e7 Avi Kivity
    address_space_memory.root = mr;
1266 1c0ffa58 Avi Kivity
    memory_region_update_topology();
1267 1c0ffa58 Avi Kivity
}
1268 658b2224 Avi Kivity
1269 658b2224 Avi Kivity
void set_system_io_map(MemoryRegion *mr)
1270 658b2224 Avi Kivity
{
1271 658b2224 Avi Kivity
    address_space_io.root = mr;
1272 658b2224 Avi Kivity
    memory_region_update_topology();
1273 658b2224 Avi Kivity
}
1274 314e2987 Blue Swirl
1275 314e2987 Blue Swirl
typedef struct MemoryRegionList MemoryRegionList;
1276 314e2987 Blue Swirl
1277 314e2987 Blue Swirl
struct MemoryRegionList {
1278 314e2987 Blue Swirl
    const MemoryRegion *mr;
1279 314e2987 Blue Swirl
    bool printed;
1280 314e2987 Blue Swirl
    QTAILQ_ENTRY(MemoryRegionList) queue;
1281 314e2987 Blue Swirl
};
1282 314e2987 Blue Swirl
1283 314e2987 Blue Swirl
typedef QTAILQ_HEAD(queue, MemoryRegionList) MemoryRegionListHead;
1284 314e2987 Blue Swirl
1285 314e2987 Blue Swirl
static void mtree_print_mr(fprintf_function mon_printf, void *f,
1286 314e2987 Blue Swirl
                           const MemoryRegion *mr, unsigned int level,
1287 314e2987 Blue Swirl
                           target_phys_addr_t base,
1288 9479c57a Jan Kiszka
                           MemoryRegionListHead *alias_print_queue)
1289 314e2987 Blue Swirl
{
1290 9479c57a Jan Kiszka
    MemoryRegionList *new_ml, *ml, *next_ml;
1291 9479c57a Jan Kiszka
    MemoryRegionListHead submr_print_queue;
1292 314e2987 Blue Swirl
    const MemoryRegion *submr;
1293 314e2987 Blue Swirl
    unsigned int i;
1294 314e2987 Blue Swirl
1295 314e2987 Blue Swirl
    if (!mr) {
1296 314e2987 Blue Swirl
        return;
1297 314e2987 Blue Swirl
    }
1298 314e2987 Blue Swirl
1299 314e2987 Blue Swirl
    for (i = 0; i < level; i++) {
1300 314e2987 Blue Swirl
        mon_printf(f, "  ");
1301 314e2987 Blue Swirl
    }
1302 314e2987 Blue Swirl
1303 314e2987 Blue Swirl
    if (mr->alias) {
1304 314e2987 Blue Swirl
        MemoryRegionList *ml;
1305 314e2987 Blue Swirl
        bool found = false;
1306 314e2987 Blue Swirl
1307 314e2987 Blue Swirl
        /* check if the alias is already in the queue */
1308 9479c57a Jan Kiszka
        QTAILQ_FOREACH(ml, alias_print_queue, queue) {
1309 314e2987 Blue Swirl
            if (ml->mr == mr->alias && !ml->printed) {
1310 314e2987 Blue Swirl
                found = true;
1311 314e2987 Blue Swirl
            }
1312 314e2987 Blue Swirl
        }
1313 314e2987 Blue Swirl
1314 314e2987 Blue Swirl
        if (!found) {
1315 314e2987 Blue Swirl
            ml = g_new(MemoryRegionList, 1);
1316 314e2987 Blue Swirl
            ml->mr = mr->alias;
1317 314e2987 Blue Swirl
            ml->printed = false;
1318 9479c57a Jan Kiszka
            QTAILQ_INSERT_TAIL(alias_print_queue, ml, queue);
1319 314e2987 Blue Swirl
        }
1320 4b474ba7 Jan Kiszka
        mon_printf(f, TARGET_FMT_plx "-" TARGET_FMT_plx " (prio %d): alias %s @%s "
1321 314e2987 Blue Swirl
                   TARGET_FMT_plx "-" TARGET_FMT_plx "\n",
1322 314e2987 Blue Swirl
                   base + mr->addr,
1323 314e2987 Blue Swirl
                   base + mr->addr + (target_phys_addr_t)mr->size - 1,
1324 4b474ba7 Jan Kiszka
                   mr->priority,
1325 314e2987 Blue Swirl
                   mr->name,
1326 314e2987 Blue Swirl
                   mr->alias->name,
1327 314e2987 Blue Swirl
                   mr->alias_offset,
1328 314e2987 Blue Swirl
                   mr->alias_offset + (target_phys_addr_t)mr->size - 1);
1329 314e2987 Blue Swirl
    } else {
1330 4b474ba7 Jan Kiszka
        mon_printf(f, TARGET_FMT_plx "-" TARGET_FMT_plx " (prio %d): %s\n",
1331 314e2987 Blue Swirl
                   base + mr->addr,
1332 314e2987 Blue Swirl
                   base + mr->addr + (target_phys_addr_t)mr->size - 1,
1333 4b474ba7 Jan Kiszka
                   mr->priority,
1334 314e2987 Blue Swirl
                   mr->name);
1335 314e2987 Blue Swirl
    }
1336 9479c57a Jan Kiszka
1337 9479c57a Jan Kiszka
    QTAILQ_INIT(&submr_print_queue);
1338 9479c57a Jan Kiszka
1339 314e2987 Blue Swirl
    QTAILQ_FOREACH(submr, &mr->subregions, subregions_link) {
1340 9479c57a Jan Kiszka
        new_ml = g_new(MemoryRegionList, 1);
1341 9479c57a Jan Kiszka
        new_ml->mr = submr;
1342 9479c57a Jan Kiszka
        QTAILQ_FOREACH(ml, &submr_print_queue, queue) {
1343 9479c57a Jan Kiszka
            if (new_ml->mr->addr < ml->mr->addr ||
1344 9479c57a Jan Kiszka
                (new_ml->mr->addr == ml->mr->addr &&
1345 9479c57a Jan Kiszka
                 new_ml->mr->priority > ml->mr->priority)) {
1346 9479c57a Jan Kiszka
                QTAILQ_INSERT_BEFORE(ml, new_ml, queue);
1347 9479c57a Jan Kiszka
                new_ml = NULL;
1348 9479c57a Jan Kiszka
                break;
1349 9479c57a Jan Kiszka
            }
1350 9479c57a Jan Kiszka
        }
1351 9479c57a Jan Kiszka
        if (new_ml) {
1352 9479c57a Jan Kiszka
            QTAILQ_INSERT_TAIL(&submr_print_queue, new_ml, queue);
1353 9479c57a Jan Kiszka
        }
1354 9479c57a Jan Kiszka
    }
1355 9479c57a Jan Kiszka
1356 9479c57a Jan Kiszka
    QTAILQ_FOREACH(ml, &submr_print_queue, queue) {
1357 9479c57a Jan Kiszka
        mtree_print_mr(mon_printf, f, ml->mr, level + 1, base + mr->addr,
1358 9479c57a Jan Kiszka
                       alias_print_queue);
1359 9479c57a Jan Kiszka
    }
1360 9479c57a Jan Kiszka
1361 9479c57a Jan Kiszka
    QTAILQ_FOREACH_SAFE(next_ml, &submr_print_queue, queue, ml) {
1362 9479c57a Jan Kiszka
        g_free(ml);
1363 314e2987 Blue Swirl
    }
1364 314e2987 Blue Swirl
}
1365 314e2987 Blue Swirl
1366 314e2987 Blue Swirl
void mtree_info(fprintf_function mon_printf, void *f)
1367 314e2987 Blue Swirl
{
1368 314e2987 Blue Swirl
    MemoryRegionListHead ml_head;
1369 314e2987 Blue Swirl
    MemoryRegionList *ml, *ml2;
1370 314e2987 Blue Swirl
1371 314e2987 Blue Swirl
    QTAILQ_INIT(&ml_head);
1372 314e2987 Blue Swirl
1373 314e2987 Blue Swirl
    mon_printf(f, "memory\n");
1374 314e2987 Blue Swirl
    mtree_print_mr(mon_printf, f, address_space_memory.root, 0, 0, &ml_head);
1375 314e2987 Blue Swirl
1376 314e2987 Blue Swirl
    /* print aliased regions */
1377 314e2987 Blue Swirl
    QTAILQ_FOREACH(ml, &ml_head, queue) {
1378 314e2987 Blue Swirl
        if (!ml->printed) {
1379 314e2987 Blue Swirl
            mon_printf(f, "%s\n", ml->mr->name);
1380 314e2987 Blue Swirl
            mtree_print_mr(mon_printf, f, ml->mr, 0, 0, &ml_head);
1381 314e2987 Blue Swirl
        }
1382 314e2987 Blue Swirl
    }
1383 314e2987 Blue Swirl
1384 314e2987 Blue Swirl
    QTAILQ_FOREACH_SAFE(ml, &ml_head, queue, ml2) {
1385 314e2987 Blue Swirl
        g_free(ml2);
1386 314e2987 Blue Swirl
    }
1387 314e2987 Blue Swirl
1388 06631810 Jan Kiszka
    if (address_space_io.root &&
1389 06631810 Jan Kiszka
        !QTAILQ_EMPTY(&address_space_io.root->subregions)) {
1390 06631810 Jan Kiszka
        QTAILQ_INIT(&ml_head);
1391 06631810 Jan Kiszka
        mon_printf(f, "I/O\n");
1392 06631810 Jan Kiszka
        mtree_print_mr(mon_printf, f, address_space_io.root, 0, 0, &ml_head);
1393 06631810 Jan Kiszka
    }
1394 314e2987 Blue Swirl
}