【问题标题】:How Linux arm64 switch between AArch32 and AArch64Linux arm64 如何在 AArch32 和 AArch64 之间切换
【发布时间】:2020-02-14 05:53:46
【问题描述】:

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

  1. 内核启用CONFIG_COMPAT
  2. 硬件支持 AArch32

我假设 32 位应用程序必须运行在 arm AArch32 执行状态,如果环境有 32 位应用程序和 64 位应用程序。

32位应用进程->arm状态为AArch32

64 位应用程序进程和内核 -> arm 状态为 AArch64

对吗?

如果是这样,
Linux 如何处理 AArch32 和 AArch64 切换?
内核是否知道正在运行的进程是32位还是64位?

【问题讨论】:

  • 由于特殊的蹦床到(未)对齐的地址。也就是说,很少有 LSB 负责切换模式。
  • @0andriy 不。您考虑的是 ARM/Thumb 互通,而不是 AArch64/AArch32 互通。
  • @EOF 我会等待你的回答,同时根据community.arm.com/developer/ip-products/processors/f/… 任何例外都可以做到这一点,所以,我的评论可能是正确的。但我不知道内核中的那个区域。
  • @0andriy 我没有写答案。我只看了一眼 ARM64 ARM。似乎每个 EL(EL3 除外)都可以配置为 AArch32 或 AArch64,具体取决于 EL 的相关PSTATE 寄存器。 Linux在用户空间对应的PSTATE寄存器中设置了相应的位,所以一旦内核返回(异常返回),用户空间就执行AArch32。

标签: linux linux-kernel arm embedded-linux


【解决方案1】:

0andriy (kernel developer) 在 cmets 中发布的链接 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 切换在异常返回时完成。

如果您当前正在运行其中一个 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-stateshttps://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.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 由 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);

【讨论】:

猜你喜欢
  • 1970-01-01
  • 2015-12-02
  • 2020-05-17
  • 2015-10-29
  • 2021-04-23
  • 1970-01-01
  • 1970-01-01
  • 2014-03-02
  • 2021-05-22
相关资源
最近更新 更多