Basi c набор шагов программирования, которые должны быть запрограммированы для запуска LPI в ARMv8A в «голой» среде? - PullRequest
0 голосов
/ 31 января 2020

Я недавно поднял Locality-Specifi c Прерывания (LPI) в программной среде с нуля на ядре ARMv8A. В частности, для LPI требуется выполнить относительно больший набор шагов, и немного сложнее получить представление более высокого уровня обо всех необходимых шагах только из спецификаций. Я не смог получить одноточечную справку для всех необходимых шагов, упомянутых для того, чтобы где-либо в сети, насколько я искал. Поэтому я задаю этот вопрос и отвечаю на него своим собственным ответом, полученным на основе опыта, накопленного мной при получении LPI.

1 Ответ

0 голосов
/ 31 января 2020

В этом посте моя цель - предоставить краткое высокоуровневое однозначное описание программирования, необходимого для запуска LPI (Locality-Specifi c Interrupt) на платформе проверки ARM v8A с нуля.

Архитектура ARM определяет специальный компонент, называемый контроллером прерываний Generi c (GI C), который отвечает за управление всеми прерываниями, определенными в архитектуре. Существует 4 вида прерываний: SGI (программно-генерируемые прерывания), PPI (частное периферийное прерывание), SPI (общее периферийное прерывание) и LPI (Locality-Specifi c Прерывание).

Из ARM / Спецификации GI C, мы можем видеть, что программирование, необходимое для генерации LPI на железной платформе, значительно больше, чем программирование для других 3 типов.

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

LPI также поддерживаются во всех реализациях Linux для АРМ. Если загруженная ОС доступна, можно использовать более высокоуровневый подход к программированию LPI (используя возможности Linux), и задача становится проще. Однако в большинстве базовых платформ нам потребуется выполнить все необходимое программирование самостоятельно, и именно здесь я надеюсь, что приведенный ниже набор шагов поможет достичь цели ускорения работы LPI.

Примечание. Компоненты GI C (распределитель, распространители, GITS) являются компонентами с отображением памяти. Все настройки, упомянутые ниже, будут иметь форму загрузки и хранения. Документация So C должна быть в состоянии предоставить информацию о том, где эти компоненты расположены на карте памяти.

Я предлагаю прочитать спецификации ARM и GI C, чтобы понять все более глубокие последствия регистра поля, доступные в следующих шагах.

Основы

LPI обычно запускается одним из устройств в So C и предназначается для одного из процессоров в системе. Каждому устройству может потребоваться инициировать прерывания разных типов целевых разных ядер для разных типов услуг, которые могут ему понадобиться. Следовательно, LPI идентифицируется кортежем (DeviceID, EventID). В архитектуре поддерживается большое количество LPI (от 8192 до 2 ^ 16-1 или событие 2 ^ 24-1). Как правило, большие наборы прерываний LPI могут быть исправными из одного и того же ЦП. Поэтому вводится концепция, называемая идентификатором сбора прерываний (ICID). Это относится к набору LPI, которые должны быть отправлены на один и тот же процессор. Структуры данных

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

Требуется шесть (6) структур данных настроить LPI -

a. Таблица свойств LPI

содержит информацию о приоритете прерывания и бите разрешения для каждого из LPI - один байт для каждого LPI. первые 8192 байта не существуют в этой таблице. Указано GICR_PROPBASER. Пожалуйста, прочитайте спецификацию GI C, чтобы понять значения полей в этом регистре b. Таблица ожиданий LPI

содержит информацию о состоянии ожидания каждого из LPI - по одному байту для каждого LPI первые 8192 байта определены в данной таблице как IMPLEMENTATION DEFINED, и после этого блока памяти размещены состояния битов ожидания LPI. by GICR_PENDBASER Пожалуйста, прочитайте спецификацию GI C, чтобы понять значения полей в этом регистре c. Очередь команд ITS

содержит последовательность команд, которые должны быть выполнены ITS (службой трансляции прерываний). РЕАЛИЗОВАНО ОПРЕДЕЛЕНО, позволяет ли реализация GI C запускать LPI без использования ITS или нет Регистры GICR_SETLPIR и GICR_CLRLPIR реализованы в этом случае Пожалуйста, прочитайте спецификацию GI C, чтобы понять больше деталей Если ITS должен использоваться для запуска LPI, нам нужно создать последовательность команд, которые будут понятны ITS. На базу очереди команд в памяти указывает GITS_CBASER. На текущую команду, считываемую ITS для выполнения, указывает GITS_CREADR. На последнюю команду в очереди указывает GITS_CWRITER. д. Таблица устройств

В этой таблице хранится сопоставление данного идентификатора устройства с таблицей трансляции прерываний для этого устройства. е. Таблица трансляции прерываний

Таблица трансляции прерываний хранит отображение из заданного EventID в соответствующий физический идентификатор прерывания (номер прерывания, который должен быть представлен ядру) и ICID (поискался далее, чтобы получить целевой процессор)

ф. Таблица сбора

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

Поток поиска (4 поиска и 1 набор таблиц) для LPI кратко описан ниже -

a. LPI запускается с помощью комбинации (идентификатор устройства, идентификатор события)

b. Идентификатор устройства ищется в таблице «Устройства» для получения соответствующей таблицы трансляции прерываний (ITT)

c. Идентификатор события ищется в ITT для получения идентификатора физического прерывания, которое должно быть инициировано, и идентификатора сбора прерываний (ICID)

d. Далее ICID ищется в таблице сбора для получения целевого перераспределителя

e. Таблица свойств LPI ищется, чтобы проверить, включен ли LPI

Если LPI включен, таблица ожидания LPI обновляется, так что физическое прерывание переводится в состояние ожидания.

Когда ядро переходит в соответствующее состояние (уровень исключения, приоритет и т. д. c.), ожидающий LPI «берется» ядром.

Шаги программирования

Теперь перейдем к действительным шагам программирования (7 шаги) -

  1. Включить GI C в системе.

a. Включить небезопасные прерывания группы 1 в распределителе.

GICD_CTLR.EnableGrp1NS = 1 Прерывания LPI всегда являются небезопасными прерываниями группы 1

b. Выведите перераспределителя из сна.

В этом есть архитектурная и определяемая РЕАЛИЗАЦИЯ часть. Архитектурная часть - Установите для GICR_WAKER.ProcessorSleep значение 0 и дождитесь, пока GICR_WAKER.ChildrenAsleep = 0. Часть IMP DEF - это отличается для разных реализаций GI C. Например, для реализации GI C -600 существует регистр с именем GICR_PWRR, и для записи GICR_WAKER в соответствии с вышеприведенным этапом необходимо установить для GICR_PWRR.RDPD и GICR_PWRR.RDAG значение 0, прежде чем записывать GICR_WAKER. Документация So C должна содержать необходимые шаги здесь

Обнуление инициализирует блок памяти, который будет использоваться всеми таблицами, используемыми для LPI

Выделить память для таблицы свойств LPI, таблицы ожидания LPI и очереди команд ITS

Во многих «железных» фреймворках «выделение» может просто определять в автономном режиме, какие диапазоны адресов использовать, и обеспечивать размещение указанных таблиц в разных областях памяти. Установите GICR_PROPBASER в точку в подходящую область памяти (предпочтительнее выравнивание 64 КБ). Установите GICR_PENDBASER, чтобы указать на подходящую область памяти (выравнивание 64 КБ). Установите GICR_CBASER, чтобы указать подходящую область памяти (выровнено 64 КБ).

Выделить память для таблицы Devices и таблицы Collections

На эти таблицы указывают регистры GITS_BASER. Эти регистры необходимо сначала прочитать, чтобы понять, какой регистр указывает на какой тип таблицы (GITS_BASER .Тип поля). Это исправлено реализацией. Установите соответствующие индексы GITS_BASER, чтобы они указывали на пустую таблицу Device и таблицу Collection

Включить LPI для перераспределителя

Установить GICR_CTLR.EnableLPIs = 1

Создать очередь команд

Базовая c последовательность, необходимая для запуска LPI, представлена ​​ниже - MAPD Создает сопоставление записи таблицы устройств DeviceID -> ITT table MAPTI Создает сопоставление записи таблицы ITT EventID -> (физический идентификатор LPI (pINTID), ICID ( ID коллекции прерываний)) MAPC Создает сопоставление записи таблицы сбора ICID -> адрес распространителя. Существует два возможных формата адреса распространителя: физический адрес или номер процессора GITS_TYPER.PTA указывает, какой формат должен использоваться GICR_TYPER.ProcessorNumber указывает назначенный номер процессора для перераспределителя INT «Программное обеспечение» запускает LPI - эта инструкция берет DeviceID и EventID, проводит их через трансляцию ITS и просит целевого распространителя установить соответствующий бит таблицы ожидающих LPI.

Включить ITS

Установить GITS_TYPER.Enable = 1. Это запустит выполнение команд ITS в очереди команд и, если все настроено правильно, должно привести к изменению LPI. в состояние ожидания на перераспределителе, связанном с целевым ядром.

Спасибо за чтение этого поста, и я очень надеюсь, что это поможет быстрее запускать LPI в системе с «голым железом».

Пожалуйста, дайте мне знать в комментариях, если вы хотите, чтобы какая-либо дополнительная информация была добавлена ​​или есть какие-либо исправления, которые нужно внести.

Спасибо !!!

...