master
inc 127 lines 3.99 KB
Raw
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.1 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 */
21
22 /* warning: addr must be aligned */
23 static inline
24 uint64_t glue(address_space_ldm_internal, SUFFIX)(ARG1_DECL, MemOp mop,
25 hwaddr addr,
26 MemTxAttrs attrs,
27 MemTxResult *result)
28 {
29 const unsigned size = memop_size(mop);
30 uint64_t val;
31 MemoryRegion *mr;
32 hwaddr l = size;
33 hwaddr addr1;
34 MemTxResult r;
35 bool release_lock = false;
36
37 RCU_READ_LOCK();
38 mr = TRANSLATE(addr, &addr1, &l, false, attrs);
39 if (l < size || !memory_access_is_direct(mr, false, attrs)) {
40 release_lock |= prepare_mmio_access(mr);
41
42 /* I/O case */
43 r = memory_region_dispatch_read(mr, addr1, &val, mop, attrs);
44 } else {
45 /* RAM case */
46 fuzz_dma_read_cb(addr, size, mr);
47 val = ldm_p(qemu_map_ram_ptr(mr->ram_block, addr1), mop);
48 r = MEMTX_OK;
49 }
50 if (result) {
51 *result = r;
52 }
53 if (release_lock) {
54 bql_unlock();
55 }
56 RCU_READ_UNLOCK();
57 return val;
58 }
59
60 uint8_t glue(address_space_ldub, SUFFIX)(ARG1_DECL, hwaddr addr,
61 MemTxAttrs attrs, MemTxResult *result)
62 {
63 return glue(address_space_ldm_internal, SUFFIX)(ARG1, MO_8, addr,
64 attrs, result);
65 }
66
67 /* warning: addr must be aligned */
68 static inline
69 void glue(address_space_stm_internal, SUFFIX)(ARG1_DECL, MemOp mop,
70 hwaddr addr, uint64_t val,
71 MemTxAttrs attrs,
72 MemTxResult *result)
73 {
74 const unsigned size = memop_size(mop);
75 MemoryRegion *mr;
76 hwaddr l = size;
77 hwaddr addr1;
78 MemTxResult r;
79 bool release_lock = false;
80
81 RCU_READ_LOCK();
82 mr = TRANSLATE(addr, &addr1, &l, true, attrs);
83 if (l < size || !memory_access_is_direct(mr, true, attrs)) {
84 release_lock |= prepare_mmio_access(mr);
85 r = memory_region_dispatch_write(mr, addr1, val, mop, attrs);
86 } else {
87 /* RAM case */
88 stm_p(qemu_map_ram_ptr(mr->ram_block, addr1), mop, val);
89 invalidate_and_set_dirty(mr, addr1, size);
90 r = MEMTX_OK;
91 }
92 if (result) {
93 *result = r;
94 }
95 if (release_lock) {
96 bql_unlock();
97 }
98 RCU_READ_UNLOCK();
99 }
100
101 void glue(address_space_stb, SUFFIX)(ARG1_DECL, hwaddr addr, uint8_t val,
102 MemTxAttrs attrs, MemTxResult *result)
103 {
104 glue(address_space_stm_internal, SUFFIX)(ARG1, MO_8, addr, val,
105 attrs, result);
106 }
107
108 #ifndef TARGET_NOT_USING_LEGACY_NATIVE_ENDIAN_API
109 #define ENDIANNESS
110 #define MO_ENDIAN (target_big_endian() ? MO_BE : MO_LE)
111 #include "memory_ldst_endian.c.inc"
112 #endif /* TARGET_NOT_USING_LEGACY_NATIVE_ENDIAN_API */
113
114 #define ENDIANNESS _le
115 #define MO_ENDIAN MO_LE
116 #include "memory_ldst_endian.c.inc"
117
118 #define ENDIANNESS _be
119 #define MO_ENDIAN MO_BE
120 #include "memory_ldst_endian.c.inc"
121
122 #undef ARG1_DECL
123 #undef ARG1
124 #undef SUFFIX
125 #undef TRANSLATE
126 #undef RCU_READ_LOCK
127 #undef RCU_READ_UNLOCK