diff options
Diffstat (limited to 'Documentation/core-api')
24 files changed, 557 insertions, 54 deletions
diff --git a/Documentation/core-api/SMP.rst b/Documentation/core-api/SMP.rst new file mode 100644 index 000000000000..0265a9835f23 --- /dev/null +++ b/Documentation/core-api/SMP.rst @@ -0,0 +1,11 @@ +.. SPDX-License-Identifier: GPL-2.0+ + +============== +SMP primitives +============== + +.. kernel-doc:: include/linux/smp.h + :internal: + +.. kernel-doc:: kernel/smp.c + :export: diff --git a/Documentation/core-api/cpu_hotplug.rst b/Documentation/core-api/cpu_hotplug.rst index 9b4afca9fd09..6de26d1c6a9a 100644 --- a/Documentation/core-api/cpu_hotplug.rst +++ b/Documentation/core-api/cpu_hotplug.rst @@ -45,11 +45,6 @@ Command Line Switches This option is limited to the X86 and S390 architecture. -``cpu0_hotplug`` - Allow to shutdown CPU0. - - This option is limited to the X86 architecture. - CPU maps ======== diff --git a/Documentation/core-api/dma-api.rst b/Documentation/core-api/dma-api.rst index ca75b3541679..ba23a472f794 100644 --- a/Documentation/core-api/dma-api.rst +++ b/Documentation/core-api/dma-api.rst @@ -508,7 +508,7 @@ call to dma_iova_try_alloc. This can be useful in the unmap path. Is used to link ranges to the IOVA previously allocated. The start of all but the first call to dma_iova_link for a given state must be aligned -to the DMA merge boundary returned by ``dma_get_merge_boundary())``, and +to the DMA merge boundary returned by ``dma_get_merge_boundary()``, and the size of all but the last range must be aligned to the DMA merge boundary as well. diff --git a/Documentation/core-api/dma-attributes.rst b/Documentation/core-api/dma-attributes.rst index 123c8468d58f..eee743184acd 100644 --- a/Documentation/core-api/dma-attributes.rst +++ b/Documentation/core-api/dma-attributes.rst @@ -179,3 +179,32 @@ interface when building their uAPIs, when possible. It must never be used in an in-kernel driver that only works with kernel memory. + +DMA_ATTR_CC_SHARED +------------------ + +This attribute indicates that a DMA mapping is shared, or decrypted, for +confidential computing guests. For normal system memory, the caller must +already have marked the memory decrypted with set_memory_decrypted(). CPU +PTEs for the mapping must use pgprot_decrypted(), and the same shared +semantic may be passed to a vIOMMU when it sets up the IOPTE. + +This attribute describes an existing mapping. It does not allocate shared +backing pages and must not be passed to dma_alloc_attrs(). For MMIO, use +this together with DMA_ATTR_MMIO to indicate shared MMIO. Unless +DMA_ATTR_MMIO is provided, the mapping requires a struct page. + +__DMA_ATTR_ALLOC_CC_SHARED +-------------------------- + +This is an internal DMA-mapping attribute for confidential computing guests. +It is used by allocation paths after the DMA core has determined that the +backing pages must be shared, or decrypted. For example, the direct DMA and +SWIOTLB allocation paths use it to select shared DMA pools, decrypt newly +allocated pages, derive DMA addresses using the shared-memory translation, and +restore encryption on free. + +__DMA_ATTR_ALLOC_CC_SHARED differs from DMA_ATTR_CC_SHARED in that it is not +a caller-visible DMA API attribute. DMA_ATTR_CC_SHARED describes an +already-shared mapping and requires the caller to have prepared normal +system memory before mapping it. diff --git a/Documentation/core-api/entry.rst b/Documentation/core-api/entry.rst index 71d8eedc0549..79fdaed954d9 100644 --- a/Documentation/core-api/entry.rst +++ b/Documentation/core-api/entry.rst @@ -58,32 +58,59 @@ state transitions must run with interrupts disabled. Syscalls -------- -Syscall-entry code starts in assembly code and calls out into low-level C code -after establishing low-level architecture-specific state and stack frames. This -low-level C code must not be instrumented. A typical syscall handling function -invoked from low-level assembly code looks like this: +Syscall-entry code starts in assembly code and calls out into low-level C +code after establishing low-level architecture-specific state and stack +frames. This low-level C code must not be instrumented. The recommended +syscall handling function invoked from low-level assembly code looks like +this: .. code-block:: c - noinstr void syscall(struct pt_regs *regs, int nr) + noinstr void syscall(struct pt_regs *regs, long nr) { arch_syscall_enter(regs); - nr = syscall_enter_from_user_mode(regs, nr); + result_reg(regs) = -ENOSYS; + if (syscall_enter_from_user_mode_randomize_stack(regs, &nr)) { + instrumentation_begin(); + if (valid(nr) + result_reg(regs) = invoke_syscall(regs, nr); + instrumentation_end(); + } + syscall_exit_to_user_mode(regs); + } - instrumentation_begin(); - if (!invoke_syscall(regs, nr) && nr != -1) - result_reg(regs) = __sys_ni_syscall(regs); - instrumentation_end(); +This is the most resilent variant as it has always a guaranteed valid +return code. The alternative variant is: +.. code-block:: c + + noinstr void syscall(struct pt_regs *regs, long nr) + { + arch_syscall_enter(regs); + if (syscall_enter_from_user_mode_randomize_stack(regs, &nr)) { + instrumentation_begin(); + if (valid(nr) + result_reg(regs) = invoke_syscall(regs, nr); + else + result_reg(regs) = -ENOSYS; + instrumentation_end(); + } syscall_exit_to_user_mode(regs); } -syscall_enter_from_user_mode() first invokes enter_from_user_mode() which -establishes state in the following order: +That works for most situations except when a probe/BPF attached to the +syscall tracepoint sets an invalid syscall number e.g. -1 and also modifies +the result register. So this variant will obviously overwrite the modified +result with -ENOSYS. + +syscall_enter_from_user_mode_randomize_stack() first invokes +enter_from_user_mode_randomize_stack() which establishes state in the +following order: * Lockdep * RCU / Context tracking * Tracing + * Apply stack randomization and then invokes the various entry work functions like ptrace, seccomp, audit, syscall tracing, etc. After all that is done, the instrumentable invoke_syscall @@ -99,10 +126,11 @@ transition in the reverse order: * RCU / Context tracking * Lockdep -syscall_enter_from_user_mode() and syscall_exit_to_user_mode() are also -available as fine grained subfunctions in cases where the architecture code -has to do extra work between the various steps. In such cases it has to -ensure that enter_from_user_mode() is called first on entry and +syscall_enter_from_user_mode_randomize_stack() and +syscall_exit_to_user_mode() are also available as fine grained subfunctions +in cases where the architecture code has to do extra work between the +various steps. In such cases it has to ensure that +enter_from_user_mode_randomize_stack() is called first on entry and exit_to_user_mode() is called last on exit. Do not nest syscalls. Nested syscalls will cause RCU and/or context tracking diff --git a/Documentation/core-api/errseq.rst b/Documentation/core-api/errseq.rst index ff332e272405..d298d4cd2f60 100644 --- a/Documentation/core-api/errseq.rst +++ b/Documentation/core-api/errseq.rst @@ -143,7 +143,7 @@ Because of this, it's often advantageous to first do an errseq_check to see if anything has changed, and only later do an errseq_check_and_advance after taking the lock. e.g.:: - if (errseq_check(&wd.wd_err, READ_ONCE(su.s_wd_err)) { + if (errseq_check(&wd.wd_err, READ_ONCE(su.s_wd_err))) { /* su.s_wd_err is protected by s_wd_err_lock */ spin_lock(&su.s_wd_err_lock); err = errseq_check_and_advance(&wd.wd_err, &su.s_wd_err); diff --git a/Documentation/core-api/housekeeping.rst b/Documentation/core-api/housekeeping.rst index 92c6e53cea75..ccb0a88b9cb3 100644 --- a/Documentation/core-api/housekeeping.rst +++ b/Documentation/core-api/housekeeping.rst @@ -99,7 +99,7 @@ the same RCU read side critical section. A typical layout example would look like this on the update side (``housekeeping_update()``):: - rcu_assign_pointer(housekeeping_cpumasks[type], trial); + rcu_assign_pointer(housekeeping.cpumasks[type], trial); synchronize_rcu(); flush_workqueue(example_workqueue); diff --git a/Documentation/core-api/index.rst b/Documentation/core-api/index.rst index 13769d5c40bf..92f91c6a0d79 100644 --- a/Documentation/core-api/index.rst +++ b/Documentation/core-api/index.rst @@ -81,6 +81,7 @@ Documentation/locking/index.rst for more related documentation. padata ../RCU/index wrappers/memory-barriers.rst + SMP Low-level hardware management ============================= diff --git a/Documentation/core-api/kernel-api.rst b/Documentation/core-api/kernel-api.rst index e8211c4ca662..4c4a57c1c094 100644 --- a/Documentation/core-api/kernel-api.rst +++ b/Documentation/core-api/kernel-api.rst @@ -307,6 +307,7 @@ Accounting Framework Block Devices ============= +.. kernel-doc:: include/linux/bvec.h .. kernel-doc:: include/linux/bio.h .. kernel-doc:: block/blk-core.c :export: diff --git a/Documentation/core-api/kho/abi.rst b/Documentation/core-api/kho/abi.rst index 799d743105a6..edeb5b311963 100644 --- a/Documentation/core-api/kho/abi.rst +++ b/Documentation/core-api/kho/abi.rst @@ -28,6 +28,11 @@ KHO persistent memory tracker ABI .. kernel-doc:: include/linux/kho/abi/kexec_handover.h :doc: KHO persistent memory tracker +KHO serialization block ABI +=========================== + +.. kernel-doc:: include/linux/kho/abi/block.h + See Also ======== diff --git a/Documentation/core-api/kho/index.rst b/Documentation/core-api/kho/index.rst index 0a2dee4f8e7d..320914a42178 100644 --- a/Documentation/core-api/kho/index.rst +++ b/Documentation/core-api/kho/index.rst @@ -83,6 +83,17 @@ Public API .. kernel-doc:: kernel/liveupdate/kexec_handover.c :export: +KHO Serialization Blocks API +============================ + +.. kernel-doc:: kernel/liveupdate/kho_block.c + :doc: KHO Serialization Blocks + +.. kernel-doc:: include/linux/kho_block.h + +.. kernel-doc:: kernel/liveupdate/kho_block.c + :internal: + See Also ======== diff --git a/Documentation/core-api/kref.rst b/Documentation/core-api/kref.rst index 8db9ff03d952..233d52d2393d 100644 --- a/Documentation/core-api/kref.rst +++ b/Documentation/core-api/kref.rst @@ -40,7 +40,7 @@ kref_init as so:: struct my_data *data; - data = kmalloc(sizeof(*data), GFP_KERNEL); + data = kmalloc_obj(*data); if (!data) return -ENOMEM; kref_init(&data->refcount); @@ -100,7 +100,7 @@ thread to process:: int rv = 0; struct my_data *data; struct task_struct *task; - data = kmalloc(sizeof(*data), GFP_KERNEL); + data = kmalloc_obj(*data); if (!data) return -ENOMEM; kref_init(&data->refcount); diff --git a/Documentation/core-api/list.rst b/Documentation/core-api/list.rst index 241464ca0549..df8b078bb366 100644 --- a/Documentation/core-api/list.rst +++ b/Documentation/core-api/list.rst @@ -112,7 +112,7 @@ list: /* State 1 */ - grock = kzalloc(sizeof(*grock), GFP_KERNEL); + grock = kzalloc_obj(*grock); if (!grock) return -ENOMEM; grock->name = "Grock"; @@ -123,7 +123,7 @@ list: /* State 2 */ - dimitri = kzalloc(sizeof(*dimitri), GFP_KERNEL); + dimitri = kzalloc_obj(*dimitri); if (!dimitri) return -ENOMEM; dimitri->name = "Dimitri"; @@ -458,7 +458,7 @@ The list_move() and list_move_tail() functions can be used to move an entry from one list to another, to either the start or end respectively. In the following example, we'll assume we start with two lists ("clowns" and -"sidewalk" in the following initial state "State 0":: +"sidewalk") in the following initial state "State 0":: .----------------------------------------------------------------. v | @@ -752,7 +752,7 @@ This is because list_splice() did not reinitialize the list_head it took entries from, leaving its pointer pointing into what is now a different list. If we want to avoid this situation, list_splice_init() can be used. It does the -same thing as list_splice(), except reinitalizes the donor list_head after the +same thing as list_splice(), except reinitializes the donor list_head after the transplant. Concurrency considerations diff --git a/Documentation/core-api/maple_tree.rst b/Documentation/core-api/maple_tree.rst index ccdd1615cf97..12bccfb6aac1 100644 --- a/Documentation/core-api/maple_tree.rst +++ b/Documentation/core-api/maple_tree.rst @@ -17,7 +17,8 @@ supports iterating over a range of entries and going to the previous or next entry in a cache-efficient manner. The tree can also be put into an RCU-safe mode of operation which allows reading and writing concurrently. Writers must synchronize on a lock, which can be the default spinlock, or the user can set -the lock to an external lock of a different type. +the lock to an external lock of a different type. Note that external locks may +interfere with allocations in a low memory situation. The Maple Tree maintains a small memory footprint and was designed to use modern processor cache efficiently. The majority of the users will be able to @@ -42,6 +43,15 @@ successful store operation within a given code segment when allocating cannot be done. Allocations of nodes are relatively small at around 256 bytes. +Since the maple tree uses internal nodes that are allocated and has rules on +data density, erasing an entry may cause allocations to occur. That is, +erasing an entry may consume memory. Users must take care to ensure that they +do not violate the larger system constraints on when and how memory is +allocated. Most situations are fine to allocate, but the pre-allocation +support is provided as a mechanism to avoid trickier situations. There is also +the possibility of using special entries and clean up the tree later, in +extreme circumstances. + .. _maple-tree-normal-api: Normal API @@ -63,7 +73,10 @@ success or an error code otherwise. mtree_store_range() works in the same way but takes a range. mtree_load() is used to retrieve the entry stored at a given index. You can use mtree_erase() to erase an entire range by only knowing one value within that range, or mtree_store() call with an entry of -NULL may be used to partially erase a range or many ranges at once. +NULL may be used to partially erase a range or many ranges at once. Note that +mtree_erase() may use GFP_KERNEL | __GFP_NOFAIL for allocations and cannot +fail. mtree_erase() can sleep, so it must not be called from an atomic +context. If you want to only store a new entry to a range (or index) if that range is currently ``NULL``, you can use mtree_insert_range() or mtree_insert() which @@ -163,7 +176,10 @@ You can use mas_erase() to erase an entire range by setting index and last of the maple state to the desired range to erase. This will erase the first range that is found in that range, set the maple state index and last as the range that was erased and return the entry that existed -at that location. +at that location. Note that mas_erase() may allocate with the GFP_KERNEL +__GFP_NOFAIL and cannot fail, but may sleep. If this is not okay, consider +using mas_store_gfp() and pass it a ``NULL``, +after setting up the correct range by walking to the entry. You can walk each entry within a range by using mas_for_each(). If you want to walk each element of the tree then ``0`` and ``ULONG_MAX`` may be used as @@ -211,7 +227,7 @@ Advanced Locking The maple tree uses a spinlock by default, but external locks can be used for tree updates as well. To use an external lock, the tree must be initialized -with the ``MT_FLAGS_LOCK_EXTERN flag``, this is usually done with the +with the ``MT_FLAGS_LOCK_EXTERN`` flag, this is usually done with the MTREE_INIT_EXT() #define, which takes an external lock as an argument. Functions and structures diff --git a/Documentation/core-api/min_heap.rst b/Documentation/core-api/min_heap.rst index 9f57766581df..919dcf1bdec7 100644 --- a/Documentation/core-api/min_heap.rst +++ b/Documentation/core-api/min_heap.rst @@ -240,19 +240,6 @@ This macro returns `true` if the heap is full, otherwise `false`. **Inline Version:** min_heap_full_inline(heap) -- **min_heap_empty(heap)**: Checks whether the heap is empty. - Complexity: **O(1)**. - -.. code-block:: c - - bool empty = min_heap_empty(heap); - -- `heap`: A pointer to the min-heap to check. - -This macro returns `true` if the heap is empty, otherwise `false`. - -**Inline Version:** min_heap_empty_inline(heap) - Example Usage ============= diff --git a/Documentation/core-api/mm-api.rst b/Documentation/core-api/mm-api.rst index aabdd3cba58e..c1d03a5a2a19 100644 --- a/Documentation/core-api/mm-api.rst +++ b/Documentation/core-api/mm-api.rst @@ -73,6 +73,7 @@ Readahead Writeback --------- +.. kernel-doc:: include/linux/writeback.h .. kernel-doc:: mm/page-writeback.c :export: @@ -117,7 +118,7 @@ More Memory Management Functions .. #kernel-doc:: mm/hmm.c (build warnings) .. kernel-doc:: mm/memremap.c .. kernel-doc:: mm/hugetlb.c -.. kernel-doc:: mm/swap.c +.. kernel-doc:: mm/folio.c .. kernel-doc:: mm/memcontrol.c .. #kernel-doc:: mm/memory-tiers.c (build warnings) .. kernel-doc:: mm/shmem.c diff --git a/Documentation/core-api/packing.rst b/Documentation/core-api/packing.rst index f68f1e08fef9..cff1a262efce 100644 --- a/Documentation/core-api/packing.rst +++ b/Documentation/core-api/packing.rst @@ -330,7 +330,7 @@ Here is an example of how to use the fields APIs: void unpack_your_data(const packed_buf_t *buf, struct data *unpacked) { - BUILD_BUG_ON(sizeof(*buf) != SIZE; + BUILD_BUG_ON(sizeof(*buf) != SIZE); unpack_fields(buf, sizeof(*buf), unpacked, fields, QUIRK_LITTLE_ENDIAN); @@ -338,7 +338,7 @@ Here is an example of how to use the fields APIs: void pack_your_data(const struct data *unpacked, packed_buf_t *buf) { - BUILD_BUG_ON(sizeof(*buf) != SIZE; + BUILD_BUG_ON(sizeof(*buf) != SIZE); pack_fields(buf, sizeof(*buf), unpacked, fields, QUIRK_LITTLE_ENDIAN); diff --git a/Documentation/core-api/printk-formats.rst b/Documentation/core-api/printk-formats.rst index c0b1b6089307..57e887ff24bc 100644 --- a/Documentation/core-api/printk-formats.rst +++ b/Documentation/core-api/printk-formats.rst @@ -322,6 +322,7 @@ MAC/FDDI addresses %pMF 00-01-02-03-04-05 %pm 000102030405 %pmR 050403020100 + %p[mM][FR][U] For printing 6-byte MAC/FDDI addresses in hex notation. The ``M`` and ``m`` specifiers result in a printed address with (M) or without (m) byte @@ -335,6 +336,8 @@ For Bluetooth addresses the ``R`` specifier shall be used after the ``M`` specifier to use reversed byte order suitable for visual interpretation of Bluetooth addresses which are in the little endian order. +When ``U`` is passed, the result is printed in the upper case. + Passed by reference. IPv4 addresses diff --git a/Documentation/core-api/real-time/hardware.rst b/Documentation/core-api/real-time/hardware.rst index 19f9bb3786e0..9f95e75e6aa1 100644 --- a/Documentation/core-api/real-time/hardware.rst +++ b/Documentation/core-api/real-time/hardware.rst @@ -130,3 +130,107 @@ https://github.com/Linutronix/RTC-Testbench. The goal of this project is to validate real-time network communication. It can be thought of as a "cyclictest" for networking and also serves as a starting point for application development. + +Firmware +-------- + +The firmware often plays a significant role in system operation because it can +perform tasks that the kernel cannot directly access, and in some cases it can +even preempt or intercept the kernel. + +A common example of firmware assisting the kernel is when it provides a generic +interface to a resource. Instead of accessing an RTC chip through an I2C host +controller, the kernel may query the firmware for the current time, and the +firmware then accesses the RTC behind the scenes. + +Firmware can also intercept kernel execution by providing services that +temporarily take control of the system. One example is memory scrubbing, where +the firmware periodically pauses the kernel, reads back portions of system +memory, and then returns control. During this time, the kernel is effectively +interrupted. +In contrast, some systems provide hardware-based memory scrubbing, which +operates independently of firmware or software. See +Documentation/edac/scrub.rst for details. + +If the kernel is intercepted for longer periods then these periods can be made +visible with the hardware latency detector. See +Documentation/trace/hwlat_detector.rst. + +The kernel can also be intercepted in response to specific events, such as +overheating. In this case, the firmware may throttle the CPU or shut it down +immediately to prevent hardware damage. + +Unless the firmware is well documented, it should be thoroughly tested to +uncover any unexpected behaviour. + +EFI +~~~~ + +EFI provides runtime services that act as a communication interface between the +firmware and the operating system. One such service is reading and writing EFI +variables, which are used, for example, to determine the boot source. + +Invoking a runtime service may require the architecture to disable kernel +preemption or interrupts during the call. This means the duration of a service +invocation directly affects the system’s observable latency. There is also +nothing that prevents a service call from disabling interrupts internally while +it runs. + +For these reasons, EFI runtime services are disabled by default on a PREEMPT_RT +kernel. They can still be enabled at boot time or via a Kconfig option if +required. +The native EFI runtime service implementation (where both the EFI service and +the kernel are either 32-bit or 64-bit executables) uses a wrapper mechanism +that invokes the service through a dedicated workqueue. This workqueue is named +efi_runtime, and it can be restricted to a housekeeping CPU using the +``/sys/devices/virtual/workqueue/efi_runtime/cpumask`` sysfs file. Assigning it +to a housekeeping CPU ensures that potentially long service invocations do not +impact the real-time workload which is restricted to other CPUs. + +It must also be verified that the runtime services behave as expected. Some +implementations on the x86 architecture pause all other CPUs while one CPU +performs the service call. In such cases, the interruption affects all CPUs, +and restricting the workqueue to a single CPU provides no benefit. + +OP-TEE (ARM) +~~~~~~~~~~~~ + +Execution flows from the normal world (Linux) into the secure world (OP-TEE) +through the secure monitor at EL3. The transition is initiated by the `smc` +(Secure Monitor Call) opcode or the `hvc` (Hypervisor Call) opcode together +with a function identifier. The calling convention defines two types of calls: +**yielding calls** and **fast calls**: + +- A **yielding call** unmasks interrupts before handling the requested service, + allowing normal world interrupts to occur. +- A **fast call** handles the requested service atomically, without allowing + interrupts from either the normal world or the secure world. + +In addition, the secure world (EL3 and OP-TEE) can receive interrupts routed to +the secure world. While a secure world interrupt is being serviced, +normal world interrupts are masked and cannot preempt the operation. + +The transition from normal world to secure monitor to OP-TEE and back introduces +additional latency due to world switching and context save/restore. This +overhead is typically a few microseconds and usually remains within the noise +floor. + +It is worth noting that the normal world cannot mask secure interrupts, while +the secure world can mask normal-world interrupts during execution. How OP-TEE +affects real-time workloads depends on whether secure interrupts are enabled +and which OP-TEE services are invoked. + +A practical concern is any fast call that runs longer than expected, for +example a function that occasionally performs a long-running cryptographic +computation. Another example that may block in an unexpected way are OP-TEE +drivers that issue RPC requests. An OP-TEE service in the secure world (RPMB +for instance) may need to issue a request back to the normal world (the Linux +driver) in order to complete the operation. While Linux remains preemptible, +the thread that issued the request stays blocked until the RPC completes and +the secure function call returns. + +The TF-A project provides documentation on interrupt management: +https://trustedfirmware-a.readthedocs.io/en/latest/design/interrupt-framework-design.html#interrupt-management-framework + +The OP-TEE project provides documentation on how interrupts are handled: +https://optee.readthedocs.io/en/latest/architecture/core.html#interrupt-handling diff --git a/Documentation/core-api/real-time/index.rst b/Documentation/core-api/real-time/index.rst index f08d2395a22c..a17a3dec535c 100644 --- a/Documentation/core-api/real-time/index.rst +++ b/Documentation/core-api/real-time/index.rst @@ -15,3 +15,4 @@ the required changes compared to a non-PREEMPT_RT configuration. differences hardware architecture-porting + kernel-configuration diff --git a/Documentation/core-api/real-time/kernel-configuration.rst b/Documentation/core-api/real-time/kernel-configuration.rst new file mode 100644 index 000000000000..d7f08e7b8760 --- /dev/null +++ b/Documentation/core-api/real-time/kernel-configuration.rst @@ -0,0 +1,307 @@ +.. SPDX-License-Identifier: GPL-2.0 + +============================== +Real-Time Kernel configuration +============================== + +.. contents:: Table of Contents + :depth: 3 + :local: + +Introduction +============ + +This document lists the kernel configuration options that might affect a +real-time kernel's worst-case latency. It is intended for system integrators. + +Configuration options +===================== + +.. Please keep the configuration listings alphabetically ordered + +CPU frequency governors +----------------------- + +``CONFIG_CPU_FREQ`` +^^^^^^^^^^^^^^^^^^^ + +:Expectation: enabled +:Severity: *high* + +The CPU frequency scaling subsystem ensures that the processor can operate at +its maximum supported frequency. While, in general, bootloaders are tasked +with setting the CPU clock to the highest speed on boot, some do not. It is +thus desirable to keep this option enabled. + +.. caution:: + + A real-time kernel is not about being "as fast as possible", however + real-time requirements may demand that the CPU is clocked at a particular + speed. + +``CONFIG_CPU_FREQ_DEFAULT_GOV_PERFORMANCE`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:Expectation: enabled +:Severity: *high* + +Real-Time workloads expect a fixed CPU frequency during execution. Using the +performance governor is an easy way to achieve that purely from kernel +configuration. + +This is not an absolute rule. Some setups might prefer to clock the CPU to +lower speeds due to thermal packaging or other requirements. The key is that +the CPU frequency remains constant once set. + +Non-performance CPU frequency governors +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:Expectation: disabled +:Severity: *medium* + +To ensure reproducible system latency measurements, disable the +non-``PERFORMANCE`` CPU frequency governors whenever possible. This avoids +the risk of unknown userspace tasks implicitly or explicitly setting a +different CPU frequency governor, and thereby changing latency behavior while +the system is running. + +If disabling other frequency governors is not an option, use a governor that +keeps the CPU frequency fixed. For example, +``CONFIG_CPU_FREQ_DEFAULT_GOV_USERSPACE`` can be enabled when userspace is +responsible for setting a *stable* frequency during system initialization. + +If a low CPU frequency is desired, then +``CONFIG_CPU_FREQ_DEFAULT_GOV_POWERSAVE`` can be set. + +The ``ONDEMAND`` governor should not be enabled on a real-time system. Its +frequency changes depend on workload behavior and can significantly harm +determinism. + +For more information, see Documentation/admin-guide/pm/cpufreq.rst + +``CONFIG_CPU_IDLE`` +------------------- + +:Expectation: enabled +:Severity: *info* + +CPU idle states (C-states) allow the processor to enter low-power modes during +periods of inactivity. Very-low CPU idle states may require flushing the CPU +caches and lowering or disabling the clocking. This can lower power +consumption, but it also increases the entry and exit latency from such +states. + +While disabling this option eliminates cpuidle-related latencies, doing so can +significantly impact hardware longevity, warranty, and thermal behavior. +Users should cap the maximum C-state to C1 instead. For ACPI platforms, this +can be achieved by using the boot parameter [1]_:: + + processor.max_cstate=1 + +Higher C-states can be acceptable depending on the user workload's latency +requirements. For ACPI-based platforms, use the ``cpupower idle-info`` +command to inspect the available idle states. + +For more information, please see: + +- ``linux/tools/power/cpupower`` +- Documentation/admin-guide/pm/cpuidle.rst +- Documentation/admin-guide/pm/index.rst + +``CONFIG_DRM`` +-------------- + +:Expectation: disabled +:Severity: *info* + +GPU-accelerated workloads can share system resources with the CPU, including +last-level cache (LLC) and memory bandwidth. Modern integrated GPUs optimize +graphics performance at the expense of CPU determinism. + +Examples of affected platforms: + +- Intel processors with integrated graphics (Gen9 and later) +- AMD APUs with Radeon Graphics +- Xilinx Zynq UltraScale+ MPSoC EG/EV series + +If graphics workloads must run alongside real-time tasks, users must conduct +thorough stress testing using tools like ``glmark2`` while measuring the +overall system latency. + +For more information, please check: + +- Documentation/core-api/real-time/hardware.rst ("Regarding hardware" section) +- Documentation/filesystems/resctrl.rst +- `Real-Time and Graphics: A Contradiction? <https://web.archive.org/web/20221025085614/https://linutronix.de/PDF/Realtime_and_graphics-acontradiction2021.pdf>`_ + +``CONFIG_EFI_DISABLE_RUNTIME`` +------------------------------ + +:Expectation: enabled +:Severity: *medium* + +EFI is the standard boot and firmware interface for multiple architectures. +EFI runtime services provide callback functions to be called from the kernel; +e.g., as utilized by (``CONFIG_EFI_VARS*``) or (``CONFIG_RTC_DRV_EFI``). For +the former, the kernel calls into EFI to update the EFI variables. + +Calling into EFI means invoking firmware callbacks. During such invocations, +the system might not be able to react to interrupts and will thus not be able +to perform a context switch. This can cause significant latency spikes for +the real-time system. + +``CONFIG_PREEMPT_RT`` enables this option by default. If this option is +manually disabled at build time, the following boot parameter [1]_ may be used +to disable EFI runtime at boot up:: + + efi=noruntime + +Alternatively, confine EFI runtime service calls to a housekeeping CPU by +restricting the ``efi_runtime`` workqueue CPU affinity. For example, set that +workqueue's affinity to CPU #0 and pin your RT tasks to a different CPU range. +See Documentation/core-api/workqueue.rst + +``CONFIG_NO_HZ`` / ``CONFIG_NO_HZ_FULL`` +---------------------------------------- + +:Expectation: disabled +:Severity: *medium* + +Tickless operation can increase kernel-to-userspace transition latency due to +the extra accounting and state book-keeping. + +*Guidance by real-time workload type:* + +- For periodic workloads; e.g., control loops executing every 100 µs, avoid + ``NO_HZ`` modes. Consistent kernel ticks are preferable. + +- For computation-intensive workloads; e.g. extended userspace execution, + ``NO_HZ_FULL`` may be beneficial. In such cases, users should offload the + kernel housekeeping to dedicated CPUs and isolate compute cores. + +See also Documentation/timers/no_hz.rst + +``CONFIG_PREEMPT_RT`` +--------------------- + +:Expectation: enabled +:Severity: **fatal** + +This option must be enabled, or the resulting kernel will not be fully +preemptible and real-time capable. + +``CONFIG_TRACING`` (and tracing options) +---------------------------------------- + +:Expectation: enabled +:Severity: *info* + +Shipping kernels with tracing support enabled (but not actively running) is +highly recommended. This will allow the users to extract more information if +latency problems arise. Nonetheless, some tracers do incur latency overhead +just by being enabled. + +.. caution:: + + Users should *not* make use of tracers or trace events during production + real-time kernel operation as they can add considerable overhead and degrade + the system's latency. + +``CONFIG_IRQSOFF_TRACER`` and ``CONFIG_PREEMPT_TRACER`` +^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^ + +:Expectation: disabled +:Severity: *high* + +These tracers do incur measurable latency overhead even when tracing is not +currently active. + +Kernel Debug Options +==================== + +Most kernel debug options add runtime overhead that increases the worst-case +latency. + +.. caution:: + + During development and early testing, users are encouraged to run their + real-time workloads and peripherals with lockdep (:ref:`lockdep`) and other + kernel debug options enabled, for a considerable amount of time. Such + workloads might trigger kernel code paths that were not triggered during the + internal Linux real-time kernel development, thus helping to uncover locking + and other types of kernel bugs. + +``CONFIG_DEBUG_ATOMIC_SLEEP`` +----------------------------- + +:Expectation: allowed + +This sanity check catches common kernel programming errors with a tolerable +latency cost. It also increases overall scheduling as each ``might_sleep()`` +can lead to a context switch. + +``CONFIG_DEBUG_BUGVERBOSE`` and ``CONFIG_DEBUG_INFO*`` +------------------------------------------------------ + +:Expectation: allowed + +These options increase the kernel image size but have no latency impact. They +are also essential for meaningful BUG logs, crash dumps, and profiling. + +``CONFIG_DEBUG_FS`` +------------------- + +:Expectation: allowed + +This is safe to include in real-time kernels, *provided that debugfs is not +accessed during production runtime*. + +``CONFIG_DEBUG_KERNEL`` +----------------------- + +:Expectation: allowed + +Meta-option which allows debug features to be enabled. It has no runtime +impact, but beware of any debug features that it may have implicitly enabled. + +``CONFIG_LOCKUP_DETECTOR`` +-------------------------- + +:Expectation: disabled +:Severity: *high* + +The lockup detector creates kernel timer callbacks that execute every few +seconds, in hard-IRQ context, even on real-time kernels. These periodic +interrupts can cause latency spikes. + +Users should use hardware watchdogs instead, which will provide a similar +functionality without the software-induced latency. + +.. _lockdep: + +``CONFIG_PROVE_LOCKING`` +------------------------ + +:Expectation: disabled +:Severity: *high* + +Proving the correctness of all kernel locking adds substantial overhead and +significantly increases worst-case latency. + +Summary +======= + +There is no "one size fits all" solution for configuring a real-time Linux +system. Beginning with the system real-time requirements, integrators must +consider the features and functions of the system's hardware, kernel, and +userspace. All such components must be properly configured in order to +establish and constrain the system's maximum latency. + +With that in mind, any incorrect real-time kernel configuration could cause a +new maximum latency that shows up at the wrong time and is catastrophic for +the real-time system's latency. + +References +========== + +.. [1] See Documentation/admin-guide/kernel-parameters.rst diff --git a/Documentation/core-api/real-time/theory.rst b/Documentation/core-api/real-time/theory.rst index 43d0120737f8..92de5654163d 100644 --- a/Documentation/core-api/real-time/theory.rst +++ b/Documentation/core-api/real-time/theory.rst @@ -25,7 +25,7 @@ Scheduling ========== The core principles of Linux scheduling and the associated user-space API are -documented in the man page sched(7) +documented in the man page `sched(7) <https://man7.org/linux/man-pages/man7/sched.7.html>`_. By default, the Linux kernel uses the SCHED_OTHER scheduling policy. Under this policy, a task is preempted when the scheduler determines that it has diff --git a/Documentation/core-api/swiotlb.rst b/Documentation/core-api/swiotlb.rst index 9e0fe027dd3b..71b4e4c27eb5 100644 --- a/Documentation/core-api/swiotlb.rst +++ b/Documentation/core-api/swiotlb.rst @@ -140,8 +140,11 @@ Data structures concepts ------------------------ Memory used for swiotlb bounce buffers is allocated from overall system memory as one or more "pools". The default pool is allocated during system boot with a -default size of 64 MiB. The default pool size may be modified with the -"swiotlb=" kernel boot line parameter. The default size may also be adjusted +default size of 64 MiB, which can be changed at compile time via +CONFIG_SWIOTLB_DEFAULT_SIZE_MB. The default pool size may also be +modified at runtime with the "swiotlb=" kernel boot line parameter, +which takes precedence over the compile-time default. The default size +may also be adjusted due to other conditions, such as running in a CoCo VM, as described above. If CONFIG_SWIOTLB_DYNAMIC is enabled, additional pools may be allocated later in the life of the system. Each pool must be a contiguous range of physical diff --git a/Documentation/core-api/workqueue.rst b/Documentation/core-api/workqueue.rst index 411e1b28b8de..bb770f556568 100644 --- a/Documentation/core-api/workqueue.rst +++ b/Documentation/core-api/workqueue.rst @@ -356,7 +356,7 @@ Guidelines well under the default limit. * A wq serves as a domain for forward progress guarantee - (``WQ_MEM_RECLAIM``, flush and work item attributes. Work items + (``WQ_MEM_RECLAIM``), flush and work item attributes. Work items which are not involved in memory reclaim and don't need to be flushed as a part of a group of work items, and don't require any special attribute, can use one of the system wq. There is no |
