Согласно спецификации 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
Описание функции 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 параметров.

  1. EFI_MP_SERVICES_PROTOCOL – указатель на интерфейсный блок вызываемого протокола, возвращенный функцией EFI_Locate_Protocol.
  2. EFI_AP_PROCEDURE – указатель на процедуру, которую должен выполнить процессор AP. Процедура должна быть предварительно подготовлена в памяти в соответствии с правилами для текущего режима работы процессора, например для UEFI x64 используется Microsoft x64 calling convention.
  3. ProcessorNumber – номер запускаемого процессора, считая от 0.
  4. WaitEvent – номер (handle) события, зарезервированного вызывающей процедурой. Вызываемая процедура генерирует данное событие для сообщения об успешном завершении подпрограммы на процессоре AP или истечении таймаута. Особый случай – нулевое значение этого параметра означает, что процессор BSP, запустивший процедуру на процессоре AP должен ожидать завершения данной процедуры перед возвратом из функции. При этом события не генерируются. Такой режим называется Blocking Mode.
  5. TimeoutInMicroseconds – значение таймаута в микросекундах, определяющее время ожидания завершения процедуры, запущенной на процессоре AP. По истечении таймаута происходит принудительное завершение процедуры с генерацией ошибки. Нулевое значение этого параметра означает отсутствие ограничений по времени выполнения процедуры (бесконечное ожидание).
  6. ProcedureArgument – параметр, передаваемый процедуре, запускаемой на процессоре AP. Нулевое значение означает не использовать передачу параметра.
  7. Finished – указатель на переменную, устанавливаемую UEFI firmware в состояние TRUE, если процедура, запущенная на AP, успешно завершилась до истечения таймаута. Нулевое значение означает не использовать такую переменную.

После выполнения, функция возвращает UEFI статус в регистре RAX.

Резюме


Можно констатировать, что по сравнению с Legacy BIOS, UEFI firmware существенно упрощает задачу системного программиста при инициализации мультипроцессорной платформы. Передача межпроцессорных прерываний, известных как IPI или Inter Processor Interrupts, а также перевод процессора AP в режим, совместимый с контекстом UEFI, можно осуществить не прямым программированием аппаратуры, а с использованием сервисных функций. Исключение могут составить задачи, при которых ресурсы платформы, обеспечивающие поддержку многопроцессорности, являются самостоятельным объектом исследования или диагностики.

Приложение




UPD. Картинку заменили: изначально по ошибке была структура интерфейсного блока EFI_MP_SERVICES_PROTOCOL

Комментарии (8)


  1. CodeRush
    30.10.2015 17:10
    +1

    Все это здорово, конечно, только зачем на ассемблере писать то, что можно написать на C в 10 строк? Ничего специфичного для архитектуры там нет, а для ARM и PPC программу уже не собрать.


    1. icbook
      30.10.2015 17:37


      1. CodeRush
        30.10.2015 17:47

        1. Понятно, что писать можно и нетрудно, непонятно только, зачем. Мне тоже приходится писать на ассемблере там, где PIC не завезли (пользуясь случаем, шлю разработчикам архитектуры amd64 охапку лучей добра за RIP-относительную адресацию), но вот так брать и писать на нем программу для UEFI Shell — больше похоже на фанатизм, дух старой школы и вот это все. :)
        2. EBC пока не реализован ни на каких архитетурах, кроме i386, amd64 и Itanium, да и компилятор дают только за деньги, так что толку от него крайне немного.
        3. Спасибо.


        1. icbook
          30.10.2015 17:54

          Извлечение EFI Byte Code из AMIBIOS:
          Значительно проще и эффективнее будет найти EBC-интерпретатор среди модулей AMIBIOS, который соответствуют требованиям расширяемого интерфейса фирменного программного обеспечения. Таковым на сегодня является версия, которая называется Aptio.

          Если по каким-то причинам возникнут затруднения с извлечением EBC-интерпретатора из бинарных файлов Aptio, исполняемый модуль виртуальной машины EFI Byte Code можно скачать здесь.


          1. CodeRush
            30.10.2015 18:00

            У меня есть доступ к исходному коду этого модуля, но картины это не меняет, т.к. интерпретатор EBC на данный момент собирается только под три вышеупомянутых архитектуры, и для ARM и PowerPC просто не реализован еще.


            1. icbook
              30.10.2015 18:18

              Да, с этим дело обстоит неважнецки. Проверить нереально.


            1. icbook
              30.10.2015 18:31

              • Мы, например получили некоторую пользу от EBC, в частности UEFImark EBC Edition работает на x64 и IA32, что стало актуальным для устройств типа Intel Compute Stick. Платный компилятор не используем: для EBC инструкций сделаны собственные макросы под FASM.
              • RIP-относительная адресация под UEFI действительно грустная тема. Смиренно используем загрузку абсолютных 64-битных адресов в регистры, вместо инструкции LEA, несмотря на то, что второй вариант компактнее...


    1. icbook
      30.10.2015 17:58

      Обычно, у нас демо-версии служат заготовками для более сложных программ, таких как, например, бенчмарки чтения-записи оперативной памяти в многопотоковом режиме AVX256/512 инструкциями. А там уже без ассемблерной низкоуровневой оптимизации не обойтись, иначе пропускная способность памяти будет задействована не полностью, а ее измерение будет недостаточно точным.