问题描述
Linux 支持运行 32 位应用程序,只要
Linux supports running 32-bit application, as long as
- 内核启用
CONFIG_COMPAT
- 硬件支持 AArch32
我假设 32 位应用程序必须在 arm AArch32 执行状态下运行,并且环境是否有 32 位应用程序和 64 位应用程序.
I assume that 32-bit application must run in arm AArch32 execution state and if the environment has 32-bit application and 64-bit application.
32位应用进程->arm状态为AArch32
32-bit application process -> arm state is AArch32
64 位应用进程和内核 -> arm 状态为 AArch64
64-bit application process and kernel -> arm state is AArch64
正确吗?
如果是这样,
Linux 如何处理 AArch32 和 AArch64 切换?
内核是否知道正在运行的进程是 32 位还是 64 位?
If so,
how does the Linux handle the AArch32 and AArch64 switch?
Does the kernel know the running process is 32-bit or 64-bit?
推荐答案
链接 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 发表在 (内核开发人员) 由 Martin Weidmann 解释了在 AArch32 用户空间进程和 AArch64 linux 内核之间切换一>.32->64 模式切换是在异常情况下完成的;并且 64->32 切换在异常返回时完成.
The link 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 posted in comments by 0andriy (kernel developer) has explanation of switching between AArch32 user-space process and AArch64 linux kernel by Martin Weidmann. The 32->64 mode switch is done at exceptions; and 64->32 switch is done at exception return.
如果您当前正在运行其中一个 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 线程有更多细节.或者在 https://medium.com/@om 中有更简单的解释.nara/aarch64-exception-levels-60d3a74280e6 在在 AArch32 和 AArch64 之间移动"
The 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 thread has some more details. Or there is much simpler explanation in https://medium.com/@om.nara/aarch64-exception-levels-60d3a74280e6 in "Moving between AArch32 and AArch64"
在发生异常时,如果异常级别发生变化,则执行状态可以:保持不变,或从 AArch32 更改为 AArch64.
从异常返回时,如果异常级别发生变化,则执行状态可以:保持不变,或从 AArch64 更改为 AArch32.
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/:
Same in https://events.static.linuxfound.org/images/stories/pdf/lcna_co2012_marinas.pdf presentation (slide 5) or in https://developer.arm.com/architectures/learn-the-architecture/exception-model/execution-and-security-states or in https://www.realworldtech.com/arm64/2/:
AArch64 异常模型
- 特权级别:EL3 – 最高,EL0 – 最低
通过异常过渡到更高级别
- Privilege levels: EL3 – highest, EL0 – lowest
Transition to higher levels via exceptions
寄存器宽度不能在较低级别中更高
Register width cannot be higher in lower levels
- 例如没有 64 位 EL0 和 32 位 EL1
- AArch32/AArch64 无法互通
现在回答您的问题:
Linux 如何处理 AArch32 和 AArch64 切换?
通过使用具有不同 PSTATE 值的 EL0/EL1 开关的异常处理(和返回)硬件功能.
By using hardware capability of exception handling (and return) with EL0/EL1 switch with different PSTATE values.
内核是否知道正在运行的进程是 32 位还是 64 位?
是的,在 64 位内核(兼容系统调用)上检查 32 位进程(任务")的内核:arch/arm64/kernel/syscall.c
Yes, there is the check in kernel for 32-bit processes ("tasks") on 64-bit kernels (compat syscalls): 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 as
Test is defined in include/asm/compat.h and arch/arm64/include/asm/thread_info.h as
#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 位精灵加载设置,并带有几个个性宏:
TIF_32BIT is set by in fs/compat_binfmt_elf.c on 32-bit elf loading with several personality macro:
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);
这篇关于Linux arm64 如何在 AArch32 和 AArch64 之间切换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!