From 3a08f39a8b77defe125c40ec11f118261d585aa3 Mon Sep 17 00:00:00 2001 From: Konstantin Demin Date: Tue, 29 Oct 2024 05:12:06 +0300 Subject: [PATCH] drop "rt" featureset --- debian/config/amd64/defines.toml | 6 - debian/config/arm64/defines.toml | 6 - debian/config/arm64/rt/config | 6 - debian/config/armhf/defines.toml | 6 - debian/config/defines.toml | 10 - debian/config/featureset-rt/config | 25 - ...vfp-Provide-vfp_lock-for-VFP-locking.patch | 75 -- ...arm-Disable-jump-label-on-PREEMPT_RT.patch | 36 - ...empt_disable-enable_rt-where-recomme.patch | 107 --- ...parse-annotation-PREEMPT_RT-s-sleepi.patch | 58 -- ...Add-notation-to-console_srcu-locking.patch | 39 - ...de-a-method-to-check-if-a-task-is-PI.patch | 54 -- ...e-annotation-for-timer_sync_wait_run.patch | 29 - ...lace-bit-spinlocks-with-a-spinlock_t.patch | 83 -- ...vfp-Use-vfp_lock-in-vfp_sync_hwstate.patch | 44 - ...isable-interrupts-on-PREEMPT_RT-duri.patch | 119 --- ...-hrtimer_cpu_base_.-_expiry-for-spar.patch | 33 - ...e-one-__cond_lock-in-RT-s-spin_trylo.patch | 44 - ...ntk-nbcon-Consolidate-alloc-and-init.patch | 109 --- ...function-to-preempt-serving-softirqs.patch | 60 -- .../0002-zram-Remove-ZRAM_LOCK.patch | 67 -- ...fp-Use-vfp_lock-in-vfp_support_entry.patch | 48 -- ...heck-for-atomic-context-on-PREEMPT_R.patch | 39 - ...ing-rt-Add-sparse-annotation-for-RCU.patch | 84 -- ...deal-with-nbcon-consoles-on-seq-init.patch | 148 ---- ...me-Allow-to-preempt-after-a-callback.patch | 47 -- ...3-zram-Shrink-zram_table_entry-flags.patch | 49 -- ...ding-signals-outside-of-vfp_lock-ed-.patch | 121 --- ...Disable-tracing-points-on-PREEMPT_RT.patch | 60 -- ...ate-unlock-followed-by-lock-for-spar.patch | 35 - ...ck-printk_deferred_enter-_exit-usage.patch | 76 -- ...spin_lock_irq-instead-of-local_irq_d.patch | 89 -- ...rify-rules-of-the-owner-waiter-match.patch | 110 --- ...rm-i915-Drop-the-irqs_disabled-check.patch | 40 - ...Remove-return-value-for-write_atomic.patch | 71 -- ...Consider-also-RCU-depth-in-busy-loop.patch | 30 - ...on-Add-detailed-doc-for-write_atomic.patch | 75 -- ...Revert-drm-i915-Depend-on-PREEMPT_RT.patch | 24 - ...-callbacks-to-synchronize-with-drive.patch | 87 -- ...-driver-synchronization-while-un-reg.patch | 124 --- ...ide-low-level-functions-to-lock-port.patch | 52 -- ...roduce-wrapper-to-set-uart_port-cons.patch | 125 --- ...ove-console_srcu_read_flags-comments.patch | 75 -- ...-acquire-context-for-non-printing-op.patch | 180 ---- ...ire-nbcon-context-in-port-lock-wrapp.patch | 185 ----- ...k-nbcon-Do-not-rely-on-proxy-headers.patch | 90 -- ...nsole_is_usable-available-to-nbcon.c.patch | 105 --- ...k-Let-console_is_usable-handle-nbcon.patch | 45 - ...flags-argument-for-console_is_usable.patch | 69 -- ...-helper-to-assign-priority-based-on-.patch | 72 -- ...vide-function-to-flush-using-write_a.patch | 225 ----- ...rintk-Track-registered-boot-consoles.patch | 82 -- ...-nbcon-consoles-in-console_flush_all.patch | 212 ----- ...printk-Add-is_printk_legacy_deferred.patch | 68 -- ...-Flush-new-records-on-device_release.patch | 79 -- ...-Flush-nbcon-consoles-first-on-panic.patch | 30 - ...k-nbcon-Add-unsafe-flushing-on-panic.patch | 161 ---- ...sole_lock-dance-if-no-legacy-or-boot.patch | 139 ---- .../0028-printk-Track-nbcon-consoles.patch | 68 -- ...-Coordinate-direct-printing-in-panic.patch | 184 ----- ...intk-Add-helper-for-flush-type-logic.patch | 348 -------- ...k-nbcon-Implement-emergency-sections.patch | 173 ---- ...panic-Mark-emergency-section-in-warn.patch | 40 - ...panic-Mark-emergency-section-in-oops.patch | 42 - ...ark-emergency-sections-in-rcu-stalls.patch | 97 --- ...emergency-sections-in-lockdep-splats.patch | 453 ---------- ...6-printk-Use-the-BITS_PER_LONG-macro.patch | 37 - ...e-raw_cpu_ptr-instead-of-open-coding.patch | 29 - ...-function-for-printers-to-reacquire-.patch | 188 ----- ...pr_flush-if-before-SYSTEM_SCHEDULING.patch | 79 -- ...-Flush-console-on-unregister_console.patch | 39 - ...nbcon-Add-context-to-usable-and-emit.patch | 184 ----- ...n-Init-nbcon_seq-to-highest-possible.patch | 57 -- ...ntk-nbcon-Introduce-printer-kthreads.patch | 696 ---------------- ...nbcon-Relocate-nbcon_atomic_emit_one.patch | 111 --- ...-thread-callback-if-in-task-context-.patch | 228 ----- ...ely-on-kthreads-for-normal-operation.patch | 287 ------- ...rovide-helper-for-message-prepending.patch | 83 -- ...bcon-Show-replay-message-on-takeover.patch | 133 --- ...soles-Add-notation-to-c_start-c_stop.patch | 37 - ...-Add-nbcon-support-for-proc-consoles.patch | 42 - ...y-sysfs-Add-nbcon-support-for-active.patch | 27 - ...-legacy-printer-kthread-for-PREEMPT_.patch | 324 -------- ...-Assign-nice-20-for-printing-threads.patch | 48 -- ...-serial-8250-Switch-to-nbcon-console.patch | 334 -------- ...se-positive-lockdep-report-for-legac.patch | 138 ---- ...rt-drop-lockdep-annotation-from-seri.patch | 29 - .../ARM64__Allow_to_enable_RT.patch | 27 - .../patches-rt/ARM__Allow_to_enable_RT.patch | 35 - ...on_section_permission_fault_handlers.patch | 91 -- .../Add_localversion_for_-RT_release.patch | 19 - .../POWERPC__Allow_to_enable_RT.patch | 35 - debian/patches-rt/PREEMPT_AUTO.patch | 779 ------------------ ..._GUP-on-PREEMPT_RT-if-HIGHPTE-is-als.patch | 35 - ...ounter-Use-u64_stats_t-for-statistic.patch | 238 ------ ...-Select-the-generic-memory-allocator.patch | 27 - .../powerpc__traps__Use_PREEMPT_RT.patch | 38 - ...kernel_MPIC_emulation_for_PREEMPT_RT.patch | 43 - ...e_a_locallock_instead_local_irq_save.patch | 115 --- ..._around_stack-guard_init_from_atomic.patch | 37 - ...force-sched-priority-to-timersd-on-b.patch | 71 -- .../riscv-add-PREEMPT_AUTO-support.patch | 44 - .../patches-rt/riscv-allow-to-enable-RT.patch | 23 - ...n-t-try-push-tasks-if-there-are-none.patch | 58 -- debian/patches-rt/series | 166 ---- ...a-dedicated-thread-for-timer-wakeups.patch | 222 ----- ...-Wake-ktimers-thread-also-in-softirq.patch | 44 - ...ysfs__Add__sys_kernel_realtime_entry.patch | 53 -- ...-storm-since-introduction-of-timersd.patch | 106 --- .../patches-rt/x86__Allow_to_enable_RT.patch | 27 - .../x86__Enable_RT_also_on_32bit.patch | 25 - debian/source/include-binaries | 1 - debian/upstream/rt-signing-key.pgp | Bin 84522 -> 0 bytes 113 files changed, 11261 deletions(-) delete mode 100644 debian/config/arm64/rt/config delete mode 100644 debian/config/featureset-rt/config delete mode 100644 debian/patches-rt/0001-ARM-vfp-Provide-vfp_lock-for-VFP-locking.patch delete mode 100644 debian/patches-rt/0001-arm-Disable-jump-label-on-PREEMPT_RT.patch delete mode 100644 debian/patches-rt/0001-drm-i915-Use-preempt_disable-enable_rt-where-recomme.patch delete mode 100644 debian/patches-rt/0001-locking-rt-Add-sparse-annotation-PREEMPT_RT-s-sleepi.patch delete mode 100644 debian/patches-rt/0001-printk-Add-notation-to-console_srcu-locking.patch delete mode 100644 debian/patches-rt/0001-sched-core-Provide-a-method-to-check-if-a-task-is-PI.patch delete mode 100644 debian/patches-rt/0001-timers-Add-sparse-annotation-for-timer_sync_wait_run.patch delete mode 100644 debian/patches-rt/0001-zram-Replace-bit-spinlocks-with-a-spinlock_t.patch delete mode 100644 debian/patches-rt/0002-ARM-vfp-Use-vfp_lock-in-vfp_sync_hwstate.patch delete mode 100644 debian/patches-rt/0002-drm-i915-Don-t-disable-interrupts-on-PREEMPT_RT-duri.patch delete mode 100644 debian/patches-rt/0002-hrtimer-Annotate-hrtimer_cpu_base_.-_expiry-for-spar.patch delete mode 100644 debian/patches-rt/0002-locking-rt-Remove-one-__cond_lock-in-RT-s-spin_trylo.patch delete mode 100644 debian/patches-rt/0002-printk-nbcon-Consolidate-alloc-and-init.patch delete mode 100644 debian/patches-rt/0002-softirq-Add-function-to-preempt-serving-softirqs.patch delete mode 100644 debian/patches-rt/0002-zram-Remove-ZRAM_LOCK.patch delete mode 100644 debian/patches-rt/0003-ARM-vfp-Use-vfp_lock-in-vfp_support_entry.patch delete mode 100644 debian/patches-rt/0003-drm-i915-Don-t-check-for-atomic-context-on-PREEMPT_R.patch delete mode 100644 debian/patches-rt/0003-locking-rt-Add-sparse-annotation-for-RCU.patch delete mode 100644 debian/patches-rt/0003-printk-Properly-deal-with-nbcon-consoles-on-seq-init.patch delete mode 100644 debian/patches-rt/0003-time-Allow-to-preempt-after-a-callback.patch delete mode 100644 debian/patches-rt/0003-zram-Shrink-zram_table_entry-flags.patch delete mode 100644 debian/patches-rt/0004-ARM-vfp-Move-sending-signals-outside-of-vfp_lock-ed-.patch delete mode 100644 debian/patches-rt/0004-drm-i915-Disable-tracing-points-on-PREEMPT_RT.patch delete mode 100644 debian/patches-rt/0004-locking-rt-Annotate-unlock-followed-by-lock-for-spar.patch delete mode 100644 debian/patches-rt/0004-printk-Check-printk_deferred_enter-_exit-usage.patch delete mode 100644 debian/patches-rt/0005-drm-i915-gt-Use-spin_lock_irq-instead-of-local_irq_d.patch delete mode 100644 debian/patches-rt/0005-printk-nbcon-Clarify-rules-of-the-owner-waiter-match.patch delete mode 100644 debian/patches-rt/0006-drm-i915-Drop-the-irqs_disabled-check.patch delete mode 100644 debian/patches-rt/0006-printk-nbcon-Remove-return-value-for-write_atomic.patch delete mode 100644 debian/patches-rt/0007-drm-i915-guc-Consider-also-RCU-depth-in-busy-loop.patch delete mode 100644 debian/patches-rt/0007-printk-nbcon-Add-detailed-doc-for-write_atomic.patch delete mode 100644 debian/patches-rt/0008-Revert-drm-i915-Depend-on-PREEMPT_RT.patch delete mode 100644 debian/patches-rt/0008-printk-nbcon-Add-callbacks-to-synchronize-with-drive.patch delete mode 100644 debian/patches-rt/0009-printk-nbcon-Use-driver-synchronization-while-un-reg.patch delete mode 100644 debian/patches-rt/0010-serial-core-Provide-low-level-functions-to-lock-port.patch delete mode 100644 debian/patches-rt/0011-serial-core-Introduce-wrapper-to-set-uart_port-cons.patch delete mode 100644 debian/patches-rt/0012-console-Improve-console_srcu_read_flags-comments.patch delete mode 100644 debian/patches-rt/0013-nbcon-Add-API-to-acquire-context-for-non-printing-op.patch delete mode 100644 debian/patches-rt/0014-serial-core-Acquire-nbcon-context-in-port-lock-wrapp.patch delete mode 100644 debian/patches-rt/0015-printk-nbcon-Do-not-rely-on-proxy-headers.patch delete mode 100644 debian/patches-rt/0016-printk-Make-console_is_usable-available-to-nbcon.c.patch delete mode 100644 debian/patches-rt/0017-printk-Let-console_is_usable-handle-nbcon.patch delete mode 100644 debian/patches-rt/0018-printk-Add-flags-argument-for-console_is_usable.patch delete mode 100644 debian/patches-rt/0019-printk-nbcon-Add-helper-to-assign-priority-based-on-.patch delete mode 100644 debian/patches-rt/0020-printk-nbcon-Provide-function-to-flush-using-write_a.patch delete mode 100644 debian/patches-rt/0021-printk-Track-registered-boot-consoles.patch delete mode 100644 debian/patches-rt/0022-printk-nbcon-Use-nbcon-consoles-in-console_flush_all.patch delete mode 100644 debian/patches-rt/0023-printk-Add-is_printk_legacy_deferred.patch delete mode 100644 debian/patches-rt/0024-printk-nbcon-Flush-new-records-on-device_release.patch delete mode 100644 debian/patches-rt/0025-printk-Flush-nbcon-consoles-first-on-panic.patch delete mode 100644 debian/patches-rt/0026-printk-nbcon-Add-unsafe-flushing-on-panic.patch delete mode 100644 debian/patches-rt/0027-printk-Avoid-console_lock-dance-if-no-legacy-or-boot.patch delete mode 100644 debian/patches-rt/0028-printk-Track-nbcon-consoles.patch delete mode 100644 debian/patches-rt/0029-printk-Coordinate-direct-printing-in-panic.patch delete mode 100644 debian/patches-rt/0030-printk-Add-helper-for-flush-type-logic.patch delete mode 100644 debian/patches-rt/0031-printk-nbcon-Implement-emergency-sections.patch delete mode 100644 debian/patches-rt/0032-panic-Mark-emergency-section-in-warn.patch delete mode 100644 debian/patches-rt/0033-panic-Mark-emergency-section-in-oops.patch delete mode 100644 debian/patches-rt/0034-rcu-Mark-emergency-sections-in-rcu-stalls.patch delete mode 100644 debian/patches-rt/0035-lockdep-Mark-emergency-sections-in-lockdep-splats.patch delete mode 100644 debian/patches-rt/0036-printk-Use-the-BITS_PER_LONG-macro.patch delete mode 100644 debian/patches-rt/0037-printk-nbcon-Use-raw_cpu_ptr-instead-of-open-coding.patch delete mode 100644 debian/patches-rt/0038-printk-nbcon-Add-function-for-printers-to-reacquire-.patch delete mode 100644 debian/patches-rt/0039-printk-Fail-pr_flush-if-before-SYSTEM_SCHEDULING.patch delete mode 100644 debian/patches-rt/0040-printk-Flush-console-on-unregister_console.patch delete mode 100644 debian/patches-rt/0041-printk-nbcon-Add-context-to-usable-and-emit.patch delete mode 100644 debian/patches-rt/0042-printk-nbcon-Init-nbcon_seq-to-highest-possible.patch delete mode 100644 debian/patches-rt/0043-printk-nbcon-Introduce-printer-kthreads.patch delete mode 100644 debian/patches-rt/0044-printk-nbcon-Relocate-nbcon_atomic_emit_one.patch delete mode 100644 debian/patches-rt/0045-printk-nbcon-Use-thread-callback-if-in-task-context-.patch delete mode 100644 debian/patches-rt/0046-printk-nbcon-Rely-on-kthreads-for-normal-operation.patch delete mode 100644 debian/patches-rt/0047-printk-Provide-helper-for-message-prepending.patch delete mode 100644 debian/patches-rt/0048-printk-nbcon-Show-replay-message-on-takeover.patch delete mode 100644 debian/patches-rt/0049-proc-consoles-Add-notation-to-c_start-c_stop.patch delete mode 100644 debian/patches-rt/0050-proc-Add-nbcon-support-for-proc-consoles.patch delete mode 100644 debian/patches-rt/0051-tty-sysfs-Add-nbcon-support-for-active.patch delete mode 100644 debian/patches-rt/0052-printk-Implement-legacy-printer-kthread-for-PREEMPT_.patch delete mode 100644 debian/patches-rt/0053-printk-nbcon-Assign-nice-20-for-printing-threads.patch delete mode 100644 debian/patches-rt/0053-serial-8250-Switch-to-nbcon-console.patch delete mode 100644 debian/patches-rt/0054-printk-Avoid-false-positive-lockdep-report-for-legac.patch delete mode 100644 debian/patches-rt/0054-serial-8250-Revert-drop-lockdep-annotation-from-seri.patch delete mode 100644 debian/patches-rt/ARM64__Allow_to_enable_RT.patch delete mode 100644 debian/patches-rt/ARM__Allow_to_enable_RT.patch delete mode 100644 debian/patches-rt/ARM__enable_irq_in_translation_section_permission_fault_handlers.patch delete mode 100644 debian/patches-rt/Add_localversion_for_-RT_release.patch delete mode 100644 debian/patches-rt/POWERPC__Allow_to_enable_RT.patch delete mode 100644 debian/patches-rt/PREEMPT_AUTO.patch delete mode 100644 debian/patches-rt/arm-Disable-FAST_GUP-on-PREEMPT_RT-if-HIGHPTE-is-als.patch delete mode 100644 debian/patches-rt/netfilter-nft_counter-Use-u64_stats_t-for-statistic.patch delete mode 100644 debian/patches-rt/powerpc-pseries-Select-the-generic-memory-allocator.patch delete mode 100644 debian/patches-rt/powerpc__traps__Use_PREEMPT_RT.patch delete mode 100644 debian/patches-rt/powerpc_kvm__Disable_in-kernel_MPIC_emulation_for_PREEMPT_RT.patch delete mode 100644 debian/patches-rt/powerpc_pseries_iommu__Use_a_locallock_instead_local_irq_save.patch delete mode 100644 debian/patches-rt/powerpc_stackprotector__work_around_stack-guard_init_from_atomic.patch delete mode 100644 debian/patches-rt/rcutorture-Also-force-sched-priority-to-timersd-on-b.patch delete mode 100644 debian/patches-rt/riscv-add-PREEMPT_AUTO-support.patch delete mode 100644 debian/patches-rt/riscv-allow-to-enable-RT.patch delete mode 100644 debian/patches-rt/sched-rt-Don-t-try-push-tasks-if-there-are-none.patch delete mode 100644 debian/patches-rt/series delete mode 100644 debian/patches-rt/softirq-Use-a-dedicated-thread-for-timer-wakeups.patch delete mode 100644 debian/patches-rt/softirq-Wake-ktimers-thread-also-in-softirq.patch delete mode 100644 debian/patches-rt/sysfs__Add__sys_kernel_realtime_entry.patch delete mode 100644 debian/patches-rt/tick-Fix-timer-storm-since-introduction-of-timersd.patch delete mode 100644 debian/patches-rt/x86__Allow_to_enable_RT.patch delete mode 100644 debian/patches-rt/x86__Enable_RT_also_on_32bit.patch delete mode 100644 debian/upstream/rt-signing-key.pgp diff --git a/debian/config/amd64/defines.toml b/debian/config/amd64/defines.toml index 8e352e0..caa0f00 100644 --- a/debian/config/amd64/defines.toml +++ b/debian/config/amd64/defines.toml @@ -19,12 +19,6 @@ hardware_long = 'cloud platforms including Amazon EC2, Microsoft Azure, and Goog [[featureset]] name = 'none' -[[featureset]] -name = 'rt' -# Override available flavours in rt featureset -[[featureset.flavour]] -name = 'amd64' - [build] enable_signed = true enable_vdso = true diff --git a/debian/config/arm64/defines.toml b/debian/config/arm64/defines.toml index 3bf8709..34932a1 100644 --- a/debian/config/arm64/defines.toml +++ b/debian/config/arm64/defines.toml @@ -25,12 +25,6 @@ hardware = '64-bit ARMv8 machines with 16k pages' [[featureset]] name = 'none' -[[featureset]] -name = 'rt' -# Override available flavours in rt featureset -[[featureset.flavour]] -name = 'arm64' - [build] compiler_gnutype_compat = 'arm-linux-gnueabihf' enable_signed = true diff --git a/debian/config/arm64/rt/config b/debian/config/arm64/rt/config deleted file mode 100644 index bd5e81c..0000000 --- a/debian/config/arm64/rt/config +++ /dev/null @@ -1,6 +0,0 @@ -## -## file: arch/arm64/kvm/Kconfig -## -#. ARCH_SUPPORTS_RT depends on HAVE_POSIX_CPU_TIMERS_TASK_WORK -#. HAVE_POSIX_CPU_TIMERS_TASK_WORK depneds on !KVM -# CONFIG_KVM is not set diff --git a/debian/config/armhf/defines.toml b/debian/config/armhf/defines.toml index 21378ed..4c89a3e 100644 --- a/debian/config/armhf/defines.toml +++ b/debian/config/armhf/defines.toml @@ -15,12 +15,6 @@ hardware_long = 'ARMv7 multiplatform kernel supporting LPAE. See https://wiki.de [[featureset]] name = 'none' -[[featureset]] -name = 'rt' -# Override available flavours in rt featureset -[[featureset.flavour]] -name = 'armmp' - [build] enable_vdso = true kernel_file = 'arch/arm/boot/zImage' diff --git a/debian/config/defines.toml b/debian/config/defines.toml index 8ccaff5..accb049 100644 --- a/debian/config/defines.toml +++ b/debian/config/defines.toml @@ -84,16 +84,6 @@ name = 'x86' [[featureset]] name = 'none' -[[featureset]] -name = 'rt' -enable = true - [featureset.description] - parts = ['rt'] - [featureset.description.long] - rt = 'This kernel includes the PREEMPT_RT realtime patch set.' - [featureset.description.short] - rt = 'PREEMPT_RT' - [build] compiler = 'gcc-14' diff --git a/debian/config/featureset-rt/config b/debian/config/featureset-rt/config deleted file mode 100644 index f571ab2..0000000 --- a/debian/config/featureset-rt/config +++ /dev/null @@ -1,25 +0,0 @@ -## -## file: init/Kconfig -## -# CONFIG_SCHED_AUTOGROUP is not set - -## -## file: kernel/Kconfig.preempt -## -## choice: Preemption Model -# CONFIG_PREEMPT_VOLUNTARY is not set -CONFIG_PREEMPT_RT=y -## end choice - -## -## file: kernel/rcu/Kconfig -## -CONFIG_RCU_EXPERT=y - -## -## file: kernel/trace/Kconfig -## -CONFIG_SCHED_TRACER=y -CONFIG_HWLAT_TRACER=y -CONFIG_OSNOISE_TRACER=y -CONFIG_TIMERLAT_TRACER=y diff --git a/debian/patches-rt/0001-ARM-vfp-Provide-vfp_lock-for-VFP-locking.patch b/debian/patches-rt/0001-ARM-vfp-Provide-vfp_lock-for-VFP-locking.patch deleted file mode 100644 index 771239e..0000000 --- a/debian/patches-rt/0001-ARM-vfp-Provide-vfp_lock-for-VFP-locking.patch +++ /dev/null @@ -1,75 +0,0 @@ -From: Sebastian Andrzej Siewior -Date: Fri, 19 May 2023 16:57:29 +0200 -Subject: [PATCH 1/4] ARM: vfp: Provide vfp_lock() for VFP locking. -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -kernel_neon_begin() uses local_bh_disable() to ensure exclusive access -to the VFP unit. This is broken on PREEMPT_RT because a BH disabled -section remains preemptible on PREEMPT_RT. - -Introduce vfp_lock() which uses local_bh_disable() and preempt_disable() -on PREEMPT_RT. Since softirqs are processed always in thread context, -disabling preemption is enough to ensure that the current context won't -get interrupted by something that is using the VFP. Use it in -kernel_neon_begin(). - -Signed-off-by: Sebastian Andrzej Siewior ---- - arch/arm/vfp/vfpmodule.c | 32 ++++++++++++++++++++++++++++++-- - 1 file changed, 30 insertions(+), 2 deletions(-) - ---- a/arch/arm/vfp/vfpmodule.c -+++ b/arch/arm/vfp/vfpmodule.c -@@ -56,6 +56,34 @@ extern unsigned int VFP_arch_feroceon __ - union vfp_state *vfp_current_hw_state[NR_CPUS]; - - /* -+ * Claim ownership of the VFP unit. -+ * -+ * The caller may change VFP registers until vfp_unlock() is called. -+ * -+ * local_bh_disable() is used to disable preemption and to disable VFP -+ * processing in softirq context. On PREEMPT_RT kernels local_bh_disable() is -+ * not sufficient because it only serializes soft interrupt related sections -+ * via a local lock, but stays preemptible. Disabling preemption is the right -+ * choice here as bottom half processing is always in thread context on RT -+ * kernels so it implicitly prevents bottom half processing as well. -+ */ -+static void vfp_lock(void) -+{ -+ if (!IS_ENABLED(CONFIG_PREEMPT_RT)) -+ local_bh_disable(); -+ else -+ preempt_disable(); -+} -+ -+static void vfp_unlock(void) -+{ -+ if (!IS_ENABLED(CONFIG_PREEMPT_RT)) -+ local_bh_enable(); -+ else -+ preempt_enable(); -+} -+ -+/* - * Is 'thread's most up to date state stored in this CPUs hardware? - * Must be called from non-preemptible context. - */ -@@ -837,7 +865,7 @@ void kernel_neon_begin(void) - unsigned int cpu; - u32 fpexc; - -- local_bh_disable(); -+ vfp_lock(); - - /* - * Kernel mode NEON is only allowed outside of hardirq context with -@@ -868,7 +896,7 @@ void kernel_neon_end(void) - { - /* Disable the NEON/VFP unit. */ - fmxr(FPEXC, fmrx(FPEXC) & ~FPEXC_EN); -- local_bh_enable(); -+ vfp_unlock(); - } - EXPORT_SYMBOL(kernel_neon_end); - diff --git a/debian/patches-rt/0001-arm-Disable-jump-label-on-PREEMPT_RT.patch b/debian/patches-rt/0001-arm-Disable-jump-label-on-PREEMPT_RT.patch deleted file mode 100644 index 5492d1b..0000000 --- a/debian/patches-rt/0001-arm-Disable-jump-label-on-PREEMPT_RT.patch +++ /dev/null @@ -1,36 +0,0 @@ -From: Thomas Gleixner -Date: Wed, 8 Jul 2015 17:14:48 +0200 -Subject: [PATCH 1/2] arm: Disable jump-label on PREEMPT_RT. -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -jump-labels are used to efficiently switch between two possible code -paths. To achieve this, stop_machine() is used to keep the CPU in a -known state while the opcode is modified. The usage of stop_machine() -here leads to large latency spikes which can be observed on PREEMPT_RT. - -Jump labels may change the target during runtime and are not restricted -to debug or "configuration/ setup" part of a PREEMPT_RT system where -high latencies could be defined as acceptable. - -Disable jump-label support on a PREEMPT_RT system. - -[bigeasy: Patch description.] - -Signed-off-by: Thomas Gleixner -Signed-off-by: Sebastian Andrzej Siewior -Link: https://lkml.kernel.org/r/20220613182447.112191-2-bigeasy@linutronix.de ---- - arch/arm/Kconfig | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/arch/arm/Kconfig -+++ b/arch/arm/Kconfig -@@ -78,7 +78,7 @@ config ARM - select HAS_IOPORT - select HAVE_ARCH_AUDITSYSCALL if AEABI && !OABI_COMPAT - select HAVE_ARCH_BITREVERSE if (CPU_32v7M || CPU_32v7) && !CPU_32v6 -- select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL && !CPU_ENDIAN_BE32 && MMU -+ select HAVE_ARCH_JUMP_LABEL if !XIP_KERNEL && !CPU_ENDIAN_BE32 && MMU && !PREEMPT_RT - select HAVE_ARCH_KFENCE if MMU && !XIP_KERNEL - select HAVE_ARCH_KGDB if !CPU_ENDIAN_BE32 && MMU - select HAVE_ARCH_KASAN if MMU && !XIP_KERNEL diff --git a/debian/patches-rt/0001-drm-i915-Use-preempt_disable-enable_rt-where-recomme.patch b/debian/patches-rt/0001-drm-i915-Use-preempt_disable-enable_rt-where-recomme.patch deleted file mode 100644 index 21af06f..0000000 --- a/debian/patches-rt/0001-drm-i915-Use-preempt_disable-enable_rt-where-recomme.patch +++ /dev/null @@ -1,107 +0,0 @@ -From: Mike Galbraith -Date: Sat, 27 Feb 2016 08:09:11 +0100 -Subject: [PATCH 1/8] drm/i915: Use preempt_disable/enable_rt() where - recommended -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -Mario Kleiner suggest in commit - ad3543ede630f ("drm/intel: Push get_scanout_position() timestamping into kms driver.") - -a spots where preemption should be disabled on PREEMPT_RT. The -difference is that on PREEMPT_RT the intel_uncore::lock disables neither -preemption nor interrupts and so region remains preemptible. - -The area covers only register reads and writes. The part that worries me -is: -- __intel_get_crtc_scanline() the worst case is 100us if no match is - found. - -- intel_crtc_scanlines_since_frame_timestamp() not sure how long this - may take in the worst case. - -It was in the RT queue for a while and nobody complained. -Disable preemption on PREEPMPT_RT during timestamping. - -[bigeasy: patch description.] - -Cc: Mario Kleiner -Signed-off-by: Mike Galbraith -Signed-off-by: Thomas Gleixner -Signed-off-by: Sebastian Andrzej Siewior ---- - drivers/gpu/drm/i915/display/intel_vblank.c | 38 ++++++++++++++++++++-------- - 1 file changed, 28 insertions(+), 10 deletions(-) - ---- a/drivers/gpu/drm/i915/display/intel_vblank.c -+++ b/drivers/gpu/drm/i915/display/intel_vblank.c -@@ -303,6 +303,26 @@ int intel_crtc_scanline_to_hw(struct int - * all register accesses to the same cacheline to be serialized, - * otherwise they may hang. - */ -+static void intel_vblank_section_enter_irqsave(struct drm_i915_private *i915, unsigned long *flags) -+ __acquires(i915->uncore.lock) -+{ -+#ifdef I915 -+ spin_lock_irqsave(&i915->uncore.lock, *flags); -+#else -+ *flags = 0; -+#endif -+} -+ -+static void intel_vblank_section_exit_irqrestore(struct drm_i915_private *i915, unsigned long flags) -+ __releases(i915->uncore.lock) -+{ -+#ifdef I915 -+ spin_unlock_irqrestore(&i915->uncore.lock, flags); -+#else -+ if (flags) -+ return; -+#endif -+} - static void intel_vblank_section_enter(struct drm_i915_private *i915) - __acquires(i915->uncore.lock) - { -@@ -354,10 +374,10 @@ static bool i915_get_crtc_scanoutpos(str - * timing critical raw register reads, potentially with - * preemption disabled, so the following code must not block. - */ -- local_irq_save(irqflags); -- intel_vblank_section_enter(dev_priv); -+ intel_vblank_section_enter_irqsave(dev_priv, &irqflags); - -- /* preempt_disable_rt() should go right here in PREEMPT_RT patchset. */ -+ if (IS_ENABLED(CONFIG_PREEMPT_RT)) -+ preempt_disable(); - - /* Get optional system timestamp before query. */ - if (stime) -@@ -421,10 +441,10 @@ static bool i915_get_crtc_scanoutpos(str - if (etime) - *etime = ktime_get(); - -- /* preempt_enable_rt() should go right here in PREEMPT_RT patchset. */ -+ if (IS_ENABLED(CONFIG_PREEMPT_RT)) -+ preempt_enable(); - -- intel_vblank_section_exit(dev_priv); -- local_irq_restore(irqflags); -+ intel_vblank_section_exit_irqrestore(dev_priv, irqflags); - - /* - * While in vblank, position will be negative -@@ -462,13 +482,11 @@ int intel_get_crtc_scanline(struct intel - unsigned long irqflags; - int position; - -- local_irq_save(irqflags); -- intel_vblank_section_enter(dev_priv); -+ intel_vblank_section_enter_irqsave(dev_priv, &irqflags); - - position = __intel_get_crtc_scanline(crtc); - -- intel_vblank_section_exit(dev_priv); -- local_irq_restore(irqflags); -+ intel_vblank_section_exit_irqrestore(dev_priv, irqflags); - - return position; - } diff --git a/debian/patches-rt/0001-locking-rt-Add-sparse-annotation-PREEMPT_RT-s-sleepi.patch b/debian/patches-rt/0001-locking-rt-Add-sparse-annotation-PREEMPT_RT-s-sleepi.patch deleted file mode 100644 index 31f5d0a..0000000 --- a/debian/patches-rt/0001-locking-rt-Add-sparse-annotation-PREEMPT_RT-s-sleepi.patch +++ /dev/null @@ -1,58 +0,0 @@ -From: Sebastian Andrzej Siewior -Date: Mon, 12 Aug 2024 12:39:02 +0200 -Subject: [PATCH 1/4] locking/rt: Add sparse annotation PREEMPT_RT's sleeping - locks. -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -The sleeping locks on PREEMPT_RT (rt_spin_lock() and friends) lack -sparse annotation. Therefore a missing spin_unlock() won't be spotted by -sparse in a PREEMPT_RT build while it is noticed on a !PREEMPT_RT build. - -Add the __acquires/__releases macros to the lock/ unlock functions. The -trylock functions already use the __cond_lock() wrapper. - -Link: https://lore.kernel.org/r/20240812104200.2239232-2-bigeasy@linutronix.de -Signed-off-by: Sebastian Andrzej Siewior ---- - include/linux/rwlock_rt.h | 10 +++++----- - include/linux/spinlock_rt.h | 8 ++++---- - 2 files changed, 9 insertions(+), 9 deletions(-) - ---- a/include/linux/rwlock_rt.h -+++ b/include/linux/rwlock_rt.h -@@ -24,13 +24,13 @@ do { \ - __rt_rwlock_init(rwl, #rwl, &__key); \ - } while (0) - --extern void rt_read_lock(rwlock_t *rwlock); -+extern void rt_read_lock(rwlock_t *rwlock) __acquires(rwlock); - extern int rt_read_trylock(rwlock_t *rwlock); --extern void rt_read_unlock(rwlock_t *rwlock); --extern void rt_write_lock(rwlock_t *rwlock); --extern void rt_write_lock_nested(rwlock_t *rwlock, int subclass); -+extern void rt_read_unlock(rwlock_t *rwlock) __releases(rwlock); -+extern void rt_write_lock(rwlock_t *rwlock) __acquires(rwlock); -+extern void rt_write_lock_nested(rwlock_t *rwlock, int subclass) __acquires(rwlock); - extern int rt_write_trylock(rwlock_t *rwlock); --extern void rt_write_unlock(rwlock_t *rwlock); -+extern void rt_write_unlock(rwlock_t *rwlock) __releases(rwlock); - - static __always_inline void read_lock(rwlock_t *rwlock) - { ---- a/include/linux/spinlock_rt.h -+++ b/include/linux/spinlock_rt.h -@@ -32,10 +32,10 @@ do { \ - __rt_spin_lock_init(slock, #slock, &__key, true); \ - } while (0) - --extern void rt_spin_lock(spinlock_t *lock); --extern void rt_spin_lock_nested(spinlock_t *lock, int subclass); --extern void rt_spin_lock_nest_lock(spinlock_t *lock, struct lockdep_map *nest_lock); --extern void rt_spin_unlock(spinlock_t *lock); -+extern void rt_spin_lock(spinlock_t *lock) __acquires(lock); -+extern void rt_spin_lock_nested(spinlock_t *lock, int subclass) __acquires(lock); -+extern void rt_spin_lock_nest_lock(spinlock_t *lock, struct lockdep_map *nest_lock) __acquires(lock); -+extern void rt_spin_unlock(spinlock_t *lock) __releases(lock); - extern void rt_spin_lock_unlock(spinlock_t *lock); - extern int rt_spin_trylock_bh(spinlock_t *lock); - extern int rt_spin_trylock(spinlock_t *lock); diff --git a/debian/patches-rt/0001-printk-Add-notation-to-console_srcu-locking.patch b/debian/patches-rt/0001-printk-Add-notation-to-console_srcu-locking.patch deleted file mode 100644 index 4125829..0000000 --- a/debian/patches-rt/0001-printk-Add-notation-to-console_srcu-locking.patch +++ /dev/null @@ -1,39 +0,0 @@ -From: John Ogness -Date: Tue, 20 Aug 2024 08:35:27 +0206 -Subject: [PATCH 01/54] printk: Add notation to console_srcu locking -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -kernel/printk/printk.c:284:5: sparse: sparse: context imbalance in -'console_srcu_read_lock' - wrong count at exit -include/linux/srcu.h:301:9: sparse: sparse: context imbalance in -'console_srcu_read_unlock' - unexpected unlock - -Fixes: 6c4afa79147e ("printk: Prepare for SRCU console list protection") -Signed-off-by: John Ogness -Reviewed-by: Petr Mladek -Acked-by: Paul E. McKenney -Link: https://lore.kernel.org/r/20240820063001.36405-2-john.ogness@linutronix.de -Signed-off-by: Petr Mladek -Signed-off-by: Sebastian Andrzej Siewior ---- - kernel/printk/printk.c | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/kernel/printk/printk.c -+++ b/kernel/printk/printk.c -@@ -282,6 +282,7 @@ EXPORT_SYMBOL(console_list_unlock); - * Return: A cookie to pass to console_srcu_read_unlock(). - */ - int console_srcu_read_lock(void) -+ __acquires(&console_srcu) - { - return srcu_read_lock_nmisafe(&console_srcu); - } -@@ -295,6 +296,7 @@ EXPORT_SYMBOL(console_srcu_read_lock); - * Counterpart to console_srcu_read_lock() - */ - void console_srcu_read_unlock(int cookie) -+ __releases(&console_srcu) - { - srcu_read_unlock_nmisafe(&console_srcu, cookie); - } diff --git a/debian/patches-rt/0001-sched-core-Provide-a-method-to-check-if-a-task-is-PI.patch b/debian/patches-rt/0001-sched-core-Provide-a-method-to-check-if-a-task-is-PI.patch deleted file mode 100644 index d87e539..0000000 --- a/debian/patches-rt/0001-sched-core-Provide-a-method-to-check-if-a-task-is-PI.patch +++ /dev/null @@ -1,54 +0,0 @@ -From: Sebastian Andrzej Siewior -Date: Fri, 4 Aug 2023 13:30:37 +0200 -Subject: [PATCH 1/3] sched/core: Provide a method to check if a task is - PI-boosted. -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -Provide a method to check if a task inherited the priority from another -task. This happens if a task owns a lock which is requested by a task -with higher priority. This can be used as a hint to add a preemption -point to the critical section. - -Provide a function which reports true if the task is PI-boosted. - -Link: https://lore.kernel.org/r/20230804113039.419794-2-bigeasy@linutronix.de -Signed-off-by: Sebastian Andrzej Siewior ---- - include/linux/sched.h | 1 + - kernel/sched/core.c | 15 +++++++++++++++ - 2 files changed, 16 insertions(+) - ---- a/include/linux/sched.h -+++ b/include/linux/sched.h -@@ -1814,6 +1814,7 @@ static inline int dl_task_check_affinity - } - #endif - -+extern bool task_is_pi_boosted(const struct task_struct *p); - extern int yield_to(struct task_struct *p, bool preempt); - extern void set_user_nice(struct task_struct *p, long nice); - extern int task_prio(const struct task_struct *p); ---- a/kernel/sched/core.c -+++ b/kernel/sched/core.c -@@ -7362,6 +7362,21 @@ static inline void preempt_dynamic_init( - - #endif /* CONFIG_PREEMPT_DYNAMIC */ - -+/* -+ * task_is_pi_boosted - Check if task has been PI boosted. -+ * @p: Task to check. -+ * -+ * Return true if task is subject to priority inheritance. -+ */ -+bool task_is_pi_boosted(const struct task_struct *p) -+{ -+ int prio = p->prio; -+ -+ if (!rt_prio(prio)) -+ return false; -+ return prio != p->normal_prio; -+} -+ - int io_schedule_prepare(void) - { - int old_iowait = current->in_iowait; diff --git a/debian/patches-rt/0001-timers-Add-sparse-annotation-for-timer_sync_wait_run.patch b/debian/patches-rt/0001-timers-Add-sparse-annotation-for-timer_sync_wait_run.patch deleted file mode 100644 index db7c5c7..0000000 --- a/debian/patches-rt/0001-timers-Add-sparse-annotation-for-timer_sync_wait_run.patch +++ /dev/null @@ -1,29 +0,0 @@ -From: Sebastian Andrzej Siewior -Date: Mon, 12 Aug 2024 12:51:04 +0200 -Subject: [PATCH 1/2] timers: Add sparse annotation for - timer_sync_wait_running(). -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -timer_sync_wait_running() first releases two locks and then acquires -them again. This is unexpected and sparse complains about it. - -Add sparse annotation for timer_sync_wait_running() to note that the -locking is expected. - -Link: https://lore.kernel.org/r/20240812105326.2240000-2-bigeasy@linutronix.de -Signed-off-by: Sebastian Andrzej Siewior ---- - kernel/time/timer.c | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/kernel/time/timer.c -+++ b/kernel/time/timer.c -@@ -1561,6 +1561,8 @@ static inline void timer_base_unlock_exp - * the waiter to acquire the lock and make progress. - */ - static void timer_sync_wait_running(struct timer_base *base) -+ __releases(&base->lock) __releases(&base->expiry_lock) -+ __acquires(&base->expiry_lock) __acquires(&base->lock) - { - if (atomic_read(&base->timer_waiters)) { - raw_spin_unlock_irq(&base->lock); diff --git a/debian/patches-rt/0001-zram-Replace-bit-spinlocks-with-a-spinlock_t.patch b/debian/patches-rt/0001-zram-Replace-bit-spinlocks-with-a-spinlock_t.patch deleted file mode 100644 index 7644b4e..0000000 --- a/debian/patches-rt/0001-zram-Replace-bit-spinlocks-with-a-spinlock_t.patch +++ /dev/null @@ -1,83 +0,0 @@ -From: Mike Galbraith -Date: Thu, 31 Mar 2016 04:08:28 +0200 -Subject: [PATCH 1/3] zram: Replace bit spinlocks with a spinlock_t. -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -The bit spinlock disables preemption. The spinlock_t lock becomes a sleeping -lock on PREEMPT_RT and it can not be acquired in this context. In this locked -section, zs_free() acquires a zs_pool::lock, and there is access to -zram::wb_limit_lock. - -Add a spinlock_t for locking. Keep the set/ clear ZRAM_LOCK bit after -the lock has been acquired/ dropped. The size of struct zram_table_entry -increases by 4 bytes due to lock and additional 4 bytes padding with -CONFIG_ZRAM_TRACK_ENTRY_ACTIME enabled. - -Signed-off-by: Mike Galbraith -Reviewed-by: Sergey Senozhatsky -Signed-off-by: Sebastian Andrzej Siewior -Link: https://lore.kernel.org/20240906141520.730009-2-bigeasy@linutronix.de ---- - drivers/block/zram/zram_drv.c | 18 ++++++++++++++---- - drivers/block/zram/zram_drv.h | 1 + - 2 files changed, 15 insertions(+), 4 deletions(-) - ---- a/drivers/block/zram/zram_drv.c -+++ b/drivers/block/zram/zram_drv.c -@@ -59,17 +59,24 @@ static int zram_read_page(struct zram *z - - static int zram_slot_trylock(struct zram *zram, u32 index) - { -- return bit_spin_trylock(ZRAM_LOCK, &zram->table[index].flags); -+ int ret; -+ -+ ret = spin_trylock(&zram->table[index].lock); -+ if (ret) -+ __set_bit(ZRAM_LOCK, &zram->table[index].flags); -+ return ret; - } - - static void zram_slot_lock(struct zram *zram, u32 index) - { -- bit_spin_lock(ZRAM_LOCK, &zram->table[index].flags); -+ spin_lock(&zram->table[index].lock); -+ __set_bit(ZRAM_LOCK, &zram->table[index].flags); - } - - static void zram_slot_unlock(struct zram *zram, u32 index) - { -- bit_spin_unlock(ZRAM_LOCK, &zram->table[index].flags); -+ __clear_bit(ZRAM_LOCK, &zram->table[index].flags); -+ spin_unlock(&zram->table[index].lock); - } - - static inline bool init_done(struct zram *zram) -@@ -1211,7 +1218,7 @@ static void zram_meta_free(struct zram * - - static bool zram_meta_alloc(struct zram *zram, u64 disksize) - { -- size_t num_pages; -+ size_t num_pages, index; - - num_pages = disksize >> PAGE_SHIFT; - zram->table = vzalloc(array_size(num_pages, sizeof(*zram->table))); -@@ -1226,6 +1233,9 @@ static bool zram_meta_alloc(struct zram - - if (!huge_class_size) - huge_class_size = zs_huge_class_size(zram->mem_pool); -+ -+ for (index = 0; index < num_pages; index++) -+ spin_lock_init(&zram->table[index].lock); - return true; - } - ---- a/drivers/block/zram/zram_drv.h -+++ b/drivers/block/zram/zram_drv.h -@@ -69,6 +69,7 @@ struct zram_table_entry { - unsigned long element; - }; - unsigned long flags; -+ spinlock_t lock; - #ifdef CONFIG_ZRAM_TRACK_ENTRY_ACTIME - ktime_t ac_time; - #endif diff --git a/debian/patches-rt/0002-ARM-vfp-Use-vfp_lock-in-vfp_sync_hwstate.patch b/debian/patches-rt/0002-ARM-vfp-Use-vfp_lock-in-vfp_sync_hwstate.patch deleted file mode 100644 index 5d1d403..0000000 --- a/debian/patches-rt/0002-ARM-vfp-Use-vfp_lock-in-vfp_sync_hwstate.patch +++ /dev/null @@ -1,44 +0,0 @@ -From: Sebastian Andrzej Siewior -Date: Fri, 19 May 2023 16:57:30 +0200 -Subject: [PATCH 2/4] ARM: vfp: Use vfp_lock() in vfp_sync_hwstate(). -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -vfp_sync_hwstate() uses preempt_disable() followed by local_bh_disable() -to ensure that it won't get interrupted while checking the VFP state. -This harms PREEMPT_RT because softirq handling can get preempted and -local_bh_disable() synchronizes the related section with a sleeping lock -which does not work with disabled preemption. - -Use the vfp_lock() to synchronize the access. - -Signed-off-by: Sebastian Andrzej Siewior ---- - arch/arm/vfp/vfpmodule.c | 9 +++------ - 1 file changed, 3 insertions(+), 6 deletions(-) - ---- a/arch/arm/vfp/vfpmodule.c -+++ b/arch/arm/vfp/vfpmodule.c -@@ -540,11 +540,9 @@ static inline void vfp_pm_init(void) { } - */ - void vfp_sync_hwstate(struct thread_info *thread) - { -- unsigned int cpu = get_cpu(); -+ vfp_lock(); - -- local_bh_disable(); -- -- if (vfp_state_in_hw(cpu, thread)) { -+ if (vfp_state_in_hw(raw_smp_processor_id(), thread)) { - u32 fpexc = fmrx(FPEXC); - - /* -@@ -555,8 +553,7 @@ void vfp_sync_hwstate(struct thread_info - fmxr(FPEXC, fpexc); - } - -- local_bh_enable(); -- put_cpu(); -+ vfp_unlock(); - } - - /* Ensure that the thread reloads the hardware VFP state on the next use. */ diff --git a/debian/patches-rt/0002-drm-i915-Don-t-disable-interrupts-on-PREEMPT_RT-duri.patch b/debian/patches-rt/0002-drm-i915-Don-t-disable-interrupts-on-PREEMPT_RT-duri.patch deleted file mode 100644 index c7daec3..0000000 --- a/debian/patches-rt/0002-drm-i915-Don-t-disable-interrupts-on-PREEMPT_RT-duri.patch +++ /dev/null @@ -1,119 +0,0 @@ -From: Mike Galbraith -Date: Sat, 27 Feb 2016 09:01:42 +0100 -Subject: [PATCH 2/8] drm/i915: Don't disable interrupts on PREEMPT_RT during - atomic updates -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -Commit - 8d7849db3eab7 ("drm/i915: Make sprite updates atomic") - -started disabling interrupts across atomic updates. This breaks on PREEMPT_RT -because within this section the code attempt to acquire spinlock_t locks which -are sleeping locks on PREEMPT_RT. - -According to the comment the interrupts are disabled to avoid random delays and -not required for protection or synchronisation. -If this needs to happen with disabled interrupts on PREEMPT_RT, and the -whole section is restricted to register access then all sleeping locks -need to be acquired before interrupts are disabled and some function -maybe moved after enabling interrupts again. -This includes: -- prepare_to_wait() + finish_wait() due its wake queue. -- drm_crtc_vblank_put() -> vblank_disable_fn() drm_device::vbl_lock. -- skl_pfit_enable(), intel_update_plane(), vlv_atomic_update_fifo() and - maybe others due to intel_uncore::lock -- drm_crtc_arm_vblank_event() due to drm_device::event_lock and - drm_device::vblank_time_lock. - -Don't disable interrupts on PREEMPT_RT during atomic updates. - -[bigeasy: drop local locks, commit message] - -Signed-off-by: Mike Galbraith -Signed-off-by: Sebastian Andrzej Siewior ---- - drivers/gpu/drm/i915/display/intel_crtc.c | 9 ++++++--- - drivers/gpu/drm/i915/display/intel_cursor.c | 9 ++++++--- - drivers/gpu/drm/i915/display/intel_vblank.c | 6 ++++-- - 3 files changed, 16 insertions(+), 8 deletions(-) - ---- a/drivers/gpu/drm/i915/display/intel_crtc.c -+++ b/drivers/gpu/drm/i915/display/intel_crtc.c -@@ -521,7 +521,8 @@ void intel_pipe_update_start(struct inte - */ - intel_psr_wait_for_idle_locked(new_crtc_state); - -- local_irq_disable(); -+ if (!IS_ENABLED(CONFIG_PREEMPT_RT)) -+ local_irq_disable(); - - crtc->debug.min_vbl = evade.min; - crtc->debug.max_vbl = evade.max; -@@ -539,7 +540,8 @@ void intel_pipe_update_start(struct inte - return; - - irq_disable: -- local_irq_disable(); -+ if (!IS_ENABLED(CONFIG_PREEMPT_RT)) -+ local_irq_disable(); - } - - #if IS_ENABLED(CONFIG_DRM_I915_DEBUG_VBLANK_EVADE) -@@ -668,7 +670,8 @@ void intel_pipe_update_end(struct intel_ - */ - intel_vrr_send_push(new_crtc_state); - -- local_irq_enable(); -+ if (!IS_ENABLED(CONFIG_PREEMPT_RT)) -+ local_irq_enable(); - - if (intel_vgpu_active(dev_priv)) - goto out; ---- a/drivers/gpu/drm/i915/display/intel_cursor.c -+++ b/drivers/gpu/drm/i915/display/intel_cursor.c -@@ -895,13 +895,15 @@ intel_legacy_cursor_update(struct drm_pl - */ - intel_psr_wait_for_idle_locked(crtc_state); - -- local_irq_disable(); -+ if (!IS_ENABLED(CONFIG_PREEMPT_RT)) -+ local_irq_disable(); - - intel_vblank_evade(&evade); - - drm_crtc_vblank_put(&crtc->base); - } else { -- local_irq_disable(); -+ if (!IS_ENABLED(CONFIG_PREEMPT_RT)) -+ local_irq_disable(); - } - - if (new_plane_state->uapi.visible) { -@@ -911,7 +913,8 @@ intel_legacy_cursor_update(struct drm_pl - intel_plane_disable_arm(plane, crtc_state); - } - -- local_irq_enable(); -+ if (!IS_ENABLED(CONFIG_PREEMPT_RT)) -+ local_irq_enable(); - - intel_psr_unlock(crtc_state); - ---- a/drivers/gpu/drm/i915/display/intel_vblank.c -+++ b/drivers/gpu/drm/i915/display/intel_vblank.c -@@ -705,11 +705,13 @@ int intel_vblank_evade(struct intel_vbla - break; - } - -- local_irq_enable(); -+ if (!IS_ENABLED(CONFIG_PREEMPT_RT)) -+ local_irq_enable(); - - timeout = schedule_timeout(timeout); - -- local_irq_disable(); -+ if (!IS_ENABLED(CONFIG_PREEMPT_RT)) -+ local_irq_disable(); - } - - finish_wait(wq, &wait); diff --git a/debian/patches-rt/0002-hrtimer-Annotate-hrtimer_cpu_base_.-_expiry-for-spar.patch b/debian/patches-rt/0002-hrtimer-Annotate-hrtimer_cpu_base_.-_expiry-for-spar.patch deleted file mode 100644 index 5069838..0000000 --- a/debian/patches-rt/0002-hrtimer-Annotate-hrtimer_cpu_base_.-_expiry-for-spar.patch +++ /dev/null @@ -1,33 +0,0 @@ -From: Sebastian Andrzej Siewior -Date: Mon, 12 Aug 2024 12:51:05 +0200 -Subject: [PATCH 2/2] hrtimer: Annotate hrtimer_cpu_base_.*_expiry() for - sparse. -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -The two hrtimer_cpu_base_.*_expiry() functions are wrapper around the -locking functions and sparse complains about the missing counterpart. - -Add sparse annotation to denote that this bevaviour is expected. - -Link: https://lore.kernel.org/r/20240812105326.2240000-3-bigeasy@linutronix.de -Signed-off-by: Sebastian Andrzej Siewior ---- - kernel/time/hrtimer.c | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/kernel/time/hrtimer.c -+++ b/kernel/time/hrtimer.c -@@ -1351,11 +1351,13 @@ static void hrtimer_cpu_base_init_expiry - } - - static void hrtimer_cpu_base_lock_expiry(struct hrtimer_cpu_base *base) -+ __acquires(&base->softirq_expiry_lock) - { - spin_lock(&base->softirq_expiry_lock); - } - - static void hrtimer_cpu_base_unlock_expiry(struct hrtimer_cpu_base *base) -+ __releases(&base->softirq_expiry_lock) - { - spin_unlock(&base->softirq_expiry_lock); - } diff --git a/debian/patches-rt/0002-locking-rt-Remove-one-__cond_lock-in-RT-s-spin_trylo.patch b/debian/patches-rt/0002-locking-rt-Remove-one-__cond_lock-in-RT-s-spin_trylo.patch deleted file mode 100644 index 2be0aa0..0000000 --- a/debian/patches-rt/0002-locking-rt-Remove-one-__cond_lock-in-RT-s-spin_trylo.patch +++ /dev/null @@ -1,44 +0,0 @@ -From: Sebastian Andrzej Siewior -Date: Mon, 12 Aug 2024 12:39:03 +0200 -Subject: [PATCH 2/4] locking/rt: Remove one __cond_lock() in RT's - spin_trylock_irqsave() -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -spin_trylock_irqsave() has a __cond_lock() wrapper which points to -__spin_trylock_irqsave(). The function then invokes spin_trylock() which -has another __cond_lock() finally pointing to rt_spin_trylock(). - -The compiler has no problem to parse this but sparse does not recognise -that users of spin_trylock_irqsave() acquire a conditional lock and -complains. - -Remove one layer of __cond_lock() so that sparse recognises conditional -locking. - -Link: https://lore.kernel.org/r/20240812104200.2239232-3-bigeasy@linutronix.de -Signed-off-by: Sebastian Andrzej Siewior ---- - include/linux/spinlock_rt.h | 5 +---- - 1 file changed, 1 insertion(+), 4 deletions(-) - ---- a/include/linux/spinlock_rt.h -+++ b/include/linux/spinlock_rt.h -@@ -132,7 +132,7 @@ static __always_inline void spin_unlock_ - #define spin_trylock_irq(lock) \ - __cond_lock(lock, rt_spin_trylock(lock)) - --#define __spin_trylock_irqsave(lock, flags) \ -+#define spin_trylock_irqsave(lock, flags) \ - ({ \ - int __locked; \ - \ -@@ -142,9 +142,6 @@ static __always_inline void spin_unlock_ - __locked; \ - }) - --#define spin_trylock_irqsave(lock, flags) \ -- __cond_lock(lock, __spin_trylock_irqsave(lock, flags)) -- - #define spin_is_contended(lock) (((void)(lock), 0)) - - static inline int spin_is_locked(spinlock_t *lock) diff --git a/debian/patches-rt/0002-printk-nbcon-Consolidate-alloc-and-init.patch b/debian/patches-rt/0002-printk-nbcon-Consolidate-alloc-and-init.patch deleted file mode 100644 index ecc003b..0000000 --- a/debian/patches-rt/0002-printk-nbcon-Consolidate-alloc-and-init.patch +++ /dev/null @@ -1,109 +0,0 @@ -From: John Ogness -Date: Tue, 20 Aug 2024 08:35:28 +0206 -Subject: [PATCH 02/54] printk: nbcon: Consolidate alloc() and init() -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -Rather than splitting the nbcon allocation and initialization into -two pieces, perform all initialization in nbcon_alloc(). Later, -the initial sequence is calculated and can be explicitly set using -nbcon_seq_force(). This removes the need for the strong rules of -nbcon_init() that even included a BUG_ON(). - -Signed-off-by: John Ogness -Reviewed-by: Petr Mladek -Link: https://lore.kernel.org/r/20240820063001.36405-3-john.ogness@linutronix.de -Signed-off-by: Petr Mladek -Signed-off-by: Sebastian Andrzej Siewior ---- - kernel/printk/internal.h | 2 -- - kernel/printk/nbcon.c | 37 +++++++++++-------------------------- - kernel/printk/printk.c | 2 +- - 3 files changed, 12 insertions(+), 29 deletions(-) - ---- a/kernel/printk/internal.h -+++ b/kernel/printk/internal.h -@@ -75,7 +75,6 @@ u16 printk_parse_prefix(const char *text - u64 nbcon_seq_read(struct console *con); - void nbcon_seq_force(struct console *con, u64 seq); - bool nbcon_alloc(struct console *con); --void nbcon_init(struct console *con); - void nbcon_free(struct console *con); - - #else -@@ -96,7 +95,6 @@ static inline bool printk_percpu_data_re - static inline u64 nbcon_seq_read(struct console *con) { return 0; } - static inline void nbcon_seq_force(struct console *con, u64 seq) { } - static inline bool nbcon_alloc(struct console *con) { return false; } --static inline void nbcon_init(struct console *con) { } - static inline void nbcon_free(struct console *con) { } - - #endif /* CONFIG_PRINTK */ ---- a/kernel/printk/nbcon.c -+++ b/kernel/printk/nbcon.c -@@ -929,17 +929,22 @@ static bool nbcon_emit_next_record(struc - } - - /** -- * nbcon_alloc - Allocate buffers needed by the nbcon console -- * @con: Console to allocate buffers for -+ * nbcon_alloc - Allocate and init the nbcon console specific data -+ * @con: Console to initialize - * -- * Return: True on success. False otherwise and the console cannot -- * be used. -+ * Return: True if the console was fully allocated and initialized. -+ * Otherwise @con must not be registered. - * -- * This is not part of nbcon_init() because buffer allocation must -- * be performed earlier in the console registration process. -+ * When allocation and init was successful, the console must be properly -+ * freed using nbcon_free() once it is no longer needed. - */ - bool nbcon_alloc(struct console *con) - { -+ struct nbcon_state state = { }; -+ -+ nbcon_state_set(con, &state); -+ atomic_long_set(&ACCESS_PRIVATE(con, nbcon_seq), 0); -+ - if (con->flags & CON_BOOT) { - /* - * Boot console printing is synchronized with legacy console -@@ -959,26 +964,6 @@ bool nbcon_alloc(struct console *con) - } - - /** -- * nbcon_init - Initialize the nbcon console specific data -- * @con: Console to initialize -- * -- * nbcon_alloc() *must* be called and succeed before this function -- * is called. -- * -- * This function expects that the legacy @con->seq has been set. -- */ --void nbcon_init(struct console *con) --{ -- struct nbcon_state state = { }; -- -- /* nbcon_alloc() must have been called and successful! */ -- BUG_ON(!con->pbufs); -- -- nbcon_seq_force(con, con->seq); -- nbcon_state_set(con, &state); --} -- --/** - * nbcon_free - Free and cleanup the nbcon console specific data - * @con: Console to free/cleanup nbcon data - */ ---- a/kernel/printk/printk.c -+++ b/kernel/printk/printk.c -@@ -3619,7 +3619,7 @@ void register_console(struct console *ne - console_init_seq(newcon, bootcon_registered); - - if (newcon->flags & CON_NBCON) -- nbcon_init(newcon); -+ nbcon_seq_force(newcon, newcon->seq); - - /* - * Put this console in the list - keep the diff --git a/debian/patches-rt/0002-softirq-Add-function-to-preempt-serving-softirqs.patch b/debian/patches-rt/0002-softirq-Add-function-to-preempt-serving-softirqs.patch deleted file mode 100644 index bbea75a..0000000 --- a/debian/patches-rt/0002-softirq-Add-function-to-preempt-serving-softirqs.patch +++ /dev/null @@ -1,60 +0,0 @@ -From: Sebastian Andrzej Siewior -Date: Fri, 4 Aug 2023 13:30:38 +0200 -Subject: [PATCH 2/3] softirq: Add function to preempt serving softirqs. -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -Add a functionality for the softirq handler to preempt its current work -if needed. The softirq core has no particular state. It reads and resets -the pending softirq bits and then processes one after the other. -It can already be preempted while it invokes a certain softirq handler. - -By enabling the BH the softirq core releases the per-CPU bh lock which -serializes all softirq handler. It is safe to do as long as the code -does not expect any serialisation in between. A typical scenarion would -after the invocation of callback where no state needs to be preserved -before the next callback is invoked. - -Add functionaliry to preempt the serving softirqs. - -Link: https://lore.kernel.org/r/20230804113039.419794-3-bigeasy@linutronix.de -Signed-off-by: Sebastian Andrzej Siewior ---- - include/linux/bottom_half.h | 2 ++ - kernel/softirq.c | 13 +++++++++++++ - 2 files changed, 15 insertions(+) - ---- a/include/linux/bottom_half.h -+++ b/include/linux/bottom_half.h -@@ -35,8 +35,10 @@ static inline void local_bh_enable(void) - - #ifdef CONFIG_PREEMPT_RT - extern bool local_bh_blocked(void); -+extern void softirq_preempt(void); - #else - static inline bool local_bh_blocked(void) { return false; } -+static inline void softirq_preempt(void) { } - #endif - - #endif /* _LINUX_BH_H */ ---- a/kernel/softirq.c -+++ b/kernel/softirq.c -@@ -248,6 +248,19 @@ void __local_bh_enable_ip(unsigned long - } - EXPORT_SYMBOL(__local_bh_enable_ip); - -+void softirq_preempt(void) -+{ -+ if (WARN_ON_ONCE(!preemptible())) -+ return; -+ -+ if (WARN_ON_ONCE(__this_cpu_read(softirq_ctrl.cnt) != SOFTIRQ_OFFSET)) -+ return; -+ -+ __local_bh_enable(SOFTIRQ_OFFSET, true); -+ /* preemption point */ -+ __local_bh_disable_ip(_RET_IP_, SOFTIRQ_OFFSET); -+} -+ - /* - * Invoked from ksoftirqd_run() outside of the interrupt disabled section - * to acquire the per CPU local lock for reentrancy protection. diff --git a/debian/patches-rt/0002-zram-Remove-ZRAM_LOCK.patch b/debian/patches-rt/0002-zram-Remove-ZRAM_LOCK.patch deleted file mode 100644 index 2c0ef6c..0000000 --- a/debian/patches-rt/0002-zram-Remove-ZRAM_LOCK.patch +++ /dev/null @@ -1,67 +0,0 @@ -From: Sebastian Andrzej Siewior -Date: Thu, 20 Jun 2024 12:27:11 +0200 -Subject: [PATCH 2/3] zram: Remove ZRAM_LOCK -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -The ZRAM_LOCK was used for locking and after the addition of spinlock_t -the bit set and cleared but there no reader of it. - -Remove the ZRAM_LOCK bit. - -Reviewed-by: Sergey Senozhatsky -Signed-off-by: Sebastian Andrzej Siewior -Link: https://lore.kernel.org/20240906141520.730009-3-bigeasy@linutronix.de ---- - drivers/block/zram/zram_drv.c | 11 ++--------- - drivers/block/zram/zram_drv.h | 4 +--- - 2 files changed, 3 insertions(+), 12 deletions(-) - ---- a/drivers/block/zram/zram_drv.c -+++ b/drivers/block/zram/zram_drv.c -@@ -59,23 +59,16 @@ static int zram_read_page(struct zram *z - - static int zram_slot_trylock(struct zram *zram, u32 index) - { -- int ret; -- -- ret = spin_trylock(&zram->table[index].lock); -- if (ret) -- __set_bit(ZRAM_LOCK, &zram->table[index].flags); -- return ret; -+ return spin_trylock(&zram->table[index].lock); - } - - static void zram_slot_lock(struct zram *zram, u32 index) - { - spin_lock(&zram->table[index].lock); -- __set_bit(ZRAM_LOCK, &zram->table[index].flags); - } - - static void zram_slot_unlock(struct zram *zram, u32 index) - { -- __clear_bit(ZRAM_LOCK, &zram->table[index].flags); - spin_unlock(&zram->table[index].lock); - } - -@@ -1293,7 +1286,7 @@ static void zram_free_page(struct zram * - zram_set_handle(zram, index, 0); - zram_set_obj_size(zram, index, 0); - WARN_ON_ONCE(zram->table[index].flags & -- ~(1UL << ZRAM_LOCK | 1UL << ZRAM_UNDER_WB)); -+ ~(1UL << ZRAM_UNDER_WB)); - } - - /* ---- a/drivers/block/zram/zram_drv.h -+++ b/drivers/block/zram/zram_drv.h -@@ -45,9 +45,7 @@ - - /* Flags for zram pages (table[page_no].flags) */ - enum zram_pageflags { -- /* zram slot is locked */ -- ZRAM_LOCK = ZRAM_FLAG_SHIFT, -- ZRAM_SAME, /* Page consists the same element */ -+ ZRAM_SAME = ZRAM_FLAG_SHIFT, /* Page consists the same element */ - ZRAM_WB, /* page is stored on backing_device */ - ZRAM_UNDER_WB, /* page is under writeback */ - ZRAM_HUGE, /* Incompressible page */ diff --git a/debian/patches-rt/0003-ARM-vfp-Use-vfp_lock-in-vfp_support_entry.patch b/debian/patches-rt/0003-ARM-vfp-Use-vfp_lock-in-vfp_support_entry.patch deleted file mode 100644 index 284534e..0000000 --- a/debian/patches-rt/0003-ARM-vfp-Use-vfp_lock-in-vfp_support_entry.patch +++ /dev/null @@ -1,48 +0,0 @@ -From: Sebastian Andrzej Siewior -Date: Wed, 28 Jun 2023 09:36:10 +0200 -Subject: [PATCH 3/4] ARM: vfp: Use vfp_lock() in vfp_support_entry(). -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -vfp_entry() is invoked from exception handler and is fully preemptible. -It uses local_bh_disable() to remain uninterrupted while checking the -VFP state. -This is not working on PREEMPT_RT because local_bh_disable() -synchronizes the relevant section but the context remains fully -preemptible. - -Use vfp_lock() for uninterrupted access. - -Signed-off-by: Sebastian Andrzej Siewior ---- - arch/arm/vfp/vfpmodule.c | 6 +++--- - 1 file changed, 3 insertions(+), 3 deletions(-) - ---- a/arch/arm/vfp/vfpmodule.c -+++ b/arch/arm/vfp/vfpmodule.c -@@ -708,7 +708,7 @@ static int vfp_support_entry(struct pt_r - if (!user_mode(regs)) - return vfp_kmode_exception(regs, trigger); - -- local_bh_disable(); -+ vfp_lock(); - fpexc = fmrx(FPEXC); - - /* -@@ -787,7 +787,7 @@ static int vfp_support_entry(struct pt_r - if (!(fpscr & FPSCR_IXE)) { - if (!(fpscr & FPSCR_LENGTH_MASK)) { - pr_debug("not VFP\n"); -- local_bh_enable(); -+ vfp_unlock(); - return -ENOEXEC; - } - fpexc |= FPEXC_DEX; -@@ -797,7 +797,7 @@ bounce: regs->ARM_pc += 4; - VFP_bounce(trigger, fpexc, regs); - } - -- local_bh_enable(); -+ vfp_unlock(); - return 0; - } - diff --git a/debian/patches-rt/0003-drm-i915-Don-t-check-for-atomic-context-on-PREEMPT_R.patch b/debian/patches-rt/0003-drm-i915-Don-t-check-for-atomic-context-on-PREEMPT_R.patch deleted file mode 100644 index 580610b..0000000 --- a/debian/patches-rt/0003-drm-i915-Don-t-check-for-atomic-context-on-PREEMPT_R.patch +++ /dev/null @@ -1,39 +0,0 @@ -From: Sebastian Andrzej Siewior -Date: Mon, 25 Oct 2021 15:05:18 +0200 -Subject: [PATCH 3/8] drm/i915: Don't check for atomic context on PREEMPT_RT -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -The !in_atomic() check in _wait_for_atomic() triggers on PREEMPT_RT -because the uncore::lock is a spinlock_t and does not disable -preemption or interrupts. - -Changing the uncore:lock to a raw_spinlock_t doubles the worst case -latency on an otherwise idle testbox during testing. - -Ignore _WAIT_FOR_ATOMIC_CHECK() on PREEMPT_RT. - -Reviewed-by: Tvrtko Ursulin -Link: https://lore.kernel.org/all/20211006164628.s2mtsdd2jdbfyf7g@linutronix.de/ -Signed-off-by: Sebastian Andrzej Siewior ---- - drivers/gpu/drm/i915/i915_utils.h | 9 +++++++-- - 1 file changed, 7 insertions(+), 2 deletions(-) - ---- a/drivers/gpu/drm/i915/i915_utils.h -+++ b/drivers/gpu/drm/i915/i915_utils.h -@@ -273,8 +273,13 @@ wait_remaining_ms_from_jiffies(unsigned - (Wmax)) - #define wait_for(COND, MS) _wait_for((COND), (MS) * 1000, 10, 1000) - --/* If CONFIG_PREEMPT_COUNT is disabled, in_atomic() always reports false. */ --#if defined(CONFIG_DRM_I915_DEBUG) && defined(CONFIG_PREEMPT_COUNT) -+/* -+ * If CONFIG_PREEMPT_COUNT is disabled, in_atomic() always reports false. -+ * On PREEMPT_RT the context isn't becoming atomic because it is used in an -+ * interrupt handler or because a spinlock_t is acquired. This leads to -+ * warnings which don't occur otherwise and therefore the check is disabled. -+ */ -+#if defined(CONFIG_DRM_I915_DEBUG) && defined(CONFIG_PREEMPT_COUNT) && !defined(CONFIG_PREEMPT_RT) - # define _WAIT_FOR_ATOMIC_CHECK(ATOMIC) WARN_ON_ONCE((ATOMIC) && !in_atomic()) - #else - # define _WAIT_FOR_ATOMIC_CHECK(ATOMIC) do { } while (0) diff --git a/debian/patches-rt/0003-locking-rt-Add-sparse-annotation-for-RCU.patch b/debian/patches-rt/0003-locking-rt-Add-sparse-annotation-for-RCU.patch deleted file mode 100644 index 47874ca..0000000 --- a/debian/patches-rt/0003-locking-rt-Add-sparse-annotation-for-RCU.patch +++ /dev/null @@ -1,84 +0,0 @@ -From: Sebastian Andrzej Siewior -Date: Mon, 12 Aug 2024 12:39:04 +0200 -Subject: [PATCH 3/4] locking/rt: Add sparse annotation for RCU. -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -Every lock, that becomes a sleeping on PREEMPT_RT, starts a RCU read -section. There is no sparse annotation for this and sparse complains -about unbalanced locking. - -Add __acquires/ __releases for the RCU lock. This covers all but the -trylock functions. I tried the __cond_acquires() annotation but it -didn't work. - -Link: https://lore.kernel.org/r/20240812104200.2239232-4-bigeasy@linutronix.de -Signed-off-by: Sebastian Andrzej Siewior ---- - kernel/locking/spinlock_rt.c | 14 +++++++------- - 1 file changed, 7 insertions(+), 7 deletions(-) - ---- a/kernel/locking/spinlock_rt.c -+++ b/kernel/locking/spinlock_rt.c -@@ -51,7 +51,7 @@ static __always_inline void __rt_spin_lo - migrate_disable(); - } - --void __sched rt_spin_lock(spinlock_t *lock) -+void __sched rt_spin_lock(spinlock_t *lock) __acquires(RCU) - { - spin_acquire(&lock->dep_map, 0, 0, _RET_IP_); - __rt_spin_lock(lock); -@@ -75,7 +75,7 @@ void __sched rt_spin_lock_nest_lock(spin - EXPORT_SYMBOL(rt_spin_lock_nest_lock); - #endif - --void __sched rt_spin_unlock(spinlock_t *lock) -+void __sched rt_spin_unlock(spinlock_t *lock) __releases(RCU) - { - spin_release(&lock->dep_map, _RET_IP_); - migrate_enable(); -@@ -225,7 +225,7 @@ int __sched rt_write_trylock(rwlock_t *r - } - EXPORT_SYMBOL(rt_write_trylock); - --void __sched rt_read_lock(rwlock_t *rwlock) -+void __sched rt_read_lock(rwlock_t *rwlock) __acquires(RCU) - { - rtlock_might_resched(); - rwlock_acquire_read(&rwlock->dep_map, 0, 0, _RET_IP_); -@@ -235,7 +235,7 @@ void __sched rt_read_lock(rwlock_t *rwlo - } - EXPORT_SYMBOL(rt_read_lock); - --void __sched rt_write_lock(rwlock_t *rwlock) -+void __sched rt_write_lock(rwlock_t *rwlock) __acquires(RCU) - { - rtlock_might_resched(); - rwlock_acquire(&rwlock->dep_map, 0, 0, _RET_IP_); -@@ -246,7 +246,7 @@ void __sched rt_write_lock(rwlock_t *rwl - EXPORT_SYMBOL(rt_write_lock); - - #ifdef CONFIG_DEBUG_LOCK_ALLOC --void __sched rt_write_lock_nested(rwlock_t *rwlock, int subclass) -+void __sched rt_write_lock_nested(rwlock_t *rwlock, int subclass) __acquires(RCU) - { - rtlock_might_resched(); - rwlock_acquire(&rwlock->dep_map, subclass, 0, _RET_IP_); -@@ -257,7 +257,7 @@ void __sched rt_write_lock_nested(rwlock - EXPORT_SYMBOL(rt_write_lock_nested); - #endif - --void __sched rt_read_unlock(rwlock_t *rwlock) -+void __sched rt_read_unlock(rwlock_t *rwlock) __releases(RCU) - { - rwlock_release(&rwlock->dep_map, _RET_IP_); - migrate_enable(); -@@ -266,7 +266,7 @@ void __sched rt_read_unlock(rwlock_t *rw - } - EXPORT_SYMBOL(rt_read_unlock); - --void __sched rt_write_unlock(rwlock_t *rwlock) -+void __sched rt_write_unlock(rwlock_t *rwlock) __releases(RCU) - { - rwlock_release(&rwlock->dep_map, _RET_IP_); - rcu_read_unlock(); diff --git a/debian/patches-rt/0003-printk-Properly-deal-with-nbcon-consoles-on-seq-init.patch b/debian/patches-rt/0003-printk-Properly-deal-with-nbcon-consoles-on-seq-init.patch deleted file mode 100644 index 7ebed86..0000000 --- a/debian/patches-rt/0003-printk-Properly-deal-with-nbcon-consoles-on-seq-init.patch +++ /dev/null @@ -1,148 +0,0 @@ -From: Petr Mladek -Date: Tue, 20 Aug 2024 08:35:29 +0206 -Subject: [PATCH 03/54] printk: Properly deal with nbcon consoles on seq init -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -If a non-boot console is registering and boot consoles exist, -the consoles are flushed before being unregistered. This allows -the non-boot console to continue where the boot console left -off. - -If for whatever reason flushing fails, the lowest seq found from -any of the enabled boot consoles is used. Until now con->seq was -checked. However, if it is an nbcon boot console, the function -nbcon_seq_read() must be used to read seq because con->seq is -not updated for nbcon consoles. - -Check if it is an nbcon boot console and if so call -nbcon_seq_read() to read seq. - -Also, avoid usage of con->seq as temporary storage of the -starting record. Instead, rename console_init_seq() to -get_init_console_seq() and just return the value. For nbcon -consoles set the sequence via nbcon_seq_force(), for legacy -consoles set con->seq. - -The cleaned design should make sure that the value stays and is -set before the console is added to the console list. It also -unifies the sequence number initialization for legacy and nbcon -consoles. - -Reviewed-by: John Ogness -Link: https://lore.kernel.org/r/20240820063001.36405-4-john.ogness@linutronix.de -Signed-off-by: Petr Mladek -Signed-off-by: Sebastian Andrzej Siewior ---- - kernel/printk/nbcon.c | 3 --- - kernel/printk/printk.c | 41 +++++++++++++++++++++++++++++------------ - 2 files changed, 29 insertions(+), 15 deletions(-) - ---- a/kernel/printk/nbcon.c -+++ b/kernel/printk/nbcon.c -@@ -172,9 +172,6 @@ void nbcon_seq_force(struct console *con - u64 valid_seq = max_t(u64, seq, prb_first_valid_seq(prb)); - - atomic_long_set(&ACCESS_PRIVATE(con, nbcon_seq), __u64seq_to_ulseq(valid_seq)); -- -- /* Clear con->seq since nbcon consoles use con->nbcon_seq instead. */ -- con->seq = 0; - } - - /** ---- a/kernel/printk/printk.c -+++ b/kernel/printk/printk.c -@@ -3449,19 +3449,21 @@ static void try_enable_default_console(s - newcon->flags |= CON_CONSDEV; - } - --static void console_init_seq(struct console *newcon, bool bootcon_registered) -+/* Return the starting sequence number for a newly registered console. */ -+static u64 get_init_console_seq(struct console *newcon, bool bootcon_registered) - { - struct console *con; - bool handover; -+ u64 init_seq; - - if (newcon->flags & (CON_PRINTBUFFER | CON_BOOT)) { - /* Get a consistent copy of @syslog_seq. */ - mutex_lock(&syslog_lock); -- newcon->seq = syslog_seq; -+ init_seq = syslog_seq; - mutex_unlock(&syslog_lock); - } else { - /* Begin with next message added to ringbuffer. */ -- newcon->seq = prb_next_seq(prb); -+ init_seq = prb_next_seq(prb); - - /* - * If any enabled boot consoles are due to be unregistered -@@ -3482,7 +3484,7 @@ static void console_init_seq(struct cons - * Flush all consoles and set the console to start at - * the next unprinted sequence number. - */ -- if (!console_flush_all(true, &newcon->seq, &handover)) { -+ if (!console_flush_all(true, &init_seq, &handover)) { - /* - * Flushing failed. Just choose the lowest - * sequence of the enabled boot consoles. -@@ -3495,19 +3497,30 @@ static void console_init_seq(struct cons - if (handover) - console_lock(); - -- newcon->seq = prb_next_seq(prb); -+ init_seq = prb_next_seq(prb); - for_each_console(con) { -- if ((con->flags & CON_BOOT) && -- (con->flags & CON_ENABLED) && -- con->seq < newcon->seq) { -- newcon->seq = con->seq; -+ u64 seq; -+ -+ if (!(con->flags & CON_BOOT) || -+ !(con->flags & CON_ENABLED)) { -+ continue; - } -+ -+ if (con->flags & CON_NBCON) -+ seq = nbcon_seq_read(con); -+ else -+ seq = con->seq; -+ -+ if (seq < init_seq) -+ init_seq = seq; - } - } - - console_unlock(); - } - } -+ -+ return init_seq; - } - - #define console_first() \ -@@ -3539,6 +3552,7 @@ void register_console(struct console *ne - struct console *con; - bool bootcon_registered = false; - bool realcon_registered = false; -+ u64 init_seq; - int err; - - console_list_lock(); -@@ -3616,10 +3630,13 @@ void register_console(struct console *ne - } - - newcon->dropped = 0; -- console_init_seq(newcon, bootcon_registered); -+ init_seq = get_init_console_seq(newcon, bootcon_registered); - -- if (newcon->flags & CON_NBCON) -- nbcon_seq_force(newcon, newcon->seq); -+ if (newcon->flags & CON_NBCON) { -+ nbcon_seq_force(newcon, init_seq); -+ } else { -+ newcon->seq = init_seq; -+ } - - /* - * Put this console in the list - keep the diff --git a/debian/patches-rt/0003-time-Allow-to-preempt-after-a-callback.patch b/debian/patches-rt/0003-time-Allow-to-preempt-after-a-callback.patch deleted file mode 100644 index 0a460a2..0000000 --- a/debian/patches-rt/0003-time-Allow-to-preempt-after-a-callback.patch +++ /dev/null @@ -1,47 +0,0 @@ -From: Sebastian Andrzej Siewior -Date: Fri, 4 Aug 2023 13:30:39 +0200 -Subject: [PATCH 3/3] time: Allow to preempt after a callback. -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -The TIMER_SOFTIRQ handler invokes timer callbacks of the expired timers. -Before each invocation the timer_base::lock is dropped. The only lock -that is still held is the timer_base::expiry_lock and the per-CPU -bh-lock as part of local_bh_disable(). The former is released as part -of lock up prevention if the timer is preempted by the caller which is -waiting for its completion. - -Both locks are already released as part of timer_sync_wait_running(). -This can be extended by also releasing in bh-lock. The timer core does -not rely on any state that is serialized by the bh-lock. The timer -callback expects the bh-state to be serialized by the lock but there is -no need to keep state synchronized while invoking multiple callbacks. - -Preempt handling softirqs and release all locks after a timer invocation -if the current has inherited priority. - -Link: https://lore.kernel.org/r/20230804113039.419794-4-bigeasy@linutronix.de -Signed-off-by: Sebastian Andrzej Siewior ---- - kernel/time/timer.c | 9 ++++++++- - 1 file changed, 8 insertions(+), 1 deletion(-) - ---- a/kernel/time/timer.c -+++ b/kernel/time/timer.c -@@ -1564,9 +1564,16 @@ static void timer_sync_wait_running(stru - __releases(&base->lock) __releases(&base->expiry_lock) - __acquires(&base->expiry_lock) __acquires(&base->lock) - { -- if (atomic_read(&base->timer_waiters)) { -+ bool need_preempt; -+ -+ need_preempt = task_is_pi_boosted(current); -+ if (need_preempt || atomic_read(&base->timer_waiters)) { - raw_spin_unlock_irq(&base->lock); - spin_unlock(&base->expiry_lock); -+ -+ if (need_preempt) -+ softirq_preempt(); -+ - spin_lock(&base->expiry_lock); - raw_spin_lock_irq(&base->lock); - } diff --git a/debian/patches-rt/0003-zram-Shrink-zram_table_entry-flags.patch b/debian/patches-rt/0003-zram-Shrink-zram_table_entry-flags.patch deleted file mode 100644 index 61c8f90..0000000 --- a/debian/patches-rt/0003-zram-Shrink-zram_table_entry-flags.patch +++ /dev/null @@ -1,49 +0,0 @@ -From: Sebastian Andrzej Siewior -Date: Thu, 20 Jun 2024 12:53:06 +0200 -Subject: [PATCH 3/3] zram: Shrink zram_table_entry::flags. -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -The zram_table_entry::flags member is of type long and uses 8 bytes on a -64bit architecture. With a PAGE_SIZE of 256KiB we have PAGE_SHIFT of 18 -which in turn leads to __NR_ZRAM_PAGEFLAGS = 27. This still fits in an -ordinary integer. -By reducing the size of `flags' to four bytes, the size of the struct -goes back to 16 bytes. The padding between the lock and ac_time (if -enabled) is also gone. - -Make zram_table_entry::flags an unsigned int and update the build test -to reflect the change. - -Reviewed-by: Sergey Senozhatsky -Signed-off-by: Sebastian Andrzej Siewior -Link: https://lore.kernel.org/20240906141520.730009-4-bigeasy@linutronix.de ---- - drivers/block/zram/zram_drv.c | 3 ++- - drivers/block/zram/zram_drv.h | 2 +- - 2 files changed, 3 insertions(+), 2 deletions(-) - ---- a/drivers/block/zram/zram_drv.c -+++ b/drivers/block/zram/zram_drv.c -@@ -2404,9 +2404,10 @@ static void destroy_devices(void) - - static int __init zram_init(void) - { -+ struct zram_table_entry zram_te; - int ret; - -- BUILD_BUG_ON(__NR_ZRAM_PAGEFLAGS > BITS_PER_LONG); -+ BUILD_BUG_ON(__NR_ZRAM_PAGEFLAGS > sizeof(zram_te.flags) * 8); - - ret = cpuhp_setup_state_multi(CPUHP_ZCOMP_PREPARE, "block/zram:prepare", - zcomp_cpu_up_prepare, zcomp_cpu_dead); ---- a/drivers/block/zram/zram_drv.h -+++ b/drivers/block/zram/zram_drv.h -@@ -66,7 +66,7 @@ struct zram_table_entry { - unsigned long handle; - unsigned long element; - }; -- unsigned long flags; -+ unsigned int flags; - spinlock_t lock; - #ifdef CONFIG_ZRAM_TRACK_ENTRY_ACTIME - ktime_t ac_time; diff --git a/debian/patches-rt/0004-ARM-vfp-Move-sending-signals-outside-of-vfp_lock-ed-.patch b/debian/patches-rt/0004-ARM-vfp-Move-sending-signals-outside-of-vfp_lock-ed-.patch deleted file mode 100644 index 1053d9d..0000000 --- a/debian/patches-rt/0004-ARM-vfp-Move-sending-signals-outside-of-vfp_lock-ed-.patch +++ /dev/null @@ -1,121 +0,0 @@ -From: Sebastian Andrzej Siewior -Date: Wed, 28 Jun 2023 09:39:33 +0200 -Subject: [PATCH 4/4] ARM: vfp: Move sending signals outside of vfp_lock()ed - section. -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -VFP_bounce() is invoked from within vfp_support_entry() and may send a -signal. Sending a signal uses spinlock_t which becomes a sleeping lock -on PREEMPT_RT and must not be acquired within a preempt-disabled -section. - -Move the vfp_raise_sigfpe() block outside of the vfp_lock() section. - -Signed-off-by: Sebastian Andrzej Siewior ---- - arch/arm/vfp/vfpmodule.c | 29 ++++++++++++++++++----------- - 1 file changed, 18 insertions(+), 11 deletions(-) - ---- a/arch/arm/vfp/vfpmodule.c -+++ b/arch/arm/vfp/vfpmodule.c -@@ -268,7 +268,7 @@ static void vfp_panic(char *reason, u32 - /* - * Process bitmask of exception conditions. - */ --static void vfp_raise_exceptions(u32 exceptions, u32 inst, u32 fpscr, struct pt_regs *regs) -+static int vfp_raise_exceptions(u32 exceptions, u32 inst, u32 fpscr) - { - int si_code = 0; - -@@ -276,8 +276,7 @@ static void vfp_raise_exceptions(u32 exc - - if (exceptions == VFP_EXCEPTION_ERROR) { - vfp_panic("unhandled bounce", inst); -- vfp_raise_sigfpe(FPE_FLTINV, regs); -- return; -+ return FPE_FLTINV; - } - - /* -@@ -305,8 +304,7 @@ static void vfp_raise_exceptions(u32 exc - RAISE(FPSCR_OFC, FPSCR_OFE, FPE_FLTOVF); - RAISE(FPSCR_IOC, FPSCR_IOE, FPE_FLTINV); - -- if (si_code) -- vfp_raise_sigfpe(si_code, regs); -+ return si_code; - } - - /* -@@ -352,6 +350,8 @@ static u32 vfp_emulate_instruction(u32 i - static void VFP_bounce(u32 trigger, u32 fpexc, struct pt_regs *regs) - { - u32 fpscr, orig_fpscr, fpsid, exceptions; -+ int si_code2 = 0; -+ int si_code = 0; - - pr_debug("VFP: bounce: trigger %08x fpexc %08x\n", trigger, fpexc); - -@@ -397,8 +397,8 @@ static void VFP_bounce(u32 trigger, u32 - * unallocated VFP instruction but with FPSCR.IXE set and not - * on VFP subarch 1. - */ -- vfp_raise_exceptions(VFP_EXCEPTION_ERROR, trigger, fpscr, regs); -- return; -+ si_code = vfp_raise_exceptions(VFP_EXCEPTION_ERROR, trigger, fpscr); -+ goto exit; - } - - /* -@@ -422,14 +422,14 @@ static void VFP_bounce(u32 trigger, u32 - */ - exceptions = vfp_emulate_instruction(trigger, fpscr, regs); - if (exceptions) -- vfp_raise_exceptions(exceptions, trigger, orig_fpscr, regs); -+ si_code2 = vfp_raise_exceptions(exceptions, trigger, orig_fpscr); - - /* - * If there isn't a second FP instruction, exit now. Note that - * the FPEXC.FP2V bit is valid only if FPEXC.EX is 1. - */ - if ((fpexc & (FPEXC_EX | FPEXC_FP2V)) != (FPEXC_EX | FPEXC_FP2V)) -- return; -+ goto exit; - - /* - * The barrier() here prevents fpinst2 being read -@@ -441,7 +441,13 @@ static void VFP_bounce(u32 trigger, u32 - emulate: - exceptions = vfp_emulate_instruction(trigger, orig_fpscr, regs); - if (exceptions) -- vfp_raise_exceptions(exceptions, trigger, orig_fpscr, regs); -+ si_code = vfp_raise_exceptions(exceptions, trigger, orig_fpscr); -+exit: -+ vfp_unlock(); -+ if (si_code2) -+ vfp_raise_sigfpe(si_code2, regs); -+ if (si_code) -+ vfp_raise_sigfpe(si_code, regs); - } - - static void vfp_enable(void *unused) -@@ -773,6 +779,7 @@ static int vfp_support_entry(struct pt_r - * replay the instruction that trapped. - */ - fmxr(FPEXC, fpexc); -+ vfp_unlock(); - } else { - /* Check for synchronous or asynchronous exceptions */ - if (!(fpexc & (FPEXC_EX | FPEXC_DEX))) { -@@ -794,10 +801,10 @@ static int vfp_support_entry(struct pt_r - } - } - bounce: regs->ARM_pc += 4; -+ /* VFP_bounce() will invoke vfp_unlock() */ - VFP_bounce(trigger, fpexc, regs); - } - -- vfp_unlock(); - return 0; - } - diff --git a/debian/patches-rt/0004-drm-i915-Disable-tracing-points-on-PREEMPT_RT.patch b/debian/patches-rt/0004-drm-i915-Disable-tracing-points-on-PREEMPT_RT.patch deleted file mode 100644 index 4cdebb4..0000000 --- a/debian/patches-rt/0004-drm-i915-Disable-tracing-points-on-PREEMPT_RT.patch +++ /dev/null @@ -1,60 +0,0 @@ -From: Sebastian Andrzej Siewior -Date: Thu, 6 Dec 2018 09:52:20 +0100 -Subject: [PATCH 4/8] drm/i915: Disable tracing points on PREEMPT_RT -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -Luca Abeni reported this: -| BUG: scheduling while atomic: kworker/u8:2/15203/0x00000003 -| CPU: 1 PID: 15203 Comm: kworker/u8:2 Not tainted 4.19.1-rt3 #10 -| Call Trace: -| rt_spin_lock+0x3f/0x50 -| gen6_read32+0x45/0x1d0 [i915] -| g4x_get_vblank_counter+0x36/0x40 [i915] -| trace_event_raw_event_i915_pipe_update_start+0x7d/0xf0 [i915] - -The tracing events use trace_intel_pipe_update_start() among other events -use functions acquire spinlock_t locks which are transformed into -sleeping locks on PREEMPT_RT. A few trace points use -intel_get_crtc_scanline(), others use ->get_vblank_counter() wich also -might acquire a sleeping locks on PREEMPT_RT. -At the time the arguments are evaluated within trace point, preemption -is disabled and so the locks must not be acquired on PREEMPT_RT. - -Based on this I don't see any other way than disable trace points on -PREMPT_RT. - -Acked-by: Tvrtko Ursulin -Reported-by: Luca Abeni -Cc: Steven Rostedt -Signed-off-by: Sebastian Andrzej Siewior ---- - drivers/gpu/drm/i915/display/intel_display_trace.h | 4 ++++ - drivers/gpu/drm/i915/i915_trace.h | 4 ++++ - 2 files changed, 8 insertions(+) - ---- a/drivers/gpu/drm/i915/display/intel_display_trace.h -+++ b/drivers/gpu/drm/i915/display/intel_display_trace.h -@@ -9,6 +9,10 @@ - #if !defined(__INTEL_DISPLAY_TRACE_H__) || defined(TRACE_HEADER_MULTI_READ) - #define __INTEL_DISPLAY_TRACE_H__ - -+#if defined(CONFIG_PREEMPT_RT) && !defined(NOTRACE) -+#define NOTRACE -+#endif -+ - #include - #include - #include ---- a/drivers/gpu/drm/i915/i915_trace.h -+++ b/drivers/gpu/drm/i915/i915_trace.h -@@ -6,6 +6,10 @@ - #if !defined(_I915_TRACE_H_) || defined(TRACE_HEADER_MULTI_READ) - #define _I915_TRACE_H_ - -+#if defined(CONFIG_PREEMPT_RT) && !defined(NOTRACE) -+#define NOTRACE -+#endif -+ - #include - #include - #include diff --git a/debian/patches-rt/0004-locking-rt-Annotate-unlock-followed-by-lock-for-spar.patch b/debian/patches-rt/0004-locking-rt-Annotate-unlock-followed-by-lock-for-spar.patch deleted file mode 100644 index f9e90ac..0000000 --- a/debian/patches-rt/0004-locking-rt-Annotate-unlock-followed-by-lock-for-spar.patch +++ /dev/null @@ -1,35 +0,0 @@ -From: Sebastian Andrzej Siewior -Date: Mon, 12 Aug 2024 12:39:05 +0200 -Subject: [PATCH 4/4] locking/rt: Annotate unlock followed by lock for sparse. -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -rt_mutex_slowlock_block() and rtlock_slowlock_locked() both unlock -lock::wait_lock and then lock it later. This is unusual and sparse -complains about it. - -Add __releases() + __acquires() annotation to mark that it is expected. - -Link: https://lore.kernel.org/r/20240812104200.2239232-5-bigeasy@linutronix.de -Signed-off-by: Sebastian Andrzej Siewior ---- - kernel/locking/rtmutex.c | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/kernel/locking/rtmutex.c -+++ b/kernel/locking/rtmutex.c -@@ -1601,6 +1601,7 @@ static int __sched rt_mutex_slowlock_blo - unsigned int state, - struct hrtimer_sleeper *timeout, - struct rt_mutex_waiter *waiter) -+ __releases(&lock->wait_lock) __acquires(&lock->wait_lock) - { - struct rt_mutex *rtm = container_of(lock, struct rt_mutex, rtmutex); - struct task_struct *owner; -@@ -1805,6 +1806,7 @@ static __always_inline int __rt_mutex_lo - * @lock: The underlying RT mutex - */ - static void __sched rtlock_slowlock_locked(struct rt_mutex_base *lock) -+ __releases(&lock->wait_lock) __acquires(&lock->wait_lock) - { - struct rt_mutex_waiter waiter; - struct task_struct *owner; diff --git a/debian/patches-rt/0004-printk-Check-printk_deferred_enter-_exit-usage.patch b/debian/patches-rt/0004-printk-Check-printk_deferred_enter-_exit-usage.patch deleted file mode 100644 index 2b3679c..0000000 --- a/debian/patches-rt/0004-printk-Check-printk_deferred_enter-_exit-usage.patch +++ /dev/null @@ -1,76 +0,0 @@ -From: Sebastian Andrzej Siewior -Date: Tue, 20 Aug 2024 08:35:30 +0206 -Subject: [PATCH 04/54] printk: Check printk_deferred_enter()/_exit() usage -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -Add validation that printk_deferred_enter()/_exit() are called in -non-migration contexts. - -Signed-off-by: Sebastian Andrzej Siewior -Signed-off-by: John Ogness -Reviewed-by: Petr Mladek -Link: https://lore.kernel.org/r/20240820063001.36405-5-john.ogness@linutronix.de -Signed-off-by: Petr Mladek -Signed-off-by: Sebastian Andrzej Siewior ---- - include/linux/printk.h | 9 +++++---- - kernel/printk/internal.h | 3 +++ - kernel/printk/printk_safe.c | 12 ++++++++++++ - 3 files changed, 20 insertions(+), 4 deletions(-) - ---- a/include/linux/printk.h -+++ b/include/linux/printk.h -@@ -161,15 +161,16 @@ int _printk(const char *fmt, ...); - */ - __printf(1, 2) __cold int _printk_deferred(const char *fmt, ...); - --extern void __printk_safe_enter(void); --extern void __printk_safe_exit(void); -+extern void __printk_deferred_enter(void); -+extern void __printk_deferred_exit(void); -+ - /* - * The printk_deferred_enter/exit macros are available only as a hack for - * some code paths that need to defer all printk console printing. Interrupts - * must be disabled for the deferred duration. - */ --#define printk_deferred_enter __printk_safe_enter --#define printk_deferred_exit __printk_safe_exit -+#define printk_deferred_enter() __printk_deferred_enter() -+#define printk_deferred_exit() __printk_deferred_exit() - - /* - * Please don't use printk_ratelimit(), because it shares ratelimiting state ---- a/kernel/printk/internal.h -+++ b/kernel/printk/internal.h -@@ -53,6 +53,9 @@ int vprintk_store(int facility, int leve - __printf(1, 0) int vprintk_default(const char *fmt, va_list args); - __printf(1, 0) int vprintk_deferred(const char *fmt, va_list args); - -+void __printk_safe_enter(void); -+void __printk_safe_exit(void); -+ - bool printk_percpu_data_ready(void); - - #define printk_safe_enter_irqsave(flags) \ ---- a/kernel/printk/printk_safe.c -+++ b/kernel/printk/printk_safe.c -@@ -26,6 +26,18 @@ void __printk_safe_exit(void) - this_cpu_dec(printk_context); - } - -+void __printk_deferred_enter(void) -+{ -+ cant_migrate(); -+ __printk_safe_enter(); -+} -+ -+void __printk_deferred_exit(void) -+{ -+ cant_migrate(); -+ __printk_safe_exit(); -+} -+ - asmlinkage int vprintk(const char *fmt, va_list args) - { - #ifdef CONFIG_KGDB_KDB diff --git a/debian/patches-rt/0005-drm-i915-gt-Use-spin_lock_irq-instead-of-local_irq_d.patch b/debian/patches-rt/0005-drm-i915-gt-Use-spin_lock_irq-instead-of-local_irq_d.patch deleted file mode 100644 index 6f618fc..0000000 --- a/debian/patches-rt/0005-drm-i915-gt-Use-spin_lock_irq-instead-of-local_irq_d.patch +++ /dev/null @@ -1,89 +0,0 @@ -From: Sebastian Andrzej Siewior -Date: Wed, 8 Sep 2021 19:03:41 +0200 -Subject: [PATCH 5/8] drm/i915/gt: Use spin_lock_irq() instead of - local_irq_disable() + spin_lock() -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -execlists_dequeue() is invoked from a function which uses -local_irq_disable() to disable interrupts so the spin_lock() behaves -like spin_lock_irq(). -This breaks PREEMPT_RT because local_irq_disable() + spin_lock() is not -the same as spin_lock_irq(). - -execlists_dequeue_irq() and execlists_dequeue() has each one caller -only. If intel_engine_cs::active::lock is acquired and released with the -_irq suffix then it behaves almost as if execlists_dequeue() would be -invoked with disabled interrupts. The difference is the last part of the -function which is then invoked with enabled interrupts. -I can't tell if this makes a difference. From looking at it, it might -work to move the last unlock at the end of the function as I didn't find -anything that would acquire the lock again. - -Reported-by: Clark Williams -Signed-off-by: Sebastian Andrzej Siewior -Reviewed-by: Maarten Lankhorst ---- - drivers/gpu/drm/i915/gt/intel_execlists_submission.c | 17 +++++------------ - 1 file changed, 5 insertions(+), 12 deletions(-) - ---- a/drivers/gpu/drm/i915/gt/intel_execlists_submission.c -+++ b/drivers/gpu/drm/i915/gt/intel_execlists_submission.c -@@ -1303,7 +1303,7 @@ static void execlists_dequeue(struct int - * and context switches) submission. - */ - -- spin_lock(&sched_engine->lock); -+ spin_lock_irq(&sched_engine->lock); - - /* - * If the queue is higher priority than the last -@@ -1403,7 +1403,7 @@ static void execlists_dequeue(struct int - * Even if ELSP[1] is occupied and not worthy - * of timeslices, our queue might be. - */ -- spin_unlock(&sched_engine->lock); -+ spin_unlock_irq(&sched_engine->lock); - return; - } - } -@@ -1429,7 +1429,7 @@ static void execlists_dequeue(struct int - - if (last && !can_merge_rq(last, rq)) { - spin_unlock(&ve->base.sched_engine->lock); -- spin_unlock(&engine->sched_engine->lock); -+ spin_unlock_irq(&engine->sched_engine->lock); - return; /* leave this for another sibling */ - } - -@@ -1591,7 +1591,7 @@ static void execlists_dequeue(struct int - */ - sched_engine->queue_priority_hint = queue_prio(sched_engine); - i915_sched_engine_reset_on_empty(sched_engine); -- spin_unlock(&sched_engine->lock); -+ spin_unlock_irq(&sched_engine->lock); - - /* - * We can skip poking the HW if we ended up with exactly the same set -@@ -1617,13 +1617,6 @@ static void execlists_dequeue(struct int - } - } - --static void execlists_dequeue_irq(struct intel_engine_cs *engine) --{ -- local_irq_disable(); /* Suspend interrupts across request submission */ -- execlists_dequeue(engine); -- local_irq_enable(); /* flush irq_work (e.g. breadcrumb enabling) */ --} -- - static void clear_ports(struct i915_request **ports, int count) - { - memset_p((void **)ports, NULL, count); -@@ -2478,7 +2471,7 @@ static void execlists_submission_tasklet - } - - if (!engine->execlists.pending[0]) { -- execlists_dequeue_irq(engine); -+ execlists_dequeue(engine); - start_timeslice(engine); - } - diff --git a/debian/patches-rt/0005-printk-nbcon-Clarify-rules-of-the-owner-waiter-match.patch b/debian/patches-rt/0005-printk-nbcon-Clarify-rules-of-the-owner-waiter-match.patch deleted file mode 100644 index 32e1d08..0000000 --- a/debian/patches-rt/0005-printk-nbcon-Clarify-rules-of-the-owner-waiter-match.patch +++ /dev/null @@ -1,110 +0,0 @@ -From: John Ogness -Date: Tue, 20 Aug 2024 08:35:31 +0206 -Subject: [PATCH 05/54] printk: nbcon: Clarify rules of the owner/waiter - matching -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -The functions nbcon_owner_matches() and nbcon_waiter_matches() -use a minimal set of data to determine if a context matches. -The existing kerneldoc and comments were not clear enough and -caused the printk folks to re-prove that the functions are -indeed reliable in all cases. - -Update and expand the explanations so that it is clear that the -implementations are sufficient for all cases. - -Signed-off-by: John Ogness -Reviewed-by: Petr Mladek -Link: https://lore.kernel.org/r/20240820063001.36405-6-john.ogness@linutronix.de -Signed-off-by: Petr Mladek -Signed-off-by: Sebastian Andrzej Siewior ---- - kernel/printk/nbcon.c | 56 +++++++++++++++++++++++++++++++++++++++++--------- - 1 file changed, 46 insertions(+), 10 deletions(-) - ---- a/kernel/printk/nbcon.c -+++ b/kernel/printk/nbcon.c -@@ -228,6 +228,13 @@ static int nbcon_context_try_acquire_dir - struct nbcon_state new; - - do { -+ /* -+ * Panic does not imply that the console is owned. However, it -+ * is critical that non-panic CPUs during panic are unable to -+ * acquire ownership in order to satisfy the assumptions of -+ * nbcon_waiter_matches(). In particular, the assumption that -+ * lower priorities are ignored during panic. -+ */ - if (other_cpu_in_panic()) - return -EPERM; - -@@ -259,18 +266,29 @@ static bool nbcon_waiter_matches(struct - /* - * The request context is well defined by the @req_prio because: - * -- * - Only a context with a higher priority can take over the request. -+ * - Only a context with a priority higher than the owner can become -+ * a waiter. -+ * - Only a context with a priority higher than the waiter can -+ * directly take over the request. - * - There are only three priorities. - * - Only one CPU is allowed to request PANIC priority. - * - Lower priorities are ignored during panic() until reboot. - * - * As a result, the following scenario is *not* possible: - * -- * 1. Another context with a higher priority directly takes ownership. -- * 2. The higher priority context releases the ownership. -- * 3. A lower priority context takes the ownership. -- * 4. Another context with the same priority as this context -+ * 1. This context is currently a waiter. -+ * 2. Another context with a higher priority than this context -+ * directly takes ownership. -+ * 3. The higher priority context releases the ownership. -+ * 4. Another lower priority context takes the ownership. -+ * 5. Another context with the same priority as this context - * creates a request and starts waiting. -+ * -+ * Event #1 implies this context is EMERGENCY. -+ * Event #2 implies the new context is PANIC. -+ * Event #3 occurs when panic() has flushed the console. -+ * Events #4 and #5 are not possible due to the other_cpu_in_panic() -+ * check in nbcon_context_try_acquire_direct(). - */ - - return (cur->req_prio == expected_prio); -@@ -578,11 +596,29 @@ static bool nbcon_owner_matches(struct n - int expected_prio) - { - /* -- * Since consoles can only be acquired by higher priorities, -- * owning contexts are uniquely identified by @prio. However, -- * since contexts can unexpectedly lose ownership, it is -- * possible that later another owner appears with the same -- * priority. For this reason @cpu is also needed. -+ * A similar function, nbcon_waiter_matches(), only deals with -+ * EMERGENCY and PANIC priorities. However, this function must also -+ * deal with the NORMAL priority, which requires additional checks -+ * and constraints. -+ * -+ * For the case where preemption and interrupts are disabled, it is -+ * enough to also verify that the owning CPU has not changed. -+ * -+ * For the case where preemption or interrupts are enabled, an -+ * external synchronization method *must* be used. In particular, -+ * the driver-specific locking mechanism used in device_lock() -+ * (including disabling migration) should be used. It prevents -+ * scenarios such as: -+ * -+ * 1. [Task A] owns a context with NBCON_PRIO_NORMAL on [CPU X] and -+ * is scheduled out. -+ * 2. Another context takes over the lock with NBCON_PRIO_EMERGENCY -+ * and releases it. -+ * 3. [Task B] acquires a context with NBCON_PRIO_NORMAL on [CPU X] -+ * and is scheduled out. -+ * 4. [Task A] gets running on [CPU X] and sees that the console is -+ * still owned by a task on [CPU X] with NBON_PRIO_NORMAL. Thus -+ * [Task A] thinks it is the owner when it is not. - */ - - if (cur->prio != expected_prio) diff --git a/debian/patches-rt/0006-drm-i915-Drop-the-irqs_disabled-check.patch b/debian/patches-rt/0006-drm-i915-Drop-the-irqs_disabled-check.patch deleted file mode 100644 index 10da433..0000000 --- a/debian/patches-rt/0006-drm-i915-Drop-the-irqs_disabled-check.patch +++ /dev/null @@ -1,40 +0,0 @@ -From: Sebastian Andrzej Siewior -Date: Fri, 1 Oct 2021 20:01:03 +0200 -Subject: [PATCH 6/8] drm/i915: Drop the irqs_disabled() check -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -The !irqs_disabled() check triggers on PREEMPT_RT even with -i915_sched_engine::lock acquired. The reason is the lock is transformed -into a sleeping lock on PREEMPT_RT and does not disable interrupts. - -There is no need to check for disabled interrupts. The lockdep -annotation below already check if the lock has been acquired by the -caller and will yell if the interrupts are not disabled. - -Remove the !irqs_disabled() check. - -Reported-by: Maarten Lankhorst -Acked-by: Tvrtko Ursulin -Signed-off-by: Sebastian Andrzej Siewior ---- - drivers/gpu/drm/i915/i915_request.c | 2 -- - 1 file changed, 2 deletions(-) - ---- a/drivers/gpu/drm/i915/i915_request.c -+++ b/drivers/gpu/drm/i915/i915_request.c -@@ -608,7 +608,6 @@ bool __i915_request_submit(struct i915_r - - RQ_TRACE(request, "\n"); - -- GEM_BUG_ON(!irqs_disabled()); - lockdep_assert_held(&engine->sched_engine->lock); - - /* -@@ -717,7 +716,6 @@ void __i915_request_unsubmit(struct i915 - */ - RQ_TRACE(request, "\n"); - -- GEM_BUG_ON(!irqs_disabled()); - lockdep_assert_held(&engine->sched_engine->lock); - - /* diff --git a/debian/patches-rt/0006-printk-nbcon-Remove-return-value-for-write_atomic.patch b/debian/patches-rt/0006-printk-nbcon-Remove-return-value-for-write_atomic.patch deleted file mode 100644 index b9ac007..0000000 --- a/debian/patches-rt/0006-printk-nbcon-Remove-return-value-for-write_atomic.patch +++ /dev/null @@ -1,71 +0,0 @@ -From: John Ogness -Date: Tue, 20 Aug 2024 08:35:32 +0206 -Subject: [PATCH 06/54] printk: nbcon: Remove return value for write_atomic() -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -The return value of write_atomic() does not provide any useful -information. On the contrary, it makes things more complicated -for the caller to appropriately deal with the information. - -Change write_atomic() to not have a return value. If the -message did not get printed due to loss of ownership, the -caller will notice this on its own. If ownership was not lost, -it will be assumed that the driver successfully printed the -message and the sequence number for that console will be -incremented. - -Signed-off-by: John Ogness -Reviewed-by: Petr Mladek -Link: https://lore.kernel.org/r/20240820063001.36405-7-john.ogness@linutronix.de -Signed-off-by: Petr Mladek -Signed-off-by: Sebastian Andrzej Siewior ---- - include/linux/console.h | 2 +- - kernel/printk/nbcon.c | 15 +++++++-------- - 2 files changed, 8 insertions(+), 9 deletions(-) - ---- a/include/linux/console.h -+++ b/include/linux/console.h -@@ -345,7 +345,7 @@ struct console { - struct hlist_node node; - - /* nbcon console specific members */ -- bool (*write_atomic)(struct console *con, -+ void (*write_atomic)(struct console *con, - struct nbcon_write_context *wctxt); - atomic_t __private nbcon_state; - atomic_long_t __private nbcon_seq; ---- a/kernel/printk/nbcon.c -+++ b/kernel/printk/nbcon.c -@@ -885,7 +885,6 @@ static bool nbcon_emit_next_record(struc - unsigned long con_dropped; - struct nbcon_state cur; - unsigned long dropped; -- bool done; - - /* - * The printk buffers are filled within an unsafe section. This -@@ -925,16 +924,16 @@ static bool nbcon_emit_next_record(struc - wctxt->unsafe_takeover = cur.unsafe_takeover; - - if (con->write_atomic) { -- done = con->write_atomic(con, wctxt); -+ con->write_atomic(con, wctxt); - } else { -- nbcon_context_release(ctxt); -+ /* -+ * This function should never be called for legacy consoles. -+ * Handle it as if ownership was lost and try to continue. -+ */ - WARN_ON_ONCE(1); -- done = false; -- } -- -- /* If not done, the emit was aborted. */ -- if (!done) -+ nbcon_context_release(ctxt); - return false; -+ } - - /* - * Since any dropped message was successfully output, reset the diff --git a/debian/patches-rt/0007-drm-i915-guc-Consider-also-RCU-depth-in-busy-loop.patch b/debian/patches-rt/0007-drm-i915-guc-Consider-also-RCU-depth-in-busy-loop.patch deleted file mode 100644 index af78d7d..0000000 --- a/debian/patches-rt/0007-drm-i915-guc-Consider-also-RCU-depth-in-busy-loop.patch +++ /dev/null @@ -1,30 +0,0 @@ -From: Sebastian Andrzej Siewior -Date: Tue, 3 Oct 2023 21:37:21 +0200 -Subject: [PATCH 7/8] drm/i915/guc: Consider also RCU depth in busy loop. -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -intel_guc_send_busy_loop() looks at in_atomic() and irqs_disabled() to -decide if it should busy-spin while waiting or if it may sleep. -Both checks will report false on PREEMPT_RT if sleeping spinlocks are -acquired leading to RCU splats while the function sleeps. - -Check also if RCU has been disabled. - -Reported-by: "John B. Wyatt IV" -Reviewed-by: Rodrigo Vivi -Signed-off-by: Sebastian Andrzej Siewior ---- - drivers/gpu/drm/i915/gt/uc/intel_guc.h | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/gpu/drm/i915/gt/uc/intel_guc.h -+++ b/drivers/gpu/drm/i915/gt/uc/intel_guc.h -@@ -362,7 +362,7 @@ static inline int intel_guc_send_busy_lo - { - int err; - unsigned int sleep_period_ms = 1; -- bool not_atomic = !in_atomic() && !irqs_disabled(); -+ bool not_atomic = !in_atomic() && !irqs_disabled() && !rcu_preempt_depth(); - - /* - * FIXME: Have caller pass in if we are in an atomic context to avoid diff --git a/debian/patches-rt/0007-printk-nbcon-Add-detailed-doc-for-write_atomic.patch b/debian/patches-rt/0007-printk-nbcon-Add-detailed-doc-for-write_atomic.patch deleted file mode 100644 index e33b9c2..0000000 --- a/debian/patches-rt/0007-printk-nbcon-Add-detailed-doc-for-write_atomic.patch +++ /dev/null @@ -1,75 +0,0 @@ -From: John Ogness -Date: Tue, 20 Aug 2024 08:35:33 +0206 -Subject: [PATCH 07/54] printk: nbcon: Add detailed doc for write_atomic() -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -The write_atomic() callback has special requirements and is -allowed to use special helper functions. Provide detailed -documentation of the callback so that a developer has a -chance of implementing it correctly. - -Signed-off-by: John Ogness -Reviewed-by: Petr Mladek -Link: https://lore.kernel.org/r/20240820063001.36405-8-john.ogness@linutronix.de -Signed-off-by: Petr Mladek -Signed-off-by: Sebastian Andrzej Siewior ---- - include/linux/console.h | 33 +++++++++++++++++++++++++++++---- - 1 file changed, 29 insertions(+), 4 deletions(-) - ---- a/include/linux/console.h -+++ b/include/linux/console.h -@@ -303,7 +303,7 @@ struct nbcon_write_context { - /** - * struct console - The console descriptor structure - * @name: The name of the console driver -- * @write: Write callback to output messages (Optional) -+ * @write: Legacy write callback to output messages (Optional) - * @read: Read callback for console input (Optional) - * @device: The underlying TTY device driver (Optional) - * @unblank: Callback to unblank the console (Optional) -@@ -320,7 +320,6 @@ struct nbcon_write_context { - * @data: Driver private data - * @node: hlist node for the console list - * -- * @write_atomic: Write callback for atomic context - * @nbcon_state: State for nbcon consoles - * @nbcon_seq: Sequence number of the next record for nbcon to print - * @pbufs: Pointer to nbcon private buffer -@@ -345,8 +344,34 @@ struct console { - struct hlist_node node; - - /* nbcon console specific members */ -- void (*write_atomic)(struct console *con, -- struct nbcon_write_context *wctxt); -+ -+ /** -+ * @write_atomic: -+ * -+ * NBCON callback to write out text in any context. (Optional) -+ * -+ * This callback is called with the console already acquired. However, -+ * a higher priority context is allowed to take it over by default. -+ * -+ * The callback must call nbcon_enter_unsafe() and nbcon_exit_unsafe() -+ * around any code where the takeover is not safe, for example, when -+ * manipulating the serial port registers. -+ * -+ * nbcon_enter_unsafe() will fail if the context has lost the console -+ * ownership in the meantime. In this case, the callback is no longer -+ * allowed to go forward. It must back out immediately and carefully. -+ * The buffer content is also no longer trusted since it no longer -+ * belongs to the context. -+ * -+ * The callback should allow the takeover whenever it is safe. It -+ * increases the chance to see messages when the system is in trouble. -+ * -+ * The callback can be called from any context (including NMI). -+ * Therefore it must avoid usage of any locking and instead rely -+ * on the console ownership for synchronization. -+ */ -+ void (*write_atomic)(struct console *con, struct nbcon_write_context *wctxt); -+ - atomic_t __private nbcon_state; - atomic_long_t __private nbcon_seq; - struct printk_buffers *pbufs; diff --git a/debian/patches-rt/0008-Revert-drm-i915-Depend-on-PREEMPT_RT.patch b/debian/patches-rt/0008-Revert-drm-i915-Depend-on-PREEMPT_RT.patch deleted file mode 100644 index 1914112..0000000 --- a/debian/patches-rt/0008-Revert-drm-i915-Depend-on-PREEMPT_RT.patch +++ /dev/null @@ -1,24 +0,0 @@ -From: Sebastian Andrzej Siewior -Date: Mon, 21 Feb 2022 17:59:14 +0100 -Subject: [PATCH 8/8] Revert "drm/i915: Depend on !PREEMPT_RT." -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -Once the known issues are addressed, it should be safe to enable the -driver. - -Acked-by: Tvrtko Ursulin -Signed-off-by: Sebastian Andrzej Siewior ---- - drivers/gpu/drm/i915/Kconfig | 1 - - 1 file changed, 1 deletion(-) - ---- a/drivers/gpu/drm/i915/Kconfig -+++ b/drivers/gpu/drm/i915/Kconfig -@@ -3,7 +3,6 @@ config DRM_I915 - tristate "Intel 8xx/9xx/G3x/G4x/HD Graphics" - depends on DRM - depends on X86 && PCI -- depends on !PREEMPT_RT - select INTEL_GTT if X86 - select INTERVAL_TREE - # we need shmfs for the swappable backing store, and in particular diff --git a/debian/patches-rt/0008-printk-nbcon-Add-callbacks-to-synchronize-with-drive.patch b/debian/patches-rt/0008-printk-nbcon-Add-callbacks-to-synchronize-with-drive.patch deleted file mode 100644 index c2b03fa..0000000 --- a/debian/patches-rt/0008-printk-nbcon-Add-callbacks-to-synchronize-with-drive.patch +++ /dev/null @@ -1,87 +0,0 @@ -From: John Ogness -Date: Tue, 20 Aug 2024 08:35:34 +0206 -Subject: [PATCH 08/54] printk: nbcon: Add callbacks to synchronize with driver -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -Console drivers typically must deal with access to the hardware -via user input/output (such as an interactive login shell) and -output of kernel messages via printk() calls. To provide the -necessary synchronization, usually some driver-specific locking -mechanism is used (for example, the port spinlock for uart -serial consoles). - -Until now, usage of this driver-specific locking has been hidden -from the printk-subsystem and implemented within the various -console callbacks. However, nbcon consoles would need to use it -even in the generic code. - -Add device_lock() and device_unlock() callback which will need -to get implemented by nbcon consoles. - -The callbacks will use whatever synchronization mechanism the -driver is using for itself. The minimum requirement is to -prevent CPU migration. It would allow a context friendly -acquiring of nbcon console ownership in non-emergency and -non-panic context. - -Signed-off-by: John Ogness -Reviewed-by: Petr Mladek -Link: https://lore.kernel.org/r/20240820063001.36405-9-john.ogness@linutronix.de -Signed-off-by: Petr Mladek -Signed-off-by: Sebastian Andrzej Siewior ---- - include/linux/console.h | 43 +++++++++++++++++++++++++++++++++++++++++++ - 1 file changed, 43 insertions(+) - ---- a/include/linux/console.h -+++ b/include/linux/console.h -@@ -372,6 +372,49 @@ struct console { - */ - void (*write_atomic)(struct console *con, struct nbcon_write_context *wctxt); - -+ /** -+ * @device_lock: -+ * -+ * NBCON callback to begin synchronization with driver code. -+ * -+ * Console drivers typically must deal with access to the hardware -+ * via user input/output (such as an interactive login shell) and -+ * output of kernel messages via printk() calls. This callback is -+ * called by the printk-subsystem whenever it needs to synchronize -+ * with hardware access by the driver. It should be implemented to -+ * use whatever synchronization mechanism the driver is using for -+ * itself (for example, the port lock for uart serial consoles). -+ * -+ * The callback is always called from task context. It may use any -+ * synchronization method required by the driver. -+ * -+ * IMPORTANT: The callback MUST disable migration. The console driver -+ * may be using a synchronization mechanism that already takes -+ * care of this (such as spinlocks). Otherwise this function must -+ * explicitly call migrate_disable(). -+ * -+ * The flags argument is provided as a convenience to the driver. It -+ * will be passed again to device_unlock(). It can be ignored if the -+ * driver does not need it. -+ */ -+ void (*device_lock)(struct console *con, unsigned long *flags); -+ -+ /** -+ * @device_unlock: -+ * -+ * NBCON callback to finish synchronization with driver code. -+ * -+ * It is the counterpart to device_lock(). -+ * -+ * This callback is always called from task context. It must -+ * appropriately re-enable migration (depending on how device_lock() -+ * disabled migration). -+ * -+ * The flags argument is the value of the same variable that was -+ * passed to device_lock(). -+ */ -+ void (*device_unlock)(struct console *con, unsigned long flags); -+ - atomic_t __private nbcon_state; - atomic_long_t __private nbcon_seq; - struct printk_buffers *pbufs; diff --git a/debian/patches-rt/0009-printk-nbcon-Use-driver-synchronization-while-un-reg.patch b/debian/patches-rt/0009-printk-nbcon-Use-driver-synchronization-while-un-reg.patch deleted file mode 100644 index 24e763c..0000000 --- a/debian/patches-rt/0009-printk-nbcon-Use-driver-synchronization-while-un-reg.patch +++ /dev/null @@ -1,124 +0,0 @@ -From: John Ogness -Date: Tue, 20 Aug 2024 08:35:35 +0206 -Subject: [PATCH 09/54] printk: nbcon: Use driver synchronization while - (un)registering -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -Console drivers typically have to deal with access to the -hardware via user input/output (such as an interactive login -shell) and output of kernel messages via printk() calls. - -They use some classic driver-specific locking mechanism in most -situations. But console->write_atomic() callbacks, used by nbcon -consoles, are synchronized only by acquiring the console -context. - -The synchronization via the console context ownership is possible -only when the console driver is registered. It is when a -particular device driver is connected with a particular console -driver. - -The two synchronization mechanisms must be synchronized between -each other. It is tricky because the console context ownership -is quite special. It might be taken over by a higher priority -context. Also CPU migration must be disabled. The most tricky -part is to (dis)connect these two mechanisms during the console -(un)registration. - -Use the driver-specific locking callbacks: device_lock(), -device_unlock(). They allow taking the device-specific lock -while the device is being (un)registered by the related console -driver. - -For example, these callbacks lock/unlock the port lock for -serial port drivers. - -Note that the driver-specific locking is only needed during -(un)register if it is an nbcon console with the write_atomic() -callback implemented. If write_atomic() is not implemented, the -driver should never attempt to access the hardware without -first acquiring its driver-specific lock. - -Signed-off-by: John Ogness -Reviewed-by: Petr Mladek -Link: https://lore.kernel.org/r/20240820063001.36405-10-john.ogness@linutronix.de -Signed-off-by: Petr Mladek -Signed-off-by: Sebastian Andrzej Siewior ---- - kernel/printk/printk.c | 33 ++++++++++++++++++++++++++++++++- - 1 file changed, 32 insertions(+), 1 deletion(-) - ---- a/kernel/printk/printk.c -+++ b/kernel/printk/printk.c -@@ -3549,9 +3549,11 @@ static int unregister_console_locked(str - */ - void register_console(struct console *newcon) - { -- struct console *con; -+ bool use_device_lock = (newcon->flags & CON_NBCON) && newcon->write_atomic; - bool bootcon_registered = false; - bool realcon_registered = false; -+ struct console *con; -+ unsigned long flags; - u64 init_seq; - int err; - -@@ -3639,6 +3641,19 @@ void register_console(struct console *ne - } - - /* -+ * If another context is actively using the hardware of this new -+ * console, it will not be aware of the nbcon synchronization. This -+ * is a risk that two contexts could access the hardware -+ * simultaneously if this new console is used for atomic printing -+ * and the other context is still using the hardware. -+ * -+ * Use the driver synchronization to ensure that the hardware is not -+ * in use while this new console transitions to being registered. -+ */ -+ if (use_device_lock) -+ newcon->device_lock(newcon, &flags); -+ -+ /* - * Put this console in the list - keep the - * preferred driver at the head of the list. - */ -@@ -3662,6 +3677,10 @@ void register_console(struct console *ne - * register_console() completes. - */ - -+ /* This new console is now registered. */ -+ if (use_device_lock) -+ newcon->device_unlock(newcon, flags); -+ - console_sysfs_notify(); - - /* -@@ -3690,6 +3709,8 @@ EXPORT_SYMBOL(register_console); - /* Must be called under console_list_lock(). */ - static int unregister_console_locked(struct console *console) - { -+ bool use_device_lock = (console->flags & CON_NBCON) && console->write_atomic; -+ unsigned long flags; - int res; - - lockdep_assert_console_list_lock_held(); -@@ -3708,8 +3729,18 @@ static int unregister_console_locked(str - if (!console_is_registered_locked(console)) - return -ENODEV; - -+ /* -+ * Use the driver synchronization to ensure that the hardware is not -+ * in use while this console transitions to being unregistered. -+ */ -+ if (use_device_lock) -+ console->device_lock(console, &flags); -+ - hlist_del_init_rcu(&console->node); - -+ if (use_device_lock) -+ console->device_unlock(console, flags); -+ - /* - * - * If this isn't the last console and it has CON_CONSDEV set, we diff --git a/debian/patches-rt/0010-serial-core-Provide-low-level-functions-to-lock-port.patch b/debian/patches-rt/0010-serial-core-Provide-low-level-functions-to-lock-port.patch deleted file mode 100644 index b3ec97f..0000000 --- a/debian/patches-rt/0010-serial-core-Provide-low-level-functions-to-lock-port.patch +++ /dev/null @@ -1,52 +0,0 @@ -From: John Ogness -Date: Tue, 20 Aug 2024 08:35:36 +0206 -Subject: [PATCH 10/54] serial: core: Provide low-level functions to lock port -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -It will be necessary at times for the uart nbcon console -drivers to acquire the port lock directly (without the -additional nbcon functionality of the port lock wrappers). -These are special cases such as the implementation of the -device_lock()/device_unlock() callbacks or for internal -port lock wrapper synchronization. - -Provide low-level variants __uart_port_lock_irqsave() and -__uart_port_unlock_irqrestore() for this purpose. - -Signed-off-by: John Ogness -Reviewed-by: Petr Mladek -Acked-by: Greg Kroah-Hartman -Link: https://lore.kernel.org/r/20240820063001.36405-11-john.ogness@linutronix.de -Signed-off-by: Petr Mladek -Signed-off-by: Sebastian Andrzej Siewior ---- - include/linux/serial_core.h | 18 ++++++++++++++++++ - 1 file changed, 18 insertions(+) - ---- a/include/linux/serial_core.h -+++ b/include/linux/serial_core.h -@@ -590,6 +590,24 @@ struct uart_port { - void *private_data; /* generic platform data pointer */ - }; - -+/* -+ * Only for console->device_lock()/_unlock() callbacks and internal -+ * port lock wrapper synchronization. -+ */ -+static inline void __uart_port_lock_irqsave(struct uart_port *up, unsigned long *flags) -+{ -+ spin_lock_irqsave(&up->lock, *flags); -+} -+ -+/* -+ * Only for console->device_lock()/_unlock() callbacks and internal -+ * port lock wrapper synchronization. -+ */ -+static inline void __uart_port_unlock_irqrestore(struct uart_port *up, unsigned long flags) -+{ -+ spin_unlock_irqrestore(&up->lock, flags); -+} -+ - /** - * uart_port_lock - Lock the UART port - * @up: Pointer to UART port structure diff --git a/debian/patches-rt/0011-serial-core-Introduce-wrapper-to-set-uart_port-cons.patch b/debian/patches-rt/0011-serial-core-Introduce-wrapper-to-set-uart_port-cons.patch deleted file mode 100644 index aff2c44..0000000 --- a/debian/patches-rt/0011-serial-core-Introduce-wrapper-to-set-uart_port-cons.patch +++ /dev/null @@ -1,125 +0,0 @@ -From: John Ogness -Date: Tue, 20 Aug 2024 08:35:37 +0206 -Subject: [PATCH 11/54] serial: core: Introduce wrapper to set @uart_port->cons -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -Introduce uart_port_set_cons() as a wrapper to set @cons of a -uart_port. The wrapper sets @cons under the port lock in order -to prevent @cons from disappearing while another context is -holding the port lock. This is necessary for a follow-up -commit relating to the port lock wrappers, which rely on @cons -not changing between lock and unlock. - -Signed-off-by: John Ogness -Tested-by: Théo Lebrun # EyeQ5, AMBA-PL011 -Acked-by: Greg Kroah-Hartman -Reviewed-by: Petr Mladek -Reviewed-by: Ilpo Järvinen -Link: https://lore.kernel.org/r/20240820063001.36405-12-john.ogness@linutronix.de -Signed-off-by: Petr Mladek -Signed-off-by: Sebastian Andrzej Siewior ---- - drivers/tty/serial/8250/8250_core.c | 6 +++--- - drivers/tty/serial/amba-pl011.c | 2 +- - drivers/tty/serial/serial_core.c | 16 ++++++++-------- - include/linux/serial_core.h | 17 +++++++++++++++++ - 4 files changed, 29 insertions(+), 12 deletions(-) - ---- a/drivers/tty/serial/8250/8250_core.c -+++ b/drivers/tty/serial/8250/8250_core.c -@@ -423,11 +423,11 @@ static int univ8250_console_setup(struct - - port = &serial8250_ports[co->index].port; - /* link port to console */ -- port->cons = co; -+ uart_port_set_cons(port, co); - - retval = serial8250_console_setup(port, options, false); - if (retval != 0) -- port->cons = NULL; -+ uart_port_set_cons(port, NULL); - return retval; - } - -@@ -485,7 +485,7 @@ static int univ8250_console_match(struct - continue; - - co->index = i; -- port->cons = co; -+ uart_port_set_cons(port, co); - return serial8250_console_setup(port, options, true); - } - ---- a/drivers/tty/serial/amba-pl011.c -+++ b/drivers/tty/serial/amba-pl011.c -@@ -2480,7 +2480,7 @@ static int pl011_console_match(struct co - continue; - - co->index = i; -- port->cons = co; -+ uart_port_set_cons(port, co); - return pl011_console_setup(co, options); - } - ---- a/drivers/tty/serial/serial_core.c -+++ b/drivers/tty/serial/serial_core.c -@@ -3176,8 +3176,15 @@ static int serial_core_add_one_port(stru - state->uart_port = uport; - uport->state = state; - -+ /* -+ * If this port is in use as a console then the spinlock is already -+ * initialised. -+ */ -+ if (!uart_console_registered(uport)) -+ uart_port_spin_lock_init(uport); -+ - state->pm_state = UART_PM_STATE_UNDEFINED; -- uport->cons = drv->cons; -+ uart_port_set_cons(uport, drv->cons); - uport->minor = drv->tty_driver->minor_start + uport->line; - uport->name = kasprintf(GFP_KERNEL, "%s%d", drv->dev_name, - drv->tty_driver->name_base + uport->line); -@@ -3186,13 +3193,6 @@ static int serial_core_add_one_port(stru - goto out; - } - -- /* -- * If this port is in use as a console then the spinlock is already -- * initialised. -- */ -- if (!uart_console_registered(uport)) -- uart_port_spin_lock_init(uport); -- - if (uport->cons && uport->dev) - of_console_check(uport->dev->of_node, uport->cons->name, uport->line); - ---- a/include/linux/serial_core.h -+++ b/include/linux/serial_core.h -@@ -609,6 +609,23 @@ static inline void __uart_port_unlock_ir - } - - /** -+ * uart_port_set_cons - Safely set the @cons field for a uart -+ * @up: The uart port to set -+ * @con: The new console to set to -+ * -+ * This function must be used to set @up->cons. It uses the port lock to -+ * synchronize with the port lock wrappers in order to ensure that the console -+ * cannot change or disappear while another context is holding the port lock. -+ */ -+static inline void uart_port_set_cons(struct uart_port *up, struct console *con) -+{ -+ unsigned long flags; -+ -+ __uart_port_lock_irqsave(up, &flags); -+ up->cons = con; -+ __uart_port_unlock_irqrestore(up, flags); -+} -+/** - * uart_port_lock - Lock the UART port - * @up: Pointer to UART port structure - */ diff --git a/debian/patches-rt/0012-console-Improve-console_srcu_read_flags-comments.patch b/debian/patches-rt/0012-console-Improve-console_srcu_read_flags-comments.patch deleted file mode 100644 index f591e60..0000000 --- a/debian/patches-rt/0012-console-Improve-console_srcu_read_flags-comments.patch +++ /dev/null @@ -1,75 +0,0 @@ -From: John Ogness -Date: Tue, 20 Aug 2024 08:35:38 +0206 -Subject: [PATCH 12/54] console: Improve console_srcu_read_flags() comments -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -It was not clear when exactly console_srcu_read_flags() must be -used vs. directly reading @console->flags. - -Refactor and clarify that console_srcu_read_flags() is only -needed if the console is registered or the caller is in a -context where the registration status of the console may change -(due to another context). - -The function requires the caller holds @console_srcu, which will -ensure that the caller sees an appropriate @flags value for the -registered console and that exit/cleanup routines will not run -if the console is in the process of unregistration. - -Signed-off-by: John Ogness -Reviewed-by: Petr Mladek -Link: https://lore.kernel.org/r/20240820063001.36405-13-john.ogness@linutronix.de -Signed-off-by: Petr Mladek -Signed-off-by: Sebastian Andrzej Siewior ---- - include/linux/console.h | 28 +++++++++++++++++----------- - 1 file changed, 17 insertions(+), 11 deletions(-) - ---- a/include/linux/console.h -+++ b/include/linux/console.h -@@ -446,28 +446,34 @@ extern void console_list_unlock(void) __ - extern struct hlist_head console_list; - - /** -- * console_srcu_read_flags - Locklessly read the console flags -+ * console_srcu_read_flags - Locklessly read flags of a possibly registered -+ * console - * @con: struct console pointer of console to read flags from - * -- * This function provides the necessary READ_ONCE() and data_race() -- * notation for locklessly reading the console flags. The READ_ONCE() -- * in this function matches the WRITE_ONCE() when @flags are modified -- * for registered consoles with console_srcu_write_flags(). -+ * Locklessly reading @con->flags provides a consistent read value because -+ * there is at most one CPU modifying @con->flags and that CPU is using only -+ * read-modify-write operations to do so. - * -- * Only use this function to read console flags when locklessly -- * iterating the console list via srcu. -+ * Requires console_srcu_read_lock to be held, which implies that @con might -+ * be a registered console. The purpose of holding console_srcu_read_lock is -+ * to guarantee that the console state is valid (CON_SUSPENDED/CON_ENABLED) -+ * and that no exit/cleanup routines will run if the console is currently -+ * undergoing unregistration. -+ * -+ * If the caller is holding the console_list_lock or it is _certain_ that -+ * @con is not and will not become registered, the caller may read -+ * @con->flags directly instead. - * - * Context: Any context. -+ * Return: The current value of the @con->flags field. - */ - static inline short console_srcu_read_flags(const struct console *con) - { - WARN_ON_ONCE(!console_srcu_read_lock_is_held()); - - /* -- * Locklessly reading console->flags provides a consistent -- * read value because there is at most one CPU modifying -- * console->flags and that CPU is using only read-modify-write -- * operations to do so. -+ * The READ_ONCE() matches the WRITE_ONCE() when @flags are modified -+ * for registered consoles with console_srcu_write_flags(). - */ - return data_race(READ_ONCE(con->flags)); - } diff --git a/debian/patches-rt/0013-nbcon-Add-API-to-acquire-context-for-non-printing-op.patch b/debian/patches-rt/0013-nbcon-Add-API-to-acquire-context-for-non-printing-op.patch deleted file mode 100644 index 762b44b..0000000 --- a/debian/patches-rt/0013-nbcon-Add-API-to-acquire-context-for-non-printing-op.patch +++ /dev/null @@ -1,180 +0,0 @@ -From: John Ogness -Date: Tue, 20 Aug 2024 08:35:39 +0206 -Subject: [PATCH 13/54] nbcon: Add API to acquire context for non-printing - operations -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -Provide functions nbcon_device_try_acquire() and -nbcon_device_release() which will try to acquire the nbcon -console ownership with NBCON_PRIO_NORMAL and mark it unsafe for -handover/takeover. - -These functions are to be used together with the device-specific -locking when performing non-printing activities on the console -device. They will allow synchronization against the -atomic_write() callback which will be serialized, for higher -priority contexts, only by acquiring the console context -ownership. - -Pitfalls: - -The API requires to be called in a context with migration -disabled because it uses per-CPU variables internally. - -The context is set unsafe for a takeover all the time. It -guarantees full serialization against any atomic_write() caller -except for the final flush in panic() which might try an unsafe -takeover. - -Signed-off-by: John Ogness -Reviewed-by: Petr Mladek -Link: https://lore.kernel.org/r/20240820063001.36405-14-john.ogness@linutronix.de -Signed-off-by: Petr Mladek -Signed-off-by: Sebastian Andrzej Siewior ---- - include/linux/console.h | 2 + - include/linux/printk.h | 14 +++++++++++ - kernel/printk/nbcon.c | 58 +++++++++++++++++++++++++++++++++++++++++++++++- - 3 files changed, 73 insertions(+), 1 deletion(-) - ---- a/include/linux/console.h -+++ b/include/linux/console.h -@@ -322,6 +322,7 @@ struct nbcon_write_context { - * - * @nbcon_state: State for nbcon consoles - * @nbcon_seq: Sequence number of the next record for nbcon to print -+ * @nbcon_device_ctxt: Context available for non-printing operations - * @pbufs: Pointer to nbcon private buffer - */ - struct console { -@@ -417,6 +418,7 @@ struct console { - - atomic_t __private nbcon_state; - atomic_long_t __private nbcon_seq; -+ struct nbcon_context __private nbcon_device_ctxt; - struct printk_buffers *pbufs; - }; - ---- a/include/linux/printk.h -+++ b/include/linux/printk.h -@@ -9,6 +9,8 @@ - #include - #include - -+struct console; -+ - extern const char linux_banner[]; - extern const char linux_proc_banner[]; - -@@ -198,6 +200,8 @@ extern asmlinkage void dump_stack_lvl(co - extern asmlinkage void dump_stack(void) __cold; - void printk_trigger_flush(void); - void console_try_replay_all(void); -+extern bool nbcon_device_try_acquire(struct console *con); -+extern void nbcon_device_release(struct console *con); - #else - static inline __printf(1, 0) - int vprintk(const char *s, va_list args) -@@ -280,6 +284,16 @@ static inline void printk_trigger_flush( - static inline void console_try_replay_all(void) - { - } -+ -+static inline bool nbcon_device_try_acquire(struct console *con) -+{ -+ return false; -+} -+ -+static inline void nbcon_device_release(struct console *con) -+{ -+} -+ - #endif - - bool this_cpu_in_panic(void); ---- a/kernel/printk/nbcon.c -+++ b/kernel/printk/nbcon.c -@@ -5,7 +5,9 @@ - #include - #include - #include -+#include - #include -+#include - #include "internal.h" - /* - * Printk console printing implementation for consoles which does not depend -@@ -546,6 +548,7 @@ static struct printk_buffers panic_nbcon - * nbcon_context_try_acquire - Try to acquire nbcon console - * @ctxt: The context of the caller - * -+ * Context: Under @ctxt->con->device_lock() or local_irq_save(). - * Return: True if the console was acquired. False otherwise. - * - * If the caller allowed an unsafe hostile takeover, on success the -@@ -553,7 +556,6 @@ static struct printk_buffers panic_nbcon - * in an unsafe state. Otherwise, on success the caller may assume - * the console is not in an unsafe state. - */ --__maybe_unused - static bool nbcon_context_try_acquire(struct nbcon_context *ctxt) - { - unsigned int cpu = smp_processor_id(); -@@ -1011,3 +1013,57 @@ void nbcon_free(struct console *con) - - con->pbufs = NULL; - } -+ -+/** -+ * nbcon_device_try_acquire - Try to acquire nbcon console and enter unsafe -+ * section -+ * @con: The nbcon console to acquire -+ * -+ * Context: Under the locking mechanism implemented in -+ * @con->device_lock() including disabling migration. -+ * Return: True if the console was acquired. False otherwise. -+ * -+ * Console drivers will usually use their own internal synchronization -+ * mechasism to synchronize between console printing and non-printing -+ * activities (such as setting baud rates). However, nbcon console drivers -+ * supporting atomic consoles may also want to mark unsafe sections when -+ * performing non-printing activities in order to synchronize against their -+ * atomic_write() callback. -+ * -+ * This function acquires the nbcon console using priority NBCON_PRIO_NORMAL -+ * and marks it unsafe for handover/takeover. -+ */ -+bool nbcon_device_try_acquire(struct console *con) -+{ -+ struct nbcon_context *ctxt = &ACCESS_PRIVATE(con, nbcon_device_ctxt); -+ -+ cant_migrate(); -+ -+ memset(ctxt, 0, sizeof(*ctxt)); -+ ctxt->console = con; -+ ctxt->prio = NBCON_PRIO_NORMAL; -+ -+ if (!nbcon_context_try_acquire(ctxt)) -+ return false; -+ -+ if (!nbcon_context_enter_unsafe(ctxt)) -+ return false; -+ -+ return true; -+} -+EXPORT_SYMBOL_GPL(nbcon_device_try_acquire); -+ -+/** -+ * nbcon_device_release - Exit unsafe section and release the nbcon console -+ * @con: The nbcon console acquired in nbcon_device_try_acquire() -+ */ -+void nbcon_device_release(struct console *con) -+{ -+ struct nbcon_context *ctxt = &ACCESS_PRIVATE(con, nbcon_device_ctxt); -+ -+ if (!nbcon_context_exit_unsafe(ctxt)) -+ return; -+ -+ nbcon_context_release(ctxt); -+} -+EXPORT_SYMBOL_GPL(nbcon_device_release); diff --git a/debian/patches-rt/0014-serial-core-Acquire-nbcon-context-in-port-lock-wrapp.patch b/debian/patches-rt/0014-serial-core-Acquire-nbcon-context-in-port-lock-wrapp.patch deleted file mode 100644 index 3958469..0000000 --- a/debian/patches-rt/0014-serial-core-Acquire-nbcon-context-in-port-lock-wrapp.patch +++ /dev/null @@ -1,185 +0,0 @@ -From: John Ogness -Date: Tue, 20 Aug 2024 08:35:40 +0206 -Subject: [PATCH 14/54] serial: core: Acquire nbcon context in port->lock - wrapper -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -Currently the port->lock wrappers uart_port_lock(), -uart_port_unlock() (and their variants) only lock/unlock -the spin_lock. - -If the port is an nbcon console that has implemented the -write_atomic() callback, the wrappers must also acquire/release -the console context and mark the region as unsafe. This allows -general port->lock synchronization to be synchronized against -the nbcon write_atomic() callback. - -Note that __uart_port_using_nbcon() relies on the port->lock -being held while a console is added and removed from the -console list (i.e. all uart nbcon drivers *must* take the -port->lock in their device_lock() callbacks). - -Signed-off-by: John Ogness -Acked-by: Greg Kroah-Hartman -Reviewed-by: Petr Mladek -Link: https://lore.kernel.org/r/20240820063001.36405-15-john.ogness@linutronix.de -Signed-off-by: Petr Mladek -Signed-off-by: Sebastian Andrzej Siewior ---- - include/linux/serial_core.h | 82 ++++++++++++++++++++++++++++++++++++++++++-- - 1 file changed, 80 insertions(+), 2 deletions(-) - ---- a/include/linux/serial_core.h -+++ b/include/linux/serial_core.h -@@ -11,6 +11,8 @@ - #include - #include - #include -+#include -+#include - #include - #include - #include -@@ -625,6 +627,60 @@ static inline void uart_port_set_cons(st - up->cons = con; - __uart_port_unlock_irqrestore(up, flags); - } -+ -+/* Only for internal port lock wrapper usage. */ -+static inline bool __uart_port_using_nbcon(struct uart_port *up) -+{ -+ lockdep_assert_held_once(&up->lock); -+ -+ if (likely(!uart_console(up))) -+ return false; -+ -+ /* -+ * @up->cons is only modified under the port lock. Therefore it is -+ * certain that it cannot disappear here. -+ * -+ * @up->cons->node is added/removed from the console list under the -+ * port lock. Therefore it is certain that the registration status -+ * cannot change here, thus @up->cons->flags can be read directly. -+ */ -+ if (hlist_unhashed_lockless(&up->cons->node) || -+ !(up->cons->flags & CON_NBCON) || -+ !up->cons->write_atomic) { -+ return false; -+ } -+ -+ return true; -+} -+ -+/* Only for internal port lock wrapper usage. */ -+static inline bool __uart_port_nbcon_try_acquire(struct uart_port *up) -+{ -+ if (!__uart_port_using_nbcon(up)) -+ return true; -+ -+ return nbcon_device_try_acquire(up->cons); -+} -+ -+/* Only for internal port lock wrapper usage. */ -+static inline void __uart_port_nbcon_acquire(struct uart_port *up) -+{ -+ if (!__uart_port_using_nbcon(up)) -+ return; -+ -+ while (!nbcon_device_try_acquire(up->cons)) -+ cpu_relax(); -+} -+ -+/* Only for internal port lock wrapper usage. */ -+static inline void __uart_port_nbcon_release(struct uart_port *up) -+{ -+ if (!__uart_port_using_nbcon(up)) -+ return; -+ -+ nbcon_device_release(up->cons); -+} -+ - /** - * uart_port_lock - Lock the UART port - * @up: Pointer to UART port structure -@@ -632,6 +688,7 @@ static inline void uart_port_set_cons(st - static inline void uart_port_lock(struct uart_port *up) - { - spin_lock(&up->lock); -+ __uart_port_nbcon_acquire(up); - } - - /** -@@ -641,6 +698,7 @@ static inline void uart_port_lock(struct - static inline void uart_port_lock_irq(struct uart_port *up) - { - spin_lock_irq(&up->lock); -+ __uart_port_nbcon_acquire(up); - } - - /** -@@ -651,6 +709,7 @@ static inline void uart_port_lock_irq(st - static inline void uart_port_lock_irqsave(struct uart_port *up, unsigned long *flags) - { - spin_lock_irqsave(&up->lock, *flags); -+ __uart_port_nbcon_acquire(up); - } - - /** -@@ -661,7 +720,15 @@ static inline void uart_port_lock_irqsav - */ - static inline bool uart_port_trylock(struct uart_port *up) - { -- return spin_trylock(&up->lock); -+ if (!spin_trylock(&up->lock)) -+ return false; -+ -+ if (!__uart_port_nbcon_try_acquire(up)) { -+ spin_unlock(&up->lock); -+ return false; -+ } -+ -+ return true; - } - - /** -@@ -673,7 +740,15 @@ static inline bool uart_port_trylock(str - */ - static inline bool uart_port_trylock_irqsave(struct uart_port *up, unsigned long *flags) - { -- return spin_trylock_irqsave(&up->lock, *flags); -+ if (!spin_trylock_irqsave(&up->lock, *flags)) -+ return false; -+ -+ if (!__uart_port_nbcon_try_acquire(up)) { -+ spin_unlock_irqrestore(&up->lock, *flags); -+ return false; -+ } -+ -+ return true; - } - - /** -@@ -682,6 +757,7 @@ static inline bool uart_port_trylock_irq - */ - static inline void uart_port_unlock(struct uart_port *up) - { -+ __uart_port_nbcon_release(up); - spin_unlock(&up->lock); - } - -@@ -691,6 +767,7 @@ static inline void uart_port_unlock(stru - */ - static inline void uart_port_unlock_irq(struct uart_port *up) - { -+ __uart_port_nbcon_release(up); - spin_unlock_irq(&up->lock); - } - -@@ -701,6 +778,7 @@ static inline void uart_port_unlock_irq( - */ - static inline void uart_port_unlock_irqrestore(struct uart_port *up, unsigned long flags) - { -+ __uart_port_nbcon_release(up); - spin_unlock_irqrestore(&up->lock, flags); - } - diff --git a/debian/patches-rt/0015-printk-nbcon-Do-not-rely-on-proxy-headers.patch b/debian/patches-rt/0015-printk-nbcon-Do-not-rely-on-proxy-headers.patch deleted file mode 100644 index e3ef6ed..0000000 --- a/debian/patches-rt/0015-printk-nbcon-Do-not-rely-on-proxy-headers.patch +++ /dev/null @@ -1,90 +0,0 @@ -From: John Ogness -Date: Tue, 20 Aug 2024 08:35:41 +0206 -Subject: [PATCH 15/54] printk: nbcon: Do not rely on proxy headers -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -The headers kernel.h, serial_core.h, and console.h allow for the -definitions of many types and functions from other headers. -Rather than relying on these as proxy headers, explicitly -include all headers providing needed definitions. Also sort the -list alphabetically to be able to easily detect duplicates. - -Suggested-by: Andy Shevchenko -Signed-off-by: John Ogness -Reviewed-by: Andy Shevchenko -Acked-by: Petr Mladek -Link: https://lore.kernel.org/r/20240820063001.36405-16-john.ogness@linutronix.de -Signed-off-by: Petr Mladek -Signed-off-by: Sebastian Andrzej Siewior ---- - kernel/printk/internal.h | 8 ++++++-- - kernel/printk/nbcon.c | 13 ++++++++++++- - kernel/printk/printk_ringbuffer.h | 2 ++ - 3 files changed, 20 insertions(+), 3 deletions(-) - ---- a/kernel/printk/internal.h -+++ b/kernel/printk/internal.h -@@ -2,11 +2,12 @@ - /* - * internal.h - printk internal definitions - */ --#include - #include --#include "printk_ringbuffer.h" -+#include -+#include - - #if defined(CONFIG_PRINTK) && defined(CONFIG_SYSCTL) -+struct ctl_table; - void __init printk_sysctl_init(void); - int devkmsg_sysctl_set_loglvl(const struct ctl_table *table, int write, - void *buffer, size_t *lenp, loff_t *ppos); -@@ -43,6 +44,9 @@ enum printk_info_flags { - LOG_CONT = 8, /* text is a fragment of a continuation line */ - }; - -+struct printk_ringbuffer; -+struct dev_printk_info; -+ - extern struct printk_ringbuffer *prb; - - __printf(4, 0) ---- a/kernel/printk/nbcon.c -+++ b/kernel/printk/nbcon.c -@@ -2,13 +2,24 @@ - // Copyright (C) 2022 Linutronix GmbH, John Ogness - // Copyright (C) 2022 Intel, Thomas Gleixner - --#include -+#include -+#include - #include - #include -+#include - #include -+#include -+#include -+#include -+#include -+#include - #include -+#include -+#include - #include -+#include - #include "internal.h" -+#include "printk_ringbuffer.h" - /* - * Printk console printing implementation for consoles which does not depend - * on the legacy style console_lock mechanism. ---- a/kernel/printk/printk_ringbuffer.h -+++ b/kernel/printk/printk_ringbuffer.h -@@ -5,6 +5,8 @@ - - #include - #include -+#include -+#include - - /* - * Meta information about each stored message. diff --git a/debian/patches-rt/0016-printk-Make-console_is_usable-available-to-nbcon.c.patch b/debian/patches-rt/0016-printk-Make-console_is_usable-available-to-nbcon.c.patch deleted file mode 100644 index 897a36c..0000000 --- a/debian/patches-rt/0016-printk-Make-console_is_usable-available-to-nbcon.c.patch +++ /dev/null @@ -1,105 +0,0 @@ -From: John Ogness -Date: Tue, 20 Aug 2024 08:35:42 +0206 -Subject: [PATCH 16/54] printk: Make console_is_usable() available to nbcon.c -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -Move console_is_usable() as-is into internal.h so that it can -be used by nbcon printing functions as well. - -Signed-off-by: John Ogness -Reviewed-by: Petr Mladek -Link: https://lore.kernel.org/r/20240820063001.36405-17-john.ogness@linutronix.de -Signed-off-by: Petr Mladek -Signed-off-by: Sebastian Andrzej Siewior ---- - kernel/printk/internal.h | 32 ++++++++++++++++++++++++++++++++ - kernel/printk/printk.c | 30 ------------------------------ - 2 files changed, 32 insertions(+), 30 deletions(-) - ---- a/kernel/printk/internal.h -+++ b/kernel/printk/internal.h -@@ -84,6 +84,36 @@ void nbcon_seq_force(struct console *con - bool nbcon_alloc(struct console *con); - void nbcon_free(struct console *con); - -+/* -+ * Check if the given console is currently capable and allowed to print -+ * records. -+ * -+ * Requires the console_srcu_read_lock. -+ */ -+static inline bool console_is_usable(struct console *con) -+{ -+ short flags = console_srcu_read_flags(con); -+ -+ if (!(flags & CON_ENABLED)) -+ return false; -+ -+ if ((flags & CON_SUSPENDED)) -+ return false; -+ -+ if (!con->write) -+ return false; -+ -+ /* -+ * Console drivers may assume that per-cpu resources have been -+ * allocated. So unless they're explicitly marked as being able to -+ * cope (CON_ANYTIME) don't call them until this CPU is officially up. -+ */ -+ if (!cpu_online(raw_smp_processor_id()) && !(flags & CON_ANYTIME)) -+ return false; -+ -+ return true; -+} -+ - #else - - #define PRINTK_PREFIX_MAX 0 -@@ -104,6 +134,8 @@ static inline void nbcon_seq_force(struc - static inline bool nbcon_alloc(struct console *con) { return false; } - static inline void nbcon_free(struct console *con) { } - -+static inline bool console_is_usable(struct console *con) { return false; } -+ - #endif /* CONFIG_PRINTK */ - - extern struct printk_buffers printk_shared_pbufs; ---- a/kernel/printk/printk.c -+++ b/kernel/printk/printk.c -@@ -2768,36 +2768,6 @@ int is_console_locked(void) - } - EXPORT_SYMBOL(is_console_locked); - --/* -- * Check if the given console is currently capable and allowed to print -- * records. -- * -- * Requires the console_srcu_read_lock. -- */ --static inline bool console_is_usable(struct console *con) --{ -- short flags = console_srcu_read_flags(con); -- -- if (!(flags & CON_ENABLED)) -- return false; -- -- if ((flags & CON_SUSPENDED)) -- return false; -- -- if (!con->write) -- return false; -- -- /* -- * Console drivers may assume that per-cpu resources have been -- * allocated. So unless they're explicitly marked as being able to -- * cope (CON_ANYTIME) don't call them until this CPU is officially up. -- */ -- if (!cpu_online(raw_smp_processor_id()) && !(flags & CON_ANYTIME)) -- return false; -- -- return true; --} -- - static void __console_unlock(void) - { - console_locked = 0; diff --git a/debian/patches-rt/0017-printk-Let-console_is_usable-handle-nbcon.patch b/debian/patches-rt/0017-printk-Let-console_is_usable-handle-nbcon.patch deleted file mode 100644 index 42f6631..0000000 --- a/debian/patches-rt/0017-printk-Let-console_is_usable-handle-nbcon.patch +++ /dev/null @@ -1,45 +0,0 @@ -From: John Ogness -Date: Tue, 20 Aug 2024 08:35:43 +0206 -Subject: [PATCH 17/54] printk: Let console_is_usable() handle nbcon -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -The nbcon consoles use a different printing callback. For nbcon -consoles, check for the write_atomic() callback instead of -write(). - -Signed-off-by: John Ogness -Reviewed-by: Petr Mladek -Link: https://lore.kernel.org/r/20240820063001.36405-18-john.ogness@linutronix.de -Signed-off-by: Petr Mladek -Signed-off-by: Sebastian Andrzej Siewior ---- - kernel/printk/internal.h | 11 +++++++++-- - 1 file changed, 9 insertions(+), 2 deletions(-) - ---- a/kernel/printk/internal.h -+++ b/kernel/printk/internal.h -@@ -86,6 +86,8 @@ void nbcon_free(struct console *con); - - /* - * Check if the given console is currently capable and allowed to print -+ * records. Note that this function does not consider the current context, -+ * which can also play a role in deciding if @con can be used to print - * records. - * - * Requires the console_srcu_read_lock. -@@ -100,8 +102,13 @@ static inline bool console_is_usable(str - if ((flags & CON_SUSPENDED)) - return false; - -- if (!con->write) -- return false; -+ if (flags & CON_NBCON) { -+ if (!con->write_atomic) -+ return false; -+ } else { -+ if (!con->write) -+ return false; -+ } - - /* - * Console drivers may assume that per-cpu resources have been diff --git a/debian/patches-rt/0018-printk-Add-flags-argument-for-console_is_usable.patch b/debian/patches-rt/0018-printk-Add-flags-argument-for-console_is_usable.patch deleted file mode 100644 index 30ff63e..0000000 --- a/debian/patches-rt/0018-printk-Add-flags-argument-for-console_is_usable.patch +++ /dev/null @@ -1,69 +0,0 @@ -From: John Ogness -Date: Tue, 20 Aug 2024 08:35:44 +0206 -Subject: [PATCH 18/54] printk: Add @flags argument for console_is_usable() -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -The caller of console_is_usable() usually needs @console->flags -for its own checks. Rather than having console_is_usable() read -its own copy, make the caller pass in the @flags. This also -ensures that the caller saw the same @flags value. - -Signed-off-by: John Ogness -Reviewed-by: Petr Mladek -Link: https://lore.kernel.org/r/20240820063001.36405-19-john.ogness@linutronix.de -Signed-off-by: Petr Mladek -Signed-off-by: Sebastian Andrzej Siewior ---- - kernel/printk/internal.h | 8 ++------ - kernel/printk/printk.c | 5 +++-- - 2 files changed, 5 insertions(+), 8 deletions(-) - ---- a/kernel/printk/internal.h -+++ b/kernel/printk/internal.h -@@ -89,13 +89,9 @@ void nbcon_free(struct console *con); - * records. Note that this function does not consider the current context, - * which can also play a role in deciding if @con can be used to print - * records. -- * -- * Requires the console_srcu_read_lock. - */ --static inline bool console_is_usable(struct console *con) -+static inline bool console_is_usable(struct console *con, short flags) - { -- short flags = console_srcu_read_flags(con); -- - if (!(flags & CON_ENABLED)) - return false; - -@@ -141,7 +137,7 @@ static inline void nbcon_seq_force(struc - static inline bool nbcon_alloc(struct console *con) { return false; } - static inline void nbcon_free(struct console *con) { } - --static inline bool console_is_usable(struct console *con) { return false; } -+static inline bool console_is_usable(struct console *con, short flags) { return false; } - - #endif /* CONFIG_PRINTK */ - ---- a/kernel/printk/printk.c -+++ b/kernel/printk/printk.c -@@ -3013,9 +3013,10 @@ static bool console_flush_all(bool do_co - - cookie = console_srcu_read_lock(); - for_each_console_srcu(con) { -+ short flags = console_srcu_read_flags(con); - bool progress; - -- if (!console_is_usable(con)) -+ if (!console_is_usable(con, flags)) - continue; - any_usable = true; - -@@ -3926,7 +3927,7 @@ static bool __pr_flush(struct console *c - * that they make forward progress, so only increment - * @diff for usable consoles. - */ -- if (!console_is_usable(c)) -+ if (!console_is_usable(c, flags)) - continue; - - if (flags & CON_NBCON) { diff --git a/debian/patches-rt/0019-printk-nbcon-Add-helper-to-assign-priority-based-on-.patch b/debian/patches-rt/0019-printk-nbcon-Add-helper-to-assign-priority-based-on-.patch deleted file mode 100644 index 161cf44..0000000 --- a/debian/patches-rt/0019-printk-nbcon-Add-helper-to-assign-priority-based-on-.patch +++ /dev/null @@ -1,72 +0,0 @@ -From: John Ogness -Date: Tue, 20 Aug 2024 08:35:45 +0206 -Subject: [PATCH 19/54] printk: nbcon: Add helper to assign priority based on - CPU state -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -Add a helper function to use the current state of the CPU to -determine which priority to assign to the printing context. - -The EMERGENCY priority handling is added in a follow-up commit. -It will use a per-CPU variable. - -Note: nbcon_device_try_acquire(), which is used by console - drivers to acquire the nbcon console for non-printing - activities, is hard-coded to always use NORMAL priority. - -Signed-off-by: John Ogness -Reviewed-by: Petr Mladek -Link: https://lore.kernel.org/r/20240820063001.36405-20-john.ogness@linutronix.de -Signed-off-by: Petr Mladek -Signed-off-by: Sebastian Andrzej Siewior ---- - kernel/printk/internal.h | 2 ++ - kernel/printk/nbcon.c | 19 +++++++++++++++++++ - 2 files changed, 21 insertions(+) - ---- a/kernel/printk/internal.h -+++ b/kernel/printk/internal.h -@@ -83,6 +83,7 @@ u64 nbcon_seq_read(struct console *con); - void nbcon_seq_force(struct console *con, u64 seq); - bool nbcon_alloc(struct console *con); - void nbcon_free(struct console *con); -+enum nbcon_prio nbcon_get_default_prio(void); - - /* - * Check if the given console is currently capable and allowed to print -@@ -136,6 +137,7 @@ static inline u64 nbcon_seq_read(struct - static inline void nbcon_seq_force(struct console *con, u64 seq) { } - static inline bool nbcon_alloc(struct console *con) { return false; } - static inline void nbcon_free(struct console *con) { } -+static inline enum nbcon_prio nbcon_get_default_prio(void) { return NBCON_PRIO_NONE; } - - static inline bool console_is_usable(struct console *con, short flags) { return false; } - ---- a/kernel/printk/nbcon.c -+++ b/kernel/printk/nbcon.c -@@ -974,6 +974,25 @@ static bool nbcon_emit_next_record(struc - } - - /** -+ * nbcon_get_default_prio - The appropriate nbcon priority to use for nbcon -+ * printing on the current CPU -+ * -+ * Context: Any context. -+ * Return: The nbcon_prio to use for acquiring an nbcon console in this -+ * context for printing. -+ * -+ * The function is safe for reading per-CPU data in any context because -+ * preemption is disabled if the current CPU is in the panic state. -+ */ -+enum nbcon_prio nbcon_get_default_prio(void) -+{ -+ if (this_cpu_in_panic()) -+ return NBCON_PRIO_PANIC; -+ -+ return NBCON_PRIO_NORMAL; -+} -+ -+/** - * nbcon_alloc - Allocate and init the nbcon console specific data - * @con: Console to initialize - * diff --git a/debian/patches-rt/0020-printk-nbcon-Provide-function-to-flush-using-write_a.patch b/debian/patches-rt/0020-printk-nbcon-Provide-function-to-flush-using-write_a.patch deleted file mode 100644 index 5ea3f79..0000000 --- a/debian/patches-rt/0020-printk-nbcon-Provide-function-to-flush-using-write_a.patch +++ /dev/null @@ -1,225 +0,0 @@ -From: Thomas Gleixner -Date: Tue, 20 Aug 2024 08:35:46 +0206 -Subject: [PATCH 20/54] printk: nbcon: Provide function to flush using - write_atomic() -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -Provide nbcon_atomic_flush_pending() to perform flushing of all -registered nbcon consoles using their write_atomic() callback. - -Unlike console_flush_all(), nbcon_atomic_flush_pending() will -only flush up through the newest record at the time of the -call. This prevents a CPU from printing unbounded when other -CPUs are adding records. If new records are added while -flushing, it is expected that the dedicated printer threads -will print those records. If the printer thread is not -available (which is always the case at this point in the -rework), nbcon_atomic_flush_pending() _will_ flush all records -in the ringbuffer. - -Unlike console_flush_all(), nbcon_atomic_flush_pending() will -fully flush one console before flushing the next. This helps to -guarantee that a block of pending records (such as a stack -trace in an emergency situation) can be printed atomically at -once before releasing console ownership. - -nbcon_atomic_flush_pending() is safe in any context because it -uses write_atomic() and acquires with unsafe_takeover disabled. - -Co-developed-by: John Ogness -Signed-off-by: John Ogness -Signed-off-by: Thomas Gleixner (Intel) -Reviewed-by: Petr Mladek -Link: https://lore.kernel.org/r/20240820063001.36405-21-john.ogness@linutronix.de -Signed-off-by: Petr Mladek -Signed-off-by: Sebastian Andrzej Siewior ---- - kernel/printk/internal.h | 2 - kernel/printk/nbcon.c | 151 ++++++++++++++++++++++++++++++++++++++++++++++- - 2 files changed, 152 insertions(+), 1 deletion(-) - ---- a/kernel/printk/internal.h -+++ b/kernel/printk/internal.h -@@ -84,6 +84,7 @@ void nbcon_seq_force(struct console *con - bool nbcon_alloc(struct console *con); - void nbcon_free(struct console *con); - enum nbcon_prio nbcon_get_default_prio(void); -+void nbcon_atomic_flush_pending(void); - - /* - * Check if the given console is currently capable and allowed to print -@@ -138,6 +139,7 @@ static inline void nbcon_seq_force(struc - static inline bool nbcon_alloc(struct console *con) { return false; } - static inline void nbcon_free(struct console *con) { } - static inline enum nbcon_prio nbcon_get_default_prio(void) { return NBCON_PRIO_NONE; } -+static inline void nbcon_atomic_flush_pending(void) { } - - static inline bool console_is_usable(struct console *con, short flags) { return false; } - ---- a/kernel/printk/nbcon.c -+++ b/kernel/printk/nbcon.c -@@ -886,7 +886,6 @@ EXPORT_SYMBOL_GPL(nbcon_exit_unsafe); - * When true is returned, @wctxt->ctxt.backlog indicates whether there are - * still records pending in the ringbuffer, - */ --__maybe_unused - static bool nbcon_emit_next_record(struct nbcon_write_context *wctxt) - { - struct nbcon_context *ctxt = &ACCESS_PRIVATE(wctxt, ctxt); -@@ -992,6 +991,156 @@ enum nbcon_prio nbcon_get_default_prio(v - return NBCON_PRIO_NORMAL; - } - -+/* -+ * __nbcon_atomic_flush_pending_con - Flush specified nbcon console using its -+ * write_atomic() callback -+ * @con: The nbcon console to flush -+ * @stop_seq: Flush up until this record -+ * -+ * Return: 0 if @con was flushed up to @stop_seq Otherwise, error code on -+ * failure. -+ * -+ * Errors: -+ * -+ * -EPERM: Unable to acquire console ownership. -+ * -+ * -EAGAIN: Another context took over ownership while printing. -+ * -+ * -ENOENT: A record before @stop_seq is not available. -+ * -+ * If flushing up to @stop_seq was not successful, it only makes sense for the -+ * caller to try again when -EAGAIN was returned. When -EPERM is returned, -+ * this context is not allowed to acquire the console. When -ENOENT is -+ * returned, it cannot be expected that the unfinalized record will become -+ * available. -+ */ -+static int __nbcon_atomic_flush_pending_con(struct console *con, u64 stop_seq) -+{ -+ struct nbcon_write_context wctxt = { }; -+ struct nbcon_context *ctxt = &ACCESS_PRIVATE(&wctxt, ctxt); -+ int err = 0; -+ -+ ctxt->console = con; -+ ctxt->spinwait_max_us = 2000; -+ ctxt->prio = nbcon_get_default_prio(); -+ -+ if (!nbcon_context_try_acquire(ctxt)) -+ return -EPERM; -+ -+ while (nbcon_seq_read(con) < stop_seq) { -+ /* -+ * nbcon_emit_next_record() returns false when the console was -+ * handed over or taken over. In both cases the context is no -+ * longer valid. -+ */ -+ if (!nbcon_emit_next_record(&wctxt)) -+ return -EAGAIN; -+ -+ if (!ctxt->backlog) { -+ /* Are there reserved but not yet finalized records? */ -+ if (nbcon_seq_read(con) < stop_seq) -+ err = -ENOENT; -+ break; -+ } -+ } -+ -+ nbcon_context_release(ctxt); -+ return err; -+} -+ -+/** -+ * nbcon_atomic_flush_pending_con - Flush specified nbcon console using its -+ * write_atomic() callback -+ * @con: The nbcon console to flush -+ * @stop_seq: Flush up until this record -+ * -+ * This will stop flushing before @stop_seq if another context has ownership. -+ * That context is then responsible for the flushing. Likewise, if new records -+ * are added while this context was flushing and there is no other context -+ * to handle the printing, this context must also flush those records. -+ */ -+static void nbcon_atomic_flush_pending_con(struct console *con, u64 stop_seq) -+{ -+ unsigned long flags; -+ int err; -+ -+again: -+ /* -+ * Atomic flushing does not use console driver synchronization (i.e. -+ * it does not hold the port lock for uart consoles). Therefore IRQs -+ * must be disabled to avoid being interrupted and then calling into -+ * a driver that will deadlock trying to acquire console ownership. -+ */ -+ local_irq_save(flags); -+ -+ err = __nbcon_atomic_flush_pending_con(con, stop_seq); -+ -+ local_irq_restore(flags); -+ -+ /* -+ * If there was a new owner (-EPERM, -EAGAIN), that context is -+ * responsible for completing. -+ * -+ * Do not wait for records not yet finalized (-ENOENT) to avoid a -+ * possible deadlock. They will either get flushed by the writer or -+ * eventually skipped on panic CPU. -+ */ -+ if (err) -+ return; -+ -+ /* -+ * If flushing was successful but more records are available, this -+ * context must flush those remaining records because there is no -+ * other context that will do it. -+ */ -+ if (prb_read_valid(prb, nbcon_seq_read(con), NULL)) { -+ stop_seq = prb_next_reserve_seq(prb); -+ goto again; -+ } -+} -+ -+/** -+ * __nbcon_atomic_flush_pending - Flush all nbcon consoles using their -+ * write_atomic() callback -+ * @stop_seq: Flush up until this record -+ */ -+static void __nbcon_atomic_flush_pending(u64 stop_seq) -+{ -+ struct console *con; -+ int cookie; -+ -+ cookie = console_srcu_read_lock(); -+ for_each_console_srcu(con) { -+ short flags = console_srcu_read_flags(con); -+ -+ if (!(flags & CON_NBCON)) -+ continue; -+ -+ if (!console_is_usable(con, flags)) -+ continue; -+ -+ if (nbcon_seq_read(con) >= stop_seq) -+ continue; -+ -+ nbcon_atomic_flush_pending_con(con, stop_seq); -+ } -+ console_srcu_read_unlock(cookie); -+} -+ -+/** -+ * nbcon_atomic_flush_pending - Flush all nbcon consoles using their -+ * write_atomic() callback -+ * -+ * Flush the backlog up through the currently newest record. Any new -+ * records added while flushing will not be flushed if there is another -+ * context available to handle the flushing. This is to avoid one CPU -+ * printing unbounded because other CPUs continue to add records. -+ */ -+void nbcon_atomic_flush_pending(void) -+{ -+ __nbcon_atomic_flush_pending(prb_next_reserve_seq(prb)); -+} -+ - /** - * nbcon_alloc - Allocate and init the nbcon console specific data - * @con: Console to initialize diff --git a/debian/patches-rt/0021-printk-Track-registered-boot-consoles.patch b/debian/patches-rt/0021-printk-Track-registered-boot-consoles.patch deleted file mode 100644 index 9f7abbf..0000000 --- a/debian/patches-rt/0021-printk-Track-registered-boot-consoles.patch +++ /dev/null @@ -1,82 +0,0 @@ -From: John Ogness -Date: Tue, 20 Aug 2024 08:35:47 +0206 -Subject: [PATCH 21/54] printk: Track registered boot consoles -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -Unfortunately it is not known if a boot console and a regular -(legacy or nbcon) console use the same hardware. For this reason -they must not be allowed to print simultaneously. - -For legacy consoles this is not an issue because they are -already synchronized with the boot consoles using the console -lock. However nbcon consoles can be triggered separately. - -Add a global flag @have_boot_console to identify if any boot -consoles are registered. This will be used in follow-up commits -to ensure that boot consoles and nbcon consoles cannot print -simultaneously. - -Signed-off-by: John Ogness -Reviewed-by: Petr Mladek -Link: https://lore.kernel.org/r/20240820063001.36405-22-john.ogness@linutronix.de -Signed-off-by: Petr Mladek -Signed-off-by: Sebastian Andrzej Siewior ---- - kernel/printk/printk.c | 24 ++++++++++++++++++++++++ - 1 file changed, 24 insertions(+) - ---- a/kernel/printk/printk.c -+++ b/kernel/printk/printk.c -@@ -463,6 +463,14 @@ static int console_msg_format = MSG_FORM - /* syslog_lock protects syslog_* variables and write access to clear_seq. */ - static DEFINE_MUTEX(syslog_lock); - -+/* -+ * Specifies if a boot console is registered. If boot consoles are present, -+ * nbcon consoles cannot print simultaneously and must be synchronized by -+ * the console lock. This is because boot consoles and nbcon consoles may -+ * have mapped the same hardware. -+ */ -+static bool have_boot_console; -+ - #ifdef CONFIG_PRINTK - DECLARE_WAIT_QUEUE_HEAD(log_wait); - /* All 3 protected by @syslog_lock. */ -@@ -3611,6 +3619,9 @@ void register_console(struct console *ne - newcon->seq = init_seq; - } - -+ if (newcon->flags & CON_BOOT) -+ have_boot_console = true; -+ - /* - * If another context is actively using the hardware of this new - * console, it will not be aware of the nbcon synchronization. This -@@ -3681,7 +3692,9 @@ EXPORT_SYMBOL(register_console); - static int unregister_console_locked(struct console *console) - { - bool use_device_lock = (console->flags & CON_NBCON) && console->write_atomic; -+ bool found_boot_con = false; - unsigned long flags; -+ struct console *c; - int res; - - lockdep_assert_console_list_lock_held(); -@@ -3739,6 +3752,17 @@ static int unregister_console_locked(str - if (console->exit) - res = console->exit(console); - -+ /* -+ * With this console gone, the global flags tracking registered -+ * console types may have changed. Update them. -+ */ -+ for_each_console(c) { -+ if (c->flags & CON_BOOT) -+ found_boot_con = true; -+ } -+ if (!found_boot_con) -+ have_boot_console = found_boot_con; -+ - return res; - } - diff --git a/debian/patches-rt/0022-printk-nbcon-Use-nbcon-consoles-in-console_flush_all.patch b/debian/patches-rt/0022-printk-nbcon-Use-nbcon-consoles-in-console_flush_all.patch deleted file mode 100644 index 8fa64f1..0000000 --- a/debian/patches-rt/0022-printk-nbcon-Use-nbcon-consoles-in-console_flush_all.patch +++ /dev/null @@ -1,212 +0,0 @@ -From: John Ogness -Date: Tue, 20 Aug 2024 08:35:48 +0206 -Subject: [PATCH 22/54] printk: nbcon: Use nbcon consoles in - console_flush_all() -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -Allow nbcon consoles to print messages in the legacy printk() -caller context (printing via unlock) by integrating them into -console_flush_all(). The write_atomic() callback is used for -printing. - -Provide nbcon_legacy_emit_next_record(), which acts as the -nbcon variant of console_emit_next_record(). Call this variant -within console_flush_all() for nbcon consoles. Since nbcon -consoles use their own @nbcon_seq variable to track the next -record to print, this also must be appropriately handled in -console_flush_all(). - -Note that the legacy printing logic uses @handover to detect -handovers for printing all consoles. For nbcon consoles, -handovers/takeovers occur on a per-console basis and thus do -not cause the console_flush_all() loop to abort. - -Signed-off-by: John Ogness -Reviewed-by: Petr Mladek -Link: https://lore.kernel.org/r/20240820063001.36405-23-john.ogness@linutronix.de -Signed-off-by: Petr Mladek -Signed-off-by: Sebastian Andrzej Siewior ---- - kernel/printk/internal.h | 6 +++ - kernel/printk/nbcon.c | 87 +++++++++++++++++++++++++++++++++++++++++++++++ - kernel/printk/printk.c | 17 ++++++--- - 3 files changed, 105 insertions(+), 5 deletions(-) - ---- a/kernel/printk/internal.h -+++ b/kernel/printk/internal.h -@@ -78,6 +78,8 @@ void defer_console_output(void); - - u16 printk_parse_prefix(const char *text, int *level, - enum printk_info_flags *flags); -+void console_lock_spinning_enable(void); -+int console_lock_spinning_disable_and_check(int cookie); - - u64 nbcon_seq_read(struct console *con); - void nbcon_seq_force(struct console *con, u64 seq); -@@ -85,6 +87,8 @@ bool nbcon_alloc(struct console *con); - void nbcon_free(struct console *con); - enum nbcon_prio nbcon_get_default_prio(void); - void nbcon_atomic_flush_pending(void); -+bool nbcon_legacy_emit_next_record(struct console *con, bool *handover, -+ int cookie); - - /* - * Check if the given console is currently capable and allowed to print -@@ -140,6 +144,8 @@ static inline bool nbcon_alloc(struct co - static inline void nbcon_free(struct console *con) { } - static inline enum nbcon_prio nbcon_get_default_prio(void) { return NBCON_PRIO_NONE; } - static inline void nbcon_atomic_flush_pending(void) { } -+static inline bool nbcon_legacy_emit_next_record(struct console *con, bool *handover, -+ int cookie) { return false; } - - static inline bool console_is_usable(struct console *con, short flags) { return false; } - ---- a/kernel/printk/nbcon.c -+++ b/kernel/printk/nbcon.c -@@ -992,6 +992,93 @@ enum nbcon_prio nbcon_get_default_prio(v - } - - /* -+ * nbcon_atomic_emit_one - Print one record for an nbcon console using the -+ * write_atomic() callback -+ * @wctxt: An initialized write context struct to use for this context -+ * -+ * Return: True, when a record has been printed and there are still -+ * pending records. The caller might want to continue flushing. -+ * -+ * False, when there is no pending record, or when the console -+ * context cannot be acquired, or the ownership has been lost. -+ * The caller should give up. Either the job is done, cannot be -+ * done, or will be handled by the owning context. -+ * -+ * This is an internal helper to handle the locking of the console before -+ * calling nbcon_emit_next_record(). -+ */ -+static bool nbcon_atomic_emit_one(struct nbcon_write_context *wctxt) -+{ -+ struct nbcon_context *ctxt = &ACCESS_PRIVATE(wctxt, ctxt); -+ -+ if (!nbcon_context_try_acquire(ctxt)) -+ return false; -+ -+ /* -+ * nbcon_emit_next_record() returns false when the console was -+ * handed over or taken over. In both cases the context is no -+ * longer valid. -+ * -+ * The higher priority printing context takes over responsibility -+ * to print the pending records. -+ */ -+ if (!nbcon_emit_next_record(wctxt)) -+ return false; -+ -+ nbcon_context_release(ctxt); -+ -+ return ctxt->backlog; -+} -+ -+/** -+ * nbcon_legacy_emit_next_record - Print one record for an nbcon console -+ * in legacy contexts -+ * @con: The console to print on -+ * @handover: Will be set to true if a printk waiter has taken over the -+ * console_lock, in which case the caller is no longer holding -+ * both the console_lock and the SRCU read lock. Otherwise it -+ * is set to false. -+ * @cookie: The cookie from the SRCU read lock. -+ * -+ * Context: Any context except NMI. -+ * Return: True, when a record has been printed and there are still -+ * pending records. The caller might want to continue flushing. -+ * -+ * False, when there is no pending record, or when the console -+ * context cannot be acquired, or the ownership has been lost. -+ * The caller should give up. Either the job is done, cannot be -+ * done, or will be handled by the owning context. -+ * -+ * This function is meant to be called by console_flush_all() to print records -+ * on nbcon consoles from legacy context (printing via console unlocking). -+ * Essentially it is the nbcon version of console_emit_next_record(). -+ */ -+bool nbcon_legacy_emit_next_record(struct console *con, bool *handover, -+ int cookie) -+{ -+ struct nbcon_write_context wctxt = { }; -+ struct nbcon_context *ctxt = &ACCESS_PRIVATE(&wctxt, ctxt); -+ unsigned long flags; -+ bool progress; -+ -+ /* Use the same procedure as console_emit_next_record(). */ -+ printk_safe_enter_irqsave(flags); -+ console_lock_spinning_enable(); -+ stop_critical_timings(); -+ -+ ctxt->console = con; -+ ctxt->prio = nbcon_get_default_prio(); -+ -+ progress = nbcon_atomic_emit_one(&wctxt); -+ -+ start_critical_timings(); -+ *handover = console_lock_spinning_disable_and_check(cookie); -+ printk_safe_exit_irqrestore(flags); -+ -+ return progress; -+} -+ -+/** - * __nbcon_atomic_flush_pending_con - Flush specified nbcon console using its - * write_atomic() callback - * @con: The nbcon console to flush ---- a/kernel/printk/printk.c -+++ b/kernel/printk/printk.c -@@ -1860,7 +1860,7 @@ static bool console_waiter; - * there may be a waiter spinning (like a spinlock). Also it must be - * ready to hand over the lock at the end of the section. - */ --static void console_lock_spinning_enable(void) -+void console_lock_spinning_enable(void) - { - /* - * Do not use spinning in panic(). The panic CPU wants to keep the lock. -@@ -1899,7 +1899,7 @@ static void console_lock_spinning_enable - * - * Return: 1 if the lock rights were passed, 0 otherwise. - */ --static int console_lock_spinning_disable_and_check(int cookie) -+int console_lock_spinning_disable_and_check(int cookie) - { - int waiter; - -@@ -3022,13 +3022,20 @@ static bool console_flush_all(bool do_co - cookie = console_srcu_read_lock(); - for_each_console_srcu(con) { - short flags = console_srcu_read_flags(con); -+ u64 printk_seq; - bool progress; - - if (!console_is_usable(con, flags)) - continue; - any_usable = true; - -- progress = console_emit_next_record(con, handover, cookie); -+ if (flags & CON_NBCON) { -+ progress = nbcon_legacy_emit_next_record(con, handover, cookie); -+ printk_seq = nbcon_seq_read(con); -+ } else { -+ progress = console_emit_next_record(con, handover, cookie); -+ printk_seq = con->seq; -+ } - - /* - * If a handover has occurred, the SRCU read lock -@@ -3038,8 +3045,8 @@ static bool console_flush_all(bool do_co - return false; - - /* Track the next of the highest seq flushed. */ -- if (con->seq > *next_seq) -- *next_seq = con->seq; -+ if (printk_seq > *next_seq) -+ *next_seq = printk_seq; - - if (!progress) - continue; diff --git a/debian/patches-rt/0023-printk-Add-is_printk_legacy_deferred.patch b/debian/patches-rt/0023-printk-Add-is_printk_legacy_deferred.patch deleted file mode 100644 index 4d33312..0000000 --- a/debian/patches-rt/0023-printk-Add-is_printk_legacy_deferred.patch +++ /dev/null @@ -1,68 +0,0 @@ -From: John Ogness -Date: Tue, 20 Aug 2024 08:35:49 +0206 -Subject: [PATCH 23/54] printk: Add is_printk_legacy_deferred() -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -If printk has been explicitly deferred or is called from NMI -context, legacy console printing must be deferred to an irq_work -context. Introduce a helper function is_printk_legacy_deferred() -for a CPU to query if it must defer legacy console printing. - -In follow-up commits this helper will be needed at other call -sites as well. - -Signed-off-by: John Ogness -Reviewed-by: Petr Mladek -Link: https://lore.kernel.org/r/20240820063001.36405-24-john.ogness@linutronix.de -Signed-off-by: Petr Mladek -Signed-off-by: Sebastian Andrzej Siewior ---- - kernel/printk/internal.h | 2 ++ - kernel/printk/printk_safe.c | 11 ++++++++++- - 2 files changed, 12 insertions(+), 1 deletion(-) - ---- a/kernel/printk/internal.h -+++ b/kernel/printk/internal.h -@@ -75,6 +75,7 @@ bool printk_percpu_data_ready(void); - } while (0) - - void defer_console_output(void); -+bool is_printk_legacy_deferred(void); - - u16 printk_parse_prefix(const char *text, int *level, - enum printk_info_flags *flags); -@@ -138,6 +139,7 @@ static inline bool console_is_usable(str - #define printk_safe_exit_irqrestore(flags) local_irq_restore(flags) - - static inline bool printk_percpu_data_ready(void) { return false; } -+static inline bool is_printk_legacy_deferred(void) { return false; } - static inline u64 nbcon_seq_read(struct console *con) { return 0; } - static inline void nbcon_seq_force(struct console *con, u64 seq) { } - static inline bool nbcon_alloc(struct console *con) { return false; } ---- a/kernel/printk/printk_safe.c -+++ b/kernel/printk/printk_safe.c -@@ -38,6 +38,15 @@ void __printk_deferred_exit(void) - __printk_safe_exit(); - } - -+bool is_printk_legacy_deferred(void) -+{ -+ /* -+ * The per-CPU variable @printk_context can be read safely in any -+ * context. CPU migration is always disabled when set. -+ */ -+ return (this_cpu_read(printk_context) || in_nmi()); -+} -+ - asmlinkage int vprintk(const char *fmt, va_list args) - { - #ifdef CONFIG_KGDB_KDB -@@ -50,7 +59,7 @@ asmlinkage int vprintk(const char *fmt, - * Use the main logbuf even in NMI. But avoid calling console - * drivers that might have their own locks. - */ -- if (this_cpu_read(printk_context) || in_nmi()) -+ if (is_printk_legacy_deferred()) - return vprintk_deferred(fmt, args); - - /* No obstacles. */ diff --git a/debian/patches-rt/0024-printk-nbcon-Flush-new-records-on-device_release.patch b/debian/patches-rt/0024-printk-nbcon-Flush-new-records-on-device_release.patch deleted file mode 100644 index d957e44..0000000 --- a/debian/patches-rt/0024-printk-nbcon-Flush-new-records-on-device_release.patch +++ /dev/null @@ -1,79 +0,0 @@ -From: John Ogness -Date: Tue, 20 Aug 2024 08:35:50 +0206 -Subject: [PATCH 24/54] printk: nbcon: Flush new records on device_release() -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -There may be new records that were added while a driver was -holding the nbcon context for non-printing purposes. These -new records must be flushed by the nbcon_device_release() -context because no other context will do it. - -If boot consoles are registered, the legacy loop is used -(either direct or per irq_work) to handle the flushing. - -Signed-off-by: John Ogness -Reviewed-by: Petr Mladek -Link: https://lore.kernel.org/r/20240820063001.36405-25-john.ogness@linutronix.de -Signed-off-by: Petr Mladek -Signed-off-by: Sebastian Andrzej Siewior ---- - kernel/printk/internal.h | 2 ++ - kernel/printk/nbcon.c | 20 ++++++++++++++++++++ - kernel/printk/printk.c | 2 +- - 3 files changed, 23 insertions(+), 1 deletion(-) - ---- a/kernel/printk/internal.h -+++ b/kernel/printk/internal.h -@@ -153,6 +153,8 @@ static inline bool console_is_usable(str - - #endif /* CONFIG_PRINTK */ - -+extern bool have_boot_console; -+ - extern struct printk_buffers printk_shared_pbufs; - - /** ---- a/kernel/printk/nbcon.c -+++ b/kernel/printk/nbcon.c -@@ -1326,10 +1326,30 @@ EXPORT_SYMBOL_GPL(nbcon_device_try_acqui - void nbcon_device_release(struct console *con) - { - struct nbcon_context *ctxt = &ACCESS_PRIVATE(con, nbcon_device_ctxt); -+ int cookie; - - if (!nbcon_context_exit_unsafe(ctxt)) - return; - - nbcon_context_release(ctxt); -+ -+ /* -+ * This context must flush any new records added while the console -+ * was locked. The console_srcu_read_lock must be taken to ensure -+ * the console is usable throughout flushing. -+ */ -+ cookie = console_srcu_read_lock(); -+ if (console_is_usable(con, console_srcu_read_flags(con)) && -+ prb_read_valid(prb, nbcon_seq_read(con), NULL)) { -+ if (!have_boot_console) { -+ __nbcon_atomic_flush_pending_con(con, prb_next_reserve_seq(prb)); -+ } else if (!is_printk_legacy_deferred()) { -+ if (console_trylock()) -+ console_unlock(); -+ } else { -+ printk_trigger_flush(); -+ } -+ } -+ console_srcu_read_unlock(cookie); - } - EXPORT_SYMBOL_GPL(nbcon_device_release); ---- a/kernel/printk/printk.c -+++ b/kernel/printk/printk.c -@@ -469,7 +469,7 @@ static DEFINE_MUTEX(syslog_lock); - * the console lock. This is because boot consoles and nbcon consoles may - * have mapped the same hardware. - */ --static bool have_boot_console; -+bool have_boot_console; - - #ifdef CONFIG_PRINTK - DECLARE_WAIT_QUEUE_HEAD(log_wait); diff --git a/debian/patches-rt/0025-printk-Flush-nbcon-consoles-first-on-panic.patch b/debian/patches-rt/0025-printk-Flush-nbcon-consoles-first-on-panic.patch deleted file mode 100644 index 9e4e402..0000000 --- a/debian/patches-rt/0025-printk-Flush-nbcon-consoles-first-on-panic.patch +++ /dev/null @@ -1,30 +0,0 @@ -From: John Ogness -Date: Tue, 20 Aug 2024 08:35:51 +0206 -Subject: [PATCH 25/54] printk: Flush nbcon consoles first on panic -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -In console_flush_on_panic(), flush the nbcon consoles before -flushing legacy consoles. The legacy write() callbacks are not -fully safe when oops_in_progress is set. - -Signed-off-by: John Ogness -Reviewed-by: Petr Mladek -Link: https://lore.kernel.org/r/20240820063001.36405-26-john.ogness@linutronix.de -Signed-off-by: Petr Mladek -Signed-off-by: Sebastian Andrzej Siewior ---- - kernel/printk/printk.c | 3 +++ - 1 file changed, 3 insertions(+) - ---- a/kernel/printk/printk.c -+++ b/kernel/printk/printk.c -@@ -3270,6 +3270,9 @@ void console_flush_on_panic(enum con_flu - if (mode == CONSOLE_REPLAY_ALL) - __console_rewind_all(); - -+ if (!have_boot_console) -+ nbcon_atomic_flush_pending(); -+ - console_flush_all(false, &next_seq, &handover); - } - diff --git a/debian/patches-rt/0026-printk-nbcon-Add-unsafe-flushing-on-panic.patch b/debian/patches-rt/0026-printk-nbcon-Add-unsafe-flushing-on-panic.patch deleted file mode 100644 index fd973c6..0000000 --- a/debian/patches-rt/0026-printk-nbcon-Add-unsafe-flushing-on-panic.patch +++ /dev/null @@ -1,161 +0,0 @@ -From: John Ogness -Date: Tue, 20 Aug 2024 08:35:52 +0206 -Subject: [PATCH 26/54] printk: nbcon: Add unsafe flushing on panic -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -Add nbcon_atomic_flush_unsafe() to flush all nbcon consoles -using the write_atomic() callback and allowing unsafe hostile -takeovers. Call this at the end of panic() as a final attempt -to flush any pending messages. - -Note that legacy consoles use unsafe methods for flushing -from the beginning of panic (see bust_spinlocks()). Therefore, -systems using both legacy and nbcon consoles may still fail to -see panic messages due to unsafe legacy console usage. - -Signed-off-by: John Ogness -Reviewed-by: Petr Mladek -Link: https://lore.kernel.org/r/20240820063001.36405-27-john.ogness@linutronix.de -Signed-off-by: Petr Mladek -Signed-off-by: Sebastian Andrzej Siewior ---- - include/linux/printk.h | 5 +++++ - kernel/panic.c | 1 + - kernel/printk/nbcon.c | 32 +++++++++++++++++++++++++------- - 3 files changed, 31 insertions(+), 7 deletions(-) - ---- a/include/linux/printk.h -+++ b/include/linux/printk.h -@@ -202,6 +202,7 @@ void printk_trigger_flush(void); - void console_try_replay_all(void); - extern bool nbcon_device_try_acquire(struct console *con); - extern void nbcon_device_release(struct console *con); -+void nbcon_atomic_flush_unsafe(void); - #else - static inline __printf(1, 0) - int vprintk(const char *s, va_list args) -@@ -294,6 +295,10 @@ static inline void nbcon_device_release( - { - } - -+static inline void nbcon_atomic_flush_unsafe(void) -+{ -+} -+ - #endif - - bool this_cpu_in_panic(void); ---- a/kernel/panic.c -+++ b/kernel/panic.c -@@ -463,6 +463,7 @@ void panic(const char *fmt, ...) - * Explicitly flush the kernel log buffer one last time. - */ - console_flush_on_panic(CONSOLE_FLUSH_PENDING); -+ nbcon_atomic_flush_unsafe(); - - local_irq_enable(); - for (i = 0; ; i += PANIC_TIMER_STEP) { ---- a/kernel/printk/nbcon.c -+++ b/kernel/printk/nbcon.c -@@ -1083,6 +1083,7 @@ bool nbcon_legacy_emit_next_record(struc - * write_atomic() callback - * @con: The nbcon console to flush - * @stop_seq: Flush up until this record -+ * @allow_unsafe_takeover: True, to allow unsafe hostile takeovers - * - * Return: 0 if @con was flushed up to @stop_seq Otherwise, error code on - * failure. -@@ -1101,7 +1102,8 @@ bool nbcon_legacy_emit_next_record(struc - * returned, it cannot be expected that the unfinalized record will become - * available. - */ --static int __nbcon_atomic_flush_pending_con(struct console *con, u64 stop_seq) -+static int __nbcon_atomic_flush_pending_con(struct console *con, u64 stop_seq, -+ bool allow_unsafe_takeover) - { - struct nbcon_write_context wctxt = { }; - struct nbcon_context *ctxt = &ACCESS_PRIVATE(&wctxt, ctxt); -@@ -1110,6 +1112,7 @@ static int __nbcon_atomic_flush_pending_ - ctxt->console = con; - ctxt->spinwait_max_us = 2000; - ctxt->prio = nbcon_get_default_prio(); -+ ctxt->allow_unsafe_takeover = allow_unsafe_takeover; - - if (!nbcon_context_try_acquire(ctxt)) - return -EPERM; -@@ -1140,13 +1143,15 @@ static int __nbcon_atomic_flush_pending_ - * write_atomic() callback - * @con: The nbcon console to flush - * @stop_seq: Flush up until this record -+ * @allow_unsafe_takeover: True, to allow unsafe hostile takeovers - * - * This will stop flushing before @stop_seq if another context has ownership. - * That context is then responsible for the flushing. Likewise, if new records - * are added while this context was flushing and there is no other context - * to handle the printing, this context must also flush those records. - */ --static void nbcon_atomic_flush_pending_con(struct console *con, u64 stop_seq) -+static void nbcon_atomic_flush_pending_con(struct console *con, u64 stop_seq, -+ bool allow_unsafe_takeover) - { - unsigned long flags; - int err; -@@ -1160,7 +1165,7 @@ static void nbcon_atomic_flush_pending_c - */ - local_irq_save(flags); - -- err = __nbcon_atomic_flush_pending_con(con, stop_seq); -+ err = __nbcon_atomic_flush_pending_con(con, stop_seq, allow_unsafe_takeover); - - local_irq_restore(flags); - -@@ -1190,8 +1195,9 @@ static void nbcon_atomic_flush_pending_c - * __nbcon_atomic_flush_pending - Flush all nbcon consoles using their - * write_atomic() callback - * @stop_seq: Flush up until this record -+ * @allow_unsafe_takeover: True, to allow unsafe hostile takeovers - */ --static void __nbcon_atomic_flush_pending(u64 stop_seq) -+static void __nbcon_atomic_flush_pending(u64 stop_seq, bool allow_unsafe_takeover) - { - struct console *con; - int cookie; -@@ -1209,7 +1215,7 @@ static void __nbcon_atomic_flush_pending - if (nbcon_seq_read(con) >= stop_seq) - continue; - -- nbcon_atomic_flush_pending_con(con, stop_seq); -+ nbcon_atomic_flush_pending_con(con, stop_seq, allow_unsafe_takeover); - } - console_srcu_read_unlock(cookie); - } -@@ -1225,7 +1231,19 @@ static void __nbcon_atomic_flush_pending - */ - void nbcon_atomic_flush_pending(void) - { -- __nbcon_atomic_flush_pending(prb_next_reserve_seq(prb)); -+ __nbcon_atomic_flush_pending(prb_next_reserve_seq(prb), false); -+} -+ -+/** -+ * nbcon_atomic_flush_unsafe - Flush all nbcon consoles using their -+ * write_atomic() callback and allowing unsafe hostile takeovers -+ * -+ * Flush the backlog up through the currently newest record. Unsafe hostile -+ * takeovers will be performed, if necessary. -+ */ -+void nbcon_atomic_flush_unsafe(void) -+{ -+ __nbcon_atomic_flush_pending(prb_next_reserve_seq(prb), true); - } - - /** -@@ -1342,7 +1360,7 @@ void nbcon_device_release(struct console - if (console_is_usable(con, console_srcu_read_flags(con)) && - prb_read_valid(prb, nbcon_seq_read(con), NULL)) { - if (!have_boot_console) { -- __nbcon_atomic_flush_pending_con(con, prb_next_reserve_seq(prb)); -+ __nbcon_atomic_flush_pending_con(con, prb_next_reserve_seq(prb), false); - } else if (!is_printk_legacy_deferred()) { - if (console_trylock()) - console_unlock(); diff --git a/debian/patches-rt/0027-printk-Avoid-console_lock-dance-if-no-legacy-or-boot.patch b/debian/patches-rt/0027-printk-Avoid-console_lock-dance-if-no-legacy-or-boot.patch deleted file mode 100644 index f0f430a..0000000 --- a/debian/patches-rt/0027-printk-Avoid-console_lock-dance-if-no-legacy-or-boot.patch +++ /dev/null @@ -1,139 +0,0 @@ -From: John Ogness -Date: Tue, 20 Aug 2024 08:35:53 +0206 -Subject: [PATCH 27/54] printk: Avoid console_lock dance if no legacy or boot - consoles -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -Currently the console lock is used to attempt legacy-type -printing even if there are no legacy or boot consoles registered. -If no such consoles are registered, the console lock does not -need to be taken. - -Add tracking of legacy console registration and use it with -boot console tracking to avoid unnecessary code paths, i.e. -do not use the console lock if there are no boot consoles -and no legacy consoles. - -Signed-off-by: John Ogness -Reviewed-by: Petr Mladek -Link: https://lore.kernel.org/r/20240820063001.36405-28-john.ogness@linutronix.de -Signed-off-by: Petr Mladek -Signed-off-by: Sebastian Andrzej Siewior ---- - kernel/printk/printk.c | 39 ++++++++++++++++++++++++++++++++++----- - 1 file changed, 34 insertions(+), 5 deletions(-) - ---- a/kernel/printk/printk.c -+++ b/kernel/printk/printk.c -@@ -464,6 +464,13 @@ static int console_msg_format = MSG_FORM - static DEFINE_MUTEX(syslog_lock); - - /* -+ * Specifies if a legacy console is registered. If legacy consoles are -+ * present, it is necessary to perform the console lock/unlock dance -+ * whenever console flushing should occur. -+ */ -+static bool have_legacy_console; -+ -+/* - * Specifies if a boot console is registered. If boot consoles are present, - * nbcon consoles cannot print simultaneously and must be synchronized by - * the console lock. This is because boot consoles and nbcon consoles may -@@ -471,6 +478,14 @@ static DEFINE_MUTEX(syslog_lock); - */ - bool have_boot_console; - -+/* -+ * Specifies if the console lock/unlock dance is needed for console -+ * printing. If @have_boot_console is true, the nbcon consoles will -+ * be printed serially along with the legacy consoles because nbcon -+ * consoles cannot print simultaneously with boot consoles. -+ */ -+#define printing_via_unlock (have_legacy_console || have_boot_console) -+ - #ifdef CONFIG_PRINTK - DECLARE_WAIT_QUEUE_HEAD(log_wait); - /* All 3 protected by @syslog_lock. */ -@@ -2339,7 +2354,7 @@ asmlinkage int vprintk_emit(int facility - printed_len = vprintk_store(facility, level, dev_info, fmt, args); - - /* If called from the scheduler, we can not call up(). */ -- if (!in_sched) { -+ if (!in_sched && printing_via_unlock) { - /* - * The caller may be holding system-critical or - * timing-sensitive locks. Disable preemption during -@@ -2359,7 +2374,7 @@ asmlinkage int vprintk_emit(int facility - preempt_enable(); - } - -- if (in_sched) -+ if (in_sched && printing_via_unlock) - defer_console_output(); - else - wake_up_klogd(); -@@ -2719,7 +2734,7 @@ void resume_console(void) - */ - static int console_cpu_notify(unsigned int cpu) - { -- if (!cpuhp_tasks_frozen) { -+ if (!cpuhp_tasks_frozen && printing_via_unlock) { - /* If trylock fails, someone else is doing the printing */ - if (console_trylock()) - console_unlock(); -@@ -3626,6 +3641,7 @@ void register_console(struct console *ne - if (newcon->flags & CON_NBCON) { - nbcon_seq_force(newcon, init_seq); - } else { -+ have_legacy_console = true; - newcon->seq = init_seq; - } - -@@ -3702,6 +3718,7 @@ EXPORT_SYMBOL(register_console); - static int unregister_console_locked(struct console *console) - { - bool use_device_lock = (console->flags & CON_NBCON) && console->write_atomic; -+ bool found_legacy_con = false; - bool found_boot_con = false; - unsigned long flags; - struct console *c; -@@ -3769,9 +3786,13 @@ static int unregister_console_locked(str - for_each_console(c) { - if (c->flags & CON_BOOT) - found_boot_con = true; -+ if (!(c->flags & CON_NBCON)) -+ found_legacy_con = true; - } - if (!found_boot_con) - have_boot_console = found_boot_con; -+ if (!found_legacy_con) -+ have_legacy_console = found_legacy_con; - - return res; - } -@@ -3932,8 +3953,10 @@ static bool __pr_flush(struct console *c - seq = prb_next_reserve_seq(prb); - - /* Flush the consoles so that records up to @seq are printed. */ -- console_lock(); -- console_unlock(); -+ if (printing_via_unlock) { -+ console_lock(); -+ console_unlock(); -+ } - - for (;;) { - unsigned long begin_jiffies; -@@ -3946,6 +3969,12 @@ static bool __pr_flush(struct console *c - * console->seq. Releasing console_lock flushes more - * records in case @seq is still not printed on all - * usable consoles. -+ * -+ * Holding the console_lock is not necessary if there -+ * are no legacy or boot consoles. However, such a -+ * console could register at any time. Always hold the -+ * console_lock as a precaution rather than -+ * synchronizing against register_console(). - */ - console_lock(); - diff --git a/debian/patches-rt/0028-printk-Track-nbcon-consoles.patch b/debian/patches-rt/0028-printk-Track-nbcon-consoles.patch deleted file mode 100644 index 2b37298..0000000 --- a/debian/patches-rt/0028-printk-Track-nbcon-consoles.patch +++ /dev/null @@ -1,68 +0,0 @@ -From: John Ogness -Date: Tue, 20 Aug 2024 08:35:54 +0206 -Subject: [PATCH 28/54] printk: Track nbcon consoles -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -Add a global flag @have_nbcon_console to identify if any nbcon -consoles are registered. This will be used in follow-up commits -to preserve legacy behavior when no nbcon consoles are registered. - -Signed-off-by: John Ogness -Reviewed-by: Petr Mladek -Link: https://lore.kernel.org/r/20240820063001.36405-29-john.ogness@linutronix.de -Signed-off-by: Petr Mladek -Signed-off-by: Sebastian Andrzej Siewior ---- - kernel/printk/printk.c | 14 +++++++++++++- - 1 file changed, 13 insertions(+), 1 deletion(-) - ---- a/kernel/printk/printk.c -+++ b/kernel/printk/printk.c -@@ -471,6 +471,11 @@ static DEFINE_MUTEX(syslog_lock); - static bool have_legacy_console; - - /* -+ * Specifies if an nbcon console is registered. -+ */ -+static bool have_nbcon_console; -+ -+/* - * Specifies if a boot console is registered. If boot consoles are present, - * nbcon consoles cannot print simultaneously and must be synchronized by - * the console lock. This is because boot consoles and nbcon consoles may -@@ -3639,6 +3644,7 @@ void register_console(struct console *ne - init_seq = get_init_console_seq(newcon, bootcon_registered); - - if (newcon->flags & CON_NBCON) { -+ have_nbcon_console = true; - nbcon_seq_force(newcon, init_seq); - } else { - have_legacy_console = true; -@@ -3719,6 +3725,7 @@ static int unregister_console_locked(str - { - bool use_device_lock = (console->flags & CON_NBCON) && console->write_atomic; - bool found_legacy_con = false; -+ bool found_nbcon_con = false; - bool found_boot_con = false; - unsigned long flags; - struct console *c; -@@ -3786,13 +3793,18 @@ static int unregister_console_locked(str - for_each_console(c) { - if (c->flags & CON_BOOT) - found_boot_con = true; -- if (!(c->flags & CON_NBCON)) -+ -+ if (c->flags & CON_NBCON) -+ found_nbcon_con = true; -+ else - found_legacy_con = true; - } - if (!found_boot_con) - have_boot_console = found_boot_con; - if (!found_legacy_con) - have_legacy_console = found_legacy_con; -+ if (!found_nbcon_con) -+ have_nbcon_console = found_nbcon_con; - - return res; - } diff --git a/debian/patches-rt/0029-printk-Coordinate-direct-printing-in-panic.patch b/debian/patches-rt/0029-printk-Coordinate-direct-printing-in-panic.patch deleted file mode 100644 index 315ea6b..0000000 --- a/debian/patches-rt/0029-printk-Coordinate-direct-printing-in-panic.patch +++ /dev/null @@ -1,184 +0,0 @@ -From: John Ogness -Date: Tue, 20 Aug 2024 08:35:55 +0206 -Subject: [PATCH 29/54] printk: Coordinate direct printing in panic -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -If legacy and nbcon consoles are registered and the nbcon -consoles are allowed to flush (i.e. no boot consoles -registered), the legacy consoles will no longer perform -direct printing on the panic CPU until after the backtrace -has been stored. This will give the safe nbcon consoles a -chance to print the panic messages before allowing the -unsafe legacy consoles to print. - -If no nbcon consoles are registered or they are not allowed -to flush because boot consoles are registered, there is no -change in behavior (i.e. legacy consoles will always attempt -to print from the printk() caller context). - -Signed-off-by: John Ogness -Reviewed-by: Petr Mladek -Link: https://lore.kernel.org/r/20240820063001.36405-30-john.ogness@linutronix.de -Signed-off-by: Petr Mladek -Signed-off-by: Sebastian Andrzej Siewior ---- - include/linux/printk.h | 5 ++++ - kernel/panic.c | 2 + - kernel/printk/internal.h | 1 - kernel/printk/printk.c | 55 +++++++++++++++++++++++++++++++++++++++++------ - 4 files changed, 56 insertions(+), 7 deletions(-) - ---- a/include/linux/printk.h -+++ b/include/linux/printk.h -@@ -200,6 +200,7 @@ extern asmlinkage void dump_stack_lvl(co - extern asmlinkage void dump_stack(void) __cold; - void printk_trigger_flush(void); - void console_try_replay_all(void); -+void printk_legacy_allow_panic_sync(void); - extern bool nbcon_device_try_acquire(struct console *con); - extern void nbcon_device_release(struct console *con); - void nbcon_atomic_flush_unsafe(void); -@@ -286,6 +287,10 @@ static inline void console_try_replay_al - { - } - -+static inline void printk_legacy_allow_panic_sync(void) -+{ -+} -+ - static inline bool nbcon_device_try_acquire(struct console *con) - { - return false; ---- a/kernel/panic.c -+++ b/kernel/panic.c -@@ -374,6 +374,8 @@ void panic(const char *fmt, ...) - - panic_other_cpus_shutdown(_crash_kexec_post_notifiers); - -+ printk_legacy_allow_panic_sync(); -+ - /* - * Run any panic handlers, including those that might need to - * add information to the kmsg dump output. ---- a/kernel/printk/internal.h -+++ b/kernel/printk/internal.h -@@ -154,6 +154,7 @@ static inline bool console_is_usable(str - #endif /* CONFIG_PRINTK */ - - extern bool have_boot_console; -+extern bool legacy_allow_panic_sync; - - extern struct printk_buffers printk_shared_pbufs; - ---- a/kernel/printk/printk.c -+++ b/kernel/printk/printk.c -@@ -471,7 +471,9 @@ static DEFINE_MUTEX(syslog_lock); - static bool have_legacy_console; - - /* -- * Specifies if an nbcon console is registered. -+ * Specifies if an nbcon console is registered. If nbcon consoles are present, -+ * synchronous printing of legacy consoles will not occur during panic until -+ * the backtrace has been stored to the ringbuffer. - */ - static bool have_nbcon_console; - -@@ -483,6 +485,9 @@ static bool have_nbcon_console; - */ - bool have_boot_console; - -+/* See printk_legacy_allow_panic_sync() for details. */ -+bool legacy_allow_panic_sync; -+ - /* - * Specifies if the console lock/unlock dance is needed for console - * printing. If @have_boot_console is true, the nbcon consoles will -@@ -2330,12 +2335,28 @@ int vprintk_store(int facility, int leve - return ret; - } - -+/* -+ * This acts as a one-way switch to allow legacy consoles to print from -+ * the printk() caller context on a panic CPU. It also attempts to flush -+ * the legacy consoles in this context. -+ */ -+void printk_legacy_allow_panic_sync(void) -+{ -+ legacy_allow_panic_sync = true; -+ -+ if (printing_via_unlock && !is_printk_legacy_deferred()) { -+ if (console_trylock()) -+ console_unlock(); -+ } -+} -+ - asmlinkage int vprintk_emit(int facility, int level, - const struct dev_printk_info *dev_info, - const char *fmt, va_list args) - { -+ bool do_trylock_unlock = printing_via_unlock; -+ bool defer_legacy = false; - int printed_len; -- bool in_sched = false; - - /* Suppress unimportant messages after panic happens */ - if (unlikely(suppress_printk)) -@@ -2349,17 +2370,35 @@ asmlinkage int vprintk_emit(int facility - if (other_cpu_in_panic() && !panic_triggering_all_cpu_backtrace) - return 0; - -+ /* If called from the scheduler, we can not call up(). */ - if (level == LOGLEVEL_SCHED) { - level = LOGLEVEL_DEFAULT; -- in_sched = true; -+ defer_legacy = do_trylock_unlock; -+ do_trylock_unlock = false; - } - - printk_delay(level); - - printed_len = vprintk_store(facility, level, dev_info, fmt, args); - -- /* If called from the scheduler, we can not call up(). */ -- if (!in_sched && printing_via_unlock) { -+ if (have_nbcon_console && !have_boot_console) { -+ nbcon_atomic_flush_pending(); -+ -+ /* -+ * In panic, the legacy consoles are not allowed to print from -+ * the printk calling context unless explicitly allowed. This -+ * gives the safe nbcon consoles a chance to print out all the -+ * panic messages first. This restriction only applies if -+ * there are nbcon consoles registered and they are allowed to -+ * flush. -+ */ -+ if (this_cpu_in_panic() && !legacy_allow_panic_sync) { -+ do_trylock_unlock = false; -+ defer_legacy = false; -+ } -+ } -+ -+ if (do_trylock_unlock) { - /* - * The caller may be holding system-critical or - * timing-sensitive locks. Disable preemption during -@@ -2379,7 +2418,7 @@ asmlinkage int vprintk_emit(int facility - preempt_enable(); - } - -- if (in_sched && printing_via_unlock) -+ if (defer_legacy) - defer_console_output(); - else - wake_up_klogd(); -@@ -3293,7 +3332,9 @@ void console_flush_on_panic(enum con_flu - if (!have_boot_console) - nbcon_atomic_flush_pending(); - -- console_flush_all(false, &next_seq, &handover); -+ /* Flush legacy consoles once allowed, even when dangerous. */ -+ if (legacy_allow_panic_sync) -+ console_flush_all(false, &next_seq, &handover); - } - - /* diff --git a/debian/patches-rt/0030-printk-Add-helper-for-flush-type-logic.patch b/debian/patches-rt/0030-printk-Add-helper-for-flush-type-logic.patch deleted file mode 100644 index a50b363..0000000 --- a/debian/patches-rt/0030-printk-Add-helper-for-flush-type-logic.patch +++ /dev/null @@ -1,348 +0,0 @@ -From: John Ogness -Date: Tue, 20 Aug 2024 08:35:56 +0206 -Subject: [PATCH 30/54] printk: Add helper for flush type logic -MIME-Version: 1.0 -Content-Type: text/plain; charset=UTF-8 -Content-Transfer-Encoding: 8bit -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -There are many call sites where console flushing occur. -Depending on the system state and types of consoles, the flush -methods to use are different. A flush call site generally must -consider: - - @have_boot_console - @have_nbcon_console - @have_legacy_console - @legacy_allow_panic_sync - is_printk_preferred() - -and take into account the current CPU state: - - NBCON_PRIO_NORMAL - NBCON_PRIO_EMERGENCY - NBCON_PRIO_PANIC - -in order to decide if it should: - - flush nbcon directly via atomic_write() callback - flush legacy directly via console_unlock - flush legacy via offload to irq_work - -All of these call sites use their own logic to make this -decision, which is complicated and error prone. Especially -later when two more flush methods will be introduced: - - flush nbcon via offload to kthread - flush legacy via offload to kthread - -Introduce a new internal struct console_flush_type that specifies -which console flushing methods should be used in the context of -the caller. - -Introduce a helper function to fill out console_flush_type to -be used for flushing call sites. - -Replace the logic of all flushing call sites to use the new -helper. - -This change standardizes behavior, leading to both fixes and -optimizations across various call sites. For instance, in -console_cpu_notify(), the new logic ensures that nbcon consoles -are flushed when they aren’t managed by the legacy loop. -Similarly, in console_flush_on_panic(), the system no longer -needs to flush nbcon consoles if none are present. - -Signed-off-by: John Ogness -Reviewed-by: Petr Mladek -Link: https://lore.kernel.org/r/20240820063001.36405-31-john.ogness@linutronix.de -[pmladek@suse.com: Updated the commit message.] -Signed-off-by: Petr Mladek -Signed-off-by: Sebastian Andrzej Siewior ---- - kernel/printk/internal.h | 73 +++++++++++++++++++++++++++++++++++++++++++++++ - kernel/printk/nbcon.c | 12 +++++-- - kernel/printk/printk.c | 68 +++++++++++++++++++------------------------ - 3 files changed, 112 insertions(+), 41 deletions(-) - ---- a/kernel/printk/internal.h -+++ b/kernel/printk/internal.h -@@ -154,8 +154,81 @@ static inline bool console_is_usable(str - #endif /* CONFIG_PRINTK */ - - extern bool have_boot_console; -+extern bool have_nbcon_console; -+extern bool have_legacy_console; - extern bool legacy_allow_panic_sync; - -+/** -+ * struct console_flush_type - Define available console flush methods -+ * @nbcon_atomic: Flush directly using nbcon_atomic() callback -+ * @legacy_direct: Call the legacy loop in this context -+ * @legacy_offload: Offload the legacy loop into IRQ -+ * -+ * Note that the legacy loop also flushes the nbcon consoles. -+ */ -+struct console_flush_type { -+ bool nbcon_atomic; -+ bool legacy_direct; -+ bool legacy_offload; -+}; -+ -+/* -+ * Identify which console flushing methods should be used in the context of -+ * the caller. -+ */ -+static inline void printk_get_console_flush_type(struct console_flush_type *ft) -+{ -+ memset(ft, 0, sizeof(*ft)); -+ -+ switch (nbcon_get_default_prio()) { -+ case NBCON_PRIO_NORMAL: -+ if (have_nbcon_console && !have_boot_console) -+ ft->nbcon_atomic = true; -+ -+ /* Legacy consoles are flushed directly when possible. */ -+ if (have_legacy_console || have_boot_console) { -+ if (!is_printk_legacy_deferred()) -+ ft->legacy_direct = true; -+ else -+ ft->legacy_offload = true; -+ } -+ break; -+ -+ case NBCON_PRIO_PANIC: -+ /* -+ * In panic, the nbcon consoles will directly print. But -+ * only allowed if there are no boot consoles. -+ */ -+ if (have_nbcon_console && !have_boot_console) -+ ft->nbcon_atomic = true; -+ -+ if (have_legacy_console || have_boot_console) { -+ /* -+ * This is the same decision as NBCON_PRIO_NORMAL -+ * except that offloading never occurs in panic. -+ * -+ * Note that console_flush_on_panic() will flush -+ * legacy consoles anyway, even if unsafe. -+ */ -+ if (!is_printk_legacy_deferred()) -+ ft->legacy_direct = true; -+ -+ /* -+ * In panic, if nbcon atomic printing occurs, -+ * the legacy consoles must remain silent until -+ * explicitly allowed. -+ */ -+ if (ft->nbcon_atomic && !legacy_allow_panic_sync) -+ ft->legacy_direct = false; -+ } -+ break; -+ -+ default: -+ WARN_ON_ONCE(1); -+ break; -+ } -+} -+ - extern struct printk_buffers printk_shared_pbufs; - - /** ---- a/kernel/printk/nbcon.c -+++ b/kernel/printk/nbcon.c -@@ -1344,6 +1344,7 @@ EXPORT_SYMBOL_GPL(nbcon_device_try_acqui - void nbcon_device_release(struct console *con) - { - struct nbcon_context *ctxt = &ACCESS_PRIVATE(con, nbcon_device_ctxt); -+ struct console_flush_type ft; - int cookie; - - if (!nbcon_context_exit_unsafe(ctxt)) -@@ -1359,12 +1360,17 @@ void nbcon_device_release(struct console - cookie = console_srcu_read_lock(); - if (console_is_usable(con, console_srcu_read_flags(con)) && - prb_read_valid(prb, nbcon_seq_read(con), NULL)) { -- if (!have_boot_console) { -+ /* -+ * If nbcon_atomic flushing is not available, fallback to -+ * using the legacy loop. -+ */ -+ printk_get_console_flush_type(&ft); -+ if (ft.nbcon_atomic) { - __nbcon_atomic_flush_pending_con(con, prb_next_reserve_seq(prb), false); -- } else if (!is_printk_legacy_deferred()) { -+ } else if (ft.legacy_direct) { - if (console_trylock()) - console_unlock(); -- } else { -+ } else if (ft.legacy_offload) { - printk_trigger_flush(); - } - } ---- a/kernel/printk/printk.c -+++ b/kernel/printk/printk.c -@@ -468,14 +468,14 @@ static DEFINE_MUTEX(syslog_lock); - * present, it is necessary to perform the console lock/unlock dance - * whenever console flushing should occur. - */ --static bool have_legacy_console; -+bool have_legacy_console; - - /* - * Specifies if an nbcon console is registered. If nbcon consoles are present, - * synchronous printing of legacy consoles will not occur during panic until - * the backtrace has been stored to the ringbuffer. - */ --static bool have_nbcon_console; -+bool have_nbcon_console; - - /* - * Specifies if a boot console is registered. If boot consoles are present, -@@ -488,14 +488,6 @@ bool have_boot_console; - /* See printk_legacy_allow_panic_sync() for details. */ - bool legacy_allow_panic_sync; - --/* -- * Specifies if the console lock/unlock dance is needed for console -- * printing. If @have_boot_console is true, the nbcon consoles will -- * be printed serially along with the legacy consoles because nbcon -- * consoles cannot print simultaneously with boot consoles. -- */ --#define printing_via_unlock (have_legacy_console || have_boot_console) -- - #ifdef CONFIG_PRINTK - DECLARE_WAIT_QUEUE_HEAD(log_wait); - /* All 3 protected by @syslog_lock. */ -@@ -2342,9 +2334,12 @@ int vprintk_store(int facility, int leve - */ - void printk_legacy_allow_panic_sync(void) - { -+ struct console_flush_type ft; -+ - legacy_allow_panic_sync = true; - -- if (printing_via_unlock && !is_printk_legacy_deferred()) { -+ printk_get_console_flush_type(&ft); -+ if (ft.legacy_direct) { - if (console_trylock()) - console_unlock(); - } -@@ -2354,8 +2349,7 @@ asmlinkage int vprintk_emit(int facility - const struct dev_printk_info *dev_info, - const char *fmt, va_list args) - { -- bool do_trylock_unlock = printing_via_unlock; -- bool defer_legacy = false; -+ struct console_flush_type ft; - int printed_len; - - /* Suppress unimportant messages after panic happens */ -@@ -2370,35 +2364,23 @@ asmlinkage int vprintk_emit(int facility - if (other_cpu_in_panic() && !panic_triggering_all_cpu_backtrace) - return 0; - -+ printk_get_console_flush_type(&ft); -+ - /* If called from the scheduler, we can not call up(). */ - if (level == LOGLEVEL_SCHED) { - level = LOGLEVEL_DEFAULT; -- defer_legacy = do_trylock_unlock; -- do_trylock_unlock = false; -+ ft.legacy_offload |= ft.legacy_direct; -+ ft.legacy_direct = false; - } - - printk_delay(level); - - printed_len = vprintk_store(facility, level, dev_info, fmt, args); - -- if (have_nbcon_console && !have_boot_console) { -+ if (ft.nbcon_atomic) - nbcon_atomic_flush_pending(); - -- /* -- * In panic, the legacy consoles are not allowed to print from -- * the printk calling context unless explicitly allowed. This -- * gives the safe nbcon consoles a chance to print out all the -- * panic messages first. This restriction only applies if -- * there are nbcon consoles registered and they are allowed to -- * flush. -- */ -- if (this_cpu_in_panic() && !legacy_allow_panic_sync) { -- do_trylock_unlock = false; -- defer_legacy = false; -- } -- } -- -- if (do_trylock_unlock) { -+ if (ft.legacy_direct) { - /* - * The caller may be holding system-critical or - * timing-sensitive locks. Disable preemption during -@@ -2418,7 +2400,7 @@ asmlinkage int vprintk_emit(int facility - preempt_enable(); - } - -- if (defer_legacy) -+ if (ft.legacy_offload) - defer_console_output(); - else - wake_up_klogd(); -@@ -2778,10 +2760,16 @@ void resume_console(void) - */ - static int console_cpu_notify(unsigned int cpu) - { -- if (!cpuhp_tasks_frozen && printing_via_unlock) { -- /* If trylock fails, someone else is doing the printing */ -- if (console_trylock()) -- console_unlock(); -+ struct console_flush_type ft; -+ -+ if (!cpuhp_tasks_frozen) { -+ printk_get_console_flush_type(&ft); -+ if (ft.nbcon_atomic) -+ nbcon_atomic_flush_pending(); -+ if (ft.legacy_direct) { -+ if (console_trylock()) -+ console_unlock(); -+ } - } - return 0; - } -@@ -3306,6 +3294,7 @@ static void __console_rewind_all(void) - */ - void console_flush_on_panic(enum con_flush_mode mode) - { -+ struct console_flush_type ft; - bool handover; - u64 next_seq; - -@@ -3329,7 +3318,8 @@ void console_flush_on_panic(enum con_flu - if (mode == CONSOLE_REPLAY_ALL) - __console_rewind_all(); - -- if (!have_boot_console) -+ printk_get_console_flush_type(&ft); -+ if (ft.nbcon_atomic) - nbcon_atomic_flush_pending(); - - /* Flush legacy consoles once allowed, even when dangerous. */ -@@ -3993,6 +3983,7 @@ static bool __pr_flush(struct console *c - { - unsigned long timeout_jiffies = msecs_to_jiffies(timeout_ms); - unsigned long remaining_jiffies = timeout_jiffies; -+ struct console_flush_type ft; - struct console *c; - u64 last_diff = 0; - u64 printk_seq; -@@ -4006,7 +3997,8 @@ static bool __pr_flush(struct console *c - seq = prb_next_reserve_seq(prb); - - /* Flush the consoles so that records up to @seq are printed. */ -- if (printing_via_unlock) { -+ printk_get_console_flush_type(&ft); -+ if (ft.legacy_direct) { - console_lock(); - console_unlock(); - } diff --git a/debian/patches-rt/0031-printk-nbcon-Implement-emergency-sections.patch b/debian/patches-rt/0031-printk-nbcon-Implement-emergency-sections.patch deleted file mode 100644 index 22c91a6..0000000 --- a/debian/patches-rt/0031-printk-nbcon-Implement-emergency-sections.patch +++ /dev/null @@ -1,173 +0,0 @@ -From: Thomas Gleixner -Date: Tue, 20 Aug 2024 08:35:57 +0206 -Subject: [PATCH 31/54] printk: nbcon: Implement emergency sections -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -In emergency situations (something has gone wrong but the -system continues to operate), usually important information -(such as a backtrace) is generated via printk(). This -information should be pushed out to the consoles ASAP. - -Add per-CPU emergency nesting tracking because an emergency -can arise while in an emergency situation. - -Add functions to mark the beginning and end of emergency -sections where the urgent messages are generated. - -Perform direct console flushing at the emergency priority if -the current CPU is in an emergency state and it is safe to do -so. - -Note that the emergency state is not system-wide. While one CPU -is in an emergency state, another CPU may attempt to print -console messages at normal priority. - -Also note that printk() already attempts to flush consoles in -the caller context for normal priority. However, follow-up -changes will introduce printing kthreads, in which case the -normal priority printk() calls will offload to the kthreads. - -Co-developed-by: John Ogness -Signed-off-by: John Ogness -Signed-off-by: Thomas Gleixner (Intel) -Reviewed-by: Petr Mladek -Link: https://lore.kernel.org/r/20240820063001.36405-32-john.ogness@linutronix.de -Signed-off-by: Petr Mladek -Signed-off-by: Sebastian Andrzej Siewior ---- - include/linux/console.h | 4 ++ - kernel/printk/internal.h | 1 - kernel/printk/nbcon.c | 75 ++++++++++++++++++++++++++++++++++++++++++++++- - 3 files changed, 79 insertions(+), 1 deletion(-) - ---- a/include/linux/console.h -+++ b/include/linux/console.h -@@ -553,10 +553,14 @@ static inline bool console_is_registered - hlist_for_each_entry(con, &console_list, node) - - #ifdef CONFIG_PRINTK -+extern void nbcon_cpu_emergency_enter(void); -+extern void nbcon_cpu_emergency_exit(void); - extern bool nbcon_can_proceed(struct nbcon_write_context *wctxt); - extern bool nbcon_enter_unsafe(struct nbcon_write_context *wctxt); - extern bool nbcon_exit_unsafe(struct nbcon_write_context *wctxt); - #else -+static inline void nbcon_cpu_emergency_enter(void) { } -+static inline void nbcon_cpu_emergency_exit(void) { } - static inline bool nbcon_can_proceed(struct nbcon_write_context *wctxt) { return false; } - static inline bool nbcon_enter_unsafe(struct nbcon_write_context *wctxt) { return false; } - static inline bool nbcon_exit_unsafe(struct nbcon_write_context *wctxt) { return false; } ---- a/kernel/printk/internal.h -+++ b/kernel/printk/internal.h -@@ -182,6 +182,7 @@ static inline void printk_get_console_fl - - switch (nbcon_get_default_prio()) { - case NBCON_PRIO_NORMAL: -+ case NBCON_PRIO_EMERGENCY: - if (have_nbcon_console && !have_boot_console) - ft->nbcon_atomic = true; - ---- a/kernel/printk/nbcon.c -+++ b/kernel/printk/nbcon.c -@@ -972,6 +972,36 @@ static bool nbcon_emit_next_record(struc - return nbcon_context_exit_unsafe(ctxt); - } - -+/* Track the nbcon emergency nesting per CPU. */ -+static DEFINE_PER_CPU(unsigned int, nbcon_pcpu_emergency_nesting); -+static unsigned int early_nbcon_pcpu_emergency_nesting __initdata; -+ -+/** -+ * nbcon_get_cpu_emergency_nesting - Get the per CPU emergency nesting pointer -+ * -+ * Context: For reading, any context. For writing, any context which could -+ * not be migrated to another CPU. -+ * Return: Either a pointer to the per CPU emergency nesting counter of -+ * the current CPU or to the init data during early boot. -+ * -+ * The function is safe for reading per-CPU variables in any context because -+ * preemption is disabled if the current CPU is in the emergency state. See -+ * also nbcon_cpu_emergency_enter(). -+ */ -+static __ref unsigned int *nbcon_get_cpu_emergency_nesting(void) -+{ -+ /* -+ * The value of __printk_percpu_data_ready gets set in normal -+ * context and before SMP initialization. As a result it could -+ * never change while inside an nbcon emergency section. -+ */ -+ if (!printk_percpu_data_ready()) -+ return &early_nbcon_pcpu_emergency_nesting; -+ -+ /* Open code this_cpu_ptr() without checking migration. */ -+ return per_cpu_ptr(&nbcon_pcpu_emergency_nesting, raw_smp_processor_id()); -+} -+ - /** - * nbcon_get_default_prio - The appropriate nbcon priority to use for nbcon - * printing on the current CPU -@@ -981,13 +1011,20 @@ static bool nbcon_emit_next_record(struc - * context for printing. - * - * The function is safe for reading per-CPU data in any context because -- * preemption is disabled if the current CPU is in the panic state. -+ * preemption is disabled if the current CPU is in the emergency or panic -+ * state. - */ - enum nbcon_prio nbcon_get_default_prio(void) - { -+ unsigned int *cpu_emergency_nesting; -+ - if (this_cpu_in_panic()) - return NBCON_PRIO_PANIC; - -+ cpu_emergency_nesting = nbcon_get_cpu_emergency_nesting(); -+ if (*cpu_emergency_nesting) -+ return NBCON_PRIO_EMERGENCY; -+ - return NBCON_PRIO_NORMAL; - } - -@@ -1247,6 +1284,42 @@ void nbcon_atomic_flush_unsafe(void) - } - - /** -+ * nbcon_cpu_emergency_enter - Enter an emergency section where printk() -+ * messages for that CPU are flushed directly -+ * -+ * Context: Any context. Disables preemption. -+ * -+ * When within an emergency section, printk() calls will attempt to flush any -+ * pending messages in the ringbuffer. -+ */ -+void nbcon_cpu_emergency_enter(void) -+{ -+ unsigned int *cpu_emergency_nesting; -+ -+ preempt_disable(); -+ -+ cpu_emergency_nesting = nbcon_get_cpu_emergency_nesting(); -+ (*cpu_emergency_nesting)++; -+} -+ -+/** -+ * nbcon_cpu_emergency_exit - Exit an emergency section -+ * -+ * Context: Within an emergency section. Enables preemption. -+ */ -+void nbcon_cpu_emergency_exit(void) -+{ -+ unsigned int *cpu_emergency_nesting; -+ -+ cpu_emergency_nesting = nbcon_get_cpu_emergency_nesting(); -+ -+ if (!WARN_ON_ONCE(*cpu_emergency_nesting == 0)) -+ (*cpu_emergency_nesting)--; -+ -+ preempt_enable(); -+} -+ -+/** - * nbcon_alloc - Allocate and init the nbcon console specific data - * @con: Console to initialize - * diff --git a/debian/patches-rt/0032-panic-Mark-emergency-section-in-warn.patch b/debian/patches-rt/0032-panic-Mark-emergency-section-in-warn.patch deleted file mode 100644 index ea522d8..0000000 --- a/debian/patches-rt/0032-panic-Mark-emergency-section-in-warn.patch +++ /dev/null @@ -1,40 +0,0 @@ -From: Thomas Gleixner -Date: Tue, 20 Aug 2024 08:35:58 +0206 -Subject: [PATCH 32/54] panic: Mark emergency section in warn -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -Mark the full contents of __warn() as an emergency section. In -this section, every printk() call will attempt to directly -flush to the consoles using the EMERGENCY priority. - -Co-developed-by: John Ogness -Signed-off-by: John Ogness -Signed-off-by: Thomas Gleixner (Intel) -Reviewed-by: Petr Mladek -Link: https://lore.kernel.org/r/20240820063001.36405-33-john.ogness@linutronix.de -Signed-off-by: Petr Mladek -Signed-off-by: Sebastian Andrzej Siewior ---- - kernel/panic.c | 4 ++++ - 1 file changed, 4 insertions(+) - ---- a/kernel/panic.c -+++ b/kernel/panic.c -@@ -718,6 +718,8 @@ struct warn_args { - void __warn(const char *file, int line, void *caller, unsigned taint, - struct pt_regs *regs, struct warn_args *args) - { -+ nbcon_cpu_emergency_enter(); -+ - disable_trace_on_warning(); - - if (file) -@@ -753,6 +755,8 @@ void __warn(const char *file, int line, - - /* Just a warning, don't kill lockdep. */ - add_taint(taint, LOCKDEP_STILL_OK); -+ -+ nbcon_cpu_emergency_exit(); - } - - #ifdef CONFIG_BUG diff --git a/debian/patches-rt/0033-panic-Mark-emergency-section-in-oops.patch b/debian/patches-rt/0033-panic-Mark-emergency-section-in-oops.patch deleted file mode 100644 index 77d20bd..0000000 --- a/debian/patches-rt/0033-panic-Mark-emergency-section-in-oops.patch +++ /dev/null @@ -1,42 +0,0 @@ -From: John Ogness -Date: Tue, 20 Aug 2024 08:35:59 +0206 -Subject: [PATCH 33/54] panic: Mark emergency section in oops -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -Mark an emergency section beginning with oops_enter() until the -end of oops_exit(). In this section, every printk() call will -attempt to directly flush to the consoles using the EMERGENCY -priority. - -The very end of oops_exit() performs a kmsg_dump(). This is not -included in the emergency section because it is another -flushing mechanism that should occur after the consoles have -flushed the oops messages. - -Signed-off-by: John Ogness -Reviewed-by: Petr Mladek -Link: https://lore.kernel.org/r/20240820063001.36405-34-john.ogness@linutronix.de -Signed-off-by: Petr Mladek -Signed-off-by: Sebastian Andrzej Siewior ---- - kernel/panic.c | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/kernel/panic.c -+++ b/kernel/panic.c -@@ -685,6 +685,7 @@ bool oops_may_print(void) - */ - void oops_enter(void) - { -+ nbcon_cpu_emergency_enter(); - tracing_off(); - /* can't trust the integrity of the kernel anymore: */ - debug_locks_off(); -@@ -707,6 +708,7 @@ void oops_exit(void) - { - do_oops_enter_exit(); - print_oops_end_marker(); -+ nbcon_cpu_emergency_exit(); - kmsg_dump(KMSG_DUMP_OOPS); - } - diff --git a/debian/patches-rt/0034-rcu-Mark-emergency-sections-in-rcu-stalls.patch b/debian/patches-rt/0034-rcu-Mark-emergency-sections-in-rcu-stalls.patch deleted file mode 100644 index bdef4f1..0000000 --- a/debian/patches-rt/0034-rcu-Mark-emergency-sections-in-rcu-stalls.patch +++ /dev/null @@ -1,97 +0,0 @@ -From: John Ogness -Date: Tue, 20 Aug 2024 08:36:00 +0206 -Subject: [PATCH 34/54] rcu: Mark emergency sections in rcu stalls -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -Mark emergency sections wherever multiple lines of -rcu stall information are generated. In an emergency -section, every printk() call will attempt to directly -flush to the consoles using the EMERGENCY priority. - -Signed-off-by: John Ogness -Reviewed-by: Petr Mladek -Acked-by: Paul E. McKenney -Link: https://lore.kernel.org/r/20240820063001.36405-35-john.ogness@linutronix.de -Signed-off-by: Petr Mladek -Signed-off-by: Sebastian Andrzej Siewior ---- - kernel/rcu/tree_exp.h | 7 +++++++ - kernel/rcu/tree_stall.h | 9 +++++++++ - 2 files changed, 16 insertions(+) - ---- a/kernel/rcu/tree_exp.h -+++ b/kernel/rcu/tree_exp.h -@@ -7,6 +7,7 @@ - * Authors: Paul E. McKenney - */ - -+#include - #include - - static void rcu_exp_handler(void *unused); -@@ -590,6 +591,9 @@ static void synchronize_rcu_expedited_wa - return; - if (rcu_stall_is_suppressed()) - continue; -+ -+ nbcon_cpu_emergency_enter(); -+ - j = jiffies; - rcu_stall_notifier_call_chain(RCU_STALL_NOTIFY_EXP, (void *)(j - jiffies_start)); - trace_rcu_stall_warning(rcu_state.name, TPS("ExpeditedStall")); -@@ -643,6 +647,9 @@ static void synchronize_rcu_expedited_wa - rcu_exp_print_detail_task_stall_rnp(rnp); - } - jiffies_stall = 3 * rcu_exp_jiffies_till_stall_check() + 3; -+ -+ nbcon_cpu_emergency_exit(); -+ - panic_on_rcu_stall(); - } - } ---- a/kernel/rcu/tree_stall.h -+++ b/kernel/rcu/tree_stall.h -@@ -7,6 +7,7 @@ - * Author: Paul E. McKenney - */ - -+#include - #include - #include - -@@ -605,6 +606,8 @@ static void print_other_cpu_stall(unsign - if (rcu_stall_is_suppressed()) - return; - -+ nbcon_cpu_emergency_enter(); -+ - /* - * OK, time to rat on our buddy... - * See Documentation/RCU/stallwarn.rst for info on how to debug -@@ -657,6 +660,8 @@ static void print_other_cpu_stall(unsign - rcu_check_gp_kthread_expired_fqs_timer(); - rcu_check_gp_kthread_starvation(); - -+ nbcon_cpu_emergency_exit(); -+ - panic_on_rcu_stall(); - - rcu_force_quiescent_state(); /* Kick them all. */ -@@ -677,6 +682,8 @@ static void print_cpu_stall(unsigned lon - if (rcu_stall_is_suppressed()) - return; - -+ nbcon_cpu_emergency_enter(); -+ - /* - * OK, time to rat on ourselves... - * See Documentation/RCU/stallwarn.rst for info on how to debug -@@ -706,6 +713,8 @@ static void print_cpu_stall(unsigned lon - jiffies + 3 * rcu_jiffies_till_stall_check() + 3); - raw_spin_unlock_irqrestore_rcu_node(rnp, flags); - -+ nbcon_cpu_emergency_exit(); -+ - panic_on_rcu_stall(); - - /* diff --git a/debian/patches-rt/0035-lockdep-Mark-emergency-sections-in-lockdep-splats.patch b/debian/patches-rt/0035-lockdep-Mark-emergency-sections-in-lockdep-splats.patch deleted file mode 100644 index 0f84166..0000000 --- a/debian/patches-rt/0035-lockdep-Mark-emergency-sections-in-lockdep-splats.patch +++ /dev/null @@ -1,453 +0,0 @@ -From: John Ogness -Date: Tue, 20 Aug 2024 08:36:01 +0206 -Subject: [PATCH 35/54] lockdep: Mark emergency sections in lockdep splats -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -Mark emergency sections wherever multiple lines of -lock debugging output are generated. In an emergency -section, every printk() call will attempt to directly -flush to the consoles using the EMERGENCY priority. - -Note that debug_show_all_locks() and -lockdep_print_held_locks() rely on their callers to -enter the emergency section. This is because these -functions can also be called in non-emergency -situations (such as sysrq). - -Signed-off-by: John Ogness -Reviewed-by: Petr Mladek -Link: https://lore.kernel.org/r/20240820063001.36405-36-john.ogness@linutronix.de -Signed-off-by: Petr Mladek -Signed-off-by: Sebastian Andrzej Siewior ---- - kernel/locking/lockdep.c | 83 +++++++++++++++++++++++++++++++++++++++++++++-- - 1 file changed, 81 insertions(+), 2 deletions(-) - ---- a/kernel/locking/lockdep.c -+++ b/kernel/locking/lockdep.c -@@ -56,6 +56,7 @@ - #include - #include - #include -+#include - - #include - -@@ -573,8 +574,10 @@ static struct lock_trace *save_trace(voi - if (!debug_locks_off_graph_unlock()) - return NULL; - -+ nbcon_cpu_emergency_enter(); - print_lockdep_off("BUG: MAX_STACK_TRACE_ENTRIES too low!"); - dump_stack(); -+ nbcon_cpu_emergency_exit(); - - return NULL; - } -@@ -887,11 +890,13 @@ look_up_lock_class(const struct lockdep_ - if (unlikely(subclass >= MAX_LOCKDEP_SUBCLASSES)) { - instrumentation_begin(); - debug_locks_off(); -+ nbcon_cpu_emergency_enter(); - printk(KERN_ERR - "BUG: looking up invalid subclass: %u\n", subclass); - printk(KERN_ERR - "turning off the locking correctness validator.\n"); - dump_stack(); -+ nbcon_cpu_emergency_exit(); - instrumentation_end(); - return NULL; - } -@@ -968,11 +973,13 @@ static bool assign_lock_key(struct lockd - else { - /* Debug-check: all keys must be persistent! */ - debug_locks_off(); -+ nbcon_cpu_emergency_enter(); - pr_err("INFO: trying to register non-static key.\n"); - pr_err("The code is fine but needs lockdep annotation, or maybe\n"); - pr_err("you didn't initialize this object before use?\n"); - pr_err("turning off the locking correctness validator.\n"); - dump_stack(); -+ nbcon_cpu_emergency_exit(); - return false; - } - -@@ -1316,8 +1323,10 @@ register_lock_class(struct lockdep_map * - return NULL; - } - -+ nbcon_cpu_emergency_enter(); - print_lockdep_off("BUG: MAX_LOCKDEP_KEYS too low!"); - dump_stack(); -+ nbcon_cpu_emergency_exit(); - return NULL; - } - nr_lock_classes++; -@@ -1349,11 +1358,13 @@ register_lock_class(struct lockdep_map * - if (verbose(class)) { - graph_unlock(); - -+ nbcon_cpu_emergency_enter(); - printk("\nnew class %px: %s", class->key, class->name); - if (class->name_version > 1) - printk(KERN_CONT "#%d", class->name_version); - printk(KERN_CONT "\n"); - dump_stack(); -+ nbcon_cpu_emergency_exit(); - - if (!graph_lock()) { - return NULL; -@@ -1392,8 +1403,10 @@ static struct lock_list *alloc_list_entr - if (!debug_locks_off_graph_unlock()) - return NULL; - -+ nbcon_cpu_emergency_enter(); - print_lockdep_off("BUG: MAX_LOCKDEP_ENTRIES too low!"); - dump_stack(); -+ nbcon_cpu_emergency_exit(); - return NULL; - } - nr_list_entries++; -@@ -2039,6 +2052,8 @@ static noinline void print_circular_bug( - - depth = get_lock_depth(target); - -+ nbcon_cpu_emergency_enter(); -+ - print_circular_bug_header(target, depth, check_src, check_tgt); - - parent = get_lock_parent(target); -@@ -2057,6 +2072,8 @@ static noinline void print_circular_bug( - - printk("\nstack backtrace:\n"); - dump_stack(); -+ -+ nbcon_cpu_emergency_exit(); - } - - static noinline void print_bfs_bug(int ret) -@@ -2569,6 +2586,8 @@ print_bad_irq_dependency(struct task_str - if (!debug_locks_off_graph_unlock() || debug_locks_silent) - return; - -+ nbcon_cpu_emergency_enter(); -+ - pr_warn("\n"); - pr_warn("=====================================================\n"); - pr_warn("WARNING: %s-safe -> %s-unsafe lock order detected\n", -@@ -2618,11 +2637,13 @@ print_bad_irq_dependency(struct task_str - pr_warn(" and %s-irq-unsafe lock:\n", irqclass); - next_root->trace = save_trace(); - if (!next_root->trace) -- return; -+ goto out; - print_shortest_lock_dependencies(forwards_entry, next_root); - - pr_warn("\nstack backtrace:\n"); - dump_stack(); -+out: -+ nbcon_cpu_emergency_exit(); - } - - static const char *state_names[] = { -@@ -2987,6 +3008,8 @@ print_deadlock_bug(struct task_struct *c - if (!debug_locks_off_graph_unlock() || debug_locks_silent) - return; - -+ nbcon_cpu_emergency_enter(); -+ - pr_warn("\n"); - pr_warn("============================================\n"); - pr_warn("WARNING: possible recursive locking detected\n"); -@@ -3009,6 +3032,8 @@ print_deadlock_bug(struct task_struct *c - - pr_warn("\nstack backtrace:\n"); - dump_stack(); -+ -+ nbcon_cpu_emergency_exit(); - } - - /* -@@ -3606,6 +3631,8 @@ static void print_collision(struct task_ - struct held_lock *hlock_next, - struct lock_chain *chain) - { -+ nbcon_cpu_emergency_enter(); -+ - pr_warn("\n"); - pr_warn("============================\n"); - pr_warn("WARNING: chain_key collision\n"); -@@ -3622,6 +3649,8 @@ static void print_collision(struct task_ - - pr_warn("\nstack backtrace:\n"); - dump_stack(); -+ -+ nbcon_cpu_emergency_exit(); - } - #endif - -@@ -3712,8 +3741,10 @@ static inline int add_chain_cache(struct - if (!debug_locks_off_graph_unlock()) - return 0; - -+ nbcon_cpu_emergency_enter(); - print_lockdep_off("BUG: MAX_LOCKDEP_CHAINS too low!"); - dump_stack(); -+ nbcon_cpu_emergency_exit(); - return 0; - } - chain->chain_key = chain_key; -@@ -3730,8 +3761,10 @@ static inline int add_chain_cache(struct - if (!debug_locks_off_graph_unlock()) - return 0; - -+ nbcon_cpu_emergency_enter(); - print_lockdep_off("BUG: MAX_LOCKDEP_CHAIN_HLOCKS too low!"); - dump_stack(); -+ nbcon_cpu_emergency_exit(); - return 0; - } - -@@ -3970,6 +4003,8 @@ print_usage_bug(struct task_struct *curr - if (!debug_locks_off() || debug_locks_silent) - return; - -+ nbcon_cpu_emergency_enter(); -+ - pr_warn("\n"); - pr_warn("================================\n"); - pr_warn("WARNING: inconsistent lock state\n"); -@@ -3998,6 +4033,8 @@ print_usage_bug(struct task_struct *curr - - pr_warn("\nstack backtrace:\n"); - dump_stack(); -+ -+ nbcon_cpu_emergency_exit(); - } - - /* -@@ -4032,6 +4069,8 @@ print_irq_inversion_bug(struct task_stru - if (!debug_locks_off_graph_unlock() || debug_locks_silent) - return; - -+ nbcon_cpu_emergency_enter(); -+ - pr_warn("\n"); - pr_warn("========================================================\n"); - pr_warn("WARNING: possible irq lock inversion dependency detected\n"); -@@ -4072,11 +4111,13 @@ print_irq_inversion_bug(struct task_stru - pr_warn("\nthe shortest dependencies between 2nd lock and 1st lock:\n"); - root->trace = save_trace(); - if (!root->trace) -- return; -+ goto out; - print_shortest_lock_dependencies(other, root); - - pr_warn("\nstack backtrace:\n"); - dump_stack(); -+out: -+ nbcon_cpu_emergency_exit(); - } - - /* -@@ -4153,6 +4194,8 @@ void print_irqtrace_events(struct task_s - { - const struct irqtrace_events *trace = &curr->irqtrace; - -+ nbcon_cpu_emergency_enter(); -+ - printk("irq event stamp: %u\n", trace->irq_events); - printk("hardirqs last enabled at (%u): [<%px>] %pS\n", - trace->hardirq_enable_event, (void *)trace->hardirq_enable_ip, -@@ -4166,6 +4209,8 @@ void print_irqtrace_events(struct task_s - printk("softirqs last disabled at (%u): [<%px>] %pS\n", - trace->softirq_disable_event, (void *)trace->softirq_disable_ip, - (void *)trace->softirq_disable_ip); -+ -+ nbcon_cpu_emergency_exit(); - } - - static int HARDIRQ_verbose(struct lock_class *class) -@@ -4686,10 +4731,12 @@ static int mark_lock(struct task_struct - * We must printk outside of the graph_lock: - */ - if (ret == 2) { -+ nbcon_cpu_emergency_enter(); - printk("\nmarked lock as {%s}:\n", usage_str[new_bit]); - print_lock(this); - print_irqtrace_events(curr); - dump_stack(); -+ nbcon_cpu_emergency_exit(); - } - - return ret; -@@ -4730,6 +4777,8 @@ print_lock_invalid_wait_context(struct t - if (debug_locks_silent) - return 0; - -+ nbcon_cpu_emergency_enter(); -+ - pr_warn("\n"); - pr_warn("=============================\n"); - pr_warn("[ BUG: Invalid wait context ]\n"); -@@ -4749,6 +4798,8 @@ print_lock_invalid_wait_context(struct t - pr_warn("stack backtrace:\n"); - dump_stack(); - -+ nbcon_cpu_emergency_exit(); -+ - return 0; - } - -@@ -4956,6 +5007,8 @@ print_lock_nested_lock_not_held(struct t - if (debug_locks_silent) - return; - -+ nbcon_cpu_emergency_enter(); -+ - pr_warn("\n"); - pr_warn("==================================\n"); - pr_warn("WARNING: Nested lock was not taken\n"); -@@ -4976,6 +5029,8 @@ print_lock_nested_lock_not_held(struct t - - pr_warn("\nstack backtrace:\n"); - dump_stack(); -+ -+ nbcon_cpu_emergency_exit(); - } - - static int __lock_is_held(const struct lockdep_map *lock, int read); -@@ -5024,11 +5079,13 @@ static int __lock_acquire(struct lockdep - debug_class_ops_inc(class); - - if (very_verbose(class)) { -+ nbcon_cpu_emergency_enter(); - printk("\nacquire class [%px] %s", class->key, class->name); - if (class->name_version > 1) - printk(KERN_CONT "#%d", class->name_version); - printk(KERN_CONT "\n"); - dump_stack(); -+ nbcon_cpu_emergency_exit(); - } - - /* -@@ -5155,6 +5212,7 @@ static int __lock_acquire(struct lockdep - #endif - if (unlikely(curr->lockdep_depth >= MAX_LOCK_DEPTH)) { - debug_locks_off(); -+ nbcon_cpu_emergency_enter(); - print_lockdep_off("BUG: MAX_LOCK_DEPTH too low!"); - printk(KERN_DEBUG "depth: %i max: %lu!\n", - curr->lockdep_depth, MAX_LOCK_DEPTH); -@@ -5162,6 +5220,7 @@ static int __lock_acquire(struct lockdep - lockdep_print_held_locks(current); - debug_show_all_locks(); - dump_stack(); -+ nbcon_cpu_emergency_exit(); - - return 0; - } -@@ -5181,6 +5240,8 @@ static void print_unlock_imbalance_bug(s - if (debug_locks_silent) - return; - -+ nbcon_cpu_emergency_enter(); -+ - pr_warn("\n"); - pr_warn("=====================================\n"); - pr_warn("WARNING: bad unlock balance detected!\n"); -@@ -5197,6 +5258,8 @@ static void print_unlock_imbalance_bug(s - - pr_warn("\nstack backtrace:\n"); - dump_stack(); -+ -+ nbcon_cpu_emergency_exit(); - } - - static noinstr int match_held_lock(const struct held_lock *hlock, -@@ -5901,6 +5964,8 @@ static void print_lock_contention_bug(st - if (debug_locks_silent) - return; - -+ nbcon_cpu_emergency_enter(); -+ - pr_warn("\n"); - pr_warn("=================================\n"); - pr_warn("WARNING: bad contention detected!\n"); -@@ -5917,6 +5982,8 @@ static void print_lock_contention_bug(st - - pr_warn("\nstack backtrace:\n"); - dump_stack(); -+ -+ nbcon_cpu_emergency_exit(); - } - - static void -@@ -6536,6 +6603,8 @@ print_freed_lock_bug(struct task_struct - if (debug_locks_silent) - return; - -+ nbcon_cpu_emergency_enter(); -+ - pr_warn("\n"); - pr_warn("=========================\n"); - pr_warn("WARNING: held lock freed!\n"); -@@ -6548,6 +6617,8 @@ print_freed_lock_bug(struct task_struct - - pr_warn("\nstack backtrace:\n"); - dump_stack(); -+ -+ nbcon_cpu_emergency_exit(); - } - - static inline int not_in_range(const void* mem_from, unsigned long mem_len, -@@ -6594,6 +6665,8 @@ static void print_held_locks_bug(void) - if (debug_locks_silent) - return; - -+ nbcon_cpu_emergency_enter(); -+ - pr_warn("\n"); - pr_warn("====================================\n"); - pr_warn("WARNING: %s/%d still has locks held!\n", -@@ -6603,6 +6676,8 @@ static void print_held_locks_bug(void) - lockdep_print_held_locks(current); - pr_warn("\nstack backtrace:\n"); - dump_stack(); -+ -+ nbcon_cpu_emergency_exit(); - } - - void debug_check_no_locks_held(void) -@@ -6660,6 +6735,7 @@ asmlinkage __visible void lockdep_sys_ex - if (unlikely(curr->lockdep_depth)) { - if (!debug_locks_off()) - return; -+ nbcon_cpu_emergency_enter(); - pr_warn("\n"); - pr_warn("================================================\n"); - pr_warn("WARNING: lock held when returning to user space!\n"); -@@ -6668,6 +6744,7 @@ asmlinkage __visible void lockdep_sys_ex - pr_warn("%s/%d is leaving the kernel with locks still held!\n", - curr->comm, curr->pid); - lockdep_print_held_locks(curr); -+ nbcon_cpu_emergency_exit(); - } - - /* -@@ -6684,6 +6761,7 @@ void lockdep_rcu_suspicious(const char * - bool rcu = warn_rcu_enter(); - - /* Note: the following can be executed concurrently, so be careful. */ -+ nbcon_cpu_emergency_enter(); - pr_warn("\n"); - pr_warn("=============================\n"); - pr_warn("WARNING: suspicious RCU usage\n"); -@@ -6722,6 +6800,7 @@ void lockdep_rcu_suspicious(const char * - lockdep_print_held_locks(curr); - pr_warn("\nstack backtrace:\n"); - dump_stack(); -+ nbcon_cpu_emergency_exit(); - warn_rcu_exit(rcu); - } - EXPORT_SYMBOL_GPL(lockdep_rcu_suspicious); diff --git a/debian/patches-rt/0036-printk-Use-the-BITS_PER_LONG-macro.patch b/debian/patches-rt/0036-printk-Use-the-BITS_PER_LONG-macro.patch deleted file mode 100644 index 93057b6..0000000 --- a/debian/patches-rt/0036-printk-Use-the-BITS_PER_LONG-macro.patch +++ /dev/null @@ -1,37 +0,0 @@ -From: Jinjie Ruan -Date: Tue, 3 Sep 2024 11:53:58 +0800 -Subject: [PATCH 36/54] printk: Use the BITS_PER_LONG macro -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -sizeof(unsigned long) * 8 is the number of bits in an unsigned long -variable, replace it with BITS_PER_LONG macro to make it simpler. - -Signed-off-by: Jinjie Ruan -Reviewed-by: John Ogness -Reviewed-by: Petr Mladek -Link: https://lore.kernel.org/r/20240903035358.308482-1-ruanjinjie@huawei.com -Signed-off-by: Petr Mladek -Signed-off-by: Sebastian Andrzej Siewior ---- - kernel/printk/printk_ringbuffer.h | 3 ++- - 1 file changed, 2 insertions(+), 1 deletion(-) - ---- a/kernel/printk/printk_ringbuffer.h -+++ b/kernel/printk/printk_ringbuffer.h -@@ -4,6 +4,7 @@ - #define _KERNEL_PRINTK_RINGBUFFER_H - - #include -+#include - #include - #include - #include -@@ -122,7 +123,7 @@ enum desc_state { - - #define _DATA_SIZE(sz_bits) (1UL << (sz_bits)) - #define _DESCS_COUNT(ct_bits) (1U << (ct_bits)) --#define DESC_SV_BITS (sizeof(unsigned long) * 8) -+#define DESC_SV_BITS BITS_PER_LONG - #define DESC_FLAGS_SHIFT (DESC_SV_BITS - 2) - #define DESC_FLAGS_MASK (3UL << DESC_FLAGS_SHIFT) - #define DESC_STATE(sv) (3UL & (sv >> DESC_FLAGS_SHIFT)) diff --git a/debian/patches-rt/0037-printk-nbcon-Use-raw_cpu_ptr-instead-of-open-coding.patch b/debian/patches-rt/0037-printk-nbcon-Use-raw_cpu_ptr-instead-of-open-coding.patch deleted file mode 100644 index 31e5ab5..0000000 --- a/debian/patches-rt/0037-printk-nbcon-Use-raw_cpu_ptr-instead-of-open-coding.patch +++ /dev/null @@ -1,29 +0,0 @@ -From: John Ogness -Date: Tue, 27 Aug 2024 16:25:31 +0206 -Subject: [PATCH 37/54] printk: nbcon: Use raw_cpu_ptr() instead of open coding -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -There is no need to open code a non-migration-checking -this_cpu_ptr(). That is exactly what raw_cpu_ptr() is. - -Signed-off-by: John Ogness -Reviewed-by: Petr Mladek -Link: https://lore.kernel.org/r/87plpum4jw.fsf@jogness.linutronix.de -Signed-off-by: Petr Mladek -Signed-off-by: Sebastian Andrzej Siewior ---- - kernel/printk/nbcon.c | 3 +-- - 1 file changed, 1 insertion(+), 2 deletions(-) - ---- a/kernel/printk/nbcon.c -+++ b/kernel/printk/nbcon.c -@@ -998,8 +998,7 @@ static __ref unsigned int *nbcon_get_cpu - if (!printk_percpu_data_ready()) - return &early_nbcon_pcpu_emergency_nesting; - -- /* Open code this_cpu_ptr() without checking migration. */ -- return per_cpu_ptr(&nbcon_pcpu_emergency_nesting, raw_smp_processor_id()); -+ return raw_cpu_ptr(&nbcon_pcpu_emergency_nesting); - } - - /** diff --git a/debian/patches-rt/0038-printk-nbcon-Add-function-for-printers-to-reacquire-.patch b/debian/patches-rt/0038-printk-nbcon-Add-function-for-printers-to-reacquire-.patch deleted file mode 100644 index 521e51b..0000000 --- a/debian/patches-rt/0038-printk-nbcon-Add-function-for-printers-to-reacquire-.patch +++ /dev/null @@ -1,188 +0,0 @@ -From: John Ogness -Date: Wed, 4 Sep 2024 14:11:20 +0206 -Subject: [PATCH 38/54] printk: nbcon: Add function for printers to reacquire - ownership -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -Since ownership can be lost at any time due to handover or -takeover, a printing context _must_ be prepared to back out -immediately and carefully. However, there are scenarios where -the printing context must reacquire ownership in order to -finalize or revert hardware changes. - -One such example is when interrupts are disabled during -printing. No other context will automagically re-enable the -interrupts. For this case, the disabling context _must_ -reacquire nbcon ownership so that it can re-enable the -interrupts. - -Provide nbcon_reacquire_nobuf() for exactly this purpose. It -allows a printing context to reacquire ownership using the same -priority as its previous ownership. - -Note that after a successful reacquire the printing context -will have no output buffer because that has been lost. This -function cannot be used to resume printing. - -Signed-off-by: John Ogness -Reviewed-by: Petr Mladek -Link: https://lore.kernel.org/r/20240904120536.115780-2-john.ogness@linutronix.de -Signed-off-by: Petr Mladek -Signed-off-by: Sebastian Andrzej Siewior ---- - include/linux/console.h | 6 +++ - kernel/printk/nbcon.c | 74 +++++++++++++++++++++++++++++++++++++++++++----- - 2 files changed, 73 insertions(+), 7 deletions(-) - ---- a/include/linux/console.h -+++ b/include/linux/console.h -@@ -366,6 +366,10 @@ struct console { - * - * The callback should allow the takeover whenever it is safe. It - * increases the chance to see messages when the system is in trouble. -+ * If the driver must reacquire ownership in order to finalize or -+ * revert hardware changes, nbcon_reacquire_nobuf() can be used. -+ * However, on reacquire the buffer content is no longer available. A -+ * reacquire cannot be used to resume printing. - * - * The callback can be called from any context (including NMI). - * Therefore it must avoid usage of any locking and instead rely -@@ -558,12 +562,14 @@ extern void nbcon_cpu_emergency_exit(voi - extern bool nbcon_can_proceed(struct nbcon_write_context *wctxt); - extern bool nbcon_enter_unsafe(struct nbcon_write_context *wctxt); - extern bool nbcon_exit_unsafe(struct nbcon_write_context *wctxt); -+extern void nbcon_reacquire_nobuf(struct nbcon_write_context *wctxt); - #else - static inline void nbcon_cpu_emergency_enter(void) { } - static inline void nbcon_cpu_emergency_exit(void) { } - static inline bool nbcon_can_proceed(struct nbcon_write_context *wctxt) { return false; } - static inline bool nbcon_enter_unsafe(struct nbcon_write_context *wctxt) { return false; } - static inline bool nbcon_exit_unsafe(struct nbcon_write_context *wctxt) { return false; } -+static inline void nbcon_reacquire_nobuf(struct nbcon_write_context *wctxt) { } - #endif - - extern int console_set_on_cmdline; ---- a/kernel/printk/nbcon.c -+++ b/kernel/printk/nbcon.c -@@ -830,6 +830,19 @@ static bool __nbcon_context_update_unsaf - return nbcon_context_can_proceed(ctxt, &cur); - } - -+static void nbcon_write_context_set_buf(struct nbcon_write_context *wctxt, -+ char *buf, unsigned int len) -+{ -+ struct nbcon_context *ctxt = &ACCESS_PRIVATE(wctxt, ctxt); -+ struct console *con = ctxt->console; -+ struct nbcon_state cur; -+ -+ wctxt->outbuf = buf; -+ wctxt->len = len; -+ nbcon_state_read(con, &cur); -+ wctxt->unsafe_takeover = cur.unsafe_takeover; -+} -+ - /** - * nbcon_enter_unsafe - Enter an unsafe region in the driver - * @wctxt: The write context that was handed to the write function -@@ -845,8 +858,12 @@ static bool __nbcon_context_update_unsaf - bool nbcon_enter_unsafe(struct nbcon_write_context *wctxt) - { - struct nbcon_context *ctxt = &ACCESS_PRIVATE(wctxt, ctxt); -+ bool is_owner; - -- return nbcon_context_enter_unsafe(ctxt); -+ is_owner = nbcon_context_enter_unsafe(ctxt); -+ if (!is_owner) -+ nbcon_write_context_set_buf(wctxt, NULL, 0); -+ return is_owner; - } - EXPORT_SYMBOL_GPL(nbcon_enter_unsafe); - -@@ -865,12 +882,44 @@ EXPORT_SYMBOL_GPL(nbcon_enter_unsafe); - bool nbcon_exit_unsafe(struct nbcon_write_context *wctxt) - { - struct nbcon_context *ctxt = &ACCESS_PRIVATE(wctxt, ctxt); -+ bool ret; - -- return nbcon_context_exit_unsafe(ctxt); -+ ret = nbcon_context_exit_unsafe(ctxt); -+ if (!ret) -+ nbcon_write_context_set_buf(wctxt, NULL, 0); -+ return ret; - } - EXPORT_SYMBOL_GPL(nbcon_exit_unsafe); - - /** -+ * nbcon_reacquire_nobuf - Reacquire a console after losing ownership -+ * while printing -+ * @wctxt: The write context that was handed to the write callback -+ * -+ * Since ownership can be lost at any time due to handover or takeover, a -+ * printing context _must_ be prepared to back out immediately and -+ * carefully. However, there are scenarios where the printing context must -+ * reacquire ownership in order to finalize or revert hardware changes. -+ * -+ * This function allows a printing context to reacquire ownership using the -+ * same priority as its previous ownership. -+ * -+ * Note that after a successful reacquire the printing context will have no -+ * output buffer because that has been lost. This function cannot be used to -+ * resume printing. -+ */ -+void nbcon_reacquire_nobuf(struct nbcon_write_context *wctxt) -+{ -+ struct nbcon_context *ctxt = &ACCESS_PRIVATE(wctxt, ctxt); -+ -+ while (!nbcon_context_try_acquire(ctxt)) -+ cpu_relax(); -+ -+ nbcon_write_context_set_buf(wctxt, NULL, 0); -+} -+EXPORT_SYMBOL_GPL(nbcon_reacquire_nobuf); -+ -+/** - * nbcon_emit_next_record - Emit a record in the acquired context - * @wctxt: The write context that will be handed to the write function - * -@@ -895,7 +944,6 @@ static bool nbcon_emit_next_record(struc - .pbufs = ctxt->pbufs, - }; - unsigned long con_dropped; -- struct nbcon_state cur; - unsigned long dropped; - - /* -@@ -930,10 +978,7 @@ static bool nbcon_emit_next_record(struc - goto update_con; - - /* Initialize the write context for driver callbacks. */ -- wctxt->outbuf = &pmsg.pbufs->outbuf[0]; -- wctxt->len = pmsg.outbuf_len; -- nbcon_state_read(con, &cur); -- wctxt->unsafe_takeover = cur.unsafe_takeover; -+ nbcon_write_context_set_buf(wctxt, &pmsg.pbufs->outbuf[0], pmsg.outbuf_len); - - if (con->write_atomic) { - con->write_atomic(con, wctxt); -@@ -947,6 +992,21 @@ static bool nbcon_emit_next_record(struc - return false; - } - -+ if (!wctxt->outbuf) { -+ /* -+ * Ownership was lost and reacquired by the driver. Handle it -+ * as if ownership was lost. -+ */ -+ nbcon_context_release(ctxt); -+ return false; -+ } -+ -+ /* -+ * Ownership may have been lost but _not_ reacquired by the driver. -+ * This case is detected and handled when entering unsafe to update -+ * dropped/seq values. -+ */ -+ - /* - * Since any dropped message was successfully output, reset the - * dropped count for the console. diff --git a/debian/patches-rt/0039-printk-Fail-pr_flush-if-before-SYSTEM_SCHEDULING.patch b/debian/patches-rt/0039-printk-Fail-pr_flush-if-before-SYSTEM_SCHEDULING.patch deleted file mode 100644 index c757ca8..0000000 --- a/debian/patches-rt/0039-printk-Fail-pr_flush-if-before-SYSTEM_SCHEDULING.patch +++ /dev/null @@ -1,79 +0,0 @@ -From: John Ogness -Date: Wed, 4 Sep 2024 14:11:21 +0206 -Subject: [PATCH 39/54] printk: Fail pr_flush() if before SYSTEM_SCHEDULING -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -A follow-up change adds pr_flush() to console unregistration. -However, with boot consoles unregistration can happen very -early if there are also regular consoles registering as well. -In this case the pr_flush() is not important because all -consoles are flushed when checking the initial console sequence -number. - -Allow pr_flush() to fail if @system_state has not yet reached -SYSTEM_SCHEDULING. This avoids might_sleep() and msleep() -explosions that would otherwise occur: - -[ 0.436739][ T0] printk: legacy console [ttyS0] enabled -[ 0.439820][ T0] printk: legacy bootconsole [earlyser0] disabled -[ 0.446822][ T0] BUG: scheduling while atomic: swapper/0/0/0x00000002 -[ 0.450491][ T0] 1 lock held by swapper/0/0: -[ 0.457897][ T0] #0: ffffffff82ae5f88 (console_mutex){+.+.}-{4:4}, at: console_list_lock+0x20/0x70 -[ 0.463141][ T0] Modules linked in: -[ 0.465307][ T0] CPU: 0 PID: 0 Comm: swapper/0 Not tainted 6.10.0-rc1+ #372 -[ 0.469394][ T0] Hardware name: QEMU Standard PC (i440FX + PIIX, 1996), BIOS 1.14.0-2 04/01/2014 -[ 0.474402][ T0] Call Trace: -[ 0.476246][ T0] -[ 0.481473][ T0] dump_stack_lvl+0x93/0xb0 -[ 0.483949][ T0] dump_stack+0x10/0x20 -[ 0.486256][ T0] __schedule_bug+0x68/0x90 -[ 0.488753][ T0] __schedule+0xb9b/0xd80 -[ 0.491179][ T0] ? lock_release+0xb5/0x270 -[ 0.493732][ T0] schedule+0x43/0x170 -[ 0.495998][ T0] schedule_timeout+0xc5/0x1e0 -[ 0.498634][ T0] ? __pfx_process_timeout+0x10/0x10 -[ 0.501522][ T0] ? msleep+0x13/0x50 -[ 0.503728][ T0] msleep+0x3c/0x50 -[ 0.505847][ T0] __pr_flush.constprop.0.isra.0+0x56/0x500 -[ 0.509050][ T0] ? _printk+0x58/0x80 -[ 0.511332][ T0] ? lock_is_held_type+0x9c/0x110 -[ 0.514106][ T0] unregister_console_locked+0xe1/0x450 -[ 0.517144][ T0] register_console+0x509/0x620 -[ 0.519827][ T0] ? __pfx_univ8250_console_init+0x10/0x10 -[ 0.523042][ T0] univ8250_console_init+0x24/0x40 -[ 0.525845][ T0] console_init+0x43/0x210 -[ 0.528280][ T0] start_kernel+0x493/0x980 -[ 0.530773][ T0] x86_64_start_reservations+0x18/0x30 -[ 0.533755][ T0] x86_64_start_kernel+0xae/0xc0 -[ 0.536473][ T0] common_startup_64+0x12c/0x138 -[ 0.539210][ T0] - -And then the kernel goes into an infinite loop complaining about: - -1. releasing a pinned lock -2. unpinning an unpinned lock -3. bad: scheduling from the idle thread! -4. goto 1 - -Signed-off-by: John Ogness -Reviewed-by: Petr Mladek -Link: https://lore.kernel.org/r/20240904120536.115780-3-john.ogness@linutronix.de -Signed-off-by: Petr Mladek -Signed-off-by: Sebastian Andrzej Siewior ---- - kernel/printk/printk.c | 4 ++++ - 1 file changed, 4 insertions(+) - ---- a/kernel/printk/printk.c -+++ b/kernel/printk/printk.c -@@ -3992,6 +3992,10 @@ static bool __pr_flush(struct console *c - u64 diff; - u64 seq; - -+ /* Sorry, pr_flush() will not work this early. */ -+ if (system_state < SYSTEM_SCHEDULING) -+ return false; -+ - might_sleep(); - - seq = prb_next_reserve_seq(prb); diff --git a/debian/patches-rt/0040-printk-Flush-console-on-unregister_console.patch b/debian/patches-rt/0040-printk-Flush-console-on-unregister_console.patch deleted file mode 100644 index 2cc6bde..0000000 --- a/debian/patches-rt/0040-printk-Flush-console-on-unregister_console.patch +++ /dev/null @@ -1,39 +0,0 @@ -From: John Ogness -Date: Wed, 4 Sep 2024 14:11:22 +0206 -Subject: [PATCH 40/54] printk: Flush console on unregister_console() -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -Ensure consoles have flushed pending records before -unregistering. The console should print up to at least its -related "console disabled" record. - -Signed-off-by: John Ogness -Reviewed-by: Petr Mladek -Link: https://lore.kernel.org/r/20240904120536.115780-4-john.ogness@linutronix.de -Signed-off-by: Petr Mladek -Signed-off-by: Sebastian Andrzej Siewior ---- - kernel/printk/printk.c | 9 +++++++-- - 1 file changed, 7 insertions(+), 2 deletions(-) - ---- a/kernel/printk/printk.c -+++ b/kernel/printk/printk.c -@@ -3772,11 +3772,16 @@ static int unregister_console_locked(str - if (res > 0) - return 0; - -+ if (!console_is_registered_locked(console)) -+ res = -ENODEV; -+ else if (console_is_usable(console, console->flags)) -+ __pr_flush(console, 1000, true); -+ - /* Disable it unconditionally */ - console_srcu_write_flags(console, console->flags & ~CON_ENABLED); - -- if (!console_is_registered_locked(console)) -- return -ENODEV; -+ if (res < 0) -+ return res; - - /* - * Use the driver synchronization to ensure that the hardware is not diff --git a/debian/patches-rt/0041-printk-nbcon-Add-context-to-usable-and-emit.patch b/debian/patches-rt/0041-printk-nbcon-Add-context-to-usable-and-emit.patch deleted file mode 100644 index 80e7ea9..0000000 --- a/debian/patches-rt/0041-printk-nbcon-Add-context-to-usable-and-emit.patch +++ /dev/null @@ -1,184 +0,0 @@ -From: John Ogness -Date: Wed, 4 Sep 2024 14:11:23 +0206 -Subject: [PATCH 41/54] printk: nbcon: Add context to usable() and emit() -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -The nbcon consoles will have two callbacks to be used for -different contexts. In order to determine if an nbcon console -is usable, console_is_usable() must know if it is a context -that will need to use the optional write_atomic() callback. -Also, nbcon_emit_next_record() must know which callback it -needs to call. - -Add an extra parameter @use_atomic to console_is_usable() and -nbcon_emit_next_record() to specify this. - -Since so far only the write_atomic() callback exists, -@use_atomic is set to true for all call sites. - -For legacy consoles, @use_atomic is not used. - -Signed-off-by: John Ogness -Reviewed-by: Petr Mladek -Link: https://lore.kernel.org/r/20240904120536.115780-5-john.ogness@linutronix.de -Signed-off-by: Petr Mladek -Signed-off-by: Sebastian Andrzej Siewior ---- - kernel/printk/internal.h | 8 +++++--- - kernel/printk/nbcon.c | 34 +++++++++++++++++++--------------- - kernel/printk/printk.c | 6 +++--- - 3 files changed, 27 insertions(+), 21 deletions(-) - ---- a/kernel/printk/internal.h -+++ b/kernel/printk/internal.h -@@ -97,7 +97,7 @@ bool nbcon_legacy_emit_next_record(struc - * which can also play a role in deciding if @con can be used to print - * records. - */ --static inline bool console_is_usable(struct console *con, short flags) -+static inline bool console_is_usable(struct console *con, short flags, bool use_atomic) - { - if (!(flags & CON_ENABLED)) - return false; -@@ -106,7 +106,8 @@ static inline bool console_is_usable(str - return false; - - if (flags & CON_NBCON) { -- if (!con->write_atomic) -+ /* The write_atomic() callback is optional. */ -+ if (use_atomic && !con->write_atomic) - return false; - } else { - if (!con->write) -@@ -149,7 +150,8 @@ static inline void nbcon_atomic_flush_pe - static inline bool nbcon_legacy_emit_next_record(struct console *con, bool *handover, - int cookie) { return false; } - --static inline bool console_is_usable(struct console *con, short flags) { return false; } -+static inline bool console_is_usable(struct console *con, short flags, -+ bool use_atomic) { return false; } - - #endif /* CONFIG_PRINTK */ - ---- a/kernel/printk/nbcon.c -+++ b/kernel/printk/nbcon.c -@@ -922,6 +922,7 @@ EXPORT_SYMBOL_GPL(nbcon_reacquire_nobuf) - /** - * nbcon_emit_next_record - Emit a record in the acquired context - * @wctxt: The write context that will be handed to the write function -+ * @use_atomic: True if the write_atomic() callback is to be used - * - * Return: True if this context still owns the console. False if - * ownership was handed over or taken. -@@ -935,7 +936,7 @@ EXPORT_SYMBOL_GPL(nbcon_reacquire_nobuf) - * When true is returned, @wctxt->ctxt.backlog indicates whether there are - * still records pending in the ringbuffer, - */ --static bool nbcon_emit_next_record(struct nbcon_write_context *wctxt) -+static bool nbcon_emit_next_record(struct nbcon_write_context *wctxt, bool use_atomic) - { - struct nbcon_context *ctxt = &ACCESS_PRIVATE(wctxt, ctxt); - struct console *con = ctxt->console; -@@ -947,6 +948,18 @@ static bool nbcon_emit_next_record(struc - unsigned long dropped; - - /* -+ * This function should never be called for consoles that have not -+ * implemented the necessary callback for writing: i.e. legacy -+ * consoles and, when atomic, nbcon consoles with no write_atomic(). -+ * Handle it as if ownership was lost and try to continue. -+ */ -+ if (WARN_ON_ONCE((use_atomic && !con->write_atomic) || -+ !(console_srcu_read_flags(con) & CON_NBCON))) { -+ nbcon_context_release(ctxt); -+ return false; -+ } -+ -+ /* - * The printk buffers are filled within an unsafe section. This - * prevents NBCON_PRIO_NORMAL and NBCON_PRIO_EMERGENCY from - * clobbering each other. -@@ -980,17 +993,8 @@ static bool nbcon_emit_next_record(struc - /* Initialize the write context for driver callbacks. */ - nbcon_write_context_set_buf(wctxt, &pmsg.pbufs->outbuf[0], pmsg.outbuf_len); - -- if (con->write_atomic) { -+ if (use_atomic) - con->write_atomic(con, wctxt); -- } else { -- /* -- * This function should never be called for legacy consoles. -- * Handle it as if ownership was lost and try to continue. -- */ -- WARN_ON_ONCE(1); -- nbcon_context_release(ctxt); -- return false; -- } - - if (!wctxt->outbuf) { - /* -@@ -1118,7 +1122,7 @@ static bool nbcon_atomic_emit_one(struct - * The higher priority printing context takes over responsibility - * to print the pending records. - */ -- if (!nbcon_emit_next_record(wctxt)) -+ if (!nbcon_emit_next_record(wctxt, true)) - return false; - - nbcon_context_release(ctxt); -@@ -1219,7 +1223,7 @@ static int __nbcon_atomic_flush_pending_ - * handed over or taken over. In both cases the context is no - * longer valid. - */ -- if (!nbcon_emit_next_record(&wctxt)) -+ if (!nbcon_emit_next_record(&wctxt, true)) - return -EAGAIN; - - if (!ctxt->backlog) { -@@ -1305,7 +1309,7 @@ static void __nbcon_atomic_flush_pending - if (!(flags & CON_NBCON)) - continue; - -- if (!console_is_usable(con, flags)) -+ if (!console_is_usable(con, flags, true)) - continue; - - if (nbcon_seq_read(con) >= stop_seq) -@@ -1490,7 +1494,7 @@ void nbcon_device_release(struct console - * the console is usable throughout flushing. - */ - cookie = console_srcu_read_lock(); -- if (console_is_usable(con, console_srcu_read_flags(con)) && -+ if (console_is_usable(con, console_srcu_read_flags(con), true) && - prb_read_valid(prb, nbcon_seq_read(con), NULL)) { - /* - * If nbcon_atomic flushing is not available, fallback to ---- a/kernel/printk/printk.c -+++ b/kernel/printk/printk.c -@@ -3072,7 +3072,7 @@ static bool console_flush_all(bool do_co - u64 printk_seq; - bool progress; - -- if (!console_is_usable(con, flags)) -+ if (!console_is_usable(con, flags, true)) - continue; - any_usable = true; - -@@ -3774,7 +3774,7 @@ static int unregister_console_locked(str - - if (!console_is_registered_locked(console)) - res = -ENODEV; -- else if (console_is_usable(console, console->flags)) -+ else if (console_is_usable(console, console->flags, true)) - __pr_flush(console, 1000, true); - - /* Disable it unconditionally */ -@@ -4044,7 +4044,7 @@ static bool __pr_flush(struct console *c - * that they make forward progress, so only increment - * @diff for usable consoles. - */ -- if (!console_is_usable(c, flags)) -+ if (!console_is_usable(c, flags, true)) - continue; - - if (flags & CON_NBCON) { diff --git a/debian/patches-rt/0042-printk-nbcon-Init-nbcon_seq-to-highest-possible.patch b/debian/patches-rt/0042-printk-nbcon-Init-nbcon_seq-to-highest-possible.patch deleted file mode 100644 index f95cecc..0000000 --- a/debian/patches-rt/0042-printk-nbcon-Init-nbcon_seq-to-highest-possible.patch +++ /dev/null @@ -1,57 +0,0 @@ -From: John Ogness -Date: Wed, 4 Sep 2024 14:11:24 +0206 -Subject: [PATCH 42/54] printk: nbcon: Init @nbcon_seq to highest possible -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -When initializing an nbcon console, have nbcon_alloc() set -@nbcon_seq to the highest possible sequence number. For all -practical purposes, this will guarantee that the console -will have nothing to print until later when @nbcon_seq is -set to the proper initial printing value. - -This will be particularly important once kthread printing is -introduced because nbcon_alloc() can create/start the kthread -before the desired initial sequence number is known. - -Signed-off-by: John Ogness -Reviewed-by: Petr Mladek -Link: https://lore.kernel.org/r/20240904120536.115780-6-john.ogness@linutronix.de -Signed-off-by: Petr Mladek -Signed-off-by: Sebastian Andrzej Siewior ---- - kernel/printk/nbcon.c | 8 +++++++- - kernel/printk/printk_ringbuffer.h | 2 ++ - 2 files changed, 9 insertions(+), 1 deletion(-) - ---- a/kernel/printk/nbcon.c -+++ b/kernel/printk/nbcon.c -@@ -1397,7 +1397,13 @@ bool nbcon_alloc(struct console *con) - struct nbcon_state state = { }; - - nbcon_state_set(con, &state); -- atomic_long_set(&ACCESS_PRIVATE(con, nbcon_seq), 0); -+ -+ /* -+ * Initialize @nbcon_seq to the highest possible sequence number so -+ * that practically speaking it will have nothing to print until a -+ * desired initial sequence number has been set via nbcon_seq_force(). -+ */ -+ atomic_long_set(&ACCESS_PRIVATE(con, nbcon_seq), ULSEQ_MAX(prb)); - - if (con->flags & CON_BOOT) { - /* ---- a/kernel/printk/printk_ringbuffer.h -+++ b/kernel/printk/printk_ringbuffer.h -@@ -404,10 +404,12 @@ u64 prb_next_reserve_seq(struct printk_r - - #define __u64seq_to_ulseq(u64seq) (u64seq) - #define __ulseq_to_u64seq(rb, ulseq) (ulseq) -+#define ULSEQ_MAX(rb) (-1) - - #else /* CONFIG_64BIT */ - - #define __u64seq_to_ulseq(u64seq) ((u32)u64seq) -+#define ULSEQ_MAX(rb) __u64seq_to_ulseq(prb_first_seq(rb) + 0x80000000UL) - - static inline u64 __ulseq_to_u64seq(struct printk_ringbuffer *rb, u32 ulseq) - { diff --git a/debian/patches-rt/0043-printk-nbcon-Introduce-printer-kthreads.patch b/debian/patches-rt/0043-printk-nbcon-Introduce-printer-kthreads.patch deleted file mode 100644 index 1d5db07..0000000 --- a/debian/patches-rt/0043-printk-nbcon-Introduce-printer-kthreads.patch +++ /dev/null @@ -1,696 +0,0 @@ -From: Thomas Gleixner -Date: Wed, 4 Sep 2024 14:11:25 +0206 -Subject: [PATCH 43/54] printk: nbcon: Introduce printer kthreads -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -Provide the main implementation for running a printer kthread -per nbcon console that is takeover/handover aware. This -includes: - -- new mandatory write_thread() callback -- kthread creation -- kthread main printing loop -- kthread wakeup mechanism -- kthread shutdown - -kthread creation is a bit tricky because consoles may register -before kthreads can be created. In such cases, registration -will succeed, even though no kthread exists. Once kthreads can -be created, an early_initcall will set @printk_kthreads_ready. -If there are no registered boot consoles, the early_initcall -creates the kthreads for all registered nbcon consoles. If -kthread creation fails, the related console is unregistered. - -If there are registered boot consoles when -@printk_kthreads_ready is set, no kthreads are created until -the final boot console unregisters. - -Once kthread creation finally occurs, @printk_kthreads_running -is set so that the system knows kthreads are available for all -registered nbcon consoles. - -If @printk_kthreads_running is already set when the console -is registering, the kthread is created during registration. If -kthread creation fails, the registration will fail. - -Until @printk_kthreads_running is set, console printing occurs -directly via the console_lock. - -kthread shutdown on system shutdown/reboot is necessary to -ensure the printer kthreads finish their printing so that the -system can cleanly transition back to direct printing via the -console_lock in order to reliably push out the final -shutdown/reboot messages. @printk_kthreads_running is cleared -before shutting down the individual kthreads. - -The kthread uses a new mandatory write_thread() callback that -is called with both device_lock() and the console context -acquired. - -The console ownership handling is necessary for synchronization -against write_atomic() which is synchronized only via the -console context ownership. - -The device_lock() serializes acquiring the console context with -NBCON_PRIO_NORMAL. It is needed in case the device_lock() does -not disable preemption. It prevents the following race: - -CPU0 CPU1 - - [ task A ] - - nbcon_context_try_acquire() - # success with NORMAL prio - # .unsafe == false; // safe for takeover - - [ schedule: task A -> B ] - - WARN_ON() - nbcon_atomic_flush_pending() - nbcon_context_try_acquire() - # success with EMERGENCY prio - - # flushing - nbcon_context_release() - - # HERE: con->nbcon_state is free - # to take by anyone !!! - - nbcon_context_try_acquire() - # success with NORMAL prio [ task B ] - - [ schedule: task B -> A ] - - nbcon_enter_unsafe() - nbcon_context_can_proceed() - -BUG: nbcon_context_can_proceed() returns "true" because - the console is owned by a context on CPU0 with - NBCON_PRIO_NORMAL. - - But it should return "false". The console is owned - by a context from task B and we do the check - in a context from task A. - -Note that with these changes, the printer kthreads do not yet -take over full responsibility for nbcon printing during normal -operation. These changes only focus on the lifecycle of the -kthreads. - -Co-developed-by: John Ogness -Signed-off-by: John Ogness -Signed-off-by: Thomas Gleixner (Intel) -Reviewed-by: Petr Mladek -Link: https://lore.kernel.org/r/20240904120536.115780-7-john.ogness@linutronix.de -Signed-off-by: Petr Mladek -Signed-off-by: Sebastian Andrzej Siewior ---- - include/linux/console.h | 40 +++++++ - kernel/printk/internal.h | 27 +++++ - kernel/printk/nbcon.c | 245 +++++++++++++++++++++++++++++++++++++++++++++++ - kernel/printk/printk.c | 108 ++++++++++++++++++++ - 4 files changed, 420 insertions(+) - ---- a/include/linux/console.h -+++ b/include/linux/console.h -@@ -16,7 +16,9 @@ - - #include - #include -+#include - #include -+#include - #include - #include - -@@ -324,6 +326,9 @@ struct nbcon_write_context { - * @nbcon_seq: Sequence number of the next record for nbcon to print - * @nbcon_device_ctxt: Context available for non-printing operations - * @pbufs: Pointer to nbcon private buffer -+ * @kthread: Printer kthread for this console -+ * @rcuwait: RCU-safe wait object for @kthread waking -+ * @irq_work: Defer @kthread waking to IRQ work context - */ - struct console { - char name[16]; -@@ -378,6 +383,37 @@ struct console { - void (*write_atomic)(struct console *con, struct nbcon_write_context *wctxt); - - /** -+ * @write_thread: -+ * -+ * NBCON callback to write out text in task context. -+ * -+ * This callback must be called only in task context with both -+ * device_lock() and the nbcon console acquired with -+ * NBCON_PRIO_NORMAL. -+ * -+ * The same rules for console ownership verification and unsafe -+ * sections handling applies as with write_atomic(). -+ * -+ * The console ownership handling is necessary for synchronization -+ * against write_atomic() which is synchronized only via the context. -+ * -+ * The device_lock() provides the primary serialization for operations -+ * on the device. It might be as relaxed (mutex)[*] or as tight -+ * (disabled preemption and interrupts) as needed. It allows -+ * the kthread to operate in the least restrictive mode[**]. -+ * -+ * [*] Standalone nbcon_context_try_acquire() is not safe with -+ * the preemption enabled, see nbcon_owner_matches(). But it -+ * can be safe when always called in the preemptive context -+ * under the device_lock(). -+ * -+ * [**] The device_lock() makes sure that nbcon_context_try_acquire() -+ * would never need to spin which is important especially with -+ * PREEMPT_RT. -+ */ -+ void (*write_thread)(struct console *con, struct nbcon_write_context *wctxt); -+ -+ /** - * @device_lock: - * - * NBCON callback to begin synchronization with driver code. -@@ -423,7 +459,11 @@ struct console { - atomic_t __private nbcon_state; - atomic_long_t __private nbcon_seq; - struct nbcon_context __private nbcon_device_ctxt; -+ - struct printk_buffers *pbufs; -+ struct task_struct *kthread; -+ struct rcuwait rcuwait; -+ struct irq_work irq_work; - }; - - #ifdef CONFIG_LOCKDEP ---- a/kernel/printk/internal.h -+++ b/kernel/printk/internal.h -@@ -48,6 +48,7 @@ struct printk_ringbuffer; - struct dev_printk_info; - - extern struct printk_ringbuffer *prb; -+extern bool printk_kthreads_running; - - __printf(4, 0) - int vprintk_store(int facility, int level, -@@ -90,6 +91,9 @@ enum nbcon_prio nbcon_get_default_prio(v - void nbcon_atomic_flush_pending(void); - bool nbcon_legacy_emit_next_record(struct console *con, bool *handover, - int cookie); -+bool nbcon_kthread_create(struct console *con); -+void nbcon_kthread_stop(struct console *con); -+void nbcon_kthreads_wake(void); - - /* - * Check if the given console is currently capable and allowed to print -@@ -125,12 +129,34 @@ static inline bool console_is_usable(str - return true; - } - -+/** -+ * nbcon_kthread_wake - Wake up a console printing thread -+ * @con: Console to operate on -+ */ -+static inline void nbcon_kthread_wake(struct console *con) -+{ -+ /* -+ * Guarantee any new records can be seen by tasks preparing to wait -+ * before this context checks if the rcuwait is empty. -+ * -+ * The full memory barrier in rcuwait_wake_up() pairs with the full -+ * memory barrier within set_current_state() of -+ * ___rcuwait_wait_event(), which is called after prepare_to_rcuwait() -+ * adds the waiter but before it has checked the wait condition. -+ * -+ * This pairs with nbcon_kthread_func:A. -+ */ -+ rcuwait_wake_up(&con->rcuwait); /* LMM(nbcon_kthread_wake:A) */ -+} -+ - #else - - #define PRINTK_PREFIX_MAX 0 - #define PRINTK_MESSAGE_MAX 0 - #define PRINTKRB_RECORD_MAX 0 - -+#define printk_kthreads_running (false) -+ - /* - * In !PRINTK builds we still export console_sem - * semaphore and some of console functions (console_unlock()/etc.), so -@@ -149,6 +175,7 @@ static inline enum nbcon_prio nbcon_get_ - static inline void nbcon_atomic_flush_pending(void) { } - static inline bool nbcon_legacy_emit_next_record(struct console *con, bool *handover, - int cookie) { return false; } -+static inline void nbcon_kthread_wake(struct console *con) { } - - static inline bool console_is_usable(struct console *con, short flags, - bool use_atomic) { return false; } ---- a/kernel/printk/nbcon.c -+++ b/kernel/printk/nbcon.c -@@ -10,6 +10,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -952,6 +953,9 @@ static bool nbcon_emit_next_record(struc - * implemented the necessary callback for writing: i.e. legacy - * consoles and, when atomic, nbcon consoles with no write_atomic(). - * Handle it as if ownership was lost and try to continue. -+ * -+ * Note that for nbcon consoles the write_thread() callback is -+ * mandatory and was already checked in nbcon_alloc(). - */ - if (WARN_ON_ONCE((use_atomic && !con->write_atomic) || - !(console_srcu_read_flags(con) & CON_NBCON))) { -@@ -995,6 +999,8 @@ static bool nbcon_emit_next_record(struc - - if (use_atomic) - con->write_atomic(con, wctxt); -+ else -+ con->write_thread(con, wctxt); - - if (!wctxt->outbuf) { - /* -@@ -1036,6 +1042,228 @@ static bool nbcon_emit_next_record(struc - return nbcon_context_exit_unsafe(ctxt); - } - -+/** -+ * nbcon_kthread_should_wakeup - Check whether a printer thread should wakeup -+ * @con: Console to operate on -+ * @ctxt: The nbcon context from nbcon_context_try_acquire() -+ * -+ * Return: True if the thread should shutdown or if the console is -+ * allowed to print and a record is available. False otherwise. -+ * -+ * After the thread wakes up, it must first check if it should shutdown before -+ * attempting any printing. -+ */ -+static bool nbcon_kthread_should_wakeup(struct console *con, struct nbcon_context *ctxt) -+{ -+ bool ret = false; -+ short flags; -+ int cookie; -+ -+ if (kthread_should_stop()) -+ return true; -+ -+ cookie = console_srcu_read_lock(); -+ -+ flags = console_srcu_read_flags(con); -+ if (console_is_usable(con, flags, false)) { -+ /* Bring the sequence in @ctxt up to date */ -+ ctxt->seq = nbcon_seq_read(con); -+ -+ ret = prb_read_valid(prb, ctxt->seq, NULL); -+ } -+ -+ console_srcu_read_unlock(cookie); -+ return ret; -+} -+ -+/** -+ * nbcon_kthread_func - The printer thread function -+ * @__console: Console to operate on -+ * -+ * Return: 0 -+ */ -+static int nbcon_kthread_func(void *__console) -+{ -+ struct console *con = __console; -+ struct nbcon_write_context wctxt = { -+ .ctxt.console = con, -+ .ctxt.prio = NBCON_PRIO_NORMAL, -+ }; -+ struct nbcon_context *ctxt = &ACCESS_PRIVATE(&wctxt, ctxt); -+ short con_flags; -+ bool backlog; -+ int cookie; -+ -+wait_for_event: -+ /* -+ * Guarantee this task is visible on the rcuwait before -+ * checking the wake condition. -+ * -+ * The full memory barrier within set_current_state() of -+ * ___rcuwait_wait_event() pairs with the full memory -+ * barrier within rcuwait_has_sleeper(). -+ * -+ * This pairs with rcuwait_has_sleeper:A and nbcon_kthread_wake:A. -+ */ -+ rcuwait_wait_event(&con->rcuwait, -+ nbcon_kthread_should_wakeup(con, ctxt), -+ TASK_INTERRUPTIBLE); /* LMM(nbcon_kthread_func:A) */ -+ -+ do { -+ if (kthread_should_stop()) -+ return 0; -+ -+ backlog = false; -+ -+ /* -+ * Keep the srcu read lock around the entire operation so that -+ * synchronize_srcu() can guarantee that the kthread stopped -+ * or suspended printing. -+ */ -+ cookie = console_srcu_read_lock(); -+ -+ con_flags = console_srcu_read_flags(con); -+ -+ if (console_is_usable(con, con_flags, false)) { -+ unsigned long lock_flags; -+ -+ con->device_lock(con, &lock_flags); -+ -+ /* -+ * Ensure this stays on the CPU to make handover and -+ * takeover possible. -+ */ -+ cant_migrate(); -+ -+ if (nbcon_context_try_acquire(ctxt)) { -+ /* -+ * If the emit fails, this context is no -+ * longer the owner. -+ */ -+ if (nbcon_emit_next_record(&wctxt, false)) { -+ nbcon_context_release(ctxt); -+ backlog = ctxt->backlog; -+ } -+ } -+ -+ con->device_unlock(con, lock_flags); -+ } -+ -+ console_srcu_read_unlock(cookie); -+ -+ cond_resched(); -+ -+ } while (backlog); -+ -+ goto wait_for_event; -+} -+ -+/** -+ * nbcon_irq_work - irq work to wake console printer thread -+ * @irq_work: The irq work to operate on -+ */ -+static void nbcon_irq_work(struct irq_work *irq_work) -+{ -+ struct console *con = container_of(irq_work, struct console, irq_work); -+ -+ nbcon_kthread_wake(con); -+} -+ -+static inline bool rcuwait_has_sleeper(struct rcuwait *w) -+{ -+ /* -+ * Guarantee any new records can be seen by tasks preparing to wait -+ * before this context checks if the rcuwait is empty. -+ * -+ * This full memory barrier pairs with the full memory barrier within -+ * set_current_state() of ___rcuwait_wait_event(), which is called -+ * after prepare_to_rcuwait() adds the waiter but before it has -+ * checked the wait condition. -+ * -+ * This pairs with nbcon_kthread_func:A. -+ */ -+ smp_mb(); /* LMM(rcuwait_has_sleeper:A) */ -+ return rcuwait_active(w); -+} -+ -+/** -+ * nbcon_kthreads_wake - Wake up printing threads using irq_work -+ */ -+void nbcon_kthreads_wake(void) -+{ -+ struct console *con; -+ int cookie; -+ -+ if (!printk_kthreads_running) -+ return; -+ -+ cookie = console_srcu_read_lock(); -+ for_each_console_srcu(con) { -+ if (!(console_srcu_read_flags(con) & CON_NBCON)) -+ continue; -+ -+ /* -+ * Only schedule irq_work if the printing thread is -+ * actively waiting. If not waiting, the thread will -+ * notice by itself that it has work to do. -+ */ -+ if (rcuwait_has_sleeper(&con->rcuwait)) -+ irq_work_queue(&con->irq_work); -+ } -+ console_srcu_read_unlock(cookie); -+} -+ -+/* -+ * nbcon_kthread_stop - Stop a console printer thread -+ * @con: Console to operate on -+ */ -+void nbcon_kthread_stop(struct console *con) -+{ -+ lockdep_assert_console_list_lock_held(); -+ -+ if (!con->kthread) -+ return; -+ -+ kthread_stop(con->kthread); -+ con->kthread = NULL; -+} -+ -+/** -+ * nbcon_kthread_create - Create a console printer thread -+ * @con: Console to operate on -+ * -+ * Return: True if the kthread was started or already exists. -+ * Otherwise false and @con must not be registered. -+ * -+ * This function is called when it will be expected that nbcon consoles are -+ * flushed using the kthread. The messages printed with NBCON_PRIO_NORMAL -+ * will be no longer flushed by the legacy loop. This is why failure must -+ * be fatal for console registration. -+ * -+ * If @con was already registered and this function fails, @con must be -+ * unregistered before the global state variable @printk_kthreads_running -+ * can be set. -+ */ -+bool nbcon_kthread_create(struct console *con) -+{ -+ struct task_struct *kt; -+ -+ lockdep_assert_console_list_lock_held(); -+ -+ if (con->kthread) -+ return true; -+ -+ kt = kthread_run(nbcon_kthread_func, con, "pr/%s%d", con->name, con->index); -+ if (WARN_ON(IS_ERR(kt))) { -+ con_printk(KERN_ERR, con, "failed to start printing thread\n"); -+ return false; -+ } -+ -+ con->kthread = kt; -+ -+ return true; -+} -+ - /* Track the nbcon emergency nesting per CPU. */ - static DEFINE_PER_CPU(unsigned int, nbcon_pcpu_emergency_nesting); - static unsigned int early_nbcon_pcpu_emergency_nesting __initdata; -@@ -1396,6 +1624,12 @@ bool nbcon_alloc(struct console *con) - { - struct nbcon_state state = { }; - -+ /* The write_thread() callback is mandatory. */ -+ if (WARN_ON(!con->write_thread)) -+ return false; -+ -+ rcuwait_init(&con->rcuwait); -+ init_irq_work(&con->irq_work, nbcon_irq_work); - nbcon_state_set(con, &state); - - /* -@@ -1418,6 +1652,14 @@ bool nbcon_alloc(struct console *con) - con_printk(KERN_ERR, con, "failed to allocate printing buffer\n"); - return false; - } -+ -+ if (printk_kthreads_running) { -+ if (!nbcon_kthread_create(con)) { -+ kfree(con->pbufs); -+ con->pbufs = NULL; -+ return false; -+ } -+ } - } - - return true; -@@ -1431,6 +1673,9 @@ void nbcon_free(struct console *con) - { - struct nbcon_state state = { }; - -+ if (printk_kthreads_running) -+ nbcon_kthread_stop(con); -+ - nbcon_state_set(con, &state); - - /* Boot consoles share global printk buffers. */ ---- a/kernel/printk/printk.c -+++ b/kernel/printk/printk.c -@@ -34,6 +34,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -496,6 +497,9 @@ static u64 syslog_seq; - static size_t syslog_partial; - static bool syslog_time; - -+/* True when _all_ printer threads are available for printing. */ -+bool printk_kthreads_running; -+ - struct latched_seq { - seqcount_latch_t latch; - u64 val[2]; -@@ -3028,6 +3032,8 @@ static bool console_emit_next_record(str - return false; - } - -+static inline void printk_kthreads_check_locked(void) { } -+ - #endif /* CONFIG_PRINTK */ - - /* -@@ -3388,6 +3394,102 @@ void console_start(struct console *conso - } - EXPORT_SYMBOL(console_start); - -+#ifdef CONFIG_PRINTK -+static int unregister_console_locked(struct console *console); -+ -+/* True when system boot is far enough to create printer threads. */ -+static bool printk_kthreads_ready __ro_after_init; -+ -+/** -+ * printk_kthreads_shutdown - shutdown all threaded printers -+ * -+ * On system shutdown all threaded printers are stopped. This allows printk -+ * to transition back to atomic printing, thus providing a robust mechanism -+ * for the final shutdown/reboot messages to be output. -+ */ -+static void printk_kthreads_shutdown(void) -+{ -+ struct console *con; -+ -+ console_list_lock(); -+ if (printk_kthreads_running) { -+ printk_kthreads_running = false; -+ -+ for_each_console(con) { -+ if (con->flags & CON_NBCON) -+ nbcon_kthread_stop(con); -+ } -+ -+ /* -+ * The threads may have been stopped while printing a -+ * backlog. Flush any records left over. -+ */ -+ nbcon_atomic_flush_pending(); -+ } -+ console_list_unlock(); -+} -+ -+static struct syscore_ops printk_syscore_ops = { -+ .shutdown = printk_kthreads_shutdown, -+}; -+ -+/* -+ * If appropriate, start nbcon kthreads and set @printk_kthreads_running. -+ * If any kthreads fail to start, those consoles are unregistered. -+ * -+ * Must be called under console_list_lock(). -+ */ -+static void printk_kthreads_check_locked(void) -+{ -+ struct hlist_node *tmp; -+ struct console *con; -+ -+ lockdep_assert_console_list_lock_held(); -+ -+ if (!printk_kthreads_ready) -+ return; -+ -+ /* -+ * Printer threads cannot be started as long as any boot console is -+ * registered because there is no way to synchronize the hardware -+ * registers between boot console code and regular console code. -+ * It can only be known that there will be no new boot consoles when -+ * an nbcon console is registered. -+ */ -+ if (have_boot_console || !have_nbcon_console) { -+ /* Clear flag in case all nbcon consoles unregistered. */ -+ printk_kthreads_running = false; -+ return; -+ } -+ -+ if (printk_kthreads_running) -+ return; -+ -+ hlist_for_each_entry_safe(con, tmp, &console_list, node) { -+ if (!(con->flags & CON_NBCON)) -+ continue; -+ -+ if (!nbcon_kthread_create(con)) -+ unregister_console_locked(con); -+ } -+ -+ printk_kthreads_running = true; -+} -+ -+static int __init printk_set_kthreads_ready(void) -+{ -+ register_syscore_ops(&printk_syscore_ops); -+ -+ console_list_lock(); -+ printk_kthreads_ready = true; -+ printk_kthreads_check_locked(); -+ console_list_unlock(); -+ -+ return 0; -+} -+early_initcall(printk_set_kthreads_ready); -+#endif /* CONFIG_PRINTK */ -+ - static int __read_mostly keep_bootcon; - - static int __init keep_bootcon_setup(char *str) -@@ -3746,6 +3848,9 @@ void register_console(struct console *ne - unregister_console_locked(con); - } - } -+ -+ /* Changed console list, may require printer threads to start/stop. */ -+ printk_kthreads_check_locked(); - unlock: - console_list_unlock(); - } -@@ -3842,6 +3947,9 @@ static int unregister_console_locked(str - if (!found_nbcon_con) - have_nbcon_console = found_nbcon_con; - -+ /* Changed console list, may require printer threads to start/stop. */ -+ printk_kthreads_check_locked(); -+ - return res; - } - diff --git a/debian/patches-rt/0044-printk-nbcon-Relocate-nbcon_atomic_emit_one.patch b/debian/patches-rt/0044-printk-nbcon-Relocate-nbcon_atomic_emit_one.patch deleted file mode 100644 index 0255ced..0000000 --- a/debian/patches-rt/0044-printk-nbcon-Relocate-nbcon_atomic_emit_one.patch +++ /dev/null @@ -1,111 +0,0 @@ -From: John Ogness -Date: Wed, 4 Sep 2024 14:11:26 +0206 -Subject: [PATCH 44/54] printk: nbcon: Relocate nbcon_atomic_emit_one() -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -Move nbcon_atomic_emit_one() so that it can be used by -nbcon_kthread_func() in a follow-up commit. - -Signed-off-by: John Ogness -Reviewed-by: Petr Mladek -Link: https://lore.kernel.org/r/20240904120536.115780-8-john.ogness@linutronix.de -Signed-off-by: Petr Mladek -Signed-off-by: Sebastian Andrzej Siewior ---- - kernel/printk/nbcon.c | 78 +++++++++++++++++++++++++------------------------- - 1 file changed, 39 insertions(+), 39 deletions(-) - ---- a/kernel/printk/nbcon.c -+++ b/kernel/printk/nbcon.c -@@ -1042,6 +1042,45 @@ static bool nbcon_emit_next_record(struc - return nbcon_context_exit_unsafe(ctxt); - } - -+/* -+ * nbcon_atomic_emit_one - Print one record for an nbcon console using the -+ * write_atomic() callback -+ * @wctxt: An initialized write context struct to use for this context -+ * -+ * Return: True, when a record has been printed and there are still -+ * pending records. The caller might want to continue flushing. -+ * -+ * False, when there is no pending record, or when the console -+ * context cannot be acquired, or the ownership has been lost. -+ * The caller should give up. Either the job is done, cannot be -+ * done, or will be handled by the owning context. -+ * -+ * This is an internal helper to handle the locking of the console before -+ * calling nbcon_emit_next_record(). -+ */ -+static bool nbcon_atomic_emit_one(struct nbcon_write_context *wctxt) -+{ -+ struct nbcon_context *ctxt = &ACCESS_PRIVATE(wctxt, ctxt); -+ -+ if (!nbcon_context_try_acquire(ctxt)) -+ return false; -+ -+ /* -+ * nbcon_emit_next_record() returns false when the console was -+ * handed over or taken over. In both cases the context is no -+ * longer valid. -+ * -+ * The higher priority printing context takes over responsibility -+ * to print the pending records. -+ */ -+ if (!nbcon_emit_next_record(wctxt, true)) -+ return false; -+ -+ nbcon_context_release(ctxt); -+ -+ return ctxt->backlog; -+} -+ - /** - * nbcon_kthread_should_wakeup - Check whether a printer thread should wakeup - * @con: Console to operate on -@@ -1319,45 +1358,6 @@ enum nbcon_prio nbcon_get_default_prio(v - return NBCON_PRIO_NORMAL; - } - --/* -- * nbcon_atomic_emit_one - Print one record for an nbcon console using the -- * write_atomic() callback -- * @wctxt: An initialized write context struct to use for this context -- * -- * Return: True, when a record has been printed and there are still -- * pending records. The caller might want to continue flushing. -- * -- * False, when there is no pending record, or when the console -- * context cannot be acquired, or the ownership has been lost. -- * The caller should give up. Either the job is done, cannot be -- * done, or will be handled by the owning context. -- * -- * This is an internal helper to handle the locking of the console before -- * calling nbcon_emit_next_record(). -- */ --static bool nbcon_atomic_emit_one(struct nbcon_write_context *wctxt) --{ -- struct nbcon_context *ctxt = &ACCESS_PRIVATE(wctxt, ctxt); -- -- if (!nbcon_context_try_acquire(ctxt)) -- return false; -- -- /* -- * nbcon_emit_next_record() returns false when the console was -- * handed over or taken over. In both cases the context is no -- * longer valid. -- * -- * The higher priority printing context takes over responsibility -- * to print the pending records. -- */ -- if (!nbcon_emit_next_record(wctxt, true)) -- return false; -- -- nbcon_context_release(ctxt); -- -- return ctxt->backlog; --} -- - /** - * nbcon_legacy_emit_next_record - Print one record for an nbcon console - * in legacy contexts diff --git a/debian/patches-rt/0045-printk-nbcon-Use-thread-callback-if-in-task-context-.patch b/debian/patches-rt/0045-printk-nbcon-Use-thread-callback-if-in-task-context-.patch deleted file mode 100644 index bf9daae..0000000 --- a/debian/patches-rt/0045-printk-nbcon-Use-thread-callback-if-in-task-context-.patch +++ /dev/null @@ -1,228 +0,0 @@ -From: John Ogness -Date: Wed, 4 Sep 2024 14:11:27 +0206 -Subject: [PATCH 45/54] printk: nbcon: Use thread callback if in task context - for legacy -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -When printing via console_lock, the write_atomic() callback is -used for nbcon consoles. However, if it is known that the -current context is a task context, the write_thread() callback -can be used instead. - -Using write_thread() instead of write_atomic() helps to reduce -large disabled preemption regions when the device_lock does not -disable preemption. - -This is mainly a preparatory change to allow avoiding -write_atomic() completely during normal operation if boot -consoles are registered. - -As a side-effect, it also allows consolidating the printing -code for legacy printing and the kthread printer. - -Signed-off-by: John Ogness -Reviewed-by: Petr Mladek -Link: https://lore.kernel.org/r/20240904120536.115780-9-john.ogness@linutronix.de -Signed-off-by: Petr Mladek -Signed-off-by: Sebastian Andrzej Siewior ---- - kernel/printk/internal.h | 4 - - kernel/printk/nbcon.c | 95 ++++++++++++++++++++++++++--------------------- - kernel/printk/printk.c | 5 +- - 3 files changed, 59 insertions(+), 45 deletions(-) - ---- a/kernel/printk/internal.h -+++ b/kernel/printk/internal.h -@@ -90,7 +90,7 @@ void nbcon_free(struct console *con); - enum nbcon_prio nbcon_get_default_prio(void); - void nbcon_atomic_flush_pending(void); - bool nbcon_legacy_emit_next_record(struct console *con, bool *handover, -- int cookie); -+ int cookie, bool use_atomic); - bool nbcon_kthread_create(struct console *con); - void nbcon_kthread_stop(struct console *con); - void nbcon_kthreads_wake(void); -@@ -174,7 +174,7 @@ static inline void nbcon_free(struct con - static inline enum nbcon_prio nbcon_get_default_prio(void) { return NBCON_PRIO_NONE; } - static inline void nbcon_atomic_flush_pending(void) { } - static inline bool nbcon_legacy_emit_next_record(struct console *con, bool *handover, -- int cookie) { return false; } -+ int cookie, bool use_atomic) { return false; } - static inline void nbcon_kthread_wake(struct console *con) { } - - static inline bool console_is_usable(struct console *con, short flags, ---- a/kernel/printk/nbcon.c -+++ b/kernel/printk/nbcon.c -@@ -1043,9 +1043,10 @@ static bool nbcon_emit_next_record(struc - } - - /* -- * nbcon_atomic_emit_one - Print one record for an nbcon console using the -- * write_atomic() callback -+ * nbcon_emit_one - Print one record for an nbcon console using the -+ * specified callback - * @wctxt: An initialized write context struct to use for this context -+ * @use_atomic: True if the write_atomic() callback is to be used - * - * Return: True, when a record has been printed and there are still - * pending records. The caller might want to continue flushing. -@@ -1058,12 +1059,25 @@ static bool nbcon_emit_next_record(struc - * This is an internal helper to handle the locking of the console before - * calling nbcon_emit_next_record(). - */ --static bool nbcon_atomic_emit_one(struct nbcon_write_context *wctxt) -+static bool nbcon_emit_one(struct nbcon_write_context *wctxt, bool use_atomic) - { - struct nbcon_context *ctxt = &ACCESS_PRIVATE(wctxt, ctxt); -+ struct console *con = ctxt->console; -+ unsigned long flags; -+ bool ret = false; -+ -+ if (!use_atomic) { -+ con->device_lock(con, &flags); -+ -+ /* -+ * Ensure this stays on the CPU to make handover and -+ * takeover possible. -+ */ -+ cant_migrate(); -+ } - - if (!nbcon_context_try_acquire(ctxt)) -- return false; -+ goto out; - - /* - * nbcon_emit_next_record() returns false when the console was -@@ -1073,12 +1087,16 @@ static bool nbcon_atomic_emit_one(struct - * The higher priority printing context takes over responsibility - * to print the pending records. - */ -- if (!nbcon_emit_next_record(wctxt, true)) -- return false; -+ if (!nbcon_emit_next_record(wctxt, use_atomic)) -+ goto out; - - nbcon_context_release(ctxt); - -- return ctxt->backlog; -+ ret = ctxt->backlog; -+out: -+ if (!use_atomic) -+ con->device_unlock(con, flags); -+ return ret; - } - - /** -@@ -1163,30 +1181,8 @@ static int nbcon_kthread_func(void *__co - - con_flags = console_srcu_read_flags(con); - -- if (console_is_usable(con, con_flags, false)) { -- unsigned long lock_flags; -- -- con->device_lock(con, &lock_flags); -- -- /* -- * Ensure this stays on the CPU to make handover and -- * takeover possible. -- */ -- cant_migrate(); -- -- if (nbcon_context_try_acquire(ctxt)) { -- /* -- * If the emit fails, this context is no -- * longer the owner. -- */ -- if (nbcon_emit_next_record(&wctxt, false)) { -- nbcon_context_release(ctxt); -- backlog = ctxt->backlog; -- } -- } -- -- con->device_unlock(con, lock_flags); -- } -+ if (console_is_usable(con, con_flags, false)) -+ backlog = nbcon_emit_one(&wctxt, false); - - console_srcu_read_unlock(cookie); - -@@ -1367,6 +1363,13 @@ enum nbcon_prio nbcon_get_default_prio(v - * both the console_lock and the SRCU read lock. Otherwise it - * is set to false. - * @cookie: The cookie from the SRCU read lock. -+ * @use_atomic: Set true when called in an atomic or unknown context. -+ * It affects which nbcon callback will be used: write_atomic() -+ * or write_thread(). -+ * -+ * When false, the write_thread() callback is used and would be -+ * called in a preemtible context unless disabled by the -+ * device_lock. The legacy handover is not allowed in this mode. - * - * Context: Any context except NMI. - * Return: True, when a record has been printed and there are still -@@ -1382,26 +1385,36 @@ enum nbcon_prio nbcon_get_default_prio(v - * Essentially it is the nbcon version of console_emit_next_record(). - */ - bool nbcon_legacy_emit_next_record(struct console *con, bool *handover, -- int cookie) -+ int cookie, bool use_atomic) - { - struct nbcon_write_context wctxt = { }; - struct nbcon_context *ctxt = &ACCESS_PRIVATE(&wctxt, ctxt); - unsigned long flags; - bool progress; - -- /* Use the same procedure as console_emit_next_record(). */ -- printk_safe_enter_irqsave(flags); -- console_lock_spinning_enable(); -- stop_critical_timings(); -- - ctxt->console = con; - ctxt->prio = nbcon_get_default_prio(); - -- progress = nbcon_atomic_emit_one(&wctxt); -+ if (use_atomic) { -+ /* -+ * In an atomic or unknown context, use the same procedure as -+ * in console_emit_next_record(). It allows to handover. -+ */ -+ printk_safe_enter_irqsave(flags); -+ console_lock_spinning_enable(); -+ stop_critical_timings(); -+ } - -- start_critical_timings(); -- *handover = console_lock_spinning_disable_and_check(cookie); -- printk_safe_exit_irqrestore(flags); -+ progress = nbcon_emit_one(&wctxt, use_atomic); -+ -+ if (use_atomic) { -+ start_critical_timings(); -+ *handover = console_lock_spinning_disable_and_check(cookie); -+ printk_safe_exit_irqrestore(flags); -+ } else { -+ /* Non-atomic does not perform legacy spinning handovers. */ -+ *handover = false; -+ } - - return progress; - } ---- a/kernel/printk/printk.c -+++ b/kernel/printk/printk.c -@@ -3078,12 +3078,13 @@ static bool console_flush_all(bool do_co - u64 printk_seq; - bool progress; - -- if (!console_is_usable(con, flags, true)) -+ if (!console_is_usable(con, flags, !do_cond_resched)) - continue; - any_usable = true; - - if (flags & CON_NBCON) { -- progress = nbcon_legacy_emit_next_record(con, handover, cookie); -+ progress = nbcon_legacy_emit_next_record(con, handover, cookie, -+ !do_cond_resched); - printk_seq = nbcon_seq_read(con); - } else { - progress = console_emit_next_record(con, handover, cookie); diff --git a/debian/patches-rt/0046-printk-nbcon-Rely-on-kthreads-for-normal-operation.patch b/debian/patches-rt/0046-printk-nbcon-Rely-on-kthreads-for-normal-operation.patch deleted file mode 100644 index 3ad1924..0000000 --- a/debian/patches-rt/0046-printk-nbcon-Rely-on-kthreads-for-normal-operation.patch +++ /dev/null @@ -1,287 +0,0 @@ -From: John Ogness -Date: Wed, 4 Sep 2024 14:11:28 +0206 -Subject: [PATCH 46/54] printk: nbcon: Rely on kthreads for normal operation -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -Once the kthread is running and available -(i.e. @printk_kthreads_running is set), the kthread becomes -responsible for flushing any pending messages which are added -in NBCON_PRIO_NORMAL context. Namely the legacy -console_flush_all() and device_release() no longer flush the -console. And nbcon_atomic_flush_pending() used by -nbcon_cpu_emergency_exit() no longer flushes messages added -after the emergency messages. - -The console context is safe when used by the kthread only when -one of the following conditions are true: - - 1. Other caller acquires the console context with - NBCON_PRIO_NORMAL with preemption disabled. It will - release the context before rescheduling. - - 2. Other caller acquires the console context with - NBCON_PRIO_NORMAL under the device_lock. - - 3. The kthread is the only context which acquires the console - with NBCON_PRIO_NORMAL. - -This is satisfied for all atomic printing call sites: - -nbcon_legacy_emit_next_record() (#1) - -nbcon_atomic_flush_pending_con() (#1) - -nbcon_device_release() (#2) - -It is even double guaranteed when @printk_kthreads_running -is set because then _only_ the kthread will print for -NBCON_PRIO_NORMAL. (#3) - -Signed-off-by: John Ogness -Reviewed-by: Petr Mladek -Link: https://lore.kernel.org/r/20240904120536.115780-10-john.ogness@linutronix.de -Signed-off-by: Petr Mladek -Signed-off-by: Sebastian Andrzej Siewior ---- - kernel/printk/internal.h | 26 +++++++++++++++++++++++++ - kernel/printk/nbcon.c | 17 ++++++++++------ - kernel/printk/printk.c | 48 ++++++++++++++++++++++++++++++++++++++++++++++- - 3 files changed, 84 insertions(+), 7 deletions(-) - ---- a/kernel/printk/internal.h -+++ b/kernel/printk/internal.h -@@ -113,6 +113,13 @@ static inline bool console_is_usable(str - /* The write_atomic() callback is optional. */ - if (use_atomic && !con->write_atomic) - return false; -+ -+ /* -+ * For the !use_atomic case, @printk_kthreads_running is not -+ * checked because the write_thread() callback is also used -+ * via the legacy loop when the printer threads are not -+ * available. -+ */ - } else { - if (!con->write) - return false; -@@ -176,6 +183,7 @@ static inline void nbcon_atomic_flush_pe - static inline bool nbcon_legacy_emit_next_record(struct console *con, bool *handover, - int cookie, bool use_atomic) { return false; } - static inline void nbcon_kthread_wake(struct console *con) { } -+static inline void nbcon_kthreads_wake(void) { } - - static inline bool console_is_usable(struct console *con, short flags, - bool use_atomic) { return false; } -@@ -190,6 +198,7 @@ extern bool legacy_allow_panic_sync; - /** - * struct console_flush_type - Define available console flush methods - * @nbcon_atomic: Flush directly using nbcon_atomic() callback -+ * @nbcon_offload: Offload flush to printer thread - * @legacy_direct: Call the legacy loop in this context - * @legacy_offload: Offload the legacy loop into IRQ - * -@@ -197,6 +206,7 @@ extern bool legacy_allow_panic_sync; - */ - struct console_flush_type { - bool nbcon_atomic; -+ bool nbcon_offload; - bool legacy_direct; - bool legacy_offload; - }; -@@ -211,6 +221,22 @@ static inline void printk_get_console_fl - - switch (nbcon_get_default_prio()) { - case NBCON_PRIO_NORMAL: -+ if (have_nbcon_console && !have_boot_console) { -+ if (printk_kthreads_running) -+ ft->nbcon_offload = true; -+ else -+ ft->nbcon_atomic = true; -+ } -+ -+ /* Legacy consoles are flushed directly when possible. */ -+ if (have_legacy_console || have_boot_console) { -+ if (!is_printk_legacy_deferred()) -+ ft->legacy_direct = true; -+ else -+ ft->legacy_offload = true; -+ } -+ break; -+ - case NBCON_PRIO_EMERGENCY: - if (have_nbcon_console && !have_boot_console) - ft->nbcon_atomic = true; ---- a/kernel/printk/nbcon.c -+++ b/kernel/printk/nbcon.c -@@ -1494,6 +1494,7 @@ static int __nbcon_atomic_flush_pending_ - static void nbcon_atomic_flush_pending_con(struct console *con, u64 stop_seq, - bool allow_unsafe_takeover) - { -+ struct console_flush_type ft; - unsigned long flags; - int err; - -@@ -1523,10 +1524,12 @@ static void nbcon_atomic_flush_pending_c - - /* - * If flushing was successful but more records are available, this -- * context must flush those remaining records because there is no -- * other context that will do it. -+ * context must flush those remaining records if the printer thread -+ * is not available do it. - */ -- if (prb_read_valid(prb, nbcon_seq_read(con), NULL)) { -+ printk_get_console_flush_type(&ft); -+ if (!ft.nbcon_offload && -+ prb_read_valid(prb, nbcon_seq_read(con), NULL)) { - stop_seq = prb_next_reserve_seq(prb); - goto again; - } -@@ -1754,17 +1757,19 @@ void nbcon_device_release(struct console - - /* - * This context must flush any new records added while the console -- * was locked. The console_srcu_read_lock must be taken to ensure -- * the console is usable throughout flushing. -+ * was locked if the printer thread is not available to do it. The -+ * console_srcu_read_lock must be taken to ensure the console is -+ * usable throughout flushing. - */ - cookie = console_srcu_read_lock(); -+ printk_get_console_flush_type(&ft); - if (console_is_usable(con, console_srcu_read_flags(con), true) && -+ !ft.nbcon_offload && - prb_read_valid(prb, nbcon_seq_read(con), NULL)) { - /* - * If nbcon_atomic flushing is not available, fallback to - * using the legacy loop. - */ -- printk_get_console_flush_type(&ft); - if (ft.nbcon_atomic) { - __nbcon_atomic_flush_pending_con(con, prb_next_reserve_seq(prb), false); - } else if (ft.legacy_direct) { ---- a/kernel/printk/printk.c -+++ b/kernel/printk/printk.c -@@ -2384,6 +2384,9 @@ asmlinkage int vprintk_emit(int facility - if (ft.nbcon_atomic) - nbcon_atomic_flush_pending(); - -+ if (ft.nbcon_offload) -+ nbcon_kthreads_wake(); -+ - if (ft.legacy_direct) { - /* - * The caller may be holding system-critical or -@@ -2733,6 +2736,7 @@ void suspend_console(void) - - void resume_console(void) - { -+ struct console_flush_type ft; - struct console *con; - - if (!console_suspend_enabled) -@@ -2750,6 +2754,10 @@ void resume_console(void) - */ - synchronize_srcu(&console_srcu); - -+ printk_get_console_flush_type(&ft); -+ if (ft.nbcon_offload) -+ nbcon_kthreads_wake(); -+ - pr_flush(1000, true); - } - -@@ -3061,6 +3069,7 @@ static inline void printk_kthreads_check - */ - static bool console_flush_all(bool do_cond_resched, u64 *next_seq, bool *handover) - { -+ struct console_flush_type ft; - bool any_usable = false; - struct console *con; - bool any_progress; -@@ -3072,12 +3081,22 @@ static bool console_flush_all(bool do_co - do { - any_progress = false; - -+ printk_get_console_flush_type(&ft); -+ - cookie = console_srcu_read_lock(); - for_each_console_srcu(con) { - short flags = console_srcu_read_flags(con); - u64 printk_seq; - bool progress; - -+ /* -+ * console_flush_all() is only responsible for nbcon -+ * consoles when the nbcon consoles cannot print via -+ * their atomic or threaded flushing. -+ */ -+ if ((flags & CON_NBCON) && (ft.nbcon_atomic || ft.nbcon_offload)) -+ continue; -+ - if (!console_is_usable(con, flags, !do_cond_resched)) - continue; - any_usable = true; -@@ -3388,9 +3407,25 @@ EXPORT_SYMBOL(console_stop); - - void console_start(struct console *console) - { -+ struct console_flush_type ft; -+ bool is_nbcon; -+ - console_list_lock(); - console_srcu_write_flags(console, console->flags | CON_ENABLED); -+ is_nbcon = console->flags & CON_NBCON; - console_list_unlock(); -+ -+ /* -+ * Ensure that all SRCU list walks have completed. The related -+ * printing context must be able to see it is enabled so that -+ * it is guaranteed to wake up and resume printing. -+ */ -+ synchronize_srcu(&console_srcu); -+ -+ printk_get_console_flush_type(&ft); -+ if (is_nbcon && ft.nbcon_offload) -+ nbcon_kthread_wake(console); -+ - __pr_flush(console, 1000, true); - } - EXPORT_SYMBOL(console_start); -@@ -4116,6 +4151,8 @@ static bool __pr_flush(struct console *c - - /* Flush the consoles so that records up to @seq are printed. */ - printk_get_console_flush_type(&ft); -+ if (ft.nbcon_atomic) -+ nbcon_atomic_flush_pending(); - if (ft.legacy_direct) { - console_lock(); - console_unlock(); -@@ -4153,8 +4190,10 @@ static bool __pr_flush(struct console *c - * that they make forward progress, so only increment - * @diff for usable consoles. - */ -- if (!console_is_usable(c, flags, true)) -+ if (!console_is_usable(c, flags, true) && -+ !console_is_usable(c, flags, false)) { - continue; -+ } - - if (flags & CON_NBCON) { - printk_seq = nbcon_seq_read(c); -@@ -4630,8 +4669,15 @@ EXPORT_SYMBOL_GPL(kmsg_dump_rewind); - */ - void console_try_replay_all(void) - { -+ struct console_flush_type ft; -+ -+ printk_get_console_flush_type(&ft); - if (console_trylock()) { - __console_rewind_all(); -+ if (ft.nbcon_atomic) -+ nbcon_atomic_flush_pending(); -+ if (ft.nbcon_offload) -+ nbcon_kthreads_wake(); - /* Consoles are flushed as part of console_unlock(). */ - console_unlock(); - } diff --git a/debian/patches-rt/0047-printk-Provide-helper-for-message-prepending.patch b/debian/patches-rt/0047-printk-Provide-helper-for-message-prepending.patch deleted file mode 100644 index cb42c7c..0000000 --- a/debian/patches-rt/0047-printk-Provide-helper-for-message-prepending.patch +++ /dev/null @@ -1,83 +0,0 @@ -From: John Ogness -Date: Wed, 4 Sep 2024 14:11:29 +0206 -Subject: [PATCH 47/54] printk: Provide helper for message prepending -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -In order to support prepending different texts to printk -messages, split out the prepending code into a helper -function. - -Signed-off-by: John Ogness -Reviewed-by: Petr Mladek -Link: https://lore.kernel.org/r/20240904120536.115780-11-john.ogness@linutronix.de -Signed-off-by: Petr Mladek -Signed-off-by: Sebastian Andrzej Siewior ---- - kernel/printk/printk.c | 36 +++++++++++++++++++++++++----------- - 1 file changed, 25 insertions(+), 11 deletions(-) - ---- a/kernel/printk/printk.c -+++ b/kernel/printk/printk.c -@@ -2844,30 +2844,31 @@ static void __console_unlock(void) - #ifdef CONFIG_PRINTK - - /* -- * Prepend the message in @pmsg->pbufs->outbuf with a "dropped message". This -- * is achieved by shifting the existing message over and inserting the dropped -- * message. -+ * Prepend the message in @pmsg->pbufs->outbuf. This is achieved by shifting -+ * the existing message over and inserting the scratchbuf message. - * -- * @pmsg is the printk message to prepend. -- * -- * @dropped is the dropped count to report in the dropped message. -+ * @pmsg is the original printk message. -+ * @fmt is the printf format of the message which will prepend the existing one. - * -- * If the message text in @pmsg->pbufs->outbuf does not have enough space for -- * the dropped message, the message text will be sufficiently truncated. -+ * If there is not enough space in @pmsg->pbufs->outbuf, the existing -+ * message text will be sufficiently truncated. - * - * If @pmsg->pbufs->outbuf is modified, @pmsg->outbuf_len is updated. - */ --void console_prepend_dropped(struct printk_message *pmsg, unsigned long dropped) -+__printf(2, 3) -+static void console_prepend_message(struct printk_message *pmsg, const char *fmt, ...) - { - struct printk_buffers *pbufs = pmsg->pbufs; - const size_t scratchbuf_sz = sizeof(pbufs->scratchbuf); - const size_t outbuf_sz = sizeof(pbufs->outbuf); - char *scratchbuf = &pbufs->scratchbuf[0]; - char *outbuf = &pbufs->outbuf[0]; -+ va_list args; - size_t len; - -- len = scnprintf(scratchbuf, scratchbuf_sz, -- "** %lu printk messages dropped **\n", dropped); -+ va_start(args, fmt); -+ len = vscnprintf(scratchbuf, scratchbuf_sz, fmt, args); -+ va_end(args); - - /* - * Make sure outbuf is sufficiently large before prepending. -@@ -2890,6 +2891,19 @@ void console_prepend_dropped(struct prin - } - - /* -+ * Prepend the message in @pmsg->pbufs->outbuf with a "dropped message". -+ * @pmsg->outbuf_len is updated appropriately. -+ * -+ * @pmsg is the printk message to prepend. -+ * -+ * @dropped is the dropped count to report in the dropped message. -+ */ -+void console_prepend_dropped(struct printk_message *pmsg, unsigned long dropped) -+{ -+ console_prepend_message(pmsg, "** %lu printk messages dropped **\n", dropped); -+} -+ -+/* - * Read and format the specified record (or a later record if the specified - * record is not available). - * diff --git a/debian/patches-rt/0048-printk-nbcon-Show-replay-message-on-takeover.patch b/debian/patches-rt/0048-printk-nbcon-Show-replay-message-on-takeover.patch deleted file mode 100644 index 791448e..0000000 --- a/debian/patches-rt/0048-printk-nbcon-Show-replay-message-on-takeover.patch +++ /dev/null @@ -1,133 +0,0 @@ -From: John Ogness -Date: Wed, 4 Sep 2024 14:11:30 +0206 -Subject: [PATCH 48/54] printk: nbcon: Show replay message on takeover -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -An emergency or panic context can takeover console ownership -while the current owner was printing a printk message. The -atomic printer will re-print the message that the previous -owner was printing. However, this can look confusing to the -user and may even seem as though a message was lost. - - [3430014.1 - [3430014.181123] usb 1-2: Product: USB Audio - -Add a new field @nbcon_prev_seq to struct console to track -the sequence number to print that was assigned to the previous -console owner. If this matches the sequence number to print -that the current owner is assigned, then a takeover must have -occurred. In this case, print an additional message to inform -the user that the previous message is being printed again. - - [3430014.1 - ** replaying previous printk message ** - [3430014.181123] usb 1-2: Product: USB Audio - -Signed-off-by: John Ogness -Reviewed-by: Petr Mladek -Link: https://lore.kernel.org/r/20240904120536.115780-12-john.ogness@linutronix.de -Signed-off-by: Petr Mladek -Signed-off-by: Sebastian Andrzej Siewior ---- - include/linux/console.h | 2 ++ - kernel/printk/internal.h | 1 + - kernel/printk/nbcon.c | 26 ++++++++++++++++++++++++++ - kernel/printk/printk.c | 11 +++++++++++ - 4 files changed, 40 insertions(+) - ---- a/include/linux/console.h -+++ b/include/linux/console.h -@@ -325,6 +325,7 @@ struct nbcon_write_context { - * @nbcon_state: State for nbcon consoles - * @nbcon_seq: Sequence number of the next record for nbcon to print - * @nbcon_device_ctxt: Context available for non-printing operations -+ * @nbcon_prev_seq: Seq num the previous nbcon owner was assigned to print - * @pbufs: Pointer to nbcon private buffer - * @kthread: Printer kthread for this console - * @rcuwait: RCU-safe wait object for @kthread waking -@@ -459,6 +460,7 @@ struct console { - atomic_t __private nbcon_state; - atomic_long_t __private nbcon_seq; - struct nbcon_context __private nbcon_device_ctxt; -+ atomic_long_t __private nbcon_prev_seq; - - struct printk_buffers *pbufs; - struct task_struct *kthread; ---- a/kernel/printk/internal.h -+++ b/kernel/printk/internal.h -@@ -319,4 +319,5 @@ bool printk_get_next_message(struct prin - - #ifdef CONFIG_PRINTK - void console_prepend_dropped(struct printk_message *pmsg, unsigned long dropped); -+void console_prepend_replay(struct printk_message *pmsg); - #endif ---- a/kernel/printk/nbcon.c -+++ b/kernel/printk/nbcon.c -@@ -946,7 +946,9 @@ static bool nbcon_emit_next_record(struc - .pbufs = ctxt->pbufs, - }; - unsigned long con_dropped; -+ struct nbcon_state cur; - unsigned long dropped; -+ unsigned long ulseq; - - /* - * This function should never be called for consoles that have not -@@ -987,6 +989,29 @@ static bool nbcon_emit_next_record(struc - if (dropped && !is_extended) - console_prepend_dropped(&pmsg, dropped); - -+ /* -+ * If the previous owner was assigned the same record, this context -+ * has taken over ownership and is replaying the record. Prepend a -+ * message to let the user know the record is replayed. -+ */ -+ ulseq = atomic_long_read(&ACCESS_PRIVATE(con, nbcon_prev_seq)); -+ if (__ulseq_to_u64seq(prb, ulseq) == pmsg.seq) { -+ console_prepend_replay(&pmsg); -+ } else { -+ /* -+ * Ensure this context is still the owner before trying to -+ * update @nbcon_prev_seq. Otherwise the value in @ulseq may -+ * not be from the previous owner and instead be some later -+ * value from the context that took over ownership. -+ */ -+ nbcon_state_read(con, &cur); -+ if (!nbcon_context_can_proceed(ctxt, &cur)) -+ return false; -+ -+ atomic_long_try_cmpxchg(&ACCESS_PRIVATE(con, nbcon_prev_seq), &ulseq, -+ __u64seq_to_ulseq(pmsg.seq)); -+ } -+ - if (!nbcon_context_exit_unsafe(ctxt)) - return false; - -@@ -1646,6 +1671,7 @@ bool nbcon_alloc(struct console *con) - - rcuwait_init(&con->rcuwait); - init_irq_work(&con->irq_work, nbcon_irq_work); -+ atomic_long_set(&ACCESS_PRIVATE(con, nbcon_prev_seq), -1UL); - nbcon_state_set(con, &state); - - /* ---- a/kernel/printk/printk.c -+++ b/kernel/printk/printk.c -@@ -2904,6 +2904,17 @@ void console_prepend_dropped(struct prin - } - - /* -+ * Prepend the message in @pmsg->pbufs->outbuf with a "replay message". -+ * @pmsg->outbuf_len is updated appropriately. -+ * -+ * @pmsg is the printk message to prepend. -+ */ -+void console_prepend_replay(struct printk_message *pmsg) -+{ -+ console_prepend_message(pmsg, "** replaying previous printk message **\n"); -+} -+ -+/* - * Read and format the specified record (or a later record if the specified - * record is not available). - * diff --git a/debian/patches-rt/0049-proc-consoles-Add-notation-to-c_start-c_stop.patch b/debian/patches-rt/0049-proc-consoles-Add-notation-to-c_start-c_stop.patch deleted file mode 100644 index 85816ec..0000000 --- a/debian/patches-rt/0049-proc-consoles-Add-notation-to-c_start-c_stop.patch +++ /dev/null @@ -1,37 +0,0 @@ -From: John Ogness -Date: Wed, 4 Sep 2024 14:11:31 +0206 -Subject: [PATCH 49/54] proc: consoles: Add notation to c_start/c_stop -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -fs/proc/consoles.c:78:13: warning: context imbalance in 'c_start' - - wrong count at exit -fs/proc/consoles.c:104:13: warning: context imbalance in 'c_stop' - - unexpected unlock - -Signed-off-by: John Ogness -Reviewed-by: Petr Mladek -Link: https://lore.kernel.org/r/20240904120536.115780-13-john.ogness@linutronix.de -Signed-off-by: Petr Mladek -Signed-off-by: Sebastian Andrzej Siewior ---- - fs/proc/consoles.c | 2 ++ - 1 file changed, 2 insertions(+) - ---- a/fs/proc/consoles.c -+++ b/fs/proc/consoles.c -@@ -68,6 +68,7 @@ static int show_console_dev(struct seq_f - } - - static void *c_start(struct seq_file *m, loff_t *pos) -+ __acquires(&console_mutex) - { - struct console *con; - loff_t off = 0; -@@ -94,6 +95,7 @@ static void *c_next(struct seq_file *m, - } - - static void c_stop(struct seq_file *m, void *v) -+ __releases(&console_mutex) - { - console_list_unlock(); - } diff --git a/debian/patches-rt/0050-proc-Add-nbcon-support-for-proc-consoles.patch b/debian/patches-rt/0050-proc-Add-nbcon-support-for-proc-consoles.patch deleted file mode 100644 index 9586921..0000000 --- a/debian/patches-rt/0050-proc-Add-nbcon-support-for-proc-consoles.patch +++ /dev/null @@ -1,42 +0,0 @@ -From: John Ogness -Date: Wed, 4 Sep 2024 14:11:32 +0206 -Subject: [PATCH 50/54] proc: Add nbcon support for /proc/consoles -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -Update /proc/consoles output to show 'W' if an nbcon console is -registered. Since the write_thread() callback is mandatory, it -enough just to check if it is an nbcon console. - -Also update /proc/consoles output to show 'N' if it is an -nbcon console. - -Signed-off-by: John Ogness -Reviewed-by: Petr Mladek -Link: https://lore.kernel.org/r/20240904120536.115780-14-john.ogness@linutronix.de -Signed-off-by: Petr Mladek -Signed-off-by: Sebastian Andrzej Siewior ---- - fs/proc/consoles.c | 5 +++-- - 1 file changed, 3 insertions(+), 2 deletions(-) - ---- a/fs/proc/consoles.c -+++ b/fs/proc/consoles.c -@@ -21,6 +21,7 @@ static int show_console_dev(struct seq_f - { CON_ENABLED, 'E' }, - { CON_CONSDEV, 'C' }, - { CON_BOOT, 'B' }, -+ { CON_NBCON, 'N' }, - { CON_PRINTBUFFER, 'p' }, - { CON_BRL, 'b' }, - { CON_ANYTIME, 'a' }, -@@ -58,8 +59,8 @@ static int show_console_dev(struct seq_f - seq_printf(m, "%s%d", con->name, con->index); - seq_pad(m, ' '); - seq_printf(m, "%c%c%c (%s)", con->read ? 'R' : '-', -- con->write ? 'W' : '-', con->unblank ? 'U' : '-', -- flags); -+ ((con->flags & CON_NBCON) || con->write) ? 'W' : '-', -+ con->unblank ? 'U' : '-', flags); - if (dev) - seq_printf(m, " %4d:%d", MAJOR(dev), MINOR(dev)); - diff --git a/debian/patches-rt/0051-tty-sysfs-Add-nbcon-support-for-active.patch b/debian/patches-rt/0051-tty-sysfs-Add-nbcon-support-for-active.patch deleted file mode 100644 index 7085bd1..0000000 --- a/debian/patches-rt/0051-tty-sysfs-Add-nbcon-support-for-active.patch +++ /dev/null @@ -1,27 +0,0 @@ -From: John Ogness -Date: Wed, 4 Sep 2024 14:11:33 +0206 -Subject: [PATCH 51/54] tty: sysfs: Add nbcon support for 'active' -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -Allow the 'active' attribute to list nbcon consoles. - -Signed-off-by: John Ogness -Reviewed-by: Petr Mladek -Link: https://lore.kernel.org/r/20240904120536.115780-15-john.ogness@linutronix.de -Signed-off-by: Petr Mladek -Signed-off-by: Sebastian Andrzej Siewior ---- - drivers/tty/tty_io.c | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/drivers/tty/tty_io.c -+++ b/drivers/tty/tty_io.c -@@ -3567,7 +3567,7 @@ static ssize_t show_cons_active(struct d - for_each_console(c) { - if (!c->device) - continue; -- if (!c->write) -+ if (!(c->flags & CON_NBCON) && !c->write) - continue; - if ((c->flags & CON_ENABLED) == 0) - continue; diff --git a/debian/patches-rt/0052-printk-Implement-legacy-printer-kthread-for-PREEMPT_.patch b/debian/patches-rt/0052-printk-Implement-legacy-printer-kthread-for-PREEMPT_.patch deleted file mode 100644 index 90f8983..0000000 --- a/debian/patches-rt/0052-printk-Implement-legacy-printer-kthread-for-PREEMPT_.patch +++ /dev/null @@ -1,324 +0,0 @@ -From: John Ogness -Date: Wed, 4 Sep 2024 14:11:34 +0206 -Subject: [PATCH 52/54] printk: Implement legacy printer kthread for PREEMPT_RT -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -The write() callback of legacy consoles usually makes use of -spinlocks. This is not permitted with PREEMPT_RT in atomic -contexts. - -For PREEMPT_RT, create a new kthread to handle printing of all -the legacy consoles (and nbcon consoles if boot consoles are -registered). This allows legacy consoles to work on PREEMPT_RT -without requiring modification. (However they will not have -the reliability properties guaranteed by nbcon atomic -consoles.) - -Use the existing printk_kthreads_check_locked() to start/stop -the legacy kthread as needed. - -Introduce the macro force_legacy_kthread() to query if the -forced threading of legacy consoles is in effect. Although -currently only enabled for PREEMPT_RT, this acts as a simple -mechanism for the future to allow other preemption models to -easily take advantage of the non-interference property provided -by the legacy kthread. - -When force_legacy_kthread() is true, the legacy kthread -fulfills the role of the console_flush_type @legacy_offload by -waking the legacy kthread instead of printing via the -console_lock in the irq_work. If the legacy kthread is not -yet available, no legacy printing takes place (unless in -panic). - -If for some reason the legacy kthread fails to create, any -legacy consoles are unregistered. With force_legacy_kthread(), -the legacy kthread is a critical component for legacy consoles. - -These changes only affect CONFIG_PREEMPT_RT. - -Signed-off-by: John Ogness -Reviewed-by: Petr Mladek -Link: https://lore.kernel.org/r/20240904120536.115780-16-john.ogness@linutronix.de -Signed-off-by: Petr Mladek -Signed-off-by: Sebastian Andrzej Siewior ---- - kernel/printk/internal.h | 16 ++++ - kernel/printk/printk.c | 157 +++++++++++++++++++++++++++++++++++++++----- - kernel/printk/printk_safe.c | 4 - - 3 files changed, 159 insertions(+), 18 deletions(-) - ---- a/kernel/printk/internal.h -+++ b/kernel/printk/internal.h -@@ -21,6 +21,19 @@ int devkmsg_sysctl_set_loglvl(const stru - (con->flags & CON_BOOT) ? "boot" : "", \ - con->name, con->index, ##__VA_ARGS__) - -+/* -+ * Identify if legacy printing is forced in a dedicated kthread. If -+ * true, all printing via console lock occurs within a dedicated -+ * legacy printer thread. The only exception is on panic, after the -+ * nbcon consoles have had their chance to print the panic messages -+ * first. -+ */ -+#ifdef CONFIG_PREEMPT_RT -+# define force_legacy_kthread() (true) -+#else -+# define force_legacy_kthread() (false) -+#endif -+ - #ifdef CONFIG_PRINTK - - #ifdef CONFIG_PRINTK_CALLER -@@ -173,6 +186,7 @@ static inline void nbcon_kthread_wake(st - #define printk_safe_exit_irqrestore(flags) local_irq_restore(flags) - - static inline bool printk_percpu_data_ready(void) { return false; } -+static inline void defer_console_output(void) { } - static inline bool is_printk_legacy_deferred(void) { return false; } - static inline u64 nbcon_seq_read(struct console *con) { return 0; } - static inline void nbcon_seq_force(struct console *con, u64 seq) { } -@@ -200,7 +214,7 @@ extern bool legacy_allow_panic_sync; - * @nbcon_atomic: Flush directly using nbcon_atomic() callback - * @nbcon_offload: Offload flush to printer thread - * @legacy_direct: Call the legacy loop in this context -- * @legacy_offload: Offload the legacy loop into IRQ -+ * @legacy_offload: Offload the legacy loop into IRQ or legacy thread - * - * Note that the legacy loop also flushes the nbcon consoles. - */ ---- a/kernel/printk/printk.c -+++ b/kernel/printk/printk.c -@@ -491,6 +491,7 @@ bool legacy_allow_panic_sync; - - #ifdef CONFIG_PRINTK - DECLARE_WAIT_QUEUE_HEAD(log_wait); -+static DECLARE_WAIT_QUEUE_HEAD(legacy_wait); - /* All 3 protected by @syslog_lock. */ - /* the next printk record to read by syslog(READ) or /proc/kmsg */ - static u64 syslog_seq; -@@ -2757,6 +2758,8 @@ void resume_console(void) - printk_get_console_flush_type(&ft); - if (ft.nbcon_offload) - nbcon_kthreads_wake(); -+ if (ft.legacy_offload) -+ defer_console_output(); - - pr_flush(1000, true); - } -@@ -3167,19 +3170,7 @@ static bool console_flush_all(bool do_co - return false; - } - --/** -- * console_unlock - unblock the console subsystem from printing -- * -- * Releases the console_lock which the caller holds to block printing of -- * the console subsystem. -- * -- * While the console_lock was held, console output may have been buffered -- * by printk(). If this is the case, console_unlock(); emits -- * the output prior to releasing the lock. -- * -- * console_unlock(); may be called from any context. -- */ --void console_unlock(void) -+static void __console_flush_and_unlock(void) - { - bool do_cond_resched; - bool handover; -@@ -3223,6 +3214,29 @@ void console_unlock(void) - */ - } while (prb_read_valid(prb, next_seq, NULL) && console_trylock()); - } -+ -+/** -+ * console_unlock - unblock the legacy console subsystem from printing -+ * -+ * Releases the console_lock which the caller holds to block printing of -+ * the legacy console subsystem. -+ * -+ * While the console_lock was held, console output may have been buffered -+ * by printk(). If this is the case, console_unlock() emits the output on -+ * legacy consoles prior to releasing the lock. -+ * -+ * console_unlock(); may be called from any context. -+ */ -+void console_unlock(void) -+{ -+ struct console_flush_type ft; -+ -+ printk_get_console_flush_type(&ft); -+ if (ft.legacy_direct) -+ __console_flush_and_unlock(); -+ else -+ __console_unlock(); -+} - EXPORT_SYMBOL(console_unlock); - - /** -@@ -3450,6 +3464,8 @@ void console_start(struct console *conso - printk_get_console_flush_type(&ft); - if (is_nbcon && ft.nbcon_offload) - nbcon_kthread_wake(console); -+ else if (ft.legacy_offload) -+ defer_console_output(); - - __pr_flush(console, 1000, true); - } -@@ -3461,6 +3477,88 @@ static int unregister_console_locked(str - /* True when system boot is far enough to create printer threads. */ - static bool printk_kthreads_ready __ro_after_init; - -+static struct task_struct *printk_legacy_kthread; -+ -+static bool legacy_kthread_should_wakeup(void) -+{ -+ struct console_flush_type ft; -+ struct console *con; -+ bool ret = false; -+ int cookie; -+ -+ if (kthread_should_stop()) -+ return true; -+ -+ printk_get_console_flush_type(&ft); -+ -+ cookie = console_srcu_read_lock(); -+ for_each_console_srcu(con) { -+ short flags = console_srcu_read_flags(con); -+ u64 printk_seq; -+ -+ /* -+ * The legacy printer thread is only responsible for nbcon -+ * consoles when the nbcon consoles cannot print via their -+ * atomic or threaded flushing. -+ */ -+ if ((flags & CON_NBCON) && (ft.nbcon_atomic || ft.nbcon_offload)) -+ continue; -+ -+ if (!console_is_usable(con, flags, false)) -+ continue; -+ -+ if (flags & CON_NBCON) { -+ printk_seq = nbcon_seq_read(con); -+ } else { -+ /* -+ * It is safe to read @seq because only this -+ * thread context updates @seq. -+ */ -+ printk_seq = con->seq; -+ } -+ -+ if (prb_read_valid(prb, printk_seq, NULL)) { -+ ret = true; -+ break; -+ } -+ } -+ console_srcu_read_unlock(cookie); -+ -+ return ret; -+} -+ -+static int legacy_kthread_func(void *unused) -+{ -+ for (;;) { -+ wait_event_interruptible(legacy_wait, legacy_kthread_should_wakeup()); -+ -+ if (kthread_should_stop()) -+ break; -+ -+ console_lock(); -+ __console_flush_and_unlock(); -+ } -+ -+ return 0; -+} -+ -+static bool legacy_kthread_create(void) -+{ -+ struct task_struct *kt; -+ -+ lockdep_assert_console_list_lock_held(); -+ -+ kt = kthread_run(legacy_kthread_func, NULL, "pr/legacy"); -+ if (WARN_ON(IS_ERR(kt))) { -+ pr_err("failed to start legacy printing thread\n"); -+ return false; -+ } -+ -+ printk_legacy_kthread = kt; -+ -+ return true; -+} -+ - /** - * printk_kthreads_shutdown - shutdown all threaded printers - * -@@ -3510,6 +3608,27 @@ static void printk_kthreads_check_locked - if (!printk_kthreads_ready) - return; - -+ if (have_legacy_console || have_boot_console) { -+ if (!printk_legacy_kthread && -+ force_legacy_kthread() && -+ !legacy_kthread_create()) { -+ /* -+ * All legacy consoles must be unregistered. If there -+ * are any nbcon consoles, they will set up their own -+ * kthread. -+ */ -+ hlist_for_each_entry_safe(con, tmp, &console_list, node) { -+ if (con->flags & CON_NBCON) -+ continue; -+ -+ unregister_console_locked(con); -+ } -+ } -+ } else if (printk_legacy_kthread) { -+ kthread_stop(printk_legacy_kthread); -+ printk_legacy_kthread = NULL; -+ } -+ - /* - * Printer threads cannot be started as long as any boot console is - * registered because there is no way to synchronize the hardware -@@ -4286,9 +4405,13 @@ static void wake_up_klogd_work_func(stru - int pending = this_cpu_xchg(printk_pending, 0); - - if (pending & PRINTK_PENDING_OUTPUT) { -- /* If trylock fails, someone else is doing the printing */ -- if (console_trylock()) -- console_unlock(); -+ if (force_legacy_kthread()) { -+ if (printk_legacy_kthread) -+ wake_up_interruptible(&legacy_wait); -+ } else { -+ if (console_trylock()) -+ console_unlock(); -+ } - } - - if (pending & PRINTK_PENDING_WAKEUP) -@@ -4703,6 +4826,8 @@ void console_try_replay_all(void) - nbcon_atomic_flush_pending(); - if (ft.nbcon_offload) - nbcon_kthreads_wake(); -+ if (ft.legacy_offload) -+ defer_console_output(); - /* Consoles are flushed as part of console_unlock(). */ - console_unlock(); - } ---- a/kernel/printk/printk_safe.c -+++ b/kernel/printk/printk_safe.c -@@ -44,7 +44,9 @@ bool is_printk_legacy_deferred(void) - * The per-CPU variable @printk_context can be read safely in any - * context. CPU migration is always disabled when set. - */ -- return (this_cpu_read(printk_context) || in_nmi()); -+ return (force_legacy_kthread() || -+ this_cpu_read(printk_context) || -+ in_nmi()); - } - - asmlinkage int vprintk(const char *fmt, va_list args) diff --git a/debian/patches-rt/0053-printk-nbcon-Assign-nice-20-for-printing-threads.patch b/debian/patches-rt/0053-printk-nbcon-Assign-nice-20-for-printing-threads.patch deleted file mode 100644 index d13fccb..0000000 --- a/debian/patches-rt/0053-printk-nbcon-Assign-nice-20-for-printing-threads.patch +++ /dev/null @@ -1,48 +0,0 @@ -From: John Ogness -Date: Wed, 4 Sep 2024 14:11:35 +0206 -Subject: [PATCH 53/54] printk: nbcon: Assign nice -20 for printing threads -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -It is important that console printing threads are scheduled -shortly after a printk call and with generous runtime budgets. - -Signed-off-by: John Ogness -Reviewed-by: Petr Mladek -Link: https://lore.kernel.org/r/20240904120536.115780-17-john.ogness@linutronix.de -Signed-off-by: Petr Mladek -Signed-off-by: Sebastian Andrzej Siewior ---- - kernel/printk/nbcon.c | 6 ++++++ - kernel/printk/printk.c | 6 ++++++ - 2 files changed, 12 insertions(+) - ---- a/kernel/printk/nbcon.c -+++ b/kernel/printk/nbcon.c -@@ -1321,6 +1321,12 @@ bool nbcon_kthread_create(struct console - - con->kthread = kt; - -+ /* -+ * It is important that console printing threads are scheduled -+ * shortly after a printk call and with generous runtime budgets. -+ */ -+ sched_set_normal(con->kthread, -20); -+ - return true; - } - ---- a/kernel/printk/printk.c -+++ b/kernel/printk/printk.c -@@ -3556,6 +3556,12 @@ static bool legacy_kthread_create(void) - - printk_legacy_kthread = kt; - -+ /* -+ * It is important that console printing threads are scheduled -+ * shortly after a printk call and with generous runtime budgets. -+ */ -+ sched_set_normal(printk_legacy_kthread, -20); -+ - return true; - } - diff --git a/debian/patches-rt/0053-serial-8250-Switch-to-nbcon-console.patch b/debian/patches-rt/0053-serial-8250-Switch-to-nbcon-console.patch deleted file mode 100644 index 87716b2..0000000 --- a/debian/patches-rt/0053-serial-8250-Switch-to-nbcon-console.patch +++ /dev/null @@ -1,334 +0,0 @@ -From: John Ogness -Date: Wed, 13 Sep 2023 15:30:36 +0000 -Subject: [PATCH 53/54] serial: 8250: Switch to nbcon console -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -Implement the necessary callbacks to switch the 8250 console driver -to perform as an nbcon console. - -Add implementations for the nbcon console callbacks (write_atomic, -write_thread, device_lock, device_unlock) and add CON_NBCON to the -initial flags. - -The legacy code is kept in order to easily switch back to legacy mode -by defining CONFIG_SERIAL_8250_LEGACY_CONSOLE. - -Signed-off-by: John Ogness -Signed-off-by: Sebastian Andrzej Siewior ---- - drivers/tty/serial/8250/8250_core.c | 42 +++++++++ - drivers/tty/serial/8250/8250_port.c | 154 +++++++++++++++++++++++++++++++++++- - include/linux/serial_8250.h | 6 + - 3 files changed, 199 insertions(+), 3 deletions(-) - ---- a/drivers/tty/serial/8250/8250_core.c -+++ b/drivers/tty/serial/8250/8250_core.c -@@ -388,6 +388,7 @@ void __init serial8250_register_ports(st - - #ifdef CONFIG_SERIAL_8250_CONSOLE - -+#ifdef CONFIG_SERIAL_8250_LEGACY_CONSOLE - static void univ8250_console_write(struct console *co, const char *s, - unsigned int count) - { -@@ -395,6 +396,37 @@ static void univ8250_console_write(struc - - serial8250_console_write(up, s, count); - } -+#else -+static void univ8250_console_write_atomic(struct console *co, -+ struct nbcon_write_context *wctxt) -+{ -+ struct uart_8250_port *up = &serial8250_ports[co->index]; -+ -+ serial8250_console_write_atomic(up, wctxt); -+} -+ -+static void univ8250_console_write_thread(struct console *co, -+ struct nbcon_write_context *wctxt) -+{ -+ struct uart_8250_port *up = &serial8250_ports[co->index]; -+ -+ serial8250_console_write_thread(up, wctxt); -+} -+ -+static void univ8250_console_device_lock(struct console *con, unsigned long *flags) -+{ -+ struct uart_port *up = &serial8250_ports[con->index].port; -+ -+ __uart_port_lock_irqsave(up, flags); -+} -+ -+static void univ8250_console_device_unlock(struct console *con, unsigned long flags) -+{ -+ struct uart_port *up = &serial8250_ports[con->index].port; -+ -+ __uart_port_unlock_irqrestore(up, flags); -+} -+#endif /* CONFIG_SERIAL_8250_LEGACY_CONSOLE */ - - static int univ8250_console_setup(struct console *co, char *options) - { -@@ -494,12 +526,20 @@ static int univ8250_console_match(struct - - static struct console univ8250_console = { - .name = "ttyS", -+#ifdef CONFIG_SERIAL_8250_LEGACY_CONSOLE - .write = univ8250_console_write, -+ .flags = CON_PRINTBUFFER | CON_ANYTIME, -+#else -+ .write_atomic = univ8250_console_write_atomic, -+ .write_thread = univ8250_console_write_thread, -+ .device_lock = univ8250_console_device_lock, -+ .device_unlock = univ8250_console_device_unlock, -+ .flags = CON_PRINTBUFFER | CON_ANYTIME | CON_NBCON, -+#endif - .device = uart_console_device, - .setup = univ8250_console_setup, - .exit = univ8250_console_exit, - .match = univ8250_console_match, -- .flags = CON_PRINTBUFFER | CON_ANYTIME, - .index = -1, - .data = &serial8250_reg, - }; ---- a/drivers/tty/serial/8250/8250_port.c -+++ b/drivers/tty/serial/8250/8250_port.c -@@ -546,6 +546,13 @@ static int serial8250_em485_init(struct - if (!p->em485) - return -ENOMEM; - -+#ifndef CONFIG_SERIAL_8250_LEGACY_CONSOLE -+ if (uart_console(&p->port)) { -+ dev_warn(p->port.dev, "no atomic printing for rs485 consoles\n"); -+ p->port.cons->write_atomic = NULL; -+ } -+#endif -+ - hrtimer_init(&p->em485->stop_tx_timer, CLOCK_MONOTONIC, - HRTIMER_MODE_REL); - hrtimer_init(&p->em485->start_tx_timer, CLOCK_MONOTONIC, -@@ -691,7 +698,11 @@ static void serial8250_set_sleep(struct - serial8250_rpm_put(p); - } - --static void serial8250_clear_IER(struct uart_8250_port *up) -+/* -+ * Only to be used by write_atomic() and the legacy write(), which do not -+ * require port lock. -+ */ -+static void __serial8250_clear_IER(struct uart_8250_port *up) - { - if (up->capabilities & UART_CAP_UUE) - serial_out(up, UART_IER, UART_IER_UUE); -@@ -699,6 +710,11 @@ static void serial8250_clear_IER(struct - serial_out(up, UART_IER, 0); - } - -+static inline void serial8250_clear_IER(struct uart_8250_port *up) -+{ -+ __serial8250_clear_IER(up); -+} -+ - #ifdef CONFIG_SERIAL_8250_RSA - /* - * Attempts to turn on the RSA FIFO. Returns zero on failure. -@@ -3269,6 +3285,11 @@ static void serial8250_console_putchar(s - - wait_for_xmitr(up, UART_LSR_THRE); - serial_port_out(port, UART_TX, ch); -+ -+ if (ch == '\n') -+ up->console_newline_needed = false; -+ else -+ up->console_newline_needed = true; - } - - /* -@@ -3297,6 +3318,7 @@ static void serial8250_console_restore(s - serial8250_out_MCR(up, up->mcr | UART_MCR_DTR | UART_MCR_RTS); - } - -+#ifdef CONFIG_SERIAL_8250_LEGACY_CONSOLE - /* - * Print a string to the serial port using the device FIFO - * -@@ -3355,7 +3377,7 @@ void serial8250_console_write(struct uar - * First save the IER then disable the interrupts - */ - ier = serial_port_in(port, UART_IER); -- serial8250_clear_IER(up); -+ __serial8250_clear_IER(up); - - /* check scratch reg to see if port powered off during system sleep */ - if (up->canary && (up->canary != serial_port_in(port, UART_SCR))) { -@@ -3421,6 +3443,131 @@ void serial8250_console_write(struct uar - if (locked) - uart_port_unlock_irqrestore(port, flags); - } -+#else -+void serial8250_console_write_thread(struct uart_8250_port *up, -+ struct nbcon_write_context *wctxt) -+{ -+ struct uart_8250_em485 *em485 = up->em485; -+ struct uart_port *port = &up->port; -+ unsigned int ier; -+ -+ touch_nmi_watchdog(); -+ -+ if (!nbcon_enter_unsafe(wctxt)) -+ return; -+ -+ /* First save IER then disable the interrupts. */ -+ ier = serial_port_in(port, UART_IER); -+ serial8250_clear_IER(up); -+ -+ /* Check scratch reg if port powered off during system sleep. */ -+ if (up->canary && (up->canary != serial_port_in(port, UART_SCR))) { -+ serial8250_console_restore(up); -+ up->canary = 0; -+ } -+ -+ if (em485) { -+ if (em485->tx_stopped) -+ up->rs485_start_tx(up); -+ mdelay(port->rs485.delay_rts_before_send); -+ } -+ -+ if (nbcon_exit_unsafe(wctxt)) { -+ int len = READ_ONCE(wctxt->len); -+ int i; -+ -+ /* -+ * Write out the message. Toggle unsafe for each byte in order -+ * to give another (higher priority) context the opportunity -+ * for a friendly takeover. If such a takeover occurs, this -+ * context must reacquire ownership in order to perform final -+ * actions (such as re-enabling the interrupts). -+ * -+ * IMPORTANT: wctxt->outbuf and wctxt->len are no longer valid -+ * after a reacquire so writing the message must be -+ * aborted. -+ */ -+ for (i = 0; i < len; i++) { -+ if (!nbcon_enter_unsafe(wctxt)) { -+ nbcon_reacquire_nobuf(wctxt); -+ break; -+ } -+ -+ uart_console_write(port, wctxt->outbuf + i, 1, serial8250_console_putchar); -+ -+ if (!nbcon_exit_unsafe(wctxt)) { -+ nbcon_reacquire_nobuf(wctxt); -+ break; -+ } -+ } -+ } else { -+ nbcon_reacquire_nobuf(wctxt); -+ } -+ -+ while (!nbcon_enter_unsafe(wctxt)) -+ nbcon_reacquire_nobuf(wctxt); -+ -+ /* Finally, wait for transmitter to become empty and restore IER. */ -+ wait_for_xmitr(up, UART_LSR_BOTH_EMPTY); -+ if (em485) { -+ mdelay(port->rs485.delay_rts_after_send); -+ if (em485->tx_stopped) -+ up->rs485_stop_tx(up); -+ } -+ serial_port_out(port, UART_IER, ier); -+ -+ /* -+ * The receive handling will happen properly because the receive ready -+ * bit will still be set; it is not cleared on read. However, modem -+ * control will not, we must call it if we have saved something in the -+ * saved flags while processing with interrupts off. -+ */ -+ if (up->msr_saved_flags) -+ serial8250_modem_status(up); -+ -+ nbcon_exit_unsafe(wctxt); -+} -+ -+void serial8250_console_write_atomic(struct uart_8250_port *up, -+ struct nbcon_write_context *wctxt) -+{ -+ struct uart_port *port = &up->port; -+ unsigned int ier; -+ -+ /* Atomic console not supported for rs485 mode. */ -+ if (WARN_ON_ONCE(up->em485)) -+ return; -+ -+ touch_nmi_watchdog(); -+ -+ if (!nbcon_enter_unsafe(wctxt)) -+ return; -+ -+ /* -+ * First save IER then disable the interrupts. The special variant to -+ * clear IER is used because atomic printing may occur without holding -+ * the port lock. -+ */ -+ ier = serial_port_in(port, UART_IER); -+ __serial8250_clear_IER(up); -+ -+ /* Check scratch reg if port powered off during system sleep. */ -+ if (up->canary && (up->canary != serial_port_in(port, UART_SCR))) { -+ serial8250_console_restore(up); -+ up->canary = 0; -+ } -+ -+ if (up->console_newline_needed) -+ uart_console_write(port, "\n", 1, serial8250_console_putchar); -+ uart_console_write(port, wctxt->outbuf, wctxt->len, serial8250_console_putchar); -+ -+ /* Finally, wait for transmitter to become empty and restore IER. */ -+ wait_for_xmitr(up, UART_LSR_BOTH_EMPTY); -+ serial_port_out(port, UART_IER, ier); -+ -+ nbcon_exit_unsafe(wctxt); -+} -+#endif /* CONFIG_SERIAL_8250_LEGACY_CONSOLE */ - - static unsigned int probe_baud(struct uart_port *port) - { -@@ -3439,6 +3586,7 @@ static unsigned int probe_baud(struct ua - - int serial8250_console_setup(struct uart_port *port, char *options, bool probe) - { -+ struct uart_8250_port *up = up_to_u8250p(port); - int baud = 9600; - int bits = 8; - int parity = 'n'; -@@ -3448,6 +3596,8 @@ int serial8250_console_setup(struct uart - if (!port->iobase && !port->membase) - return -ENODEV; - -+ up->console_newline_needed = false; -+ - if (options) - uart_parse_options(options, &baud, &parity, &bits, &flow); - else if (probe) ---- a/include/linux/serial_8250.h -+++ b/include/linux/serial_8250.h -@@ -153,6 +153,8 @@ struct uart_8250_port { - #define MSR_SAVE_FLAGS UART_MSR_ANY_DELTA - unsigned char msr_saved_flags; - -+ bool console_newline_needed; -+ - struct uart_8250_dma *dma; - const struct uart_8250_ops *ops; - -@@ -204,6 +206,10 @@ void serial8250_init_port(struct uart_82 - void serial8250_set_defaults(struct uart_8250_port *up); - void serial8250_console_write(struct uart_8250_port *up, const char *s, - unsigned int count); -+void serial8250_console_write_atomic(struct uart_8250_port *up, -+ struct nbcon_write_context *wctxt); -+void serial8250_console_write_thread(struct uart_8250_port *up, -+ struct nbcon_write_context *wctxt); - int serial8250_console_setup(struct uart_port *port, char *options, bool probe); - int serial8250_console_exit(struct uart_port *port); - diff --git a/debian/patches-rt/0054-printk-Avoid-false-positive-lockdep-report-for-legac.patch b/debian/patches-rt/0054-printk-Avoid-false-positive-lockdep-report-for-legac.patch deleted file mode 100644 index 3db7640..0000000 --- a/debian/patches-rt/0054-printk-Avoid-false-positive-lockdep-report-for-legac.patch +++ /dev/null @@ -1,138 +0,0 @@ -From: John Ogness -Date: Wed, 4 Sep 2024 14:11:36 +0206 -Subject: [PATCH 54/54] printk: Avoid false positive lockdep report for legacy - printing -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -Legacy console printing from printk() caller context may invoke -the console driver from atomic context. This leads to a lockdep -splat because the console driver will acquire a sleeping lock -and the caller may already hold a spinning lock. This is noticed -by lockdep on !PREEMPT_RT configurations because it will lead to -a problem on PREEMPT_RT. - -However, on PREEMPT_RT the printing path from atomic context is -always avoided and the console driver is always invoked from a -dedicated thread. Thus the lockdep splat on !PREEMPT_RT is a -false positive. - -For !PREEMPT_RT override the lock-context before invoking the -console driver to avoid the false positive. - -Do not override the lock-context for PREEMPT_RT in order to -allow lockdep to catch any real locking context issues related -to the write callback usage. - -Signed-off-by: John Ogness -Reviewed-by: Petr Mladek -Link: https://lore.kernel.org/r/20240904120536.115780-18-john.ogness@linutronix.de -Signed-off-by: Petr Mladek -Signed-off-by: Sebastian Andrzej Siewior ---- - kernel/printk/printk.c | 83 +++++++++++++++++++++++++++++++++++++------------ - 1 file changed, 63 insertions(+), 20 deletions(-) - ---- a/kernel/printk/printk.c -+++ b/kernel/printk/printk.c -@@ -2983,6 +2983,34 @@ bool printk_get_next_message(struct prin - } - - /* -+ * Legacy console printing from printk() caller context does not respect -+ * raw_spinlock/spinlock nesting. For !PREEMPT_RT the lockdep warning is a -+ * false positive. For PREEMPT_RT the false positive condition does not -+ * occur. -+ * -+ * This map is used to temporarily establish LD_WAIT_SLEEP context for the -+ * console write() callback when legacy printing to avoid false positive -+ * lockdep complaints, thus allowing lockdep to continue to function for -+ * real issues. -+ */ -+#ifdef CONFIG_PREEMPT_RT -+static inline void printk_legacy_allow_spinlock_enter(void) { } -+static inline void printk_legacy_allow_spinlock_exit(void) { } -+#else -+static DEFINE_WAIT_OVERRIDE_MAP(printk_legacy_map, LD_WAIT_SLEEP); -+ -+static inline void printk_legacy_allow_spinlock_enter(void) -+{ -+ lock_map_acquire_try(&printk_legacy_map); -+} -+ -+static inline void printk_legacy_allow_spinlock_exit(void) -+{ -+ lock_map_release(&printk_legacy_map); -+} -+#endif /* CONFIG_PREEMPT_RT */ -+ -+/* - * Used as the printk buffers for non-panic, serialized console printing. - * This is for legacy (!CON_NBCON) as well as all boot (CON_BOOT) consoles. - * Its usage requires the console_lock held. -@@ -3031,31 +3059,46 @@ static bool console_emit_next_record(str - con->dropped = 0; - } - -- /* -- * While actively printing out messages, if another printk() -- * were to occur on another CPU, it may wait for this one to -- * finish. This task can not be preempted if there is a -- * waiter waiting to take over. -- * -- * Interrupts are disabled because the hand over to a waiter -- * must not be interrupted until the hand over is completed -- * (@console_waiter is cleared). -- */ -- printk_safe_enter_irqsave(flags); -- console_lock_spinning_enable(); -+ /* Write everything out to the hardware. */ - -- /* Do not trace print latency. */ -- stop_critical_timings(); -+ if (force_legacy_kthread() && !panic_in_progress()) { -+ /* -+ * With forced threading this function is in a task context -+ * (either legacy kthread or get_init_console_seq()). There -+ * is no need for concern about printk reentrance, handovers, -+ * or lockdep complaints. -+ */ - -- /* Write everything out to the hardware. */ -- con->write(con, outbuf, pmsg.outbuf_len); -+ con->write(con, outbuf, pmsg.outbuf_len); -+ con->seq = pmsg.seq + 1; -+ } else { -+ /* -+ * While actively printing out messages, if another printk() -+ * were to occur on another CPU, it may wait for this one to -+ * finish. This task can not be preempted if there is a -+ * waiter waiting to take over. -+ * -+ * Interrupts are disabled because the hand over to a waiter -+ * must not be interrupted until the hand over is completed -+ * (@console_waiter is cleared). -+ */ -+ printk_safe_enter_irqsave(flags); -+ console_lock_spinning_enable(); -+ -+ /* Do not trace print latency. */ -+ stop_critical_timings(); -+ -+ printk_legacy_allow_spinlock_enter(); -+ con->write(con, outbuf, pmsg.outbuf_len); -+ printk_legacy_allow_spinlock_exit(); - -- start_critical_timings(); -+ start_critical_timings(); - -- con->seq = pmsg.seq + 1; -+ con->seq = pmsg.seq + 1; - -- *handover = console_lock_spinning_disable_and_check(cookie); -- printk_safe_exit_irqrestore(flags); -+ *handover = console_lock_spinning_disable_and_check(cookie); -+ printk_safe_exit_irqrestore(flags); -+ } - skip: - return true; - } diff --git a/debian/patches-rt/0054-serial-8250-Revert-drop-lockdep-annotation-from-seri.patch b/debian/patches-rt/0054-serial-8250-Revert-drop-lockdep-annotation-from-seri.patch deleted file mode 100644 index 368e114..0000000 --- a/debian/patches-rt/0054-serial-8250-Revert-drop-lockdep-annotation-from-seri.patch +++ /dev/null @@ -1,29 +0,0 @@ -From: John Ogness -Date: Mon, 2 Oct 2023 15:30:43 +0000 -Subject: [PATCH 54/54] serial: 8250: Revert "drop lockdep annotation from - serial8250_clear_IER()" -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -The 8250 driver no longer depends on @oops_in_progress and -will no longer violate the port->lock locking constraints. - -This reverts commit 3d9e6f556e235ddcdc9f73600fdd46fe1736b090. - -Signed-off-by: John Ogness -Signed-off-by: Sebastian Andrzej Siewior ---- - drivers/tty/serial/8250/8250_port.c | 3 +++ - 1 file changed, 3 insertions(+) - ---- a/drivers/tty/serial/8250/8250_port.c -+++ b/drivers/tty/serial/8250/8250_port.c -@@ -712,6 +712,9 @@ static void __serial8250_clear_IER(struc - - static inline void serial8250_clear_IER(struct uart_8250_port *up) - { -+ /* Port locked to synchronize UART_IER access against the console. */ -+ lockdep_assert_held_once(&up->port.lock); -+ - __serial8250_clear_IER(up); - } - diff --git a/debian/patches-rt/ARM64__Allow_to_enable_RT.patch b/debian/patches-rt/ARM64__Allow_to_enable_RT.patch deleted file mode 100644 index ef8659f..0000000 --- a/debian/patches-rt/ARM64__Allow_to_enable_RT.patch +++ /dev/null @@ -1,27 +0,0 @@ -Subject: ARM64: Allow to enable RT -From: Sebastian Andrzej Siewior -Date: Fri Oct 11 13:14:35 2019 +0200 -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -From: Sebastian Andrzej Siewior - -Allow to select RT. - -Signed-off-by: Sebastian Andrzej Siewior -Signed-off-by: Thomas Gleixner - - ---- - arch/arm64/Kconfig | 1 + - 1 file changed, 1 insertion(+) ---- ---- a/arch/arm64/Kconfig -+++ b/arch/arm64/Kconfig -@@ -99,6 +99,7 @@ config ARM64 - select ARCH_SUPPORTS_NUMA_BALANCING - select ARCH_SUPPORTS_PAGE_TABLE_CHECK - select ARCH_SUPPORTS_PER_VMA_LOCK -+ select ARCH_SUPPORTS_RT - select ARCH_WANT_BATCHED_UNMAP_TLB_FLUSH - select ARCH_WANT_COMPAT_IPC_PARSE_VERSION if COMPAT - select ARCH_WANT_DEFAULT_BPF_JIT diff --git a/debian/patches-rt/ARM__Allow_to_enable_RT.patch b/debian/patches-rt/ARM__Allow_to_enable_RT.patch deleted file mode 100644 index 669c331..0000000 --- a/debian/patches-rt/ARM__Allow_to_enable_RT.patch +++ /dev/null @@ -1,35 +0,0 @@ -Subject: ARM: Allow to enable RT -From: Sebastian Andrzej Siewior -Date: Fri Oct 11 13:14:29 2019 +0200 -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -From: Sebastian Andrzej Siewior - -Allow to select RT. - -Signed-off-by: Sebastian Andrzej Siewior -Signed-off-by: Thomas Gleixner - - ---- - arch/arm/Kconfig | 2 ++ - 1 file changed, 2 insertions(+) ---- ---- a/arch/arm/Kconfig -+++ b/arch/arm/Kconfig -@@ -39,6 +39,7 @@ config ARM - select ARCH_SUPPORTS_CFI_CLANG - select ARCH_SUPPORTS_HUGETLBFS if ARM_LPAE - select ARCH_SUPPORTS_PER_VMA_LOCK -+ select ARCH_SUPPORTS_RT if HAVE_POSIX_CPU_TIMERS_TASK_WORK - select ARCH_USE_BUILTIN_BSWAP - select ARCH_USE_CMPXCHG_LOCKREF - select ARCH_USE_MEMTEST -@@ -126,6 +127,7 @@ config ARM - select HAVE_PERF_EVENTS - select HAVE_PERF_REGS - select HAVE_PERF_USER_STACK_DUMP -+ select HAVE_POSIX_CPU_TIMERS_TASK_WORK if !KVM - select MMU_GATHER_RCU_TABLE_FREE if SMP && ARM_LPAE - select HAVE_REGS_AND_STACK_ACCESS_API - select HAVE_RSEQ diff --git a/debian/patches-rt/ARM__enable_irq_in_translation_section_permission_fault_handlers.patch b/debian/patches-rt/ARM__enable_irq_in_translation_section_permission_fault_handlers.patch deleted file mode 100644 index 0d51d54..0000000 --- a/debian/patches-rt/ARM__enable_irq_in_translation_section_permission_fault_handlers.patch +++ /dev/null @@ -1,91 +0,0 @@ -Subject: ARM: enable irq in translation/section permission fault handlers -From: Yadi.hu -Date: Wed Dec 10 10:32:09 2014 +0800 -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -From: Yadi.hu - -Probably happens on all ARM, with -CONFIG_PREEMPT_RT -CONFIG_DEBUG_ATOMIC_SLEEP - -This simple program.... - -int main() { - *((char*)0xc0001000) = 0; -}; - -[ 512.742724] BUG: sleeping function called from invalid context at kernel/rtmutex.c:658 -[ 512.743000] in_atomic(): 0, irqs_disabled(): 128, pid: 994, name: a -[ 512.743217] INFO: lockdep is turned off. -[ 512.743360] irq event stamp: 0 -[ 512.743482] hardirqs last enabled at (0): [< (null)>] (null) -[ 512.743714] hardirqs last disabled at (0): [] copy_process+0x3b0/0x11c0 -[ 512.744013] softirqs last enabled at (0): [] copy_process+0x3b0/0x11c0 -[ 512.744303] softirqs last disabled at (0): [< (null)>] (null) -[ 512.744631] [] (unwind_backtrace+0x0/0x104) -[ 512.745001] [] (dump_stack+0x20/0x24) -[ 512.745355] [] (__might_sleep+0x1dc/0x1e0) -[ 512.745717] [] (rt_spin_lock+0x34/0x6c) -[ 512.746073] [] (do_force_sig_info+0x34/0xf0) -[ 512.746457] [] (force_sig_info+0x18/0x1c) -[ 512.746829] [] (__do_user_fault+0x9c/0xd8) -[ 512.747185] [] (do_bad_area+0x7c/0x94) -[ 512.747536] [] (do_sect_fault+0x40/0x48) -[ 512.747898] [] (do_DataAbort+0x40/0xa0) -[ 512.748181] Exception stack(0xecaa1fb0 to 0xecaa1ff8) - -Oxc0000000 belongs to kernel address space, user task can not be -allowed to access it. For above condition, correct result is that -test case should receive a “segment fault” and exits but not stacks. - -the root cause is commit 02fe2845d6a8 ("avoid enabling interrupts in -prefetch/data abort handlers"),it deletes irq enable block in Data -abort assemble code and move them into page/breakpiont/alignment fault -handlers instead. But author does not enable irq in translation/section -permission fault handlers. ARM disables irq when it enters exception/ -interrupt mode, if kernel doesn't enable irq, it would be still disabled -during translation/section permission fault. - -We see the above splat because do_force_sig_info is still called with -IRQs off, and that code eventually does a: - - spin_lock_irqsave(&t->sighand->siglock, flags); - -As this is architecture independent code, and we've not seen any other -need for other arch to have the siglock converted to raw lock, we can -conclude that we should enable irq for ARM translation/section -permission exception. - - -Signed-off-by: Yadi.hu -Signed-off-by: Sebastian Andrzej Siewior -Signed-off-by: Thomas Gleixner - - ---- - arch/arm/mm/fault.c | 6 ++++++ - 1 file changed, 6 insertions(+) ---- ---- a/arch/arm/mm/fault.c -+++ b/arch/arm/mm/fault.c -@@ -474,6 +474,9 @@ do_translation_fault(unsigned long addr, - if (addr < TASK_SIZE) - return do_page_fault(addr, fsr, regs); - -+ if (interrupts_enabled(regs)) -+ local_irq_enable(); -+ - if (user_mode(regs)) - goto bad_area; - -@@ -544,6 +547,9 @@ do_translation_fault(unsigned long addr, - static int - do_sect_fault(unsigned long addr, unsigned int fsr, struct pt_regs *regs) - { -+ if (interrupts_enabled(regs)) -+ local_irq_enable(); -+ - do_bad_area(addr, fsr, regs); - return 0; - } diff --git a/debian/patches-rt/Add_localversion_for_-RT_release.patch b/debian/patches-rt/Add_localversion_for_-RT_release.patch deleted file mode 100644 index 7b37c63..0000000 --- a/debian/patches-rt/Add_localversion_for_-RT_release.patch +++ /dev/null @@ -1,19 +0,0 @@ -Subject: Add localversion for -RT release -From: Thomas Gleixner -Date: Fri Jul 8 20:25:16 2011 +0200 -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -From: Thomas Gleixner - -Signed-off-by: Thomas Gleixner - - ---- - localversion-rt | 1 + - 1 file changed, 1 insertion(+) - create mode 100644 localversion-rt ---- ---- /dev/null -+++ b/localversion-rt -@@ -0,0 +1 @@ -+-rt7 diff --git a/debian/patches-rt/POWERPC__Allow_to_enable_RT.patch b/debian/patches-rt/POWERPC__Allow_to_enable_RT.patch deleted file mode 100644 index 07408dc..0000000 --- a/debian/patches-rt/POWERPC__Allow_to_enable_RT.patch +++ /dev/null @@ -1,35 +0,0 @@ -Subject: POWERPC: Allow to enable RT -From: Sebastian Andrzej Siewior -Date: Fri Oct 11 13:14:41 2019 +0200 -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -From: Sebastian Andrzej Siewior - -Allow to select RT. - -Signed-off-by: Sebastian Andrzej Siewior -Signed-off-by: Thomas Gleixner - - ---- - arch/powerpc/Kconfig | 2 ++ - 1 file changed, 2 insertions(+) ---- ---- a/arch/powerpc/Kconfig -+++ b/arch/powerpc/Kconfig -@@ -167,6 +167,7 @@ config PPC - select ARCH_STACKWALK - select ARCH_SUPPORTS_ATOMIC_RMW - select ARCH_SUPPORTS_DEBUG_PAGEALLOC if PPC_BOOK3S || PPC_8xx -+ select ARCH_SUPPORTS_RT if HAVE_POSIX_CPU_TIMERS_TASK_WORK - select ARCH_USE_BUILTIN_BSWAP - select ARCH_USE_CMPXCHG_LOCKREF if PPC64 - select ARCH_USE_MEMTEST -@@ -271,6 +272,7 @@ config PPC - select HAVE_PERF_USER_STACK_DUMP - select HAVE_REGS_AND_STACK_ACCESS_API - select HAVE_RELIABLE_STACKTRACE -+ select HAVE_POSIX_CPU_TIMERS_TASK_WORK if !KVM - select HAVE_RSEQ - select HAVE_SETUP_PER_CPU_AREA if PPC64 - select HAVE_SOFTIRQ_ON_OWN_STACK diff --git a/debian/patches-rt/PREEMPT_AUTO.patch b/debian/patches-rt/PREEMPT_AUTO.patch deleted file mode 100644 index 618c65f..0000000 --- a/debian/patches-rt/PREEMPT_AUTO.patch +++ /dev/null @@ -1,779 +0,0 @@ -From: Thomas Gleixner -Date: Sat, 23 Sep 2023 03:11:05 +0200 -Subject: [PATCH] sched: define TIF_ALLOW_RESCHED -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -On Fri, Sep 22 2023 at 00:55, Thomas Gleixner wrote: -> On Thu, Sep 21 2023 at 09:00, Linus Torvalds wrote: ->> That said - I think as a proof of concept and "look, with this we get ->> the expected scheduling event counts", that patch is perfect. I think ->> you more than proved the concept. -> -> There is certainly quite some analyis work to do to make this a one to -> one replacement. -> -> With a handful of benchmarks the PoC (tweaked with some obvious fixes) -> is pretty much on par with the current mainline variants (NONE/FULL), -> but the memtier benchmark makes a massive dent. -> -> It sports a whopping 10% regression with the LAZY mode versus the mainline -> NONE model. Non-LAZY and FULL behave unsurprisingly in the same way. -> -> That benchmark is really sensitive to the preemption model. With current -> mainline (DYNAMIC_PREEMPT enabled) the preempt=FULL model has ~20% -> performance drop versus preempt=NONE. - -That 20% was a tired pilot error. The real number is in the 5% ballpark. - -> I have no clue what's going on there yet, but that shows that there is -> obviously quite some work ahead to get this sorted. - -It took some head scratching to figure that out. The initial fix broke -the handling of the hog issue, i.e. the problem that Ankur tried to -solve, but I hacked up a "solution" for that too. - -With that the memtier benchmark is roughly back to the mainline numbers, -but my throughput benchmark know how is pretty close to zero, so that -should be looked at by people who actually understand these things. - -Likewise the hog prevention is just at the PoC level and clearly beyond -my knowledge of scheduler details: It unconditionally forces a -reschedule when the looping task is not responding to a lazy reschedule -request before the next tick. IOW it forces a reschedule on the second -tick, which is obviously different from the cond_resched()/might_sleep() -behaviour. - -The changes vs. the original PoC aside of the bug and thinko fixes: - - 1) A hack to utilize the TRACE_FLAG_IRQS_NOSUPPORT flag to trace the - lazy preempt bit as the trace_entry::flags field is full already. - - That obviously breaks the tracer ABI, but if we go there then - this needs to be fixed. Steven? - - 2) debugfs file to validate that loops can be force preempted w/o - cond_resched() - - The usage is: - - # taskset -c 1 bash - # echo 1 > /sys/kernel/debug/sched/hog & - # echo 1 > /sys/kernel/debug/sched/hog & - # echo 1 > /sys/kernel/debug/sched/hog & - - top shows ~33% CPU for each of the hogs and tracing confirms that - the crude hack in the scheduler tick works: - - bash-4559 [001] dlh2. 2253.331202: resched_curr <-__update_curr - bash-4560 [001] dlh2. 2253.340199: resched_curr <-__update_curr - bash-4561 [001] dlh2. 2253.346199: resched_curr <-__update_curr - bash-4559 [001] dlh2. 2253.353199: resched_curr <-__update_curr - bash-4561 [001] dlh2. 2253.358199: resched_curr <-__update_curr - bash-4560 [001] dlh2. 2253.370202: resched_curr <-__update_curr - bash-4559 [001] dlh2. 2253.378198: resched_curr <-__update_curr - bash-4561 [001] dlh2. 2253.389199: resched_curr <-__update_curr - - The 'l' instead of the usual 'N' reflects that the lazy resched - bit is set. That makes __update_curr() invoke resched_curr() - instead of the lazy variant. resched_curr() sets TIF_NEED_RESCHED - and folds it into preempt_count so that preemption happens at the - next possible point, i.e. either in return from interrupt or at - the next preempt_enable(). - -That's as much as I wanted to demonstrate and I'm not going to spend -more cycles on it as I have already too many other things on flight and -the resulting scheduler woes are clearly outside of my expertice. - -Though definitely I'm putting a permanent NAK in place for any attempts -to duct tape the preempt=NONE model any further by sprinkling more -cond*() and whatever warts around. - -Thanks, - - tglx - -[tglx: s@CONFIG_PREEMPT_AUTO@CONFIG_PREEMPT_BUILD_AUTO@ ] - -Link: https://lore.kernel.org/all/87jzshhexi.ffs@tglx/ -Signed-off-by: Thomas Gleixner -Signed-off-by: Sebastian Andrzej Siewior ---- - arch/x86/Kconfig | 1 - arch/x86/include/asm/thread_info.h | 6 ++-- - drivers/acpi/processor_idle.c | 2 - - include/linux/entry-common.h | 2 - - include/linux/entry-kvm.h | 2 - - include/linux/sched.h | 12 +++++--- - include/linux/sched/idle.h | 8 ++--- - include/linux/thread_info.h | 24 +++++++++++++++++ - include/linux/trace_events.h | 8 ++--- - kernel/Kconfig.preempt | 17 +++++++++++- - kernel/entry/common.c | 4 +- - kernel/entry/kvm.c | 2 - - kernel/sched/core.c | 50 +++++++++++++++++++++++++------------ - kernel/sched/debug.c | 19 ++++++++++++++ - kernel/sched/fair.c | 46 ++++++++++++++++++++++------------ - kernel/sched/features.h | 2 + - kernel/sched/idle.c | 3 -- - kernel/sched/sched.h | 1 - kernel/trace/trace.c | 2 + - kernel/trace/trace_output.c | 16 ++++++++++- - 20 files changed, 171 insertions(+), 56 deletions(-) - ---- a/arch/x86/Kconfig -+++ b/arch/x86/Kconfig -@@ -282,6 +282,7 @@ - select HAVE_STATIC_CALL - select HAVE_STATIC_CALL_INLINE if HAVE_OBJTOOL - select HAVE_PREEMPT_DYNAMIC_CALL -+ select HAVE_PREEMPT_AUTO - select HAVE_RSEQ - select HAVE_RUST if X86_64 - select HAVE_SYSCALL_TRACEPOINTS ---- a/arch/x86/include/asm/thread_info.h -+++ b/arch/x86/include/asm/thread_info.h -@@ -87,8 +87,9 @@ - #define TIF_NOTIFY_RESUME 1 /* callback before returning to user */ - #define TIF_SIGPENDING 2 /* signal pending */ - #define TIF_NEED_RESCHED 3 /* rescheduling necessary */ --#define TIF_SINGLESTEP 4 /* reenable singlestep on user return*/ --#define TIF_SSBD 5 /* Speculative store bypass disable */ -+#define TIF_ARCH_RESCHED_LAZY 4 /* Lazy rescheduling */ -+#define TIF_SINGLESTEP 5 /* reenable singlestep on user return*/ -+#define TIF_SSBD 6 /* Speculative store bypass disable */ - #define TIF_SPEC_IB 9 /* Indirect branch speculation mitigation */ - #define TIF_SPEC_L1D_FLUSH 10 /* Flush L1D on mm switches (processes) */ - #define TIF_USER_RETURN_NOTIFY 11 /* notify kernel of userspace return */ -@@ -110,6 +111,7 @@ - #define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME) - #define _TIF_SIGPENDING (1 << TIF_SIGPENDING) - #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) -+#define _TIF_ARCH_RESCHED_LAZY (1 << TIF_ARCH_RESCHED_LAZY) - #define _TIF_SINGLESTEP (1 << TIF_SINGLESTEP) - #define _TIF_SSBD (1 << TIF_SSBD) - #define _TIF_SPEC_IB (1 << TIF_SPEC_IB) ---- a/drivers/acpi/processor_idle.c -+++ b/drivers/acpi/processor_idle.c -@@ -107,7 +107,7 @@ - */ - static void __cpuidle acpi_safe_halt(void) - { -- if (!tif_need_resched()) { -+ if (!need_resched()) { - raw_safe_halt(); - raw_local_irq_disable(); - } ---- a/include/linux/entry-common.h -+++ b/include/linux/entry-common.h -@@ -65,7 +65,7 @@ - #define EXIT_TO_USER_MODE_WORK \ - (_TIF_SIGPENDING | _TIF_NOTIFY_RESUME | _TIF_UPROBE | \ - _TIF_NEED_RESCHED | _TIF_PATCH_PENDING | _TIF_NOTIFY_SIGNAL | \ -- ARCH_EXIT_TO_USER_MODE_WORK) -+ _TIF_NEED_RESCHED_LAZY | ARCH_EXIT_TO_USER_MODE_WORK) - - /** - * arch_enter_from_user_mode - Architecture specific sanity check for user mode regs ---- a/include/linux/entry-kvm.h -+++ b/include/linux/entry-kvm.h -@@ -18,7 +18,7 @@ - - #define XFER_TO_GUEST_MODE_WORK \ - (_TIF_NEED_RESCHED | _TIF_SIGPENDING | _TIF_NOTIFY_SIGNAL | \ -- _TIF_NOTIFY_RESUME | ARCH_XFER_TO_GUEST_MODE_WORK) -+ _TIF_NOTIFY_RESUME | _TIF_NEED_RESCHED_LAZY | ARCH_XFER_TO_GUEST_MODE_WORK) - - struct kvm_vcpu; - ---- a/include/linux/sched.h -+++ b/include/linux/sched.h -@@ -1957,17 +1957,17 @@ - update_ti_thread_flag(task_thread_info(tsk), flag, value); - } - --static inline int test_and_set_tsk_thread_flag(struct task_struct *tsk, int flag) -+static inline bool test_and_set_tsk_thread_flag(struct task_struct *tsk, int flag) - { - return test_and_set_ti_thread_flag(task_thread_info(tsk), flag); - } - --static inline int test_and_clear_tsk_thread_flag(struct task_struct *tsk, int flag) -+static inline bool test_and_clear_tsk_thread_flag(struct task_struct *tsk, int flag) - { - return test_and_clear_ti_thread_flag(task_thread_info(tsk), flag); - } - --static inline int test_tsk_thread_flag(struct task_struct *tsk, int flag) -+static inline bool test_tsk_thread_flag(struct task_struct *tsk, int flag) - { - return test_ti_thread_flag(task_thread_info(tsk), flag); - } -@@ -1980,9 +1980,11 @@ - static inline void clear_tsk_need_resched(struct task_struct *tsk) - { - clear_tsk_thread_flag(tsk,TIF_NEED_RESCHED); -+ if (IS_ENABLED(CONFIG_PREEMPT_BUILD_AUTO)) -+ clear_tsk_thread_flag(tsk, TIF_NEED_RESCHED_LAZY); - } - --static inline int test_tsk_need_resched(struct task_struct *tsk) -+static inline bool test_tsk_need_resched(struct task_struct *tsk) - { - return unlikely(test_tsk_thread_flag(tsk,TIF_NEED_RESCHED)); - } -@@ -2082,7 +2084,7 @@ - - static __always_inline bool need_resched(void) - { -- return unlikely(tif_need_resched()); -+ return unlikely(tif_need_resched_lazy() || tif_need_resched()); - } - - /* ---- a/include/linux/sched/idle.h -+++ b/include/linux/sched/idle.h -@@ -63,7 +63,7 @@ - */ - smp_mb__after_atomic(); - -- return unlikely(tif_need_resched()); -+ return unlikely(need_resched()); - } - - static __always_inline bool __must_check current_clr_polling_and_test(void) -@@ -76,7 +76,7 @@ - */ - smp_mb__after_atomic(); - -- return unlikely(tif_need_resched()); -+ return unlikely(need_resched()); - } - - #else -@@ -85,11 +85,11 @@ - - static inline bool __must_check current_set_polling_and_test(void) - { -- return unlikely(tif_need_resched()); -+ return unlikely(need_resched()); - } - static inline bool __must_check current_clr_polling_and_test(void) - { -- return unlikely(tif_need_resched()); -+ return unlikely(need_resched()); - } - #endif - ---- a/include/linux/thread_info.h -+++ b/include/linux/thread_info.h -@@ -59,6 +59,16 @@ - - #include - -+#ifdef CONFIG_PREEMPT_BUILD_AUTO -+# define TIF_NEED_RESCHED_LAZY TIF_ARCH_RESCHED_LAZY -+# define _TIF_NEED_RESCHED_LAZY _TIF_ARCH_RESCHED_LAZY -+# define TIF_NEED_RESCHED_LAZY_OFFSET (TIF_NEED_RESCHED_LAZY - TIF_NEED_RESCHED) -+#else -+# define TIF_NEED_RESCHED_LAZY TIF_NEED_RESCHED -+# define _TIF_NEED_RESCHED_LAZY _TIF_NEED_RESCHED -+# define TIF_NEED_RESCHED_LAZY_OFFSET 0 -+#endif -+ - #ifdef __KERNEL__ - - #ifndef arch_set_restart_data -@@ -185,6 +195,13 @@ - (unsigned long *)(¤t_thread_info()->flags)); - } - -+static __always_inline bool tif_need_resched_lazy(void) -+{ -+ return IS_ENABLED(CONFIG_PREEMPT_BUILD_AUTO) && -+ arch_test_bit(TIF_NEED_RESCHED_LAZY, -+ (unsigned long *)(¤t_thread_info()->flags)); -+} -+ - #else - - static __always_inline bool tif_need_resched(void) -@@ -193,6 +210,13 @@ - (unsigned long *)(¤t_thread_info()->flags)); - } - -+static __always_inline bool tif_need_resched_lazy(void) -+{ -+ return IS_ENABLED(CONFIG_PREEMPT_BUILD_AUTO) && -+ test_bit(TIF_NEED_RESCHED_LAZY, -+ (unsigned long *)(¤t_thread_info()->flags)); -+} -+ - #endif /* _ASM_GENERIC_BITOPS_INSTRUMENTED_NON_ATOMIC_H */ - - #ifndef CONFIG_HAVE_ARCH_WITHIN_STACK_FRAMES ---- a/include/linux/trace_events.h -+++ b/include/linux/trace_events.h -@@ -184,8 +184,8 @@ - - enum trace_flag_type { - TRACE_FLAG_IRQS_OFF = 0x01, -- TRACE_FLAG_IRQS_NOSUPPORT = 0x02, -- TRACE_FLAG_NEED_RESCHED = 0x04, -+ TRACE_FLAG_NEED_RESCHED = 0x02, -+ TRACE_FLAG_NEED_RESCHED_LAZY = 0x04, - TRACE_FLAG_HARDIRQ = 0x08, - TRACE_FLAG_SOFTIRQ = 0x10, - TRACE_FLAG_PREEMPT_RESCHED = 0x20, -@@ -211,11 +211,11 @@ - - static inline unsigned int tracing_gen_ctx_flags(unsigned long irqflags) - { -- return tracing_gen_ctx_irq_test(TRACE_FLAG_IRQS_NOSUPPORT); -+ return tracing_gen_ctx_irq_test(0); - } - static inline unsigned int tracing_gen_ctx(void) - { -- return tracing_gen_ctx_irq_test(TRACE_FLAG_IRQS_NOSUPPORT); -+ return tracing_gen_ctx_irq_test(0); - } - #endif - ---- a/kernel/Kconfig.preempt -+++ b/kernel/Kconfig.preempt -@@ -11,6 +11,13 @@ - select PREEMPTION - select UNINLINE_SPIN_UNLOCK if !ARCH_INLINE_SPIN_UNLOCK - -+config PREEMPT_BUILD_AUTO -+ bool -+ select PREEMPT_BUILD -+ -+config HAVE_PREEMPT_AUTO -+ bool -+ - choice - prompt "Preemption Model" - default PREEMPT_NONE -@@ -67,9 +74,17 @@ - embedded system with latency requirements in the milliseconds - range. - -+config PREEMPT_AUTO -+ bool "Automagic preemption mode with runtime tweaking support" -+ depends on HAVE_PREEMPT_AUTO -+ select PREEMPT_BUILD_AUTO -+ help -+ Add some sensible blurb here -+ - config PREEMPT_RT - bool "Fully Preemptible Kernel (Real-Time)" - depends on EXPERT && ARCH_SUPPORTS_RT -+ select PREEMPT_BUILD_AUTO if HAVE_PREEMPT_AUTO - select PREEMPTION - help - This option turns the kernel into a real-time kernel by replacing -@@ -95,7 +110,7 @@ - - config PREEMPT_DYNAMIC - bool "Preemption behaviour defined on boot" -- depends on HAVE_PREEMPT_DYNAMIC && !PREEMPT_RT -+ depends on HAVE_PREEMPT_DYNAMIC && !PREEMPT_RT && !PREEMPT_AUTO - select JUMP_LABEL if HAVE_PREEMPT_DYNAMIC_KEY - select PREEMPT_BUILD - default y if HAVE_PREEMPT_DYNAMIC_CALL ---- a/kernel/entry/common.c -+++ b/kernel/entry/common.c -@@ -98,7 +98,7 @@ - - local_irq_enable_exit_to_user(ti_work); - -- if (ti_work & _TIF_NEED_RESCHED) -+ if (ti_work & (_TIF_NEED_RESCHED | _TIF_NEED_RESCHED_LAZY)) - schedule(); - - if (ti_work & _TIF_UPROBE) -@@ -307,7 +307,7 @@ - rcu_irq_exit_check_preempt(); - if (IS_ENABLED(CONFIG_DEBUG_ENTRY)) - WARN_ON_ONCE(!on_thread_stack()); -- if (need_resched()) -+ if (test_tsk_need_resched(current)) - preempt_schedule_irq(); - } - } ---- a/kernel/entry/kvm.c -+++ b/kernel/entry/kvm.c -@@ -13,7 +13,7 @@ - return -EINTR; - } - -- if (ti_work & _TIF_NEED_RESCHED) -+ if (ti_work & (_TIF_NEED_RESCHED | TIF_NEED_RESCHED_LAZY)) - schedule(); - - if (ti_work & _TIF_NOTIFY_RESUME) ---- a/kernel/sched/core.c -+++ b/kernel/sched/core.c -@@ -899,14 +899,15 @@ - - #if defined(CONFIG_SMP) && defined(TIF_POLLING_NRFLAG) - /* -- * Atomically set TIF_NEED_RESCHED and test for TIF_POLLING_NRFLAG, -+ * Atomically set TIF_NEED_RESCHED[_LAZY] and test for TIF_POLLING_NRFLAG, - * this avoids any races wrt polling state changes and thereby avoids - * spurious IPIs. - */ --static inline bool set_nr_and_not_polling(struct task_struct *p) -+static inline bool set_nr_and_not_polling(struct task_struct *p, int tif_bit) - { - struct thread_info *ti = task_thread_info(p); -- return !(fetch_or(&ti->flags, _TIF_NEED_RESCHED) & _TIF_POLLING_NRFLAG); -+ -+ return !(fetch_or(&ti->flags, 1 << tif_bit) & _TIF_POLLING_NRFLAG); - } - - /* -@@ -923,7 +924,7 @@ - do { - if (!(val & _TIF_POLLING_NRFLAG)) - return false; -- if (val & _TIF_NEED_RESCHED) -+ if (val & (_TIF_NEED_RESCHED | _TIF_NEED_RESCHED_LAZY)) - return true; - } while (!try_cmpxchg(&ti->flags, &val, val | _TIF_NEED_RESCHED)); - -@@ -931,9 +932,9 @@ - } - - #else --static inline bool set_nr_and_not_polling(struct task_struct *p) -+static inline bool set_nr_and_not_polling(struct task_struct *p, int tif_bit) - { -- set_tsk_need_resched(p); -+ set_tsk_thread_flag(p, tif_bit); - return true; - } - -@@ -1038,28 +1039,47 @@ - * might also involve a cross-CPU call to trigger the scheduler on - * the target CPU. - */ --void resched_curr(struct rq *rq) -+static void __resched_curr(struct rq *rq, int lazy) - { -+ int cpu, tif_bit = TIF_NEED_RESCHED + lazy; - struct task_struct *curr = rq->curr; -- int cpu; - - lockdep_assert_rq_held(rq); - -- if (test_tsk_need_resched(curr)) -+ if (unlikely(test_tsk_thread_flag(curr, tif_bit))) - return; - - cpu = cpu_of(rq); - - if (cpu == smp_processor_id()) { -- set_tsk_need_resched(curr); -- set_preempt_need_resched(); -+ set_tsk_thread_flag(curr, tif_bit); -+ if (!lazy) -+ set_preempt_need_resched(); - return; - } - -- if (set_nr_and_not_polling(curr)) -- smp_send_reschedule(cpu); -- else -+ if (set_nr_and_not_polling(curr, tif_bit)) { -+ if (!lazy) -+ smp_send_reschedule(cpu); -+ } else { - trace_sched_wake_idle_without_ipi(cpu); -+ } -+} -+ -+void resched_curr(struct rq *rq) -+{ -+ __resched_curr(rq, 0); -+} -+ -+void resched_curr_lazy(struct rq *rq) -+{ -+ int lazy = IS_ENABLED(CONFIG_PREEMPT_BUILD_AUTO) && !sched_feat(FORCE_NEED_RESCHED) ? -+ TIF_NEED_RESCHED_LAZY_OFFSET : 0; -+ -+ if (lazy && unlikely(test_tsk_thread_flag(rq->curr, TIF_NEED_RESCHED))) -+ return; -+ -+ __resched_curr(rq, lazy); - } - - void resched_cpu(int cpu) -@@ -1154,7 +1174,7 @@ - * and testing of the above solutions didn't appear to report - * much benefits. - */ -- if (set_nr_and_not_polling(rq->idle)) -+ if (set_nr_and_not_polling(rq->idle, TIF_NEED_RESCHED)) - smp_send_reschedule(cpu); - else - trace_sched_wake_idle_without_ipi(cpu); ---- a/kernel/sched/debug.c -+++ b/kernel/sched/debug.c -@@ -333,6 +333,23 @@ - .release = seq_release, - }; - -+static ssize_t sched_hog_write(struct file *filp, const char __user *ubuf, -+ size_t cnt, loff_t *ppos) -+{ -+ unsigned long end = jiffies + 60 * HZ; -+ -+ for (; time_before(jiffies, end) && !signal_pending(current);) -+ cpu_relax(); -+ -+ return cnt; -+} -+ -+static const struct file_operations sched_hog_fops = { -+ .write = sched_hog_write, -+ .open = simple_open, -+ .llseek = default_llseek, -+}; -+ - static struct dentry *debugfs_sched; - - static __init int sched_init_debug(void) -@@ -374,6 +391,8 @@ - - debugfs_create_file("debug", 0444, debugfs_sched, NULL, &sched_debug_fops); - -+ debugfs_create_file("hog", 0200, debugfs_sched, NULL, &sched_hog_fops); -+ - return 0; - } - late_initcall(sched_init_debug); ---- a/kernel/sched/fair.c -+++ b/kernel/sched/fair.c -@@ -974,8 +974,10 @@ - * XXX: strictly: vd_i += N*r_i/w_i such that: vd_i > ve_i - * this is probably good enough. - */ --static void update_deadline(struct cfs_rq *cfs_rq, struct sched_entity *se) -+static void update_deadline(struct cfs_rq *cfs_rq, struct sched_entity *se, bool tick) - { -+ struct rq *rq = rq_of(cfs_rq); -+ - if ((s64)(se->vruntime - se->deadline) < 0) - return; - -@@ -994,10 +996,19 @@ - /* - * The task has consumed its request, reschedule. - */ -- if (cfs_rq->nr_running > 1) { -- resched_curr(rq_of(cfs_rq)); -- clear_buddies(cfs_rq, se); -+ if (cfs_rq->nr_running < 2) -+ return; -+ -+ if (!IS_ENABLED(CONFIG_PREEMPT_BUILD_AUTO) || sched_feat(FORCE_NEED_RESCHED)) { -+ resched_curr(rq); -+ } else { -+ /* Did the task ignore the lazy reschedule request? */ -+ if (tick && test_tsk_thread_flag(rq->curr, TIF_NEED_RESCHED_LAZY)) -+ resched_curr(rq); -+ else -+ resched_curr_lazy(rq); - } -+ clear_buddies(cfs_rq, se); - } - - #include "pelt.h" -@@ -1153,7 +1164,7 @@ - /* - * Update the current task's runtime statistics. - */ --static void update_curr(struct cfs_rq *cfs_rq) -+static void __update_curr(struct cfs_rq *cfs_rq, bool tick) - { - struct sched_entity *curr = cfs_rq->curr; - s64 delta_exec; -@@ -1166,7 +1177,7 @@ - return; - - curr->vruntime += calc_delta_fair(delta_exec, curr); -- update_deadline(cfs_rq, curr); -+ update_deadline(cfs_rq, curr, tick); - update_min_vruntime(cfs_rq); - - if (entity_is_task(curr)) -@@ -1175,6 +1186,11 @@ - account_cfs_rq_runtime(cfs_rq, delta_exec); - } - -+static inline void update_curr(struct cfs_rq *cfs_rq) -+{ -+ __update_curr(cfs_rq, false); -+} -+ - static void update_curr_fair(struct rq *rq) - { - update_curr(cfs_rq_of(&rq->curr->se)); -@@ -5520,7 +5536,7 @@ - /* - * Update run-time statistics of the 'current'. - */ -- update_curr(cfs_rq); -+ __update_curr(cfs_rq, true); - - /* - * Ensure that runnable average is periodically updated. -@@ -5534,7 +5550,7 @@ - * validating it and just reschedule. - */ - if (queued) { -- resched_curr(rq_of(cfs_rq)); -+ resched_curr_lazy(rq_of(cfs_rq)); - return; - } - /* -@@ -5680,7 +5696,7 @@ - * hierarchy can be throttled - */ - if (!assign_cfs_rq_runtime(cfs_rq) && likely(cfs_rq->curr)) -- resched_curr(rq_of(cfs_rq)); -+ resched_curr_lazy(rq_of(cfs_rq)); - } - - static __always_inline -@@ -5940,7 +5956,7 @@ - - /* Determine whether we need to wake up potentially idle CPU: */ - if (rq->curr == rq->idle && rq->cfs.nr_running) -- resched_curr(rq); -+ resched_curr_lazy(rq); - } - - #ifdef CONFIG_SMP -@@ -6655,7 +6671,7 @@ - - if (delta < 0) { - if (task_current(rq, p)) -- resched_curr(rq); -+ resched_curr_lazy(rq); - return; - } - hrtick_start(rq, delta); -@@ -8387,7 +8403,7 @@ - * prevents us from potentially nominating it as a false LAST_BUDDY - * below. - */ -- if (test_tsk_need_resched(curr)) -+ if (need_resched()) - return; - - if (!sched_feat(WAKEUP_PREEMPTION)) -@@ -8425,7 +8441,7 @@ - return; - - preempt: -- resched_curr(rq); -+ resched_curr_lazy(rq); - } - - #ifdef CONFIG_SMP -@@ -12579,7 +12595,7 @@ - */ - if (rq->core->core_forceidle_count && rq->cfs.nr_running == 1 && - __entity_slice_used(&curr->se, MIN_NR_TASKS_DURING_FORCEIDLE)) -- resched_curr(rq); -+ resched_curr_lazy(rq); - } - - /* -@@ -12746,7 +12762,7 @@ - */ - if (task_current(rq, p)) { - if (p->prio > oldprio) -- resched_curr(rq); -+ resched_curr_lazy(rq); - } else - wakeup_preempt(rq, p, 0); - } ---- a/kernel/sched/features.h -+++ b/kernel/sched/features.h -@@ -87,3 +87,5 @@ - SCHED_FEAT(LATENCY_WARN, false) - - SCHED_FEAT(HZ_BW, true) -+ -+SCHED_FEAT(FORCE_NEED_RESCHED, false) ---- a/kernel/sched/idle.c -+++ b/kernel/sched/idle.c -@@ -57,8 +57,7 @@ - ct_cpuidle_enter(); - - raw_local_irq_enable(); -- while (!tif_need_resched() && -- (cpu_idle_force_poll || tick_check_broadcast_expired())) -+ while (!need_resched() && (cpu_idle_force_poll || tick_check_broadcast_expired())) - cpu_relax(); - raw_local_irq_disable(); - ---- a/kernel/sched/sched.h -+++ b/kernel/sched/sched.h -@@ -2513,6 +2513,7 @@ - extern void reweight_task(struct task_struct *p, const struct load_weight *lw); - - extern void resched_curr(struct rq *rq); -+extern void resched_curr_lazy(struct rq *rq); - extern void resched_cpu(int cpu); - - extern struct rt_bandwidth def_rt_bandwidth; ---- a/kernel/trace/trace.c -+++ b/kernel/trace/trace.c -@@ -2515,6 +2515,8 @@ - - if (tif_need_resched()) - trace_flags |= TRACE_FLAG_NEED_RESCHED; -+ if (tif_need_resched_lazy()) -+ trace_flags |= TRACE_FLAG_NEED_RESCHED_LAZY; - if (test_preempt_need_resched()) - trace_flags |= TRACE_FLAG_PREEMPT_RESCHED; - return (trace_flags << 16) | (min_t(unsigned int, pc & 0xff, 0xf)) | ---- a/kernel/trace/trace_output.c -+++ b/kernel/trace/trace_output.c -@@ -460,17 +460,29 @@ - (entry->flags & TRACE_FLAG_IRQS_OFF && bh_off) ? 'D' : - (entry->flags & TRACE_FLAG_IRQS_OFF) ? 'd' : - bh_off ? 'b' : -- (entry->flags & TRACE_FLAG_IRQS_NOSUPPORT) ? 'X' : -+ !IS_ENABLED(CONFIG_TRACE_IRQFLAGS_SUPPORT) ? 'X' : - '.'; - -- switch (entry->flags & (TRACE_FLAG_NEED_RESCHED | -+ switch (entry->flags & (TRACE_FLAG_NEED_RESCHED | TRACE_FLAG_NEED_RESCHED_LAZY | - TRACE_FLAG_PREEMPT_RESCHED)) { -+ case TRACE_FLAG_NEED_RESCHED | TRACE_FLAG_NEED_RESCHED_LAZY | TRACE_FLAG_PREEMPT_RESCHED: -+ need_resched = 'B'; -+ break; - case TRACE_FLAG_NEED_RESCHED | TRACE_FLAG_PREEMPT_RESCHED: - need_resched = 'N'; - break; -+ case TRACE_FLAG_NEED_RESCHED_LAZY | TRACE_FLAG_PREEMPT_RESCHED: -+ need_resched = 'L'; -+ break; -+ case TRACE_FLAG_NEED_RESCHED | TRACE_FLAG_NEED_RESCHED_LAZY: -+ need_resched = 'b'; -+ break; - case TRACE_FLAG_NEED_RESCHED: - need_resched = 'n'; - break; -+ case TRACE_FLAG_NEED_RESCHED_LAZY: -+ need_resched = 'l'; -+ break; - case TRACE_FLAG_PREEMPT_RESCHED: - need_resched = 'p'; - break; diff --git a/debian/patches-rt/arm-Disable-FAST_GUP-on-PREEMPT_RT-if-HIGHPTE-is-als.patch b/debian/patches-rt/arm-Disable-FAST_GUP-on-PREEMPT_RT-if-HIGHPTE-is-als.patch deleted file mode 100644 index 03a8d05..0000000 --- a/debian/patches-rt/arm-Disable-FAST_GUP-on-PREEMPT_RT-if-HIGHPTE-is-als.patch +++ /dev/null @@ -1,35 +0,0 @@ -From: Sebastian Andrzej Siewior -Date: Tue, 23 Jan 2024 12:56:21 +0100 -Subject: [PATCH] arm: Disable FAST_GUP on PREEMPT_RT if HIGHPTE is also - enabled. -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -gup_pgd_range() is invoked with disabled interrupts and invokes -__kmap_local_page_prot() via pte_offset_map(), gup_p4d_range(). -With HIGHPTE enabled, __kmap_local_page_prot() invokes kmap_high_get() -which uses a spinlock_t via lock_kmap_any(). This leads to an -sleeping-while-atomic error on PREEMPT_RT because spinlock_t becomes a -sleeping lock and must not be acquired in atomic context. - -The loop in map_new_virtual() uses wait_queue_head_t for wake up which -also is using a spinlock_t. - -Limit HAVE_FAST_GUP additionaly to remain disabled on PREEMPT_RT with -HIGHPTE enabled. - -Signed-off-by: Sebastian Andrzej Siewior ---- - arch/arm/Kconfig | 2 +- - 1 file changed, 1 insertion(+), 1 deletion(-) - ---- a/arch/arm/Kconfig -+++ b/arch/arm/Kconfig -@@ -102,7 +102,7 @@ config ARM - select HAVE_DYNAMIC_FTRACE_WITH_REGS if HAVE_DYNAMIC_FTRACE - select HAVE_EFFICIENT_UNALIGNED_ACCESS if (CPU_V6 || CPU_V6K || CPU_V7) && MMU - select HAVE_EXIT_THREAD -- select HAVE_GUP_FAST if ARM_LPAE -+ select HAVE_GUP_FAST if ARM_LPAE && !(PREEMPT_RT && HIGHPTE) - select HAVE_FTRACE_MCOUNT_RECORD if !XIP_KERNEL - select HAVE_FUNCTION_ERROR_INJECTION - select HAVE_FUNCTION_GRAPH_TRACER diff --git a/debian/patches-rt/netfilter-nft_counter-Use-u64_stats_t-for-statistic.patch b/debian/patches-rt/netfilter-nft_counter-Use-u64_stats_t-for-statistic.patch deleted file mode 100644 index aff0fe0..0000000 --- a/debian/patches-rt/netfilter-nft_counter-Use-u64_stats_t-for-statistic.patch +++ /dev/null @@ -1,238 +0,0 @@ -From: Sebastian Andrzej Siewior -Date: Mon, 19 Aug 2024 15:29:12 +0200 -Subject: [PATCH] netfilter: nft_counter: Use u64_stats_t for statistic. -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -The nft_counter uses two s64 counters for statistics. Those two are -protected by a seqcount to ensure that the 64bit variable is always -properly seen during updates even on 32bit architectures where the store -is performed by two writes. A side effect is that the two counter (bytes -and packet) are written and read together in the same window. - -This can be replaced with u64_stats_t. write_seqcount_begin()/ end() is -replaced with u64_stats_update_begin()/ end() and behaves the same way -as with seqcount_t on 32bit architectures. Additionally there is a -preempt_disable on PREEMPT_RT to ensure that a reader does not preempt a -writer. -On 64bit architectures the macros are removed and the reads happen -without any retries. This also means that the reader can observe one -counter (bytes) from before the update and the other counter (packets) -but that is okay since there is no requirement to have both counter from -the same update window. - -Convert the statistic to u64_stats_t. There is one optimisation: -nft_counter_do_init() and nft_counter_clone() allocate a new per-CPU -counter and assign a value to it. During this assignment preemption is -disabled which is not needed because the counter is not yet exposed to -the system so there can not be another writer or reader. Therefore -disabling preemption is omitted and raw_cpu_ptr() is used to obtain a -pointer to a counter for the assignment. - -Cc: stable-rt@vger.kernel.org -Signed-off-by: Sebastian Andrzej Siewior ---- - net/netfilter/nft_counter.c | 90 ++++++++++++++++++++++---------------------- - 1 file changed, 46 insertions(+), 44 deletions(-) - ---- a/net/netfilter/nft_counter.c -+++ b/net/netfilter/nft_counter.c -@@ -8,7 +8,7 @@ - #include - #include - #include --#include -+#include - #include - #include - #include -@@ -17,6 +17,11 @@ - #include - - struct nft_counter { -+ u64_stats_t bytes; -+ u64_stats_t packets; -+}; -+ -+struct nft_counter_tot { - s64 bytes; - s64 packets; - }; -@@ -25,25 +30,24 @@ struct nft_counter_percpu_priv { - struct nft_counter __percpu *counter; - }; - --static DEFINE_PER_CPU(seqcount_t, nft_counter_seq); -+static DEFINE_PER_CPU(struct u64_stats_sync, nft_counter_sync); - - static inline void nft_counter_do_eval(struct nft_counter_percpu_priv *priv, - struct nft_regs *regs, - const struct nft_pktinfo *pkt) - { -+ struct u64_stats_sync *nft_sync; - struct nft_counter *this_cpu; -- seqcount_t *myseq; - - local_bh_disable(); - this_cpu = this_cpu_ptr(priv->counter); -- myseq = this_cpu_ptr(&nft_counter_seq); -- -- write_seqcount_begin(myseq); -+ nft_sync = this_cpu_ptr(&nft_counter_sync); - -- this_cpu->bytes += pkt->skb->len; -- this_cpu->packets++; -+ u64_stats_update_begin(nft_sync); -+ u64_stats_add(&this_cpu->bytes, pkt->skb->len); -+ u64_stats_inc(&this_cpu->packets); -+ u64_stats_update_end(nft_sync); - -- write_seqcount_end(myseq); - local_bh_enable(); - } - -@@ -66,17 +70,16 @@ static int nft_counter_do_init(const str - if (cpu_stats == NULL) - return -ENOMEM; - -- preempt_disable(); -- this_cpu = this_cpu_ptr(cpu_stats); -+ this_cpu = raw_cpu_ptr(cpu_stats); - if (tb[NFTA_COUNTER_PACKETS]) { -- this_cpu->packets = -- be64_to_cpu(nla_get_be64(tb[NFTA_COUNTER_PACKETS])); -+ u64_stats_set(&this_cpu->packets, -+ be64_to_cpu(nla_get_be64(tb[NFTA_COUNTER_PACKETS]))); - } - if (tb[NFTA_COUNTER_BYTES]) { -- this_cpu->bytes = -- be64_to_cpu(nla_get_be64(tb[NFTA_COUNTER_BYTES])); -+ u64_stats_set(&this_cpu->bytes, -+ be64_to_cpu(nla_get_be64(tb[NFTA_COUNTER_BYTES]))); - } -- preempt_enable(); -+ - priv->counter = cpu_stats; - return 0; - } -@@ -104,40 +107,41 @@ static void nft_counter_obj_destroy(cons - } - - static void nft_counter_reset(struct nft_counter_percpu_priv *priv, -- struct nft_counter *total) -+ struct nft_counter_tot *total) - { -+ struct u64_stats_sync *nft_sync; - struct nft_counter *this_cpu; -- seqcount_t *myseq; - - local_bh_disable(); - this_cpu = this_cpu_ptr(priv->counter); -- myseq = this_cpu_ptr(&nft_counter_seq); -+ nft_sync = this_cpu_ptr(&nft_counter_sync); -+ -+ u64_stats_update_begin(nft_sync); -+ u64_stats_add(&this_cpu->packets, -total->packets); -+ u64_stats_add(&this_cpu->bytes, -total->bytes); -+ u64_stats_update_end(nft_sync); - -- write_seqcount_begin(myseq); -- this_cpu->packets -= total->packets; -- this_cpu->bytes -= total->bytes; -- write_seqcount_end(myseq); - local_bh_enable(); - } - - static void nft_counter_fetch(struct nft_counter_percpu_priv *priv, -- struct nft_counter *total) -+ struct nft_counter_tot *total) - { - struct nft_counter *this_cpu; -- const seqcount_t *myseq; - u64 bytes, packets; - unsigned int seq; - int cpu; - - memset(total, 0, sizeof(*total)); - for_each_possible_cpu(cpu) { -- myseq = per_cpu_ptr(&nft_counter_seq, cpu); -+ struct u64_stats_sync *nft_sync = per_cpu_ptr(&nft_counter_sync, cpu); -+ - this_cpu = per_cpu_ptr(priv->counter, cpu); - do { -- seq = read_seqcount_begin(myseq); -- bytes = this_cpu->bytes; -- packets = this_cpu->packets; -- } while (read_seqcount_retry(myseq, seq)); -+ seq = u64_stats_fetch_begin(nft_sync); -+ bytes = u64_stats_read(&this_cpu->bytes); -+ packets = u64_stats_read(&this_cpu->packets); -+ } while (u64_stats_fetch_retry(nft_sync, seq)); - - total->bytes += bytes; - total->packets += packets; -@@ -148,7 +152,7 @@ static int nft_counter_do_dump(struct sk - struct nft_counter_percpu_priv *priv, - bool reset) - { -- struct nft_counter total; -+ struct nft_counter_tot total; - - nft_counter_fetch(priv, &total); - -@@ -237,7 +241,7 @@ static int nft_counter_clone(struct nft_ - struct nft_counter_percpu_priv *priv_clone = nft_expr_priv(dst); - struct nft_counter __percpu *cpu_stats; - struct nft_counter *this_cpu; -- struct nft_counter total; -+ struct nft_counter_tot total; - - nft_counter_fetch(priv, &total); - -@@ -245,11 +249,9 @@ static int nft_counter_clone(struct nft_ - if (cpu_stats == NULL) - return -ENOMEM; - -- preempt_disable(); -- this_cpu = this_cpu_ptr(cpu_stats); -- this_cpu->packets = total.packets; -- this_cpu->bytes = total.bytes; -- preempt_enable(); -+ this_cpu = raw_cpu_ptr(cpu_stats); -+ u64_stats_set(&this_cpu->packets, total.packets); -+ u64_stats_set(&this_cpu->bytes, total.bytes); - - priv_clone->counter = cpu_stats; - return 0; -@@ -267,17 +269,17 @@ static void nft_counter_offload_stats(st - const struct flow_stats *stats) - { - struct nft_counter_percpu_priv *priv = nft_expr_priv(expr); -+ struct u64_stats_sync *nft_sync; - struct nft_counter *this_cpu; -- seqcount_t *myseq; - - local_bh_disable(); - this_cpu = this_cpu_ptr(priv->counter); -- myseq = this_cpu_ptr(&nft_counter_seq); -+ nft_sync = this_cpu_ptr(&nft_counter_sync); - -- write_seqcount_begin(myseq); -- this_cpu->packets += stats->pkts; -- this_cpu->bytes += stats->bytes; -- write_seqcount_end(myseq); -+ u64_stats_update_begin(nft_sync); -+ u64_stats_add(&this_cpu->packets, stats->pkts); -+ u64_stats_add(&this_cpu->bytes, stats->bytes); -+ u64_stats_update_end(nft_sync); - local_bh_enable(); - } - -@@ -286,7 +288,7 @@ void nft_counter_init_seqcount(void) - int cpu; - - for_each_possible_cpu(cpu) -- seqcount_init(per_cpu_ptr(&nft_counter_seq, cpu)); -+ u64_stats_init(per_cpu_ptr(&nft_counter_sync, cpu)); - } - - struct nft_expr_type nft_counter_type; diff --git a/debian/patches-rt/powerpc-pseries-Select-the-generic-memory-allocator.patch b/debian/patches-rt/powerpc-pseries-Select-the-generic-memory-allocator.patch deleted file mode 100644 index 41849cb..0000000 --- a/debian/patches-rt/powerpc-pseries-Select-the-generic-memory-allocator.patch +++ /dev/null @@ -1,27 +0,0 @@ -From: Sebastian Andrzej Siewior -Date: Thu, 9 Mar 2023 09:13:52 +0100 -Subject: [PATCH] powerpc/pseries: Select the generic memory allocator. -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -The RTAS work area allocator is using the generic memory allocator and -as such it must select it. - -Select the generic memory allocator on pseries. - -Fixes: 43033bc62d349 ("powerpc/pseries: add RTAS work area allocator") -Signed-off-by: Sebastian Andrzej Siewior -Link: https://lore.kernel.org/20230309135110.uAxhqRFk@linutronix.de ---- - arch/powerpc/platforms/pseries/Kconfig | 1 + - 1 file changed, 1 insertion(+) - ---- a/arch/powerpc/platforms/pseries/Kconfig -+++ b/arch/powerpc/platforms/pseries/Kconfig -@@ -2,6 +2,7 @@ - config PPC_PSERIES - depends on PPC64 && PPC_BOOK3S - bool "IBM pSeries & new (POWER5-based) iSeries" -+ select GENERIC_ALLOCATOR - select HAVE_PCSPKR_PLATFORM - select MPIC - select OF_DYNAMIC diff --git a/debian/patches-rt/powerpc__traps__Use_PREEMPT_RT.patch b/debian/patches-rt/powerpc__traps__Use_PREEMPT_RT.patch deleted file mode 100644 index e6ad11b..0000000 --- a/debian/patches-rt/powerpc__traps__Use_PREEMPT_RT.patch +++ /dev/null @@ -1,38 +0,0 @@ -Subject: powerpc: traps: Use PREEMPT_RT -From: Sebastian Andrzej Siewior -Date: Fri Jul 26 11:30:49 2019 +0200 -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -From: Sebastian Andrzej Siewior - -Add PREEMPT_RT to the backtrace if enabled. - -Signed-off-by: Sebastian Andrzej Siewior -Signed-off-by: Thomas Gleixner - - ---- - arch/powerpc/kernel/traps.c | 7 ++++++- - 1 file changed, 6 insertions(+), 1 deletion(-) ---- ---- a/arch/powerpc/kernel/traps.c -+++ b/arch/powerpc/kernel/traps.c -@@ -261,12 +261,17 @@ static char *get_mmu_str(void) - - static int __die(const char *str, struct pt_regs *regs, long err) - { -+ const char *pr = ""; -+ - printk("Oops: %s, sig: %ld [#%d]\n", str, err, ++die_counter); - -+ if (IS_ENABLED(CONFIG_PREEMPTION)) -+ pr = IS_ENABLED(CONFIG_PREEMPT_RT) ? " PREEMPT_RT" : " PREEMPT"; -+ - printk("%s PAGE_SIZE=%luK%s%s%s%s%s%s %s\n", - IS_ENABLED(CONFIG_CPU_LITTLE_ENDIAN) ? "LE" : "BE", - PAGE_SIZE / 1024, get_mmu_str(), -- IS_ENABLED(CONFIG_PREEMPT) ? " PREEMPT" : "", -+ pr, - IS_ENABLED(CONFIG_SMP) ? " SMP" : "", - IS_ENABLED(CONFIG_SMP) ? (" NR_CPUS=" __stringify(NR_CPUS)) : "", - debug_pagealloc_enabled() ? " DEBUG_PAGEALLOC" : "", diff --git a/debian/patches-rt/powerpc_kvm__Disable_in-kernel_MPIC_emulation_for_PREEMPT_RT.patch b/debian/patches-rt/powerpc_kvm__Disable_in-kernel_MPIC_emulation_for_PREEMPT_RT.patch deleted file mode 100644 index aa085c9..0000000 --- a/debian/patches-rt/powerpc_kvm__Disable_in-kernel_MPIC_emulation_for_PREEMPT_RT.patch +++ /dev/null @@ -1,43 +0,0 @@ -Subject: powerpc/kvm: Disable in-kernel MPIC emulation for PREEMPT_RT -From: Bogdan Purcareata -Date: Fri Apr 24 15:53:13 2015 +0000 -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -From: Bogdan Purcareata - -While converting the openpic emulation code to use a raw_spinlock_t enables -guests to run on RT, there's still a performance issue. For interrupts sent in -directed delivery mode with a multiple CPU mask, the emulated openpic will loop -through all of the VCPUs, and for each VCPUs, it call IRQ_check, which will loop -through all the pending interrupts for that VCPU. This is done while holding the -raw_lock, meaning that in all this time the interrupts and preemption are -disabled on the host Linux. A malicious user app can max both these number and -cause a DoS. - -This temporary fix is sent for two reasons. First is so that users who want to -use the in-kernel MPIC emulation are aware of the potential latencies, thus -making sure that the hardware MPIC and their usage scenario does not involve -interrupts sent in directed delivery mode, and the number of possible pending -interrupts is kept small. Secondly, this should incentivize the development of a -proper openpic emulation that would be better suited for RT. - -Acked-by: Scott Wood -Signed-off-by: Bogdan Purcareata -Signed-off-by: Sebastian Andrzej Siewior -Signed-off-by: Thomas Gleixner - - ---- - arch/powerpc/kvm/Kconfig | 1 + - 1 file changed, 1 insertion(+) ---- ---- a/arch/powerpc/kvm/Kconfig -+++ b/arch/powerpc/kvm/Kconfig -@@ -221,6 +221,7 @@ config KVM_E500MC - config KVM_MPIC - bool "KVM in-kernel MPIC emulation" - depends on KVM && PPC_E500 -+ depends on !PREEMPT_RT - select HAVE_KVM_IRQCHIP - select HAVE_KVM_IRQ_ROUTING - select HAVE_KVM_MSI diff --git a/debian/patches-rt/powerpc_pseries_iommu__Use_a_locallock_instead_local_irq_save.patch b/debian/patches-rt/powerpc_pseries_iommu__Use_a_locallock_instead_local_irq_save.patch deleted file mode 100644 index 353f5b1..0000000 --- a/debian/patches-rt/powerpc_pseries_iommu__Use_a_locallock_instead_local_irq_save.patch +++ /dev/null @@ -1,115 +0,0 @@ -Subject: powerpc/pseries/iommu: Use a locallock instead local_irq_save() -From: Sebastian Andrzej Siewior -Date: Tue Mar 26 18:31:54 2019 +0100 -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -From: Sebastian Andrzej Siewior - -The locallock protects the per-CPU variable tce_page. The function -attempts to allocate memory while tce_page is protected (by disabling -interrupts). - -Use local_irq_save() instead of local_irq_disable(). - -Cc: stable-rt@vger.kernel.org -Signed-off-by: Sebastian Andrzej Siewior -Signed-off-by: Thomas Gleixner - - ---- - arch/powerpc/platforms/pseries/iommu.c | 31 ++++++++++++++++++++----------- - 1 file changed, 20 insertions(+), 11 deletions(-) ---- ---- a/arch/powerpc/platforms/pseries/iommu.c -+++ b/arch/powerpc/platforms/pseries/iommu.c -@@ -26,6 +26,7 @@ - #include - #include - #include -+#include - #include - #include - #include -@@ -244,7 +245,13 @@ static int tce_build_pSeriesLP(unsigned - return ret; - } - --static DEFINE_PER_CPU(__be64 *, tce_page); -+struct tce_page { -+ __be64 * page; -+ local_lock_t lock; -+}; -+static DEFINE_PER_CPU(struct tce_page, tce_page) = { -+ .lock = INIT_LOCAL_LOCK(lock), -+}; - - static int tce_buildmulti_pSeriesLP(struct iommu_table *tbl, long tcenum, - long npages, unsigned long uaddr, -@@ -267,9 +274,10 @@ static int tce_buildmulti_pSeriesLP(stru - direction, attrs); - } - -- local_irq_save(flags); /* to protect tcep and the page behind it */ -+ /* to protect tcep and the page behind it */ -+ local_lock_irqsave(&tce_page.lock, flags); - -- tcep = __this_cpu_read(tce_page); -+ tcep = __this_cpu_read(tce_page.page); - - /* This is safe to do since interrupts are off when we're called - * from iommu_alloc{,_sg}() -@@ -278,12 +286,12 @@ static int tce_buildmulti_pSeriesLP(stru - tcep = (__be64 *)__get_free_page(GFP_ATOMIC); - /* If allocation fails, fall back to the loop implementation */ - if (!tcep) { -- local_irq_restore(flags); -+ local_unlock_irqrestore(&tce_page.lock, flags); - return tce_build_pSeriesLP(tbl->it_index, tcenum, - tceshift, - npages, uaddr, direction, attrs); - } -- __this_cpu_write(tce_page, tcep); -+ __this_cpu_write(tce_page.page, tcep); - } - - rpn = __pa(uaddr) >> tceshift; -@@ -313,7 +321,7 @@ static int tce_buildmulti_pSeriesLP(stru - tcenum += limit; - } while (npages > 0 && !rc); - -- local_irq_restore(flags); -+ local_unlock_irqrestore(&tce_page.lock, flags); - - if (unlikely(rc == H_NOT_ENOUGH_RESOURCES)) { - ret = (int)rc; -@@ -497,16 +505,17 @@ static int tce_setrange_multi_pSeriesLP( - DMA_BIDIRECTIONAL, 0); - } - -- local_irq_disable(); /* to protect tcep and the page behind it */ -- tcep = __this_cpu_read(tce_page); -+ /* to protect tcep and the page behind it */ -+ local_lock_irq(&tce_page.lock); -+ tcep = __this_cpu_read(tce_page.page); - - if (!tcep) { - tcep = (__be64 *)__get_free_page(GFP_ATOMIC); - if (!tcep) { -- local_irq_enable(); -+ local_unlock_irq(&tce_page.lock); - return -ENOMEM; - } -- __this_cpu_write(tce_page, tcep); -+ __this_cpu_write(tce_page.page, tcep); - } - - proto_tce = TCE_PCI_READ | TCE_PCI_WRITE; -@@ -549,7 +558,7 @@ static int tce_setrange_multi_pSeriesLP( - - /* error cleanup: caller will clear whole range */ - -- local_irq_enable(); -+ local_unlock_irq(&tce_page.lock); - return rc; - } - diff --git a/debian/patches-rt/powerpc_stackprotector__work_around_stack-guard_init_from_atomic.patch b/debian/patches-rt/powerpc_stackprotector__work_around_stack-guard_init_from_atomic.patch deleted file mode 100644 index 2168a4a..0000000 --- a/debian/patches-rt/powerpc_stackprotector__work_around_stack-guard_init_from_atomic.patch +++ /dev/null @@ -1,37 +0,0 @@ -Subject: powerpc/stackprotector: work around stack-guard init from atomic -From: Sebastian Andrzej Siewior -Date: Tue Mar 26 18:31:29 2019 +0100 -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -From: Sebastian Andrzej Siewior - -This is invoked from the secondary CPU in atomic context. On x86 we use -tsc instead. On Power we XOR it against mftb() so lets use stack address -as the initial value. - -Cc: stable-rt@vger.kernel.org -Signed-off-by: Sebastian Andrzej Siewior -Signed-off-by: Thomas Gleixner - - ---- - arch/powerpc/include/asm/stackprotector.h | 7 ++++++- - 1 file changed, 6 insertions(+), 1 deletion(-) ---- ---- a/arch/powerpc/include/asm/stackprotector.h -+++ b/arch/powerpc/include/asm/stackprotector.h -@@ -19,8 +19,13 @@ - */ - static __always_inline void boot_init_stack_canary(void) - { -- unsigned long canary = get_random_canary(); -+ unsigned long canary; - -+#ifndef CONFIG_PREEMPT_RT -+ canary = get_random_canary(); -+#else -+ canary = ((unsigned long)&canary) & CANARY_MASK; -+#endif - current->stack_canary = canary; - #ifdef CONFIG_PPC64 - get_paca()->canary = canary; diff --git a/debian/patches-rt/rcutorture-Also-force-sched-priority-to-timersd-on-b.patch b/debian/patches-rt/rcutorture-Also-force-sched-priority-to-timersd-on-b.patch deleted file mode 100644 index dedd360..0000000 --- a/debian/patches-rt/rcutorture-Also-force-sched-priority-to-timersd-on-b.patch +++ /dev/null @@ -1,71 +0,0 @@ -From: Frederic Weisbecker -Date: Tue, 5 Apr 2022 03:07:51 +0200 -Subject: [PATCH] rcutorture: Also force sched priority to timersd on - boosting test. -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -ksoftirqd is statically boosted to the priority level right above the -one of rcu_torture_boost() so that timers, which torture readers rely on, -get a chance to run while rcu_torture_boost() is polling. - -However timers processing got split from ksoftirqd into their own kthread -(timersd) that isn't boosted. It has the same SCHED_FIFO low prio as -rcu_torture_boost() and therefore timers can't preempt it and may -starve. - -The issue can be triggered in practice on v5.17.1-rt17 using: - - ./kvm.sh --allcpus --configs TREE04 --duration 10m --kconfig "CONFIG_EXPERT=y CONFIG_PREEMPT_RT=y" - -Fix this with statically boosting timersd just like is done with -ksoftirqd in commit - ea6d962e80b61 ("rcutorture: Judge RCU priority boosting on grace periods, not callbacks") - -Suggested-by: Mel Gorman -Cc: Sebastian Andrzej Siewior -Cc: Thomas Gleixner -Signed-off-by: Frederic Weisbecker -Link: https://lkml.kernel.org/r/20220405010752.1347437-1-frederic@kernel.org -Signed-off-by: Sebastian Andrzej Siewior ---- - include/linux/interrupt.h | 1 + - kernel/rcu/rcutorture.c | 6 ++++++ - kernel/softirq.c | 2 +- - 3 files changed, 8 insertions(+), 1 deletion(-) - ---- a/include/linux/interrupt.h -+++ b/include/linux/interrupt.h -@@ -617,6 +617,7 @@ extern void raise_softirq_irqoff(unsigne - extern void raise_softirq(unsigned int nr); - - #ifdef CONFIG_PREEMPT_RT -+DECLARE_PER_CPU(struct task_struct *, timersd); - extern void raise_timer_softirq(void); - extern void raise_hrtimer_softirq(void); - ---- a/kernel/rcu/rcutorture.c -+++ b/kernel/rcu/rcutorture.c -@@ -2425,6 +2425,12 @@ static int rcutorture_booster_init(unsig - WARN_ON_ONCE(!t); - sp.sched_priority = 2; - sched_setscheduler_nocheck(t, SCHED_FIFO, &sp); -+#ifdef CONFIG_PREEMPT_RT -+ t = per_cpu(timersd, cpu); -+ WARN_ON_ONCE(!t); -+ sp.sched_priority = 2; -+ sched_setscheduler_nocheck(t, SCHED_FIFO, &sp); -+#endif - } - - /* Don't allow time recalculation while creating a new task. */ ---- a/kernel/softirq.c -+++ b/kernel/softirq.c -@@ -625,7 +625,7 @@ static inline void tick_irq_exit(void) - } - - #ifdef CONFIG_PREEMPT_RT --static DEFINE_PER_CPU(struct task_struct *, timersd); -+DEFINE_PER_CPU(struct task_struct *, timersd); - static DEFINE_PER_CPU(unsigned long, pending_timer_softirq); - - static unsigned int local_pending_timers(void) diff --git a/debian/patches-rt/riscv-add-PREEMPT_AUTO-support.patch b/debian/patches-rt/riscv-add-PREEMPT_AUTO-support.patch deleted file mode 100644 index ac3094e..0000000 --- a/debian/patches-rt/riscv-add-PREEMPT_AUTO-support.patch +++ /dev/null @@ -1,44 +0,0 @@ -From: Jisheng Zhang -Date: Tue, 31 Oct 2023 22:35:20 +0800 -Subject: [PATCH] riscv: add PREEMPT_AUTO support -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -riscv has switched to GENERIC_ENTRY, so adding PREEMPT_AUTO is as simple -as adding TIF_ARCH_RESCHED_LAZY related definitions and enabling -HAVE_PREEMPT_AUTO. - -Signed-off-by: Jisheng Zhang -Signed-off-by: Sebastian Andrzej Siewior ---- - arch/riscv/Kconfig | 1 + - arch/riscv/include/asm/thread_info.h | 2 ++ - 2 files changed, 3 insertions(+) - ---- a/arch/riscv/Kconfig -+++ b/arch/riscv/Kconfig -@@ -170,6 +170,7 @@ config RISCV - select HAVE_PERF_USER_STACK_DUMP - select HAVE_POSIX_CPU_TIMERS_TASK_WORK - select HAVE_PREEMPT_DYNAMIC_KEY if !XIP_KERNEL -+ select HAVE_PREEMPT_AUTO - select HAVE_REGS_AND_STACK_ACCESS_API - select HAVE_RETHOOK if !XIP_KERNEL - select HAVE_RSEQ ---- a/arch/riscv/include/asm/thread_info.h -+++ b/arch/riscv/include/asm/thread_info.h -@@ -95,6 +95,7 @@ int arch_dup_task_struct(struct task_str - * - pending work-to-be-done flags are in lowest half-word - * - other flags in upper half-word(s) - */ -+#define TIF_ARCH_RESCHED_LAZY 0 /* Lazy rescheduling */ - #define TIF_NOTIFY_RESUME 1 /* callback before returning to user */ - #define TIF_SIGPENDING 2 /* signal pending */ - #define TIF_NEED_RESCHED 3 /* rescheduling necessary */ -@@ -105,6 +106,7 @@ int arch_dup_task_struct(struct task_str - #define TIF_32BIT 11 /* compat-mode 32bit process */ - #define TIF_RISCV_V_DEFER_RESTORE 12 /* restore Vector before returing to user */ - -+#define _TIF_ARCH_RESCHED_LAZY (1 << TIF_ARCH_RESCHED_LAZY) - #define _TIF_NOTIFY_RESUME (1 << TIF_NOTIFY_RESUME) - #define _TIF_SIGPENDING (1 << TIF_SIGPENDING) - #define _TIF_NEED_RESCHED (1 << TIF_NEED_RESCHED) diff --git a/debian/patches-rt/riscv-allow-to-enable-RT.patch b/debian/patches-rt/riscv-allow-to-enable-RT.patch deleted file mode 100644 index c5c941c..0000000 --- a/debian/patches-rt/riscv-allow-to-enable-RT.patch +++ /dev/null @@ -1,23 +0,0 @@ -From: Jisheng Zhang -Date: Tue, 31 Oct 2023 22:35:21 +0800 -Subject: [PATCH] riscv: allow to enable RT -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -Now, it's ready to enable RT on riscv. - -Signed-off-by: Jisheng Zhang -Signed-off-by: Sebastian Andrzej Siewior ---- - arch/riscv/Kconfig | 1 + - 1 file changed, 1 insertion(+) - ---- a/arch/riscv/Kconfig -+++ b/arch/riscv/Kconfig -@@ -64,6 +64,7 @@ config RISCV - select ARCH_SUPPORTS_LTO_CLANG_THIN if LLD_VERSION >= 140000 - select ARCH_SUPPORTS_PAGE_TABLE_CHECK if MMU - select ARCH_SUPPORTS_PER_VMA_LOCK if MMU -+ select ARCH_SUPPORTS_RT - select ARCH_SUPPORTS_SHADOW_CALL_STACK if HAVE_SHADOW_CALL_STACK - select ARCH_USE_CMPXCHG_LOCKREF if 64BIT - select ARCH_USE_MEMTEST diff --git a/debian/patches-rt/sched-rt-Don-t-try-push-tasks-if-there-are-none.patch b/debian/patches-rt/sched-rt-Don-t-try-push-tasks-if-there-are-none.patch deleted file mode 100644 index 122fe72..0000000 --- a/debian/patches-rt/sched-rt-Don-t-try-push-tasks-if-there-are-none.patch +++ /dev/null @@ -1,58 +0,0 @@ -From: Sebastian Andrzej Siewior -Date: Tue, 1 Aug 2023 17:26:48 +0200 -Subject: [PATCH] sched/rt: Don't try push tasks if there are none. -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -I have a RT task X at a high priority and cyclictest on each CPU with -lower priority than X's. If X is active and each CPU wakes their own -cylictest thread then it ends in a longer rto_push storm. -A random CPU determines via balance_rt() that the CPU on which X is -running needs to push tasks. X has the highest priority, cyclictest is -next in line so there is nothing that can be done since the task with -the higher priority is not touched. - -tell_cpu_to_push() increments rto_loop_next and schedules -rto_push_irq_work_func() on X's CPU. The other CPUs also increment the -loop counter and do the same. Once rto_push_irq_work_func() is active it -does nothing because it has _no_ pushable tasks on its runqueue. Then -checks rto_next_cpu() and decides to queue irq_work on the local CPU -because another CPU requested a push by incrementing the counter. - -I have traces where ~30 CPUs request this ~3 times each before it -finally ends. This greatly increases X's runtime while X isn't making -much progress. - -Teach rto_next_cpu() to only return CPUs which also have tasks on their -runqueue which can be pushed away. This does not reduce the -tell_cpu_to_push() invocations (rto_loop_next counter increments) but -reduces the amount of issued rto_push_irq_work_func() if nothing can be -done. As the result the overloaded CPU is blocked less often. - -There are still cases where the "same job" is repeated several times -(for instance the current CPU needs to resched but didn't yet because -the irq-work is repeated a few times and so the old task remains on the -CPU) but the majority of request end in tell_cpu_to_push() before an IPI -is issued. - -Reviewed-by: "Steven Rostedt (Google)" -Link: https://lore.kernel.org/r/20230801152648._y603AS_@linutronix.de -Signed-off-by: Sebastian Andrzej Siewior ---- - kernel/sched/rt.c | 5 ++++- - 1 file changed, 4 insertions(+), 1 deletion(-) - ---- a/kernel/sched/rt.c -+++ b/kernel/sched/rt.c -@@ -2193,8 +2193,11 @@ static int rto_next_cpu(struct root_doma - - rd->rto_cpu = cpu; - -- if (cpu < nr_cpu_ids) -+ if (cpu < nr_cpu_ids) { -+ if (!has_pushable_tasks(cpu_rq(cpu))) -+ continue; - return cpu; -+ } - - rd->rto_cpu = -1; - diff --git a/debian/patches-rt/series b/debian/patches-rt/series deleted file mode 100644 index 314fce9..0000000 --- a/debian/patches-rt/series +++ /dev/null @@ -1,166 +0,0 @@ -# Applied upstream - -########################################################################### -# Posted and applied -########################################################################### - -########################################################################### -# Posted -########################################################################### - -########################################################################### -# John's printk queue -########################################################################### -# printk-for-6.12 from the printk tree. -0001-printk-Add-notation-to-console_srcu-locking.patch -0002-printk-nbcon-Consolidate-alloc-and-init.patch -0003-printk-Properly-deal-with-nbcon-consoles-on-seq-init.patch -0004-printk-Check-printk_deferred_enter-_exit-usage.patch -0005-printk-nbcon-Clarify-rules-of-the-owner-waiter-match.patch -0006-printk-nbcon-Remove-return-value-for-write_atomic.patch -0007-printk-nbcon-Add-detailed-doc-for-write_atomic.patch -0008-printk-nbcon-Add-callbacks-to-synchronize-with-drive.patch -0009-printk-nbcon-Use-driver-synchronization-while-un-reg.patch -0010-serial-core-Provide-low-level-functions-to-lock-port.patch -0011-serial-core-Introduce-wrapper-to-set-uart_port-cons.patch -0012-console-Improve-console_srcu_read_flags-comments.patch -0013-nbcon-Add-API-to-acquire-context-for-non-printing-op.patch -0014-serial-core-Acquire-nbcon-context-in-port-lock-wrapp.patch -0015-printk-nbcon-Do-not-rely-on-proxy-headers.patch -0016-printk-Make-console_is_usable-available-to-nbcon.c.patch -0017-printk-Let-console_is_usable-handle-nbcon.patch -0018-printk-Add-flags-argument-for-console_is_usable.patch -0019-printk-nbcon-Add-helper-to-assign-priority-based-on-.patch -0020-printk-nbcon-Provide-function-to-flush-using-write_a.patch -0021-printk-Track-registered-boot-consoles.patch -0022-printk-nbcon-Use-nbcon-consoles-in-console_flush_all.patch -0023-printk-Add-is_printk_legacy_deferred.patch -0024-printk-nbcon-Flush-new-records-on-device_release.patch -0025-printk-Flush-nbcon-consoles-first-on-panic.patch -0026-printk-nbcon-Add-unsafe-flushing-on-panic.patch -0027-printk-Avoid-console_lock-dance-if-no-legacy-or-boot.patch -0028-printk-Track-nbcon-consoles.patch -0029-printk-Coordinate-direct-printing-in-panic.patch -0030-printk-Add-helper-for-flush-type-logic.patch -0031-printk-nbcon-Implement-emergency-sections.patch -0032-panic-Mark-emergency-section-in-warn.patch -0033-panic-Mark-emergency-section-in-oops.patch -0034-rcu-Mark-emergency-sections-in-rcu-stalls.patch -0035-lockdep-Mark-emergency-sections-in-lockdep-splats.patch -0036-printk-Use-the-BITS_PER_LONG-macro.patch -0037-printk-nbcon-Use-raw_cpu_ptr-instead-of-open-coding.patch -0038-printk-nbcon-Add-function-for-printers-to-reacquire-.patch -0039-printk-Fail-pr_flush-if-before-SYSTEM_SCHEDULING.patch -0040-printk-Flush-console-on-unregister_console.patch -0041-printk-nbcon-Add-context-to-usable-and-emit.patch -0042-printk-nbcon-Init-nbcon_seq-to-highest-possible.patch -0043-printk-nbcon-Introduce-printer-kthreads.patch -0044-printk-nbcon-Relocate-nbcon_atomic_emit_one.patch -0045-printk-nbcon-Use-thread-callback-if-in-task-context-.patch -0046-printk-nbcon-Rely-on-kthreads-for-normal-operation.patch -0047-printk-Provide-helper-for-message-prepending.patch -0048-printk-nbcon-Show-replay-message-on-takeover.patch -0049-proc-consoles-Add-notation-to-c_start-c_stop.patch -0050-proc-Add-nbcon-support-for-proc-consoles.patch -0051-tty-sysfs-Add-nbcon-support-for-active.patch -0052-printk-Implement-legacy-printer-kthread-for-PREEMPT_.patch -0053-printk-nbcon-Assign-nice-20-for-printing-threads.patch -0054-printk-Avoid-false-positive-lockdep-report-for-legac.patch -# Atomic console -0053-serial-8250-Switch-to-nbcon-console.patch -0054-serial-8250-Revert-drop-lockdep-annotation-from-seri.patch - -########################################################################### -# Post -########################################################################### - -########################################################################### -# Enabling -########################################################################### -x86__Allow_to_enable_RT.patch -x86__Enable_RT_also_on_32bit.patch -ARM64__Allow_to_enable_RT.patch -riscv-allow-to-enable-RT.patch - -########################################################################### -# For later, not essencial -########################################################################### -# Posted -sched-rt-Don-t-try-push-tasks-if-there-are-none.patch - -# sparse -0001-locking-rt-Add-sparse-annotation-PREEMPT_RT-s-sleepi.patch -0002-locking-rt-Remove-one-__cond_lock-in-RT-s-spin_trylo.patch -0003-locking-rt-Add-sparse-annotation-for-RCU.patch -0004-locking-rt-Annotate-unlock-followed-by-lock-for-spar.patch -0001-timers-Add-sparse-annotation-for-timer_sync_wait_run.patch -0002-hrtimer-Annotate-hrtimer_cpu_base_.-_expiry-for-spar.patch - -# Needs discussion first. -softirq-Use-a-dedicated-thread-for-timer-wakeups.patch -rcutorture-Also-force-sched-priority-to-timersd-on-b.patch -tick-Fix-timer-storm-since-introduction-of-timersd.patch -softirq-Wake-ktimers-thread-also-in-softirq.patch - -# zram -0001-zram-Replace-bit-spinlocks-with-a-spinlock_t.patch -0002-zram-Remove-ZRAM_LOCK.patch -0003-zram-Shrink-zram_table_entry-flags.patch - -# Sched -0001-sched-core-Provide-a-method-to-check-if-a-task-is-PI.patch -0002-softirq-Add-function-to-preempt-serving-softirqs.patch -0003-time-Allow-to-preempt-after-a-callback.patch - -# Net -netfilter-nft_counter-Use-u64_stats_t-for-statistic.patch -########################################################################### -# DRM: -########################################################################### -# https://lore.kernel.org/all/20240613102818.4056866-1-bigeasy@linutronix.de/ -0001-drm-i915-Use-preempt_disable-enable_rt-where-recomme.patch -0002-drm-i915-Don-t-disable-interrupts-on-PREEMPT_RT-duri.patch -0003-drm-i915-Don-t-check-for-atomic-context-on-PREEMPT_R.patch -0004-drm-i915-Disable-tracing-points-on-PREEMPT_RT.patch -0005-drm-i915-gt-Use-spin_lock_irq-instead-of-local_irq_d.patch -0006-drm-i915-Drop-the-irqs_disabled-check.patch -0007-drm-i915-guc-Consider-also-RCU-depth-in-busy-loop.patch -0008-Revert-drm-i915-Depend-on-PREEMPT_RT.patch - -# Lazy preemption -PREEMPT_AUTO.patch - -########################################################################### -# ARM -########################################################################### -0001-arm-Disable-jump-label-on-PREEMPT_RT.patch -ARM__enable_irq_in_translation_section_permission_fault_handlers.patch -arm-Disable-FAST_GUP-on-PREEMPT_RT-if-HIGHPTE-is-als.patch -0001-ARM-vfp-Provide-vfp_lock-for-VFP-locking.patch -0002-ARM-vfp-Use-vfp_lock-in-vfp_sync_hwstate.patch -0003-ARM-vfp-Use-vfp_lock-in-vfp_support_entry.patch -0004-ARM-vfp-Move-sending-signals-outside-of-vfp_lock-ed-.patch -ARM__Allow_to_enable_RT.patch - -########################################################################### -# POWERPC -########################################################################### -powerpc__traps__Use_PREEMPT_RT.patch -powerpc_pseries_iommu__Use_a_locallock_instead_local_irq_save.patch -powerpc-pseries-Select-the-generic-memory-allocator.patch -powerpc_kvm__Disable_in-kernel_MPIC_emulation_for_PREEMPT_RT.patch -powerpc_stackprotector__work_around_stack-guard_init_from_atomic.patch -POWERPC__Allow_to_enable_RT.patch - -########################################################################### -# RISC-V -########################################################################### -riscv-add-PREEMPT_AUTO-support.patch - -# Sysfs file vs uname() -v -sysfs__Add__sys_kernel_realtime_entry.patch - -########################################################################### -# RT release version -########################################################################### -Add_localversion_for_-RT_release.patch diff --git a/debian/patches-rt/softirq-Use-a-dedicated-thread-for-timer-wakeups.patch b/debian/patches-rt/softirq-Use-a-dedicated-thread-for-timer-wakeups.patch deleted file mode 100644 index 4cfb1ab..0000000 --- a/debian/patches-rt/softirq-Use-a-dedicated-thread-for-timer-wakeups.patch +++ /dev/null @@ -1,222 +0,0 @@ -From: Sebastian Andrzej Siewior -Date: Wed, 1 Dec 2021 17:41:09 +0100 -Subject: [PATCH] softirq: Use a dedicated thread for timer wakeups. -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -A timer/hrtimer softirq is raised in-IRQ context. With threaded -interrupts enabled or on PREEMPT_RT this leads to waking the ksoftirqd -for the processing of the softirq. -Once the ksoftirqd is marked as pending (or is running) it will collect -all raised softirqs. This in turn means that a softirq which would have -been processed at the end of the threaded interrupt, which runs at an -elevated priority, is now moved to ksoftirqd which runs at SCHED_OTHER -priority and competes with every regular task for CPU resources. -This introduces long delays on heavy loaded systems and is not desired -especially if the system is not overloaded by the softirqs. - -Split the TIMER_SOFTIRQ and HRTIMER_SOFTIRQ processing into a dedicated -timers thread and let it run at the lowest SCHED_FIFO priority. -RT tasks are are woken up from hardirq context so only timer_list timers -and hrtimers for "regular" tasks are processed here. The higher priority -ensures that wakeups are performed before scheduling SCHED_OTHER tasks. - -Using a dedicated variable to store the pending softirq bits values -ensure that the timer are not accidentally picked up by ksoftirqd and -other threaded interrupts. -It shouldn't be picked up by ksoftirqd since it runs at lower priority. -However if the timer bits are ORed while a threaded interrupt is -running, then the timer softirq would be performed at higher priority. -The new timer thread will block on the softirq lock before it starts -softirq work. This "race window" isn't closed because while timer thread -is performing the softirq it can get PI-boosted via the softirq lock by -a random force-threaded thread. -The timer thread can pick up pending softirqs from ksoftirqd but only -if the softirq load is high. It is not be desired that the picked up -softirqs are processed at SCHED_FIFO priority under high softirq load -but this can already happen by a PI-boost by a force-threaded interrupt. - -Reported-by: kernel test robot [ static timer_threads ] -Signed-off-by: Sebastian Andrzej Siewior ---- - include/linux/interrupt.h | 16 ++++++++ - kernel/softirq.c | 92 ++++++++++++++++++++++++++++++++++++++++++++-- - kernel/time/hrtimer.c | 4 +- - kernel/time/timer.c | 2 - - 4 files changed, 108 insertions(+), 6 deletions(-) - ---- a/include/linux/interrupt.h -+++ b/include/linux/interrupt.h -@@ -616,6 +616,22 @@ extern void __raise_softirq_irqoff(unsig - extern void raise_softirq_irqoff(unsigned int nr); - extern void raise_softirq(unsigned int nr); - -+#ifdef CONFIG_PREEMPT_RT -+extern void raise_timer_softirq(void); -+extern void raise_hrtimer_softirq(void); -+ -+#else -+static inline void raise_timer_softirq(void) -+{ -+ raise_softirq(TIMER_SOFTIRQ); -+} -+ -+static inline void raise_hrtimer_softirq(void) -+{ -+ raise_softirq_irqoff(HRTIMER_SOFTIRQ); -+} -+#endif -+ - DECLARE_PER_CPU(struct task_struct *, ksoftirqd); - - static inline struct task_struct *this_cpu_ksoftirqd(void) ---- a/kernel/softirq.c -+++ b/kernel/softirq.c -@@ -624,6 +624,29 @@ static inline void tick_irq_exit(void) - #endif - } - -+#ifdef CONFIG_PREEMPT_RT -+static DEFINE_PER_CPU(struct task_struct *, timersd); -+static DEFINE_PER_CPU(unsigned long, pending_timer_softirq); -+ -+static unsigned int local_pending_timers(void) -+{ -+ return __this_cpu_read(pending_timer_softirq); -+} -+ -+static void wake_timersd(void) -+{ -+ struct task_struct *tsk = __this_cpu_read(timersd); -+ -+ if (tsk) -+ wake_up_process(tsk); -+} -+ -+#else -+ -+static inline void wake_timersd(void) { } -+ -+#endif -+ - static inline void __irq_exit_rcu(void) - { - #ifndef __ARCH_IRQ_EXIT_IRQS_DISABLED -@@ -633,8 +656,13 @@ static inline void __irq_exit_rcu(void) - #endif - account_hardirq_exit(current); - preempt_count_sub(HARDIRQ_OFFSET); -- if (!in_interrupt() && local_softirq_pending()) -- invoke_softirq(); -+ if (!in_interrupt()) { -+ if (local_softirq_pending()) -+ invoke_softirq(); -+ -+ if (IS_ENABLED(CONFIG_PREEMPT_RT) && local_pending_timers()) -+ wake_timersd(); -+ } - - tick_irq_exit(); - } -@@ -972,12 +1000,70 @@ static struct smp_hotplug_thread softirq - .thread_comm = "ksoftirqd/%u", - }; - -+#ifdef CONFIG_PREEMPT_RT -+static void timersd_setup(unsigned int cpu) -+{ -+ sched_set_fifo_low(current); -+} -+ -+static int timersd_should_run(unsigned int cpu) -+{ -+ return local_pending_timers(); -+} -+ -+static void run_timersd(unsigned int cpu) -+{ -+ unsigned int timer_si; -+ -+ ksoftirqd_run_begin(); -+ -+ timer_si = local_pending_timers(); -+ __this_cpu_write(pending_timer_softirq, 0); -+ or_softirq_pending(timer_si); -+ -+ __do_softirq(); -+ -+ ksoftirqd_run_end(); -+} -+ -+static void raise_ktimers_thread(unsigned int nr) -+{ -+ trace_softirq_raise(nr); -+ __this_cpu_or(pending_timer_softirq, 1 << nr); -+} -+ -+void raise_hrtimer_softirq(void) -+{ -+ raise_ktimers_thread(HRTIMER_SOFTIRQ); -+} -+ -+void raise_timer_softirq(void) -+{ -+ unsigned long flags; -+ -+ local_irq_save(flags); -+ raise_ktimers_thread(TIMER_SOFTIRQ); -+ wake_timersd(); -+ local_irq_restore(flags); -+} -+ -+static struct smp_hotplug_thread timer_threads = { -+ .store = &timersd, -+ .setup = timersd_setup, -+ .thread_should_run = timersd_should_run, -+ .thread_fn = run_timersd, -+ .thread_comm = "ktimers/%u", -+}; -+#endif -+ - static __init int spawn_ksoftirqd(void) - { - cpuhp_setup_state_nocalls(CPUHP_SOFTIRQ_DEAD, "softirq:dead", NULL, - takeover_tasklets); - BUG_ON(smpboot_register_percpu_thread(&softirq_threads)); -- -+#ifdef CONFIG_PREEMPT_RT -+ BUG_ON(smpboot_register_percpu_thread(&timer_threads)); -+#endif - return 0; - } - early_initcall(spawn_ksoftirqd); ---- a/kernel/time/hrtimer.c -+++ b/kernel/time/hrtimer.c -@@ -1811,7 +1811,7 @@ void hrtimer_interrupt(struct clock_even - if (!ktime_before(now, cpu_base->softirq_expires_next)) { - cpu_base->softirq_expires_next = KTIME_MAX; - cpu_base->softirq_activated = 1; -- raise_softirq_irqoff(HRTIMER_SOFTIRQ); -+ raise_hrtimer_softirq(); - } - - __hrtimer_run_queues(cpu_base, now, flags, HRTIMER_ACTIVE_HARD); -@@ -1906,7 +1906,7 @@ void hrtimer_run_queues(void) - if (!ktime_before(now, cpu_base->softirq_expires_next)) { - cpu_base->softirq_expires_next = KTIME_MAX; - cpu_base->softirq_activated = 1; -- raise_softirq_irqoff(HRTIMER_SOFTIRQ); -+ raise_hrtimer_softirq(); - } - - __hrtimer_run_queues(cpu_base, now, flags, HRTIMER_ACTIVE_HARD); ---- a/kernel/time/timer.c -+++ b/kernel/time/timer.c -@@ -2467,7 +2467,7 @@ static void run_local_timers(void) - /* Raise the softirq only if required. */ - if (time_after_eq(jiffies, base->next_expiry) || - (i == BASE_DEF && tmigr_requires_handle_remote())) { -- raise_softirq(TIMER_SOFTIRQ); -+ raise_timer_softirq(); - return; - } - } diff --git a/debian/patches-rt/softirq-Wake-ktimers-thread-also-in-softirq.patch b/debian/patches-rt/softirq-Wake-ktimers-thread-also-in-softirq.patch deleted file mode 100644 index 4d5b83f..0000000 --- a/debian/patches-rt/softirq-Wake-ktimers-thread-also-in-softirq.patch +++ /dev/null @@ -1,44 +0,0 @@ -From: Junxiao Chang -Date: Mon, 20 Feb 2023 09:12:20 +0100 -Subject: [PATCH] softirq: Wake ktimers thread also in softirq. -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -If the hrtimer is raised while a softirq is processed then it does not -wake the corresponding ktimers thread. This is due to the optimisation in the -irq-exit path which is also used to wake the ktimers thread. For the other -softirqs, this is okay because the additional softirq bits will be handled by -the currently running softirq handler. -The timer related softirq bits are added to a different variable and rely on -the ktimers thread. -As a consuequence the wake up of ktimersd is delayed until the next timer tick. - -Always wake the ktimers thread if a timer related softirq is pending. - -Reported-by: Peh, Hock Zhang -Signed-off-by: Junxiao Chang -Signed-off-by: Sebastian Andrzej Siewior ---- - kernel/softirq.c | 11 +++++------ - 1 file changed, 5 insertions(+), 6 deletions(-) - ---- a/kernel/softirq.c -+++ b/kernel/softirq.c -@@ -651,13 +651,12 @@ static inline void __irq_exit_rcu(void) - #endif - account_hardirq_exit(current); - preempt_count_sub(HARDIRQ_OFFSET); -- if (!in_interrupt()) { -- if (local_softirq_pending()) -- invoke_softirq(); -+ if (!in_interrupt() && local_softirq_pending()) -+ invoke_softirq(); - -- if (IS_ENABLED(CONFIG_PREEMPT_RT) && local_pending_timers()) -- wake_timersd(); -- } -+ if (IS_ENABLED(CONFIG_PREEMPT_RT) && local_pending_timers() && -+ !(in_nmi() | in_hardirq())) -+ wake_timersd(); - - tick_irq_exit(); - } diff --git a/debian/patches-rt/sysfs__Add__sys_kernel_realtime_entry.patch b/debian/patches-rt/sysfs__Add__sys_kernel_realtime_entry.patch deleted file mode 100644 index a77c862..0000000 --- a/debian/patches-rt/sysfs__Add__sys_kernel_realtime_entry.patch +++ /dev/null @@ -1,53 +0,0 @@ -Subject: sysfs: Add /sys/kernel/realtime entry -From: Clark Williams -Date: Sat Jul 30 21:55:53 2011 -0500 -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -From: Clark Williams - -Add a /sys/kernel entry to indicate that the kernel is a -realtime kernel. - -Clark says that he needs this for udev rules, udev needs to evaluate -if its a PREEMPT_RT kernel a few thousand times and parsing uname -output is too slow or so. - -Are there better solutions? Should it exist and return 0 on !-rt? - -Signed-off-by: Clark Williams -Signed-off-by: Peter Zijlstra -Signed-off-by: Thomas Gleixner - - ---- - kernel/ksysfs.c | 12 ++++++++++++ - 1 file changed, 12 insertions(+) ---- ---- a/kernel/ksysfs.c -+++ b/kernel/ksysfs.c -@@ -188,6 +188,15 @@ KERNEL_ATTR_RO(crash_elfcorehdr_size); - - #endif /* CONFIG_VMCORE_INFO */ - -+#if defined(CONFIG_PREEMPT_RT) -+static ssize_t realtime_show(struct kobject *kobj, -+ struct kobj_attribute *attr, char *buf) -+{ -+ return sprintf(buf, "%d\n", 1); -+} -+KERNEL_ATTR_RO(realtime); -+#endif -+ - /* whether file capabilities are enabled */ - static ssize_t fscaps_show(struct kobject *kobj, - struct kobj_attribute *attr, char *buf) -@@ -286,6 +295,9 @@ static struct attribute * kernel_attrs[] - &rcu_expedited_attr.attr, - &rcu_normal_attr.attr, - #endif -+#ifdef CONFIG_PREEMPT_RT -+ &realtime_attr.attr, -+#endif - NULL - }; - diff --git a/debian/patches-rt/tick-Fix-timer-storm-since-introduction-of-timersd.patch b/debian/patches-rt/tick-Fix-timer-storm-since-introduction-of-timersd.patch deleted file mode 100644 index 37d5761..0000000 --- a/debian/patches-rt/tick-Fix-timer-storm-since-introduction-of-timersd.patch +++ /dev/null @@ -1,106 +0,0 @@ -From: Frederic Weisbecker -Date: Tue, 5 Apr 2022 03:07:52 +0200 -Subject: [PATCH] tick: Fix timer storm since introduction of timersd -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -If timers are pending while the tick is reprogrammed on nohz_mode, the -next expiry is not armed to fire now, it is delayed one jiffy forward -instead so as not to raise an inextinguishable timer storm with such -scenario: - -1) IRQ triggers and queue a timer -2) ksoftirqd() is woken up -3) IRQ tail: timer is reprogrammed to fire now -4) IRQ exit -5) TIMER interrupt -6) goto 3) - -...all that until we finally reach ksoftirqd. - -Unfortunately we are checking the wrong softirq vector bitmask since -timersd kthread has split from ksoftirqd. Timers now have their own -vector state field that must be checked separately. As a result, the -old timer storm is back. This shows up early on boot with extremely long -initcalls: - - [ 333.004807] initcall dquot_init+0x0/0x111 returned 0 after 323822879 usecs - -and the cause is uncovered with the right trace events showing just -10 microseconds between ticks (~100 000 Hz): - -|swapper/-1 1dn.h111 60818582us : hrtimer_expire_entry: hrtimer=00000000e0ef0f6b function=tick_sched_timer now=60415486608 -|swapper/-1 1dn.h111 60818592us : hrtimer_expire_entry: hrtimer=00000000e0ef0f6b function=tick_sched_timer now=60415496082 -|swapper/-1 1dn.h111 60818601us : hrtimer_expire_entry: hrtimer=00000000e0ef0f6b function=tick_sched_timer now=60415505550 - -Fix this by checking the right timer vector state from the nohz code. - -Signed-off-by: Frederic Weisbecker -Cc: Mel Gorman -Cc: Sebastian Andrzej Siewior -Cc: Thomas Gleixner -Signed-off-by: Sebastian Andrzej Siewior -Link: https://lkml.kernel.org/r/20220405010752.1347437-2-frederic@kernel.org ---- - include/linux/interrupt.h | 12 ++++++++++++ - kernel/softirq.c | 7 +------ - kernel/time/tick-sched.c | 2 +- - 3 files changed, 14 insertions(+), 7 deletions(-) - ---- a/include/linux/interrupt.h -+++ b/include/linux/interrupt.h -@@ -618,9 +618,16 @@ extern void raise_softirq(unsigned int n - - #ifdef CONFIG_PREEMPT_RT - DECLARE_PER_CPU(struct task_struct *, timersd); -+DECLARE_PER_CPU(unsigned long, pending_timer_softirq); -+ - extern void raise_timer_softirq(void); - extern void raise_hrtimer_softirq(void); - -+static inline unsigned int local_pending_timers(void) -+{ -+ return __this_cpu_read(pending_timer_softirq); -+} -+ - #else - static inline void raise_timer_softirq(void) - { -@@ -631,6 +638,11 @@ static inline void raise_hrtimer_softirq - { - raise_softirq_irqoff(HRTIMER_SOFTIRQ); - } -+ -+static inline unsigned int local_pending_timers(void) -+{ -+ return local_softirq_pending(); -+} - #endif - - DECLARE_PER_CPU(struct task_struct *, ksoftirqd); ---- a/kernel/softirq.c -+++ b/kernel/softirq.c -@@ -626,12 +626,7 @@ static inline void tick_irq_exit(void) - - #ifdef CONFIG_PREEMPT_RT - DEFINE_PER_CPU(struct task_struct *, timersd); --static DEFINE_PER_CPU(unsigned long, pending_timer_softirq); -- --static unsigned int local_pending_timers(void) --{ -- return __this_cpu_read(pending_timer_softirq); --} -+DEFINE_PER_CPU(unsigned long, pending_timer_softirq); - - static void wake_timersd(void) - { ---- a/kernel/time/tick-sched.c -+++ b/kernel/time/tick-sched.c -@@ -859,7 +859,7 @@ static void tick_nohz_restart(struct tic - - static inline bool local_timer_softirq_pending(void) - { -- return local_softirq_pending() & BIT(TIMER_SOFTIRQ); -+ return local_pending_timers() & BIT(TIMER_SOFTIRQ); - } - - /* diff --git a/debian/patches-rt/x86__Allow_to_enable_RT.patch b/debian/patches-rt/x86__Allow_to_enable_RT.patch deleted file mode 100644 index 0b56e19..0000000 --- a/debian/patches-rt/x86__Allow_to_enable_RT.patch +++ /dev/null @@ -1,27 +0,0 @@ -Subject: x86: Allow to enable RT -From: Sebastian Andrzej Siewior -Date: Wed Aug 7 18:15:38 2019 +0200 -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -From: Sebastian Andrzej Siewior - -Allow to select RT. - -Signed-off-by: Sebastian Andrzej Siewior -Signed-off-by: Thomas Gleixner - - ---- - arch/x86/Kconfig | 1 + - 1 file changed, 1 insertion(+) ---- ---- a/arch/x86/Kconfig -+++ b/arch/x86/Kconfig -@@ -28,6 +28,7 @@ config X86_64 - select ARCH_HAS_GIGANTIC_PAGE - select ARCH_SUPPORTS_INT128 if CC_HAS_INT128 - select ARCH_SUPPORTS_PER_VMA_LOCK -+ select ARCH_SUPPORTS_RT - select HAVE_ARCH_SOFT_DIRTY - select MODULES_USE_ELF_RELA - select NEED_DMA_MAP_STATE diff --git a/debian/patches-rt/x86__Enable_RT_also_on_32bit.patch b/debian/patches-rt/x86__Enable_RT_also_on_32bit.patch deleted file mode 100644 index b654850..0000000 --- a/debian/patches-rt/x86__Enable_RT_also_on_32bit.patch +++ /dev/null @@ -1,25 +0,0 @@ -Subject: x86: Enable RT also on 32bit -From: Sebastian Andrzej Siewior -Date: Thu Nov 7 17:49:20 2019 +0100 -Origin: https://www.kernel.org/pub/linux/kernel/projects/rt/6.11/older/patches-6.11-rt7.tar.xz - -From: Sebastian Andrzej Siewior - -Signed-off-by: Sebastian Andrzej Siewior -Signed-off-by: Thomas Gleixner - - ---- - arch/x86/Kconfig | 1 + - 1 file changed, 1 insertion(+) ---- ---- a/arch/x86/Kconfig -+++ b/arch/x86/Kconfig -@@ -123,6 +123,7 @@ config X86 - select ARCH_USES_CFI_TRAPS if X86_64 && CFI_CLANG - select ARCH_SUPPORTS_LTO_CLANG - select ARCH_SUPPORTS_LTO_CLANG_THIN -+ select ARCH_SUPPORTS_RT - select ARCH_USE_BUILTIN_BSWAP - select ARCH_USE_CMPXCHG_LOCKREF if X86_CMPXCHG64 - select ARCH_USE_MEMTEST diff --git a/debian/source/include-binaries b/debian/source/include-binaries index 76f94eb..e69de29 100644 --- a/debian/source/include-binaries +++ b/debian/source/include-binaries @@ -1 +0,0 @@ -debian/upstream/rt-signing-key.pgp diff --git a/debian/upstream/rt-signing-key.pgp b/debian/upstream/rt-signing-key.pgp deleted file mode 100644 index 6ba4cb0fdd67aa22d1f5f86eb5c0ee725be8d3d2..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 84522 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 z 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