Documentation/fb/deferred_io.rst GitHub 원문 ↗

Linux 6.18.37 · Frame Buffer

Deferred IO

MMU page fault와 workqueue를 이용한 framebuffer deferred I/O 흐름 및 driver API의 한국어 전문 번역입니다.

Source pathDocumentation/fb/deferred_io.rst
Source versionLinux v6.18.37
TranslationDUJINLABS 전문 번역 + 해설

요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.

1. 요약·해설

원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.

요약·해설

deferred_io.rst:1-79

Deferred I/O는 MMU page fault로 쓰인 framebuffer page를 추적하고 workqueue에서 실제 device update를 지연 수행해 burst write를 coalesce합니다. Application은 일반 mmap framebuffer처럼 사용하며 driver가 callback과 lifecycle을 구현합니다.

Deferred update
Page fault marks pageWrites accumulateDelayed work runsDriver updates displayPages are cleaned

여러 userspace write를 하나의 device I/O 묶음으로 바꿉니다.

2. 영어 원문 전체

번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.

원문 전체 펼치기
1 ===========
2 Deferred IO
3 ===========
4
5 Deferred IO is a way to delay and repurpose IO. It uses host memory as a
6 buffer and the MMU pagefault as a pretrigger for when to perform the device
7 IO. The following example may be a useful explanation of how one such setup
8 works:
9
10 - userspace app like Xfbdev mmaps framebuffer
11 - deferred IO and driver sets up fault and page_mkwrite handlers
12 - userspace app tries to write to mmapped vaddress
13 - we get pagefault and reach fault handler
14 - fault handler finds and returns physical page
15 - we get page_mkwrite where we add this page to a list
16 - schedule a workqueue task to be run after a delay
17 - app continues writing to that page with no additional cost. this is
18 the key benefit.
19 - the workqueue task comes in and mkcleans the pages on the list, then
20 completes the work associated with updating the framebuffer. this is
21 the real work talking to the device.
22 - app tries to write to the address (that has now been mkcleaned)
23 - get pagefault and the above sequence occurs again
24
25 As can be seen from above, one benefit is roughly to allow bursty framebuffer
26 writes to occur at minimum cost. Then after some time when hopefully things
27 have gone quiet, we go and really update the framebuffer which would be
28 a relatively more expensive operation.
29
30 For some types of nonvolatile high latency displays, the desired image is
31 the final image rather than the intermediate stages which is why it's okay
32 to not update for each write that is occurring.
33
34 It may be the case that this is useful in other scenarios as well. Paul Mundt
35 has mentioned a case where it is beneficial to use the page count to decide
36 whether to coalesce and issue SG DMA or to do memory bursts.
37
38 Another one may be if one has a device framebuffer that is in an usual format,
39 say diagonally shifting RGB, this may then be a mechanism for you to allow
40 apps to pretend to have a normal framebuffer but reswizzle for the device
41 framebuffer at vsync time based on the touched pagelist.
42
43 How to use it: (for applications)
44 ---------------------------------
45 No changes needed. mmap the framebuffer like normal and just use it.
46
47 How to use it: (for fbdev drivers)
48 ----------------------------------
49 The following example may be helpful.
50
51 1. Setup your structure. Eg::
52
53 static struct fb_deferred_io hecubafb_defio = {
54 .delay = HZ,
55 .deferred_io = hecubafb_dpy_deferred_io,
56 };
57
58 The delay is the minimum delay between when the page_mkwrite trigger occurs
59 and when the deferred_io callback is called. The deferred_io callback is
60 explained below.
61
62 2. Setup your deferred IO callback. Eg::
63
64 static void hecubafb_dpy_deferred_io(struct fb_info *info,
65 struct list_head *pagelist)
66
67 The deferred_io callback is where you would perform all your IO to the display
68 device. You receive the pagelist which is the list of pages that were written
69 to during the delay. You must not modify this list. This callback is called
70 from a workqueue.
71
72 3. Call init::
73
74 info->fbdefio = &hecubafb_defio;
75 fb_deferred_io_init(info);
76
77 4. Call cleanup::
78
79 fb_deferred_io_cleanup(info);
80

3. 한국어 전문 번역

영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.

Deferred I/O page-fault 흐름

1-24

Deferred 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가 반복됩니다.

Deferred I/O cycle
Userspace `mmap()`s framebufferFirst write triggers page fault`page_mkwrite` adds page to pagelistDelayed workqueue is scheduledFurther writes proceed without extra faultWorkqueue mkcleans pages and updates deviceNext write starts the cycle again

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할 수도 있습니다.

Deferred I/O 활용
상황효과
Bursty write여러 write를 지연된 한 번의 update로 결합
Nonvolatile display중간 frame 생략, 최종 image 반영
DMA 선택Page count로 SG DMA와 memory burst 결정
특수 pixel layoutVsync 때 touched page만 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-46

Application은 변경할 필요가 없습니다. 일반 framebuffer와 동일하게 `mmap()`하고 사용하면 됩니다.

Application 관점
Open framebufferMap with `mmap()`Write normallyDriver defers device update

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-79

Driver는 먼저 `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)`를 호출합니다.

Driver setup
Define `struct fb_deferred_io`Implement workqueue callbackAssign `info->fbdefio`Call `fb_deferred_io_init(info)`Perform display I/O from callbackCall `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);