master
h 212 lines 6.74 KB
Raw
1 /*
2 * Physical memory management API
3 *
4 * Copyright 2011 Red Hat, Inc. and/or its affiliates
5 *
6 * Authors:
7 * Avi Kivity <avi@redhat.com>
8 *
9 * SPDX-License-Identifier: GPL-2.0-or-later
10 */
11
12 #ifndef SYSTEM_MEMORY_CACHED_H
13 #define SYSTEM_MEMORY_CACHED_H
14
15 #include "exec/hwaddr.h"
16 #include "system/memory.h"
17
18 struct MemoryRegionCache {
19 uint8_t *ptr;
20 hwaddr xlat;
21 hwaddr len;
22 FlatView *fv;
23 MemoryRegionSection mrs;
24 bool is_write;
25 };
26
27 /**
28 * address_space_ld*_cached: load from a cached #MemoryRegion
29 * address_space_st*_cached: store into a cached #MemoryRegion
30 *
31 * These functions perform a load or store of the byte, word,
32 * longword or quad to the specified address. The address is
33 * a physical address in the AddressSpace, but it must lie within
34 * a #MemoryRegion that was mapped with address_space_cache_init.
35 *
36 * The _le suffixed functions treat the data as little endian;
37 * _be indicates big endian; no suffix indicates "same endianness
38 * as guest CPU".
39 *
40 * The "guest CPU endianness" accessors are deprecated for use outside
41 * target-* code; devices should be CPU-agnostic and use either the LE
42 * or the BE accessors.
43 *
44 * @cache: previously initialized #MemoryRegionCache to be accessed
45 * @addr: address within the address space
46 * @val: data value, for stores
47 * @attrs: memory transaction attributes
48 * @result: location to write the success/failure of the transaction;
49 * if NULL, this information is discarded
50 */
51
52 #define SUFFIX _cached_slow
53 #define ARG1 cache
54 #define ARG1_DECL const MemoryRegionCache *cache
55 #include "system/memory_ldst.h.inc"
56
57 /* Inline fast path for direct RAM access. */
58 static inline
59 uint8_t address_space_ldub_cached(const MemoryRegionCache *cache, hwaddr addr,
60 MemTxAttrs attrs, MemTxResult *result)
61 {
62 assert(addr < cache->len);
63 if (likely(cache->ptr)) {
64 return ldub_p(cache->ptr + addr);
65 } else {
66 return address_space_ldub_cached_slow(cache, addr, attrs, result);
67 }
68 }
69
70 static inline
71 void address_space_stb_cached(const MemoryRegionCache *cache,
72 hwaddr addr, uint8_t val,
73 MemTxAttrs attrs, MemTxResult *result)
74 {
75 assert(addr < cache->len);
76 if (likely(cache->ptr)) {
77 stb_p(cache->ptr + addr, val);
78 } else {
79 address_space_stb_cached_slow(cache, addr, val, attrs, result);
80 }
81 }
82
83 #ifndef TARGET_NOT_USING_LEGACY_NATIVE_ENDIAN_API
84 #define ENDIANNESS
85 #include "system/memory_ldst_cached.h.inc"
86 #endif
87
88 #define ENDIANNESS _le
89 #include "system/memory_ldst_cached.h.inc"
90
91 #define ENDIANNESS _be
92 #include "system/memory_ldst_cached.h.inc"
93
94 #define SUFFIX _cached
95 #define ARG1 cache
96 #define ARG1_DECL const MemoryRegionCache *cache
97 #include "system/memory_ldst_phys.h.inc"
98
99 /**
100 * address_space_cache_init: prepare for repeated access to a physical
101 * memory region
102 *
103 * @cache: #MemoryRegionCache to be filled
104 * @as: #AddressSpace to be accessed
105 * @addr: address within that address space
106 * @len: length of buffer
107 * @is_write: indicates the transfer direction
108 *
109 * Will only work with RAM, and may map a subset of the requested range by
110 * returning a value that is less than @len. On failure, return a negative
111 * errno value.
112 *
113 * Because it only works with RAM, this function can be used for
114 * read-modify-write operations. In this case, is_write should be %true.
115 *
116 * Note that addresses passed to the address_space_*_cached functions
117 * are relative to @addr.
118 */
119 int64_t address_space_cache_init(MemoryRegionCache *cache,
120 const AddressSpace *as,
121 hwaddr addr,
122 hwaddr len,
123 bool is_write);
124
125 /**
126 * address_space_cache_init_empty: Initialize empty #MemoryRegionCache
127 *
128 * @cache: The #MemoryRegionCache to operate on.
129 *
130 * Initializes #MemoryRegionCache structure without memory region attached.
131 * Cache initialized this way can only be safely destroyed, but not used.
132 */
133 static inline void address_space_cache_init_empty(MemoryRegionCache *cache)
134 {
135 cache->mrs.mr = NULL;
136 /* There is no real need to initialize fv, but it makes Coverity happy. */
137 cache->fv = NULL;
138 }
139
140 /**
141 * address_space_cache_invalidate: complete a write to a #MemoryRegionCache
142 *
143 * @cache: The #MemoryRegionCache to operate on.
144 * @addr: The first physical address that was written, relative to the
145 * address that was passed to @address_space_cache_init.
146 * @access_len: The number of bytes that were written starting at @addr.
147 */
148 void address_space_cache_invalidate(const MemoryRegionCache *cache,
149 hwaddr addr,
150 hwaddr access_len);
151
152 /**
153 * address_space_cache_destroy: free a #MemoryRegionCache
154 *
155 * @cache: The #MemoryRegionCache whose memory should be released.
156 */
157 void address_space_cache_destroy(MemoryRegionCache *cache);
158
159 /*
160 * Internal functions, part of the implementation of address_space_read_cached
161 * and address_space_write_cached.
162 */
163 MemTxResult address_space_read_cached_slow(const MemoryRegionCache *cache,
164 hwaddr addr, void *buf, hwaddr len);
165 MemTxResult address_space_write_cached_slow(const MemoryRegionCache *cache,
166 hwaddr addr, const void *buf,
167 hwaddr len);
168
169 /**
170 * address_space_read_cached: read from a cached RAM region
171 *
172 * @cache: Cached region to be addressed
173 * @addr: address relative to the base of the RAM region
174 * @buf: buffer with the data transferred
175 * @len: length of the data transferred
176 */
177 static inline MemTxResult
178 address_space_read_cached(const MemoryRegionCache *cache, hwaddr addr,
179 void *buf, hwaddr len)
180 {
181 assert(addr < cache->len && len <= cache->len - addr);
182 fuzz_dma_read_cb(cache->xlat + addr, len, cache->mrs.mr);
183 if (likely(cache->ptr)) {
184 memcpy(buf, cache->ptr + addr, len);
185 return MEMTX_OK;
186 } else {
187 return address_space_read_cached_slow(cache, addr, buf, len);
188 }
189 }
190
191 /**
192 * address_space_write_cached: write to a cached RAM region
193 *
194 * @cache: Cached region to be addressed
195 * @addr: address relative to the base of the RAM region
196 * @buf: buffer with the data transferred
197 * @len: length of the data transferred
198 */
199 static inline MemTxResult
200 address_space_write_cached(const MemoryRegionCache *cache, hwaddr addr,
201 const void *buf, hwaddr len)
202 {
203 assert(addr < cache->len && len <= cache->len - addr);
204 if (likely(cache->ptr)) {
205 memcpy(cache->ptr + addr, buf, len);
206 return MEMTX_OK;
207 } else {
208 return address_space_write_cached_slow(cache, addr, buf, len);
209 }
210 }
211
212 #endif