mirror of
https://github.com/Motorhead1991/qemu.git
synced 2026-02-11 19:39:26 -07:00
exec: introduce MemoryRegionCache
Device models often have to perform multiple access to a single memory region that is known in advance, but would to use "DMA-style" functions instead of address_space_map/unmap. This can happen for example when the data has to undergo endianness conversion. Introduce a new data structure to cache the result of address_space_translate without forcing usage of a host address like address_space_map does. Signed-off-by: Paolo Bonzini <pbonzini@redhat.com>
This commit is contained in:
parent
715c31ec8e
commit
1f4e496e1f
4 changed files with 251 additions and 0 deletions
|
|
@ -186,6 +186,29 @@ void address_space_stl(AddressSpace *as, hwaddr addr, uint32_t val,
|
|||
MemTxAttrs attrs, MemTxResult *result);
|
||||
void address_space_stq(AddressSpace *as, hwaddr addr, uint64_t val,
|
||||
MemTxAttrs attrs, MemTxResult *result);
|
||||
|
||||
uint32_t lduw_phys_cached(MemoryRegionCache *cache, hwaddr addr);
|
||||
uint32_t ldl_phys_cached(MemoryRegionCache *cache, hwaddr addr);
|
||||
uint64_t ldq_phys_cached(MemoryRegionCache *cache, hwaddr addr);
|
||||
void stl_phys_notdirty_cached(MemoryRegionCache *cache, hwaddr addr, uint32_t val);
|
||||
void stw_phys_cached(MemoryRegionCache *cache, hwaddr addr, uint32_t val);
|
||||
void stl_phys_cached(MemoryRegionCache *cache, hwaddr addr, uint32_t val);
|
||||
void stq_phys_cached(MemoryRegionCache *cache, hwaddr addr, uint64_t val);
|
||||
|
||||
uint32_t address_space_lduw_cached(MemoryRegionCache *cache, hwaddr addr,
|
||||
MemTxAttrs attrs, MemTxResult *result);
|
||||
uint32_t address_space_ldl_cached(MemoryRegionCache *cache, hwaddr addr,
|
||||
MemTxAttrs attrs, MemTxResult *result);
|
||||
uint64_t address_space_ldq_cached(MemoryRegionCache *cache, hwaddr addr,
|
||||
MemTxAttrs attrs, MemTxResult *result);
|
||||
void address_space_stl_notdirty_cached(MemoryRegionCache *cache, hwaddr addr,
|
||||
uint32_t val, MemTxAttrs attrs, MemTxResult *result);
|
||||
void address_space_stw_cached(MemoryRegionCache *cache, hwaddr addr, uint32_t val,
|
||||
MemTxAttrs attrs, MemTxResult *result);
|
||||
void address_space_stl_cached(MemoryRegionCache *cache, hwaddr addr, uint32_t val,
|
||||
MemTxAttrs attrs, MemTxResult *result);
|
||||
void address_space_stq_cached(MemoryRegionCache *cache, hwaddr addr, uint64_t val,
|
||||
MemTxAttrs attrs, MemTxResult *result);
|
||||
#endif
|
||||
|
||||
/* page related stuff */
|
||||
|
|
|
|||
|
|
@ -1419,6 +1419,125 @@ void stl_be_phys(AddressSpace *as, hwaddr addr, uint32_t val);
|
|||
void stq_le_phys(AddressSpace *as, hwaddr addr, uint64_t val);
|
||||
void stq_be_phys(AddressSpace *as, hwaddr addr, uint64_t val);
|
||||
|
||||
struct MemoryRegionCache {
|
||||
hwaddr xlat;
|
||||
void *ptr;
|
||||
hwaddr len;
|
||||
MemoryRegion *mr;
|
||||
bool is_write;
|
||||
};
|
||||
|
||||
/* address_space_cache_init: prepare for repeated access to a physical
|
||||
* memory region
|
||||
*
|
||||
* @cache: #MemoryRegionCache to be filled
|
||||
* @as: #AddressSpace to be accessed
|
||||
* @addr: address within that address space
|
||||
* @len: length of buffer
|
||||
* @is_write: indicates the transfer direction
|
||||
*
|
||||
* Will only work with RAM, and may map a subset of the requested range by
|
||||
* returning a value that is less than @len. On failure, return a negative
|
||||
* errno value.
|
||||
*
|
||||
* Because it only works with RAM, this function can be used for
|
||||
* read-modify-write operations. In this case, is_write should be %true.
|
||||
*
|
||||
* Note that addresses passed to the address_space_*_cached functions
|
||||
* are relative to @addr.
|
||||
*/
|
||||
int64_t address_space_cache_init(MemoryRegionCache *cache,
|
||||
AddressSpace *as,
|
||||
hwaddr addr,
|
||||
hwaddr len,
|
||||
bool is_write);
|
||||
|
||||
/**
|
||||
* address_space_cache_invalidate: complete a write to a #MemoryRegionCache
|
||||
*
|
||||
* @cache: The #MemoryRegionCache to operate on.
|
||||
* @addr: The first physical address that was written, relative to the
|
||||
* address that was passed to @address_space_cache_init.
|
||||
* @access_len: The number of bytes that were written starting at @addr.
|
||||
*/
|
||||
void address_space_cache_invalidate(MemoryRegionCache *cache,
|
||||
hwaddr addr,
|
||||
hwaddr access_len);
|
||||
|
||||
/**
|
||||
* address_space_cache_destroy: free a #MemoryRegionCache
|
||||
*
|
||||
* @cache: The #MemoryRegionCache whose memory should be released.
|
||||
*/
|
||||
void address_space_cache_destroy(MemoryRegionCache *cache);
|
||||
|
||||
/* address_space_ld*_cached: load from a cached #MemoryRegion
|
||||
* address_space_st*_cached: store into a cached #MemoryRegion
|
||||
*
|
||||
* These functions perform a load or store of the byte, word,
|
||||
* longword or quad to the specified address. The address is
|
||||
* a physical address in the AddressSpace, but it must lie within
|
||||
* a #MemoryRegion that was mapped with address_space_cache_init.
|
||||
*
|
||||
* The _le suffixed functions treat the data as little endian;
|
||||
* _be indicates big endian; no suffix indicates "same endianness
|
||||
* as guest CPU".
|
||||
*
|
||||
* The "guest CPU endianness" accessors are deprecated for use outside
|
||||
* target-* code; devices should be CPU-agnostic and use either the LE
|
||||
* or the BE accessors.
|
||||
*
|
||||
* @cache: previously initialized #MemoryRegionCache to be accessed
|
||||
* @addr: address within the address space
|
||||
* @val: data value, for stores
|
||||
* @attrs: memory transaction attributes
|
||||
* @result: location to write the success/failure of the transaction;
|
||||
* if NULL, this information is discarded
|
||||
*/
|
||||
uint32_t address_space_ldub_cached(MemoryRegionCache *cache, hwaddr addr,
|
||||
MemTxAttrs attrs, MemTxResult *result);
|
||||
uint32_t address_space_lduw_le_cached(MemoryRegionCache *cache, hwaddr addr,
|
||||
MemTxAttrs attrs, MemTxResult *result);
|
||||
uint32_t address_space_lduw_be_cached(MemoryRegionCache *cache, hwaddr addr,
|
||||
MemTxAttrs attrs, MemTxResult *result);
|
||||
uint32_t address_space_ldl_le_cached(MemoryRegionCache *cache, hwaddr addr,
|
||||
MemTxAttrs attrs, MemTxResult *result);
|
||||
uint32_t address_space_ldl_be_cached(MemoryRegionCache *cache, hwaddr addr,
|
||||
MemTxAttrs attrs, MemTxResult *result);
|
||||
uint64_t address_space_ldq_le_cached(MemoryRegionCache *cache, hwaddr addr,
|
||||
MemTxAttrs attrs, MemTxResult *result);
|
||||
uint64_t address_space_ldq_be_cached(MemoryRegionCache *cache, hwaddr addr,
|
||||
MemTxAttrs attrs, MemTxResult *result);
|
||||
void address_space_stb_cached(MemoryRegionCache *cache, hwaddr addr, uint32_t val,
|
||||
MemTxAttrs attrs, MemTxResult *result);
|
||||
void address_space_stw_le_cached(MemoryRegionCache *cache, hwaddr addr, uint32_t val,
|
||||
MemTxAttrs attrs, MemTxResult *result);
|
||||
void address_space_stw_be_cached(MemoryRegionCache *cache, hwaddr addr, uint32_t val,
|
||||
MemTxAttrs attrs, MemTxResult *result);
|
||||
void address_space_stl_le_cached(MemoryRegionCache *cache, hwaddr addr, uint32_t val,
|
||||
MemTxAttrs attrs, MemTxResult *result);
|
||||
void address_space_stl_be_cached(MemoryRegionCache *cache, hwaddr addr, uint32_t val,
|
||||
MemTxAttrs attrs, MemTxResult *result);
|
||||
void address_space_stq_le_cached(MemoryRegionCache *cache, hwaddr addr, uint64_t val,
|
||||
MemTxAttrs attrs, MemTxResult *result);
|
||||
void address_space_stq_be_cached(MemoryRegionCache *cache, hwaddr addr, uint64_t val,
|
||||
MemTxAttrs attrs, MemTxResult *result);
|
||||
|
||||
uint32_t ldub_phys_cached(MemoryRegionCache *cache, hwaddr addr);
|
||||
uint32_t lduw_le_phys_cached(MemoryRegionCache *cache, hwaddr addr);
|
||||
uint32_t lduw_be_phys_cached(MemoryRegionCache *cache, hwaddr addr);
|
||||
uint32_t ldl_le_phys_cached(MemoryRegionCache *cache, hwaddr addr);
|
||||
uint32_t ldl_be_phys_cached(MemoryRegionCache *cache, hwaddr addr);
|
||||
uint64_t ldq_le_phys_cached(MemoryRegionCache *cache, hwaddr addr);
|
||||
uint64_t ldq_be_phys_cached(MemoryRegionCache *cache, hwaddr addr);
|
||||
void stb_phys_cached(MemoryRegionCache *cache, hwaddr addr, uint32_t val);
|
||||
void stw_le_phys_cached(MemoryRegionCache *cache, hwaddr addr, uint32_t val);
|
||||
void stw_be_phys_cached(MemoryRegionCache *cache, hwaddr addr, uint32_t val);
|
||||
void stl_le_phys_cached(MemoryRegionCache *cache, hwaddr addr, uint32_t val);
|
||||
void stl_be_phys_cached(MemoryRegionCache *cache, hwaddr addr, uint32_t val);
|
||||
void stq_le_phys_cached(MemoryRegionCache *cache, hwaddr addr, uint64_t val);
|
||||
void stq_be_phys_cached(MemoryRegionCache *cache, hwaddr addr, uint64_t val);
|
||||
|
||||
/* address_space_translate: translate an address range into an address space
|
||||
* into a MemoryRegion and an address range into that section. Should be
|
||||
* called from an RCU critical section, to avoid that the last reference
|
||||
|
|
@ -1544,6 +1663,38 @@ MemTxResult address_space_read(AddressSpace *as, hwaddr addr, MemTxAttrs attrs,
|
|||
return result;
|
||||
}
|
||||
|
||||
/**
|
||||
* address_space_read_cached: read from a cached RAM region
|
||||
*
|
||||
* @cache: Cached region to be addressed
|
||||
* @addr: address relative to the base of the RAM region
|
||||
* @buf: buffer with the data transferred
|
||||
* @len: length of the data transferred
|
||||
*/
|
||||
static inline void
|
||||
address_space_read_cached(MemoryRegionCache *cache, hwaddr addr,
|
||||
void *buf, int len)
|
||||
{
|
||||
assert(addr < cache->len && len <= cache->len - addr);
|
||||
memcpy(buf, cache->ptr + addr, len);
|
||||
}
|
||||
|
||||
/**
|
||||
* address_space_write_cached: write to a cached RAM region
|
||||
*
|
||||
* @cache: Cached region to be addressed
|
||||
* @addr: address relative to the base of the RAM region
|
||||
* @buf: buffer with the data transferred
|
||||
* @len: length of the data transferred
|
||||
*/
|
||||
static inline void
|
||||
address_space_write_cached(MemoryRegionCache *cache, hwaddr addr,
|
||||
void *buf, int len)
|
||||
{
|
||||
assert(addr < cache->len && len <= cache->len - addr);
|
||||
memcpy(cache->ptr + addr, buf, len);
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue