요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
========================
The io_mapping functions
========================
API
===
The io_mapping functions in linux/io-mapping.h provide an abstraction for
efficiently mapping small regions of an I/O device to the CPU. The initial
usage is to support the large graphics aperture on 32-bit processors where
ioremap_wc cannot be used to statically map the entire aperture to the CPU
as it would consume too much of the kernel address space.
A mapping object is created during driver initialization using::
struct io_mapping *io_mapping_create_wc(unsigned long base,
unsigned long size)
'base' is the bus address of the region to be made
mappable, while 'size' indicates how large a mapping region to
enable. Both are in bytes.
This _wc variant provides a mapping which may only be used with
io_mapping_map_atomic_wc(), io_mapping_map_local_wc() or
io_mapping_map_wc().
With this mapping object, individual pages can be mapped either temporarily
or long term, depending on the requirements. Of course, temporary maps are
more efficient. They come in two flavours::
void *io_mapping_map_local_wc(struct io_mapping *mapping,
unsigned long offset)
void *io_mapping_map_atomic_wc(struct io_mapping *mapping,
unsigned long offset)
'offset' is the offset within the defined mapping region. Accessing
addresses beyond the region specified in the creation function yields
undefined results. Using an offset which is not page aligned yields an
undefined result. The return value points to a single page in CPU address
space.
This _wc variant returns a write-combining map to the page and may only be
used with mappings created by io_mapping_create_wc()
Temporary mappings are only valid in the context of the caller. The mapping
is not guaranteed to be globally visible.
io_mapping_map_local_wc() has a side effect on X86 32bit as it disables
migration to make the mapping code work. No caller can rely on this side
effect.
io_mapping_map_atomic_wc() has the side effect of disabling preemption and
pagefaults. Don't use in new code. Use io_mapping_map_local_wc() instead.
Nested mappings need to be undone in reverse order because the mapping
code uses a stack for keeping track of them::
addr1 = io_mapping_map_local_wc(map1, offset1);
addr2 = io_mapping_map_local_wc(map2, offset2);
...
io_mapping_unmap_local(addr2);
io_mapping_unmap_local(addr1);
The mappings are released with::
void io_mapping_unmap_local(void *vaddr)
void io_mapping_unmap_atomic(void *vaddr)
'vaddr' must be the value returned by the last io_mapping_map_local_wc() or
io_mapping_map_atomic_wc() call. This unmaps the specified mapping and
undoes the side effects of the mapping functions.
If you need to sleep while holding a mapping, you can use the regular
variant, although this may be significantly slower::
void *io_mapping_map_wc(struct io_mapping *mapping,
unsigned long offset)
This works like io_mapping_map_atomic/local_wc() except it has no side
effects and the pointer is globally visible.
The mappings are released with::
void io_mapping_unmap(void *vaddr)
Use for pages mapped with io_mapping_map_wc().
At driver close time, the io_mapping object must be freed::
void io_mapping_free(struct io_mapping *mapping)
3. 한국어 전문 번역
영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.
io_mapping abstraction
1-13문서 제목은 `The io_mapping functions`입니다. `linux/io-mapping.h`의 io_mapping function은 I/O device의 작은 region을 CPU에 효율적으로 mapping하는 abstraction을 제공합니다.
초기 use case는 32-bit processor의 큰 graphics aperture입니다. 전체 aperture를 `ioremap_wc`로 CPU에 static mapping하면 kernel address space를 너무 많이 소비하므로 사용할 수 없습니다.
큰 device aperture에서 필요한 page만 mapping합니다.
Write-combining mapping 생성
14-25Driver initialization 때 `io_mapping_create_wc(base, size)`로 mapping object를 만듭니다. `base`는 mapping할 region의 bus address이고 `size`는 enable할 mapping region 크기이며 둘 다 byte 단위입니다.
struct io_mapping *io_mapping_create_wc(unsigned long base,
unsigned long size)
이 `_wc` variant가 만든 mapping은 `io_mapping_map_atomic_wc()`, `io_mapping_map_local_wc()`, `io_mapping_map_wc()`에만 사용할 수 있습니다.
Mapping 가능 bus range를 정의합니다.
Temporary page mapping
26-55Mapping object가 있으면 필요에 따라 individual page를 temporary 또는 long-term으로 mapping할 수 있으며 temporary map이 더 효율적입니다. Temporary 방식은 local과 atomic 두 가지입니다.
void *io_mapping_map_local_wc(struct io_mapping *mapping,
unsigned long offset)
void *io_mapping_map_atomic_wc(struct io_mapping *mapping,
unsigned long offset)
`offset`은 정의한 mapping region 안 offset입니다. Creation 범위를 벗어난 address나 page-aligned가 아닌 offset을 사용하면 결과가 undefined입니다. Return value는 CPU address space의 single page를 가리킵니다.
두 `_wc` variant는 write-combining page map을 반환하며 `io_mapping_create_wc()`로 만든 mapping에만 쓸 수 있습니다. Temporary mapping은 caller context에서만 valid하고 globally visible하다고 보장되지 않습니다.
`io_mapping_map_local_wc()`는 x86 32-bit에서 mapping code를 위해 migration을 disable하는 side effect가 있지만 caller는 이에 의존하면 안 됩니다. `io_mapping_map_atomic_wc()`는 preemption과 page fault를 disable하므로 new code에서 쓰지 말고 local variant를 사용해야 합니다.
Local과 atomic variant의 side effect와 권장 여부입니다.
Nested mapping 해제 순서
56-64Mapping code가 stack으로 nested mapping을 추적하므로 중첩 mapping은 생성의 reverse order로 undo해야 합니다. `map1` 뒤 `map2`를 mapping했다면 `addr2`를 먼저, `addr1`을 나중에 unmap합니다.
addr1 = io_mapping_map_local_wc(map1, offset1);
addr2 = io_mapping_map_local_wc(map2, offset2);
...
io_mapping_unmap_local(addr2);
io_mapping_unmap_local(addr1);
Nested local mapping의 stack discipline입니다.
Temporary mapping 해제
65-73Temporary mapping은 `io_mapping_unmap_local(vaddr)` 또는 `io_mapping_unmap_atomic(vaddr)`으로 해제합니다.
void io_mapping_unmap_local(void *vaddr)
void io_mapping_unmap_atomic(void *vaddr)
`vaddr`은 마지막 `io_mapping_map_local_wc()` 또는 `io_mapping_map_atomic_wc()` 호출이 반환한 값이어야 합니다. Unmap은 지정 mapping을 해제하고 mapping function의 side effect도 되돌립니다.
Variant별 올바른 해제 function입니다.
Sleep 가능한 regular mapping
74-87Mapping을 유지한 채 sleep해야 한다면 significantly slower일 수 있는 regular variant `io_mapping_map_wc()`를 사용합니다.
void *io_mapping_map_wc(struct io_mapping *mapping,
unsigned long offset)
이 function은 atomic/local `_wc`와 비슷하지만 side effect가 없고 pointer가 globally visible합니다. 해제는 `io_mapping_unmap()`을 사용합니다.
void io_mapping_unmap(void *vaddr)
Visibility·sleep·성능을 비교합니다.
Mapping object 해제
88-91Driver close 시점에는 `io_mapping_free(mapping)`으로 io_mapping object를 반드시 해제해야 합니다.
void io_mapping_free(struct io_mapping *mapping)
Driver init부터 close까지의 resource lifecycle입니다.
요약과 해설
io-mapping.rst:1-91io_mapping은 32-bit kernel address space를 아끼며 큰 device aperture의 필요한 page만 mapping합니다. Temporary mapping은 caller context와 LIFO unmap 규칙을 지켜야 하고, sleep이 필요하면 느리지만 globally visible한 regular mapping을 사용합니다.