← Documents Documentation/devicetree/overlay-notes.rst GitHub 원문 ↗

Linux 6.18.37 · Devicetree

Devicetree Overlay Notes

Device Tree overlay가 live tree와 장치 상태를 변경하는 방식, label·path 대상 문법, 적용·제거 API와 notifier pointer 수명 규칙을 설명합니다.

Source pathDocumentation/devicetree/overlay-notes.rst
Source versionLinux v6.18.37
TranslationDUJINLABS 전문 번역 + 해설

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

1. 요약·해설

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

요약과 해설

overlay-notes.rst:1-150

Device Tree overlay가 live tree와 장치 상태를 변경하는 방식, label·path 대상 문법, 적용·제거 API와 notifier pointer 수명 규칙을 설명합니다. 영어 원문 전체와 한국어 전문 번역을 함께 제공하며 함수명, symbol, source path, DTS 예제와 원문 줄 좌표를 보존합니다.

2. 영어 원문 전체

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

원문 전체 펼치기
1 .. SPDX-License-Identifier: GPL-2.0
2
3 ========================
4 Devicetree Overlay Notes
5 ========================
6
7 This document describes the implementation of the in-kernel
8 device tree overlay functionality residing in drivers/of/overlay.c and is a
9 companion document to Documentation/devicetree/dynamic-resolution-notes.rst[1]
10
11 How overlays work
12 -----------------
13
14 A Devicetree's overlay purpose is to modify the kernel's live tree, and
15 have the modification affecting the state of the kernel in a way that
16 is reflecting the changes.
17 Since the kernel mainly deals with devices, any new device node that results
18 in an active device should have it created while if the device node is either
19 disabled or removed all together, the affected device should be deregistered.
20
21 Let's take an example where we have a foo board with the following base tree::
22
23 ---- foo.dts ---------------------------------------------------------------
24 /* FOO platform */
25 /dts-v1/;
26 / {
27 compatible = "corp,foo";
28
29 /* shared resources */
30 res: res {
31 };
32
33 /* On chip peripherals */
34 ocp: ocp {
35 /* peripherals that are always instantiated */
36 peripheral1 { ... };
37 };
38 };
39 ---- foo.dts ---------------------------------------------------------------
40
41 The overlay bar.dtso,
42 ::
43
44 ---- bar.dtso - overlay target location by label ---------------------------
45 /dts-v1/;
46 /plugin/;
47 &ocp {
48 /* bar peripheral */
49 bar {
50 compatible = "corp,bar";
51 ... /* various properties and child nodes */
52 };
53 };
54 ---- bar.dtso --------------------------------------------------------------
55
56 when loaded (and resolved as described in [1]) should result in foo+bar.dts::
57
58 ---- foo+bar.dts -----------------------------------------------------------
59 /* FOO platform + bar peripheral */
60 / {
61 compatible = "corp,foo";
62
63 /* shared resources */
64 res: res {
65 };
66
67 /* On chip peripherals */
68 ocp: ocp {
69 /* peripherals that are always instantiated */
70 peripheral1 { ... };
71
72 /* bar peripheral */
73 bar {
74 compatible = "corp,bar";
75 ... /* various properties and child nodes */
76 };
77 };
78 };
79 ---- foo+bar.dts -----------------------------------------------------------
80
81 As a result of the overlay, a new device node (bar) has been created
82 so a bar platform device will be registered and if a matching device driver
83 is loaded the device will be created as expected.
84
85 If the base DT was not compiled with the -@ option then the "&ocp" label
86 will not be available to resolve the overlay node(s) to the proper location
87 in the base DT. In this case, the target path can be provided. The target
88 location by label syntax is preferred because the overlay can be applied to
89 any base DT containing the label, no matter where the label occurs in the DT.
90
91 The above bar.dtso example modified to use target path syntax is::
92
93 ---- bar.dtso - overlay target location by explicit path -------------------
94 /dts-v1/;
95 /plugin/;
96 &{/ocp} {
97 /* bar peripheral */
98 bar {
99 compatible = "corp,bar";
100 ... /* various properties and child nodes */
101 }
102 };
103 ---- bar.dtso --------------------------------------------------------------
104
105
106 Overlay in-kernel API
107 --------------------------------
108
109 The API is quite easy to use.
110
111 1) Call of_overlay_fdt_apply() to create and apply an overlay changeset. The
112 return value is an error or a cookie identifying this overlay.
113
114 2) Call of_overlay_remove() to remove and clean up the overlay changeset
115 previously created via the call to of_overlay_fdt_apply(). Removal of an
116 overlay changeset that is stacked by another will not be permitted.
117
118 Finally, if you need to remove all overlays in one-go, just call
119 of_overlay_remove_all() which will remove every single one in the correct
120 order.
121
122 There is the option to register notifiers that get called on
123 overlay operations. See of_overlay_notifier_register/unregister and
124 enum of_overlay_notify_action for details.
125
126 A notifier callback for OF_OVERLAY_PRE_APPLY, OF_OVERLAY_POST_APPLY, or
127 OF_OVERLAY_PRE_REMOVE may store pointers to a device tree node in the overlay
128 or its content but these pointers must not persist past the notifier callback
129 for OF_OVERLAY_POST_REMOVE. The memory containing the overlay will be
130 kfree()ed after OF_OVERLAY_POST_REMOVE notifiers are called. Note that the
131 memory will be kfree()ed even if the notifier for OF_OVERLAY_POST_REMOVE
132 returns an error.
133
134 The changeset notifiers in drivers/of/dynamic.c are a second type of notifier
135 that could be triggered by applying or removing an overlay. These notifiers
136 are not allowed to store pointers to a device tree node in the overlay
137 or its content. The overlay code does not protect against such pointers
138 remaining active when the memory containing the overlay is freed as a result
139 of removing the overlay.
140
141 Any other code that retains a pointer to the overlay nodes or data is
142 considered to be a bug because after removing the overlay the pointer
143 will refer to freed memory.
144
145 Users of overlays must be especially aware of the overall operations that
146 occur on the system to ensure that other kernel code does not retain any
147 pointers to the overlay nodes or data. Any example of an inadvertent use
148 of such pointers is if a driver or subsystem module is loaded after an
149 overlay has been applied, and the driver or subsystem scans the entire
150 devicetree or a large portion of it, including the overlay nodes.
151

3. 한국어 전문 번역

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

Devicetree Overlay Notes

1-10

이 문서는 `drivers/of/overlay.c`에 구현된 커널 내부 Device Tree overlay 기능을 설명합니다. `Documentation/devicetree/dynamic-resolution-notes.rst`[1]의 동반 문서이며 `GPL-2.0` 라이선스가 적용됩니다.

overlay가 live tree와 장치 상태를 바꾸는 방법

11-20

Devicetree overlay의 목적은 커널의 live tree를 수정하고 그 변경 사항이 커널 상태에도 반영되게 하는 것입니다.

커널은 주로 장치를 다루므로, 새 장치 노드가 활성 장치를 만들면 해당 장치를 생성해야 합니다. 반대로 장치 노드가 비활성화되거나 완전히 제거되면 영향을 받는 장치의 등록을 해제해야 합니다.

foo 보드의 기본 트리

21-40

예제의 `foo` 보드는 `corp,foo` 호환 루트, 공유 자원 `res`, on-chip peripheral 버스 `ocp`와 항상 인스턴스화되는 `peripheral1`을 가진 다음 기본 트리를 사용합니다.

---- foo.dts ---------------------------------------------------------------
    /* FOO platform */
    /dts-v1/;
    / {
            compatible = "corp,foo";

            /* shared resources */
            res: res {
            };

            /* On chip peripherals */
            ocp: ocp {
                    /* peripherals that are always instantiated */
                    peripheral1 { ... };
            };
    };
---- foo.dts ---------------------------------------------------------------

label을 대상으로 하는 bar.dtso

41-55

`bar.dtso` overlay는 `/plugin/`을 선언하고 `&ocp` label을 대상으로 `corp,bar` 호환 장치 노드와 그 속성·자식 노드를 추가합니다.

---- bar.dtso - overlay target location by label ---------------------------
    /dts-v1/;
    /plugin/;
    &ocp {
            /* bar peripheral */
            bar {
                    compatible = "corp,bar";
                    ... /* various properties and child nodes */
            };
    };
---- bar.dtso --------------------------------------------------------------

overlay 해석 후의 foo+bar 트리

56-84

[1]에서 설명한 방식으로 overlay를 해석해 불러오면 `bar` 노드가 기존 `ocp` 아래에 들어간 다음 `foo+bar.dts` 트리가 됩니다.

---- foo+bar.dts -----------------------------------------------------------
    /* FOO platform + bar peripheral */
    / {
            compatible = "corp,foo";

            /* shared resources */
            res: res {
            };

            /* On chip peripherals */
            ocp: ocp {
                    /* peripherals that are always instantiated */
                    peripheral1 { ... };

                    /* bar peripheral */
                    bar {
                            compatible = "corp,bar";
                            ... /* various properties and child nodes */
                    };
            };
    };
---- foo+bar.dts -----------------------------------------------------------

overlay 결과로 새 장치 노드 `bar`가 만들어지므로 `bar` platform device가 등록됩니다. 일치하는 장치 드라이버가 로드되어 있으면 예상대로 장치도 생성됩니다.

label 대신 explicit target path 사용

85-104

기본 DT를 `-@` 옵션 없이 컴파일했다면 `&ocp` label을 사용할 수 없어 overlay 노드를 기본 DT의 올바른 위치로 해석할 수 없습니다. 이 경우 target path를 직접 지정할 수 있습니다.

label 대상 문법이 권장됩니다. label이 DT 안의 어디에 있든 그 label을 포함하는 모든 기본 DT에 overlay를 적용할 수 있기 때문입니다. 위 `bar.dtso`를 explicit path 문법으로 바꾸면 `&{/ocp}`를 사용합니다.

---- bar.dtso - overlay target location by explicit path -------------------
    /dts-v1/;
    /plugin/;
    &{/ocp} {
            /* bar peripheral */
            bar {
                    compatible = "corp,bar";
                    ... /* various properties and child nodes */
            }
    };
---- bar.dtso --------------------------------------------------------------

커널 내부 overlay API

105-121

커널 내부 overlay API의 사용 순서는 단순합니다.

  • 1. `of_overlay_fdt_apply()`를 호출하여 overlay changeset을 만들고 적용합니다. 반환값은 오류이거나 이 overlay를 식별하는 cookie입니다.
  • 2. `of_overlay_fdt_apply()`로 만든 overlay changeset을 제거하고 정리하려면 `of_overlay_remove()`를 호출합니다. 다른 overlay가 그 위에 쌓여 있는 changeset은 제거할 수 없습니다.

모든 overlay를 한 번에 제거하려면 `of_overlay_remove_all()`을 호출합니다. 이 함수는 각각의 overlay를 올바른 순서로 제거합니다.

overlay notifier와 pointer 유효 기간

122-133

overlay 작업 때 호출되는 notifier를 등록할 수 있습니다. 자세한 내용은 `of_overlay_notifier_register/unregister`와 `enum of_overlay_notify_action`을 참조합니다.

`OF_OVERLAY_PRE_APPLY`, `OF_OVERLAY_POST_APPLY`, `OF_OVERLAY_PRE_REMOVE`의 notifier callback은 overlay의 Device Tree 노드나 그 내용에 대한 pointer를 저장할 수 있습니다. 하지만 이 pointer는 `OF_OVERLAY_POST_REMOVE` notifier callback이 끝난 뒤까지 남아 있어서는 안 됩니다.

overlay가 들어 있는 메모리는 `OF_OVERLAY_POST_REMOVE` notifier를 호출한 뒤 `kfree()`됩니다. `OF_OVERLAY_POST_REMOVE` notifier가 오류를 반환하더라도 메모리는 `kfree()`됩니다.

changeset notifier의 pointer 저장 금지

134-143

`drivers/of/dynamic.c`의 changeset notifier는 overlay를 적용하거나 제거할 때 발생할 수 있는 두 번째 notifier 유형입니다. 이 notifier는 overlay의 Device Tree 노드나 그 내용에 대한 pointer를 저장할 수 없습니다.

overlay 코드는 overlay 제거로 메모리가 해제될 때 그런 pointer가 계속 활성 상태로 남는 일을 방지하지 않습니다. overlay 노드나 데이터에 대한 pointer를 보관하는 다른 코드는 overlay 제거 후 해제된 메모리를 가리키게 되므로 버그로 간주합니다.

다른 커널 코드의 간접 pointer 보관 주의

144-150

overlay 사용자는 다른 커널 코드가 overlay 노드나 데이터의 pointer를 보관하지 않는지 확인할 수 있도록 시스템 전체에서 수행되는 작업을 특히 주의해야 합니다.

의도하지 않은 pointer 사용의 예로는 overlay를 적용한 뒤 드라이버나 subsystem 모듈을 로드하고, 그 드라이버나 subsystem이 overlay 노드를 포함한 전체 Devicetree 또는 그 대부분을 검색하는 경우가 있습니다.