linux - Linux arm64 如何在 AArch32 和 AArch64 之间切换
问题描述
Linux 支持运行 32 位应用程序,只要
- 内核启用
CONFIG_COMPAT
- 硬件支持 AArch32
我假设 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- 0andriy(内核开发人员)在评论中发布的aarch64-in-software解释了Martin Weidmann在 AArch32 用户空间进程和 AArch64 linux 内核之间的切换。32->64模式切换在异常情况下完成;并且 64->32 切换在异常返回时完成。
如果您当前正在运行其中一个 32 位应用程序并且您遇到异常(例如 IRQ、来自系统调用的 SVC、因页面错误而中止......)您进入 64 位操作系统。所以一个 AArch32 --> AArch64 转换。当操作系统执行异常返回到应用程序时,这是一个 AArch64-->AArch32 转换。... AArch32 状态中的任何异常类型都可能导致执行状态更改为 AArch64。...对于异常返回,反之亦然。AArch64 中的异常返回可能会导致执行状态更改为 AArch32。
对于异常和异常返回,只有在 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线程有更多细节。或者在“在 AArch32 和 AArch64 之间移动”中的https://medium.com/@om.nara/aarch64-exception-levels-60d3a74280e6中有更简单的解释
在发生异常时,如果异常级别发生变化,则执行状态可以:保持不变,或从 AArch32 更改为 AArch64。
从异常返回时,如果异常级别发生更改,则执行状态可以:保持不变,或从 AArch64 更改为 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 异常模型
- 特权等级:EL3 – 最高,EL0 – 最低
通过异常过渡到更高级别
较低级别的寄存器宽度不能更高
- 例如,没有 64 位 EL0 和 32 位 EL1
- 通过异常在 AArch32 和 AArch64 之间转换
- AArch32/AArch64 互通不可能
现在为您的问题:
Linux 如何处理 AArch32 和 AArch64 开关?
通过使用具有不同 PSTATE 值的 EL0/EL1 开关的异常处理(和返回)的硬件能力。
内核是否知道正在运行的进程是 32 位还是 64 位?
是的,在 64 位内核(兼容系统调用)上检查 32 位进程(“任务”)的内核:arch/arm64/kernel/syscall.c
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中定义为
#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
/*
* 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
#define SET_PERSONALITY COMPAT_SET_PERSONALITY
https://elixir.bootlin.com/linux/v4.19.107/source/fs/binfmt_elf.c#L690
#define SET_PERSONALITY2(ex, state) \
SET_PERSONALITY(ex)
static int load_elf_binary(struct linux_binprm *bprm)
SET_PERSONALITY2(loc->elf_ex, &arch_state);
推荐阅读
- mysql - 数据插入后如何为sql表创建索引号列?
- android - 事件总线订阅事件未调用
- java - properties-maven-plugin 未正确设置系统属性
- r - 带有特殊字符的变量名
- java - 大型测试用例失败:创建字符串回文所需的最少字符数
- android - Android DarkMode textColor 在 RecyclerView 的行文件中没有改变
- r - 根据 3 列更改值
- java - Jacoco exec 文件总是出现 EOFException
- apache-spark - 通过 Airflow 调度在 Kubernetes 上运行的 Spark 作业
- apache-kafka-streams - Spring Cloud Stream 将值生成为包含 JSON 而不仅仅是 JSON 的字符串