本文介绍了Linux arm64 如何在 AArch32 和 AArch64 之间切换的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

Linux 支持运行 32 位应用程序,只要

Linux supports running 32-bit application, as long as

  1. 内核启用CONFIG_COMPAT
  2. 硬件支持 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.harch/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 之间切换的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持!

05-23 07:11