use*_*363 3 linux arm linux-kernel embedded-linux
Linux支持运行32位应用程序,只要
CONFIG_COMPAT我假设32位应用程序必须在arm AArch32执行状态下运行,并且如果环境有32位应用程序和64位应用程序。
32位应用程序进程->arm状态为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-to- aarch64-in-software在0andriy(内核开发人员)的评论中发表了Martin Weidmann对 AArch32 用户空间进程和 AArch64 Linux 内核之间切换的解释。32->64模式切换是在异常时进行的;64->32 切换是在异常返回时完成的。
\n\n\n\n\n如果您当前正在运行 32 位应用程序之一,并且发生异常(例如,系统调用中的 IRQ、SVC、页面错误中止......),您将进入 64 位操作系统。所以 AArch32 --> AArch64 过渡。当操作系统执行异常返回到应用程序时,这是 AArch64-->AArch32 转换。...\n AArch32 状态中的任何异常类型都可能导致执行状态更改为 AArch64。...对于异常返回,则相反。AArch64 中的异常返回可能会导致执行状态更改为 AArch32。
\n
\n 对于异常和异常返回,只有当 EL 也发生变化时,才会发生执行状态的变化。从 EL0 到 EL1 的异常可能会导致执行状态发生变化。但从 EL1 到 EL1 的例外则不能。
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\n\n发生异常时,如果异常级别发生变化,执行状态可以: 保持不变,或从 AArch32 更改为 AArch64。
\n\n从异常返回时,如果异常级别发生变化,则执行状态可以: 保持不变,或从 AArch64 更改为 AArch32。
\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-states或https://www.realworldtech.com/arm64/2/:
\n\n\n\n\nAArch64 异常模型
\n\n\n
\n- 权限级别:EL3 \xe2\x80\x93 最高,EL0 \xe2\x80\x93 最低
\n- \n
通过例外过渡到更高级别
- \n
较低级别的寄存器宽度不能更大
- \n
\n
- 例如,没有 64 位 EL0,有 32 位 EL1
\n- 通过异常在 AArch32 和 AArch64 之间转换
\n- \n
\n
- AArch32/AArch64 无法互通
\n
现在回答您的问题:
\n\n\n\n\nLinux如何处理AArch32和AArch64切换?
\n
通过使用具有不同 PSTATE 值的 EL0/EL1 开关的异常处理(和返回)硬件功能。
\n\n\n\n\n内核是否知道正在运行的进程是32位还是64位?
\n
是的,在 64 位内核(兼容系统调用)上有 32 位进程(“任务”)的内核检查:arch/arm64/kernel/syscall.c
\n\nstatic 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}\nRun Code Online (Sandbox Code Playgroud)\n\n测试在include/asm/compat.h和arch/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}\nRun Code Online (Sandbox Code Playgroud)\n\nTIF_32BIT 在 fs/compat_binfmt_elf.c 中通过几个个性宏在 32 位 elf 加载上设置:
\n\nhttps://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 })\nRun Code Online (Sandbox Code Playgroud)\n\nhttps://elixir.bootlin.com/linux/v4.19.107/source/fs/compat_binfmt_elf.c#L104
\n\n #define SET_PERSONALITY COMPAT_SET_PERSONALITY\nRun Code Online (Sandbox Code Playgroud)\n\nhttps://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);\nRun Code Online (Sandbox Code Playgroud)\n
| 归档时间: |
|
| 查看次数: |
3379 次 |
| 最近记录: |