繁体   English   中英

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

[英]How Linux arm64 switch between AArch32 and AArch64

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

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

我假设 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软件式在发表的评论0andriy内核开发)具有通过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- 中相同模型/执行和安全状态或在https://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);

暂无
暂无

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

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