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)在评论中发布的链接kernel developer解释了Martin Weidmann在AArch32用户空间进程和AArch64 Linux内核之间切换的原因。 32-> 64模式切换在异常(exception)情况下完成;并且在异常返回时完成了64-> 32切换。
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中有更简单的解释。
在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/中相同:
现在为您的问题:
通过使用具有不同PSTATE值的EL0/EL1开关的异常处理(和返回)硬件功能。
是的,在64位内核(compat syscalls)上有32位进程(“任务”)的 checkin 内核: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);