From patchwork Wed Oct 18 16:12:04 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Paolo Bonzini X-Patchwork-Id: 827718 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Authentication-Results: ozlabs.org; spf=pass (mailfrom) smtp.mailfrom=nongnu.org (client-ip=2001:4830:134:3::11; helo=lists.gnu.org; envelope-from=qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org; receiver=) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b="DKkPjtbY"; dkim-atps=neutral Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3yHHQQ3H51z9sBd for ; Thu, 19 Oct 2017 03:22:22 +1100 (AEDT) Received: from localhost ([::1]:45489 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1e4r6q-0001xK-GO for incoming@patchwork.ozlabs.org; Wed, 18 Oct 2017 12:22:20 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:35853) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1e4qy4-0003Ug-UT for qemu-devel@nongnu.org; Wed, 18 Oct 2017 12:13:23 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1e4qy2-00027P-M5 for qemu-devel@nongnu.org; Wed, 18 Oct 2017 12:13:16 -0400 Received: from mail-wm0-x241.google.com ([2a00:1450:400c:c09::241]:47834) by eggs.gnu.org with esmtps (TLS1.0:RSA_AES_128_CBC_SHA1:16) (Exim 4.71) (envelope-from ) id 1e4qy2-00026l-AS for qemu-devel@nongnu.org; Wed, 18 Oct 2017 12:13:14 -0400 Received: by mail-wm0-x241.google.com with SMTP id t69so10985818wmt.2 for ; Wed, 18 Oct 2017 09:13:14 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20161025; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=0CLq1UGtPC1wXTZjTtDBDAfQxq/8zfzEquXbzkGu7uI=; b=DKkPjtbYoMbRGzCScVKc7FotpX8G9U7unr8gTfWCroUOt9KK4rjX80otgshAooykpl f0RUp6+NhhMxlLk2Sq15vVliknEJaJ04xWKv9mY6mIQN/23v1uy/T5nYLUSwq88pISGx kJp0bedNgeUSX/wQCKjX8kA9F+p02v2/c7iQkUB3ku0z6uZtlpVkcMvX061WdZvTfi81 8fmNG6XnCOVczAsTj8AkWH4R0Rl7mLdlZD9tXp3KUrqZTwWBazjKvA0EoxIwVtPx5GP4 OMl2d/RAuYWRwpc+FJK+vY/l29mVf6Dq6xq0FEbwIyieLXhffQzJBma+lN9EG5Ai/CTW WKwA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references; bh=0CLq1UGtPC1wXTZjTtDBDAfQxq/8zfzEquXbzkGu7uI=; b=fYyia0f1sbnv4dtVPuIlJDTyHPz/qVqtcamKw11JzO3Oye3HMfnQjXvVOLO9mQFQvy RM5hkz4mMh4+JT3/yhuq6HwfPgOJA3O63Qb9KkEUzpzVvViysz/dO4CXA+lCKYQDm+4k VIyTxVELCtBK2jLCWC6O0obQ23OPByYxYPgpRMCkKs8lZU3FEln+rDQ4ZOFCoSqm9myv m4tnqUFCgZ7B6IDwn1KMVAGr8j/vD6ptuqFrrfAEvudsFXEXghSR+cD7qS+zzg7tszI/ 8Ga/sfKCG0TkMP5I4i1+JPhhOqyYu/gxGvHQu5McPqjTNpolYtJt9fG8PFs6Sz3ok4qK pcUg== X-Gm-Message-State: AMCzsaWgeCqV0tRoeuzzSbCqiyX3XreAQyLmBZDnIBxa/qyCLjVzMCZ8 Qp81ZRbSGjqXNJ7HRtc4puXWyFmB X-Google-Smtp-Source: ABhQp+QaMGjvImkG3ojSywNKaQc8AfcWcT5i41y4J0gUWnQgo4J4qdJ209bYIl8MmPiIJidaGkA6iw== X-Received: by 10.28.4.150 with SMTP id 144mr6994538wme.79.1508343192711; Wed, 18 Oct 2017 09:13:12 -0700 (PDT) Received: from 640k.lan (94-39-155-245.adsl-ull.clienti.tiscali.it. [94.39.155.245]) by smtp.gmail.com with ESMTPSA id 69sm13436794wmm.2.2017.10.18.09.13.11 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Wed, 18 Oct 2017 09:13:12 -0700 (PDT) From: Paolo Bonzini To: qemu-devel@nongnu.org Date: Wed, 18 Oct 2017 18:12:04 +0200 Message-Id: <1508343141-31835-13-git-send-email-pbonzini@redhat.com> X-Mailer: git-send-email 1.8.3.1 In-Reply-To: <1508343141-31835-1-git-send-email-pbonzini@redhat.com> References: <1508343141-31835-1-git-send-email-pbonzini@redhat.com> X-detected-operating-system: by eggs.gnu.org: Genre and OS details not recognized. X-Received-From: 2a00:1450:400c:c09::241 Subject: [Qemu-devel] [PULL 12/29] docs/devel/loads-stores.rst: Document our various load and store APIs X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: Peter Maydell Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" From: Peter Maydell QEMU has a wide selection of different functions for doing loads and stores; provide some overview documentation of what they do and how to pick which one to use. Signed-off-by: Peter Maydell Reviewed-by: Eric Blake Message-Id: <1507813181-11860-1-git-send-email-peter.maydell@linaro.org> Signed-off-by: Paolo Bonzini --- docs/devel/loads-stores.rst | 396 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 396 insertions(+) create mode 100644 docs/devel/loads-stores.rst diff --git a/docs/devel/loads-stores.rst b/docs/devel/loads-stores.rst new file mode 100644 index 0000000..6a990cc --- /dev/null +++ b/docs/devel/loads-stores.rst @@ -0,0 +1,396 @@ +.. + 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. + +Regexes for git grep + - ``\`` + - ``\`` + +``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,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 + - ``\`` + - ``\`` + +``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 + - ``\`` + - ``\`` + +``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 + - ``\`` + - ``\`` + - ``\`` + +``{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 + - ``\`` + - ``\`` + +``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_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 + - ``\`` + +``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 + - ``\`` + - ``\`` + - ``\``