← Documents Documentation/gpu/drm-uapi.rst GitHub 원문 ↗

Linux 6.18.37 · GPU·DRM

Userland interfaces

DRM userspace ABI 정책, render node, hot-unplug·reset recovery, ioctl, IGT·VKMS와 trace 안정성을 다루는 전문 번역입니다.

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

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

1. 요약·해설

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

요약·해설

drm-uapi.rst:1-764

DRM primary/render node와 authentication·lease, open-source userspace가 선행되어야 하는 ABI 정책, hot-unplug·reset·wedging recovery 계약, ioctl errno, IGT·VKMS 검증, debugfs/sysfs·vblank·dma-buf·stable trace event를 설명합니다. Udev rule·shell script·test command와 19개 kernel-doc source·selector를 원문 그대로 보존합니다.

UAPI 검토 순서
단계
접근 권한Primary Nodes / Render nodes / Leasing
ABI 승인Open-Source Userspace Requirements
Device 소실Device Hot-Unplug / Memory Maps
Hang·resetDevice reset / Device Wedging
Ioctl 계약Recommended IOCTL Return Values
검증IGT / VKMS
관찰 interfaceCRC / debugfs / sysfs / trace events

새 userspace interface를 설계·배포할 때 확인할 주요 절입니다.

2. 영어 원문 전체

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

원문 전체 펼치기
1 .. Copyright 2020 DisplayLink (UK) Ltd.
2
3 ===================
4 Userland interfaces
5 ===================
6
7 The DRM core exports several interfaces to applications, generally
8 intended to be used through corresponding libdrm wrapper functions. In
9 addition, drivers export device-specific interfaces for use by userspace
10 drivers & device-aware applications through ioctls and sysfs files.
11
12 External interfaces include: memory mapping, context management, DMA
13 operations, AGP management, vblank control, fence management, memory
14 management, and output management.
15
16 Cover generic ioctls and sysfs layout here. We only need high-level
17 info, since man pages should cover the rest.
18
19 libdrm Device Lookup
20 ====================
21
22 .. kernel-doc:: drivers/gpu/drm/drm_ioctl.c
23 :doc: getunique and setversion story
24
25
26 .. _drm_primary_node:
27
28 Primary Nodes, DRM Master and Authentication
29 ============================================
30
31 .. kernel-doc:: drivers/gpu/drm/drm_auth.c
32 :doc: master and authentication
33
34 .. kernel-doc:: drivers/gpu/drm/drm_auth.c
35 :export:
36
37 .. kernel-doc:: include/drm/drm_auth.h
38 :internal:
39
40
41 .. _drm_leasing:
42
43 DRM Display Resource Leasing
44 ============================
45
46 .. kernel-doc:: drivers/gpu/drm/drm_lease.c
47 :doc: drm leasing
48
49 Open-Source Userspace Requirements
50 ==================================
51
52 The DRM subsystem has stricter requirements than most other kernel subsystems on
53 what the userspace side for new uAPI needs to look like. This section here
54 explains what exactly those requirements are, and why they exist.
55
56 The short summary is that any addition of DRM uAPI requires corresponding
57 open-sourced userspace patches, and those patches must be reviewed and ready for
58 merging into a suitable and canonical upstream project.
59
60 GFX devices (both display and render/GPU side) are really complex bits of
61 hardware, with userspace and kernel by necessity having to work together really
62 closely. The interfaces, for rendering and modesetting, must be extremely wide
63 and flexible, and therefore it is almost always impossible to precisely define
64 them for every possible corner case. This in turn makes it really practically
65 infeasible to differentiate between behaviour that's required by userspace, and
66 which must not be changed to avoid regressions, and behaviour which is only an
67 accidental artifact of the current implementation.
68
69 Without access to the full source code of all userspace users that means it
70 becomes impossible to change the implementation details, since userspace could
71 depend upon the accidental behaviour of the current implementation in minute
72 details. And debugging such regressions without access to source code is pretty
73 much impossible. As a consequence this means:
74
75 - The Linux kernel's "no regression" policy holds in practice only for
76 open-source userspace of the DRM subsystem. DRM developers are perfectly fine
77 if closed-source blob drivers in userspace use the same uAPI as the open
78 drivers, but they must do so in the exact same way as the open drivers.
79 Creative (ab)use of the interfaces will, and in the past routinely has, lead
80 to breakage.
81
82 - Any new userspace interface must have an open-source implementation as
83 demonstration vehicle.
84
85 The other reason for requiring open-source userspace is uAPI review. Since the
86 kernel and userspace parts of a GFX stack must work together so closely, code
87 review can only assess whether a new interface achieves its goals by looking at
88 both sides. Making sure that the interface indeed covers the use-case fully
89 leads to a few additional requirements:
90
91 - The open-source userspace must not be a toy/test application, but the real
92 thing. Specifically it needs to handle all the usual error and corner cases.
93 These are often the places where new uAPI falls apart and hence essential to
94 assess the fitness of a proposed interface.
95
96 - The userspace side must be fully reviewed and tested to the standards of that
97 userspace project. For e.g. mesa this means piglit testcases and review on the
98 mailing list. This is again to ensure that the new interface actually gets the
99 job done. The userspace-side reviewer should also provide an Acked-by on the
100 kernel uAPI patch indicating that they believe the proposed uAPI is sound and
101 sufficiently documented and validated for userspace's consumption.
102
103 - The userspace patches must be against the canonical upstream, not some vendor
104 fork. This is to make sure that no one cheats on the review and testing
105 requirements by doing a quick fork.
106
107 - The kernel patch can only be merged after all the above requirements are met,
108 but it **must** be merged to either drm-next or drm-misc-next **before** the
109 userspace patches land. uAPI always flows from the kernel, doing things the
110 other way round risks divergence of the uAPI definitions and header files.
111
112 These are fairly steep requirements, but have grown out from years of shared
113 pain and experience with uAPI added hastily, and almost always regretted about
114 just as fast. GFX devices change really fast, requiring a paradigm shift and
115 entire new set of uAPI interfaces every few years at least. Together with the
116 Linux kernel's guarantee to keep existing userspace running for 10+ years this
117 is already rather painful for the DRM subsystem, with multiple different uAPIs
118 for the same thing co-existing. If we add a few more complete mistakes into the
119 mix every year it would be entirely unmanageable.
120
121 .. _drm_render_node:
122
123 Render nodes
124 ============
125
126 DRM core provides multiple character-devices for user-space to use.
127 Depending on which device is opened, user-space can perform a different
128 set of operations (mainly ioctls). The primary node is always created
129 and called card<num>. Additionally, a currently unused control node,
130 called controlD<num> is also created. The primary node provides all
131 legacy operations and historically was the only interface used by
132 userspace. With KMS, the control node was introduced. However, the
133 planned KMS control interface has never been written and so the control
134 node stays unused to date.
135
136 With the increased use of offscreen renderers and GPGPU applications,
137 clients no longer require running compositors or graphics servers to
138 make use of a GPU. But the DRM API required unprivileged clients to
139 authenticate to a DRM-Master prior to getting GPU access. To avoid this
140 step and to grant clients GPU access without authenticating, render
141 nodes were introduced. Render nodes solely serve render clients, that
142 is, no modesetting or privileged ioctls can be issued on render nodes.
143 Only non-global rendering commands are allowed. If a driver supports
144 render nodes, it must advertise it via the DRIVER_RENDER DRM driver
145 capability. If not supported, the primary node must be used for render
146 clients together with the legacy drmAuth authentication procedure.
147
148 If a driver advertises render node support, DRM core will create a
149 separate render node called renderD<num>. There will be one render node
150 per device. No ioctls except PRIME-related ioctls will be allowed on
151 this node. Especially GEM_OPEN will be explicitly prohibited. For a
152 complete list of driver-independent ioctls that can be used on render
153 nodes, see the ioctls marked DRM_RENDER_ALLOW in drm_ioctl.c Render
154 nodes are designed to avoid the buffer-leaks, which occur if clients
155 guess the flink names or mmap offsets on the legacy interface.
156 Additionally to this basic interface, drivers must mark their
157 driver-dependent render-only ioctls as DRM_RENDER_ALLOW so render
158 clients can use them. Driver authors must be careful not to allow any
159 privileged ioctls on render nodes.
160
161 With render nodes, user-space can now control access to the render node
162 via basic file-system access-modes. A running graphics server which
163 authenticates clients on the privileged primary/legacy node is no longer
164 required. Instead, a client can open the render node and is immediately
165 granted GPU access. Communication between clients (or servers) is done
166 via PRIME. FLINK from render node to legacy node is not supported. New
167 clients must not use the insecure FLINK interface.
168
169 Besides dropping all modeset/global ioctls, render nodes also drop the
170 DRM-Master concept. There is no reason to associate render clients with
171 a DRM-Master as they are independent of any graphics server. Besides,
172 they must work without any running master, anyway. Drivers must be able
173 to run without a master object if they support render nodes. If, on the
174 other hand, a driver requires shared state between clients which is
175 visible to user-space and accessible beyond open-file boundaries, they
176 cannot support render nodes.
177
178 Device Hot-Unplug
179 =================
180
181 .. note::
182 The following is the plan. Implementation is not there yet
183 (2020 May).
184
185 Graphics devices (display and/or render) may be connected via USB (e.g.
186 display adapters or docking stations) or Thunderbolt (e.g. eGPU). An end
187 user is able to hot-unplug this kind of devices while they are being
188 used, and expects that the very least the machine does not crash. Any
189 damage from hot-unplugging a DRM device needs to be limited as much as
190 possible and userspace must be given the chance to handle it if it wants
191 to. Ideally, unplugging a DRM device still lets a desktop continue to
192 run, but that is going to need explicit support throughout the whole
193 graphics stack: from kernel and userspace drivers, through display
194 servers, via window system protocols, and in applications and libraries.
195
196 Other scenarios that should lead to the same are: unrecoverable GPU
197 crash, PCI device disappearing off the bus, or forced unbind of a driver
198 from the physical device.
199
200 In other words, from userspace perspective everything needs to keep on
201 working more or less, until userspace stops using the disappeared DRM
202 device and closes it completely. Userspace will learn of the device
203 disappearance from the device removed uevent, ioctls returning ENODEV
204 (or driver-specific ioctls returning driver-specific things), or open()
205 returning ENXIO.
206
207 Only after userspace has closed all relevant DRM device and dmabuf file
208 descriptors and removed all mmaps, the DRM driver can tear down its
209 instance for the device that no longer exists. If the same physical
210 device somehow comes back in the mean time, it shall be a new DRM
211 device.
212
213 Similar to PIDs, chardev minor numbers are not recycled immediately. A
214 new DRM device always picks the next free minor number compared to the
215 previous one allocated, and wraps around when minor numbers are
216 exhausted.
217
218 The goal raises at least the following requirements for the kernel and
219 drivers.
220
221 Requirements for KMS UAPI
222 -------------------------
223
224 - KMS connectors must change their status to disconnected.
225
226 - Legacy modesets and pageflips, and atomic commits, both real and
227 TEST_ONLY, and any other ioctls either fail with ENODEV or fake
228 success.
229
230 - Pending non-blocking KMS operations deliver the DRM events userspace
231 is expecting. This applies also to ioctls that faked success.
232
233 - open() on a device node whose underlying device has disappeared will
234 fail with ENXIO.
235
236 - Attempting to create a DRM lease on a disappeared DRM device will
237 fail with ENODEV. Existing DRM leases remain and work as listed
238 above.
239
240 Requirements for Render and Cross-Device UAPI
241 ---------------------------------------------
242
243 - All GPU jobs that can no longer run must have their fences
244 force-signalled to avoid inflicting hangs on userspace.
245 The associated error code is ENODEV.
246
247 - Some userspace APIs already define what should happen when the device
248 disappears (OpenGL, GL ES: `GL_KHR_robustness`_; `Vulkan`_:
249 VK_ERROR_DEVICE_LOST; etc.). DRM drivers are free to implement this
250 behaviour the way they see best, e.g. returning failures in
251 driver-specific ioctls and handling those in userspace drivers, or
252 rely on uevents, and so on.
253
254 - dmabuf which point to memory that has disappeared will either fail to
255 import with ENODEV or continue to be successfully imported if it would
256 have succeeded before the disappearance. See also about memory maps
257 below for already imported dmabufs.
258
259 - Attempting to import a dmabuf to a disappeared device will either fail
260 with ENODEV or succeed if it would have succeeded without the
261 disappearance.
262
263 - open() on a device node whose underlying device has disappeared will
264 fail with ENXIO.
265
266 .. _GL_KHR_robustness: https://www.khronos.org/registry/OpenGL/extensions/KHR/KHR_robustness.txt
267 .. _Vulkan: https://www.khronos.org/vulkan/
268
269 Requirements for Memory Maps
270 ----------------------------
271
272 Memory maps have further requirements that apply to both existing maps
273 and maps created after the device has disappeared. If the underlying
274 memory disappears, the map is created or modified such that reads and
275 writes will still complete successfully but the result is undefined.
276 This applies to both userspace mmap()'d memory and memory pointed to by
277 dmabuf which might be mapped to other devices (cross-device dmabuf
278 imports).
279
280 Raising SIGBUS is not an option, because userspace cannot realistically
281 handle it. Signal handlers are global, which makes them extremely
282 difficult to use correctly from libraries like those that Mesa produces.
283 Signal handlers are not composable, you can't have different handlers
284 for GPU1 and GPU2 from different vendors, and a third handler for
285 mmapped regular files. Threads cause additional pain with signal
286 handling as well.
287
288 Device reset
289 ============
290
291 The GPU stack is really complex and is prone to errors, from hardware bugs,
292 faulty applications and everything in between the many layers. Some errors
293 require resetting the device in order to make the device usable again. This
294 section describes the expectations for DRM and usermode drivers when a
295 device resets and how to propagate the reset status.
296
297 Device resets can not be disabled without tainting the kernel, which can lead to
298 hanging the entire kernel through shrinkers/mmu_notifiers. Userspace role in
299 device resets is to propagate the message to the application and apply any
300 special policy for blocking guilty applications, if any. Corollary is that
301 debugging a hung GPU context require hardware support to be able to preempt such
302 a GPU context while it's stopped.
303
304 Kernel Mode Driver
305 ------------------
306
307 The KMD is responsible for checking if the device needs a reset, and to perform
308 it as needed. Usually a hang is detected when a job gets stuck executing.
309
310 Propagation of errors to userspace has proven to be tricky since it goes in
311 the opposite direction of the usual flow of commands. Because of this vendor
312 independent error handling was added to the &dma_fence object, this way drivers
313 can add an error code to their fences before signaling them. See function
314 dma_fence_set_error() on how to do this and for examples of error codes to use.
315
316 The DRM scheduler also allows setting error codes on all pending fences when
317 hardware submissions are restarted after an reset. Error codes are also
318 forwarded from the hardware fence to the scheduler fence to bubble up errors
319 to the higher levels of the stack and eventually userspace.
320
321 Fence errors can be queried by userspace through the generic SYNC_IOC_FILE_INFO
322 IOCTL as well as through driver specific interfaces.
323
324 Additional to setting fence errors drivers should also keep track of resets per
325 context, the DRM scheduler provides the drm_sched_entity_error() function as
326 helper for this use case. After a reset, KMD should reject new command
327 submissions for affected contexts.
328
329 User Mode Driver
330 ----------------
331
332 After command submission, UMD should check if the submission was accepted or
333 rejected. After a reset, KMD should reject submissions, and UMD can issue an
334 ioctl to the KMD to check the reset status, and this can be checked more often
335 if the UMD requires it. After detecting a reset, UMD will then proceed to report
336 it to the application using the appropriate API error code, as explained in the
337 section below about robustness.
338
339 Robustness
340 ----------
341
342 The only way to try to keep a graphical API context working after a reset is if
343 it complies with the robustness aspects of the graphical API that it is using.
344
345 Graphical APIs provide ways to applications to deal with device resets. However,
346 there is no guarantee that the app will use such features correctly, and a
347 userspace that doesn't support robust interfaces (like a non-robust
348 OpenGL context or API without any robustness support like libva) leave the
349 robustness handling entirely to the userspace driver. There is no strong
350 community consensus on what the userspace driver should do in that case,
351 since all reasonable approaches have some clear downsides.
352
353 OpenGL
354 ~~~~~~
355
356 Apps using OpenGL should use the available robust interfaces, like the
357 extension ``GL_ARB_robustness`` (or ``GL_EXT_robustness`` for OpenGL ES). This
358 interface tells if a reset has happened, and if so, all the context state is
359 considered lost and the app proceeds by creating new ones. There's no consensus
360 on what to do to if robustness is not in use.
361
362 Vulkan
363 ~~~~~~
364
365 Apps using Vulkan should check for ``VK_ERROR_DEVICE_LOST`` for submissions.
366 This error code means, among other things, that a device reset has happened and
367 it needs to recreate the contexts to keep going.
368
369 Reporting causes of resets
370 --------------------------
371
372 Apart from propagating the reset through the stack so apps can recover, it's
373 really useful for driver developers to learn more about what caused the reset in
374 the first place. For this, drivers can make use of devcoredump to store relevant
375 information about the reset and send device wedged event with ``none`` recovery
376 method (as explained in "Device Wedging" chapter) to notify userspace, so this
377 information can be collected and added to user bug reports.
378
379 Device Wedging
380 ==============
381
382 Drivers can optionally make use of device wedged event (implemented as
383 drm_dev_wedged_event() in DRM subsystem), which notifies userspace of 'wedged'
384 (hanged/unusable) state of the DRM device through a uevent. This is useful
385 especially in cases where the device is no longer operating as expected and has
386 become unrecoverable from driver context. Purpose of this implementation is to
387 provide drivers a generic way to recover the device with the help of userspace
388 intervention, without taking any drastic measures (like resetting or
389 re-enumerating the full bus, on which the underlying physical device is sitting)
390 in the driver.
391
392 A 'wedged' device is basically a device that is declared dead by the driver
393 after exhausting all possible attempts to recover it from driver context. The
394 uevent is the notification that is sent to userspace along with a hint about
395 what could possibly be attempted to recover the device from userspace and bring
396 it back to usable state. Different drivers may have different ideas of a
397 'wedged' device depending on hardware implementation of the underlying physical
398 device, and hence the vendor agnostic nature of the event. It is up to the
399 drivers to decide when they see the need for device recovery and how they want
400 to recover from the available methods.
401
402 Driver prerequisites
403 --------------------
404
405 The driver, before opting for recovery, needs to make sure that the 'wedged'
406 device doesn't harm the system as a whole by taking care of the prerequisites.
407 Necessary actions must include disabling DMA to system memory as well as any
408 communication channels with other devices. Further, the driver must ensure
409 that all dma_fences are signalled and any device state that the core kernel
410 might depend on is cleaned up. All existing mmaps should be invalidated and
411 page faults should be redirected to a dummy page. Once the event is sent, the
412 device must be kept in 'wedged' state until the recovery is performed. New
413 accesses to the device (IOCTLs) should be rejected, preferably with an error
414 code that resembles the type of failure the device has encountered. This will
415 signify the reason for wedging, which can be reported to the application if
416 needed.
417
418 Recovery
419 --------
420
421 Current implementation defines four recovery methods, out of which, drivers
422 can use any one, multiple or none. Method(s) of choice will be sent in the
423 uevent environment as ``WEDGED=<method1>[,..,<methodN>]`` in order of less to
424 more side-effects. See the section `Vendor Specific Recovery`_
425 for ``WEDGED=vendor-specific``. If driver is unsure about recovery or
426 method is unknown, ``WEDGED=unknown`` will be sent instead.
427
428 Userspace consumers can parse this event and attempt recovery as per the
429 following expectations.
430
431 =============== ========================================
432 Recovery method Consumer expectations
433 =============== ========================================
434 none optional telemetry collection
435 rebind unbind + bind driver
436 bus-reset unbind + bus reset/re-enumeration + bind
437 vendor-specific vendor specific recovery method
438 unknown consumer policy
439 =============== ========================================
440
441 The only exception to this is ``WEDGED=none``, which signifies that the device
442 was temporarily 'wedged' at some point but was recovered from driver context
443 using device specific methods like reset. No explicit recovery is expected from
444 the consumer in this case, but it can still take additional steps like gathering
445 telemetry information (devcoredump, syslog). This is useful because the first
446 hang is usually the most critical one which can result in consequential hangs or
447 complete wedging.
448
449
450 Vendor Specific Recovery
451 ------------------------
452
453 When ``WEDGED=vendor-specific`` is sent, it indicates that the device requires
454 a recovery procedure specific to the hardware vendor and is not one of the
455 standardized approaches.
456
457 ``WEDGED=vendor-specific`` may be used to indicate different cases within a
458 single vendor driver, each requiring a distinct recovery procedure.
459 In such scenarios, the vendor driver must provide comprehensive documentation
460 that describes each case, include additional hints to identify specific case and
461 outline the corresponding recovery procedure. The documentation includes:
462
463 Case - A list of all cases that sends the ``WEDGED=vendor-specific`` recovery method.
464
465 Hints - Additional Information to assist the userspace consumer in identifying and
466 differentiating between different cases. This can be exposed through sysfs, debugfs,
467 traces, dmesg etc.
468
469 Recovery Procedure - Clear instructions and guidance for recovering each case.
470 This may include userspace scripts, tools needed for the recovery procedure.
471
472 It is the responsibility of the admin/userspace consumer to identify the case and
473 verify additional identification hints before attempting a recovery procedure.
474
475 Example: If the device uses the Xe driver, then userspace consumer should refer to
476 :ref:`Xe Device Wedging <xe-device-wedging>` for the detailed documentation.
477
478 Task information
479 ----------------
480
481 The information about which application (if any) was involved in the device
482 wedging is useful for userspace if they want to notify the user about what
483 happened (e.g. the compositor display a message to the user "The <task name>
484 caused a graphical error and the system recovered") or to implement policies
485 (e.g. the daemon may "ban" an task that keeps resetting the device). If the task
486 information is available, the uevent will display as ``PID=<pid>`` and
487 ``TASK=<task name>``. Otherwise, ``PID`` and ``TASK`` will not appear in the
488 event string.
489
490 The reliability of this information is driver and hardware specific, and should
491 be taken with a caution regarding it's precision. To have a big picture of what
492 really happened, the devcoredump file provides much more detailed information
493 about the device state and about the event.
494
495 Consumer prerequisites
496 ----------------------
497
498 It is the responsibility of the consumer to make sure that the device or its
499 resources are not in use by any process before attempting recovery. With IOCTLs
500 erroring out, all device memory should be unmapped and file descriptors should
501 be closed to prevent leaks or undefined behaviour. The idea here is to clear the
502 device of all user context beforehand and set the stage for a clean recovery.
503
504 For ``WEDGED=vendor-specific`` recovery method, it is the responsibility of the
505 consumer to check the driver documentation and the usecase before attempting
506 a recovery.
507
508 Example - rebind
509 ----------------
510
511 Udev rule::
512
513 SUBSYSTEM=="drm", ENV{WEDGED}=="rebind", DEVPATH=="*/drm/card[0-9]",
514 RUN+="/path/to/rebind.sh $env{DEVPATH}"
515
516 Recovery script::
517
518 #!/bin/sh
519
520 DEVPATH=$(readlink -f /sys/$1/device)
521 DEVICE=$(basename $DEVPATH)
522 DRIVER=$(readlink -f $DEVPATH/driver)
523
524 echo -n $DEVICE > $DRIVER/unbind
525 echo -n $DEVICE > $DRIVER/bind
526
527 Customization
528 -------------
529
530 Although basic recovery is possible with a simple script, consumers can define
531 custom policies around recovery. For example, if the driver supports multiple
532 recovery methods, consumers can opt for the suitable one depending on scenarios
533 like repeat offences or vendor specific failures. Consumers can also choose to
534 have the device available for debugging or telemetry collection and base their
535 recovery decision on the findings. This is useful especially when the driver is
536 unsure about recovery or method is unknown.
537
538 .. _drm_driver_ioctl:
539
540 IOCTL Support on Device Nodes
541 =============================
542
543 .. kernel-doc:: drivers/gpu/drm/drm_ioctl.c
544 :doc: driver specific ioctls
545
546 Recommended IOCTL Return Values
547 -------------------------------
548
549 In theory a driver's IOCTL callback is only allowed to return very few error
550 codes. In practice it's good to abuse a few more. This section documents common
551 practice within the DRM subsystem:
552
553 ENOENT:
554 Strictly this should only be used when a file doesn't exist e.g. when
555 calling the open() syscall. We reuse that to signal any kind of object
556 lookup failure, e.g. for unknown GEM buffer object handles, unknown KMS
557 object handles and similar cases.
558
559 ENOSPC:
560 Some drivers use this to differentiate "out of kernel memory" from "out
561 of VRAM". Sometimes also applies to other limited gpu resources used for
562 rendering (e.g. when you have a special limited compression buffer).
563 Sometimes resource allocation/reservation issues in command submission
564 IOCTLs are also signalled through EDEADLK.
565
566 Simply running out of kernel/system memory is signalled through ENOMEM.
567
568 EPERM/EACCES:
569 Returned for an operation that is valid, but needs more privileges.
570 E.g. root-only or much more common, DRM master-only operations return
571 this when called by unpriviledged clients. There's no clear
572 difference between EACCES and EPERM.
573
574 ENODEV:
575 The device is not present anymore or is not yet fully initialized.
576
577 EOPNOTSUPP:
578 Feature (like PRIME, modesetting, GEM) is not supported by the driver.
579
580 ENXIO:
581 Remote failure, either a hardware transaction (like i2c), but also used
582 when the exporting driver of a shared dma-buf or fence doesn't support a
583 feature needed.
584
585 EINTR:
586 DRM drivers assume that userspace restarts all IOCTLs. Any DRM IOCTL can
587 return EINTR and in such a case should be restarted with the IOCTL
588 parameters left unchanged.
589
590 EIO:
591 The GPU died and couldn't be resurrected through a reset. Modesetting
592 hardware failures are signalled through the "link status" connector
593 property.
594
595 EINVAL:
596 Catch-all for anything that is an invalid argument combination which
597 cannot work.
598
599 IOCTL also use other error codes like ETIME, EFAULT, EBUSY, ENOTTY but their
600 usage is in line with the common meanings. The above list tries to just document
601 DRM specific patterns. Note that ENOTTY has the slightly unintuitive meaning of
602 "this IOCTL does not exist", and is used exactly as such in DRM.
603
604 .. kernel-doc:: include/drm/drm_ioctl.h
605 :internal:
606
607 .. kernel-doc:: drivers/gpu/drm/drm_ioctl.c
608 :export:
609
610 .. kernel-doc:: drivers/gpu/drm/drm_ioc32.c
611 :export:
612
613 Testing and validation
614 ======================
615
616 Testing Requirements for userspace API
617 --------------------------------------
618
619 New cross-driver userspace interface extensions, like new IOCTL, new KMS
620 properties, new files in sysfs or anything else that constitutes an API change
621 should have driver-agnostic testcases in IGT for that feature, if such a test
622 can be reasonably made using IGT for the target hardware.
623
624 Validating changes with IGT
625 ---------------------------
626
627 There's a collection of tests that aims to cover the whole functionality of
628 DRM drivers and that can be used to check that changes to DRM drivers or the
629 core don't regress existing functionality. This test suite is called IGT and
630 its code and instructions to build and run can be found in
631 https://gitlab.freedesktop.org/drm/igt-gpu-tools/.
632
633 Using VKMS to test DRM API
634 --------------------------
635
636 VKMS is a software-only model of a KMS driver that is useful for testing
637 and for running compositors. VKMS aims to enable a virtual display without
638 the need for a hardware display capability. These characteristics made VKMS
639 a perfect tool for validating the DRM core behavior and also support the
640 compositor developer. VKMS makes it possible to test DRM functions in a
641 virtual machine without display, simplifying the validation of some of the
642 core changes.
643
644 To Validate changes in DRM API with VKMS, start setting the kernel: make
645 sure to enable VKMS module; compile the kernel with the VKMS enabled and
646 install it in the target machine. VKMS can be run in a Virtual Machine
647 (QEMU, virtme or similar). It's recommended the use of KVM with the minimum
648 of 1GB of RAM and four cores.
649
650 It's possible to run the IGT-tests in a VM in two ways:
651
652 1. Use IGT inside a VM
653 2. Use IGT from the host machine and write the results in a shared directory.
654
655 Following is an example of using a VM with a shared directory with
656 the host machine to run igt-tests. This example uses virtme::
657
658 $ virtme-run --rwdir /path/for/shared_dir --kdir=path/for/kernel/directory --mods=auto
659
660 Run the igt-tests in the guest machine. This example runs the 'kms_flip'
661 tests::
662
663 $ /path/for/igt-gpu-tools/scripts/run-tests.sh -p -s -t "kms_flip.*" -v
664
665 In this example, instead of building the igt_runner, Piglit is used
666 (-p option). It creates an HTML summary of the test results and saves
667 them in the folder "igt-gpu-tools/results". It executes only the igt-tests
668 matching the -t option.
669
670 Display CRC Support
671 -------------------
672
673 .. kernel-doc:: drivers/gpu/drm/drm_debugfs_crc.c
674 :doc: CRC ABI
675
676 .. kernel-doc:: drivers/gpu/drm/drm_debugfs_crc.c
677 :export:
678
679 Debugfs Support
680 ---------------
681
682 .. kernel-doc:: include/drm/drm_debugfs.h
683 :internal:
684
685 .. kernel-doc:: drivers/gpu/drm/drm_debugfs.c
686 :export:
687
688 Sysfs Support
689 =============
690
691 .. kernel-doc:: drivers/gpu/drm/drm_sysfs.c
692 :doc: overview
693
694 .. kernel-doc:: drivers/gpu/drm/drm_sysfs.c
695 :export:
696
697
698 VBlank event handling
699 =====================
700
701 The DRM core exposes two vertical blank related ioctls:
702
703 :c:macro:`DRM_IOCTL_WAIT_VBLANK`
704 This takes a struct drm_wait_vblank structure as its argument, and
705 it is used to block or request a signal when a specified vblank
706 event occurs.
707
708 :c:macro:`DRM_IOCTL_MODESET_CTL`
709 This was only used for user-mode-settind drivers around modesetting
710 changes to allow the kernel to update the vblank interrupt after
711 mode setting, since on many devices the vertical blank counter is
712 reset to 0 at some point during modeset. Modern drivers should not
713 call this any more since with kernel mode setting it is a no-op.
714
715 Userspace API Structures
716 ========================
717
718 .. kernel-doc:: include/uapi/drm/drm_mode.h
719 :doc: overview
720
721 .. _crtc_index:
722
723 CRTC index
724 ----------
725
726 CRTC's have both an object ID and an index, and they are not the same thing.
727 The index is used in cases where a densely packed identifier for a CRTC is
728 needed, for instance a bitmask of CRTC's. The member possible_crtcs of struct
729 drm_mode_get_plane is an example.
730
731 :c:macro:`DRM_IOCTL_MODE_GETRESOURCES` populates a structure with an array of
732 CRTC ID's, and the CRTC index is its position in this array.
733
734 .. kernel-doc:: include/uapi/drm/drm.h
735 :internal:
736
737 .. kernel-doc:: include/uapi/drm/drm_mode.h
738 :internal:
739
740
741 dma-buf interoperability
742 ========================
743
744 Please see Documentation/userspace-api/dma-buf-alloc-exchange.rst for
745 information on how dma-buf is integrated and exposed within DRM.
746
747
748 Trace events
749 ============
750
751 See Documentation/trace/tracepoints.rst for information about using
752 Linux Kernel Tracepoints.
753 In the DRM subsystem, some events are considered stable uAPI to avoid
754 breaking tools (e.g.: GPUVis, umr) relying on them. Stable means that fields
755 cannot be removed, nor their formatting updated. Adding new fields is
756 possible, under the normal uAPI requirements.
757
758 Stable uAPI events
759 ------------------
760
761 From ``drivers/gpu/drm/scheduler/gpu_scheduler_trace.h``
762
763 .. kernel-doc:: drivers/gpu/drm/scheduler/gpu_scheduler_trace.h
764 :doc: uAPI trace events

3. 한국어 전문 번역

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

Userland interface, DRM master·authentication과 lease

1-48

DRM core는 application에 여러 interface를 export하며 일반적으로 대응하는 `libdrm` wrapper function을 통해 사용합니다. Driver는 device-specific userspace driver와 device-aware application을 위해 ioctl과 sysfs file로 고유 interface도 export합니다.

외부 interface에는 memory mapping, context·DMA·AGP 관리, vblank control, fence·memory·output 관리가 포함됩니다. 이 문서는 generic ioctl과 sysfs layout의 상위 수준 정보만 다루며 세부사항은 man page의 역할입니다.

`libdrm Device Lookup`은 `drm_ioctl.c`의 getunique·setversion history를 포함합니다. Primary node 절은 DRM master와 authentication 개요·exported API·내부 header를, display resource leasing 절은 `drm_lease.c`의 lease 문서를 제공합니다.

DRM userland interface 범위
Interface용도
libdrm wrapperGeneric DRM ioctl을 application API로 제공
Driver-specific ioctlHardware 고유 rendering·device operation
sysfsDevice state와 관리 attribute
Primary node authenticationDRM master와 legacy client 권한 부여
DRM leaseDisplay resource 일부를 다른 client에 위임

Core와 driver가 userspace에 노출하는 기능을 구분합니다.

Kernel-doc: lookup·authentication·leasing
Source pathSelector포함 범위
drivers/gpu/drm/drm_ioctl.c:doc: getunique and setversion storygetunique and setversion story 문서 블록
drivers/gpu/drm/drm_auth.c:doc: master and authenticationmaster and authentication 문서 블록
drivers/gpu/drm/drm_auth.c:export:Exported API
include/drm/drm_auth.h:internal:내부 type·함수 문서
drivers/gpu/drm/drm_lease.c:doc: drm leasingdrm leasing 문서 블록

Device lookup, primary node master/auth와 display lease의 5개 block입니다.

.. Copyright 2020 DisplayLink (UK) Ltd.

===================
Userland interfaces
===================

The DRM core exports several interfaces to applications, generally
intended to be used through corresponding libdrm wrapper functions. In
addition, drivers export device-specific interfaces for use by userspace
drivers & device-aware applications through ioctls and sysfs files.

External interfaces include: memory mapping, context management, DMA
operations, AGP management, vblank control, fence management, memory
management, and output management.

Cover generic ioctls and sysfs layout here. We only need high-level
info, since man pages should cover the rest.

libdrm Device Lookup
====================

.. kernel-doc:: drivers/gpu/drm/drm_ioctl.c
   :doc: getunique and setversion story


.. _drm_primary_node:

Primary Nodes, DRM Master and Authentication
============================================

.. kernel-doc:: drivers/gpu/drm/drm_auth.c
   :doc: master and authentication

.. kernel-doc:: drivers/gpu/drm/drm_auth.c
   :export:

.. kernel-doc:: include/drm/drm_auth.h
   :internal:


.. _drm_leasing:

DRM Display Resource Leasing
============================

.. kernel-doc:: drivers/gpu/drm/drm_lease.c
   :doc: drm leasing

Open-source userspace가 필요한 이유와 merge 순서

49-122

DRM subsystem은 새 uAPI의 userspace 측 구현에 대해 대부분의 kernel subsystem보다 엄격한 요구사항을 둡니다. 요약하면 DRM uAPI를 추가할 때 대응하는 open-source userspace patch가 있어야 하고, 적절한 canonical upstream project에 merge할 준비가 되도록 review를 마쳐야 합니다.

Display와 render/GPU를 포함한 GFX device는 매우 복잡하고 userspace와 kernel이 긴밀하게 협력해야 합니다. Rendering·modesetting interface는 폭넓고 유연해야 하므로 모든 corner case를 정확히 정의하기 거의 불가능합니다. 따라서 userspace가 반드시 의존하는 동작과 현재 구현의 우연한 artifact를 구분하기 어렵습니다.

모든 userspace source에 접근할 수 없으면 폐쇄형 userspace가 사소한 우연적 동작에 의존할 수 있어 구현 세부사항을 변경할 수 없고 regression debug도 사실상 불가능합니다. Linux kernel의 no-regression 정책은 DRM에서는 실제로 open-source userspace에 대해서만 유지됩니다. Closed-source blob이 같은 uAPI를 써도 되지만 open driver와 정확히 같은 방식으로 사용해야 하며 interface를 창의적으로 오용하면 깨질 수 있습니다.

새 userspace interface에는 반드시 실제 open-source 구현이 demonstration vehicle로 있어야 합니다. Toy/test application이 아니라 일반 error와 corner case를 모두 처리하는 실제 구현이어야 새 uAPI의 적합성을 평가할 수 있습니다.

Userspace 측은 해당 project 기준으로 review와 test를 완료해야 합니다. Mesa라면 piglit testcase와 mailing-list review가 필요하며 userspace reviewer는 제안 uAPI가 충분히 문서화·검증되었다는 뜻의 `Acked-by`를 kernel uAPI patch에도 제공해야 합니다.

Userspace patch는 vendor fork가 아니라 canonical upstream을 대상으로 해야 합니다. Kernel patch는 모든 요구사항이 충족된 뒤에만 merge할 수 있지만 userspace patch가 들어가기 전에 `drm-next` 또는 `drm-misc-next`에 먼저 merge되어야 합니다. uAPI는 항상 kernel에서 흘러나와야 definition과 header가 갈라지는 위험을 막을 수 있습니다.

이 요구사항은 성급하게 추가한 uAPI로 겪은 오랜 문제에서 생겼습니다. GFX hardware는 빠르게 변해 몇 년마다 새로운 paradigm과 uAPI가 필요하지만 kernel은 10년 이상 기존 userspace 동작을 보장합니다. 같은 기능의 여러 uAPI가 공존하는 상황에서 잘못된 interface까지 계속 추가하면 관리할 수 없습니다.

새 DRM uAPI merge 조건
단계요구사항
실제 구현Toy가 아닌 open-source userspace가 error·corner case까지 처리
Userspace 검증Canonical upstream의 review·test와 reviewer Acked-by
Kernel 검토Userspace와 kernel 양쪽을 함께 보고 use case 충족 확인
Merge 순서Kernel patch를 drm-next/drm-misc-next에 먼저, userspace patch를 뒤에 merge
호환성Closed-source userspace도 공개 driver와 동일한 uAPI 사용 방식 준수

Kernel과 userspace 양쪽에서 충족해야 하는 순서와 품질 기준입니다.

Open-Source Userspace Requirements
==================================

The DRM subsystem has stricter requirements than most other kernel subsystems on
what the userspace side for new uAPI needs to look like. This section here
explains what exactly those requirements are, and why they exist.

The short summary is that any addition of DRM uAPI requires corresponding
open-sourced userspace patches, and those patches must be reviewed and ready for
merging into a suitable and canonical upstream project.

GFX devices (both display and render/GPU side) are really complex bits of
hardware, with userspace and kernel by necessity having to work together really
closely.  The interfaces, for rendering and modesetting, must be extremely wide
and flexible, and therefore it is almost always impossible to precisely define
them for every possible corner case. This in turn makes it really practically
infeasible to differentiate between behaviour that's required by userspace, and
which must not be changed to avoid regressions, and behaviour which is only an
accidental artifact of the current implementation.

Without access to the full source code of all userspace users that means it
becomes impossible to change the implementation details, since userspace could
depend upon the accidental behaviour of the current implementation in minute
details. And debugging such regressions without access to source code is pretty
much impossible. As a consequence this means:

- The Linux kernel's "no regression" policy holds in practice only for
  open-source userspace of the DRM subsystem. DRM developers are perfectly fine
  if closed-source blob drivers in userspace use the same uAPI as the open
  drivers, but they must do so in the exact same way as the open drivers.
  Creative (ab)use of the interfaces will, and in the past routinely has, lead
  to breakage.

- Any new userspace interface must have an open-source implementation as
  demonstration vehicle.

The other reason for requiring open-source userspace is uAPI review. Since the
kernel and userspace parts of a GFX stack must work together so closely, code
review can only assess whether a new interface achieves its goals by looking at
both sides. Making sure that the interface indeed covers the use-case fully
leads to a few additional requirements:

- The open-source userspace must not be a toy/test application, but the real
  thing. Specifically it needs to handle all the usual error and corner cases.
  These are often the places where new uAPI falls apart and hence essential to
  assess the fitness of a proposed interface.

- The userspace side must be fully reviewed and tested to the standards of that
  userspace project. For e.g. mesa this means piglit testcases and review on the
  mailing list. This is again to ensure that the new interface actually gets the
  job done.  The userspace-side reviewer should also provide an Acked-by on the
  kernel uAPI patch indicating that they believe the proposed uAPI is sound and
  sufficiently documented and validated for userspace's consumption.

- The userspace patches must be against the canonical upstream, not some vendor
  fork. This is to make sure that no one cheats on the review and testing
  requirements by doing a quick fork.

- The kernel patch can only be merged after all the above requirements are met,
  but it **must** be merged to either drm-next or drm-misc-next **before** the
  userspace patches land. uAPI always flows from the kernel, doing things the
  other way round risks divergence of the uAPI definitions and header files.

These are fairly steep requirements, but have grown out from years of shared
pain and experience with uAPI added hastily, and almost always regretted about
just as fast. GFX devices change really fast, requiring a paradigm shift and
entire new set of uAPI interfaces every few years at least. Together with the
Linux kernel's guarantee to keep existing userspace running for 10+ years this
is already rather painful for the DRM subsystem, with multiple different uAPIs
for the same thing co-existing. If we add a few more complete mistakes into the
mix every year it would be entirely unmanageable.

.. _drm_render_node:

Primary·control·render node와 권한 모델

123-177

DRM core는 userspace가 사용할 여러 character device를 제공합니다. 어떤 node를 여느냐에 따라 사용할 operation, 주로 ioctl 집합이 달라집니다. Primary node `card<num>`는 항상 생성되고 모든 legacy operation을 제공합니다. `controlD<num>` control node도 생성되지만 계획했던 KMS control interface가 구현되지 않아 현재 사용하지 않습니다.

Offscreen renderer와 GPGPU application이 늘면서 GPU 사용에 compositor나 graphics server가 필요하지 않게 되었습니다. 기존 DRM API는 unprivileged client가 GPU access 전에 DRM master에 authentication하도록 했지만, 이 단계를 없애기 위해 render node가 도입되었습니다.

Render node는 render client만 지원하므로 modesetting과 privileged ioctl을 허용하지 않고 non-global rendering command만 허용합니다. Driver는 `DRIVER_RENDER` capability를 광고해야 합니다. 지원하지 않으면 render client도 primary node와 legacy `drmAuth` 절차를 사용해야 합니다.

지원 시 device마다 `renderD<num>` node 하나가 생성됩니다. Driver-independent ioctl 중 PRIME 관련 ioctl과 `drm_ioctl.c`에서 `DRM_RENDER_ALLOW`로 표시된 것만 허용하며 `GEM_OPEN`은 명시적으로 금지됩니다. Driver-specific render-only ioctl도 `DRM_RENDER_ALLOW`로 표시해야 하고 privileged ioctl을 허용하지 않도록 주의해야 합니다.

Render node는 filesystem access mode로 권한을 제어하고 open 즉시 GPU access를 부여하므로 client를 인증하는 graphics server가 필요 없습니다. Client 간 공유는 PRIME을 사용하며 render node에서 legacy node로 FLINK하는 것은 지원하지 않습니다. 새 client는 안전하지 않은 FLINK를 사용하면 안 됩니다.

Render node에는 DRM master 개념도 없습니다. Driver는 master object 없이 동작할 수 있어야 합니다. Open-file 경계를 넘어 userspace에 보이고 client가 공유하는 state가 꼭 필요한 driver는 render node를 지원할 수 없습니다.

DRM device node 비교
Node이름권한·용도
Primarycard<num>Legacy·modeset·privileged operation, DRM master/authentication
ControlcontrolD<num>계획된 KMS control interface가 없어 현재 미사용
RenderrenderD<num>Non-global rendering과 PRIME, modeset·privileged ioctl 금지

Node별 목적과 허용 operation입니다.

Render client access
Filesystem permission으로 renderD<num> open 허용Client가 authentication 없이 GPU access 획득DRM_RENDER_ALLOW ioctl로 non-global rendering 수행다른 client·device와 buffer는 PRIME으로 공유

DRM master authentication 없이 안전한 rendering access를 제공합니다.

Render nodes
============

DRM core provides multiple character-devices for user-space to use.
Depending on which device is opened, user-space can perform a different
set of operations (mainly ioctls). The primary node is always created
and called card<num>. Additionally, a currently unused control node,
called controlD<num> is also created. The primary node provides all
legacy operations and historically was the only interface used by
userspace. With KMS, the control node was introduced. However, the
planned KMS control interface has never been written and so the control
node stays unused to date.

With the increased use of offscreen renderers and GPGPU applications,
clients no longer require running compositors or graphics servers to
make use of a GPU. But the DRM API required unprivileged clients to
authenticate to a DRM-Master prior to getting GPU access. To avoid this
step and to grant clients GPU access without authenticating, render
nodes were introduced. Render nodes solely serve render clients, that
is, no modesetting or privileged ioctls can be issued on render nodes.
Only non-global rendering commands are allowed. If a driver supports
render nodes, it must advertise it via the DRIVER_RENDER DRM driver
capability. If not supported, the primary node must be used for render
clients together with the legacy drmAuth authentication procedure.

If a driver advertises render node support, DRM core will create a
separate render node called renderD<num>. There will be one render node
per device. No ioctls except PRIME-related ioctls will be allowed on
this node. Especially GEM_OPEN will be explicitly prohibited. For a
complete list of driver-independent ioctls that can be used on render
nodes, see the ioctls marked DRM_RENDER_ALLOW in drm_ioctl.c  Render
nodes are designed to avoid the buffer-leaks, which occur if clients
guess the flink names or mmap offsets on the legacy interface.
Additionally to this basic interface, drivers must mark their
driver-dependent render-only ioctls as DRM_RENDER_ALLOW so render
clients can use them. Driver authors must be careful not to allow any
privileged ioctls on render nodes.

With render nodes, user-space can now control access to the render node
via basic file-system access-modes. A running graphics server which
authenticates clients on the privileged primary/legacy node is no longer
required. Instead, a client can open the render node and is immediately
granted GPU access. Communication between clients (or servers) is done
via PRIME. FLINK from render node to legacy node is not supported. New
clients must not use the insecure FLINK interface.

Besides dropping all modeset/global ioctls, render nodes also drop the
DRM-Master concept. There is no reason to associate render clients with
a DRM-Master as they are independent of any graphics server. Besides,
they must work without any running master, anyway. Drivers must be able
to run without a master object if they support render nodes. If, on the
other hand, a driver requires shared state between clients which is
visible to user-space and accessible beyond open-file boundaries, they
cannot support render nodes.

Hot-unplug 후 KMS·render·mmap 계약

178-287

이 절은 2020년 5월 기준 구현 완료가 아닌 계획임을 명시합니다. USB display adapter·dock이나 Thunderbolt eGPU는 사용 중 hot-unplug될 수 있으며 최소한 system이 crash하지 않아야 합니다. Damage를 제한하고 userspace가 처리할 기회를 줘야 하며 이상적으로 desktop이 계속 동작하려면 kernel/userspace driver, display server, window protocol, application과 library 전체의 명시적 지원이 필요합니다.

복구 불가능한 GPU crash, PCI bus에서 device 소실, physical device에서 driver 강제 unbind도 같은 동작으로 이어져야 합니다. Userspace가 사라진 DRM device 사용을 멈추고 완전히 닫을 때까지 나머지 기능은 대체로 계속 동작해야 합니다.

Userspace는 device-removed uevent, `ENODEV`를 반환하는 ioctl, driver-specific 오류, `ENXIO`를 반환하는 `open()`으로 소실을 알게 됩니다. 관련 DRM device·dma-buf fd를 모두 닫고 mmap을 제거한 뒤에만 driver가 instance를 해체할 수 있습니다. Physical device가 다시 나타나면 새 DRM device로 취급합니다. Character-device minor는 PID처럼 즉시 재사용하지 않고 다음 free number를 선택하며 소진되면 wrap합니다.

Device disappearance lifecycle
Hot-unplug·GPU crash·PCI disappearance·forced unbind 발생uevent와 ENODEV/ENXIO로 userspace에 소실 통지Pending event와 fence를 완료하고 기존 mapping access를 안전하게 처리Userspace가 DRM·dma-buf fd와 mmap을 모두 해제Driver instance 해체, 재등장 device는 새 minor의 새 DRM device로 생성

Userspace resource가 남아 있는 동안 instance를 유지한 뒤 안전하게 해체합니다.

KMS connector는 disconnected로 바뀌어야 합니다. Legacy modeset·pageflip, real·`TEST_ONLY` atomic commit과 기타 ioctl은 `ENODEV`로 실패하거나 성공을 가장해야 합니다. 성공을 가장한 경우를 포함해 pending nonblocking operation은 userspace가 기대하는 DRM event를 전달해야 합니다. 사라진 node의 `open()`은 `ENXIO`, 새 lease 생성은 `ENODEV`이며 기존 lease는 위 규칙에 따라 유지됩니다.

Hot-unplug KMS 요구사항
Operation결과
Connector statusdisconnected
Modeset·pageflip·atomic commitENODEV 또는 fake success
Pending nonblocking KMS기대하는 DRM event 전달
open()ENXIO
새 DRM leaseENODEV
기존 DRM lease유지하고 동일한 hot-unplug 규칙 적용

Display UAPI가 사라진 device를 처리하는 방식입니다.

더는 실행할 수 없는 GPU job의 fence는 userspace hang을 막기 위해 `ENODEV` error로 force-signal해야 합니다. OpenGL·OpenGL ES의 `GL_KHR_robustness`, Vulkan의 `VK_ERROR_DEVICE_LOST`처럼 device 소실 동작을 이미 정의한 API는 driver-specific ioctl, uevent 등 적절한 방법으로 구현할 수 있습니다.

사라진 memory를 가리키는 dma-buf는 import가 `ENODEV`로 실패하거나 소실 전 성공했을 경우 계속 성공할 수 있습니다. 사라진 device로 dma-buf를 import하는 경우도 같은 선택입니다. 기존·신규 memory map에서 backing memory가 사라지면 read/write는 성공적으로 끝나되 결과는 undefined여야 합니다. Userspace mmap과 다른 device에 mapping된 cross-device dma-buf 모두에 적용됩니다.

`SIGBUS`는 현실적으로 userspace가 처리할 수 없어 사용할 수 없습니다. Signal handler는 process 전역이고 library에서 올바르게 사용하기 매우 어려우며 vendor가 다른 GPU1·GPU2와 일반 mmap file에 서로 다른 handler를 합성할 수 없습니다. Thread도 signal handling을 더 어렵게 합니다.

Render·dma-buf·mmap 요구사항
영역요구사항
GPU fenceENODEV를 설정해 force-signal
API robustnessGL_KHR_robustness 또는 VK_ERROR_DEVICE_LOST 의미로 전달
dma-buf importENODEV 또는 소실 전과 같은 성공
Existing/new mmapRead/write 완료, 결과 undefined
SignalSIGBUS 사용 금지

Display 외 UAPI가 device disappearance를 전파하는 계약입니다.

Device Hot-Unplug
=================

.. note::
   The following is the plan. Implementation is not there yet
   (2020 May).

Graphics devices (display and/or render) may be connected via USB (e.g.
display adapters or docking stations) or Thunderbolt (e.g. eGPU). An end
user is able to hot-unplug this kind of devices while they are being
used, and expects that the very least the machine does not crash. Any
damage from hot-unplugging a DRM device needs to be limited as much as
possible and userspace must be given the chance to handle it if it wants
to. Ideally, unplugging a DRM device still lets a desktop continue to
run, but that is going to need explicit support throughout the whole
graphics stack: from kernel and userspace drivers, through display
servers, via window system protocols, and in applications and libraries.

Other scenarios that should lead to the same are: unrecoverable GPU
crash, PCI device disappearing off the bus, or forced unbind of a driver
from the physical device.

In other words, from userspace perspective everything needs to keep on
working more or less, until userspace stops using the disappeared DRM
device and closes it completely. Userspace will learn of the device
disappearance from the device removed uevent, ioctls returning ENODEV
(or driver-specific ioctls returning driver-specific things), or open()
returning ENXIO.

Only after userspace has closed all relevant DRM device and dmabuf file
descriptors and removed all mmaps, the DRM driver can tear down its
instance for the device that no longer exists. If the same physical
device somehow comes back in the mean time, it shall be a new DRM
device.

Similar to PIDs, chardev minor numbers are not recycled immediately. A
new DRM device always picks the next free minor number compared to the
previous one allocated, and wraps around when minor numbers are
exhausted.

The goal raises at least the following requirements for the kernel and
drivers.

Requirements for KMS UAPI
-------------------------

- KMS connectors must change their status to disconnected.

- Legacy modesets and pageflips, and atomic commits, both real and
  TEST_ONLY, and any other ioctls either fail with ENODEV or fake
  success.

- Pending non-blocking KMS operations deliver the DRM events userspace
  is expecting. This applies also to ioctls that faked success.

- open() on a device node whose underlying device has disappeared will
  fail with ENXIO.

- Attempting to create a DRM lease on a disappeared DRM device will
  fail with ENODEV. Existing DRM leases remain and work as listed
  above.

Requirements for Render and Cross-Device UAPI
---------------------------------------------

- All GPU jobs that can no longer run must have their fences
  force-signalled to avoid inflicting hangs on userspace.
  The associated error code is ENODEV.

- Some userspace APIs already define what should happen when the device
  disappears (OpenGL, GL ES: `GL_KHR_robustness`_; `Vulkan`_:
  VK_ERROR_DEVICE_LOST; etc.). DRM drivers are free to implement this
  behaviour the way they see best, e.g. returning failures in
  driver-specific ioctls and handling those in userspace drivers, or
  rely on uevents, and so on.

- dmabuf which point to memory that has disappeared will either fail to
  import with ENODEV or continue to be successfully imported if it would
  have succeeded before the disappearance. See also about memory maps
  below for already imported dmabufs.

- Attempting to import a dmabuf to a disappeared device will either fail
  with ENODEV or succeed if it would have succeeded without the
  disappearance.

- open() on a device node whose underlying device has disappeared will
  fail with ENXIO.

.. _GL_KHR_robustness: https://www.khronos.org/registry/OpenGL/extensions/KHR/KHR_robustness.txt
.. _Vulkan: https://www.khronos.org/vulkan/

Requirements for Memory Maps
----------------------------

Memory maps have further requirements that apply to both existing maps
and maps created after the device has disappeared. If the underlying
memory disappears, the map is created or modified such that reads and
writes will still complete successfully but the result is undefined.
This applies to both userspace mmap()'d memory and memory pointed to by
dmabuf which might be mapped to other devices (cross-device dmabuf
imports).

Raising SIGBUS is not an option, because userspace cannot realistically
handle it. Signal handlers are global, which makes them extremely
difficult to use correctly from libraries like those that Mesa produces.
Signal handlers are not composable, you can't have different handlers
for GPU1 and GPU2 from different vendors, and a third handler for
mmapped regular files. Threads cause additional pain with signal
handling as well.

Device reset과 robustness error propagation

288-378

GPU stack은 hardware bug, 잘못된 application과 여러 layer의 오류에 취약하며 device를 다시 사용하려면 reset이 필요할 수 있습니다. 이 절은 DRM과 user-mode driver가 reset 상태를 전파하는 방식을 설명합니다.

Kernel을 taint하지 않고 device reset을 비활성화할 수는 없습니다. 비활성화하면 shrinker·mmu_notifier를 통해 kernel 전체가 hang할 수 있습니다. Userspace는 reset message를 application에 전달하고 필요하면 원인 application 차단 policy를 적용합니다. 멈춘 GPU context를 debug하려면 정지 상태에서도 context를 preempt할 hardware 지원이 필요합니다.

KMD는 reset 필요 여부를 검사하고 필요하면 수행합니다. 보통 job 실행이 멈추면 hang을 감지합니다. Error는 command 흐름과 반대 방향으로 전파되므로 `dma_fence_set_error()`로 `dma_fence`에 vendor-independent error code를 넣고 signal합니다.

DRM scheduler는 reset 뒤 hardware submission을 재시작할 때 pending fence 전체에 error를 설정할 수 있고 hardware fence의 error를 scheduler fence로 전달해 stack 상위와 userspace까지 올립니다. Userspace는 generic `SYNC_IOC_FILE_INFO` 또는 driver-specific interface로 fence error를 조회합니다. KMD는 `drm_sched_entity_error()`로 context별 reset을 추적하고 영향받은 context의 새 command submission을 거부해야 합니다.

UMD는 command submission이 accepted인지 rejected인지 확인해야 합니다. Reset 뒤 KMD가 submission을 거부하면 UMD는 ioctl로 reset status를 확인하고 graphical API에 맞는 error code로 application에 보고합니다.

Reset 뒤 context를 계속 쓰려면 해당 graphical API의 robustness 규칙을 따라야 합니다. Non-robust OpenGL context나 robustness가 없는 libva 같은 API는 처리를 userspace driver에 전적으로 맡기며 합리적인 선택마다 단점이 있어 community consensus가 없습니다.

OpenGL application은 `GL_ARB_robustness`, OpenGL ES는 `GL_EXT_robustness`를 사용해야 합니다. Reset이 발생하면 context state 전체가 lost로 간주되어 새 context를 만듭니다. Vulkan application은 submission의 `VK_ERROR_DEVICE_LOST`를 확인하고 context를 재생성해야 합니다.

Reset 원인 분석을 위해 driver는 devcoredump에 관련 정보를 저장하고 recovery method가 `none`인 device-wedged event를 보내 userspace가 수집해 bug report에 첨부하도록 할 수 있습니다.

Reset error propagation
KMD가 stuck job과 reset 필요 감지dma_fence_set_error()와 scheduler fence에 error 설정Context별 reset 기록 후 새 submission 거부UMD가 ioctl·SYNC_IOC_FILE_INFO로 reset 확인Application에 GL robustness 또는 VK_ERROR_DEVICE_LOST 보고

Hardware hang에서 graphical API error까지 fence를 통해 전달합니다.

Graphical API recovery
API확인 수단동작
OpenGLGL_ARB_robustnessContext state를 lost로 보고 새 context 생성
OpenGL ESGL_EXT_robustnessContext state를 lost로 보고 재생성
VulkanVK_ERROR_DEVICE_LOSTDevice context를 재생성
Non-robust API표준 수단 없음Userspace driver policy에 의존

Application이 reset 뒤 context를 처리하는 규칙입니다.

Device reset
============

The GPU stack is really complex and is prone to errors, from hardware bugs,
faulty applications and everything in between the many layers. Some errors
require resetting the device in order to make the device usable again. This
section describes the expectations for DRM and usermode drivers when a
device resets and how to propagate the reset status.

Device resets can not be disabled without tainting the kernel, which can lead to
hanging the entire kernel through shrinkers/mmu_notifiers. Userspace role in
device resets is to propagate the message to the application and apply any
special policy for blocking guilty applications, if any. Corollary is that
debugging a hung GPU context require hardware support to be able to preempt such
a GPU context while it's stopped.

Kernel Mode Driver
------------------

The KMD is responsible for checking if the device needs a reset, and to perform
it as needed. Usually a hang is detected when a job gets stuck executing.

Propagation of errors to userspace has proven to be tricky since it goes in
the opposite direction of the usual flow of commands. Because of this vendor
independent error handling was added to the &dma_fence object, this way drivers
can add an error code to their fences before signaling them. See function
dma_fence_set_error() on how to do this and for examples of error codes to use.

The DRM scheduler also allows setting error codes on all pending fences when
hardware submissions are restarted after an reset. Error codes are also
forwarded from the hardware fence to the scheduler fence to bubble up errors
to the higher levels of the stack and eventually userspace.

Fence errors can be queried by userspace through the generic SYNC_IOC_FILE_INFO
IOCTL as well as through driver specific interfaces.

Additional to setting fence errors drivers should also keep track of resets per
context, the DRM scheduler provides the drm_sched_entity_error() function as
helper for this use case. After a reset, KMD should reject new command
submissions for affected contexts.

User Mode Driver
----------------

After command submission, UMD should check if the submission was accepted or
rejected. After a reset, KMD should reject submissions, and UMD can issue an
ioctl to the KMD to check the reset status, and this can be checked more often
if the UMD requires it. After detecting a reset, UMD will then proceed to report
it to the application using the appropriate API error code, as explained in the
section below about robustness.

Robustness
----------

The only way to try to keep a graphical API context working after a reset is if
it complies with the robustness aspects of the graphical API that it is using.

Graphical APIs provide ways to applications to deal with device resets. However,
there is no guarantee that the app will use such features correctly, and a
userspace that doesn't support robust interfaces (like a non-robust
OpenGL context or API without any robustness support like libva) leave the
robustness handling entirely to the userspace driver. There is no strong
community consensus on what the userspace driver should do in that case,
since all reasonable approaches have some clear downsides.

OpenGL
~~~~~~

Apps using OpenGL should use the available robust interfaces, like the
extension ``GL_ARB_robustness`` (or ``GL_EXT_robustness`` for OpenGL ES). This
interface tells if a reset has happened, and if so, all the context state is
considered lost and the app proceeds by creating new ones. There's no consensus
on what to do to if robustness is not in use.

Vulkan
~~~~~~

Apps using Vulkan should check for ``VK_ERROR_DEVICE_LOST`` for submissions.
This error code means, among other things, that a device reset has happened and
it needs to recreate the contexts to keep going.

Reporting causes of resets
--------------------------

Apart from propagating the reset through the stack so apps can recover, it's
really useful for driver developers to learn more about what caused the reset in
the first place. For this, drivers can make use of devcoredump to store relevant
information about the reset and send device wedged event with ``none`` recovery
method (as explained in "Device Wedging" chapter) to notify userspace, so this
information can be collected and added to user bug reports.

Device wedging event와 userspace recovery

379-539

Driver는 `drm_dev_wedged_event()`로 device가 hung/unusable한 wedged state임을 uevent로 알릴 수 있습니다. Driver context에서 복구할 수 없을 때 userspace 도움으로 device를 회복하되 driver가 전체 bus를 reset·재열거하는 과격한 조치를 직접 하지 않도록 하는 vendor-agnostic interface입니다.

Wedged device는 driver가 가능한 복구 시도를 모두 소진한 뒤 dead로 선언한 device입니다. Uevent는 userspace가 시도할 recovery hint를 함께 전달합니다. Hardware 구현에 따라 wedged의 의미가 다르므로 driver가 recovery 시점과 사용 가능한 method를 결정합니다.

Recovery 전에 driver는 system 전체를 보호해야 합니다. System memory DMA와 다른 device의 communication channel을 끄고 모든 `dma_fence`를 signal하며 core kernel이 의존하는 state를 정리해야 합니다. Existing mmap은 invalidate하고 page fault는 dummy page로 redirect합니다. Event 뒤 recovery까지 wedged state를 유지하고 새 ioctl access는 failure 유형에 가까운 error code로 거부해야 합니다.

Wedged event 전제
DMA와 device 간 communication channel 비활성화모든 dma_fence signal과 core dependency 정리Existing mmap invalidate, page fault를 dummy page로 redirect새 ioctl 거부 후 WEDGED uevent 전송Userspace recovery가 끝날 때까지 wedged state 유지

Userspace recovery를 요청하기 전에 driver가 system을 격리합니다.

Recovery method는 side effect가 적은 순서로 `WEDGED=<method1>[,..,<methodN>]`에 담깁니다. Driver는 `none`, `rebind`, `bus-reset`, `vendor-specific` 중 하나 이상 또는 아무 것도 선택할 수 있고 불명확하면 `unknown`을 보냅니다.

WEDGED recovery method
MethodConsumer 동작
none선택적 telemetry 수집
rebindDriver unbind 후 bind
bus-resetUnbind, bus reset/re-enumeration, bind
vendor-specificVendor가 문서화한 recovery 수행
unknownConsumer policy에 따라 결정

Uevent 값과 consumer가 기대하는 동작입니다.

`WEDGED=none`은 device가 일시적으로 wedged였으나 reset 같은 device-specific 방식으로 driver가 이미 복구했음을 뜻합니다. 명시적 recovery는 필요 없지만 첫 hang이 후속 hang이나 완전한 wedging의 원인이 될 수 있으므로 devcoredump·syslog telemetry를 수집할 수 있습니다.

`WEDGED=vendor-specific`은 표준 방법이 아닌 vendor hardware 고유 절차가 필요함을 뜻하며 한 driver 안에서도 여러 case를 나타낼 수 있습니다. Driver 문서는 모든 case, sysfs·debugfs·trace·dmesg 등 case를 구분할 hint, 필요한 script·tool을 포함한 명확한 recovery procedure를 제공해야 합니다. Admin/consumer는 case와 hint를 확인한 뒤 실행해야 합니다. Xe의 예는 `Xe Device Wedging <xe-device-wedging>` 문서를 참조합니다.

Wedging에 관련된 application 정보가 있으면 uevent에 `PID=<pid>`와 `TASK=<task name>`이 나타납니다. Userspace는 사용자 알림이나 반복 reset task 차단 policy에 활용할 수 있지만 정확도는 driver·hardware에 따라 다르므로 주의해야 합니다. 전체 상황은 devcoredump가 더 자세히 제공합니다.

Wedged event 정보
정보용도
WEDGED가능한 recovery method와 side-effect 순서
PID / TASK관련 application 알림·policy, 정확도는 보장되지 않음
devcoredumpDevice state와 reset 원인의 상세 자료
sysfs/debugfs/trace/dmesgVendor-specific case 식별 hint

Recovery 결정과 원인 분석에 쓰는 uevent·telemetry field입니다.

Consumer는 recovery 전에 어떤 process도 device나 resource를 사용하지 않게 해야 합니다. 실패하는 ioctl 뒤 모든 device memory를 unmap하고 fd를 닫아 leak과 undefined behavior를 막고 user context를 제거합니다. Vendor-specific method는 driver 문서와 use case를 확인해야 합니다.

`rebind` 예시는 다음 udev rule과 recovery script를 사용합니다.

SUBSYSTEM=="drm", ENV{WEDGED}=="rebind", DEVPATH=="*/drm/card[0-9]",
RUN+="/path/to/rebind.sh $env{DEVPATH}"
#!/bin/sh

DEVPATH=$(readlink -f /sys/$1/device)
DEVICE=$(basename $DEVPATH)
DRIVER=$(readlink -f $DEVPATH/driver)

echo -n $DEVICE > $DRIVER/unbind
echo -n $DEVICE > $DRIVER/bind

Consumer는 반복 offense, vendor failure 등 상황에 따라 여러 method 중 하나를 고르거나 device를 debug·telemetry 수집 상태로 남겨 결과에 따라 recovery를 결정하는 custom policy를 만들 수 있습니다. Driver가 recovery를 확신하지 못하거나 method가 unknown일 때 특히 유용합니다.

Device Wedging
==============

Drivers can optionally make use of device wedged event (implemented as
drm_dev_wedged_event() in DRM subsystem), which notifies userspace of 'wedged'
(hanged/unusable) state of the DRM device through a uevent. This is useful
especially in cases where the device is no longer operating as expected and has
become unrecoverable from driver context. Purpose of this implementation is to
provide drivers a generic way to recover the device with the help of userspace
intervention, without taking any drastic measures (like resetting or
re-enumerating the full bus, on which the underlying physical device is sitting)
in the driver.

A 'wedged' device is basically a device that is declared dead by the driver
after exhausting all possible attempts to recover it from driver context. The
uevent is the notification that is sent to userspace along with a hint about
what could possibly be attempted to recover the device from userspace and bring
it back to usable state. Different drivers may have different ideas of a
'wedged' device depending on hardware implementation of the underlying physical
device, and hence the vendor agnostic nature of the event. It is up to the
drivers to decide when they see the need for device recovery and how they want
to recover from the available methods.

Driver prerequisites
--------------------

The driver, before opting for recovery, needs to make sure that the 'wedged'
device doesn't harm the system as a whole by taking care of the prerequisites.
Necessary actions must include disabling DMA to system memory as well as any
communication channels with other devices. Further, the driver must ensure
that all dma_fences are signalled and any device state that the core kernel
might depend on is cleaned up. All existing mmaps should be invalidated and
page faults should be redirected to a dummy page. Once the event is sent, the
device must be kept in 'wedged' state until the recovery is performed. New
accesses to the device (IOCTLs) should be rejected, preferably with an error
code that resembles the type of failure the device has encountered. This will
signify the reason for wedging, which can be reported to the application if
needed.

Recovery
--------

Current implementation defines four recovery methods, out of which, drivers
can use any one, multiple or none. Method(s) of choice will be sent in the
uevent environment as ``WEDGED=<method1>[,..,<methodN>]`` in order of less to
more side-effects. See the section `Vendor Specific Recovery`_
for ``WEDGED=vendor-specific``. If driver is unsure about recovery or
method is unknown, ``WEDGED=unknown`` will be sent instead.

Userspace consumers can parse this event and attempt recovery as per the
following expectations.

    =============== ========================================
    Recovery method Consumer expectations
    =============== ========================================
    none            optional telemetry collection
    rebind          unbind + bind driver
    bus-reset       unbind + bus reset/re-enumeration + bind
    vendor-specific vendor specific recovery method
    unknown         consumer policy
    =============== ========================================

The only exception to this is ``WEDGED=none``, which signifies that the device
was temporarily 'wedged' at some point but was recovered from driver context
using device specific methods like reset. No explicit recovery is expected from
the consumer in this case, but it can still take additional steps like gathering
telemetry information (devcoredump, syslog). This is useful because the first
hang is usually the most critical one which can result in consequential hangs or
complete wedging.


Vendor Specific Recovery
------------------------

When ``WEDGED=vendor-specific`` is sent, it indicates that the device requires
a recovery procedure specific to the hardware vendor and is not one of the
standardized approaches.

``WEDGED=vendor-specific`` may be used to indicate different cases within a
single vendor driver, each requiring a distinct recovery procedure.
In such scenarios, the vendor driver must provide comprehensive documentation
that describes each case, include additional hints to identify specific case and
outline the corresponding recovery procedure. The documentation includes:

Case - A list of all cases that sends the ``WEDGED=vendor-specific`` recovery method.

Hints - Additional Information to assist the userspace consumer in identifying and
differentiating between different cases. This can be exposed through sysfs, debugfs,
traces, dmesg etc.

Recovery Procedure - Clear instructions and guidance for recovering each case.
This may include userspace scripts, tools needed for the recovery procedure.

It is the responsibility of the admin/userspace consumer to identify the case and
verify additional identification hints before attempting a recovery procedure.

Example: If the device uses the Xe driver, then userspace consumer should refer to
:ref:`Xe Device Wedging <xe-device-wedging>` for the detailed documentation.

Task information
----------------

The information about which application (if any) was involved in the device
wedging is useful for userspace if they want to notify the user about what
happened (e.g. the compositor display a message to the user "The <task name>
caused a graphical error and the system recovered") or to implement policies
(e.g. the daemon may "ban" an task that keeps resetting the device). If the task
information is available, the uevent will display as ``PID=<pid>`` and
``TASK=<task name>``. Otherwise, ``PID`` and ``TASK`` will not appear in the
event string.

The reliability of this information is driver and hardware specific, and should
be taken with a caution regarding it's precision. To have a big picture of what
really happened, the devcoredump file provides much more detailed information
about the device state and about the event.

Consumer prerequisites
----------------------

It is the responsibility of the consumer to make sure that the device or its
resources are not in use by any process before attempting recovery. With IOCTLs
erroring out, all device memory should be unmapped and file descriptors should
be closed to prevent leaks or undefined behaviour. The idea here is to clear the
device of all user context beforehand and set the stage for a clean recovery.

For ``WEDGED=vendor-specific`` recovery method, it is the responsibility of the
consumer to check the driver documentation and the usecase before attempting
a recovery.

Example - rebind
----------------

Udev rule::

    SUBSYSTEM=="drm", ENV{WEDGED}=="rebind", DEVPATH=="*/drm/card[0-9]",
    RUN+="/path/to/rebind.sh $env{DEVPATH}"

Recovery script::

    #!/bin/sh

    DEVPATH=$(readlink -f /sys/$1/device)
    DEVICE=$(basename $DEVPATH)
    DRIVER=$(readlink -f $DEVPATH/driver)

    echo -n $DEVICE > $DRIVER/unbind
    echo -n $DEVICE > $DRIVER/bind

Customization
-------------

Although basic recovery is possible with a simple script, consumers can define
custom policies around recovery. For example, if the driver supports multiple
recovery methods, consumers can opt for the suitable one depending on scenarios
like repeat offences or vendor specific failures. Consumers can also choose to
have the device available for debugging or telemetry collection and base their
recovery decision on the findings. This is useful especially when the driver is
unsure about recovery or method is unknown.

.. _drm_driver_ioctl:

Device node ioctl과 권장 errno

540-612

Driver-specific ioctl reference 뒤에는 DRM ioctl callback의 일반적인 return value 관례를 정리합니다. 이론상 허용 error code는 적지만 DRM에서는 공통 의미를 확장해 사용합니다.

DRM ioctl 권장 return value
ErrnoDRM에서의 의미
ENOENTUnknown GEM/KMS object handle 등 object lookup 실패
ENOSPCVRAM 또는 제한된 GPU resource 부족; kernel/system memory 부족은 ENOMEM
EPERM / EACCES유효하지만 root·DRM master 등 추가 권한이 필요한 operation
ENODEVDevice가 사라졌거나 아직 완전히 초기화되지 않음
EOPNOTSUPPPRIME·modesetting·GEM 같은 기능을 driver가 지원하지 않음
ENXIOI2C transaction 또는 shared dma-buf/fence exporter의 remote failure
EINTRParameter를 바꾸지 않고 userspace가 ioctl을 재시작해야 함
EIOGPU reset으로도 복구할 수 없음; modeset failure는 connector link status 사용
EINVAL동작할 수 없는 invalid argument 조합의 catch-all
ENOTTY해당 ioctl이 존재하지 않음

DRM-specific 관례와 일반 kernel 의미를 구분합니다.

Command submission의 allocation·reservation 문제는 `EDEADLK`로 나타날 수도 있습니다. `ETIME`, `EFAULT`, `EBUSY` 등 다른 code는 일반 의미대로 사용합니다. DRM ioctl은 언제든 `EINTR`를 반환할 수 있고 userspace는 argument를 그대로 두고 재시작해야 합니다.

Kernel-doc: driver ioctl
Source pathSelector포함 범위
drivers/gpu/drm/drm_ioctl.c:doc: driver specific ioctlsdriver specific ioctls 문서 블록
include/drm/drm_ioctl.h:internal:내부 type·함수 문서
drivers/gpu/drm/drm_ioctl.c:export:Exported API
drivers/gpu/drm/drm_ioc32.c:export:Exported API

Driver-specific ioctl 설명, 내부 declaration, native·compat exported API의 4개 block입니다.

IOCTL Support on Device Nodes
=============================

.. kernel-doc:: drivers/gpu/drm/drm_ioctl.c
   :doc: driver specific ioctls

Recommended IOCTL Return Values
-------------------------------

In theory a driver's IOCTL callback is only allowed to return very few error
codes. In practice it's good to abuse a few more. This section documents common
practice within the DRM subsystem:

ENOENT:
        Strictly this should only be used when a file doesn't exist e.g. when
        calling the open() syscall. We reuse that to signal any kind of object
        lookup failure, e.g. for unknown GEM buffer object handles, unknown KMS
        object handles and similar cases.

ENOSPC:
        Some drivers use this to differentiate "out of kernel memory" from "out
        of VRAM". Sometimes also applies to other limited gpu resources used for
        rendering (e.g. when you have a special limited compression buffer).
        Sometimes resource allocation/reservation issues in command submission
        IOCTLs are also signalled through EDEADLK.

        Simply running out of kernel/system memory is signalled through ENOMEM.

EPERM/EACCES:
        Returned for an operation that is valid, but needs more privileges.
        E.g. root-only or much more common, DRM master-only operations return
        this when called by unpriviledged clients. There's no clear
        difference between EACCES and EPERM.

ENODEV:
        The device is not present anymore or is not yet fully initialized.

EOPNOTSUPP:
        Feature (like PRIME, modesetting, GEM) is not supported by the driver.

ENXIO:
        Remote failure, either a hardware transaction (like i2c), but also used
        when the exporting driver of a shared dma-buf or fence doesn't support a
        feature needed.

EINTR:
        DRM drivers assume that userspace restarts all IOCTLs. Any DRM IOCTL can
        return EINTR and in such a case should be restarted with the IOCTL
        parameters left unchanged.

EIO:
        The GPU died and couldn't be resurrected through a reset. Modesetting
        hardware failures are signalled through the "link status" connector
        property.

EINVAL:
        Catch-all for anything that is an invalid argument combination which
        cannot work.

IOCTL also use other error codes like ETIME, EFAULT, EBUSY, ENOTTY but their
usage is in line with the common meanings. The above list tries to just document
DRM specific patterns. Note that ENOTTY has the slightly unintuitive meaning of
"this IOCTL does not exist", and is used exactly as such in DRM.

.. kernel-doc:: include/drm/drm_ioctl.h
   :internal:

.. kernel-doc:: drivers/gpu/drm/drm_ioctl.c
   :export:

.. kernel-doc:: drivers/gpu/drm/drm_ioc32.c
   :export:

IGT와 VKMS를 이용한 UAPI 검증

613-669

새 ioctl, KMS property, sysfs file처럼 cross-driver userspace interface를 확장하는 API 변경에는 target hardware에서 IGT로 합리적으로 test할 수 있다면 driver-agnostic IGT testcase가 있어야 합니다.

IGT는 DRM driver와 core의 전체 기능을 다루고 regression을 확인하는 test suite입니다. Code와 build·실행 지침은 `https://gitlab.freedesktop.org/drm/igt-gpu-tools/`에서 제공합니다.

VKMS는 hardware display 없이 virtual display를 제공하는 software-only KMS driver model입니다. DRM core 동작과 compositor를 검증하고 display가 없는 virtual machine에서도 DRM function을 test할 수 있습니다.

VKMS module을 활성화한 kernel을 build해 target에 설치하고 QEMU·virtme 같은 VM에서 실행합니다. KVM, 최소 RAM 1GB와 4 core를 권장합니다. IGT는 VM 내부에서 직접 실행하거나 host에서 실행해 shared directory에 결과를 기록할 수 있습니다.

$ virtme-run --rwdir /path/for/shared_dir --kdir=path/for/kernel/directory --mods=auto
$ /path/for/igt-gpu-tools/scripts/run-tests.sh -p -s -t "kms_flip.*" -v

예시는 `kms_flip.*` test만 실행합니다. `-p` option으로 `igt_runner` 대신 Piglit을 사용해 HTML summary를 만들고 `igt-gpu-tools/results`에 저장하며 `-t`와 일치하는 test만 실행합니다.

DRM API 검증 구성
도구역할
IGTCross-driver testcase와 regression suite
VKMSHardware 없는 virtual KMS implementation
virtme/QEMUVKMS kernel과 test를 실행할 VM
Piglit modeHTML result summary 생성

새 UAPI와 core 변경을 검증하는 도구별 역할입니다.

Testing and validation
======================

Testing Requirements for userspace API
--------------------------------------

New cross-driver userspace interface extensions, like new IOCTL, new KMS
properties, new files in sysfs or anything else that constitutes an API change
should have driver-agnostic testcases in IGT for that feature, if such a test
can be reasonably made using IGT for the target hardware.

Validating changes with IGT
---------------------------

There's a collection of tests that aims to cover the whole functionality of
DRM drivers and that can be used to check that changes to DRM drivers or the
core don't regress existing functionality. This test suite is called IGT and
its code and instructions to build and run can be found in
https://gitlab.freedesktop.org/drm/igt-gpu-tools/.

Using VKMS to test DRM API
--------------------------

VKMS is a software-only model of a KMS driver that is useful for testing
and for running compositors. VKMS aims to enable a virtual display without
the need for a hardware display capability. These characteristics made VKMS
a perfect tool for validating the DRM core behavior and also support the
compositor developer. VKMS makes it possible to test DRM functions in a
virtual machine without display, simplifying the validation of some of the
core changes.

To Validate changes in DRM API with VKMS, start setting the kernel: make
sure to enable VKMS module; compile the kernel with the VKMS enabled and
install it in the target machine. VKMS can be run in a Virtual Machine
(QEMU, virtme or similar). It's recommended the use of KVM with the minimum
of 1GB of RAM and four cores.

It's possible to run the IGT-tests in a VM in two ways:

        1. Use IGT inside a VM
        2. Use IGT from the host machine and write the results in a shared directory.

Following is an example of using a VM with a shared directory with
the host machine to run igt-tests. This example uses virtme::

        $ virtme-run --rwdir /path/for/shared_dir --kdir=path/for/kernel/directory --mods=auto

Run the igt-tests in the guest machine. This example runs the 'kms_flip'
tests::

        $ /path/for/igt-gpu-tools/scripts/run-tests.sh -p -s -t "kms_flip.*" -v

In this example, instead of building the igt_runner, Piglit is used
(-p option). It creates an HTML summary of the test results and saves
them in the folder "igt-gpu-tools/results". It executes only the igt-tests
matching the -t option.

CRC·debugfs·sysfs, vblank와 CRTC index

670-740

Display CRC support는 `drm_debugfs_crc.c`의 CRC ABI와 exported API를 제공합니다. Debugfs support는 header 내부 interface와 implementation API를, sysfs support는 overview와 exported API를 제공합니다.

DRM core는 vertical blank 관련 ioctl 두 개를 노출합니다. `DRM_IOCTL_WAIT_VBLANK`는 `struct drm_wait_vblank`을 받아 지정 vblank event가 발생할 때 block하거나 signal을 요청합니다.

`DRM_IOCTL_MODESET_CTL`은 과거 user-mode-setting driver가 modeset 뒤 vblank interrupt를 갱신하도록 사용했습니다. 많은 device가 modeset 중 vblank counter를 0으로 reset하기 때문입니다. 현대 kernel mode setting driver에서는 no-op이므로 호출하면 안 됩니다.

Vblank ioctl
Ioctl상태역할
DRM_IOCTL_WAIT_VBLANK사용특정 vblank event 대기 또는 signal 요청
DRM_IOCTL_MODESET_CTLLegacy no-opUser-mode-setting 시절 modeset 전후 vblank 갱신

Legacy와 현재 사용 가능한 vertical blank interface를 구분합니다.

Userspace API structure는 `include/uapi/drm/drm_mode.h` overview와 `drm.h`·`drm_mode.h` 내부 문서를 제공합니다. CRTC에는 object ID와 별개의 index가 있습니다. Index는 CRTC bitmask처럼 조밀한 식별자가 필요할 때 쓰며 `drm_mode_get_plane.possible_crtcs`가 예입니다.

`DRM_IOCTL_MODE_GETRESOURCES`가 채우는 CRTC ID array에서 CRTC index는 해당 ID의 array 위치입니다.

Kernel-doc: CRC·debugfs·sysfs·UAPI structure
Source pathSelector포함 범위
drivers/gpu/drm/drm_debugfs_crc.c:doc: CRC ABICRC ABI 문서 블록
drivers/gpu/drm/drm_debugfs_crc.c:export:Exported API
include/drm/drm_debugfs.h:internal:내부 type·함수 문서
drivers/gpu/drm/drm_debugfs.c:export:Exported API
drivers/gpu/drm/drm_sysfs.c:doc: overviewoverview 문서 블록
drivers/gpu/drm/drm_sysfs.c:export:Exported API
include/uapi/drm/drm_mode.h:doc: overviewoverview 문서 블록
include/uapi/drm/drm.h:internal:내부 type·함수 문서
include/uapi/drm/drm_mode.h:internal:내부 type·함수 문서

Display validation interface와 public mode structure의 9개 block입니다.

Display CRC Support
-------------------

.. kernel-doc:: drivers/gpu/drm/drm_debugfs_crc.c
   :doc: CRC ABI

.. kernel-doc:: drivers/gpu/drm/drm_debugfs_crc.c
   :export:

Debugfs Support
---------------

.. kernel-doc:: include/drm/drm_debugfs.h
   :internal:

.. kernel-doc:: drivers/gpu/drm/drm_debugfs.c
   :export:

Sysfs Support
=============

.. kernel-doc:: drivers/gpu/drm/drm_sysfs.c
   :doc: overview

.. kernel-doc:: drivers/gpu/drm/drm_sysfs.c
   :export:


VBlank event handling
=====================

The DRM core exposes two vertical blank related ioctls:

:c:macro:`DRM_IOCTL_WAIT_VBLANK`
    This takes a struct drm_wait_vblank structure as its argument, and
    it is used to block or request a signal when a specified vblank
    event occurs.

:c:macro:`DRM_IOCTL_MODESET_CTL`
    This was only used for user-mode-settind drivers around modesetting
    changes to allow the kernel to update the vblank interrupt after
    mode setting, since on many devices the vertical blank counter is
    reset to 0 at some point during modeset. Modern drivers should not
    call this any more since with kernel mode setting it is a no-op.

Userspace API Structures
========================

.. kernel-doc:: include/uapi/drm/drm_mode.h
   :doc: overview

.. _crtc_index:

CRTC index
----------

CRTC's have both an object ID and an index, and they are not the same thing.
The index is used in cases where a densely packed identifier for a CRTC is
needed, for instance a bitmask of CRTC's. The member possible_crtcs of struct
drm_mode_get_plane is an example.

:c:macro:`DRM_IOCTL_MODE_GETRESOURCES` populates a structure with an array of
CRTC ID's, and the CRTC index is its position in this array.

.. kernel-doc:: include/uapi/drm/drm.h
   :internal:

.. kernel-doc:: include/uapi/drm/drm_mode.h
   :internal:

dma-buf interoperability와 stable trace event

741-764

DRM 안에서 dma-buf를 통합·노출하는 방법은 `Documentation/userspace-api/dma-buf-alloc-exchange.rst`를 참조합니다.

Linux kernel tracepoint 사용법은 `Documentation/trace/tracepoints.rst`를 참조합니다. DRM subsystem의 일부 event는 GPUVis, umr 같은 tool을 깨뜨리지 않기 위해 stable uAPI로 간주됩니다.

Stable event에서는 field를 제거하거나 formatting을 바꿀 수 없습니다. 새 field 추가는 일반 uAPI 요구사항을 충족하면 가능합니다. `drivers/gpu/drm/scheduler/gpu_scheduler_trace.h`의 `uAPI trace events` kernel-doc이 stable scheduler event를 정의합니다.

Stable trace uAPI 규칙
변경허용 여부
기존 field 제거금지
기존 formatting 변경금지
새 field 추가일반 uAPI 요구사항을 충족하면 가능

Tool compatibility를 위해 허용되는 변경과 금지되는 변경입니다.

Kernel-doc: stable scheduler trace
Source pathSelector포함 범위
drivers/gpu/drm/scheduler/gpu_scheduler_trace.h:doc: uAPI trace eventsuAPI trace events 문서 블록

GPU scheduler가 stable uAPI로 제공하는 trace event 문서입니다.

dma-buf interoperability
========================

Please see Documentation/userspace-api/dma-buf-alloc-exchange.rst for
information on how dma-buf is integrated and exposed within DRM.


Trace events
============

See Documentation/trace/tracepoints.rst for information about using
Linux Kernel Tracepoints.
In the DRM subsystem, some events are considered stable uAPI to avoid
breaking tools (e.g.: GPUVis, umr) relying on them. Stable means that fields
cannot be removed, nor their formatting updated. Adding new fields is
possible, under the normal uAPI requirements.

Stable uAPI events
------------------

From ``drivers/gpu/drm/scheduler/gpu_scheduler_trace.h``

.. kernel-doc::  drivers/gpu/drm/scheduler/gpu_scheduler_trace.h
   :doc: uAPI trace events