- Портирование ОС на Aarch64
- Регистры и набор команд
- Режимы исполнения и переключение между ними
- Advanced SIMD
- Платформы
- Заключение
- Полезные ссылки
- Русские Блоги
- Архитектура ARMV8 Описание: Aarch64 Уровень системы Программирование системы (1) -EL / et / st
- 1. Введение
- 2. Ненормальный уровень
- 2.1 Обзор уровня исключения
- 4. Secure state
- 4.1 Воздействие EL3 на безопасное состояние
- 4.2 EL3 влияет на влияние Aarch64 или Aarch32
- 5. Сообщение состояния исполнения с безопасным состоянием
- Сегодняшний мир — это amd64, armv7 и aarch64. Всё остальное мертво, Джим
Портирование ОС на Aarch64
Aarch64 — это 64-битная архитектура от ARM (иногда её называют arm64). В этой статье я расскажу, чем она отличается от «обычных» (32-битных) ARM и насколько сложно портировать на него свою систему.
Эта статья — не детальный гайд, скорее обзор тех модулей системы, которые придётся переделать, и насколько сильно архитектура в целом отличается от обычных 32-битных ARM-ов; всё это по моему личному опыту портирования Embox на эту архитектуру. Для непосредственного портирования конкретной системы так или иначе придётся разбираться с документацией, в конце статьи я оставил ссылки на некоторые документы, которые могут оказаться полезны.
На самом деле, различий больше, чем сходств, и Aarch64 — это скорее новая архитектура, чем 64-битное расширение привычных ARM. Предшественником Aarch64 во многом является Aarch32 (это расширение обычного 32-битного ARM), но так как у меня не было опыта работы с ним, писать о нём я и не буду 🙂
Далее в статье, если я пишу о «старом» или «прежнем» ARM, я имею ввиду 32-битный ARM (с набором команд ARM).
Кратко пройдусь по списку изменений по сравнению с 32-битным ARM, а затем разберу их поподробнее.
- Регистры общего назначения стали в 2 раза шире (теперь они по 64 бита), и количество их удвоилось (т.е. теперь их не 16, а 32).
- Отказ от концепции сопроцессорных регистров, теперь к ним можно обращаться просто по имени, например msr vbar_el1, x0 (против прежнего mcr p15, 0, %0, c1, c1, 2 )
- Новая модель MMU (со старой никак не связана, придётся писать заново).
- Раньше было два уровня привилегий: пользовательский (соответствует режиму процессора USR) и системный (соответствует режимам SYS, IRQ, FIQ, ABT, . ), теперь всё одновременно проще и сложнее — режима теперь 4.
- AdvSIMD пришёл на смену NEON, операции с плавающей точкой делаются через него же.
Теперь подробнее по пунктам.
Регистры и набор команд
Регистры общего назначения — r0-r30, при этом обращаться можно к ним как к 64-битным (x0-x30) или как к 32-битным (w0-w30, доступ к младшим 32 битам).
Набор инструкций для Aarch64 называется A64. Ознакомиться с описанием инструкций можно тут. Базовые арифметические и некоторые другие команды на языке ассемблера остались прежними:
Теперь немного о различиях:
- Появился специальный «zero»-регистр rzr/xzr/wzr , который равен нулю при чтении (можно применять запись в регистр, но результат вычисления не будет никуда записан).
- Нельзя складывать в стэк сразу много регистров ( stmfd sp!,
), придётся делать это парами:
Регистр PC (Program counter, указатель на текущую выполняемую инструкцию) теперь не регистр общего назначения (раньше это был R15), следовательно, к нему нельзя обращаться обычными командами ( mov , ldr ), только через ret , bl и так далее.
Состояние программы теперь отображает не CPSR (этого регистра попросту нет), а регистры DAIF (содержит маску IRQ, FIQ и т.д., AIF — те самые биты A, I, F из CPSR), NZCV (биты negative, zero, carry, oVerflow — внезапно, те самые NZCV из CPSR) и System Control Register (SCTLR, для включения кэширования, MMU, endianness и так далее).
Вроде бы, этих команд достаточно, чтобы написать простенький загрузчик, который сможет передать управление в платформо-независимый код 🙂
Режимы исполнения и переключение между ними
Про режимы исполнения хорошо написано в Fundamentals of ARMv8-A, я здесь кратко перескажу суть этого документа.
В Aarch64 есть 4 уровня привилегий (Execution level, дальше сокращённо EL).
- EL3 — Secure Monitor (предполагается, что на этом уровне исполняется прошивка)
- EL2 — Гипервизор
- EL1 — ОС
- EL0 — Приложения
На 64-битной ОС можно выполнять и 32-битные, и 64-битные приложения; на 32-битной ОС можно выполнять только 32-битные приложения.
Переходы между EL совершаются либо при помощи исключений (системные вызовы, прерывания, ошибка доступа к памяти), либо при помощи команды возврата из исключения ( eret ).
Каждый EL имеет свои регистры SPSR, ELR, SP (т.е. это «banked registers»).
Многие системные регистры также разделены по EL — например, регистр контекста MMU ttbr0 — есть ttbr0_el2 , ttbr0_el1 , и на соответствующем EL нужно осуществлять доступ к своему регистру. Это же относится к регистрам состояния программы — DAIF, NZCV, SCTLR, SPSR, ELR.
Armv8-A поддерживает MMU ARMv8.2 LPA, подробнее про это можно почитать в главе D5 ARM Architecture Reference Manual для Armv8, Armv8-A.
Если говорить коротко, то этот MMU поддерживает страницы по 4KiB (4 уровня таблиц виртуальной памяти), 16KiB (4 уровня) и 64KiB (3 уровня). На любом из промежуточных уровней можно задать блок памяти, таким образом указывая не на следующий уровень таблицы, а на целый кусок памяти такого размера, какой должна «покрывать» таблица следующего уровня. У меня есть давнишняя статья про виртуальную память, там можно почитать про таблицы, уровни трансляции и вот это всё.
Из небольших изменений — от доменов (domain) отказались, зато добавили флажки вроде dirty bit.
В целом, кроме «блоков» вместо промежуточных табиц трансляции, особых концептуальных изменений не замечено, MMU как MMU.
Advanced SIMD
Есть существенные AdvSIMD отличия у старого NEON, как при работе с плавающей точкой, так и с векторными операциями (SIMD). Например, если раньше D0 состоял из S0 и S1, а Q0 — из D0 и D1, то теперь это не так: Q0 соответствует D0 и S0, для Q1 — D1 и S0 и так далее. При этом поддержка VFP/SIMD обязательна, по соглашению о вызовах теперь нет никакой программной передачи параметров (то, что раньше называлось «soft float ABI», в GCC — флаг -mfloat-abi=softfp ), так что придётся реализовывать аппаратную поддержку плавающей точки.
Было 16 регистров по 128 бит:
Стало 32 регистра по 128 бит:
Подробнее про NEON можно почитать в этой статье, перечень доступных команд для Aarch64 можно найти тут.
Базовые операции с регистрами с плавающей точкой:
Базовые операции SIMD:
Платформы
В QEMU есть поддержка Aarch64. Одна из платформ — virt , для того, чтобы она запускалась в 64-битном режиме, нужно дополнительно передать флаг -cpu cortex-a53 , примерно так:
Что приятно, для этой платформы используется куча периферии, драйвера для которой уже были в Embox — например PL011 для консоли, ARM Generic Interrupt Controller и т. д. Само собой, у этих устройств другие базовые адреса регистров и другие номера прерываний, но главное — код драйверов без изменений работает на новой архитектуре. При старте системы управление находится в EL1.
Из-за этой железки и было затеяно портирование на Aarch64 — i.MX8MQ Nitrogen8M.
В отличие от QEMU, u-boot передаёт управление образу в EL2, и, более того, зачем-то включает MMU (вся память мэпируется 1 к 1), что создаёт некоторые дополнительные проблемы при инициализации.
Embox уже поддерживал i.MX6, и, что хорошо, в i.MX8 часть периферии та же самая — например, UART и Ethernet, которые также заработали (пришлось подправить пару мест, где была жёсткая привязка к 32-битным адресам). С другой стороны, контроллер прерываний там другой — ARM GICv3, который достаточно сильно отличается от первой версии.
Заключение
На данный момент поддержка Aarch64 в Embox не полная, но минимальный функционал уже есть — прерывания, MMU, ввод-вывод через UART. Многое ещё предстоит доработать, но первые шаги было сделать проще, чем казалось с самого начала. Документации и статей заметно меньше, чем по ARM, но информации больше, чем достаточно, чтобы со всем разобраться.
В целом, если у вас есть опыт работы с ARM, портирование на Aarch64 — посильная задача. Хотя, как обычно, можно споткнуться на какой-нибудь мелочи 🙂
Скачать проект, чтобы потыркать его в QEMU, можно из нашего репозитория, если есть какие-то вопросы — пишите в комментах, или в рассылку, или в чат в Телеграме (есть ещё канал).
Полезные ссылки
24-25 августа мы будем выступать на TechTrain, слушайте наши выступления раз два три, приходите к стенду — ответим на ваши вопросы 🙂
Источник
Русские Блоги
Архитектура ARMV8 Описание: Aarch64 Уровень системы Программирование системы (1) -EL / et / st
1. Введение
Модель программирования системы ARMV8 системы в основном включает в себя ненормальный уровень, статус эксплуатации, состояние безопасности, синхронное исключение, асинхронное исключение, отладку
Эта статья в основном делает обзор модели программирования уровня системы
2. Ненормальный уровень
2.1 Обзор уровня исключения
ELX (X 64bit, в противном случае => 32 бит
Hcr_l2.rw Определяет состояние выполнения EL1, 1 => 64bit, в противном случае => 32 бит
Scr_el3.rw Определяет состояние выполнения EL2 или EL1, 1 => 64bit, в противном случае => 32 бит
Переключатель между AARCH32 и AARCH64 может быть реализован только путем сброса исключения или системы. (A32 -> T32 переключается инструкцией BX)
4. Secure state
Non-secure
EL0 / EL1 / EL2, только доступ к небезопасному физическому адресу пространства
Secure
EL0 / EL1 / EL3, вы можете получить доступ к непроференным физическим адресным пространством и безопасным физическим адресным пространством, может использоваться для физической барьерной безопасности.
4.1 Воздействие EL3 на безопасное состояние
Внедрить EL3.
- EL3 — только безопасное состояние;
- Небезопасное состояние для защищенного состояния может произойти только при EL3 получает исключение;
- Безопасное состояние для небезопасного состояния может происходить только в результате возврата исключения из EL3;
- Если EL2 реализован, доступно только не безопасное состояние.
Не реализуйте EL3
- Если EL2 не реализован, безопасное состояние определяется производителем SOC;
- Если вы реализуете EL2, только не безопасное состояние
4.2 EL3 влияет на влияние Aarch64 или Aarch32
Пользовательский режим (Aarch32 только) только в небезопасных EL0 или безопасных EL0
SCR_EL3.Ns определяется статусным состоянием низкого уровня EL, чтобы не определить свой собственный
EL2 только небезопасное состояние
EL0 имеет оба не защищенное состояние, также имеет безопасное состояние
Если scr_el3.ns == 0, переключитесь в безопасный статус EL0 / EL1, в противном случае переключитесь на небезопасное состояние EL0 / EL1
Защищенное состояние имеет безопасную EL0 / EL1 / EL3
Защищенное состояние только безопасно EL0 / EL3, без безопасного EL1
5. Сообщение состояния исполнения с безопасным состоянием
Рисунок EL3 Исполнение состояния и защищенная государственная комбинация при использовании Aarch64
Рисунок EL3 использует AARCH32 при выполнении состояния и защищенной государственной комбинации
Источник
Сегодняшний мир — это amd64, armv7 и aarch64. Всё остальное мертво, Джим
Вашему вниманию предлагается перевод прощального письма Миода Валлата, разработчика OpenBSD в течение 15+ лет, покинувшего проект неделю назад. Письмо, изначально адресованное лично некоему Джиму, рассказывает историю о том, куда порой приводят благие намерения, и вызвало резонанс среди пользователей Reddit и HackerNews. Учтите — высказанное мнение субъективно, и, по словам самого автора, «вы имеете право с ним не согласиться».
Сегодняшний мир — это amd64 (по-другому x64, или x86-64), armv7 и, в скором будущем, aarch64 (64-битный ARMv8). Всё остальное мертво, Джим. Никто не вкладывает достаточно денег и мыслительного труда в прочие архитектуры. В действительности, лишь небольшая часть людей в курсе существования остальной части экосистемы (mips, power8, . ), и все равно никому нет до них дела.
Поддержка устаревшей платформы на плаву — это весело, поскольку это напоминает тебе о 90-ых, когда существовал большой выбор «железных» платформ, с приблизительно одинаковым соотношением цены/мощности. В конце концов, дешевые PC убили практически всю конкуренцию, а рынок смартфонов дал ARM нездоровую долю рынка в мире встраиваемых систем.
Затем, спустя некоторое время, веселье подходит к концу, поскольку никто не пишет код, держа в уме твою платформу, — ведь она не считается достаточно мощной, а современные компиляторы больше ее не поддерживают (или они генерируют для нее нерабочий код, что на деле еще хуже). У твоей платформы есть аппаратные границы в несколько сотен MB физической памяти? Тебе не удастся запустить на ней веб-браузер или даже программу для просмотра PDF. Кто-нибудь все еще запускает testsuite из последней версии gcc на твоей платформе? Нет? Прости, чувак, но вот тебе «никель» (5 центов), сходи купи себе уже компьютер получше…
На деле, поддержка платформы в жизнеспособном состоянии — это настоящая командная работа. Она требует серьезных обязательств от проектов, являющихся «строительными блоками»: не слишком сильно «забагованного» тулчейна (as/ld/gcc), поддержки в флагманских проектах (emacs, python, X11, mozilla, libreoffice. ), а также аккуратной и актуальной документации, доступной бесплатно.
Ни один из перечисленных пунктов не является истиной для всех платформ, исключая amd64, armv7 и aarch64.
Из-за всего этого стремление поддерживать «жизнь» какой-либо другой платформы — это на самом деле попытка плыть против течения.
Конечно, ты все еще можешь встретить нескольких безумцев, готовых выполнить невероятный объем работы для предотвращения упадка их любимой платформы и умело создающих впечатление того, что эти платформы — все еще «пассажиры первого класса». Но эти ребята — те же самые люди, что были и десять лет назад. Рано или поздно, они устают и сдаются. Как, например, я.
Самое худшее во всем этом — это когда ты оглядываешься назад и понимаешь, что после всех этих лет, свободное ПО проиграло. Компаниям, занимающимся созданием не-свободного ПО, хватило достаточно ума и смекалки, чтобы поймать «импульс» разработчиков свободного ПО, направленный на работу над встраиваемыми платформами, и использовать его для того, чтобы максимально сократить собственные расходы на разработку ПО, получив при этом еще и позитивную реакцию прессы.
Таким образом, сегодня мы строим одноразовые системы, не учитывающие того, что ждет нас в будущем — поскольку, когда придет время, мы просто возьмем очередной модный SoC. Нет необходимости иметь всё то, что формирует архитектуру:
- видение будущего, позволяющее различным поколениям аппаратного обеспечения использовать одно и то же «железо» и софт;
- дизайн, позволяющий сегодняшнему ПО запускаться на «железе» завтрашнего дня до тех пор, пока изменения не слишком радикальны;
- целостность в выборе шин, процессоров, отображений адресного пространства (consistency in choices of busses, key chips, address maps);
- настоящего firmware, а не чего-то абсолютно отвратительного вроде EFI, который не может соревноваться даже со старым Open Firmware (IEEE 1275), которому уже больше 20 лет;
- надежные перечислители шин (reliably enumerable busses).
Нет, сэр, мы возьмем нынешний распоследний SoC, подключим несколько дополнительных устройств туда, где сможем найти дыру в адресном пространстве, засунем туда кастрированный u-boot и стабильное ядро Linux, — получите и распишитесь, ваша «платформа» готова. А люди и рады.
Я потратил 20 лет своей жизни, пытаясь продвигать правильный взгляд на свободное программное обеспечение, его ценности и его этику; сражался за него, всегда был активно вовлечен, старался показывать другим пример, и сегодня я чувствую так, словно все мои усилия были лишь пустой тратой времени, и ничего из того, что я сделал, не принесло пользы.
С этим трудно смириться, но лучше сдаться сейчас, чем продолжать попытки и только еще больше расстраиваться.
Источник