Возможна ли мультипроцессорная обработка в UEFI?
Согласно спецификации Unified Extensible Firmware Interface программная среда, обеспечивающая выполнение инициализационных процедур до загрузки операционной системы, не поддерживает многопотоковую обработку. Основная причина – однопотоковая идеология UEFI и, как следствие, нереентерабельность сервисных процедур UEFI API. Вместе с тем, ряд задач не связанных с вызовом сервисных функций (например, тестирование оперативной памяти) не только допускают параллельное выполнение несколькими программными потоками, но и получают от такого похода прибавку производительности.
Примечание: несколько лет назад в нашей лаборатории были проведены эксперименты по инициализации мультипроцессорной платформы в 16-битной среде MS-DOS, с использованием прямого программирования аппаратных ресурсов, в частности контроллеров прерываний Local APIC. Опыт успешный с технической точки зрения, тем не менее оказался в чем-то похож на анекдот про дрессировщика, который научил собаку играть на скрипке, а зрители, как выяснилось, ходят в цирк не для того, чтобы слушать скрипичный концерт…
Наличие в составе UEFI firmware документированного набора сервисных функций под названием EFI_MP_SERVICES_PROTOCOL позволяет предположить, что судьба многопотоковой обработки под UEFI сложится несколько иначе. Рассмотрим подробнее одну из функций этого протокола.
Запуск AP: как это делается
Рассмотрим набор параметров и принципы использования одной из основных функций StartupThisAP, обеспечивающей запуск AP (Application Processors) мультипроцессорной системы и координацию их работы со стороны BSP (Bootstrap Processor).
Описание функции StartupThisAP в документе UEFI Platform Initialization Specification. Volume 2. Driver Execution Environment Core Interface. Version 1.3.
Функция позволяет запустить произвольную процедуру на заданном логическом процессоре мультипроцессорной платформы. Объектом управления являются логические процессоры, например, в системе с двумя 8-ядерными процессорами, поддерживающими технологию Hyper-Threading, количество логических процессоров будет равно 2*8*2 = 32. Для запроса количества процессоров используется функция GetNumberOfProcessors, пример использования которой приведен в описании утилиты SMP Detect.
Итак, функция StartupThisAP принимает 7 параметров.
- EFI_MP_SERVICES_PROTOCOL – указатель на интерфейсный блок вызываемого протокола, возвращенный функцией EFI_Locate_Protocol.
- EFI_AP_PROCEDURE – указатель на процедуру, которую должен выполнить процессор AP. Процедура должна быть предварительно подготовлена в памяти в соответствии с правилами для текущего режима работы процессора, например для UEFI x64 используется Microsoft x64 calling convention.
- ProcessorNumber – номер запускаемого процессора, считая от 0.
- WaitEvent – номер (handle) события, зарезервированного вызывающей процедурой. Вызываемая процедура генерирует данное событие для сообщения об успешном завершении подпрограммы на процессоре AP или истечении таймаута. Особый случай – нулевое значение этого параметра означает, что процессор BSP, запустивший процедуру на процессоре AP должен ожидать завершения данной процедуры перед возвратом из функции. При этом события не генерируются. Такой режим называется Blocking Mode.
- TimeoutInMicroseconds – значение таймаута в микросекундах, определяющее время ожидания завершения процедуры, запущенной на процессоре AP. По истечении таймаута происходит принудительное завершение процедуры с генерацией ошибки. Нулевое значение этого параметра означает отсутствие ограничений по времени выполнения процедуры (бесконечное ожидание).
- ProcedureArgument – параметр, передаваемый процедуре, запускаемой на процессоре AP. Нулевое значение означает не использовать передачу параметра.
- Finished – указатель на переменную, устанавливаемую UEFI firmware в состояние TRUE, если процедура, запущенная на AP, успешно завершилась до истечения таймаута. Нулевое значение означает не использовать такую переменную.
После выполнения, функция возвращает UEFI статус в регистре RAX.
Резюме
Можно констатировать, что по сравнению с Legacy BIOS, UEFI firmware существенно упрощает задачу системного программиста при инициализации мультипроцессорной платформы. Передача межпроцессорных прерываний, известных как IPI или Inter Processor Interrupts, а также перевод процессора AP в режим, совместимый с контекстом UEFI, можно осуществить не прямым программированием аппаратуры, а с использованием сервисных функций. Исключение могут составить задачи, при которых ресурсы платформы, обеспечивающие поддержку многопроцессорности, являются самостоятельным объектом исследования или диагностики.
Приложение
UPD. Картинку заменили: изначально по ошибке была структура интерфейсного блока EFI_MP_SERVICES_PROTOCOL