요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
==============
DMA attributes
==============
This document describes the semantics of the DMA attributes that are
defined in linux/dma-mapping.h.
DMA_ATTR_WEAK_ORDERING
----------------------
DMA_ATTR_WEAK_ORDERING specifies that reads and writes to the mapping
may be weakly ordered, that is that reads and writes may pass each other.
Since it is optional for platforms to implement DMA_ATTR_WEAK_ORDERING,
those that do not will simply ignore the attribute and exhibit default
behavior.
DMA_ATTR_WRITE_COMBINE
----------------------
DMA_ATTR_WRITE_COMBINE specifies that writes to the mapping may be
buffered to improve performance.
Since it is optional for platforms to implement DMA_ATTR_WRITE_COMBINE,
those that do not will simply ignore the attribute and exhibit default
behavior.
DMA_ATTR_NO_KERNEL_MAPPING
--------------------------
DMA_ATTR_NO_KERNEL_MAPPING lets the platform to avoid creating a kernel
virtual mapping for the allocated buffer. On some architectures creating
such mapping is non-trivial task and consumes very limited resources
(like kernel virtual address space or dma consistent address space).
Buffers allocated with this attribute can be only passed to user space
by calling dma_mmap_attrs(). By using this API, you are guaranteeing
that you won't dereference the pointer returned by dma_alloc_attr(). You
can treat it as a cookie that must be passed to dma_mmap_attrs() and
dma_free_attrs(). Make sure that both of these also get this attribute
set on each call.
Since it is optional for platforms to implement
DMA_ATTR_NO_KERNEL_MAPPING, those that do not will simply ignore the
attribute and exhibit default behavior.
DMA_ATTR_SKIP_CPU_SYNC
----------------------
By default dma_map_{single,page,sg} functions family transfer a given
buffer from CPU domain to device domain. Some advanced use cases might
require sharing a buffer between more than one device. This requires
having a mapping created separately for each device and is usually
performed by calling dma_map_{single,page,sg} function more than once
for the given buffer with device pointer to each device taking part in
the buffer sharing. The first call transfers a buffer from 'CPU' domain
to 'device' domain, what synchronizes CPU caches for the given region
(usually it means that the cache has been flushed or invalidated
depending on the dma direction). However, next calls to
dma_map_{single,page,sg}() for other devices will perform exactly the
same synchronization operation on the CPU cache. CPU cache synchronization
might be a time consuming operation, especially if the buffers are
large, so it is highly recommended to avoid it if possible.
DMA_ATTR_SKIP_CPU_SYNC allows platform code to skip synchronization of
the CPU cache for the given buffer assuming that it has been already
transferred to 'device' domain. This attribute can be also used for
dma_unmap_{single,page,sg} functions family to force buffer to stay in
device domain after releasing a mapping for it. Use this attribute with
care!
DMA_ATTR_FORCE_CONTIGUOUS
-------------------------
By default DMA-mapping subsystem is allowed to assemble the buffer
allocated by dma_alloc_attrs() function from individual pages if it can
be mapped as contiguous chunk into device dma address space. By
specifying this attribute the allocated buffer is forced to be contiguous
also in physical memory.
DMA_ATTR_ALLOC_SINGLE_PAGES
---------------------------
This is a hint to the DMA-mapping subsystem that it's probably not worth
the time to try to allocate memory to in a way that gives better TLB
efficiency (AKA it's not worth trying to build the mapping out of larger
pages). You might want to specify this if:
- You know that the accesses to this memory won't thrash the TLB.
You might know that the accesses are likely to be sequential or
that they aren't sequential but it's unlikely you'll ping-pong
between many addresses that are likely to be in different physical
pages.
- You know that the penalty of TLB misses while accessing the
memory will be small enough to be inconsequential. If you are
doing a heavy operation like decryption or decompression this
might be the case.
- You know that the DMA mapping is fairly transitory. If you expect
the mapping to have a short lifetime then it may be worth it to
optimize allocation (avoid coming up with large pages) instead of
getting the slight performance win of larger pages.
Setting this hint doesn't guarantee that you won't get huge pages, but it
means that we won't try quite as hard to get them.
.. note:: At the moment DMA_ATTR_ALLOC_SINGLE_PAGES is only implemented on ARM,
though ARM64 patches will likely be posted soon.
DMA_ATTR_NO_WARN
----------------
This tells the DMA-mapping subsystem to suppress allocation failure reports
(similarly to __GFP_NOWARN).
On some architectures allocation failures are reported with error messages
to the system logs. Although this can help to identify and debug problems,
drivers which handle failures (eg, retry later) have no problems with them,
and can actually flood the system logs with error messages that aren't any
problem at all, depending on the implementation of the retry mechanism.
So, this provides a way for drivers to avoid those error messages on calls
where allocation failures are not a problem, and shouldn't bother the logs.
.. note:: At the moment DMA_ATTR_NO_WARN is only implemented on PowerPC.
DMA_ATTR_PRIVILEGED
-------------------
Some advanced peripherals such as remote processors and GPUs perform
accesses to DMA buffers in both privileged "supervisor" and unprivileged
"user" modes. This attribute is used to indicate to the DMA-mapping
subsystem that the buffer is fully accessible at the elevated privilege
level (and ideally inaccessible or at least read-only at the
lesser-privileged levels).
DMA_ATTR_MMIO
-------------
This attribute indicates the physical address is not normal system
memory. It may not be used with kmap*()/phys_to_virt()/phys_to_page()
functions, it may not be cacheable, and access using CPU load/store
instructions may not be allowed.
Usually this will be used to describe MMIO addresses, or other non-cacheable
register addresses. When DMA mapping this sort of address we call
the operation Peer to Peer as a one device is DMA'ing to another device.
For PCI devices the p2pdma APIs must be used to determine if
DMA_ATTR_MMIO is appropriate.
For architectures that require cache flushing for DMA coherence
DMA_ATTR_MMIO will not perform any cache flushing. The address
provided must never be mapped cacheable into the CPU.
3. 한국어 전문 번역
영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.
DMA attribute 개요
1-7DMA attributes (DMA 속성)
이 문서는 `linux/dma-mapping.h`에 정의된 DMA attribute의 의미를 설명합니다.
DMA_ATTR_WEAK_ORDERING
8-17`DMA_ATTR_WEAK_ORDERING`
`DMA_ATTR_WEAK_ORDERING`은 mapping에 대한 read와 write가 weakly ordered일 수 있음을 지정합니다. 즉 read와 write가 서로 앞질러 실행될 수 있습니다.
Platform의 `DMA_ATTR_WEAK_ORDERING` 구현은 optional입니다. 구현하지 않은 platform은 attribute를 무시하고 기본 동작을 보입니다.
DMA_ATTR_WRITE_COMBINE
18-27`DMA_ATTR_WRITE_COMBINE`
`DMA_ATTR_WRITE_COMBINE`은 성능 향상을 위해 mapping으로 향하는 write를 buffer에 모을 수 있음을 지정합니다.
Platform의 `DMA_ATTR_WRITE_COMBINE` 구현은 optional입니다. 구현하지 않은 platform은 attribute를 무시하고 기본 동작을 보입니다.
DMA_ATTR_NO_KERNEL_MAPPING
28-45`DMA_ATTR_NO_KERNEL_MAPPING`
`DMA_ATTR_NO_KERNEL_MAPPING`은 allocate한 buffer에 대한 kernel virtual mapping 생성을 platform이 피할 수 있게 합니다. 일부 architecture에서 이런 mapping은 간단하지 않고 kernel virtual address space나 DMA consistent address space 같은 매우 제한적인 resource를 소비합니다.
이 attribute로 allocate한 buffer는 `dma_mmap_attrs()`를 호출해야만 user space에 전달할 수 있습니다. 이 API를 사용하면 `dma_alloc_attr()`가 반환한 pointer를 dereference하지 않겠다고 보장하는 것입니다. Pointer는 `dma_mmap_attrs()`와 `dma_free_attrs()`에 전달해야 하는 cookie로 취급하고 두 호출에도 항상 이 attribute를 설정해야 합니다.
이 attribute 역시 optional이므로 구현하지 않은 platform은 무시하고 기본 동작을 사용합니다.
DMA_ATTR_SKIP_CPU_SYNC
46-69`DMA_ATTR_SKIP_CPU_SYNC`
기본적으로 `dma_map_{single,page,sg}` 함수군은 주어진 buffer를 CPU domain에서 device domain으로 이전합니다. 여러 device가 한 buffer를 공유하는 고급 용도에서는 참여 device마다 별도 mapping을 만들어 같은 buffer에 각 device pointer로 mapping 함수를 여러 번 호출합니다.
첫 호출은 buffer를 CPU domain에서 device domain으로 옮기며 DMA direction에 따라 해당 region의 CPU cache를 flush 또는 invalidate합니다. 다른 device를 위한 다음 호출도 같은 CPU cache synchronization을 반복합니다. 큰 buffer에서는 시간이 많이 들 수 있으므로 가능하면 피하는 것이 좋습니다.
`DMA_ATTR_SKIP_CPU_SYNC`는 buffer가 이미 device domain으로 이전되었다고 가정하고 platform code가 CPU cache synchronization을 생략하도록 합니다. `dma_unmap_{single,page,sg}` 함수군에도 사용하여 mapping 해제 뒤 buffer가 device domain에 남도록 강제할 수 있습니다. 매우 주의해서 사용해야 합니다.
DMA_ATTR_FORCE_CONTIGUOUS
70-78`DMA_ATTR_FORCE_CONTIGUOUS`
기본적으로 DMA-mapping subsystem은 `dma_alloc_attrs()`가 allocate하는 buffer를 device DMA address space에서 contiguous chunk로 mapping할 수 있다면 개별 page를 조립해 만들 수 있습니다. 이 attribute를 지정하면 allocate한 buffer가 physical memory에서도 연속되도록 강제합니다.
DMA_ATTR_ALLOC_SINGLE_PAGES
79-106`DMA_ATTR_ALLOC_SINGLE_PAGES`
이 attribute는 더 나은 TLB 효율을 위해 큰 page로 mapping을 구성하려고 시간을 들이는 것이 가치 없을 가능성이 높다는 hint입니다. 다음 상황에서 지정할 수 있습니다.
- 이 memory 접근이 TLB thrashing을 일으키지 않음을 알고 있는 경우입니다. 접근이 sequential하거나, 비순차적이어도 서로 다른 physical page에 있을 법한 많은 address 사이를 오갈 가능성이 낮을 수 있습니다.
- Memory 접근 중 TLB miss penalty가 무시할 만큼 작음을 아는 경우입니다. Decryption이나 decompression 같은 무거운 operation이 이에 해당할 수 있습니다.
- DMA mapping 수명이 상당히 짧다고 아는 경우입니다. 큰 page의 소폭 성능 향상보다 큰 page를 만들지 않아 allocation을 최적화하는 편이 나을 수 있습니다.
이 hint를 설정해도 huge page를 절대 받지 않는다는 보장은 없지만, subsystem이 이를 얻기 위해 큰 노력을 기울이지 않게 합니다.
현재 `DMA_ATTR_ALLOC_SINGLE_PAGES`는 ARM에서만 구현되어 있으며 ARM64 patch도 곧 제출될 가능성이 있습니다.
DMA_ATTR_NO_WARN
107-123`DMA_ATTR_NO_WARN`
`DMA_ATTR_NO_WARN`은 `__GFP_NOWARN`과 비슷하게 DMA-mapping subsystem이 allocation failure report를 억제하도록 합니다.
일부 architecture는 allocation failure를 system log의 error message로 보고합니다. 문제 식별에는 도움이 되지만 실패를 나중에 재시도하는 등 정상 처리하는 driver에서는 retry 구현에 따라 실제 문제가 아닌 message로 log를 가득 채울 수 있습니다.
따라서 allocation failure가 문제가 아니고 log를 방해할 필요가 없는 호출에서 driver가 error message를 피할 수 있게 합니다.
현재 `DMA_ATTR_NO_WARN`은 PowerPC에서만 구현되어 있습니다.
DMA_ATTR_PRIVILEGED
124-133`DMA_ATTR_PRIVILEGED`
Remote processor와 GPU 같은 일부 고급 peripheral은 privileged `supervisor` mode와 unprivileged `user` mode 모두에서 DMA buffer에 접근합니다. 이 attribute는 높은 privilege level에서 buffer 전체에 접근할 수 있고, 낮은 privilege level에서는 이상적으로 접근 불가이거나 최소한 read-only임을 DMA-mapping subsystem에 알립니다.
DMA_ATTR_MMIO
134-150`DMA_ATTR_MMIO`
이 attribute는 physical address가 normal system memory가 아님을 나타냅니다. `kmap*()`, `phys_to_virt()`, `phys_to_page()`와 함께 사용할 수 없고 cacheable하지 않을 수 있으며 CPU load/store instruction 접근이 허용되지 않을 수도 있습니다.
보통 MMIO address나 그 밖의 non-cacheable register address를 설명할 때 사용합니다. 한 device가 다른 device로 DMA하는 이런 address mapping을 Peer to Peer operation이라 합니다. PCI device는 `DMA_ATTR_MMIO`가 적절한지 판단할 때 `p2pdma` API를 사용해야 합니다.
DMA coherency를 위해 cache flush가 필요한 architecture에서도 `DMA_ATTR_MMIO`는 cache flush를 수행하지 않습니다. 제공된 address를 CPU에 cacheable하게 mapping해서는 절대 안 됩니다.
요약과 해설
dma-attributes.rst:1-150DMA attribute는 generic DMA API의 기본 계약에 선택적인 platform별 의미를 더합니다. 구현하지 않은 optional attribute는 무시될 수 있으므로 driver는 attribute 없이도 정확성이 유지되는지 구분해야 합니다.
`DMA_ATTR_SKIP_CPU_SYNC`는 여러 device가 buffer를 공유할 때 중복 cache synchronization을 피하지만 ownership을 정확히 추적해야 합니다. `DMA_ATTR_FORCE_CONTIGUOUS`와 `DMA_ATTR_ALLOC_SINGLE_PAGES`는 서로 다른 allocation 목적을 나타냅니다.
`DMA_ATTR_MMIO`는 normal RAM이 아닌 peer device address를 위한 것으로 CPU cacheable mapping과 일반 page 변환 API를 금지합니다. PCI에서는 `p2pdma` API로 적합성을 확인해야 합니다.