요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
===========
Deferred IO
===========
Deferred IO is a way to delay and repurpose IO. It uses host memory as a
buffer and the MMU pagefault as a pretrigger for when to perform the device
IO. The following example may be a useful explanation of how one such setup
works:
- userspace app like Xfbdev mmaps framebuffer
- deferred IO and driver sets up fault and page_mkwrite handlers
- userspace app tries to write to mmapped vaddress
- we get pagefault and reach fault handler
- fault handler finds and returns physical page
- we get page_mkwrite where we add this page to a list
- schedule a workqueue task to be run after a delay
- app continues writing to that page with no additional cost. this is
the key benefit.
- the workqueue task comes in and mkcleans the pages on the list, then
completes the work associated with updating the framebuffer. this is
the real work talking to the device.
- app tries to write to the address (that has now been mkcleaned)
- get pagefault and the above sequence occurs again
As can be seen from above, one benefit is roughly to allow bursty framebuffer
writes to occur at minimum cost. Then after some time when hopefully things
have gone quiet, we go and really update the framebuffer which would be
a relatively more expensive operation.
For some types of nonvolatile high latency displays, the desired image is
the final image rather than the intermediate stages which is why it's okay
to not update for each write that is occurring.
It may be the case that this is useful in other scenarios as well. Paul Mundt
has mentioned a case where it is beneficial to use the page count to decide
whether to coalesce and issue SG DMA or to do memory bursts.
Another one may be if one has a device framebuffer that is in an usual format,
say diagonally shifting RGB, this may then be a mechanism for you to allow
apps to pretend to have a normal framebuffer but reswizzle for the device
framebuffer at vsync time based on the touched pagelist.
How to use it: (for applications)
---------------------------------
No changes needed. mmap the framebuffer like normal and just use it.
How to use it: (for fbdev drivers)
----------------------------------
The following example may be helpful.
1. Setup your structure. Eg::
static struct fb_deferred_io hecubafb_defio = {
.delay = HZ,
.deferred_io = hecubafb_dpy_deferred_io,
};
The delay is the minimum delay between when the page_mkwrite trigger occurs
and when the deferred_io callback is called. The deferred_io callback is
explained below.
2. Setup your deferred IO callback. Eg::
static void hecubafb_dpy_deferred_io(struct fb_info *info,
struct list_head *pagelist)
The deferred_io callback is where you would perform all your IO to the display
device. You receive the pagelist which is the list of pages that were written
to during the delay. You must not modify this list. This callback is called
from a workqueue.
3. Call init::
info->fbdefio = &hecubafb_defio;
fb_deferred_io_init(info);
4. Call cleanup::
fb_deferred_io_cleanup(info);
3. 한국어 전문 번역
영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.
Deferred I/O page-fault 흐름
1-24Deferred I/O는 I/O를 지연하고 다른 방식으로 활용하는 기법입니다. Host memory를 buffer로 사용하고 MMU page fault를 device I/O 수행 시점을 알리는 pretrigger로 사용합니다.
Xfbdev 같은 userspace application이 framebuffer를 `mmap()`하면 deferred I/O와 driver가 `fault` 및 `page_mkwrite` handler를 설치합니다. Application이 mapped virtual address에 처음 쓰면 page fault가 발생하고 fault handler가 physical page를 찾아 반환합니다.
이어 `page_mkwrite`가 해당 page를 list에 넣고 지연 후 실행할 workqueue task를 예약합니다. 이후 application은 추가 비용 없이 그 page에 계속 쓸 수 있으며 이것이 핵심 이점입니다.
Workqueue task는 list의 page를 `mkclean`하고 실제 device와 통신해 framebuffer를 갱신합니다. Application이 clean 처리된 address에 다시 쓰면 page fault가 발생해 같은 sequence가 반복됩니다.
Page fault를 변경 감지 신호로 사용해 여러 write를 한 번의 device update로 모읍니다.
===========
Deferred IO
===========
Deferred IO is a way to delay and repurpose IO. It uses host memory as a
buffer and the MMU pagefault as a pretrigger for when to perform the device
IO. The following example may be a useful explanation of how one such setup
works:
- userspace app like Xfbdev mmaps framebuffer
- deferred IO and driver sets up fault and page_mkwrite handlers
- userspace app tries to write to mmapped vaddress
- we get pagefault and reach fault handler
- fault handler finds and returns physical page
- we get page_mkwrite where we add this page to a list
- schedule a workqueue task to be run after a delay
- app continues writing to that page with no additional cost. this is
the key benefit.
- the workqueue task comes in and mkcleans the pages on the list, then
completes the work associated with updating the framebuffer. this is
the real work talking to the device.
- app tries to write to the address (that has now been mkcleaned)
- get pagefault and the above sequence occurs again
Write coalescing과 활용 사례
25-42이 방식은 burst 형태의 framebuffer write를 최소 비용으로 처리한 뒤 일정 시간 조용해졌을 때 상대적으로 비싼 실제 framebuffer update를 수행할 수 있게 합니다.
Nonvolatile high-latency display에서는 중간 image보다 최종 image가 중요하므로 모든 write마다 update하지 않아도 됩니다.
다른 활용으로는 touched page 수를 보고 write를 coalesce해 scatter-gather DMA를 발행할지 memory burst를 수행할지 결정하는 방식이 제안됐습니다.
Device framebuffer가 대각선 이동 RGB 같은 특이한 format이라면 application에는 일반 framebuffer처럼 보이게 하고, vsync 시점에 touched pagelist를 기준으로 device format에 맞게 reswizzle할 수도 있습니다.
As can be seen from above, one benefit is roughly to allow bursty framebuffer
writes to occur at minimum cost. Then after some time when hopefully things
have gone quiet, we go and really update the framebuffer which would be
a relatively more expensive operation.
For some types of nonvolatile high latency displays, the desired image is
the final image rather than the intermediate stages which is why it's okay
to not update for each write that is occurring.
It may be the case that this is useful in other scenarios as well. Paul Mundt
has mentioned a case where it is beneficial to use the page count to decide
whether to coalesce and issue SG DMA or to do memory bursts.
Another one may be if one has a device framebuffer that is in an usual format,
say diagonally shifting RGB, this may then be a mechanism for you to allow
apps to pretend to have a normal framebuffer but reswizzle for the device
framebuffer at vsync time based on the touched pagelist.
Application 사용법
43-46Application은 변경할 필요가 없습니다. 일반 framebuffer와 동일하게 `mmap()`하고 사용하면 됩니다.
Deferred I/O는 fbdev driver 내부에서 투명하게 동작합니다.
How to use it: (for applications)
---------------------------------
No changes needed. mmap the framebuffer like normal and just use it.
Fbdev driver 초기화와 callback
47-79Driver는 먼저 `struct fb_deferred_io`를 만들고 `delay`와 `deferred_io` callback을 설정합니다. 예제의 `hecubafb_defio`는 `delay=HZ`, callback=`hecubafb_dpy_deferred_io`입니다.
`delay`는 `page_mkwrite` trigger부터 `deferred_io` callback 호출까지의 최소 지연입니다.
Callback은 `struct fb_info *info`와 지연 동안 쓰인 page 목록인 `struct list_head *pagelist`를 받습니다. 이 함수에서 display device로 필요한 모든 I/O를 수행하며, pagelist를 수정해서는 안 됩니다. Callback은 workqueue context에서 호출됩니다.
초기화할 때 `info->fbdefio = &hecubafb_defio`를 설정하고 `fb_deferred_io_init(info)`를 호출합니다. 정리할 때는 `fb_deferred_io_cleanup(info)`를 호출합니다.
Deferred I/O 구조체 등록부터 cleanup까지의 순서입니다.
How to use it: (for fbdev drivers)
----------------------------------
The following example may be helpful.
1. Setup your structure. Eg::
static struct fb_deferred_io hecubafb_defio = {
.delay = HZ,
.deferred_io = hecubafb_dpy_deferred_io,
};
The delay is the minimum delay between when the page_mkwrite trigger occurs
and when the deferred_io callback is called. The deferred_io callback is
explained below.
2. Setup your deferred IO callback. Eg::
static void hecubafb_dpy_deferred_io(struct fb_info *info,
struct list_head *pagelist)
The deferred_io callback is where you would perform all your IO to the display
device. You receive the pagelist which is the list of pages that were written
to during the delay. You must not modify this list. This callback is called
from a workqueue.
3. Call init::
info->fbdefio = &hecubafb_defio;
fb_deferred_io_init(info);
4. Call cleanup::
fb_deferred_io_cleanup(info);
요약·해설
deferred_io.rst:1-79Deferred I/O는 MMU page fault로 쓰인 framebuffer page를 추적하고 workqueue에서 실제 device update를 지연 수행해 burst write를 coalesce합니다. Application은 일반 mmap framebuffer처럼 사용하며 driver가 callback과 lifecycle을 구현합니다.
여러 userspace write를 하나의 device I/O 묶음으로 바꿉니다.