요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
.. SPDX-License-Identifier: GPL-2.0
========================
Devicetree Overlay Notes
========================
This document describes the implementation of the in-kernel
device tree overlay functionality residing in drivers/of/overlay.c and is a
companion document to Documentation/devicetree/dynamic-resolution-notes.rst[1]
How overlays work
-----------------
A Devicetree's overlay purpose is to modify the kernel's live tree, and
have the modification affecting the state of the kernel in a way that
is reflecting the changes.
Since the kernel mainly deals with devices, any new device node that results
in an active device should have it created while if the device node is either
disabled or removed all together, the affected device should be deregistered.
Let's take an example where we have a foo board with the following base tree::
---- 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 ---------------------------------------------------------------
The overlay bar.dtso,
::
---- bar.dtso - overlay target location by label ---------------------------
/dts-v1/;
/plugin/;
&ocp {
/* bar peripheral */
bar {
compatible = "corp,bar";
... /* various properties and child nodes */
};
};
---- bar.dtso --------------------------------------------------------------
when loaded (and resolved as described in [1]) should result in 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 -----------------------------------------------------------
As a result of the overlay, a new device node (bar) has been created
so a bar platform device will be registered and if a matching device driver
is loaded the device will be created as expected.
If the base DT was not compiled with the -@ option then the "&ocp" label
will not be available to resolve the overlay node(s) to the proper location
in the base DT. In this case, the target path can be provided. The target
location by label syntax is preferred because the overlay can be applied to
any base DT containing the label, no matter where the label occurs in the DT.
The above bar.dtso example modified to use target path syntax is::
---- 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 in-kernel API
--------------------------------
The API is quite easy to use.
1) Call of_overlay_fdt_apply() to create and apply an overlay changeset. The
return value is an error or a cookie identifying this overlay.
2) Call of_overlay_remove() to remove and clean up the overlay changeset
previously created via the call to of_overlay_fdt_apply(). Removal of an
overlay changeset that is stacked by another will not be permitted.
Finally, if you need to remove all overlays in one-go, just call
of_overlay_remove_all() which will remove every single one in the correct
order.
There is the option to register notifiers that get called on
overlay operations. See of_overlay_notifier_register/unregister and
enum of_overlay_notify_action for details.
A notifier callback for OF_OVERLAY_PRE_APPLY, OF_OVERLAY_POST_APPLY, or
OF_OVERLAY_PRE_REMOVE may store pointers to a device tree node in the overlay
or its content but these pointers must not persist past the notifier callback
for OF_OVERLAY_POST_REMOVE. The memory containing the overlay will be
kfree()ed after OF_OVERLAY_POST_REMOVE notifiers are called. Note that the
memory will be kfree()ed even if the notifier for OF_OVERLAY_POST_REMOVE
returns an error.
The changeset notifiers in drivers/of/dynamic.c are a second type of notifier
that could be triggered by applying or removing an overlay. These notifiers
are not allowed to store pointers to a device tree node in the overlay
or its content. The overlay code does not protect against such pointers
remaining active when the memory containing the overlay is freed as a result
of removing the overlay.
Any other code that retains a pointer to the overlay nodes or data is
considered to be a bug because after removing the overlay the pointer
will refer to freed memory.
Users of overlays must be especially aware of the overall operations that
occur on the system to ensure that other kernel code does not retain any
pointers to the overlay nodes or data. Any example of an inadvertent use
of such pointers is if a driver or subsystem module is loaded after an
overlay has been applied, and the driver or subsystem scans the entire
devicetree or a large portion of it, including the overlay nodes.
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-20Devicetree 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-133overlay 작업 때 호출되는 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-150overlay 사용자는 다른 커널 코드가 overlay 노드나 데이터의 pointer를 보관하지 않는지 확인할 수 있도록 시스템 전체에서 수행되는 작업을 특히 주의해야 합니다.
의도하지 않은 pointer 사용의 예로는 overlay를 적용한 뒤 드라이버나 subsystem 모듈을 로드하고, 그 드라이버나 subsystem이 overlay 노드를 포함한 전체 Devicetree 또는 그 대부분을 검색하는 경우가 있습니다.
요약과 해설
overlay-notes.rst:1-150Device Tree overlay가 live tree와 장치 상태를 변경하는 방식, label·path 대상 문법, 적용·제거 API와 notifier pointer 수명 규칙을 설명합니다. 영어 원문 전체와 한국어 전문 번역을 함께 제공하며 함수명, symbol, source path, DTS 예제와 원문 줄 좌표를 보존합니다.