On Wed, Dec 11, 2024 at 04:40:23PM +0100, Frederic Weisbecker wrote: > When a kthread or any other task has an affinity mask that is fully > offline or unallowed, the scheduler reaffines the task to all possible > CPUs as a last resort. > > This default decision doesn't mix up very well with nohz_full CPUs that > are part of the possible cpumask but don't want to be disturbed by > unbound kthreads or even detached pinned user tasks. > > Make the fallback affinity setting aware of nohz_full. > > Suggested-by: Michal Hocko <mhocko@xxxxxxxx> > Signed-off-by: Frederic Weisbecker <frederic@xxxxxxxxxx> > --- > arch/arm64/include/asm/cpufeature.h | 1 + > arch/arm64/include/asm/mmu_context.h | 2 ++ > arch/arm64/kernel/cpufeature.c | 11 +++++++++++ > include/linux/mmu_context.h | 1 + > kernel/sched/core.c | 2 +- > 5 files changed, 16 insertions(+), 1 deletion(-) > > diff --git a/arch/arm64/include/asm/cpufeature.h b/arch/arm64/include/asm/cpufeature.h > index 8b4e5a3cd24c..cac5efc836c0 100644 > --- a/arch/arm64/include/asm/cpufeature.h > +++ b/arch/arm64/include/asm/cpufeature.h > @@ -671,6 +671,7 @@ static inline bool supports_clearbhb(int scope) > } > > const struct cpumask *system_32bit_el0_cpumask(void); > +const struct cpumask *fallback_32bit_el0_cpumask(void); > DECLARE_STATIC_KEY_FALSE(arm64_mismatched_32bit_el0); > > static inline bool system_supports_32bit_el0(void) > diff --git a/arch/arm64/include/asm/mmu_context.h b/arch/arm64/include/asm/mmu_context.h > index 48b3d9553b67..7883abd6b29a 100644 > --- a/arch/arm64/include/asm/mmu_context.h > +++ b/arch/arm64/include/asm/mmu_context.h > @@ -283,6 +283,8 @@ task_cpu_possible_mask(struct task_struct *p) > } > #define task_cpu_possible_mask task_cpu_possible_mask > > +const struct cpumask *task_cpu_fallback_mask(struct task_struct *p); > + > void verify_cpu_asid_bits(void); > void post_ttbr_update_workaround(void); > > diff --git a/arch/arm64/kernel/cpufeature.c b/arch/arm64/kernel/cpufeature.c > index 7ce1b8ab417f..2b7aa32bf436 100644 > --- a/arch/arm64/kernel/cpufeature.c > +++ b/arch/arm64/kernel/cpufeature.c > @@ -1642,6 +1642,17 @@ const struct cpumask *system_32bit_el0_cpumask(void) > return cpu_possible_mask; > } > > +const struct cpumask *task_cpu_fallback_mask(struct task_struct *p) > +{ > + if (!static_branch_unlikely(&arm64_mismatched_32bit_el0)) > + return housekeeping_cpumask(HK_TYPE_TICK); > + > + if (!is_compat_thread(task_thread_info(p))) > + return housekeeping_cpumask(HK_TYPE_TICK); > + > + return system_32bit_el0_cpumask(); > +} I think this is correct, but damn what we really want to ask for is the intersection of task_cpu_possible_mask(p) and housekeeping_cpumask(HK_TYPE_TICK). It's a shame to duplicate the logic in task_cpu_possible_mask() here because we don't want to allocate a temporary mask. Maybe we could have a helper to consolidate things a little? static inline const struct cpumask * __task_cpu_possible_mask(struct task_struct *p, const struct cpumask *mask) { if (!static_branch_unlikely(&arm64_mismatched_32bit_el0)) return mask; if (!is_compat_thread(task_thread_info(p))) return mask; return system_32bit_el0_cpumask(); } Then we could call that from both task_cpu_possible_mask() and task_cpu_fallback_mask(), but passing 'cpu_possible_mask' and housekeeping_cpumask(HK_TYPE_TICK) for the 'mask' argument respectively? Will