device-core: use RCU for list of children of a bus
[qemu/ar7.git] / memory_ldst.c.inc
blobc54aee4a951fcd4c0b00e23faf9224b42e8f0370
1 /*
2  *  Physical memory access templates
3  *
4  *  Copyright (c) 2003 Fabrice Bellard
5  *  Copyright (c) 2015 Linaro, Inc.
6  *  Copyright (c) 2016 Red Hat, Inc.
7  *
8  * This library is free software; you can redistribute it and/or
9  * modify it under the terms of the GNU Lesser General Public
10  * License as published by the Free Software Foundation; either
11  * version 2 of the License, or (at your option) any later version.
12  *
13  * This library is distributed in the hope that it will be useful,
14  * but WITHOUT ANY WARRANTY; without even the implied warranty of
15  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
16  * Lesser General Public License for more details.
17  *
18  * You should have received a copy of the GNU Lesser General Public
19  * License along with this library; if not, see <http://www.gnu.org/licenses/>.
20  */
22 /* warning: addr must be aligned */
23 static inline uint32_t glue(address_space_ldl_internal, SUFFIX)(ARG1_DECL,
24     hwaddr addr, MemTxAttrs attrs, MemTxResult *result,
25     enum device_endian endian)
27     uint8_t *ptr;
28     uint64_t val;
29     MemoryRegion *mr;
30     hwaddr l = 4;
31     hwaddr addr1;
32     MemTxResult r;
33     bool release_lock = false;
35     RCU_READ_LOCK();
36     mr = TRANSLATE(addr, &addr1, &l, false, attrs);
37     if (l < 4 || !memory_access_is_direct(mr, false)) {
38         release_lock |= prepare_mmio_access(mr);
40         /* I/O case */
41         r = memory_region_dispatch_read(mr, addr1, &val,
42                                         MO_32 | devend_memop(endian), attrs);
43     } else {
44         /* RAM case */
45         ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
46         switch (endian) {
47         case DEVICE_LITTLE_ENDIAN:
48             val = ldl_le_p(ptr);
49             break;
50         case DEVICE_BIG_ENDIAN:
51             val = ldl_be_p(ptr);
52             break;
53         default:
54             val = ldl_p(ptr);
55             break;
56         }
57         r = MEMTX_OK;
58     }
59     if (result) {
60         *result = r;
61     }
62     if (release_lock) {
63         qemu_mutex_unlock_iothread();
64     }
65     RCU_READ_UNLOCK();
66     return val;
69 uint32_t glue(address_space_ldl, SUFFIX)(ARG1_DECL,
70     hwaddr addr, MemTxAttrs attrs, MemTxResult *result)
72     return glue(address_space_ldl_internal, SUFFIX)(ARG1, addr, attrs, result,
73                                                     DEVICE_NATIVE_ENDIAN);
76 uint32_t glue(address_space_ldl_le, SUFFIX)(ARG1_DECL,
77     hwaddr addr, MemTxAttrs attrs, MemTxResult *result)
79     return glue(address_space_ldl_internal, SUFFIX)(ARG1, addr, attrs, result,
80                                                     DEVICE_LITTLE_ENDIAN);
83 uint32_t glue(address_space_ldl_be, SUFFIX)(ARG1_DECL,
84     hwaddr addr, MemTxAttrs attrs, MemTxResult *result)
86     return glue(address_space_ldl_internal, SUFFIX)(ARG1, addr, attrs, result,
87                                                     DEVICE_BIG_ENDIAN);
90 /* warning: addr must be aligned */
91 static inline uint64_t glue(address_space_ldq_internal, SUFFIX)(ARG1_DECL,
92     hwaddr addr, MemTxAttrs attrs, MemTxResult *result,
93     enum device_endian endian)
95     uint8_t *ptr;
96     uint64_t val;
97     MemoryRegion *mr;
98     hwaddr l = 8;
99     hwaddr addr1;
100     MemTxResult r;
101     bool release_lock = false;
103     RCU_READ_LOCK();
104     mr = TRANSLATE(addr, &addr1, &l, false, attrs);
105     if (l < 8 || !memory_access_is_direct(mr, false)) {
106         release_lock |= prepare_mmio_access(mr);
108         /* I/O case */
109         r = memory_region_dispatch_read(mr, addr1, &val,
110                                         MO_64 | devend_memop(endian), attrs);
111     } else {
112         /* RAM case */
113         ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
114         switch (endian) {
115         case DEVICE_LITTLE_ENDIAN:
116             val = ldq_le_p(ptr);
117             break;
118         case DEVICE_BIG_ENDIAN:
119             val = ldq_be_p(ptr);
120             break;
121         default:
122             val = ldq_p(ptr);
123             break;
124         }
125         r = MEMTX_OK;
126     }
127     if (result) {
128         *result = r;
129     }
130     if (release_lock) {
131         qemu_mutex_unlock_iothread();
132     }
133     RCU_READ_UNLOCK();
134     return val;
137 uint64_t glue(address_space_ldq, SUFFIX)(ARG1_DECL,
138     hwaddr addr, MemTxAttrs attrs, MemTxResult *result)
140     return glue(address_space_ldq_internal, SUFFIX)(ARG1, addr, attrs, result,
141                                                     DEVICE_NATIVE_ENDIAN);
144 uint64_t glue(address_space_ldq_le, SUFFIX)(ARG1_DECL,
145     hwaddr addr, MemTxAttrs attrs, MemTxResult *result)
147     return glue(address_space_ldq_internal, SUFFIX)(ARG1, addr, attrs, result,
148                                                     DEVICE_LITTLE_ENDIAN);
151 uint64_t glue(address_space_ldq_be, SUFFIX)(ARG1_DECL,
152     hwaddr addr, MemTxAttrs attrs, MemTxResult *result)
154     return glue(address_space_ldq_internal, SUFFIX)(ARG1, addr, attrs, result,
155                                                     DEVICE_BIG_ENDIAN);
158 uint32_t glue(address_space_ldub, SUFFIX)(ARG1_DECL,
159     hwaddr addr, MemTxAttrs attrs, MemTxResult *result)
161     uint8_t *ptr;
162     uint64_t val;
163     MemoryRegion *mr;
164     hwaddr l = 1;
165     hwaddr addr1;
166     MemTxResult r;
167     bool release_lock = false;
169     RCU_READ_LOCK();
170     mr = TRANSLATE(addr, &addr1, &l, false, attrs);
171     if (!memory_access_is_direct(mr, false)) {
172         release_lock |= prepare_mmio_access(mr);
174         /* I/O case */
175         r = memory_region_dispatch_read(mr, addr1, &val, MO_8, attrs);
176     } else {
177         /* RAM case */
178         ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
179         val = ldub_p(ptr);
180         r = MEMTX_OK;
181     }
182     if (result) {
183         *result = r;
184     }
185     if (release_lock) {
186         qemu_mutex_unlock_iothread();
187     }
188     RCU_READ_UNLOCK();
189     return val;
192 /* warning: addr must be aligned */
193 static inline uint32_t glue(address_space_lduw_internal, SUFFIX)(ARG1_DECL,
194     hwaddr addr, MemTxAttrs attrs, MemTxResult *result,
195     enum device_endian endian)
197     uint8_t *ptr;
198     uint64_t val;
199     MemoryRegion *mr;
200     hwaddr l = 2;
201     hwaddr addr1;
202     MemTxResult r;
203     bool release_lock = false;
205     RCU_READ_LOCK();
206     mr = TRANSLATE(addr, &addr1, &l, false, attrs);
207     if (l < 2 || !memory_access_is_direct(mr, false)) {
208         release_lock |= prepare_mmio_access(mr);
210         /* I/O case */
211         r = memory_region_dispatch_read(mr, addr1, &val,
212                                         MO_16 | devend_memop(endian), attrs);
213     } else {
214         /* RAM case */
215         ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
216         switch (endian) {
217         case DEVICE_LITTLE_ENDIAN:
218             val = lduw_le_p(ptr);
219             break;
220         case DEVICE_BIG_ENDIAN:
221             val = lduw_be_p(ptr);
222             break;
223         default:
224             val = lduw_p(ptr);
225             break;
226         }
227         r = MEMTX_OK;
228     }
229     if (result) {
230         *result = r;
231     }
232     if (release_lock) {
233         qemu_mutex_unlock_iothread();
234     }
235     RCU_READ_UNLOCK();
236     return val;
239 uint32_t glue(address_space_lduw, SUFFIX)(ARG1_DECL,
240     hwaddr addr, MemTxAttrs attrs, MemTxResult *result)
242     return glue(address_space_lduw_internal, SUFFIX)(ARG1, addr, attrs, result,
243                                                      DEVICE_NATIVE_ENDIAN);
246 uint32_t glue(address_space_lduw_le, SUFFIX)(ARG1_DECL,
247     hwaddr addr, MemTxAttrs attrs, MemTxResult *result)
249     return glue(address_space_lduw_internal, SUFFIX)(ARG1, addr, attrs, result,
250                                                      DEVICE_LITTLE_ENDIAN);
253 uint32_t glue(address_space_lduw_be, SUFFIX)(ARG1_DECL,
254     hwaddr addr, MemTxAttrs attrs, MemTxResult *result)
256     return glue(address_space_lduw_internal, SUFFIX)(ARG1, addr, attrs, result,
257                                        DEVICE_BIG_ENDIAN);
260 /* warning: addr must be aligned. The ram page is not masked as dirty
261    and the code inside is not invalidated. It is useful if the dirty
262    bits are used to track modified PTEs */
263 void glue(address_space_stl_notdirty, SUFFIX)(ARG1_DECL,
264     hwaddr addr, uint32_t val, MemTxAttrs attrs, MemTxResult *result)
266     uint8_t *ptr;
267     MemoryRegion *mr;
268     hwaddr l = 4;
269     hwaddr addr1;
270     MemTxResult r;
271     uint8_t dirty_log_mask;
272     bool release_lock = false;
274     RCU_READ_LOCK();
275     mr = TRANSLATE(addr, &addr1, &l, true, attrs);
276     if (l < 4 || !memory_access_is_direct(mr, true)) {
277         release_lock |= prepare_mmio_access(mr);
279         r = memory_region_dispatch_write(mr, addr1, val, MO_32, attrs);
280     } else {
281         ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
282         stl_p(ptr, val);
284         dirty_log_mask = memory_region_get_dirty_log_mask(mr);
285         dirty_log_mask &= ~(1 << DIRTY_MEMORY_CODE);
286         cpu_physical_memory_set_dirty_range(memory_region_get_ram_addr(mr) + addr,
287                                             4, dirty_log_mask);
288         r = MEMTX_OK;
289     }
290     if (result) {
291         *result = r;
292     }
293     if (release_lock) {
294         qemu_mutex_unlock_iothread();
295     }
296     RCU_READ_UNLOCK();
299 /* warning: addr must be aligned */
300 static inline void glue(address_space_stl_internal, SUFFIX)(ARG1_DECL,
301     hwaddr addr, uint32_t val, MemTxAttrs attrs,
302     MemTxResult *result, enum device_endian endian)
304     uint8_t *ptr;
305     MemoryRegion *mr;
306     hwaddr l = 4;
307     hwaddr addr1;
308     MemTxResult r;
309     bool release_lock = false;
311     RCU_READ_LOCK();
312     mr = TRANSLATE(addr, &addr1, &l, true, attrs);
313     if (l < 4 || !memory_access_is_direct(mr, true)) {
314         release_lock |= prepare_mmio_access(mr);
315         r = memory_region_dispatch_write(mr, addr1, val,
316                                          MO_32 | devend_memop(endian), attrs);
317     } else {
318         /* RAM case */
319         ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
320         switch (endian) {
321         case DEVICE_LITTLE_ENDIAN:
322             stl_le_p(ptr, val);
323             break;
324         case DEVICE_BIG_ENDIAN:
325             stl_be_p(ptr, val);
326             break;
327         default:
328             stl_p(ptr, val);
329             break;
330         }
331         invalidate_and_set_dirty(mr, addr1, 4);
332         r = MEMTX_OK;
333     }
334     if (result) {
335         *result = r;
336     }
337     if (release_lock) {
338         qemu_mutex_unlock_iothread();
339     }
340     RCU_READ_UNLOCK();
343 void glue(address_space_stl, SUFFIX)(ARG1_DECL,
344     hwaddr addr, uint32_t val, MemTxAttrs attrs, MemTxResult *result)
346     glue(address_space_stl_internal, SUFFIX)(ARG1, addr, val, attrs,
347                                              result, DEVICE_NATIVE_ENDIAN);
350 void glue(address_space_stl_le, SUFFIX)(ARG1_DECL,
351     hwaddr addr, uint32_t val, MemTxAttrs attrs, MemTxResult *result)
353     glue(address_space_stl_internal, SUFFIX)(ARG1, addr, val, attrs,
354                                              result, DEVICE_LITTLE_ENDIAN);
357 void glue(address_space_stl_be, SUFFIX)(ARG1_DECL,
358     hwaddr addr, uint32_t val, MemTxAttrs attrs, MemTxResult *result)
360     glue(address_space_stl_internal, SUFFIX)(ARG1, addr, val, attrs,
361                                              result, DEVICE_BIG_ENDIAN);
364 void glue(address_space_stb, SUFFIX)(ARG1_DECL,
365     hwaddr addr, uint32_t val, MemTxAttrs attrs, MemTxResult *result)
367     uint8_t *ptr;
368     MemoryRegion *mr;
369     hwaddr l = 1;
370     hwaddr addr1;
371     MemTxResult r;
372     bool release_lock = false;
374     RCU_READ_LOCK();
375     mr = TRANSLATE(addr, &addr1, &l, true, attrs);
376     if (!memory_access_is_direct(mr, true)) {
377         release_lock |= prepare_mmio_access(mr);
378         r = memory_region_dispatch_write(mr, addr1, val, MO_8, attrs);
379     } else {
380         /* RAM case */
381         ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
382         stb_p(ptr, val);
383         invalidate_and_set_dirty(mr, addr1, 1);
384         r = MEMTX_OK;
385     }
386     if (result) {
387         *result = r;
388     }
389     if (release_lock) {
390         qemu_mutex_unlock_iothread();
391     }
392     RCU_READ_UNLOCK();
395 /* warning: addr must be aligned */
396 static inline void glue(address_space_stw_internal, SUFFIX)(ARG1_DECL,
397     hwaddr addr, uint32_t val, MemTxAttrs attrs,
398     MemTxResult *result, enum device_endian endian)
400     uint8_t *ptr;
401     MemoryRegion *mr;
402     hwaddr l = 2;
403     hwaddr addr1;
404     MemTxResult r;
405     bool release_lock = false;
407     RCU_READ_LOCK();
408     mr = TRANSLATE(addr, &addr1, &l, true, attrs);
409     if (l < 2 || !memory_access_is_direct(mr, true)) {
410         release_lock |= prepare_mmio_access(mr);
411         r = memory_region_dispatch_write(mr, addr1, val,
412                                          MO_16 | devend_memop(endian), attrs);
413     } else {
414         /* RAM case */
415         ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
416         switch (endian) {
417         case DEVICE_LITTLE_ENDIAN:
418             stw_le_p(ptr, val);
419             break;
420         case DEVICE_BIG_ENDIAN:
421             stw_be_p(ptr, val);
422             break;
423         default:
424             stw_p(ptr, val);
425             break;
426         }
427         invalidate_and_set_dirty(mr, addr1, 2);
428         r = MEMTX_OK;
429     }
430     if (result) {
431         *result = r;
432     }
433     if (release_lock) {
434         qemu_mutex_unlock_iothread();
435     }
436     RCU_READ_UNLOCK();
439 void glue(address_space_stw, SUFFIX)(ARG1_DECL,
440     hwaddr addr, uint32_t val, MemTxAttrs attrs, MemTxResult *result)
442     glue(address_space_stw_internal, SUFFIX)(ARG1, addr, val, attrs, result,
443                                              DEVICE_NATIVE_ENDIAN);
446 void glue(address_space_stw_le, SUFFIX)(ARG1_DECL,
447     hwaddr addr, uint32_t val, MemTxAttrs attrs, MemTxResult *result)
449     glue(address_space_stw_internal, SUFFIX)(ARG1, addr, val, attrs, result,
450                                              DEVICE_LITTLE_ENDIAN);
453 void glue(address_space_stw_be, SUFFIX)(ARG1_DECL,
454     hwaddr addr, uint32_t val, MemTxAttrs attrs, MemTxResult *result)
456     glue(address_space_stw_internal, SUFFIX)(ARG1, addr, val, attrs, result,
457                                DEVICE_BIG_ENDIAN);
460 static void glue(address_space_stq_internal, SUFFIX)(ARG1_DECL,
461     hwaddr addr, uint64_t val, MemTxAttrs attrs,
462     MemTxResult *result, enum device_endian endian)
464     uint8_t *ptr;
465     MemoryRegion *mr;
466     hwaddr l = 8;
467     hwaddr addr1;
468     MemTxResult r;
469     bool release_lock = false;
471     RCU_READ_LOCK();
472     mr = TRANSLATE(addr, &addr1, &l, true, attrs);
473     if (l < 8 || !memory_access_is_direct(mr, true)) {
474         release_lock |= prepare_mmio_access(mr);
475         r = memory_region_dispatch_write(mr, addr1, val,
476                                          MO_64 | devend_memop(endian), attrs);
477     } else {
478         /* RAM case */
479         ptr = qemu_map_ram_ptr(mr->ram_block, addr1);
480         switch (endian) {
481         case DEVICE_LITTLE_ENDIAN:
482             stq_le_p(ptr, val);
483             break;
484         case DEVICE_BIG_ENDIAN:
485             stq_be_p(ptr, val);
486             break;
487         default:
488             stq_p(ptr, val);
489             break;
490         }
491         invalidate_and_set_dirty(mr, addr1, 8);
492         r = MEMTX_OK;
493     }
494     if (result) {
495         *result = r;
496     }
497     if (release_lock) {
498         qemu_mutex_unlock_iothread();
499     }
500     RCU_READ_UNLOCK();
503 void glue(address_space_stq, SUFFIX)(ARG1_DECL,
504     hwaddr addr, uint64_t val, MemTxAttrs attrs, MemTxResult *result)
506     glue(address_space_stq_internal, SUFFIX)(ARG1, addr, val, attrs, result,
507                                              DEVICE_NATIVE_ENDIAN);
510 void glue(address_space_stq_le, SUFFIX)(ARG1_DECL,
511     hwaddr addr, uint64_t val, MemTxAttrs attrs, MemTxResult *result)
513     glue(address_space_stq_internal, SUFFIX)(ARG1, addr, val, attrs, result,
514                                              DEVICE_LITTLE_ENDIAN);
517 void glue(address_space_stq_be, SUFFIX)(ARG1_DECL,
518     hwaddr addr, uint64_t val, MemTxAttrs attrs, MemTxResult *result)
520     glue(address_space_stq_internal, SUFFIX)(ARG1, addr, val, attrs, result,
521                                              DEVICE_BIG_ENDIAN);
524 #undef ARG1_DECL
525 #undef ARG1
526 #undef SUFFIX
527 #undef TRANSLATE
528 #undef RCU_READ_LOCK
529 #undef RCU_READ_UNLOCK