Linuxarm64如何在AArch32和AArch64之间切换

use*_*363 3 linux arm linux-kernel embedded-linux

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

  1. 内核启用CONFIG_COMPAT
  2. 硬件支持AArch32

我假设32位应用程序必须在arm AArch32执行状态下运行,并且如果环境有32位应用程序和64位应用程序。

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

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

这是对的吗?

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

osg*_*sgx 5

链接https://community.arm.com/developer/ip-products/processors/f/cortex-a-forum/6706/in-aarch32-state-what-is-the-mechanism-to-switch-to- aarch64-in-software0andriy内核开发人员)的评论中发表了Martin Weidmann对 AArch32 用户空间进程和 AArch64 Linux 内核之间切换的解释。32->64模式切换是在异常时进行的;64->32 切换是在异常返回时完成的。

\n\n
\n

如果您当前正在运行 32 位应用程序之一,并且发生异常(例如,系统调用中的 IRQ、SVC、页面错误中止......),您将进入 64 位操作系统。所以 AArch32 --> AArch64 过渡。当操作系统执行异常返回到应用程序时,这是 AArch64-->AArch32 转换。...\n AArch32 状态中的任何异常类型都可能导致执行状态更改为 AArch64。...对于异常返回,则相反。AArch64 中的异常返回可能会导致执行状态更改为 AArch32。
\n 对于异常和异常返回,只有当 EL 也发生变化时,才会发生执行状态的变化。从 EL0 到 EL1 的异常可能会导致执行状态发生变化。但从 EL1 到 EL1 的例外则不能。

\n
\n\n

https://community.arm.com/developer/ip-products/processors/f/cortex-a-forum/6706/in-aarch32-state-what-is-the-mechanism-to-switch-to-aarch64 ​-in-software线程有一些更多细节。或者https://medium.com/@om.nara/aarch64-exception-levels-60d3a74280e6中的“在 AArch32 和 AArch64 之间移动”中有更简单的解释

\n\n
\n

发生异常时,如果异常级别发生变化,执行状态可以: 保持不变,或从 AArch32 更改为 AArch64。

\n\n

从异常返回时,如果异常级别发生变化,则执行状态可以: 保持不变,或从 AArch64 更改为 AArch32。

\n
\n\n

与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-stateshttps://www.realworldtech.com/arm64/2/

\n\n
\n

AArch64 异常模型

\n\n
    \n
  • 权限级别:EL3 \xe2\x80\x93 最高,EL0 \xe2\x80\x93 最低
  • \n
  • 通过例外过渡到更高级别

  • \n
  • 较低级别的寄存器宽度不能更大

  • \n
    • \n
    • 例如,没有 64 位 EL0,有 32 位 EL1
    • \n
  • \n
  • 通过异常在 AArch32 和 AArch64 之间转换
  • \n
    • \n
    • AArch32/AArch64 无法互通
    • \n
  • \n
\n
\n\n

现在回答您的问题:

\n\n
\n

Linux如何处理AArch32和AArch64切换?

\n
\n\n

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

\n\n
\n

内核是否知道正在运行的进程是32位还是64位?

\n
\n\n

是的,在 64 位内核(兼容系统调用)上有 32 位进程(“任务”)的内核检查:arch/arm64/kernel/syscall.c

\n\n
static long do_ni_syscall(struct pt_regs *regs, int scno)\n{\n#ifdef CONFIG_COMPAT\n    long ret;\n    if (is_compat_task()) {\n        ret = compat_arm_syscall(regs, scno);\n        if (ret != -ENOSYS)\n            return ret;\n    }\n#endif\n\n    return sys_ni_syscall();\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n\n
#define TIF_32BIT       22  /* 32bit process */\nstatic inline int is_compat_task(void)\n{\n    return test_thread_flag(TIF_32BIT);\n}\n
Run Code Online (Sandbox Code Playgroud)\n\n

TIF_32BIT 在 fs/compat_binfmt_elf.c 中通过几个个性宏在 32 位 elf 加载上设置:

\n\n

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

\n\n
/*\n * Unlike the native SET_PERSONALITY macro, the compat version maintains\n * READ_IMPLIES_EXEC across an execve() since this is the behaviour on\n * arch/arm/.\n */\n#define COMPAT_SET_PERSONALITY(ex)                  \\\n({                                  \\\n    set_thread_flag(TIF_32BIT);                 \\\n })\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n\n
 #define    SET_PERSONALITY     COMPAT_SET_PERSONALITY\n
Run Code Online (Sandbox Code Playgroud)\n\n

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

\n\n
#define SET_PERSONALITY2(ex, state) \\\n    SET_PERSONALITY(ex)\n static int load_elf_binary(struct linux_binprm *bprm)\n    SET_PERSONALITY2(loc->elf_ex, &arch_state);\n
Run Code Online (Sandbox Code Playgroud)\n