简体   繁体   English

Linux arm64 如何在 AArch32 和 AArch64 之间切换

[英]How Linux arm64 switch between AArch32 and AArch64

Linux supports running 32-bit application, as long as Linux 支持运行 32 位应用程序,只要

  1. kernel enables CONFIG_COMPAT内核启用CONFIG_COMPAT
  2. the hardware supports the AArch32硬件支持 AArch32

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 位应用程序和 64 位应用程序。

32-bit application process -> arm state is AArch32 32位应用进程->arm状态为AArch32

64-bit application process and kernel -> arm state is AArch64 64 位应用进程和内核 -> arm 状态为 AArch64

Is it correct?这是正确的吗?

If so,如果是这样的话,
how does the Linux handle the AArch32 and AArch64 switch? Linux 如何处理 AArch32 和 AArch64 开关?
Does the kernel know the running process is 32-bit or 64-bit?内核是否知道正在运行的进程是 32 位还是 64 位?

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 .链接https://community.arm.com/developer/ip-products/processors/f/cortex-a-forum/6706/in-aarch32-state-what-is-the-mechanism-to-switch-to- aarch64软件式在发表的评论0andriy内核开发)具有通过AArch32用户空间进程和AArch64 Linux内核之间的切换说明马丁·魏德曼 The 32->64 mode switch is done at exceptions; 32->64 模式切换是在异常情况下完成的; and 64->32 switch is done at exception return.并且 64->32 切换在异常返回时完成。

If you are currently running one of the 32-bit apps and you take an exception (eg IRQ, SVC from a system call, abort from a page fault,....) you enter the 64-bit OS.如果您当前正在运行其中一个 32 位应用程序并且出现异常(例如 IRQ、系统调用中的 SVC、页面错误中止等),您将进入 64 位操作系统。 So a AArch32 --> AArch64 transition.所以 AArch32 --> AArch64 过渡。 When the OS performs an exception return back into the app, that's an AArch64-->AArch32 transition.当操作系统执行异常返回到应用程序时,这是一个 AArch64-->AArch32 转换。 ... Any exception type in AArch32 state could potentially lead to Execution state changing to AArch64. ... AArch32 状态中的任何异常类型都可能导致执行状态更改为 AArch64。 ... For exceptions returns the reverse is true. ... 对于异常返回,反之亦然。 An exception return in AArch64 might cause execution state to change to AArch32. AArch64 中的异常返回可能会导致执行状态更改为 AArch32。
For both exceptions and exception returns, a change of Execution state can only occur if there is also a change in EL.对于异常和异常返回,只有当 EL 也发生变化时,才会发生执行状态的变化。 That is an exception from EL0 to EL1 could lead to a change in Execution state.即从 EL0 到 EL1 的异常可能导致执行状态的更改。 But an exception from EL1 to EL1 could not.但是从 EL1 到 EL1 的异常不能。

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. 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线程有更多细节。 Or there is much simpler explanation in https://medium.com/@om.nara/aarch64-exception-levels-60d3a74280e6 in "Moving between AArch32 and AArch64"或者在“在 AArch32 和 AArch64 之间移动”中的https://medium.com/@om.nara/aarch64-exception-levels-60d3a74280e6中有更简单的解释

On taking an exception, if the Exception level changes, the Execution state can: Remain unchanged, OR Change from AArch32 to AArch64.在发生异常时,如果异常级别发生变化,则执行状态可以:保持不变,或从 AArch32 更改为 AArch64。

On returning from an exception, if the Exception level changes, the Execution state can: Remain unchanged, OR Change from AArch64 to AArch32.从异常返回时,如果异常级别发生变化,执行状态可以:保持不变,或从 AArch64 更改为 AArch32。

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/ :https://events.static.linuxfound.org/images/stories/pdf/lcna_co2012_marinas.pdf演示文稿(幻灯片 5)或https://developer.arm.com/architectures/learn-the-architecture/exception- 中相同模型/执行和安全状态或在https://www.realworldtech.com/arm64/2/ 中

AArch64 Exception Model AArch64 异常模型

  • Privilege levels: EL3 – highest, EL0 – lowest特权级别:EL3 – 最高,EL0 – 最低
  • Transition to higher levels via exceptions通过异常过渡到更高级别

  • Register width cannot be higher in lower levels寄存器宽度在较低级别不能更高

    • Eg no 64-bit EL0 with 32-bit EL1例如,没有 64 位 EL0 和 32 位 EL1
  • Transition between AArch32 and AArch64 via exceptions通过异常在 AArch32 和 AArch64 之间转换
    • AArch32/AArch64 interworking not possible AArch32/AArch64 无法互通

Now for your questions:现在回答您的问题:

how does the Linux handle the AArch32 and AArch64 switch? Linux 如何处理 AArch32 和 AArch64 开关?

By using hardware capability of exception handling (and return) with EL0/EL1 switch with different PSTATE values.通过使用具有不同 PSTATE 值的 EL0/EL1 开关的异常处理(和返回)硬件功能。

Does the kernel know the running process is 32-bit or 64-bit?内核是否知道正在运行的进程是 32 位还是 64 位?

Yes, there is the check in kernel for 32-bit processes ("tasks") on 64-bit kernels (compat syscalls): arch/arm64/kernel/syscall.c是的,在 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();
}

Test is defined in include/asm/compat.h and arch/arm64/include/asm/thread_info.h as测试在include/asm/compat.harch/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 is set by in fs/compat_binfmt_elf.c on 32-bit elf loading with several personality macro: 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 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 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 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);

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM