EFI Byte Code и операции с памятью

в 7:58, , рубрики: EBC, EFI Byte Code, UEFI, Железо, ненормальное программирование, Софт, метки: , ,

Как известно, использование виртуальных машин, работа которых строится на программной интерпретации кода, позволяет создавать универсальные приложения, выполняемые на различных аппаратных платформах без рекомпиляции. Технология EFI Byte Code является типичным примером успешного применения данного подхода. Но при всех его преимуществах есть очевидный недостаток – программно реализованный процессор существенно медленнее аппаратного. В предлагаемой статье рассматривается метод, позволяющий нивелировать падение производительности EBC-программ на примере операций заполнения блока памяти константой и копирования содержимого блока памяти. Причем, об использовании «вставок» нативного кода центрального процессора речь не идет, поскольку это дискредитирует саму идею кроссплатформенности.

Постановка задачи

Итак, представим, что нашему приложению необходимо заполнять заданной константой, заданные области памяти, а также выполнять копирование блоков. Причем массивы достаточно большого размера и производительность данной операции критична для производительности приложения в целом. Использование EBC-инструкций для обработки блоков приведет к потере производительности, а «вставки» нативного кода означают потерю кроссплатформенности. Как быть?

Решение существует

Разработчики спецификации UEFI предусмотрели изящное решение для проблем такого типа. В наборе сервисных функций EFI Boot Services предусмотрены процедуры для заполнения блока памяти константой SetMem() и копирования блока памяти CopyMem(). Напомним, сервисные процедуры UEFI API делятся на EFI Boot Services и EFI Runtime Services. Первые доступны только на фазе загрузки ОС, вторые – в течение всего времени работы ОС.

image

Рис 1. Описание параметров функции SetMem() в документе UEFI Specification version 2.4 Errata A.
Buffer – базовый адрес блока;
Size – размер блока;
Value – данные для заполнения блока.

Функция заполняет байтовой константой Value блок памяти, адрес которого равен значению Buffer, размер в байтах равен значению Size.

image

Рис 2. Описание параметров функции CopyMem() в документе UEFI Specification version 2.4 Errata A
Destination – базовый адрес блока-получателя;
Source – базовый адрес блока-источника;
Length – длина для операции пересылки, в байтах.

Функция копирует блок-источник размером Length, расположенный по адресу Source, в блок-получатель, расположенный по адресу Destination.

Пример заполнения блока константой

На Рис.3 приведен листинг EBC-программы, заполняющей константой 11h блок, размером 32 байта. Рассмотрим ее выполнение. В регистр R7 записывается базовый адрес блока, R6 – длина блока, R5 – данные для записи. После этого создается стековый фрейм, используемый для передачи параметров вызываемой подпрограмме. Затем, из таблицы EFI System Table читается адрес дочерней таблицы EFI Boot Services Table, в которой, в свою очередь под номером 42 находится указатель для вызова функции SetMem(). Для шлюзования между EBC-программой и вызываемой процедурой UEFI firmware используется инструкция CALL32EXA. После того, как подпрограмма отработала, стековый фрейм ликвидируется.

В этом и следующем примерах, _Primary_Memory_Base и _EFI_Table это смещения, используемые для адресации переменных, хранящих соответственно базовый адрес блока памяти, используемого программой и базовый адрес корневой системной таблицы EFI System Table, передаваемый приложению при старте.

Вспомним одну особенность построения системных таблиц UEFI, существенную для обеспечения кроссплатформенности. 32-битные реализации UEFI используют указатели размером 4 байта, 64 битные – размером 8 байт. Поле заголовка таблицы всегда имеет размер 24 байта. Поэтому, инструкции, адресующие системные таблицы UEFI оперируют двумя слагаемыми при вычислении адреса: номер указателя (entry) и размер заголовка (header size). Это позволяет виртуальной машине EBC корректно вычислить адрес требуемого элемента, независимо от нативной разрядности процессора, определяющей размер элементов.

image

Рис 3. Пример процедуры заполнения блока константой с использованием функции SetMem(). Используются инструкции ассемблера EBC

image

Рис 4. Результат работы процедуры заполнения блока константой с использованием функции SetMem(). Для просмотра используется Intel EBC Debugger. В этом примере базовый адрес визуализируемого блока 6C40000h, длина 80h=128 байт. Константой 11h заполнен блок размером 32 байта

Пример копирования блока

На Рис.5 приведен листинг EBC-программы, выполняющей копирование блока размером 32 байта. Рассмотрим ее выполнение. В регистр R7 записывается базовый адрес блока-источника, R6 – базовый адрес блока-получателя, R5 – длина блоков. После этого создается стековый фрейм, используемый для передачи параметров вызываемой подпрограмме. Затем, из таблицы EFI System Table читается адрес дочерней таблицы EFI Boot Services Table, в которой, в свою очередь под номером 41 находится указатель для вызова функции CopyMem(). Для шлюзования между EBC-программой и вызываемой процедурой UEFI firmware используется инструкция CALL32EXA. После того, как подпрограмма отработала, стековый фрейм ликвидируется.

image

Рис 5. Пример процедуры копирования блока с использованием функции CopyMem(). Используются инструкции ассемблера EBC

image

Рис 6. Результат работы процедуры копирования блока с использованием функции CopyMem(). Для просмотра используется Intel EBC Debugger. В этом примере базовый адрес визуализируемого блока 6C40000h, длина 80h=128 байт. Блок-источник, расположенный по адресам 6C40000h-6C4001Fh, скопирован в блок-получатель по адресам 6C40030h-6C4004Fh

Резюме

Реализация в составе UEFI firmware, функций, связанных с примитивной обработкой больших массивов, теоретически, позволяет оптимизировать выполнение этих операций под особенности конкретной платформы. Существенное повышение производительности может быть достигнуто с использованием 128 или 256-битных SSE-инструкций центрального процессора x86, применением различных DMA-сопроцессоров, а также аппаратной реализации средствами контроллера памяти. Насколько эффективно разработчики платформ задействуют данный потенциал – покажут наши дальнейшие исследования, но даже при использовании процедурами UEFI firmware классических 32-битных x86-инструкций, EBC-приложение, не теряя кроссплатформенности и выполняясь на программном процессоре, получает в свое распоряжение производительность аппаратного процессора.

Автор: icbook

Источник

Поделиться

* - обязательные к заполнению поля