ANDROID: arm64: Handle AArch32 tasks running on non AArch32 cpu

On Asym AArch32 system, if a tasks tries to run on unsupported CPU, we
fix up the cpumask silently to make sure tasks aren't killed if placed
on a CPU without AArch32 support

This patch can be omitted if user-space can guarantee the cpumask of
all AArch32 apps only contains AArch32 capable CPUs.

The biggest danger is in apps who try to modify their own cpu affinity
via sched_setaffinity(). Without this change they could trigger
a SIGKILL if they unknowingly affine to the wrong CPU.

Without this patch user-space must ensure that any 32bit app is cloned
into a cpuset cgroup that will restrict it to aarch32 capable cpus.
clone3 syscall allows specifying the cgroup on fork.

Split from Catalin's original patch to support Asym AArch32 systems.
Only modified cpumask_t to become cpumask_var_t in
set_32bit_cpus_allowed().

Bug: 168847043
Reason: Needed for bringup. Revert when upstream patch is available
Signed-off-by: Qais Yousef <qais.yousef@arm.com>
Change-Id: If520cbf5cd705fb0e0399f36b81d4a68e90beb3a
This commit is contained in:
Qais Yousef
2020-09-15 11:42:28 +01:00
committed by Todd Kjos
parent 8a2a23717d
commit cacae105ed
2 changed files with 29 additions and 10 deletions

View File

@@ -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.

View File

@@ -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)