← Documents Documentation/gpu/vgaarbiter.rst GitHub 원문 ↗

Linux 6.18.37 · GPU·DRM

VGA Arbiter

Legacy VGA I/O·memory decode 충돌을 조정하는 kernel·userspace ABI를 설명합니다.

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

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

1. 요약·해설

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

요약·해설

vgaarbiter.rst:1-191

Legacy VGA I/O·memory decode 충돌을 조정하는 kernel·userspace ABI를 설명합니다.

문서 위치
항목
SourceDocumentation/gpu/vgaarbiter.rst
분량191 source lines
관련/dev/vga_arbiter · drivers/pci/vgaarb.c

Source와 관련 구현입니다.

2. 영어 원문 전체

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

원문 전체 펼치기
1 ===========
2 VGA Arbiter
3 ===========
4
5 Graphic devices are accessed through ranges in I/O or memory space. While most
6 modern devices allow relocation of such ranges, some "Legacy" VGA devices
7 implemented on PCI will typically have the same "hard-decoded" addresses as
8 they did on ISA. For more details see "PCI Bus Binding to IEEE Std 1275-1994
9 Standard for Boot (Initialization Configuration) Firmware Revision 2.1"
10 Section 7, Legacy Devices.
11
12 The Resource Access Control (RAC) module inside the X server [0] existed for
13 the legacy VGA arbitration task (besides other bus management tasks) when more
14 than one legacy device co-exist on the same machine. But the problem happens
15 when these devices are trying to be accessed by different userspace clients
16 (e.g. two servers in parallel). Their address assignments conflict. Moreover,
17 ideally, being a userspace application, it is not the role of the X server to
18 control bus resources. Therefore an arbitration scheme outside of the X server
19 is needed to control the sharing of these resources. This document introduces
20 the operation of the VGA arbiter implemented for the Linux kernel.
21
22 vgaarb kernel/userspace ABI
23 ---------------------------
24
25 The vgaarb is a module of the Linux Kernel. When it is initially loaded, it
26 scans all PCI devices and adds the VGA ones inside the arbitration. The
27 arbiter then enables/disables the decoding on different devices of the VGA
28 legacy instructions. Devices which do not want/need to use the arbiter may
29 explicitly tell it by calling vga_set_legacy_decoding().
30
31 The kernel exports a char device interface (/dev/vga_arbiter) to the clients,
32 which has the following semantics:
33
34 open
35 Opens a user instance of the arbiter. By default, it's attached to the
36 default VGA device of the system.
37
38 close
39 Close a user instance. Release locks made by the user
40
41 read
42 Return a string indicating the status of the target like:
43
44 "<card_ID>,decodes=<io_state>,owns=<io_state>,locks=<io_state> (ic,mc)"
45
46 An IO state string is of the form {io,mem,io+mem,none}, mc and
47 ic are respectively mem and io lock counts (for debugging/
48 diagnostic only). "decodes" indicate what the card currently
49 decodes, "owns" indicates what is currently enabled on it, and
50 "locks" indicates what is locked by this card. If the card is
51 unplugged, we get "invalid" then for card_ID and an -ENODEV
52 error is returned for any command until a new card is targeted.
53
54
55 write
56 Write a command to the arbiter. List of commands:
57
58 target <card_ID>
59 switch target to card <card_ID> (see below)
60 lock <io_state>
61 acquires locks on target ("none" is an invalid io_state)
62 trylock <io_state>
63 non-blocking acquire locks on target (returns EBUSY if
64 unsuccessful)
65 unlock <io_state>
66 release locks on target
67 unlock all
68 release all locks on target held by this user (not implemented
69 yet)
70 decodes <io_state>
71 set the legacy decoding attributes for the card
72
73 poll
74 event if something changes on any card (not just the target)
75
76 card_ID is of the form "PCI:domain:bus:dev.fn". It can be set to "default"
77 to go back to the system default card (TODO: not implemented yet). Currently,
78 only PCI is supported as a prefix, but the userland API may support other bus
79 types in the future, even if the current kernel implementation doesn't.
80
81 Note about locks:
82
83 The driver keeps track of which user has which locks on which card. It
84 supports stacking, like the kernel one. This complexifies the implementation
85 a bit, but makes the arbiter more tolerant to user space problems and able
86 to properly cleanup in all cases when a process dies.
87 Currently, a max of 16 cards can have locks simultaneously issued from
88 user space for a given user (file descriptor instance) of the arbiter.
89
90 In the case of devices hot-{un,}plugged, there is a hook - pci_notify() - to
91 notify them being added/removed in the system and automatically added/removed
92 in the arbiter.
93
94 There is also an in-kernel API of the arbiter in case DRM, vgacon, or other
95 drivers want to use it.
96
97 In-kernel interface
98 -------------------
99
100 .. kernel-doc:: include/linux/vgaarb.h
101 :internal:
102
103 .. kernel-doc:: drivers/pci/vgaarb.c
104 :export:
105
106 libpciaccess
107 ------------
108
109 To use the vga arbiter char device, an API was implemented inside the
110 libpciaccess library. One field was added to struct pci_device (each device
111 on the system)::
112
113 /* the type of resource decoded by the device */
114 int vgaarb_rsrc;
115
116 Besides it, in pci_system were added::
117
118 int vgaarb_fd;
119 int vga_count;
120 struct pci_device *vga_target;
121 struct pci_device *vga_default_dev;
122
123 The vga_count is used to track how many cards are being arbitrated, so for
124 instance, if there is only one card, then it can completely escape arbitration.
125
126 These functions below acquire VGA resources for the given card and mark those
127 resources as locked. If the resources requested are "normal" (and not legacy)
128 resources, the arbiter will first check whether the card is doing legacy
129 decoding for that type of resource. If yes, the lock is "converted" into a
130 legacy resource lock. The arbiter will first look for all VGA cards that
131 might conflict and disable their IOs and/or Memory access, including VGA
132 forwarding on P2P bridges if necessary, so that the requested resources can
133 be used. Then, the card is marked as locking these resources and the IO and/or
134 Memory access is enabled on the card (including VGA forwarding on parent
135 P2P bridges if any). In the case of vga_arb_lock(), the function will block
136 if some conflicting card is already locking one of the required resources (or
137 any resource on a different bus segment, since P2P bridges don't differentiate
138 VGA memory and IO afaik). If the card already owns the resources, the function
139 succeeds. vga_arb_trylock() will return (-EBUSY) instead of blocking. Nested
140 calls are supported (a per-resource counter is maintained).
141
142 Set the target device of this client. ::
143
144 int pci_device_vgaarb_set_target (struct pci_device *dev);
145
146 For instance, in x86 if two devices on the same bus want to lock different
147 resources, both will succeed (lock). If devices are in different buses and
148 trying to lock different resources, only the first who tried succeeds. ::
149
150 int pci_device_vgaarb_lock (void);
151 int pci_device_vgaarb_trylock (void);
152
153 Unlock resources of device. ::
154
155 int pci_device_vgaarb_unlock (void);
156
157 Indicates to the arbiter if the card decodes legacy VGA IOs, legacy VGA
158 Memory, both, or none. All cards default to both, the card driver (fbdev for
159 example) should tell the arbiter if it has disabled legacy decoding, so the
160 card can be left out of the arbitration process (and can be safe to take
161 interrupts at any time. ::
162
163 int pci_device_vgaarb_decodes (int new_vgaarb_rsrc);
164
165 Connects to the arbiter device, allocates the struct ::
166
167 int pci_device_vgaarb_init (void);
168
169 Close the connection ::
170
171 void pci_device_vgaarb_fini (void);
172
173 xf86VGAArbiter (X server implementation)
174 ----------------------------------------
175
176 X server basically wraps all the functions that touch VGA registers somehow.
177
178 References
179 ----------
180
181 Benjamin Herrenschmidt (IBM?) started this work when he discussed such design
182 with the Xorg community in 2005 [1, 2]. In the end of 2007, Paulo Zanoni and
183 Tiago Vignatti (both of C3SL/Federal University of Paraná) proceeded his work
184 enhancing the kernel code to adapt as a kernel module and also did the
185 implementation of the user space side [3]. Now (2009) Tiago Vignatti and Dave
186 Airlie finally put this work in shape and queued to Jesse Barnes' PCI tree.
187
188 0) https://cgit.freedesktop.org/xorg/xserver/commit/?id=4b42448a2388d40f257774fbffdccaea87bd0347
189 1) https://lists.freedesktop.org/archives/xorg/2005-March/006663.html
190 2) https://lists.freedesktop.org/archives/xorg/2005-March/006745.html
191 3) https://lists.freedesktop.org/archives/xorg/2007-October/029507.html
192

3. 한국어 전문 번역

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

Legacy VGA 자원 충돌과 kernel arbiter

1-21

Graphics device는 I/O space 또는 memory space의 range를 통해 접근합니다. 현대 장치는 대부분 range를 relocation할 수 있지만 PCI의 legacy VGA device는 ISA 시절과 같은 hard-decoded address를 쓰는 경우가 많습니다. 자세한 배경은 `PCI Bus Binding to IEEE Std 1275-1994 Standard for Boot (Initialization Configuration) Firmware Revision 2.1`의 Section 7 `Legacy Devices`를 참고합니다.

X server의 Resource Access Control(RAC) module은 한 시스템에 legacy VGA device가 여러 개 있을 때 arbitration을 포함한 bus management를 수행했습니다. 하지만 서로 다른 userspace client, 예를 들어 병렬로 실행되는 두 server가 각 device에 접근하면 address assignment가 충돌합니다.

Userspace application인 X server가 bus resource를 통제하는 것도 이상적이지 않습니다. 따라서 이 자원 공유를 X server 밖에서 제어할 arbitration scheme이 필요하며, 이 문서는 Linux kernel에 구현된 VGA arbiter의 동작을 설명합니다.

Legacy VGA 충돌
원인영향
Hard-decoded address여러 PCI VGA device의 I/O·memory range 충돌
복수 userspace client서로 다른 server가 동시에 접근
X server RACBus resource 정책이 userspace에 위치
Kernel vgaarb공통 resource ownership과 lock 조정

Arbitration이 필요한 이유를 정리합니다.

Arbitration 필요성
여러 legacy VGA device 발견Hard-decoded range 충돌 식별Userspace client의 access 요청Kernel arbiter가 decode와 lock 조정선택된 device에만 자원 허용

충돌하는 legacy decode를 kernel이 직렬화합니다.

===========
VGA Arbiter
===========

Graphic devices are accessed through ranges in I/O or memory space. While most
modern devices allow relocation of such ranges, some "Legacy" VGA devices
implemented on PCI will typically have the same "hard-decoded" addresses as
they did on ISA. For more details see "PCI Bus Binding to IEEE Std 1275-1994
Standard for Boot (Initialization Configuration) Firmware Revision 2.1"
Section 7, Legacy Devices.

The Resource Access Control (RAC) module inside the X server [0] existed for
the legacy VGA arbitration task (besides other bus management tasks) when more
than one legacy device co-exist on the same machine. But the problem happens
when these devices are trying to be accessed by different userspace clients
(e.g. two servers in parallel). Their address assignments conflict. Moreover,
ideally, being a userspace application, it is not the role of the X server to
control bus resources. Therefore an arbitration scheme outside of the X server
is needed to control the sharing of these resources. This document introduces
the operation of the VGA arbiter implemented for the Linux kernel.

/dev/vga_arbiter userspace ABI

22-96

`vgaarb`는 Linux kernel module입니다. 처음 load되면 모든 PCI device를 scan하고 VGA device를 arbitration 대상에 추가합니다. Arbiter는 device별 legacy VGA instruction decode를 enable 또는 disable합니다. Arbiter가 필요 없는 device는 `vga_set_legacy_decoding()`을 호출해 명시적으로 알릴 수 있습니다.

Kernel은 client에 character device `/dev/vga_arbiter`를 노출합니다. `open`은 user instance를 만들고 기본적으로 시스템 default VGA device에 연결합니다. `close`는 instance를 닫고 해당 user가 획득한 lock을 해제합니다.

`read`는 target 상태를 `"<card_ID>,decodes=<io_state>,owns=<io_state>,locks=<io_state> (ic,mc)"` 형식의 문자열로 반환합니다. `io_state`는 `io`, `mem`, `io+mem`, `none` 중 하나입니다. `mc`와 `ic`는 각각 memory와 I/O lock count이며 debugging·diagnostic 용도입니다.

`decodes`는 card가 현재 decode하는 자원, `owns`는 현재 enable된 자원, `locks`는 card가 lock한 자원을 나타냅니다. Card가 unplug되면 `card_ID`에 `invalid`가 표시되고 새 target을 지정할 때까지 모든 command가 `-ENODEV`를 반환합니다.

`write` command 중 `target <card_ID>`는 target card를 바꿉니다. `lock <io_state>`는 target에 blocking lock을 획득하고, `trylock <io_state>`는 nonblocking으로 시도해 실패하면 `EBUSY`를 반환합니다. `unlock <io_state>`는 해당 lock을 해제하며 `unlock all`은 이 user가 target에 보유한 lock을 모두 해제하는 명령이지만 아직 구현되지 않았습니다. `decodes <io_state>`는 card의 legacy decoding attribute를 설정합니다.

`poll`은 target뿐 아니라 어느 card에서든 상태가 변하면 event를 제공합니다. `card_ID` 형식은 `PCI:domain:bus:dev.fn`입니다. `default`를 지정해 시스템 default card로 돌아가는 기능은 TODO이며 아직 구현되지 않았습니다. 현재 prefix는 PCI만 지원하지만 userspace API는 향후 다른 bus type을 지원할 수 있습니다.

Driver는 어느 user가 어느 card의 어떤 lock을 보유하는지 추적합니다. Kernel lock처럼 stacking을 지원하므로 구현은 복잡해지지만 userspace 오류에 강하고 process가 종료될 때 모든 경우를 정리할 수 있습니다. 한 user, 즉 file descriptor instance는 동시에 최대 16개 card에 lock을 발급할 수 있습니다.

Device hotplug와 hot-unplug 때는 `pci_notify()` hook이 추가·제거를 알려 arbiter 대상도 자동으로 갱신합니다. DRM, vgacon 또는 다른 kernel driver가 사용할 in-kernel API도 제공됩니다.

/dev/vga_arbiter ABI
Operation동작
open/closeDefault target 연결·user lock 정리
readdecodes·owns·locks와 ic/mc 반환
targetPCI card_ID 또는 default 선택
lock/trylockBlocking 또는 EBUSY nonblocking 획득
unlock특정 resource 해제
decodesLegacy I/O·memory decode 설정
poll모든 card의 상태 변화 event

Character device operation과 상태 표현입니다.

Userspace lock 요청
/dev/vga_arbiter opentarget PCI:domain:bus:dev.fnlock 또는 trylock io_stateread로 owns·locks 확인사용 후 unlock·close

Target을 선택하고 legacy 자원 ownership을 획득합니다.

vgaarb kernel/userspace ABI
---------------------------

The vgaarb is a module of the Linux Kernel. When it is initially loaded, it
scans all PCI devices and adds the VGA ones inside the arbitration. The
arbiter then enables/disables the decoding on different devices of the VGA
legacy instructions. Devices which do not want/need to use the arbiter may
explicitly tell it by calling vga_set_legacy_decoding().

The kernel exports a char device interface (/dev/vga_arbiter) to the clients,
which has the following semantics:

open
        Opens a user instance of the arbiter. By default, it's attached to the
        default VGA device of the system.

close
        Close a user instance. Release locks made by the user

read
        Return a string indicating the status of the target like:

        "<card_ID>,decodes=<io_state>,owns=<io_state>,locks=<io_state> (ic,mc)"

        An IO state string is of the form {io,mem,io+mem,none}, mc and
        ic are respectively mem and io lock counts (for debugging/
        diagnostic only). "decodes" indicate what the card currently
        decodes, "owns" indicates what is currently enabled on it, and
        "locks" indicates what is locked by this card. If the card is
        unplugged, we get "invalid" then for card_ID and an -ENODEV
        error is returned for any command until a new card is targeted.


write
        Write a command to the arbiter. List of commands:

        target <card_ID>
                switch target to card <card_ID> (see below)
        lock <io_state>
                acquires locks on target ("none" is an invalid io_state)
        trylock <io_state>
                non-blocking acquire locks on target (returns EBUSY if
                unsuccessful)
        unlock <io_state>
                release locks on target
        unlock all
                release all locks on target held by this user (not implemented
                yet)
        decodes <io_state>
                set the legacy decoding attributes for the card

        poll
                event if something changes on any card (not just the target)

        card_ID is of the form "PCI:domain:bus:dev.fn". It can be set to "default"
        to go back to the system default card (TODO: not implemented yet). Currently,
        only PCI is supported as a prefix, but the userland API may support other bus
        types in the future, even if the current kernel implementation doesn't.

Note about locks:

The driver keeps track of which user has which locks on which card. It
supports stacking, like the kernel one. This complexifies the implementation
a bit, but makes the arbiter more tolerant to user space problems and able
to properly cleanup in all cases when a process dies.
Currently, a max of 16 cards can have locks simultaneously issued from
user space for a given user (file descriptor instance) of the arbiter.

In the case of devices hot-{un,}plugged, there is a hook - pci_notify() - to
notify them being added/removed in the system and automatically added/removed
in the arbiter.

There is also an in-kernel API of the arbiter in case DRM, vgacon, or other
drivers want to use it.

In-kernel API와 libpciaccess locking

97-172

In-kernel interface는 `include/linux/vgaarb.h`의 internal kernel-doc와 `drivers/pci/vgaarb.c`의 exported 함수 문서로 제공됩니다.

VGA arbiter character device를 사용하도록 libpciaccess에도 API가 구현됐습니다. 시스템의 각 device를 나타내는 `struct pci_device`에는 device가 decode하는 resource type을 담는 `int vgaarb_rsrc` field가 추가됐습니다.

`pci_system`에는 `int vgaarb_fd`, `int vga_count`, `struct pci_device *vga_target`, `struct pci_device *vga_default_dev`가 추가됐습니다. `vga_count`는 arbitration 중인 card 수를 추적하므로 card가 하나뿐이면 arbitration을 완전히 피할 수 있습니다.

Lock 함수는 주어진 card의 VGA resource를 획득하고 locked 상태로 표시합니다. 요청이 legacy가 아닌 normal resource라면 arbiter는 먼저 card가 해당 type을 legacy decode하는지 확인합니다. 그렇다면 lock을 legacy resource lock으로 변환합니다.

Arbiter는 충돌할 수 있는 모든 VGA card를 찾고 I/O 또는 memory access를 disable합니다. 필요하면 P2P bridge의 VGA forwarding도 disable하여 요청 자원을 안전하게 사용할 수 있게 합니다. 그다음 요청 card가 자원을 lock한 것으로 표시하고 card와 parent P2P bridge의 I/O 또는 memory access를 enable합니다.

`vga_arb_lock()`은 충돌 card가 필요한 resource를 이미 lock했으면 block합니다. P2P bridge는 VGA memory와 I/O를 구분하지 않는 것으로 알려져 있으므로 다른 bus segment의 어떤 resource lock과도 충돌할 수 있습니다. Card가 이미 resource를 own하면 성공하고, `vga_arb_trylock()`은 block 대신 `-EBUSY`를 반환합니다. Resource별 counter로 nested call도 지원합니다.

Client target 지정 함수는 `int pci_device_vgaarb_set_target(struct pci_device *dev);`입니다. x86에서 같은 bus의 두 device가 서로 다른 resource를 lock하면 둘 다 성공하지만, 다른 bus에 있는 device가 서로 다른 resource를 lock하려 하면 먼저 시도한 쪽만 성공합니다.

Resource 획득 함수는 `pci_device_vgaarb_lock()`과 `pci_device_vgaarb_trylock()`, 해제 함수는 `pci_device_vgaarb_unlock()`입니다. `pci_device_vgaarb_decodes(int new_vgaarb_rsrc)`는 card가 legacy VGA I/O, memory, 둘 다 또는 어느 것도 decode하지 않는다고 arbiter에 알립니다.

모든 card의 기본값은 I/O와 memory 둘 다입니다. Fbdev 같은 card driver가 legacy decoding을 disable했다면 arbiter에 알려 arbitration에서 제외할 수 있게 해야 하며, 그러면 언제든 안전하게 interrupt를 받을 수 있습니다. `pci_device_vgaarb_init()`은 arbiter device에 연결하고 구조를 할당하며 `pci_device_vgaarb_fini()`는 연결을 닫습니다.

libpciaccess VGA arbiter API
함수역할
pci_device_vgaarb_set_targetClient target device 선택
pci_device_vgaarb_lockBlocking resource lock
pci_device_vgaarb_trylockNonblocking lock, 실패 시 -EBUSY
pci_device_vgaarb_unlockDevice resource 해제
pci_device_vgaarb_decodesLegacy decode capability 설정
pci_device_vgaarb_init/finiArbiter 연결 생명주기

Target·lock·decode·connection 함수입니다.

Kernel resource arbitration
Target과 요청 resource type 확인필요하면 normal lock을 legacy lock으로 변환충돌 VGA card와 P2P forwarding disableTarget card를 locked로 표시Target과 parent bridge access enableNested counter에 따라 unlock

충돌 card를 차단한 뒤 target access를 허용합니다.

In-kernel interface
-------------------

.. kernel-doc:: include/linux/vgaarb.h
   :internal:

.. kernel-doc:: drivers/pci/vgaarb.c
   :export:

libpciaccess
------------

To use the vga arbiter char device, an API was implemented inside the
libpciaccess library. One field was added to struct pci_device (each device
on the system)::

    /* the type of resource decoded by the device */
    int vgaarb_rsrc;

Besides it, in pci_system were added::

    int vgaarb_fd;
    int vga_count;
    struct pci_device *vga_target;
    struct pci_device *vga_default_dev;

The vga_count is used to track how many cards are being arbitrated, so for
instance, if there is only one card, then it can completely escape arbitration.

These functions below acquire VGA resources for the given card and mark those
resources as locked. If the resources requested are "normal" (and not legacy)
resources, the arbiter will first check whether the card is doing legacy
decoding for that type of resource. If yes, the lock is "converted" into a
legacy resource lock. The arbiter will first look for all VGA cards that
might conflict and disable their IOs and/or Memory access, including VGA
forwarding on P2P bridges if necessary, so that the requested resources can
be used. Then, the card is marked as locking these resources and the IO and/or
Memory access is enabled on the card (including VGA forwarding on parent
P2P bridges if any). In the case of vga_arb_lock(), the function will block
if some conflicting card is already locking one of the required resources (or
any resource on a different bus segment, since P2P bridges don't differentiate
VGA memory and IO afaik). If the card already owns the resources, the function
succeeds.  vga_arb_trylock() will return (-EBUSY) instead of blocking. Nested
calls are supported (a per-resource counter is maintained).

Set the target device of this client. ::

    int  pci_device_vgaarb_set_target   (struct pci_device *dev);

For instance, in x86 if two devices on the same bus want to lock different
resources, both will succeed (lock). If devices are in different buses and
trying to lock different resources, only the first who tried succeeds. ::

    int  pci_device_vgaarb_lock         (void);
    int  pci_device_vgaarb_trylock      (void);

Unlock resources of device. ::

    int  pci_device_vgaarb_unlock       (void);

Indicates to the arbiter if the card decodes legacy VGA IOs, legacy VGA
Memory, both, or none. All cards default to both, the card driver (fbdev for
example) should tell the arbiter if it has disabled legacy decoding, so the
card can be left out of the arbitration process (and can be safe to take
interrupts at any time. ::

    int  pci_device_vgaarb_decodes      (int new_vgaarb_rsrc);

Connects to the arbiter device, allocates the struct ::

    int  pci_device_vgaarb_init         (void);

Close the connection ::

    void pci_device_vgaarb_fini         (void);

X server wrapper와 구현 역사

173-191

X server의 `xf86VGAArbiter` 구현은 VGA register를 건드리는 모든 함수를 기본적으로 wrapping합니다.

Benjamin Herrenschmidt는 2005년 Xorg community와 설계를 논의하며 이 작업을 시작했습니다. 관련 기록은 `https://lists.freedesktop.org/archives/xorg/2005-March/006663.html`과 `https://lists.freedesktop.org/archives/xorg/2005-March/006745.html`에 있습니다.

2007년 말 C3SL/Federal University of Paraná의 Paulo Zanoni와 Tiago Vignatti가 kernel code를 module에 맞게 개선하고 userspace 구현도 만들었습니다. 기록은 `https://lists.freedesktop.org/archives/xorg/2007-October/029507.html`에 있습니다.

2009년 Tiago Vignatti와 Dave Airlie가 코드를 정리해 Jesse Barnes의 PCI tree에 올렸습니다. RAC 관련 기준 commit은 `https://cgit.freedesktop.org/xorg/xserver/commit/?id=4b42448a2388d40f257774fbffdccaea87bd0347`입니다.

VGA arbiter 역사
시점내용
2005Benjamin Herrenschmidt와 Xorg 설계 논의
2007Kernel module 개선·userspace 구현
2009PCI tree 반영을 위한 정리

Kernel과 userspace 구현의 주요 시점입니다.

구현 계보
X server RAC legacy arbitrationXorg community 설계 논의Kernel module·userspace API 구현libpciaccess와 X server wrapper 연결PCI tree 통합

X server RAC에서 kernel arbitration으로 역할이 이동했습니다.

xf86VGAArbiter (X server implementation)
----------------------------------------

X server basically wraps all the functions that touch VGA registers somehow.

References
----------

Benjamin Herrenschmidt (IBM?) started this work when he discussed such design
with the Xorg community in 2005 [1, 2]. In the end of 2007, Paulo Zanoni and
Tiago Vignatti (both of C3SL/Federal University of Paraná) proceeded his work
enhancing the kernel code to adapt as a kernel module and also did the
implementation of the user space side [3]. Now (2009) Tiago Vignatti and Dave
Airlie finally put this work in shape and queued to Jesse Barnes' PCI tree.

0) https://cgit.freedesktop.org/xorg/xserver/commit/?id=4b42448a2388d40f257774fbffdccaea87bd0347
1) https://lists.freedesktop.org/archives/xorg/2005-March/006663.html
2) https://lists.freedesktop.org/archives/xorg/2005-March/006745.html
3) https://lists.freedesktop.org/archives/xorg/2007-October/029507.html