Embedded ARM

Средства виртуализации занимают особое место в системах на базе процессоров ARM. Статья Сергея Темерханова и Игоря Починка посвящена обзору этих средств с точки зрения разработки системного ПО.

Статья была опубликована в журнале МКА: ВКС, 2018, том 2, с. 38–43.


Средства виртуализации в системах на базе процессоров ARM занимают особое место и состоят из целого ряда компонентов. Впервые специальный режим процессора, предназначенный для работы гипервизора, появился в ARMv7 как расширение, но в ARMv8 он уже стал частью архитектуры и интегрирован в общую систему уровней привилегий под названием EL2. В то же время использование одного только этого режима решает задачи, связанные с обращением процессора к ресурсам системы, таким как память и периферийные устройства. Для того чтобы повысить эффективность транзакций, выполняемых устройстами в виртуализированном окружении, для систем на базе ARMv8 был разработан целый ряд компонентов, таких как новые блоки контроллера прерываний, и, конечно же, IOMMU. Эта статья посвящена обзору этих средств с точки зрения разработки системного ПО.

Виртуализация в системах на ARMv8 организована следующим образом (рис. 1): на уровне привилегий EL2 работает гипервизор, который управляет исполнением кода виртуальных машин (ВМ) и распределением ресурсов между ними. Самим экземплярам ВМ доступны уровни EL1 (ядро ОС, привилегированный код) и EL0 (непривилегированный код). Трансляция адресов при этом выполняется в два этапа (рис. 2): на первом этапе из виртуального адреса вычисляется так называемый промежуточный физический адрес (Intermediate Physical Address, IPA), используя таблицы трансляции первого уровня (указатели на которые хранятся в регистрах TTBR0_EL1/TTBR1_EL1); на втором этапе производится вычисление реального физического адреса, используя таблицу второго уровня, подготовленную гипервизором (указатель хранится в регистре VTTBR_EL2). Такая схема организации обеспечивает эффективное разделение привилегий и изоляцию ВМ от аппаратуры, что позволяет иметь, например, множество экземпляров одинаковых ВМ. Двухуровневая трансляция позволяет ВМ полностью контролировать собственные таблицы трансляции и в то же время гипервизору – полностью контролировать конечные результаты.

Рис. 1. Разделение уровней привилегий в виртуализованных окружениях

Уровень привилегий EL2 предназначен специально для исполнения кода гипервизора и имеет ряд отличий от других уровней. Так, это минимальный уровень привилегий, на котором доступны специальные регистры VTTBR_EL2, VTCR_EL2 и ряд других, предназначенных для управления виртуальными машинами. В оригинальной версии архитектуры ARMv8 для гипервизора предусмотрена одна таблица трансляции, равно как и для текущей виртуальной машины. Гипервизор имеет доступ к целому ряду специальных регистров, с помощью которых задаются параметры конфигурации, видимые ВМ на уровне EL1, такие как идентификаторы процессора (производитель, версия и т. п., а также номер в многопроцессорной системе), что позволяет «показывать» разным ВМ, работающим на одной и той же системе, различные топологии виртуальных процессорных систем и процессоры разных версий и даже производителей.

В случае, когда внутри ВМ происходит некоторое событие, требующее реакции гипервизора, обработка его выполняется следующим образом: возникает исключение на уровне EL2, в соответствии с типом которого вызывается соответствующий обработчик из таблицы, адрес которой находится в регистре VBAR_EL2, выполняются необходимые действия, в регистры при необходимости помещаются нужные значения и выполняется возврат в ВМ, исполнение которой было прервано (или переключение ВМ, если гипервизор спроектирован подобным образом). События, по которым происходят такие исключения, определяются битами регистра HCR_EL2. Так, это могут быть обращения к системным регистрам, в том числе доступным на уровне EL1 (таким как TTBR0_EL1/TTBR1_EL1, FAR_EL1 и другим), инструкции сброса кэша и TLB, обычные исключения (прерывания, в том числе от таймера, неподдерживаемые коды инструкций и т. д.), инструкции ожидания прерываний и событий, и т. д. Разрешение двухуровневой трансляции адресов также контролируется этим регистром.

Рис. 2. Схема трансляции адресов в виртуализованных окружениях ARMv8

Кроме того, на уровне EL2 доступен отдельный аппаратный таймер, что позволяет организовать периодическое прерывание, обычно применяемое для организации переключения ВМ, наподобие того, как переключаются задачи в современных ОС. Сам процесс переключения включает в себя также сохранение контекста текущей ВМ, загрузку новой, и передачу управления на неё.

Виртуальные машины могут в то же время выполнять вызовы супервизора, примерно так же, как непривилегированный код на уровне EL0 выполняет системные вызовы. Для того чтобы выполнить такой вызов, ВМ помещает в регистры параметры и выполняет инструкцию «hvc». При этом возникает исключение на уровне привилегий EL2, которое обрабатывается стандартным образом. Обычно подобное поведение имеет место при вызовах стандартизированных функций протокола PSCI. Следует также отметить, что супервизором могут быть перехвачены вызовы функций доверенного кода, выполняемые из ВМ (тот же PSCI в невиртуализованных окружениях реализуется в нём и такой вызов обрабатывается на высшем уровне привилегий EL3).

Также в архитектуре ARMv8 предусмотрены средства повышения производительности виртуализованных окружений: помимо доменов локальности (Shareability domains), которые гипервизор может назначать для уменьшения трафика когерентности кэша, каждой ВМ может быть присвоен собственный идентификатор, VMID. Его использование позволяет избежать сброса TLB при переключении ВМ, являющегося достаточно «дорогой» операцией. Оригинальная версия ARMv8 предусматривала 8-битные идентификаторы, в дальнейшем они были расширены до 16 бит.

Также в ARMv8.4 была добавлена вторая таблица трансляции для уровня EL2, TTBR1_EL2, так что гипервизоры второго типа (являющиеся частью ОС) получают больше возможностей.

В то же время, как уже было сказано ранее, полноценная виртуализация требует обеспечения взаимодействия ВМ с периферийными устройствами, такими как сетевые адаптеры, контроллеры устройств хранения данных, и т. п., по возможности – с минимальным участием гипервизора, а также доставки прерываний от устройств к процессорам. Эти аспекты виртуализованных окружений в системах на ARMv8 обрабатываются двумя блоками: контроллером прерываний (GIC) и блоком трансляции адресов ввода/вывода (SMMU) (рис. 3).

Рис. 3. Трансляция адресов ввода/вывода SMMU ARMv8 

Блок трансляции адресов ввода/вывода (SMMU) выполняет трансляцию адресов ввода/ вывода аналогично тому, как это делается для обращений к памяти, инициируемых процессорами. Блок поддерживает одно- и двухуровневую трансляцию адресов ввода/вывода, благодаря чему преимуществами трансляции и защиты областей памяти могут воспользоваться, помимо гипервизора, также и ВМ: устройствам разрешается чтение/запись только из выделенных/в выделенные им области памяти. Кроме того, иногда удобно бывает организовать сборку/распределение буферов ввода/вывода (так называемые scatter-gather) средствами SMMU. Использование уровней трансляции – примерно такое же, как и в случае процессоров, то есть на выходе первой стадии получается промежуточный физический адрес, уникальный для текущей ВМ, а на выходе второй – реальный физический адрес, уникальный для всей системы. Формат таблиц трансляции для SMMU схож с таковым для процессоров, специфика присутствует в атрибутах страниц. Поддерживаются страницы размером 4, 16 и 64 Кбайт, а также одна или две таблицы в зависимости от настроек регистров и уровня трансляции и полное 48 (или 52)-битное адресное пространство. Каждое устройство, обращения от которого подвергаются трансляции, имеет собственный контекст трансляции (что сводится в конечном итоге к выбору нужного набора таблиц трансляции), при этом допускается совместное использование контекстов устройствами. Выбор контекста производится блоком на основе так называемого идентификатора потока (Stream ID) – аппаратно-зависимого идентификатора устройства. Так, для устройств PCIe (физических или виртуальных функций) таким идентификатором является RID, совпадающий с адресом устройства в конфигурационном пространстве PCIe. Блок SMMU имеет собственный TLB и для ускорения также поддерживает идентификаторы виртуальных машин.

В случае обнаружения некорректной конфигурации, ошибок трансляции и других исключительных ситуаций SMMU сигнализирует о них процессорам посредством так называемых контекстных прерываний – прерываний, связанных с контекстами трансляции.

Управление SMMU довольно сильно напоминает управление процессорным MMU, с той разницей, что операции, выполняемые для процессорного MMU специальными инструкциями (такие как сброс TLB, получение результата трансляции и ряд других) в случае SMMU выполняются посредством доступа к регистрам соответствующего контекста.

К концу 2017 года существовало несколько версий спецификаций SMMU, последняя из них – 3.1. Блоки SMMU версий 3.0 и 3.1 имеют поддержку расширенных идентификаторов потоков и используют таблицы в ОЗУ для сопоставления номеров потоков и контекстов. Такие таблицы могут быть одно- или двухуровневыми. Элементы таблиц при этом содержат указатели на дескрипторы контекстов, которые тоже располагаются в памяти, а также идентификатор ВМ, к которому относится данный элемент и указатель на таблицу трансляции второго уровня. Дескрипторы контекстов, в свою очередь, содержат указатели на таблицы первого уровня трансляции.

Одна из важных особенностей SMMUv3 – возможность задержки выполнения транзакций до получения реакции программного обеспечения. Такая модель работы позволяет организовать обращение устройств к страницам, не находящимся в оперативной памяти (например, сброшенным в файл/на раздел подкачки) или выделенным в спекулятивном порядке.

Также SMMU может самостоятельно устанавливать биты индикации изменённых страниц в таблицах трансляции, что может значительно помочь при миграции ВМ, получении снимка состояния и т. д.

Для SMMUv3 введена также поддержка масок идентификаторов ВМ, что позволяет иметь таблицы трансляции, разделяемые между разными ВМ, уменьшая, таким образом, нагрузку на TLB.

В SMMUv3 была значительно переработана система как управления, так и сигнализации о событиях: в этой версии блока используется очередь событий, представляющая собой кольцевой буфер в памяти, а контекстные прерывания заменены прерыванием, сигнализирующим появление в очереди новых дескрипторов событий. Для запроса страниц, к которым обращаются устройства, существует отдельная очередь, так называемый интерфейс запроса страниц (PRI).

Вместо контекстных регистров, как уже было упомянуто, используются также структуры специального формата в памяти, а управление контекстами выполняется посредством записи команд в очередь команд и запуска их на исполнение.

Очень значительную роль в организации работы виртуализованных окружений на ARMv8 играет контроллер прерываний (GIC). На конец 2017 года последней версией спецификации была четвёртая, при этом минимальной версией, рассчитанной на работу с процессорами ARMv8, является вторая.

Сам по себе GIC – достаточно сложное устройство, что обусловлено необходимостью доставки прерываний в многопроцессорных системах (существующие реализации могут иметь 256 и более аппаратных потоков), в этой статье будут рассмотрены только те особенности контроллера, которые имеют прямое отношение к средствам виртуализации.

Основная часть регистров GIC не виртуализована, что ведёт к необходимости вмешательства гипервизора при доступе к ним из ВМ. В то же время спецификация вводит такое понятие, как виртуальные прерывания. Виртуальные прерывания могут быть включены в одну из двух виртуальных групп: 0 и 1. Группа 0 – это так называемые «быстрые прерывания» (FIQ), группа 1 – все остальные (IRQ). Виртуальные прерывания обрабатываются процессором точно так же, как и физические.

Обработка прерываний в виртуализованных окружениях на базе ARMv8 организована следующим образом: физические прерывания от устройств направляются на уровень EL2, то есть гипервизору, а гипервизор уже выставляет в активное состояние соответствующее виртуальное прерывание на виртуальном процессоре в случае, если прерывание предназначено для него. Ряд прерываний может быть адресован гипервизору – это ряд системных и служебных прерываний. Гипервизор обрабатывает физические прерывания до того, как они будут виртуализованы, в соответствии с правилами, определяемыми спецификацией GIC.

Собственно поддержка виртуализации прерываний в GIC включает в себя список событий, обозначающих виртуальные прерывания, хранящихся в соответствующих регистрах, и представленных как виртуальные IRQ или FIQ. Управление виртуальными прерываниями через регистровый интерфейс процессора выполняется точно так же, как и для физических прерываний. Таким образом, ПО, выполняемое на виртуальном процессоре, может:

  • выставлять виртуальные маски приоритета,
  • управлять тем, как виртуальный приоритет делится в группе,
  • подтверждать виртуальные прерывания,
  • снижать приоритет виртуальных прерываний,
  • деактивировать виртуальные прерывания.

Для управления виртуальными прерываниями интерфейс процессора предоставляет набор системных регистров, находящихся по тем же адресам, что и регистры управления физическими прерывамиями, то есть для ВМ механизм управления абсолютно прозрачен.

Количество регистров списка виртуальных прерываний определяется реализацией, но ограничено сверху шестнадцатью. В том случае, когда число прерываний, адресованных виртуальному процессору, превышает число доступных регистров, гипервизор может сохранять соответствующие события в памяти, чтобы потом записать их в освободившиеся регистры. Приоретизация прерываний выполняется аппаратными средствами.

Виртуальный интерфейс генерирует прерывания, адресованные гипервизору, с помощью которых сигнализирует о событиях, таких как опустошение списка прерываний, включение и отключение групп, сигнализация конца прерывания для прерываний, не находящихся в регистрах, и т. д., на которые гипервизор должен отреагировать соответствующим образом.

Кроме прерываний PPI (Private Peripheral Interrupts) и SPI (Shared Peripheral Interrupts), в системах на ARMv8 присутствует целый класс прерываний, активируемых сообщениями (MSI, Message Signaled Interrupts), называемый LPI (Locality Specific Interrupts). Контроллеры GICv3 и выше имеют специальную расширенную поддержку этого класса прерываний, заключающуюся в возможности обработки сообщений о прерываниях по специальным правилам (так называемым ITS – Interrupt Translation Services). Строго говоря, эти возможности имеют несколько опосредованное отношение к виртуализации, однако стоит кратко описать их, для того чтобы создать у читателя целостную картину о том, для чего были введены изменения GICv4.

Рис. 4. Интерфейсы и взаимодействие компонентов с контроллером прерываний в виртуализованном окружении в системе на базе ARMv8

Устройства при использовании ITS сигнализируют о событиях путём записи в регистр GITS_TRANSLATER. Транзакция записи имеет ряд атрибутов: во-первых, это сами записываемые данные, представляющие собой номер события, а во-вторых, идентификатор источника, тот же, что использует SMMU. Системное ПО программирует регистры ITS так, что те указывают на таблицы устройств, коллекций и трансляции прерываний в памяти, содержащие правила обработки событий от соответствующих источников, в конечном итоге задающие целевой процессор и номер прерывания на нем. Прерывания приводят к установке соответствующих полей элементов таблицы ожидания. Для GICv3 этот механизм определён только для физических прерываний, то есть сигнализируемых непосредственно устройствами. Это приводит к определённым неудобствам при реализации гипервизоров, в частности, требуется программное выполнение всех действий, которые выполняются ITS. В GICv4 введена возможность генерации прерываний программными средствами и трансляции LPI в виртуальные прерывания, предназначенные для соответствующих виртуальных процессоров, для чего введены дополнительные таблицы, описывающие распределение прерываний по целевым процессорам, а также таблицы ожидания виртуальных прерываний.

В случае, если на целевом физическом процессоре, соответствующем целевому виртуальному, в момент прихода прерывания исполняется ВМ с другим идентификатором, GICv4 формирует специальное прерывание, предназначенное для сигнализации об этом гипервизору.

Для управления трансляцией виртуальных прерываний в командный интерфейс ITS GICv4 были добавлены и новые типы команд.

Рассмотренные средства представляют собой весьма обширную базу для реализации виртуализованных окружений и в настоящее время уже достаточно неплохо поддержаны различными программными реализациями гипервизоров, как первого, так и второго типов. В целом идёт постоянное развитие архитектуры как процессоров, так и системных средств с учётом пожеланий, выдвигаемых разработчиками программного обеспечения, а следовательно, будет появляться материал для новых статей.

Литература
  1. ARM® Architecture Reference Manual ARMv8, for ARMv8-A architecture profile
  2. ARM® System Memory Management Unit Architecture Specification SMMU architecture version 2.0
  3. ARM® System Memory Management Unit Architecture Specification SMMU architecture version 3.0 and version 3.1
  4. ARM® Generic Interrupt Controller Architecture Specification GIC architecture version 3.0 and version 4.0