-
Notifications
You must be signed in to change notification settings - Fork 3.3k
/
Copy pathdrm.tmpl
4231 lines (4175 loc) · 174 KB
/
drm.tmpl
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE book PUBLIC "-//OASIS//DTD DocBook XML V4.1.2//EN"
"http://www.oasis-open.org/docbook/xml/4.1.2/docbookx.dtd" []>
<book id="drmDevelopersGuide">
<bookinfo>
<title>Linux DRM Developer's Guide</title>
<authorgroup>
<author>
<firstname>Jesse</firstname>
<surname>Barnes</surname>
<contrib>Initial version</contrib>
<affiliation>
<orgname>Intel Corporation</orgname>
<address>
<email>jesse.barnes@intel.com</email>
</address>
</affiliation>
</author>
<author>
<firstname>Laurent</firstname>
<surname>Pinchart</surname>
<contrib>Driver internals</contrib>
<affiliation>
<orgname>Ideas on board SPRL</orgname>
<address>
<email>laurent.pinchart@ideasonboard.com</email>
</address>
</affiliation>
</author>
<author>
<firstname>Daniel</firstname>
<surname>Vetter</surname>
<contrib>Contributions all over the place</contrib>
<affiliation>
<orgname>Intel Corporation</orgname>
<address>
<email>daniel.vetter@ffwll.ch</email>
</address>
</affiliation>
</author>
</authorgroup>
<copyright>
<year>2008-2009</year>
<year>2013-2014</year>
<holder>Intel Corporation</holder>
</copyright>
<copyright>
<year>2012</year>
<holder>Laurent Pinchart</holder>
</copyright>
<legalnotice>
<para>
The contents of this file may be used under the terms of the GNU
General Public License version 2 (the "GPL") as distributed in
the kernel source COPYING file.
</para>
</legalnotice>
<revhistory>
<!-- Put document revisions here, newest first. -->
<revision>
<revnumber>1.0</revnumber>
<date>2012-07-13</date>
<authorinitials>LP</authorinitials>
<revremark>Added extensive documentation about driver internals.
</revremark>
</revision>
</revhistory>
</bookinfo>
<toc></toc>
<part id="drmCore">
<title>DRM Core</title>
<partintro>
<para>
This first part of the DRM Developer's Guide documents core DRM code,
helper libraries for writing drivers and generic userspace interfaces
exposed by DRM drivers.
</para>
</partintro>
<chapter id="drmIntroduction">
<title>Introduction</title>
<para>
The Linux DRM layer contains code intended to support the needs
of complex graphics devices, usually containing programmable
pipelines well suited to 3D graphics acceleration. Graphics
drivers in the kernel may make use of DRM functions to make
tasks like memory management, interrupt handling and DMA easier,
and provide a uniform interface to applications.
</para>
<para>
A note on versions: this guide covers features found in the DRM
tree, including the TTM memory manager, output configuration and
mode setting, and the new vblank internals, in addition to all
the regular features found in current kernels.
</para>
<para>
[Insert diagram of typical DRM stack here]
</para>
</chapter>
<!-- Internals -->
<chapter id="drmInternals">
<title>DRM Internals</title>
<para>
This chapter documents DRM internals relevant to driver authors
and developers working to add support for the latest features to
existing drivers.
</para>
<para>
First, we go over some typical driver initialization
requirements, like setting up command buffers, creating an
initial output configuration, and initializing core services.
Subsequent sections cover core internals in more detail,
providing implementation notes and examples.
</para>
<para>
The DRM layer provides several services to graphics drivers,
many of them driven by the application interfaces it provides
through libdrm, the library that wraps most of the DRM ioctls.
These include vblank event handling, memory
management, output management, framebuffer management, command
submission & fencing, suspend/resume support, and DMA
services.
</para>
<!-- Internals: driver init -->
<sect1>
<title>Driver Initialization</title>
<para>
At the core of every DRM driver is a <structname>drm_driver</structname>
structure. Drivers typically statically initialize a drm_driver structure,
and then pass it to one of the <function>drm_*_init()</function> functions
to register it with the DRM subsystem.
</para>
<para>
Newer drivers that no longer require a <structname>drm_bus</structname>
structure can alternatively use the low-level device initialization and
registration functions such as <function>drm_dev_alloc()</function> and
<function>drm_dev_register()</function> directly.
</para>
<para>
The <structname>drm_driver</structname> structure contains static
information that describes the driver and features it supports, and
pointers to methods that the DRM core will call to implement the DRM API.
We will first go through the <structname>drm_driver</structname> static
information fields, and will then describe individual operations in
details as they get used in later sections.
</para>
<sect2>
<title>Driver Information</title>
<sect3>
<title>Driver Features</title>
<para>
Drivers inform the DRM core about their requirements and supported
features by setting appropriate flags in the
<structfield>driver_features</structfield> field. Since those flags
influence the DRM core behaviour since registration time, most of them
must be set to registering the <structname>drm_driver</structname>
instance.
</para>
<synopsis>u32 driver_features;</synopsis>
<variablelist>
<title>Driver Feature Flags</title>
<varlistentry>
<term>DRIVER_USE_AGP</term>
<listitem><para>
Driver uses AGP interface, the DRM core will manage AGP resources.
</para></listitem>
</varlistentry>
<varlistentry>
<term>DRIVER_REQUIRE_AGP</term>
<listitem><para>
Driver needs AGP interface to function. AGP initialization failure
will become a fatal error.
</para></listitem>
</varlistentry>
<varlistentry>
<term>DRIVER_PCI_DMA</term>
<listitem><para>
Driver is capable of PCI DMA, mapping of PCI DMA buffers to
userspace will be enabled. Deprecated.
</para></listitem>
</varlistentry>
<varlistentry>
<term>DRIVER_SG</term>
<listitem><para>
Driver can perform scatter/gather DMA, allocation and mapping of
scatter/gather buffers will be enabled. Deprecated.
</para></listitem>
</varlistentry>
<varlistentry>
<term>DRIVER_HAVE_DMA</term>
<listitem><para>
Driver supports DMA, the userspace DMA API will be supported.
Deprecated.
</para></listitem>
</varlistentry>
<varlistentry>
<term>DRIVER_HAVE_IRQ</term><term>DRIVER_IRQ_SHARED</term>
<listitem><para>
DRIVER_HAVE_IRQ indicates whether the driver has an IRQ handler
managed by the DRM Core. The core will support simple IRQ handler
installation when the flag is set. The installation process is
described in <xref linkend="drm-irq-registration"/>.</para>
<para>DRIVER_IRQ_SHARED indicates whether the device & handler
support shared IRQs (note that this is required of PCI drivers).
</para></listitem>
</varlistentry>
<varlistentry>
<term>DRIVER_GEM</term>
<listitem><para>
Driver use the GEM memory manager.
</para></listitem>
</varlistentry>
<varlistentry>
<term>DRIVER_MODESET</term>
<listitem><para>
Driver supports mode setting interfaces (KMS).
</para></listitem>
</varlistentry>
<varlistentry>
<term>DRIVER_PRIME</term>
<listitem><para>
Driver implements DRM PRIME buffer sharing.
</para></listitem>
</varlistentry>
<varlistentry>
<term>DRIVER_RENDER</term>
<listitem><para>
Driver supports dedicated render nodes.
</para></listitem>
</varlistentry>
<varlistentry>
<term>DRIVER_ATOMIC</term>
<listitem><para>
Driver supports atomic properties. In this case the driver
must implement appropriate obj->atomic_get_property() vfuncs
for any modeset objects with driver specific properties.
</para></listitem>
</varlistentry>
</variablelist>
</sect3>
<sect3>
<title>Major, Minor and Patchlevel</title>
<synopsis>int major;
int minor;
int patchlevel;</synopsis>
<para>
The DRM core identifies driver versions by a major, minor and patch
level triplet. The information is printed to the kernel log at
initialization time and passed to userspace through the
DRM_IOCTL_VERSION ioctl.
</para>
<para>
The major and minor numbers are also used to verify the requested driver
API version passed to DRM_IOCTL_SET_VERSION. When the driver API changes
between minor versions, applications can call DRM_IOCTL_SET_VERSION to
select a specific version of the API. If the requested major isn't equal
to the driver major, or the requested minor is larger than the driver
minor, the DRM_IOCTL_SET_VERSION call will return an error. Otherwise
the driver's set_version() method will be called with the requested
version.
</para>
</sect3>
<sect3>
<title>Name, Description and Date</title>
<synopsis>char *name;
char *desc;
char *date;</synopsis>
<para>
The driver name is printed to the kernel log at initialization time,
used for IRQ registration and passed to userspace through
DRM_IOCTL_VERSION.
</para>
<para>
The driver description is a purely informative string passed to
userspace through the DRM_IOCTL_VERSION ioctl and otherwise unused by
the kernel.
</para>
<para>
The driver date, formatted as YYYYMMDD, is meant to identify the date of
the latest modification to the driver. However, as most drivers fail to
update it, its value is mostly useless. The DRM core prints it to the
kernel log at initialization time and passes it to userspace through the
DRM_IOCTL_VERSION ioctl.
</para>
</sect3>
</sect2>
<sect2>
<title>Device Registration</title>
<para>
A number of functions are provided to help with device registration.
The functions deal with PCI and platform devices, respectively.
</para>
!Edrivers/gpu/drm/drm_pci.c
!Edrivers/gpu/drm/drm_platform.c
<para>
New drivers that no longer rely on the services provided by the
<structname>drm_bus</structname> structure can call the low-level
device registration functions directly. The
<function>drm_dev_alloc()</function> function can be used to allocate
and initialize a new <structname>drm_device</structname> structure.
Drivers will typically want to perform some additional setup on this
structure, such as allocating driver-specific data and storing a
pointer to it in the DRM device's <structfield>dev_private</structfield>
field. Drivers should also set the device's unique name using the
<function>drm_dev_set_unique()</function> function. After it has been
set up a device can be registered with the DRM subsystem by calling
<function>drm_dev_register()</function>. This will cause the device to
be exposed to userspace and will call the driver's
<structfield>.load()</structfield> implementation. When a device is
removed, the DRM device can safely be unregistered and freed by calling
<function>drm_dev_unregister()</function> followed by a call to
<function>drm_dev_unref()</function>.
</para>
!Edrivers/gpu/drm/drm_drv.c
</sect2>
<sect2>
<title>Driver Load</title>
<para>
The <methodname>load</methodname> method is the driver and device
initialization entry point. The method is responsible for allocating and
initializing driver private data, performing resource allocation and
mapping (e.g. acquiring
clocks, mapping registers or allocating command buffers), initializing
the memory manager (<xref linkend="drm-memory-management"/>), installing
the IRQ handler (<xref linkend="drm-irq-registration"/>), setting up
vertical blanking handling (<xref linkend="drm-vertical-blank"/>), mode
setting (<xref linkend="drm-mode-setting"/>) and initial output
configuration (<xref linkend="drm-kms-init"/>).
</para>
<note><para>
If compatibility is a concern (e.g. with drivers converted over from
User Mode Setting to Kernel Mode Setting), care must be taken to prevent
device initialization and control that is incompatible with currently
active userspace drivers. For instance, if user level mode setting
drivers are in use, it would be problematic to perform output discovery
& configuration at load time. Likewise, if user-level drivers
unaware of memory management are in use, memory management and command
buffer setup may need to be omitted. These requirements are
driver-specific, and care needs to be taken to keep both old and new
applications and libraries working.
</para></note>
<synopsis>int (*load) (struct drm_device *, unsigned long flags);</synopsis>
<para>
The method takes two arguments, a pointer to the newly created
<structname>drm_device</structname> and flags. The flags are used to
pass the <structfield>driver_data</structfield> field of the device id
corresponding to the device passed to <function>drm_*_init()</function>.
Only PCI devices currently use this, USB and platform DRM drivers have
their <methodname>load</methodname> method called with flags to 0.
</para>
<sect3>
<title>Driver Private Data</title>
<para>
The driver private hangs off the main
<structname>drm_device</structname> structure and can be used for
tracking various device-specific bits of information, like register
offsets, command buffer status, register state for suspend/resume, etc.
At load time, a driver may simply allocate one and set
<structname>drm_device</structname>.<structfield>dev_priv</structfield>
appropriately; it should be freed and
<structname>drm_device</structname>.<structfield>dev_priv</structfield>
set to NULL when the driver is unloaded.
</para>
</sect3>
<sect3 id="drm-irq-registration">
<title>IRQ Registration</title>
<para>
The DRM core tries to facilitate IRQ handler registration and
unregistration by providing <function>drm_irq_install</function> and
<function>drm_irq_uninstall</function> functions. Those functions only
support a single interrupt per device, devices that use more than one
IRQs need to be handled manually.
</para>
<sect4>
<title>Managed IRQ Registration</title>
<para>
<function>drm_irq_install</function> starts by calling the
<methodname>irq_preinstall</methodname> driver operation. The operation
is optional and must make sure that the interrupt will not get fired by
clearing all pending interrupt flags or disabling the interrupt.
</para>
<para>
The passed-in IRQ will then be requested by a call to
<function>request_irq</function>. If the DRIVER_IRQ_SHARED driver
feature flag is set, a shared (IRQF_SHARED) IRQ handler will be
requested.
</para>
<para>
The IRQ handler function must be provided as the mandatory irq_handler
driver operation. It will get passed directly to
<function>request_irq</function> and thus has the same prototype as all
IRQ handlers. It will get called with a pointer to the DRM device as the
second argument.
</para>
<para>
Finally the function calls the optional
<methodname>irq_postinstall</methodname> driver operation. The operation
usually enables interrupts (excluding the vblank interrupt, which is
enabled separately), but drivers may choose to enable/disable interrupts
at a different time.
</para>
<para>
<function>drm_irq_uninstall</function> is similarly used to uninstall an
IRQ handler. It starts by waking up all processes waiting on a vblank
interrupt to make sure they don't hang, and then calls the optional
<methodname>irq_uninstall</methodname> driver operation. The operation
must disable all hardware interrupts. Finally the function frees the IRQ
by calling <function>free_irq</function>.
</para>
</sect4>
<sect4>
<title>Manual IRQ Registration</title>
<para>
Drivers that require multiple interrupt handlers can't use the managed
IRQ registration functions. In that case IRQs must be registered and
unregistered manually (usually with the <function>request_irq</function>
and <function>free_irq</function> functions, or their devm_* equivalent).
</para>
<para>
When manually registering IRQs, drivers must not set the DRIVER_HAVE_IRQ
driver feature flag, and must not provide the
<methodname>irq_handler</methodname> driver operation. They must set the
<structname>drm_device</structname> <structfield>irq_enabled</structfield>
field to 1 upon registration of the IRQs, and clear it to 0 after
unregistering the IRQs.
</para>
</sect4>
</sect3>
<sect3>
<title>Memory Manager Initialization</title>
<para>
Every DRM driver requires a memory manager which must be initialized at
load time. DRM currently contains two memory managers, the Translation
Table Manager (TTM) and the Graphics Execution Manager (GEM).
This document describes the use of the GEM memory manager only. See
<xref linkend="drm-memory-management"/> for details.
</para>
</sect3>
<sect3>
<title>Miscellaneous Device Configuration</title>
<para>
Another task that may be necessary for PCI devices during configuration
is mapping the video BIOS. On many devices, the VBIOS describes device
configuration, LCD panel timings (if any), and contains flags indicating
device state. Mapping the BIOS can be done using the pci_map_rom() call,
a convenience function that takes care of mapping the actual ROM,
whether it has been shadowed into memory (typically at address 0xc0000)
or exists on the PCI device in the ROM BAR. Note that after the ROM has
been mapped and any necessary information has been extracted, it should
be unmapped; on many devices, the ROM address decoder is shared with
other BARs, so leaving it mapped could cause undesired behaviour like
hangs or memory corruption.
<!--!Fdrivers/pci/rom.c pci_map_rom-->
</para>
</sect3>
</sect2>
</sect1>
<!-- Internals: memory management -->
<sect1 id="drm-memory-management">
<title>Memory management</title>
<para>
Modern Linux systems require large amount of graphics memory to store
frame buffers, textures, vertices and other graphics-related data. Given
the very dynamic nature of many of that data, managing graphics memory
efficiently is thus crucial for the graphics stack and plays a central
role in the DRM infrastructure.
</para>
<para>
The DRM core includes two memory managers, namely Translation Table Maps
(TTM) and Graphics Execution Manager (GEM). TTM was the first DRM memory
manager to be developed and tried to be a one-size-fits-them all
solution. It provides a single userspace API to accommodate the need of
all hardware, supporting both Unified Memory Architecture (UMA) devices
and devices with dedicated video RAM (i.e. most discrete video cards).
This resulted in a large, complex piece of code that turned out to be
hard to use for driver development.
</para>
<para>
GEM started as an Intel-sponsored project in reaction to TTM's
complexity. Its design philosophy is completely different: instead of
providing a solution to every graphics memory-related problems, GEM
identified common code between drivers and created a support library to
share it. GEM has simpler initialization and execution requirements than
TTM, but has no video RAM management capabilities and is thus limited to
UMA devices.
</para>
<sect2>
<title>The Translation Table Manager (TTM)</title>
<para>
TTM design background and information belongs here.
</para>
<sect3>
<title>TTM initialization</title>
<warning><para>This section is outdated.</para></warning>
<para>
Drivers wishing to support TTM must fill out a drm_bo_driver
structure. The structure contains several fields with function
pointers for initializing the TTM, allocating and freeing memory,
waiting for command completion and fence synchronization, and memory
migration. See the radeon_ttm.c file for an example of usage.
</para>
<para>
The ttm_global_reference structure is made up of several fields:
</para>
<programlisting>
struct ttm_global_reference {
enum ttm_global_types global_type;
size_t size;
void *object;
int (*init) (struct ttm_global_reference *);
void (*release) (struct ttm_global_reference *);
};
</programlisting>
<para>
There should be one global reference structure for your memory
manager as a whole, and there will be others for each object
created by the memory manager at runtime. Your global TTM should
have a type of TTM_GLOBAL_TTM_MEM. The size field for the global
object should be sizeof(struct ttm_mem_global), and the init and
release hooks should point at your driver-specific init and
release routines, which probably eventually call
ttm_mem_global_init and ttm_mem_global_release, respectively.
</para>
<para>
Once your global TTM accounting structure is set up and initialized
by calling ttm_global_item_ref() on it,
you need to create a buffer object TTM to
provide a pool for buffer object allocation by clients and the
kernel itself. The type of this object should be TTM_GLOBAL_TTM_BO,
and its size should be sizeof(struct ttm_bo_global). Again,
driver-specific init and release functions may be provided,
likely eventually calling ttm_bo_global_init() and
ttm_bo_global_release(), respectively. Also, like the previous
object, ttm_global_item_ref() is used to create an initial reference
count for the TTM, which will call your initialization function.
</para>
</sect3>
</sect2>
<sect2 id="drm-gem">
<title>The Graphics Execution Manager (GEM)</title>
<para>
The GEM design approach has resulted in a memory manager that doesn't
provide full coverage of all (or even all common) use cases in its
userspace or kernel API. GEM exposes a set of standard memory-related
operations to userspace and a set of helper functions to drivers, and let
drivers implement hardware-specific operations with their own private API.
</para>
<para>
The GEM userspace API is described in the
<ulink url="http://lwn.net/Articles/283798/"><citetitle>GEM - the Graphics
Execution Manager</citetitle></ulink> article on LWN. While slightly
outdated, the document provides a good overview of the GEM API principles.
Buffer allocation and read and write operations, described as part of the
common GEM API, are currently implemented using driver-specific ioctls.
</para>
<para>
GEM is data-agnostic. It manages abstract buffer objects without knowing
what individual buffers contain. APIs that require knowledge of buffer
contents or purpose, such as buffer allocation or synchronization
primitives, are thus outside of the scope of GEM and must be implemented
using driver-specific ioctls.
</para>
<para>
On a fundamental level, GEM involves several operations:
<itemizedlist>
<listitem>Memory allocation and freeing</listitem>
<listitem>Command execution</listitem>
<listitem>Aperture management at command execution time</listitem>
</itemizedlist>
Buffer object allocation is relatively straightforward and largely
provided by Linux's shmem layer, which provides memory to back each
object.
</para>
<para>
Device-specific operations, such as command execution, pinning, buffer
read & write, mapping, and domain ownership transfers are left to
driver-specific ioctls.
</para>
<sect3>
<title>GEM Initialization</title>
<para>
Drivers that use GEM must set the DRIVER_GEM bit in the struct
<structname>drm_driver</structname>
<structfield>driver_features</structfield> field. The DRM core will
then automatically initialize the GEM core before calling the
<methodname>load</methodname> operation. Behind the scene, this will
create a DRM Memory Manager object which provides an address space
pool for object allocation.
</para>
<para>
In a KMS configuration, drivers need to allocate and initialize a
command ring buffer following core GEM initialization if required by
the hardware. UMA devices usually have what is called a "stolen"
memory region, which provides space for the initial framebuffer and
large, contiguous memory regions required by the device. This space is
typically not managed by GEM, and must be initialized separately into
its own DRM MM object.
</para>
</sect3>
<sect3>
<title>GEM Objects Creation</title>
<para>
GEM splits creation of GEM objects and allocation of the memory that
backs them in two distinct operations.
</para>
<para>
GEM objects are represented by an instance of struct
<structname>drm_gem_object</structname>. Drivers usually need to extend
GEM objects with private information and thus create a driver-specific
GEM object structure type that embeds an instance of struct
<structname>drm_gem_object</structname>.
</para>
<para>
To create a GEM object, a driver allocates memory for an instance of its
specific GEM object type and initializes the embedded struct
<structname>drm_gem_object</structname> with a call to
<function>drm_gem_object_init</function>. The function takes a pointer to
the DRM device, a pointer to the GEM object and the buffer object size
in bytes.
</para>
<para>
GEM uses shmem to allocate anonymous pageable memory.
<function>drm_gem_object_init</function> will create an shmfs file of
the requested size and store it into the struct
<structname>drm_gem_object</structname> <structfield>filp</structfield>
field. The memory is used as either main storage for the object when the
graphics hardware uses system memory directly or as a backing store
otherwise.
</para>
<para>
Drivers are responsible for the actual physical pages allocation by
calling <function>shmem_read_mapping_page_gfp</function> for each page.
Note that they can decide to allocate pages when initializing the GEM
object, or to delay allocation until the memory is needed (for instance
when a page fault occurs as a result of a userspace memory access or
when the driver needs to start a DMA transfer involving the memory).
</para>
<para>
Anonymous pageable memory allocation is not always desired, for instance
when the hardware requires physically contiguous system memory as is
often the case in embedded devices. Drivers can create GEM objects with
no shmfs backing (called private GEM objects) by initializing them with
a call to <function>drm_gem_private_object_init</function> instead of
<function>drm_gem_object_init</function>. Storage for private GEM
objects must be managed by drivers.
</para>
<para>
Drivers that do not need to extend GEM objects with private information
can call the <function>drm_gem_object_alloc</function> function to
allocate and initialize a struct <structname>drm_gem_object</structname>
instance. The GEM core will call the optional driver
<methodname>gem_init_object</methodname> operation after initializing
the GEM object with <function>drm_gem_object_init</function>.
<synopsis>int (*gem_init_object) (struct drm_gem_object *obj);</synopsis>
</para>
<para>
No alloc-and-init function exists for private GEM objects.
</para>
</sect3>
<sect3>
<title>GEM Objects Lifetime</title>
<para>
All GEM objects are reference-counted by the GEM core. References can be
acquired and release by <function>calling drm_gem_object_reference</function>
and <function>drm_gem_object_unreference</function> respectively. The
caller must hold the <structname>drm_device</structname>
<structfield>struct_mutex</structfield> lock. As a convenience, GEM
provides the <function>drm_gem_object_reference_unlocked</function> and
<function>drm_gem_object_unreference_unlocked</function> functions that
can be called without holding the lock.
</para>
<para>
When the last reference to a GEM object is released the GEM core calls
the <structname>drm_driver</structname>
<methodname>gem_free_object</methodname> operation. That operation is
mandatory for GEM-enabled drivers and must free the GEM object and all
associated resources.
</para>
<para>
<synopsis>void (*gem_free_object) (struct drm_gem_object *obj);</synopsis>
Drivers are responsible for freeing all GEM object resources, including
the resources created by the GEM core. If an mmap offset has been
created for the object (in which case
<structname>drm_gem_object</structname>::<structfield>map_list</structfield>::<structfield>map</structfield>
is not NULL) it must be freed by a call to
<function>drm_gem_free_mmap_offset</function>. The shmfs backing store
must be released by calling <function>drm_gem_object_release</function>
(that function can safely be called if no shmfs backing store has been
created).
</para>
</sect3>
<sect3>
<title>GEM Objects Naming</title>
<para>
Communication between userspace and the kernel refers to GEM objects
using local handles, global names or, more recently, file descriptors.
All of those are 32-bit integer values; the usual Linux kernel limits
apply to the file descriptors.
</para>
<para>
GEM handles are local to a DRM file. Applications get a handle to a GEM
object through a driver-specific ioctl, and can use that handle to refer
to the GEM object in other standard or driver-specific ioctls. Closing a
DRM file handle frees all its GEM handles and dereferences the
associated GEM objects.
</para>
<para>
To create a handle for a GEM object drivers call
<function>drm_gem_handle_create</function>. The function takes a pointer
to the DRM file and the GEM object and returns a locally unique handle.
When the handle is no longer needed drivers delete it with a call to
<function>drm_gem_handle_delete</function>. Finally the GEM object
associated with a handle can be retrieved by a call to
<function>drm_gem_object_lookup</function>.
</para>
<para>
Handles don't take ownership of GEM objects, they only take a reference
to the object that will be dropped when the handle is destroyed. To
avoid leaking GEM objects, drivers must make sure they drop the
reference(s) they own (such as the initial reference taken at object
creation time) as appropriate, without any special consideration for the
handle. For example, in the particular case of combined GEM object and
handle creation in the implementation of the
<methodname>dumb_create</methodname> operation, drivers must drop the
initial reference to the GEM object before returning the handle.
</para>
<para>
GEM names are similar in purpose to handles but are not local to DRM
files. They can be passed between processes to reference a GEM object
globally. Names can't be used directly to refer to objects in the DRM
API, applications must convert handles to names and names to handles
using the DRM_IOCTL_GEM_FLINK and DRM_IOCTL_GEM_OPEN ioctls
respectively. The conversion is handled by the DRM core without any
driver-specific support.
</para>
<para>
GEM also supports buffer sharing with dma-buf file descriptors through
PRIME. GEM-based drivers must use the provided helpers functions to
implement the exporting and importing correctly. See <xref linkend="drm-prime-support" />.
Since sharing file descriptors is inherently more secure than the
easily guessable and global GEM names it is the preferred buffer
sharing mechanism. Sharing buffers through GEM names is only supported
for legacy userspace. Furthermore PRIME also allows cross-device
buffer sharing since it is based on dma-bufs.
</para>
</sect3>
<sect3 id="drm-gem-objects-mapping">
<title>GEM Objects Mapping</title>
<para>
Because mapping operations are fairly heavyweight GEM favours
read/write-like access to buffers, implemented through driver-specific
ioctls, over mapping buffers to userspace. However, when random access
to the buffer is needed (to perform software rendering for instance),
direct access to the object can be more efficient.
</para>
<para>
The mmap system call can't be used directly to map GEM objects, as they
don't have their own file handle. Two alternative methods currently
co-exist to map GEM objects to userspace. The first method uses a
driver-specific ioctl to perform the mapping operation, calling
<function>do_mmap</function> under the hood. This is often considered
dubious, seems to be discouraged for new GEM-enabled drivers, and will
thus not be described here.
</para>
<para>
The second method uses the mmap system call on the DRM file handle.
<synopsis>void *mmap(void *addr, size_t length, int prot, int flags, int fd,
off_t offset);</synopsis>
DRM identifies the GEM object to be mapped by a fake offset passed
through the mmap offset argument. Prior to being mapped, a GEM object
must thus be associated with a fake offset. To do so, drivers must call
<function>drm_gem_create_mmap_offset</function> on the object. The
function allocates a fake offset range from a pool and stores the
offset divided by PAGE_SIZE in
<literal>obj->map_list.hash.key</literal>. Care must be taken not to
call <function>drm_gem_create_mmap_offset</function> if a fake offset
has already been allocated for the object. This can be tested by
<literal>obj->map_list.map</literal> being non-NULL.
</para>
<para>
Once allocated, the fake offset value
(<literal>obj->map_list.hash.key << PAGE_SHIFT</literal>)
must be passed to the application in a driver-specific way and can then
be used as the mmap offset argument.
</para>
<para>
The GEM core provides a helper method <function>drm_gem_mmap</function>
to handle object mapping. The method can be set directly as the mmap
file operation handler. It will look up the GEM object based on the
offset value and set the VMA operations to the
<structname>drm_driver</structname> <structfield>gem_vm_ops</structfield>
field. Note that <function>drm_gem_mmap</function> doesn't map memory to
userspace, but relies on the driver-provided fault handler to map pages
individually.
</para>
<para>
To use <function>drm_gem_mmap</function>, drivers must fill the struct
<structname>drm_driver</structname> <structfield>gem_vm_ops</structfield>
field with a pointer to VM operations.
</para>
<para>
<synopsis>struct vm_operations_struct *gem_vm_ops
struct vm_operations_struct {
void (*open)(struct vm_area_struct * area);
void (*close)(struct vm_area_struct * area);
int (*fault)(struct vm_area_struct *vma, struct vm_fault *vmf);
};</synopsis>
</para>
<para>
The <methodname>open</methodname> and <methodname>close</methodname>
operations must update the GEM object reference count. Drivers can use
the <function>drm_gem_vm_open</function> and
<function>drm_gem_vm_close</function> helper functions directly as open
and close handlers.
</para>
<para>
The fault operation handler is responsible for mapping individual pages
to userspace when a page fault occurs. Depending on the memory
allocation scheme, drivers can allocate pages at fault time, or can
decide to allocate memory for the GEM object at the time the object is
created.
</para>
<para>
Drivers that want to map the GEM object upfront instead of handling page
faults can implement their own mmap file operation handler.
</para>
</sect3>
<sect3>
<title>Memory Coherency</title>
<para>
When mapped to the device or used in a command buffer, backing pages
for an object are flushed to memory and marked write combined so as to
be coherent with the GPU. Likewise, if the CPU accesses an object
after the GPU has finished rendering to the object, then the object
must be made coherent with the CPU's view of memory, usually involving
GPU cache flushing of various kinds. This core CPU<->GPU
coherency management is provided by a device-specific ioctl, which
evaluates an object's current domain and performs any necessary
flushing or synchronization to put the object into the desired
coherency domain (note that the object may be busy, i.e. an active
render target; in that case, setting the domain blocks the client and
waits for rendering to complete before performing any necessary
flushing operations).
</para>
</sect3>
<sect3>
<title>Command Execution</title>
<para>
Perhaps the most important GEM function for GPU devices is providing a
command execution interface to clients. Client programs construct
command buffers containing references to previously allocated memory
objects, and then submit them to GEM. At that point, GEM takes care to
bind all the objects into the GTT, execute the buffer, and provide
necessary synchronization between clients accessing the same buffers.
This often involves evicting some objects from the GTT and re-binding
others (a fairly expensive operation), and providing relocation
support which hides fixed GTT offsets from clients. Clients must take
care not to submit command buffers that reference more objects than
can fit in the GTT; otherwise, GEM will reject them and no rendering
will occur. Similarly, if several objects in the buffer require fence
registers to be allocated for correct rendering (e.g. 2D blits on
pre-965 chips), care must be taken not to require more fence registers
than are available to the client. Such resource management should be
abstracted from the client in libdrm.
</para>
</sect3>
<sect3>
<title>GEM Function Reference</title>
!Edrivers/gpu/drm/drm_gem.c
</sect3>
</sect2>
<sect2>
<title>VMA Offset Manager</title>
!Pdrivers/gpu/drm/drm_vma_manager.c vma offset manager
!Edrivers/gpu/drm/drm_vma_manager.c
!Iinclude/drm/drm_vma_manager.h
</sect2>
<sect2 id="drm-prime-support">
<title>PRIME Buffer Sharing</title>
<para>
PRIME is the cross device buffer sharing framework in drm, originally
created for the OPTIMUS range of multi-gpu platforms. To userspace
PRIME buffers are dma-buf based file descriptors.
</para>
<sect3>
<title>Overview and Driver Interface</title>
<para>
Similar to GEM global names, PRIME file descriptors are
also used to share buffer objects across processes. They offer
additional security: as file descriptors must be explicitly sent over
UNIX domain sockets to be shared between applications, they can't be
guessed like the globally unique GEM names.
</para>
<para>
Drivers that support the PRIME
API must set the DRIVER_PRIME bit in the struct
<structname>drm_driver</structname>
<structfield>driver_features</structfield> field, and implement the
<methodname>prime_handle_to_fd</methodname> and
<methodname>prime_fd_to_handle</methodname> operations.
</para>
<para>
<synopsis>int (*prime_handle_to_fd)(struct drm_device *dev,
struct drm_file *file_priv, uint32_t handle,
uint32_t flags, int *prime_fd);
int (*prime_fd_to_handle)(struct drm_device *dev,
struct drm_file *file_priv, int prime_fd,
uint32_t *handle);</synopsis>
Those two operations convert a handle to a PRIME file descriptor and
vice versa. Drivers must use the kernel dma-buf buffer sharing framework
to manage the PRIME file descriptors. Similar to the mode setting
API PRIME is agnostic to the underlying buffer object manager, as
long as handles are 32bit unsigned integers.
</para>
<para>
While non-GEM drivers must implement the operations themselves, GEM
drivers must use the <function>drm_gem_prime_handle_to_fd</function>
and <function>drm_gem_prime_fd_to_handle</function> helper functions.
Those helpers rely on the driver
<methodname>gem_prime_export</methodname> and
<methodname>gem_prime_import</methodname> operations to create a dma-buf
instance from a GEM object (dma-buf exporter role) and to create a GEM
object from a dma-buf instance (dma-buf importer role).
</para>
<para>
<synopsis>struct dma_buf * (*gem_prime_export)(struct drm_device *dev,
struct drm_gem_object *obj,
int flags);
struct drm_gem_object * (*gem_prime_import)(struct drm_device *dev,
struct dma_buf *dma_buf);</synopsis>
These two operations are mandatory for GEM drivers that support
PRIME.
</para>
</sect3>
<sect3>
<title>PRIME Helper Functions</title>
!Pdrivers/gpu/drm/drm_prime.c PRIME Helpers
</sect3>
</sect2>
<sect2>
<title>PRIME Function References</title>
!Edrivers/gpu/drm/drm_prime.c
</sect2>
<sect2>
<title>DRM MM Range Allocator</title>
<sect3>
<title>Overview</title>
!Pdrivers/gpu/drm/drm_mm.c Overview
</sect3>
<sect3>
<title>LRU Scan/Eviction Support</title>
!Pdrivers/gpu/drm/drm_mm.c lru scan roaster
</sect3>
</sect2>
<sect2>
<title>DRM MM Range Allocator Function References</title>
!Edrivers/gpu/drm/drm_mm.c
!Iinclude/drm/drm_mm.h
</sect2>
<sect2>
<title>CMA Helper Functions Reference</title>
!Pdrivers/gpu/drm/drm_gem_cma_helper.c cma helpers
!Edrivers/gpu/drm/drm_gem_cma_helper.c
!Iinclude/drm/drm_gem_cma_helper.h
</sect2>
</sect1>
<!-- Internals: mode setting -->
<sect1 id="drm-mode-setting">
<title>Mode Setting</title>
<para>
Drivers must initialize the mode setting core by calling
<function>drm_mode_config_init</function> on the DRM device. The function
initializes the <structname>drm_device</structname>
<structfield>mode_config</structfield> field and never fails. Once done,
mode configuration must be setup by initializing the following fields.
</para>
<itemizedlist>
<listitem>
<synopsis>int min_width, min_height;
int max_width, max_height;</synopsis>
<para>
Minimum and maximum width and height of the frame buffers in pixel
units.
</para>