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

  • 内核启用CONFIG_COMPAT
  • 硬件支持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-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-stateshttps://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.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);
    

    08-25 00:20