diff --git a/arch/arm64/Kconfig b/arch/arm64/Kconfig index 16f9cf01fe21..f8a96aa5f794 100644 --- a/arch/arm64/Kconfig +++ b/arch/arm64/Kconfig @@ -1895,10 +1895,9 @@ config ASYMMETRIC_AARCH32 Enable this option to allow support for asymmetric AArch32 EL0 CPU configurations. Once the AArch32 EL0 support is detected on a CPU, the feature is made available to user space to allow - the execution of 32-bit (compat) applications. If the affinity - of the 32-bit application contains a non-AArch32 capable CPU - or the last AArch32 capable CPU is offlined, the application - will be killed. + the execution of 32-bit (compat) applications by migrating + them to the capable CPUs. Offlining such CPUs leads to 32-bit + applications being killed. If unsure say N. diff --git a/arch/arm64/kernel/signal.c b/arch/arm64/kernel/signal.c index 68c13bcaf974..d7f4623fa208 100644 --- a/arch/arm64/kernel/signal.c +++ b/arch/arm64/kernel/signal.c @@ -912,14 +912,34 @@ static void do_signal(struct pt_regs *regs) restore_saved_sigmask(); } -static void check_aarch32_cpumask(void) +static void set_32bit_cpus_allowed(void) { + int ret; + /* - * The task must be a subset of aarch32_el0_mask or it could end up - * migrating and running on the wrong CPU. + * Try to honour as best as possible whatever affinity request this + * task has. If it spans no compatible CPU, disregard it entirely. */ - if (!cpumask_subset(current->cpus_ptr, &aarch32_el0_mask)) { - pr_warn_once("CPU affinity contains CPUs that are not capable of running 32-bit tasks\n"); + if (cpumask_intersects(current->cpus_ptr, &aarch32_el0_mask)) { + cpumask_var_t cpus_allowed; + + if (!alloc_cpumask_var(&cpus_allowed, GFP_ATOMIC)) { + + ret = set_cpus_allowed_ptr(current, &aarch32_el0_mask); + + } else { + + cpumask_and(cpus_allowed, current->cpus_ptr, &aarch32_el0_mask); + ret = set_cpus_allowed_ptr(current, cpus_allowed); + free_cpumask_var(cpus_allowed); + + } + } else { + ret = set_cpus_allowed_ptr(current, &aarch32_el0_mask); + } + + if (ret) { + pr_warn_once("No CPUs capable of running 32-bit tasks\n"); force_sig(SIGKILL); } } @@ -949,7 +969,7 @@ asmlinkage void do_notify_resume(struct pt_regs *regs, if (IS_ENABLED(CONFIG_ASYMMETRIC_AARCH32) && thread_flags & _TIF_CHECK_32BIT_AFFINITY) { clear_thread_flag(TIF_CHECK_32BIT_AFFINITY); - check_aarch32_cpumask(); + set_32bit_cpus_allowed(); } if (thread_flags & _TIF_UPROBE)