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