]> git.ipfire.org Git - thirdparty/kernel/linux.git/commitdiff
Merge tag 'arm64-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64...
authorLinus Torvalds <torvalds@linux-foundation.org>
Tue, 14 Apr 2026 23:48:56 +0000 (16:48 -0700)
committerLinus Torvalds <torvalds@linux-foundation.org>
Tue, 14 Apr 2026 23:48:56 +0000 (16:48 -0700)
Pull arm64 updates from Catalin Marinas:
 "The biggest changes are MPAM enablement in drivers/resctrl and new PMU
  support under drivers/perf.

  On the core side, FEAT_LSUI lets futex atomic operations with EL0
  permissions, avoiding PAN toggling.

  The rest is mostly TLB invalidation refactoring, further generic entry
  work, sysreg updates and a few fixes.

  Core features:

   - Add support for FEAT_LSUI, allowing futex atomic operations without
     toggling Privileged Access Never (PAN)

   - Further refactor the arm64 exception handling code towards the
     generic entry infrastructure

   - Optimise __READ_ONCE() with CONFIG_LTO=y and allow alias analysis
     through it

  Memory management:

   - Refactor the arm64 TLB invalidation API and implementation for
     better control over barrier placement and level-hinted invalidation

   - Enable batched TLB flushes during memory hot-unplug

   - Fix rodata=full block mapping support for realm guests (when
     BBML2_NOABORT is available)

  Perf and PMU:

   - Add support for a whole bunch of system PMUs featured in NVIDIA's
     Tegra410 SoC (cspmu extensions for the fabric and PCIe, new drivers
     for CPU/C2C memory latency PMUs)

   - Clean up iomem resource handling in the Arm CMN driver

   - Fix signedness handling of AA64DFR0.{PMUVer,PerfMon}

  MPAM (Memory Partitioning And Monitoring):

   - Add architecture context-switch and hiding of the feature from KVM

   - Add interface to allow MPAM to be exposed to user-space using
     resctrl

   - Add errata workaround for some existing platforms

   - Add documentation for using MPAM and what shape of platforms can
     use resctrl

  Miscellaneous:

   - Check DAIF (and PMR, where relevant) at task-switch time

   - Skip TFSR_EL1 checks and barriers in synchronous MTE tag check mode
     (only relevant to asynchronous or asymmetric tag check modes)

   - Remove a duplicate allocation in the kexec code

   - Remove redundant save/restore of SCS SP on entry to/from EL0

   - Generate the KERNEL_HWCAP_ definitions from the arm64 hwcap
     descriptions

   - Add kselftest coverage for cmpbr_sigill()

   - Update sysreg definitions"

* tag 'arm64-upstream' of git://git.kernel.org/pub/scm/linux/kernel/git/arm64/linux: (109 commits)
  arm64: rsi: use linear-map alias for realm config buffer
  arm64: Kconfig: fix duplicate word in CMDLINE help text
  arm64: mte: Skip TFSR_EL1 checks and barriers in synchronous tag check mode
  arm64/sysreg: Update ID_AA64SMFR0_EL1 description to DDI0601 2025-12
  arm64/sysreg: Update ID_AA64ZFR0_EL1 description to DDI0601 2025-12
  arm64/sysreg: Update ID_AA64FPFR0_EL1 description to DDI0601 2025-12
  arm64/sysreg: Update ID_AA64ISAR2_EL1 description to DDI0601 2025-12
  arm64/sysreg: Update ID_AA64ISAR0_EL1 description to DDI0601 2025-12
  arm64/hwcap: Generate the KERNEL_HWCAP_ definitions for the hwcaps
  arm64: kexec: Remove duplicate allocation for trans_pgd
  ACPI: AGDI: fix missing newline in error message
  arm64: Check DAIF (and PMR) at task-switch time
  arm64: entry: Use split preemption logic
  arm64: entry: Use irqentry_{enter_from,exit_to}_kernel_mode()
  arm64: entry: Consistently prefix arm64-specific wrappers
  arm64: entry: Don't preempt with SError or Debug masked
  entry: Split preemption from irqentry_exit_to_kernel_mode()
  entry: Split kernel mode logic from irqentry_{enter,exit}()
  entry: Move irqentry_enter() prototype later
  entry: Remove local_irq_{enable,disable}_exit_to_user()
  ...

1  2 
arch/arm64/Kconfig
arch/arm64/include/asm/uaccess.h
arch/arm64/kernel/Makefile
arch/arm64/kernel/cpufeature.c
arch/arm64/kernel/rsi.c
arch/arm64/kvm/at.c
drivers/perf/arm_cspmu/arm_cspmu.c
drivers/resctrl/mpam_devices.c
include/linux/entry-common.h
include/linux/irq-entry-common.h
kernel/entry/common.c

Simple merge
Simple merge
Simple merge
Simple merge
index 9e846ce4ef9ca7c3781d9e98224647494f478713,6e883bc431864aa13db1f574a0a3bc0d6c5c3afe..92160f2e57ff7fc3ea91ceb1c49df4b521bb3b65
@@@ -145,9 -144,9 +145,9 @@@ void __init arm64_rsi_init(void
                return;
        if (!rsi_version_matches())
                return;
-       if (WARN_ON(rsi_get_realm_config(&config)))
+       if (WARN_ON(rsi_get_realm_config(lm_alias(&config))))
                return;
 -      prot_ns_shared = BIT(config.ipa_bits - 1);
 +      prot_ns_shared = __phys_to_pte_val(BIT(config.ipa_bits - 1));
  
        if (arm64_ioremap_prot_hook_register(realm_ioremap_hook))
                return;
index a024d9a770dc7419514b2b93f8dc9a3ec52cdf38,1adf88a5732840e93d45ebe11f4a6795dcd64710..9f8f0ae8e86e84c3e36f6b77d6b06f7bd3a8d2b6
@@@ -1753,8 -1785,10 +1783,10 @@@ int __kvm_at_swap_desc(struct kvm *kvm
        if (!writable)
                return -EPERM;
  
 -      ptep = (u64 __user *)hva + offset;
 +      ptep = (void __user *)hva + offset;
-       if (cpus_have_final_cap(ARM64_HAS_LSE_ATOMICS))
+       if (cpus_have_final_cap(ARM64_HAS_LSUI))
+               r = __lsui_swap_desc(ptep, old, new);
+       else if (cpus_have_final_cap(ARM64_HAS_LSE_ATOMICS))
                r = __lse_swap_desc(ptep, old, new);
        else
                r = __llsc_swap_desc(ptep, old, new);
Simple merge
Simple merge
Simple merge
index b976946b3cdbbef4b2f81f70d03046c3c1104d83,384520217bfe3af507211a266e968251ba2c1577..7ab41eec549fe6c88368053ca7b2223a4ee2b643
@@@ -378,6 -336,205 +349,207 @@@ typedef struct irqentry_state 
  } irqentry_state_t;
  #endif
  
+ /**
+  * irqentry_exit_cond_resched - Conditionally reschedule on return from interrupt
+  *
+  * Conditional reschedule with additional sanity checks.
+  */
+ void raw_irqentry_exit_cond_resched(void);
+ #ifdef CONFIG_PREEMPT_DYNAMIC
+ #if defined(CONFIG_HAVE_PREEMPT_DYNAMIC_CALL)
+ #define irqentry_exit_cond_resched_dynamic_enabled    raw_irqentry_exit_cond_resched
+ #define irqentry_exit_cond_resched_dynamic_disabled   NULL
+ DECLARE_STATIC_CALL(irqentry_exit_cond_resched, raw_irqentry_exit_cond_resched);
+ #define irqentry_exit_cond_resched()  static_call(irqentry_exit_cond_resched)()
+ #elif defined(CONFIG_HAVE_PREEMPT_DYNAMIC_KEY)
+ DECLARE_STATIC_KEY_TRUE(sk_dynamic_irqentry_exit_cond_resched);
+ void dynamic_irqentry_exit_cond_resched(void);
+ #define irqentry_exit_cond_resched()  dynamic_irqentry_exit_cond_resched()
+ #endif
+ #else /* CONFIG_PREEMPT_DYNAMIC */
+ #define irqentry_exit_cond_resched()  raw_irqentry_exit_cond_resched()
+ #endif /* CONFIG_PREEMPT_DYNAMIC */
+ /**
+  * irqentry_enter_from_kernel_mode - Establish state before invoking the irq handler
+  * @regs:     Pointer to currents pt_regs
+  *
+  * Invoked from architecture specific entry code with interrupts disabled.
+  * Can only be called when the interrupt entry came from kernel mode. The
+  * calling code must be non-instrumentable.  When the function returns all
+  * state is correct and the subsequent functions can be instrumented.
+  *
+  * The function establishes state (lockdep, RCU (context tracking), tracing) and
+  * is provided for architectures which require a strict split between entry from
+  * kernel and user mode and therefore cannot use irqentry_enter() which handles
+  * both entry modes.
+  *
+  * Returns: An opaque object that must be passed to irqentry_exit_to_kernel_mode().
+  */
+ static __always_inline irqentry_state_t irqentry_enter_from_kernel_mode(struct pt_regs *regs)
+ {
+       irqentry_state_t ret = {
+               .exit_rcu = false,
+       };
+       /*
+        * If this entry hit the idle task invoke ct_irq_enter() whether
+        * RCU is watching or not.
+        *
+        * Interrupts can nest when the first interrupt invokes softirq
+        * processing on return which enables interrupts.
+        *
+        * Scheduler ticks in the idle task can mark quiescent state and
+        * terminate a grace period, if and only if the timer interrupt is
+        * not nested into another interrupt.
+        *
+        * Checking for rcu_is_watching() here would prevent the nesting
+        * interrupt to invoke ct_irq_enter(). If that nested interrupt is
+        * the tick then rcu_flavor_sched_clock_irq() would wrongfully
+        * assume that it is the first interrupt and eventually claim
+        * quiescent state and end grace periods prematurely.
+        *
+        * Unconditionally invoke ct_irq_enter() so RCU state stays
+        * consistent.
+        *
+        * TINY_RCU does not support EQS, so let the compiler eliminate
+        * this part when enabled.
+        */
+       if (!IS_ENABLED(CONFIG_TINY_RCU) &&
+           (is_idle_task(current) || arch_in_rcu_eqs())) {
+               /*
+                * If RCU is not watching then the same careful
+                * sequence vs. lockdep and tracing is required
+                * as in irqentry_enter_from_user_mode().
+                */
+               lockdep_hardirqs_off(CALLER_ADDR0);
+               ct_irq_enter();
+               instrumentation_begin();
+               kmsan_unpoison_entry_regs(regs);
+               trace_hardirqs_off_finish();
+               instrumentation_end();
+               ret.exit_rcu = true;
+               return ret;
+       }
+       /*
+        * If RCU is watching then RCU only wants to check whether it needs
+        * to restart the tick in NOHZ mode. rcu_irq_enter_check_tick()
+        * already contains a warning when RCU is not watching, so no point
+        * in having another one here.
+        */
+       lockdep_hardirqs_off(CALLER_ADDR0);
+       instrumentation_begin();
+       kmsan_unpoison_entry_regs(regs);
+       rcu_irq_enter_check_tick();
+       trace_hardirqs_off_finish();
+       instrumentation_end();
+       return ret;
+ }
+ /**
+  * irqentry_exit_to_kernel_mode_preempt - Run preempt checks on return to kernel mode
+  * @regs:     Pointer to current's pt_regs
+  * @state:    Return value from matching call to irqentry_enter_from_kernel_mode()
+  *
+  * This is to be invoked before irqentry_exit_to_kernel_mode_after_preempt() to
+  * allow kernel preemption on return from interrupt.
+  *
+  * Must be invoked with interrupts disabled and CPU state which allows kernel
+  * preemption.
+  *
+  * After returning from this function, the caller can modify CPU state before
+  * invoking irqentry_exit_to_kernel_mode_after_preempt(), which is required to
+  * re-establish the tracing, lockdep and RCU state for returning to the
+  * interrupted context.
+  */
+ static inline void irqentry_exit_to_kernel_mode_preempt(struct pt_regs *regs,
+                                                       irqentry_state_t state)
+ {
+       if (regs_irqs_disabled(regs) || state.exit_rcu)
+               return;
+       if (IS_ENABLED(CONFIG_PREEMPTION))
+               irqentry_exit_cond_resched();
++
++      hrtimer_rearm_deferred();
+ }
+ /**
+  * irqentry_exit_to_kernel_mode_after_preempt - Establish trace, lockdep and RCU state
+  * @regs:     Pointer to current's pt_regs
+  * @state:    Return value from matching call to irqentry_enter_from_kernel_mode()
+  *
+  * This is to be invoked after irqentry_exit_to_kernel_mode_preempt() and before
+  * actually returning to the interrupted context.
+  *
+  * There are no requirements for the CPU state other than being able to complete
+  * the tracing, lockdep and RCU state transitions. After this function returns
+  * the caller must return directly to the interrupted context.
+  */
+ static __always_inline void
+ irqentry_exit_to_kernel_mode_after_preempt(struct pt_regs *regs, irqentry_state_t state)
+ {
+       if (!regs_irqs_disabled(regs)) {
+               /*
+                * If RCU was not watching on entry this needs to be done
+                * carefully and needs the same ordering of lockdep/tracing
+                * and RCU as the return to user mode path.
+                */
+               if (state.exit_rcu) {
+                       instrumentation_begin();
+                       /* Tell the tracer that IRET will enable interrupts */
+                       trace_hardirqs_on_prepare();
+                       lockdep_hardirqs_on_prepare();
+                       instrumentation_end();
+                       ct_irq_exit();
+                       lockdep_hardirqs_on(CALLER_ADDR0);
+                       return;
+               }
+               instrumentation_begin();
+               /* Covers both tracing and lockdep */
+               trace_hardirqs_on();
+               instrumentation_end();
+       } else {
+               /*
+                * IRQ flags state is correct already. Just tell RCU if it
+                * was not watching on entry.
+                */
+               if (state.exit_rcu)
+                       ct_irq_exit();
+       }
+ }
+ /**
+  * irqentry_exit_to_kernel_mode - Run preempt checks and establish state after
+  *                              invoking the interrupt handler
+  * @regs:     Pointer to current's pt_regs
+  * @state:    Return value from matching call to irqentry_enter_from_kernel_mode()
+  *
+  * This is the counterpart of irqentry_enter_from_kernel_mode() and combines
+  * the calls to irqentry_exit_to_kernel_mode_preempt() and
+  * irqentry_exit_to_kernel_mode_after_preempt().
+  *
+  * The requirement for the CPU state is that it can schedule. After the function
+  * returns the tracing, lockdep and RCU state transitions are completed and the
+  * caller must return directly to the interrupted context.
+  */
+ static __always_inline void irqentry_exit_to_kernel_mode(struct pt_regs *regs,
+                                                        irqentry_state_t state)
+ {
+       lockdep_assert_irqs_disabled();
+       instrumentation_begin();
+       irqentry_exit_to_kernel_mode_preempt(regs, state);
+       instrumentation_end();
+       irqentry_exit_to_kernel_mode_after_preempt(regs, state);
+ }
  /**
   * irqentry_enter - Handle state tracking on ordinary interrupt entries
   * @regs:     Pointer to pt_regs of interrupted context
index 9e1a6afb07f22358db4429536b9ee6db66f2fe8e,1034be02eae844f0547707d088caba5f67916698..19d2244a9fefc527a21a68e47c9a2862cf64c23f
@@@ -47,10 -47,10 +47,10 @@@ static __always_inline unsigned long __
         */
        while (ti_work & EXIT_TO_USER_MODE_WORK_LOOP) {
  
-               local_irq_enable_exit_to_user(ti_work);
+               local_irq_enable();
  
                if (ti_work & (_TIF_NEED_RESCHED | _TIF_NEED_RESCHED_LAZY)) {
 -                      if (!rseq_grant_slice_extension(ti_work & TIF_SLICE_EXT_DENY))
 +                      if (!rseq_grant_slice_extension(ti_work, TIF_SLICE_EXT_DENY))
                                schedule();
                }