Linux arm64如何在AArch32和AArch64之间切换

How Linux arm64 switch between AArch32 and AArch64

Linux支持运行32位应用程序,只要

  • 内核启用CONFIG_COMPAT
  • 硬件支持AArch32
  • 我假定32位应用程序必须在arm AArch32执行状态下运行,并且该环境具有32位应用程序和64位应用程序。

    32位应用程序->臂状态为AArch32

    64位应用程序进程和内核-> arm状态为AArch64

    是否正确?

    如果是这样,
    Linux如何处理AArch32和AArch64开关?
    内核是否知道正在运行的进程是32位还是64位?


    链接https://community.arm.com/developer/ip-products/processors/f/cortex-a-forum/6706/in-aarch32-state-what-is-the-mechanism-to-switch 0andriy(内核开发人员)在评论中发布的" to-aarch64-in-in-software"解释了Martin Weidmann在AArch32用户空间进程和AArch64 Linux内核之间进行切换的说明。在例外情况下完成了32-> 64模式切换;并且在异常返回时完成了64-> 32切换。

    If you are currently running one of the 32-bit apps and you take an exception (e.g. IRQ, SVC from a system call, abort from a page fault,....) you enter the 64-bit OS. So a AArch32 --> AArch64 transition. When the OS performs an exception return back into the app, that's an AArch64-->AArch32 transition. ...
    Any exception type in AArch32 state could potentially lead to Execution state changing to AArch64. ... For exceptions returns the reverse is true. An exception return in AArch64 might cause execution state to change to AArch32.
    For both exceptions and exception returns, a change of Execution state can only occur if there is also a change in EL. That is an exception from EL0 to EL1 could lead to a change in Execution state. But an exception from EL1 to EL1 could not.

    https://community.arm.com/developer/ip-products/processors/f/cortex-a-forum/6706/in-aarch32-state-what-is-the-mechanism-to-switch-软件中的to-aarch64线程具有更多详细信息。或者在"在AArch32和AArch64之间移动"

    中,https://medium.com/@om.nara/aarch64-exception-levels-60d3a74280e6中有更简单的解释。

    On taking an exception, if the Exception level changes, the Execution state can: Remain unchanged, OR Change from AArch32 to AArch64.

    On returning from an exception, if the Exception level changes, the Execution state can: Remain unchanged, OR Change from AArch64 to AArch32.

    与https://events.static.linuxfound.org/images/stories/pdf/lcna_co2012_marinas.pdf演示文稿(幻灯片5)或https://developer.arm.com/architectures/learn-the-architecture中的内容相同/ exception-model / execution-and-security-states或https://www.realworldtech.com/arm64/2/:

    AArch64 Exception Model

    • Privilege levels: EL3 – highest, EL0 – lowest
    • Transition to higher levels via exceptions

    • Register width cannot be higher in lower levels

      • E.g. no 64-bit EL0 with 32-bit EL1
    • Transition between AArch32 and AArch64 via exceptions
      • AArch32/AArch64 interworking not possible

    现在提出您的问题:

    how does the Linux handle the AArch32 and AArch64 switch?

    通过使用具有不同PSTATE值的EL0 / EL1开关的异常处理(和返回)的硬件功能。

    Does the kernel know the running process is 32-bit or 64-bit?

    是的,在64位内核(compat syscalls)上有32位进程("任务")的签入内核:arch / arm64 / kernel / syscall.c

    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    static long do_ni_syscall(struct pt_regs *regs, int scno)
    {
    #ifdef CONFIG_COMPAT
        long ret;
        if (is_compat_task()) {
            ret = compat_arm_syscall(regs, scno);
            if (ret != -ENOSYS)
                return ret;
        }
    #endif

        return sys_ni_syscall();
    }

    测试在include / asm / compat.h和arch / arm64 / include / asm / thread_info.h中定义为

    1
    2
    3
    4
    5
    #define TIF_32BIT       22  /* 32bit process */
    static inline int is_compat_task(void)
    {
        return test_thread_flag(TIF_32BIT);
    }

    TIF_32BIT由fs / compat_binfmt_elf.c在具有一些个性宏的32位elf加载中设置:

    https://elixir.bootlin.com/linux/v4.19.107/source/arch/arm64/include/asm/elf.h#L208

    1
    2
    3
    4
    5
    6
    7
    8
    9
    /*
     * Unlike the native SET_PERSONALITY macro, the compat version maintains
     * READ_IMPLIES_EXEC across an execve() since this is the behaviour on
     * arch/arm/.
     */
    #define COMPAT_SET_PERSONALITY(ex)                  \\
    ({                                  \\
        set_thread_flag(TIF_32BIT);                 \\
     })

    https://elixir.bootlin.com/linux/v4.19.107/source/fs/compat_binfmt_elf.c#L104

    1
     #define    SET_PERSONALITY     COMPAT_SET_PERSONALITY

    https://elixir.bootlin.com/linux/v4.19.107/source/fs/binfmt_elf.c#L690

    1
    2
    3
    4
    #define SET_PERSONALITY2(ex, state) \\
        SET_PERSONALITY(ex)
     static int load_elf_binary(struct linux_binprm *bprm)
        SET_PERSONALITY2(loc->elf_ex, &arch_state);