- PVSM.RU - https://www.pvsm.ru -

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

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

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

Итак, представим, что нашему приложению необходимо заполнять заданной константой, заданные области памяти, а также выполнять копирование блоков. Причем массивы достаточно большого размера и производительность данной операции критична для производительности приложения в целом. Использование 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

Источник [3]


Сайт-источник PVSM.RU: https://www.pvsm.ru

Путь до страницы источника: https://www.pvsm.ru/zhelezo/56090

Ссылки в тексте:

[1] Технология EFI Byte Code: http://habrahabr.ru/post/201954/

[2] кроссплатформенности: http://habrahabr.ru/post/212363/

[3] Источник: http://habrahabr.ru/post/214119/