Статья: Исследование и реализация способов расширения номенклатуры виртуальных устройств, подключаемых к гипервизорному виртуализационному решению

Внимание! Если размещение файла нарушает Ваши авторские права, то обязательно сообщите нам

1. DMA (Direct Memory Access) - способ взаимодействия устройств с памятью в обход процессора для экономия процессорного времени и ускорения чтения / записи в память устройством. IOMMU работает именно с этим механизмом.

Взаимодействие с процессором:

1. MMIO (Memory Mapped Input/Output) - способ взаимодействия устройств с процессором через стандартный интерфейс обращения к памяти. При использовании MMIO процессор для чтения / записи в регистры устройства использует стандартные системные вызовы READ и WRITE. Процессор пишет данные по виртуальным адресам, которые поступают в MMU для конвертации в физические. В MMU адрес записи чтения конвертируется в физический, но при этом, данный физический адрес лежит вне диапазона существующей физической памяти. Поэтому, когда запрос попадает на шину, он отправляется не в память, а к соответствующему устройству.

2. IO Ports - способ взаимодействия с устройством с использованием интерфейса в виде системных вызовов IN и OUT. Поскольку данные через него передаются побайтно за одну команду, данный интерфейс имеет сравнительно небольшую скорость. Поэтому, на сегодняшний день, он мало применяется.

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

Остается один тип виртуализации - паравиртуализация. В этом случае мы сами устанавливаем интерфейс взаимодействия между устройством и гостевой операционной системой. Именно создание эффективного интерфейса передачи данных и является непосредственной целью данной дипломной работы. Основой нашего, более широкого, интерфейса будет уже реализованный в рамках Parallels Desktop интерфейс передачи данных - Open ToolsGate.

5. Устройство базового механизма Open ToolsGate

Устройство базового механизма Open ToolsGate (OTG), на основе которого будет разработан интерфейс передачи данных между устройствами и гостевой операционной системой, изображено на рисунке.

Устройство базового механизма OTG

Прежде всего, стоит отметить, что в силу некоторых программных ограничений, базовый механизм OTG оперирует блоками данных, размером 4 килобайта. Также, стоит обратить внимание на то, что инициатором обмена с использованием данного механизма может быть только гостевая операционная система (т.е. со стороны хостовой операционной системы невозможно подать сигнал о начале обмена данными).

Передача данных происходит следующим образом:

1. Гость инициирует передачу путем вызова ключевой (небезопасной для прямого исполнения) инструкции - RDPMC. Предварительно гость должен записать аргументы передачи в различные регистры. Самыми важными аргументами являются:

- указатель на буфер данных для обмена

- фактический размер данных, содержащийся в буфере

- общий размер данных, которые мы хотим передать / получить через данную операцию

- идентификатор данной операции

- текущее состояние данной операции

После заполнения регистров данными и вызова RDPMC происходит переключение в VMM с целью дальнейшей обработки запроса.

2. В VMM происходит копирование данных в буфер VMM (который он разделяет с приложением уровня пользователя на уровне физической памяти). После копирования определяется, нужна ли какая-либо обработка данных на стороне VMM, и нужна ли последующая обработка на стороне приложения уровня пользователя. Если обработка на его стороне нужна (а чаще всего так и бывает), то после окончания обработки в VMM происходит HyperSwitch, и управление передается приложению уровня пользователя.

3. На стороне приложения уровня пользователя запрос первым делом попадает к диспетчеру OTG запросов. Тот смотрит на идентификатор запроса, и определяет его текущее состояние. Если запрос имеет состояние SEND, то это означает, что данные передаются с гостевой на хостовую операционную систему. В этом случае данные считываются в буфер для входящих данных и запрос завершается. Если запрос находится в состоянии EXECUTE, то это означает, что все данные с гостя получены, и запрос отправляется на обработку к обработчику данного запроса. Обработчик определяется из данных, посланных в регистрах вместе с запросом и может вызвать другую функцию для обработки, например, функцию драйвера нужного устройства. Наконец, если запрос находится в состоянии RECEIVE, то это означает, что данных с гостя нет, а нам надо передавать те данные, которые вернул нам наш обработчик запроса. В этом случае мы забираем часть выходного буфера, размером 4 килобайта, и передаем ее гостю посредством предоставленного совместного буфера (просто копируем туда данные).

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

В последующих двух частях описывается результат данного исследования - два варианта интерфейса, основывающиеся на вышеописанном механизме передачи данных Open ToolsGate.

6. Базовый вариант интерфейса для передачи данных устройств на основе Open ToolsGate

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

Базовый вариант интерфейса передачи данных

Основная преимущество данного интерфейса по сравнению с базовым механизмом OTG, это возможность использовать буферы данных, размером более 4 килобайт. Для достижения этой цели, мы создаем статическую библиотеку в гостевой операционной системе, которая будет поставляться всем пользователям данного интерфейса (вместе с заголовочным файлом, содержащим определение функций интерфейса). Функция, поставляемая данной библиотекой, будет принимать на вход гостевой пользовательский буфер с данными и возвращать указатель на возвращаемый буфер с данными. Внутри себя функция производит разбивку пользовательского буфера на фрагменты, размером 4 килобайта, а затем производит циклическую посылку этих фрагментов с одним и тем же идентификатором операции. После отправления всех сегментов данных, функция ожидает получения возвращаемого буфера. Буфер принимается аналогичным способом - по 4-рех килобайтным сегментам. После получения всех сегментов, из них собирается исходный буфер и отправляется на выход функции интерфейса. Благодаря этому, пользователь данного интерфейса со стороны гостевой операционной системы может не беспокоится по поводу деталей работы базового механизма OTG, а использовать достаточно простой интерфейс для обмена данными с хостовой операционной системой. Стоит также заметить, что изменения, вносимые на хостовую часть механизма OTG, довольно незначительны, т.к. в рамках диспетчеризации входящих OTG запросов существует механизм сборки / разбиения буферов из сегментов.

Тем не менее, данный механизм нельзя назвать достаточно эффективным, поскольку в рамках передачи буфера данных с гостевой на хостовую операционную систему при передачи каждого 4-рех килобайтного сегмента данных происходят следующие действия, сильно уменьшающие общую скорость передачи данных:

1. VMexit при переключении с гостевой операционной системы на VMM.

2. Копирование данных из гостевой памяти в общий буфер VMM и приложения уровня пользователя.

3. HyperSwitch при переключении контекста между VMM и хостовой операционной системой.

В расширенной модели интерфейса все эти недостатки устранены в значительной степени.

виртуализация интерфейс производительность

7. Расширенный вариант интерфейса для передачи данных устройств на основе Open ToolsGate

Концептуальная схема расширенного варианта интерфейса для передачи данных между гостевой и хостовой операционными системами представлен на рисунке.

Расширенный вариант интерфейса передачи данных

В расширенном варианте интерфейс, предоставляемый пользователю, аналогичен интерфейсу базового варианта (тот же API, также поставляется в виде библиотека + заголовочный файл). Различие заключается в способе передачи данных.

Когда пользователь вызывает функцию расширенного интерфейса для передачи данных, функция не передает буфер по 4-рех килобайтным сегментам (как это было в базовом механизме). Вместо этого, в 4-рех килобайтный буфер, используемый для передаваемых данных при вызове RDPMC, записываются адреса виртуальных страниц, на которых лежит гостевой пользовательский буфер. На каждую запись выделяется 4 байта из 4096. Адрес записывается не напрямую, а с 12-битным смещением (т.к. это адрес страницы, то эти биты нулевые). Это позволяет использовать 44-битный диапазон адресов, т.е. 16 Терабайт памяти.

После вызова RDPMC и передачи управления в VMM, вызывается обработчик OTG запросов на стороне VMM. Внутри него мы используем интерфейс виртуальной машины для получения физического адреса тех страниц, линейные адреса которых ранее были записаны в буфер обмена. В итоге, проделав данную операцию для всех адресов из списка, мы получаем аналогичный буфер, только заполненный уже гостевыми физическими, а не виртуальными, адресами. Дополнительно, в рамках получения физического адреса страницы, делается проверка на присутствие страницы в физической памяти. Если страница отсутствует, то мы приостанавливаем выполнение кода обработчика, а затем эмулируем PAGE_FAULT для данной страницы в гостевой операционной системе. Гость обрабатывает данный PAGE_FAULT, а затем перезапускает инструкцию RDPMC, чтобы мы могли корректно получить гостевой физический адрес страницы. После того, как адреса всех страниц из списка конвертированы в гостевые физические, мы перекопируем буфер с адресами в буфер, разделяемый VMM и приложением уровня пользователя, и передаем второму управление.

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

В результате, данный метод устранил все недостатки базового варианта интерфейса для обмена данными. При использовании расширенного метода, нам не нужно копировать все данные во время обработки в VMM (мы копируем только 4-рех килобайтный буфер со списком адресов). Также, поскольку адреса страниц буфера передаются на хостовую операционную систему за один вызов RDPMC (если размер буфера данных не превышает 4 Мегабайта), то и VMexit, и HyperSwitch происходит всего один раз за весь цикл обмена данными (при использовании базового метода, при передаче 4 Мегабайт данных, число переключений контекста равно 1024). Благодаря этому, скорость передачи данных расширенного метода должна значительно превосходить скорость базового метода.

Стоит также заметить, что в случае данных, размером более 4 Мегабайт, требуется надстройка над расширенным механизмом передачи данных, которая будет разбивать буфер на 4-рех Мегабайтные сегменты и передавать их по отдельности. Данная надстройка, по своей концепции, практически идентична концепции базового интерфейса передачи данных.

8. Сравнение производительности вариантов

В предыдущих двух главах были описаны два механизма передачи данных на основе OTG. Было сказано об их преимуществах и недостатках относительно друг друга. Для того, чтобы иметь более четкое представление о возможности использования данных интерфейсов для передачи данных между устройствами и гостевой операционной системой, был проведен ряд измерений скорости передачи данных в зависимости от размера передаваемых данных и механизма передачи (базовый или расширенный). Результаты этих измерений приведены в таблице.

Зависимость скорости передачи от механизма и размера данных

1 Мб

2Мб

3Мб

4Мб

Базовый

78 Мб/сек

83 Мб/сек

85 Мб/сек

80 Мб/сек

Расширенный

121 Мб/сек

126 Мб/сек

132 Мб/сек

134 Мб/сек

Из таблицы видно, что скорость передачи данных с использованием базового механизма практически не зависит от размера данных. Это лего объясняется тем, что число ресурсозатратных операций при каждом запросе (копирование, VMexit, HyperSwitch) прямо пропорционально размеру данных.

С другой стороны, скорость передачи данных с использованием расширенного механизма, хоть и превосходит скорость базового механизма, но всего лишь примерно в полтора раза, что довольно неожиданно, учитывая тот факт, что наиболее очевидные проблемы производительности были базового механизма были устранены в дополнительном. Также можно заметить, что с ростом объема данных, скорость растет очень медленно, что не согласуется с теорией, т.к. передача любого блока данных, размером до 4 Мегабайт, должна происходить за одно переключение из гостевой в хостовую операционную систему, т.е. примерно за одинаковое время. Все это указывает на наличие некоторых ресурсозатратных операции, которые не были учтены при расчетах и разработке расширенной версии передачи данных.

Источник: https://otherreferats.allbest.ru/download/1105667/