Как Linux arm64 переключаться между AArch32 и AArch64 - PullRequest
1 голос
/ 14 февраля 2020

Linux поддерживает запуск 32-разрядного приложения, если

  1. ядро ​​поддерживает CONFIG_COMPAT
  2. , аппаратное обеспечение поддерживает AArch32

Я предполагаю, что 32-разрядное приложение должно работать в состоянии выполнения AArch32 для режима охраны, и если в среде есть 32-разрядное приложение и 64-разрядное приложение.

32-разрядный процесс приложения -> состояние состояния - AArch32

64-битный прикладной процесс и ядро ​​-> состояние постановки на охрану AArch64

Это правильно?

Если да,
Как Linux обрабатывает переключатели AArch32 и AArch64?
Знает ли ядро, что запущенный процесс является 32-битным или 64-битным?

1 Ответ

1 голос
/ 04 марта 2020

Ссылка 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 ( разработчик ядра ), объясняет переключение между процессом пользовательского пространства AArch32 и AArch64 linux ядро Мартин Вайдман . Переключение режима 32-> 64 выполняется при исключениях; и переключение 64-> 32 выполняется при возврате исключения.

Если вы в данный момент запускаете одно из 32-битных приложений, и вы берете исключение (например, IRQ, SV C из системного вызова) , прервать ошибку страницы, ....) вы входите в 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»

При принятии исключения, если уровень Exception изменяется, состояние выполнения может: остаться неизменным, или измениться с 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-states или в https://www.realworldtech.com/arm64/2/:

Модель исключений AArch64

  • Уровни привилегий: EL3 - самый высокий, EL0 - самый низкий
  • Переход на более высокие уровни с помощью исключений

  • Ширина регистра не может быть выше на более низких уровнях

    • Например, нет 64-битного EL0 с 32-битным EL1
  • Переход между AArch32 и AArch64 через исключения
    • AArch32 / AArch64 in работа невозможна

Теперь по вашим вопросам:

как Linux обрабатывает переключатели AArch32 и AArch64?

Используя аппаратную возможность обработки исключений (и возврата) с переключателем EL0 / EL1 с различными значениями PSTATE.

Знает ли ядро, что запущенный процесс является 32-битным или 64-битным -bit?

Да, в ядре есть проверка 32-битных процессов («задач») на 64-битных ядрах (compys 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.h и 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-битной загрузке эльфа с несколькими макросами личности:

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);
...