lists.openwall.net   lists  /  announce  owl-users  owl-dev  john-users  john-dev  passwdqc-users  yescrypt  popa3d-users  /  oss-security  kernel-hardening  musl  sabotage  tlsify  passwords  /  crypt-dev  xvendor  /  Bugtraq  Full-Disclosure  linux-kernel  linux-netdev  linux-ext4  linux-hardening  linux-cve-announce  PHC 
Open Source and information security mailing list archives
 
Hash Suite for Android: free password hash cracker in your pocket
[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-ID: <5362505E.8010106@infradead.org>
Date:	Thu, 01 May 2014 06:47:10 -0700
From:	Randy Dunlap <rdunlap@...radead.org>
To:	Bjorn Helgaas <bhelgaas@...gle.com>
CC:	linux-pci@...r.kernel.org, linux-kernel@...r.kernel.org,
	"James E.J. Bottomley" <JBottomley@...allels.com>,
	linux-doc@...r.kernel.org
Subject: Re: [PATCH] DMA-API: Clarify physical/bus address distinction

On 04/30/2014 12:42 PM, Bjorn Helgaas wrote:
> The DMA-API documentation sometimes refers to "physical addresses" when it
> really means "bus addresses."  Historically these were often the same, but
> they may be different if the bridge leading to the bus performs address
> transaction.  Update the documentation to use "bus address" when

   translation.

The changes look OK to me.
Hopefully James and other interested parties can also review this.


> appropriate.
>
> Also, consistently capitalize "DMA" and reword a few sections to improve
> clarity.
>
> Signed-off-by: Bjorn Helgaas <bhelgaas@...gle.com>
> ---
>   Documentation/DMA-API-HOWTO.txt |   26 ++++------
>   Documentation/DMA-API.txt       |  103 +++++++++++++++++++--------------------
>   Documentation/DMA-ISA-LPC.txt   |    4 +-
>   3 files changed, 64 insertions(+), 69 deletions(-)
>
> diff --git a/Documentation/DMA-API-HOWTO.txt b/Documentation/DMA-API-HOWTO.txt
> index 5e983031cc11..fe1f710c3882 100644
> --- a/Documentation/DMA-API-HOWTO.txt
> +++ b/Documentation/DMA-API-HOWTO.txt
> @@ -9,16 +9,14 @@ This is a guide to device driver writers on how to use the DMA API
>   with example pseudo-code.  For a concise description of the API, see
>   DMA-API.txt.
>
> -Most of the 64bit platforms have special hardware that translates bus
> +Most 64bit platforms have special IOMMU hardware that translates bus
>   addresses (DMA addresses) into physical addresses.  This is similar to
>   how page tables and/or a TLB translates virtual addresses to physical
>   addresses on a CPU.  This is needed so that e.g. PCI devices can
>   access with a Single Address Cycle (32bit DMA address) any page in the
>   64bit physical address space.  Previously in Linux those 64bit
>   platforms had to set artificial limits on the maximum RAM size in the
> -system, so that the virt_to_bus() static scheme works (the DMA address
> -translation tables were simply filled on bootup to map each bus
> -address to the physical page __pa(bus_to_virt())).
> +system so devices could address all physical memory.
>
>   So that Linux can use the dynamic DMA mapping, it needs some help from the
>   drivers, namely it has to take into account that DMA addresses should be
> @@ -30,7 +28,7 @@ hardware exists.
>
>   Note that the DMA API works with any bus independent of the underlying
>   microprocessor architecture. You should use the DMA API rather than
> -the bus specific DMA API (e.g. pci_dma_*).
> +the bus-specific DMA API (e.g. pci_dma_*).
>
>   First of all, you should make sure
>
> @@ -347,7 +345,7 @@ dma_alloc_coherent returns two values: the virtual address which you
>   can use to access it from the CPU and dma_handle which you pass to the
>   card.
>
> -The cpu return address and the DMA bus master address are both
> +The CPU virtual address and the DMA bus address are both
>   guaranteed to be aligned to the smallest PAGE_SIZE order which
>   is greater than or equal to the requested size.  This invariant
>   exists (for example) to guarantee that if you allocate a chunk
> @@ -383,7 +381,7 @@ pass 0 for alloc; passing 4096 says memory allocated from this pool
>   must not cross 4KByte boundaries (but at that time it may be better to
>   go for dma_alloc_coherent directly instead).
>
> -Allocate memory from a dma pool like this:
> +Allocate memory from a DMA pool like this:
>
>   	cpu_addr = dma_pool_alloc(pool, flags, &dma_handle);
>
> @@ -489,14 +487,14 @@ and to unmap it:
>   	dma_unmap_single(dev, dma_handle, size, direction);
>
>   You should call dma_mapping_error() as dma_map_single() could fail and return
> -error. Not all dma implementations support dma_mapping_error() interface.
> +error. Not all DMA implementations support the dma_mapping_error() interface.
>   However, it is a good practice to call dma_mapping_error() interface, which
>   will invoke the generic mapping error check interface. Doing so will ensure
> -that the mapping code will work correctly on all dma implementations without
> +that the mapping code will work correctly on all DMA implementations without
>   any dependency on the specifics of the underlying implementation. Using the
>   returned address without checking for errors could result in failures ranging
>   from panics to silent data corruption. A couple of examples of incorrect ways
> -to check for errors that make assumptions about the underlying dma
> +to check for errors that make assumptions about the underlying DMA
>   implementation are as follows and these are applicable to dma_map_page() as
>   well.
>
> @@ -589,14 +587,12 @@ PLEASE NOTE:  The 'nents' argument to the dma_unmap_sg call must be
>                 dma_map_sg call.
>
>   Every dma_map_{single,sg} call should have its dma_unmap_{single,sg}
> -counterpart, because the bus address space is a shared resource (although
> -in some ports the mapping is per each BUS so less devices contend for the
> -same bus address space) and you could render the machine unusable by eating
> -all bus addresses.
> +counterpart, because the bus address space is a shared resource and
> +you could render the machine unusable by consuming all bus addresses.
>
>   If you need to use the same streaming DMA region multiple times and touch
>   the data in between the DMA transfers, the buffer needs to be synced
> -properly in order for the cpu and device to see the most uptodate and
> +properly in order for the cpu and device to see the most up-to-date and
>   correct copy of the DMA buffer.
>
>   So, firstly, just map it with dma_map_{single,sg}, and after each DMA
> diff --git a/Documentation/DMA-API.txt b/Documentation/DMA-API.txt
> index e865279cec58..0371ad0f37e7 100644
> --- a/Documentation/DMA-API.txt
> +++ b/Documentation/DMA-API.txt
> @@ -4,14 +4,13 @@
>           James E.J. Bottomley <James.Bottomley@...senPartnership.com>
>
>   This document describes the DMA API.  For a more gentle introduction
> -of the API (and actual examples) see
> -Documentation/DMA-API-HOWTO.txt.
> +of the API (and actual examples), see Documentation/DMA-API-HOWTO.txt.
>
> -This API is split into two pieces.  Part I describes the API.  Part II
> -describes the extensions to the API for supporting non-consistent
> -memory machines.  Unless you know that your driver absolutely has to
> -support non-consistent platforms (this is usually only legacy
> -platforms) you should only use the API described in part I.
> +This API is split into two pieces.  Part I describes the basic API.
> +Part II describes extensions for supporting non-consistent memory
> +machines.  Unless you know that your driver absolutely has to support
> +non-consistent platforms (this is usually only legacy platforms) you
> +should only use the API described in part I.
>
>   Part I - dma_ API
>   -------------------------------------
> @@ -19,7 +18,7 @@ Part I - dma_ API
>   To get the dma_ API, you must #include <linux/dma-mapping.h>
>
>
> -Part Ia - Using large dma-coherent buffers
> +Part Ia - Using large DMA-coherent buffers
>   ------------------------------------------
>
>   void *
> @@ -34,8 +33,8 @@ devices to read that memory.)
>
>   This routine allocates a region of <size> bytes of consistent memory.
>   It also returns a <dma_handle> which may be cast to an unsigned
> -integer the same width as the bus and used as the physical address
> -base of the region.
> +integer the same width as the bus and used as the bus address base
> +of the region.
>
>   Returns: a pointer to the allocated region (in the processor's virtual
>   address space) or NULL if the allocation failed.
> @@ -70,15 +69,15 @@ Note that unlike their sibling allocation calls, these routines
>   may only be called with IRQs enabled.
>
>
> -Part Ib - Using small dma-coherent buffers
> +Part Ib - Using small DMA-coherent buffers
>   ------------------------------------------
>
>   To get this part of the dma_ API, you must #include <linux/dmapool.h>
>
> -Many drivers need lots of small dma-coherent memory regions for DMA
> +Many drivers need lots of small DMA-coherent memory regions for DMA
>   descriptors or I/O buffers.  Rather than allocating in units of a page
>   or more using dma_alloc_coherent(), you can use DMA pools.  These work
> -much like a struct kmem_cache, except that they use the dma-coherent allocator,
> +much like a struct kmem_cache, except that they use the DMA-coherent allocator,
>   not __get_free_pages().  Also, they understand common hardware constraints
>   for alignment, like queue heads needing to be aligned on N-byte boundaries.
>
> @@ -87,7 +86,7 @@ for alignment, like queue heads needing to be aligned on N-byte boundaries.
>   	dma_pool_create(const char *name, struct device *dev,
>   			size_t size, size_t align, size_t alloc);
>
> -The pool create() routines initialize a pool of dma-coherent buffers
> +The pool create() routines initialize a pool of DMA-coherent buffers
>   for use with a given device.  It must be called in a context which
>   can sleep.
>
> @@ -102,19 +101,20 @@ from this pool must not cross 4KByte boundaries.
>   	void *dma_pool_alloc(struct dma_pool *pool, gfp_t gfp_flags,
>   			dma_addr_t *dma_handle);
>
> -This allocates memory from the pool; the returned memory will meet the size
> -and alignment requirements specified at creation time.  Pass GFP_ATOMIC to
> -prevent blocking, or if it's permitted (not in_interrupt, not holding SMP locks),
> -pass GFP_KERNEL to allow blocking.  Like dma_alloc_coherent(), this returns
> -two values:  an address usable by the cpu, and the dma address usable by the
> -pool's device.
> +This allocates memory from the pool; the returned memory will meet the
> +size and alignment requirements specified at creation time.  Pass
> +GFP_ATOMIC to prevent blocking, or if it's permitted (not
> +in_interrupt, not holding SMP locks), pass GFP_KERNEL to allow
> +blocking.  Like dma_alloc_coherent(), this returns two values:  an
> +address usable by the cpu, and the DMA address usable by the pool's
> +device.
>
>
>   	void dma_pool_free(struct dma_pool *pool, void *vaddr,
>   			dma_addr_t addr);
>
>   This puts memory back into the pool.  The pool is what was passed to
> -the pool allocation routine; the cpu (vaddr) and dma addresses are what
> +the pool allocation routine; the cpu (vaddr) and DMA addresses are what
>   were returned when that routine allocated the memory being freed.
>
>
> @@ -187,9 +187,9 @@ dma_map_single(struct device *dev, void *cpu_addr, size_t size,
>   		      enum dma_data_direction direction)
>
>   Maps a piece of processor virtual memory so it can be accessed by the
> -device and returns the physical handle of the memory.
> +device and returns the bus address of the memory.
>
> -The direction for both api's may be converted freely by casting.
> +The direction for both APIs may be converted freely by casting.
>   However the dma_ API uses a strongly typed enumerator for its
>   direction:
>
> @@ -198,31 +198,30 @@ DMA_TO_DEVICE		data is going from the memory to the device
>   DMA_FROM_DEVICE		data is coming from the device to the memory
>   DMA_BIDIRECTIONAL	direction isn't known
>
> -Notes:  Not all memory regions in a machine can be mapped by this
> -API.  Further, regions that appear to be physically contiguous in
> -kernel virtual space may not be contiguous as physical memory.  Since
> -this API does not provide any scatter/gather capability, it will fail
> -if the user tries to map a non-physically contiguous piece of memory.
> -For this reason, it is recommended that memory mapped by this API be
> -obtained only from sources which guarantee it to be physically contiguous
> -(like kmalloc).
> -
> -Further, the physical address of the memory must be within the
> -dma_mask of the device (the dma_mask represents a bit mask of the
> -addressable region for the device.  I.e., if the physical address of
> -the memory anded with the dma_mask is still equal to the physical
> -address, then the device can perform DMA to the memory).  In order to
> +Notes:  Not all memory regions in a machine can be mapped by this API.
> +Further, contiguous kernel virtual space may not be contiguous as
> +physical memory.  Since this API does not provide any scatter/gather
> +capability, it will fail if the user tries to map a non-physically
> +contiguous piece of memory.  For this reason, memory to be mapped by
> +this API should be obtained from sources which guarantee it to be
> +physically contiguous (like kmalloc).
> +
> +Further, the bus address of the memory must be within the
> +dma_mask of the device (the dma_mask is a bit mask of the
> +addressable region for the device, i.e., if the bus address of
> +the memory ANDed with the dma_mask is still equal to the bus
> +address, then the device can perform DMA to the memory).  To
>   ensure that the memory allocated by kmalloc is within the dma_mask,
>   the driver may specify various platform-dependent flags to restrict
> -the physical memory range of the allocation (e.g. on x86, GFP_DMA
> -guarantees to be within the first 16Mb of available physical memory,
> +the bus address range of the allocation (e.g., on x86, GFP_DMA
> +guarantees to be within the first 16MB of available bus addresses,
>   as required by ISA devices).
>
>   Note also that the above constraints on physical contiguity and
>   dma_mask may not apply if the platform has an IOMMU (a device which
> -supplies a physical to virtual mapping between the I/O memory bus and
> -the device).  However, to be portable, device driver writers may *not*
> -assume that such an IOMMU exists.
> +maps an I/O bus address to a physical memory address).  However, to be
> +portable, device driver writers may *not* assume that such an IOMMU
> +exists.
>
>   Warnings:  Memory coherency operates at a granularity called the cache
>   line width.  In order for memory mapped by this API to operate
> @@ -283,7 +282,7 @@ dma_mapping_error(struct device *dev, dma_addr_t dma_addr)
>
>   In some circumstances dma_map_single and dma_map_page will fail to create
>   a mapping. A driver can check for these errors by testing the returned
> -dma address with dma_mapping_error(). A non-zero return value means the mapping
> +DMA address with dma_mapping_error(). A non-zero return value means the mapping
>   could not be created and the driver should take appropriate action (e.g.
>   reduce current DMA mapping usage or delay and try again later).
>
> @@ -291,7 +290,7 @@ reduce current DMA mapping usage or delay and try again later).
>   	dma_map_sg(struct device *dev, struct scatterlist *sg,
>   		int nents, enum dma_data_direction direction)
>
> -Returns: the number of physical segments mapped (this may be shorter
> +Returns: the number of bus address segments mapped (this may be shorter
>   than <nents> passed in if some elements of the scatter/gather list are
>   physically or virtually adjacent and an IOMMU maps them with a single
>   entry).
> @@ -335,7 +334,7 @@ must be the same as those and passed in to the scatter/gather mapping
>   API.
>
>   Note: <nents> must be the number you passed in, *not* the number of
> -physical entries returned.
> +bus address entries returned.
>
>   void
>   dma_sync_single_for_cpu(struct device *dev, dma_addr_t dma_handle, size_t size,
> @@ -391,10 +390,10 @@ The four functions above are just like the counterpart functions
>   without the _attrs suffixes, except that they pass an optional
>   struct dma_attrs*.
>
> -struct dma_attrs encapsulates a set of "dma attributes". For the
> +struct dma_attrs encapsulates a set of "DMA attributes". For the
>   definition of struct dma_attrs see linux/dma-attrs.h.
>
> -The interpretation of dma attributes is architecture-specific, and
> +The interpretation of DMA attributes is architecture-specific, and
>   each attribute should be documented in Documentation/DMA-attributes.txt.
>
>   If struct dma_attrs* is NULL, the semantics of each of these
> @@ -458,7 +457,7 @@ Note: where the platform can return consistent memory, it will
>   guarantee that the sync points become nops.
>
>   Warning:  Handling non-consistent memory is a real pain.  You should
> -only ever use this API if you positively know your driver will be
> +only use this API if you positively know your driver will be
>   required to work on one of the rare (usually non-PCI) architectures
>   that simply cannot make consistent memory.
>
> @@ -503,13 +502,13 @@ bus_addr is the physical address to which the memory is currently
>   assigned in the bus responding region (this will be used by the
>   platform to perform the mapping).
>
> -device_addr is the physical address the device needs to be programmed
> +device_addr is the bus address the device needs to be programmed
>   with actually to address this memory (this will be handed out as the
>   dma_addr_t in dma_alloc_coherent()).
>
>   size is the size of the area (must be multiples of PAGE_SIZE).
>
> -flags can be or'd together and are:
> +flags can be ORed together and are:
>
>   DMA_MEMORY_MAP - request that the memory returned from
>   dma_alloc_coherent() be directly writable.
> @@ -690,11 +689,11 @@ architectural default.
>   void debug_dmap_mapping_error(struct device *dev, dma_addr_t dma_addr);
>
>   dma-debug interface debug_dma_mapping_error() to debug drivers that fail
> -to check dma mapping errors on addresses returned by dma_map_single() and
> +to check DMA mapping errors on addresses returned by dma_map_single() and
>   dma_map_page() interfaces. This interface clears a flag set by
>   debug_dma_map_page() to indicate that dma_mapping_error() has been called by
>   the driver. When driver does unmap, debug_dma_unmap() checks the flag and if
>   this flag is still set, prints warning message that includes call trace that
>   leads up to the unmap. This interface can be called from dma_mapping_error()
> -routines to enable dma mapping error check debugging.
> +routines to enable DMA mapping error check debugging.
>
> diff --git a/Documentation/DMA-ISA-LPC.txt b/Documentation/DMA-ISA-LPC.txt
> index e767805b4182..b1a19835e907 100644
> --- a/Documentation/DMA-ISA-LPC.txt
> +++ b/Documentation/DMA-ISA-LPC.txt
> @@ -16,7 +16,7 @@ To do ISA style DMA you need to include two headers:
>   #include <asm/dma.h>
>
>   The first is the generic DMA API used to convert virtual addresses to
> -physical addresses (see Documentation/DMA-API.txt for details).
> +bus addresses (see Documentation/DMA-API.txt for details).
>
>   The second contains the routines specific to ISA DMA transfers. Since
>   this is not present on all platforms make sure you construct your
> @@ -50,7 +50,7 @@ early as possible and not release it until the driver is unloaded.)
>   Part III - Address translation
>   ------------------------------
>
> -To translate the virtual address to a physical use the normal DMA
> +To translate the virtual address to a bus address, use the normal DMA
>   API. Do _not_ use isa_virt_to_phys() even though it does the same
>   thing. The reason for this is that the function isa_virt_to_phys()
>   will require a Kconfig dependency to ISA, not just ISA_DMA_API which
>
> --



-- 
~Randy
--
To unsubscribe from this list: send the line "unsubscribe linux-kernel" in
the body of a message to majordomo@...r.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html
Please read the FAQ at  http://www.tux.org/lkml/

Powered by blists - more mailing lists

Powered by Openwall GNU/*/Linux Powered by OpenVZ