← Documents Documentation/core-api/real-time/architecture-porting.rst GitHub 원문 ↗

Linux 6.18.37 · Core API

Porting an architecture to support PREEMPT_RT

PREEMPT_RT architecture port에 필요한 threaded interrupt, preemption, timer, IRQ stack, FPU/SIMD, exception 처리와 권장 기능을 설명합니다.

Source pathDocumentation/core-api/real-time/architecture-porting.rst
Source versionLinux v6.18.37
TranslationDUJINLABS 전문 번역 + 해설

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

1. 요약·해설

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

요약과 해설

architecture-porting.rst:1-109

`ARCH_SUPPORTS_RT`를 제공하려는 architecture는 forced threaded interrupt와 즉시 preemption을 지원하고, POSIX timer와 KVM pending work를 thread context에서 안전하게 처리해야 합니다.

Softirq stack, kernel FPU/SIMD 구간, exception handler는 일반 kernel과 다른 PREEMPT_RT 실행 문맥 및 sleep 가능성을 고려해야 합니다. 특히 `kernel_fpu_begin()`은 `preempt_disable()`을 사용하고 user-space exception path에서는 interrupt를 일찍 활성화해야 합니다.

High-resolution timer, lazy preemption, NBCON console은 필수는 아니지만 latency와 crash-time 진단 품질을 높입니다. NBCON driver는 atomic output과 thread output을 모두 지원하는 callback을 구현해야 합니다.

2. 영어 원문 전체

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

원문 전체 펼치기
1 .. SPDX-License-Identifier: GPL-2.0
2
3 =============================================
4 Porting an architecture to support PREEMPT_RT
5 =============================================
6
7 :Author: Sebastian Andrzej Siewior <bigeasy@linutronix.de>
8
9 This list outlines the architecture specific requirements that must be
10 implemented in order to enable PREEMPT_RT. Once all required features are
11 implemented, ARCH_SUPPORTS_RT can be selected in architecture’s Kconfig to make
12 PREEMPT_RT selectable.
13 Many prerequisites (genirq support for example) are enforced by the common code
14 and are omitted here.
15
16 The optional features are not strictly required but it is worth to consider
17 them.
18
19 Requirements
20 ------------
21
22 Forced threaded interrupts
23 CONFIG_IRQ_FORCED_THREADING must be selected. Any interrupts that must
24 remain in hard-IRQ context must be marked with IRQF_NO_THREAD. This
25 requirement applies for instance to clocksource event interrupts,
26 perf interrupts and cascading interrupt-controller handlers.
27
28 PREEMPTION support
29 Kernel preemption must be supported and requires that
30 CONFIG_ARCH_NO_PREEMPT remain unselected. Scheduling requests, such as those
31 issued from an interrupt or other exception handler, must be processed
32 immediately.
33
34 POSIX CPU timers and KVM
35 POSIX CPU timers must expire from thread context rather than directly within
36 the timer interrupt. This behavior is enabled by setting the configuration
37 option CONFIG_HAVE_POSIX_CPU_TIMERS_TASK_WORK.
38 When KVM is enabled, CONFIG_KVM_XFER_TO_GUEST_WORK must also be set to ensure
39 that any pending work, such as POSIX timer expiration, is handled before
40 transitioning into guest mode.
41
42 Hard-IRQ and Soft-IRQ stacks
43 Soft interrupts are handled in the thread context in which they are raised. If
44 a soft interrupt is triggered from hard-IRQ context, its execution is deferred
45 to the ksoftirqd thread. Preemption is never disabled during soft interrupt
46 handling, which makes soft interrupts preemptible.
47 If an architecture provides a custom __do_softirq() implementation that uses a
48 separate stack, it must select CONFIG_HAVE_SOFTIRQ_ON_OWN_STACK. The
49 functionality should only be enabled when CONFIG_SOFTIRQ_ON_OWN_STACK is set.
50
51 FPU and SIMD access in kernel mode
52 FPU and SIMD registers are typically not used in kernel mode and are therefore
53 not saved during kernel preemption. As a result, any kernel code that uses
54 these registers must be enclosed within a kernel_fpu_begin() and
55 kernel_fpu_end() section.
56 The kernel_fpu_begin() function usually invokes local_bh_disable() to prevent
57 interruptions from softirqs and to disable regular preemption. This allows the
58 protected code to run safely in both thread and softirq contexts.
59 On PREEMPT_RT kernels, however, kernel_fpu_begin() must not call
60 local_bh_disable(). Instead, it should use preempt_disable(), since softirqs
61 are always handled in thread context under PREEMPT_RT. In this case, disabling
62 preemption alone is sufficient.
63 The crypto subsystem operates on memory pages and requires users to "walk and
64 map" these pages while processing a request. This operation must occur outside
65 the kernel_fpu_begin()/ kernel_fpu_end() section because it requires preemption
66 to be enabled. These preemption points are generally sufficient to avoid
67 excessive scheduling latency.
68
69 Exception handlers
70 Exception handlers, such as the page fault handler, typically enable interrupts
71 early, before invoking any generic code to process the exception. This is
72 necessary because handling a page fault may involve operations that can sleep.
73 Enabling interrupts is especially important on PREEMPT_RT, where certain
74 locks, such as spinlock_t, become sleepable. For example, handling an
75 invalid opcode may result in sending a SIGILL signal to the user task. A
76 debug excpetion will send a SIGTRAP signal.
77 In both cases, if the exception occurred in user space, it is safe to enable
78 interrupts early. Sending a signal requires both interrupts and kernel
79 preemption to be enabled.
80
81 Optional features
82 -----------------
83
84 Timer and clocksource
85 A high-resolution clocksource and clockevents device are recommended. The
86 clockevents device should support the CLOCK_EVT_FEAT_ONESHOT feature for
87 optimal timer behavior. In most cases, microsecond-level accuracy is
88 sufficient
89
90 Lazy preemption
91 This mechanism allows an in-kernel scheduling request for non-real-time tasks
92 to be delayed until the task is about to return to user space. It helps avoid
93 preempting a task that holds a sleeping lock at the time of the scheduling
94 request.
95 With CONFIG_GENERIC_IRQ_ENTRY enabled, supporting this feature requires
96 defining a bit for TIF_NEED_RESCHED_LAZY, preferably near TIF_NEED_RESCHED.
97
98 Serial console with NBCON
99 With PREEMPT_RT enabled, all console output is handled by a dedicated thread
100 rather than directly from the context in which printk() is invoked. This design
101 allows printk() to be safely used in atomic contexts.
102 However, this also means that if the kernel crashes and cannot switch to the
103 printing thread, no output will be visible preventing the system from printing
104 its final messages.
105 There are exceptions for immediate output, such as during panic() handling. To
106 support this, the console driver must implement new-style lock handling. This
107 involves setting the CON_NBCON flag in console::flags and providing
108 implementations for the write_atomic, write_thread, device_lock, and
109 device_unlock callbacks.
110

3. 한국어 전문 번역

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

PREEMPT_RT architecture porting 개요

1-18

SPDX 라이선스 식별자는 GPL-2.0입니다.

PREEMPT_RT를 지원하도록 architecture porting하기

저자: Sebastian Andrzej Siewior <bigeasy@linutronix.de>

이 목록은 `PREEMPT_RT`를 활성화하기 위해 구현해야 하는 architecture별 요구 사항을 정리합니다. 모든 필수 기능을 구현한 뒤 architecture의 Kconfig에서 `ARCH_SUPPORTS_RT`를 선택하면 `PREEMPT_RT`를 선택 가능하게 만들 수 있습니다.

`genirq` 지원과 같은 많은 선행 조건은 common code가 강제하므로 여기서는 생략합니다.

선택 기능은 엄격한 필수 조건은 아니지만 함께 검토할 가치가 있습니다.

Threaded interrupt, preemption, POSIX timer와 KVM

19-40

요구 사항

강제 threaded interrupt

`CONFIG_IRQ_FORCED_THREADING`을 선택해야 합니다. Hard-IRQ context에 남아야 하는 interrupt에는 `IRQF_NO_THREAD`를 표시해야 합니다. 예를 들면 clocksource event interrupt, perf interrupt, cascading interrupt-controller handler가 이 요구 사항에 해당합니다.

PREEMPTION 지원

Kernel preemption을 지원해야 하며 `CONFIG_ARCH_NO_PREEMPT`는 선택하지 않은 상태여야 합니다. Interrupt 또는 다른 exception handler에서 발생한 요청을 포함한 scheduling request를 즉시 처리해야 합니다.

POSIX CPU timer와 KVM

POSIX CPU timer는 timer interrupt 안에서 직접 만료시키지 않고 thread context에서 만료시켜야 합니다. Configuration option `CONFIG_HAVE_POSIX_CPU_TIMERS_TASK_WORK`를 설정하면 이 동작을 활성화할 수 있습니다.

KVM을 활성화한 경우에는 `CONFIG_KVM_XFER_TO_GUEST_WORK`도 설정해야 합니다. 그래야 POSIX timer 만료 같은 pending work를 guest mode로 전환하기 전에 처리할 수 있습니다.

Hard-IRQ와 Soft-IRQ stack

41-50

Hard-IRQ와 Soft-IRQ stack

Soft interrupt는 자신을 발생시킨 thread context에서 처리합니다. Hard-IRQ context에서 soft interrupt가 발생하면 실행을 `ksoftirqd` thread로 미룹니다. Soft interrupt를 처리하는 동안에는 preemption을 끄지 않으므로 soft interrupt를 preempt할 수 있습니다.

Architecture가 별도 stack을 사용하는 custom `__do_softirq()` 구현을 제공한다면 `CONFIG_HAVE_SOFTIRQ_ON_OWN_STACK`을 선택해야 합니다. 이 기능은 `CONFIG_SOFTIRQ_ON_OWN_STACK`이 설정된 경우에만 활성화해야 합니다.

Kernel mode의 FPU와 SIMD 접근

51-68

Kernel mode의 FPU와 SIMD 접근

FPU와 SIMD register는 보통 kernel mode에서 사용하지 않으므로 kernel preemption 때 저장하지 않습니다. 따라서 이 register를 사용하는 kernel code는 `kernel_fpu_begin()`과 `kernel_fpu_end()` 구간으로 감싸야 합니다.

일반적으로 `kernel_fpu_begin()`은 softirq의 간섭과 보통 preemption을 막기 위해 `local_bh_disable()`을 호출합니다. 그러면 보호된 code를 thread context와 softirq context 양쪽에서 안전하게 실행할 수 있습니다.

그러나 `PREEMPT_RT` kernel의 `kernel_fpu_begin()`은 `local_bh_disable()`을 호출하면 안 됩니다. `PREEMPT_RT`에서는 softirq를 항상 thread context에서 처리하므로 대신 `preempt_disable()`을 사용해야 하며, preemption만 비활성화해도 충분합니다.

Crypto subsystem은 memory page를 다루며 request를 처리하는 동안 사용자가 이 page를 "walk and map"하도록 요구합니다. 이 작업은 preemption이 활성화되어야 하므로 `kernel_fpu_begin()`과 `kernel_fpu_end()` 구간 밖에서 수행해야 합니다. 이러한 preemption point는 일반적으로 과도한 scheduling latency를 피하는 데 충분합니다.

Exception handler

69-80

Exception handler

Page fault handler 같은 exception handler는 보통 exception을 처리하는 generic code를 호출하기 전에 interrupt를 일찍 활성화합니다. Page fault 처리에는 sleep할 수 있는 작업이 포함될 수 있으므로 이것이 필요합니다.

`PREEMPT_RT`에서는 `spinlock_t` 같은 일부 lock이 sleep 가능해지므로 interrupt를 활성화하는 일이 특히 중요합니다. 예를 들어 invalid opcode를 처리하면 user task에 `SIGILL` signal을 보낼 수 있고, debug exception은 `SIGTRAP` signal을 보냅니다.

두 경우 모두 exception이 user space에서 발생했다면 interrupt를 일찍 활성화해도 안전합니다. Signal 전송에는 interrupt와 kernel preemption이 모두 활성화되어 있어야 합니다.

Timer, clocksource와 lazy preemption

81-97

선택 기능

Timer와 clocksource

High-resolution clocksource와 clockevents device를 권장합니다. 최적의 timer 동작을 위해 clockevents device는 `CLOCK_EVT_FEAT_ONESHOT` 기능을 지원해야 합니다. 대부분은 microsecond 수준의 정확도로 충분합니다.

Lazy preemption

이 메커니즘은 non-real-time task에 대한 in-kernel scheduling request를 task가 user space로 돌아가려는 시점까지 지연할 수 있게 합니다. Scheduling request가 발생한 순간 sleep 가능한 lock을 보유한 task가 preempt되는 것을 피하는 데 도움이 됩니다.

`CONFIG_GENERIC_IRQ_ENTRY`를 활성화한 상태에서 이 기능을 지원하려면 `TIF_NEED_RESCHED_LAZY` bit를 정의해야 하며, 가능하면 `TIF_NEED_RESCHED` 가까이에 두는 것이 좋습니다.

NBCON을 사용하는 serial console

98-109

NBCON을 사용하는 serial console

`PREEMPT_RT`를 활성화하면 모든 console output은 `printk()`를 호출한 context에서 직접 처리하지 않고 전용 thread가 처리합니다. 이 설계 덕분에 atomic context에서도 `printk()`를 안전하게 사용할 수 있습니다.

하지만 kernel이 crash하여 printing thread로 전환할 수 없다면 output이 전혀 보이지 않아 system이 마지막 message를 출력하지 못할 수도 있습니다.

`panic()` 처리 중과 같이 즉시 출력하는 예외가 있습니다. 이를 지원하려면 console driver가 새로운 방식의 lock 처리를 구현해야 합니다. 구체적으로 `console::flags`에 `CON_NBCON` flag를 설정하고 `write_atomic`, `write_thread`, `device_lock`, `device_unlock` callback을 구현해야 합니다.