 afa4f6653d
			
		
	
	
		afa4f6653d
		
	
	
	
	
		
			
			There's a common pattern in QEMU where a function needs to perform a data load or store of an N byte integer in a particular endianness. At the moment this is handled by doing a switch() on the size and calling the appropriate ld*_p or st*_p function for each size. Provide a new family of functions ldn_*_p() and stn_*_p() which take the size as an argument and do the switch() themselves. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20180611171007.4165-2-peter.maydell@linaro.org
		
			
				
	
	
		
			412 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
	
	
			
		
		
	
	
			412 lines
		
	
	
		
			12 KiB
		
	
	
	
		
			ReStructuredText
		
	
	
	
	
	
| ..
 | |
|    Copyright (c) 2017 Linaro Limited
 | |
|    Written by Peter Maydell
 | |
| 
 | |
| ===================
 | |
| Load and Store APIs
 | |
| ===================
 | |
| 
 | |
| QEMU internally has multiple families of functions for performing
 | |
| loads and stores. This document attempts to enumerate them all
 | |
| and indicate when to use them. It does not provide detailed
 | |
| documentation of each API -- for that you should look at the
 | |
| documentation comments in the relevant header files.
 | |
| 
 | |
| 
 | |
| ``ld*_p and st*_p``
 | |
| ~~~~~~~~~~~~~~~~~~~
 | |
| 
 | |
| These functions operate on a host pointer, and should be used
 | |
| when you already have a pointer into host memory (corresponding
 | |
| to guest ram or a local buffer). They deal with doing accesses
 | |
| with the desired endianness and with correctly handling
 | |
| potentially unaligned pointer values.
 | |
| 
 | |
| Function names follow the pattern:
 | |
| 
 | |
| load: ``ld{type}{sign}{size}_{endian}_p(ptr)``
 | |
| 
 | |
| store: ``st{type}{size}_{endian}_p(ptr, val)``
 | |
| 
 | |
| ``type``
 | |
|  - (empty) : integer access
 | |
|  - ``f`` : float access
 | |
| 
 | |
| ``sign``
 | |
|  - (empty) : for 32 or 64 bit sizes (including floats and doubles)
 | |
|  - ``u`` : unsigned
 | |
|  - ``s`` : signed
 | |
| 
 | |
| ``size``
 | |
|  - ``b`` : 8 bits
 | |
|  - ``w`` : 16 bits
 | |
|  - ``l`` : 32 bits
 | |
|  - ``q`` : 64 bits
 | |
| 
 | |
| ``endian``
 | |
|  - ``he`` : host endian
 | |
|  - ``be`` : big endian
 | |
|  - ``le`` : little endian
 | |
| 
 | |
| The ``_{endian}`` infix is omitted for target-endian accesses.
 | |
| 
 | |
| The target endian accessors are only available to source
 | |
| files which are built per-target.
 | |
| 
 | |
| There are also functions which take the size as an argument:
 | |
| 
 | |
| load: ``ldn{endian}_p(ptr, sz)``
 | |
| 
 | |
| which performs an unsigned load of ``sz`` bytes from ``ptr``
 | |
| as an ``{endian}`` order value and returns it in a uint64_t.
 | |
| 
 | |
| store: ``stn{endian}_p(ptr, sz, val)``
 | |
| 
 | |
| which stores ``val`` to ``ptr`` as an ``{endian}`` order value
 | |
| of size ``sz`` bytes.
 | |
| 
 | |
| 
 | |
| Regexes for git grep
 | |
|  - ``\<ldf\?[us]\?[bwlq]\(_[hbl]e\)\?_p\>``
 | |
|  - ``\<stf\?[bwlq]\(_[hbl]e\)\?_p\>``
 | |
|  - ``\<ldn_\([hbl]e\)?_p\>``
 | |
|  - ``\<stn_\([hbl]e\)?_p\>``
 | |
| 
 | |
| ``cpu_{ld,st}_*``
 | |
| ~~~~~~~~~~~~~~~~~
 | |
| 
 | |
| These functions operate on a guest virtual address. Be aware
 | |
| that these functions may cause a guest CPU exception to be
 | |
| taken (e.g. for an alignment fault or MMU fault) which will
 | |
| result in guest CPU state being updated and control longjumping
 | |
| out of the function call. They should therefore only be used
 | |
| in code that is implementing emulation of the target CPU.
 | |
| 
 | |
| These functions may throw an exception (longjmp() back out
 | |
| to the top level TCG loop). This means they must only be used
 | |
| from helper functions where the translator has saved all
 | |
| necessary CPU state before generating the helper function call.
 | |
| It's usually better to use the ``_ra`` variants described below
 | |
| from helper functions, but these functions are the right choice
 | |
| for calls made from hooks like the CPU do_interrupt hook or
 | |
| when you know for certain that the translator had to save all
 | |
| the CPU state that ``cpu_restore_state()`` would restore anyway.
 | |
| 
 | |
| Function names follow the pattern:
 | |
| 
 | |
| load: ``cpu_ld{sign}{size}_{mmusuffix}(env, ptr)``
 | |
| 
 | |
| store: ``cpu_st{size}_{mmusuffix}(env, ptr, val)``
 | |
| 
 | |
| ``sign``
 | |
|  - (empty) : for 32 or 64 bit sizes
 | |
|  - ``u`` : unsigned
 | |
|  - ``s`` : signed
 | |
| 
 | |
| ``size``
 | |
|  - ``b`` : 8 bits
 | |
|  - ``w`` : 16 bits
 | |
|  - ``l`` : 32 bits
 | |
|  - ``q`` : 64 bits
 | |
| 
 | |
| ``mmusuffix`` is one of the generic suffixes ``data`` or ``code``, or
 | |
| (for softmmu configs) a target-specific MMU mode suffix as defined
 | |
| in the target's ``cpu.h``.
 | |
| 
 | |
| Regexes for git grep
 | |
|  - ``\<cpu_ld[us]\?[bwlq]_[a-zA-Z0-9]\+\>``
 | |
|  - ``\<cpu_st[bwlq]_[a-zA-Z0-9]\+\>``
 | |
| 
 | |
| ``cpu_{ld,st}_*_ra``
 | |
| ~~~~~~~~~~~~~~~~~~~~
 | |
| 
 | |
| These functions work like the ``cpu_{ld,st}_*`` functions except
 | |
| that they also take a ``retaddr`` argument. This extra argument
 | |
| allows for correct unwinding of any exception that is taken,
 | |
| and should generally be the result of GETPC() called directly
 | |
| from the top level HELPER(foo) function (i.e. the return address
 | |
| in the generated code).
 | |
| 
 | |
| These are generally the preferred way to do accesses by guest
 | |
| virtual address from helper functions; see the documentation
 | |
| of the non-``_ra`` variants for when those would be better.
 | |
| 
 | |
| Calling these functions with a ``retaddr`` argument of 0 is
 | |
| equivalent to calling the non-``_ra`` version of the function.
 | |
| 
 | |
| Function names follow the pattern:
 | |
| 
 | |
| load: ``cpu_ld{sign}{size}_{mmusuffix}_ra(env, ptr, retaddr)``
 | |
| 
 | |
| store: ``cpu_st{sign}{size}_{mmusuffix}_ra(env, ptr, val, retaddr)``
 | |
| 
 | |
| Regexes for git grep
 | |
|  - ``\<cpu_ld[us]\?[bwlq]_[a-zA-Z0-9]\+_ra\>``
 | |
|  - ``\<cpu_st[bwlq]_[a-zA-Z0-9]\+_ra\>``
 | |
| 
 | |
| ``helper_*_{ld,st}*mmu``
 | |
| ~~~~~~~~~~~~~~~~~~~~~~~~
 | |
| 
 | |
| These functions are intended primarily to be called by the code
 | |
| generated by the TCG backend. They may also be called by target
 | |
| CPU helper function code. Like the ``cpu_{ld,st}_*_ra`` functions
 | |
| they perform accesses by guest virtual address; the difference is
 | |
| that these functions allow you to specify an ``opindex`` parameter
 | |
| which encodes (among other things) the mmu index to use for the
 | |
| access. This is necessary if your helper needs to make an access
 | |
| via a specific mmu index (for instance, an "always as non-privileged"
 | |
| access) rather than using the default mmu index for the current state
 | |
| of the guest CPU.
 | |
| 
 | |
| The ``opindex`` parameter should be created by calling ``make_memop_idx()``.
 | |
| 
 | |
| The ``retaddr`` parameter should be the result of GETPC() called directly
 | |
| from the top level HELPER(foo) function (or 0 if no guest CPU state
 | |
| unwinding is required).
 | |
| 
 | |
| **TODO** The names of these functions are a bit odd for historical
 | |
| reasons because they were originally expected to be called only from
 | |
| within generated code. We should rename them to bring them
 | |
| more in line with the other memory access functions.
 | |
| 
 | |
| load: ``helper_{endian}_ld{sign}{size}_mmu(env, addr, opindex, retaddr)``
 | |
| 
 | |
| load (code): ``helper_{endian}_ld{sign}{size}_cmmu(env, addr, opindex, retaddr)``
 | |
| 
 | |
| store: ``helper_{endian}_st{size}_mmu(env, addr, val, opindex, retaddr)``
 | |
| 
 | |
| ``sign``
 | |
|  - (empty) : for 32 or 64 bit sizes
 | |
|  - ``u`` : unsigned
 | |
|  - ``s`` : signed
 | |
| 
 | |
| ``size``
 | |
|  - ``b`` : 8 bits
 | |
|  - ``w`` : 16 bits
 | |
|  - ``l`` : 32 bits
 | |
|  - ``q`` : 64 bits
 | |
| 
 | |
| ``endian``
 | |
|  - ``le`` : little endian
 | |
|  - ``be`` : big endian
 | |
|  - ``ret`` : target endianness
 | |
| 
 | |
| Regexes for git grep
 | |
|  - ``\<helper_\(le\|be\|ret\)_ld[us]\?[bwlq]_c\?mmu\>``
 | |
|  - ``\<helper_\(le\|be\|ret\)_st[bwlq]_mmu\>``
 | |
| 
 | |
| ``address_space_*``
 | |
| ~~~~~~~~~~~~~~~~~~~
 | |
| 
 | |
| These functions are the primary ones to use when emulating CPU
 | |
| or device memory accesses. They take an AddressSpace, which is the
 | |
| way QEMU defines the view of memory that a device or CPU has.
 | |
| (They generally correspond to being the "master" end of a hardware bus
 | |
| or bus fabric.)
 | |
| 
 | |
| Each CPU has an AddressSpace. Some kinds of CPU have more than
 | |
| one AddressSpace (for instance ARM guest CPUs have an AddressSpace
 | |
| for the Secure world and one for NonSecure if they implement TrustZone).
 | |
| Devices which can do DMA-type operations should generally have an
 | |
| AddressSpace. There is also a "system address space" which typically
 | |
| has all the devices and memory that all CPUs can see. (Some older
 | |
| device models use the "system address space" rather than properly
 | |
| modelling that they have an AddressSpace of their own.)
 | |
| 
 | |
| Functions are provided for doing byte-buffer reads and writes,
 | |
| and also for doing one-data-item loads and stores.
 | |
| 
 | |
| In all cases the caller provides a MemTxAttrs to specify bus
 | |
| transaction attributes, and can check whether the memory transaction
 | |
| succeeded using a MemTxResult return code.
 | |
| 
 | |
| ``address_space_read(address_space, addr, attrs, buf, len)``
 | |
| 
 | |
| ``address_space_write(address_space, addr, attrs, buf, len)``
 | |
| 
 | |
| ``address_space_rw(address_space, addr, attrs, buf, len, is_write)``
 | |
| 
 | |
| ``address_space_ld{sign}{size}_{endian}(address_space, addr, attrs, txresult)``
 | |
| 
 | |
| ``address_space_st{size}_{endian}(address_space, addr, val, attrs, txresult)``
 | |
| 
 | |
| ``sign``
 | |
|  - (empty) : for 32 or 64 bit sizes
 | |
|  - ``u`` : unsigned
 | |
| 
 | |
| (No signed load operations are provided.)
 | |
| 
 | |
| ``size``
 | |
|  - ``b`` : 8 bits
 | |
|  - ``w`` : 16 bits
 | |
|  - ``l`` : 32 bits
 | |
|  - ``q`` : 64 bits
 | |
| 
 | |
| ``endian``
 | |
|  - ``le`` : little endian
 | |
|  - ``be`` : big endian
 | |
| 
 | |
| The ``_{endian}`` suffix is omitted for byte accesses.
 | |
| 
 | |
| Regexes for git grep
 | |
|  - ``\<address_space_\(read\|write\|rw\)\>``
 | |
|  - ``\<address_space_ldu\?[bwql]\(_[lb]e\)\?\>``
 | |
|  - ``\<address_space_st[bwql]\(_[lb]e\)\?\>``
 | |
| 
 | |
| ``{ld,st}*_phys``
 | |
| ~~~~~~~~~~~~~~~~~
 | |
| 
 | |
| These are functions which are identical to
 | |
| ``address_space_{ld,st}*``, except that they always pass
 | |
| ``MEMTXATTRS_UNSPECIFIED`` for the transaction attributes, and ignore
 | |
| whether the transaction succeeded or failed.
 | |
| 
 | |
| The fact that they ignore whether the transaction succeeded means
 | |
| they should not be used in new code, unless you know for certain
 | |
| that your code will only be used in a context where the CPU or
 | |
| device doing the access has no way to report such an error.
 | |
| 
 | |
| ``load: ld{sign}{size}_{endian}_phys``
 | |
| 
 | |
| ``store: st{size}_{endian}_phys``
 | |
| 
 | |
| ``sign``
 | |
|  - (empty) : for 32 or 64 bit sizes
 | |
|  - ``u`` : unsigned
 | |
| 
 | |
| (No signed load operations are provided.)
 | |
| 
 | |
| ``size``
 | |
|  - ``b`` : 8 bits
 | |
|  - ``w`` : 16 bits
 | |
|  - ``l`` : 32 bits
 | |
|  - ``q`` : 64 bits
 | |
| 
 | |
| ``endian``
 | |
|  - ``le`` : little endian
 | |
|  - ``be`` : big endian
 | |
| 
 | |
| The ``_{endian}_`` infix is omitted for byte accesses.
 | |
| 
 | |
| Regexes for git grep
 | |
|  - ``\<ldu\?[bwlq]\(_[bl]e\)\?_phys\>``
 | |
|  - ``\<st[bwlq]\(_[bl]e\)\?_phys\>``
 | |
| 
 | |
| ``cpu_physical_memory_*``
 | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~
 | |
| 
 | |
| These are convenience functions which are identical to
 | |
| ``address_space_*`` but operate specifically on the system address space,
 | |
| always pass a ``MEMTXATTRS_UNSPECIFIED`` set of memory attributes and
 | |
| ignore whether the memory transaction succeeded or failed.
 | |
| For new code they are better avoided:
 | |
| 
 | |
| * there is likely to be behaviour you need to model correctly for a
 | |
|   failed read or write operation
 | |
| * a device should usually perform operations on its own AddressSpace
 | |
|   rather than using the system address space
 | |
| 
 | |
| ``cpu_physical_memory_read``
 | |
| 
 | |
| ``cpu_physical_memory_write``
 | |
| 
 | |
| ``cpu_physical_memory_rw``
 | |
| 
 | |
| Regexes for git grep
 | |
|  - ``\<cpu_physical_memory_\(read\|write\|rw\)\>``
 | |
| 
 | |
| ``cpu_physical_memory_write_rom``
 | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | |
| 
 | |
| This function performs a write by physical address like
 | |
| ``address_space_write``, except that if the write is to a ROM then
 | |
| the ROM contents will be modified, even though a write by the guest
 | |
| CPU to the ROM would be ignored.
 | |
| 
 | |
| Note that unlike ``cpu_physical_memory_write()`` this function takes
 | |
| an AddressSpace argument, but unlike ``address_space_write()`` this
 | |
| function does not take a ``MemTxAttrs`` or return a ``MemTxResult``.
 | |
| 
 | |
| **TODO**: we should probably clean up this inconsistency and
 | |
| turn the function into ``address_space_write_rom`` with an API
 | |
| matching ``address_space_write``.
 | |
| 
 | |
| ``cpu_physical_memory_write_rom``
 | |
| 
 | |
| 
 | |
| ``cpu_memory_rw_debug``
 | |
| ~~~~~~~~~~~~~~~~~~~~~~~
 | |
| 
 | |
| Access CPU memory by virtual address for debug purposes.
 | |
| 
 | |
| This function is intended for use by the GDB stub and similar code.
 | |
| It takes a virtual address, converts it to a physical address via
 | |
| an MMU lookup using the current settings of the specified CPU,
 | |
| and then performs the access (using ``address_space_rw`` for
 | |
| reads or ``cpu_physical_memory_write_rom`` for writes).
 | |
| This means that if the access is a write to a ROM then this
 | |
| function will modify the contents (whereas a normal guest CPU access
 | |
| would ignore the write attempt).
 | |
| 
 | |
| ``cpu_memory_rw_debug``
 | |
| 
 | |
| ``dma_memory_*``
 | |
| ~~~~~~~~~~~~~~~~
 | |
| 
 | |
| These behave like ``address_space_*``, except that they perform a DMA
 | |
| barrier operation first.
 | |
| 
 | |
| **TODO**: We should provide guidance on when you need the DMA
 | |
| barrier operation and when it's OK to use ``address_space_*``, and
 | |
| make sure our existing code is doing things correctly.
 | |
| 
 | |
| ``dma_memory_read``
 | |
| 
 | |
| ``dma_memory_write``
 | |
| 
 | |
| ``dma_memory_rw``
 | |
| 
 | |
| Regexes for git grep
 | |
|  - ``\<dma_memory_\(read\|write\|rw\)\>``
 | |
| 
 | |
| ``pci_dma_*`` and ``{ld,st}*_pci_dma``
 | |
| ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~
 | |
| 
 | |
| These functions are specifically for PCI device models which need to
 | |
| perform accesses where the PCI device is a bus master. You pass them a
 | |
| ``PCIDevice *`` and they will do ``dma_memory_*`` operations on the
 | |
| correct address space for that device.
 | |
| 
 | |
| ``pci_dma_read``
 | |
| 
 | |
| ``pci_dma_write``
 | |
| 
 | |
| ``pci_dma_rw``
 | |
| 
 | |
| ``load: ld{sign}{size}_{endian}_pci_dma``
 | |
| 
 | |
| ``store: st{size}_{endian}_pci_dma``
 | |
| 
 | |
| ``sign``
 | |
|  - (empty) : for 32 or 64 bit sizes
 | |
|  - ``u`` : unsigned
 | |
| 
 | |
| (No signed load operations are provided.)
 | |
| 
 | |
| ``size``
 | |
|  - ``b`` : 8 bits
 | |
|  - ``w`` : 16 bits
 | |
|  - ``l`` : 32 bits
 | |
|  - ``q`` : 64 bits
 | |
| 
 | |
| ``endian``
 | |
|  - ``le`` : little endian
 | |
|  - ``be`` : big endian
 | |
| 
 | |
| The ``_{endian}_`` infix is omitted for byte accesses.
 | |
| 
 | |
| Regexes for git grep
 | |
|  - ``\<pci_dma_\(read\|write\|rw\)\>``
 | |
|  - ``\<ldu\?[bwlq]\(_[bl]e\)\?_pci_dma\>``
 | |
|  - ``\<st[bwlq]\(_[bl]e\)\?_pci_dma\>``
 |