Back to home page

OSCL-LXR

 
 

    


0001 ======================
0002 Asymmetric 32-bit SoCs
0003 ======================
0004 
0005 Author: Will Deacon <will@kernel.org>
0006 
0007 This document describes the impact of asymmetric 32-bit SoCs on the
0008 execution of 32-bit (``AArch32``) applications.
0009 
0010 Date: 2021-05-17
0011 
0012 Introduction
0013 ============
0014 
0015 Some Armv9 SoCs suffer from a big.LITTLE misfeature where only a subset
0016 of the CPUs are capable of executing 32-bit user applications. On such
0017 a system, Linux by default treats the asymmetry as a "mismatch" and
0018 disables support for both the ``PER_LINUX32`` personality and
0019 ``execve(2)`` of 32-bit ELF binaries, with the latter returning
0020 ``-ENOEXEC``. If the mismatch is detected during late onlining of a
0021 64-bit-only CPU, then the onlining operation fails and the new CPU is
0022 unavailable for scheduling.
0023 
0024 Surprisingly, these SoCs have been produced with the intention of
0025 running legacy 32-bit binaries. Unsurprisingly, that doesn't work very
0026 well with the default behaviour of Linux.
0027 
0028 It seems inevitable that future SoCs will drop 32-bit support
0029 altogether, so if you're stuck in the unenviable position of needing to
0030 run 32-bit code on one of these transitionary platforms then you would
0031 be wise to consider alternatives such as recompilation, emulation or
0032 retirement. If neither of those options are practical, then read on.
0033 
0034 Enabling kernel support
0035 =======================
0036 
0037 Since the kernel support is not completely transparent to userspace,
0038 allowing 32-bit tasks to run on an asymmetric 32-bit system requires an
0039 explicit "opt-in" and can be enabled by passing the
0040 ``allow_mismatched_32bit_el0`` parameter on the kernel command-line.
0041 
0042 For the remainder of this document we will refer to an *asymmetric
0043 system* to mean an asymmetric 32-bit SoC running Linux with this kernel
0044 command-line option enabled.
0045 
0046 Userspace impact
0047 ================
0048 
0049 32-bit tasks running on an asymmetric system behave in mostly the same
0050 way as on a homogeneous system, with a few key differences relating to
0051 CPU affinity.
0052 
0053 sysfs
0054 -----
0055 
0056 The subset of CPUs capable of running 32-bit tasks is described in
0057 ``/sys/devices/system/cpu/aarch32_el0`` and is documented further in
0058 ``Documentation/ABI/testing/sysfs-devices-system-cpu``.
0059 
0060 **Note:** CPUs are advertised by this file as they are detected and so
0061 late-onlining of 32-bit-capable CPUs can result in the file contents
0062 being modified by the kernel at runtime. Once advertised, CPUs are never
0063 removed from the file.
0064 
0065 ``execve(2)``
0066 -------------
0067 
0068 On a homogeneous system, the CPU affinity of a task is preserved across
0069 ``execve(2)``. This is not always possible on an asymmetric system,
0070 specifically when the new program being executed is 32-bit yet the
0071 affinity mask contains 64-bit-only CPUs. In this situation, the kernel
0072 determines the new affinity mask as follows:
0073 
0074   1. If the 32-bit-capable subset of the affinity mask is not empty,
0075      then the affinity is restricted to that subset and the old affinity
0076      mask is saved. This saved mask is inherited over ``fork(2)`` and
0077      preserved across ``execve(2)`` of 32-bit programs.
0078 
0079      **Note:** This step does not apply to ``SCHED_DEADLINE`` tasks.
0080      See `SCHED_DEADLINE`_.
0081 
0082   2. Otherwise, the cpuset hierarchy of the task is walked until an
0083      ancestor is found containing at least one 32-bit-capable CPU. The
0084      affinity of the task is then changed to match the 32-bit-capable
0085      subset of the cpuset determined by the walk.
0086 
0087   3. On failure (i.e. out of memory), the affinity is changed to the set
0088      of all 32-bit-capable CPUs of which the kernel is aware.
0089 
0090 A subsequent ``execve(2)`` of a 64-bit program by the 32-bit task will
0091 invalidate the affinity mask saved in (1) and attempt to restore the CPU
0092 affinity of the task using the saved mask if it was previously valid.
0093 This restoration may fail due to intervening changes to the deadline
0094 policy or cpuset hierarchy, in which case the ``execve(2)`` continues
0095 with the affinity unchanged.
0096 
0097 Calls to ``sched_setaffinity(2)`` for a 32-bit task will consider only
0098 the 32-bit-capable CPUs of the requested affinity mask. On success, the
0099 affinity for the task is updated and any saved mask from a prior
0100 ``execve(2)`` is invalidated.
0101 
0102 ``SCHED_DEADLINE``
0103 ------------------
0104 
0105 Explicit admission of a 32-bit deadline task to the default root domain
0106 (e.g. by calling ``sched_setattr(2)``) is rejected on an asymmetric
0107 32-bit system unless admission control is disabled by writing -1 to
0108 ``/proc/sys/kernel/sched_rt_runtime_us``.
0109 
0110 ``execve(2)`` of a 32-bit program from a 64-bit deadline task will
0111 return ``-ENOEXEC`` if the root domain for the task contains any
0112 64-bit-only CPUs and admission control is enabled. Concurrent offlining
0113 of 32-bit-capable CPUs may still necessitate the procedure described in
0114 `execve(2)`_, in which case step (1) is skipped and a warning is
0115 emitted on the console.
0116 
0117 **Note:** It is recommended that a set of 32-bit-capable CPUs are placed
0118 into a separate root domain if ``SCHED_DEADLINE`` is to be used with
0119 32-bit tasks on an asymmetric system. Failure to do so is likely to
0120 result in missed deadlines.
0121 
0122 Cpusets
0123 -------
0124 
0125 The affinity of a 32-bit task on an asymmetric system may include CPUs
0126 that are not explicitly allowed by the cpuset to which it is attached.
0127 This can occur as a result of the following two situations:
0128 
0129   - A 64-bit task attached to a cpuset which allows only 64-bit CPUs
0130     executes a 32-bit program.
0131 
0132   - All of the 32-bit-capable CPUs allowed by a cpuset containing a
0133     32-bit task are offlined.
0134 
0135 In both of these cases, the new affinity is calculated according to step
0136 (2) of the process described in `execve(2)`_ and the cpuset hierarchy is
0137 unchanged irrespective of the cgroup version.
0138 
0139 CPU hotplug
0140 -----------
0141 
0142 On an asymmetric system, the first detected 32-bit-capable CPU is
0143 prevented from being offlined by userspace and any such attempt will
0144 return ``-EPERM``. Note that suspend is still permitted even if the
0145 primary CPU (i.e. CPU 0) is 64-bit-only.
0146 
0147 KVM
0148 ---
0149 
0150 Although KVM will not advertise 32-bit EL0 support to any vCPUs on an
0151 asymmetric system, a broken guest at EL1 could still attempt to execute
0152 32-bit code at EL0. In this case, an exit from a vCPU thread in 32-bit
0153 mode will return to host userspace with an ``exit_reason`` of
0154 ``KVM_EXIT_FAIL_ENTRY`` and will remain non-runnable until successfully
0155 re-initialised by a subsequent ``KVM_ARM_VCPU_INIT`` operation.