Заголовок pcivirt.h

Справочное руководство по использованию интерфейсов, используемых для предоставления виртуальных ФС виртуальной машине.

Устройства, соответствующие спецификации PCI Express Single-Root I/O Virtualization (SR-IOV), могут предоставлять несколько интерфейсов для устройства. Эти интерфейсы, известные как виртуальные функции (VF), являются независимыми и предоставляются через исходный интерфейс устройства, известный как физическая функция (PF). Например, сетевая плата Ethernet, поддерживающая SR-IOV, может быть спроектирована таким образом, чтобы иметь коммутатор с одним физическим портом Ethernet (подключенным к физическому проводу) и множеством виртуальных портов Ethernet.

Конфигурационное пространство PF позволяет драйверу PF управлять ресурсами PCI VF, включая отображаемое в память пространство ввода-вывода и прерывания, сигнализируемые сообщениями. Поскольку ВФ являются подмножеством готового устройства, их аппаратное обеспечение может быть менее дорогостоящим, чем традиционная функция в многофункциональном корпусе. Это позволяет производителю устройства создавать больше интерфейсов и централизованно управлять любыми общими ресурсами.

Когда Windows работает непосредственно на аппаратном обеспечении компьютера, драйверы устройств участвуют в операциях, связанных с Plug and Play, управлением питанием, управлением прерываниями и другими задачами. Доверенный драйвер шины Windows и уровень аппаратной абстракции (HAL) самостоятельно настраивают шину и настраивают всю шину. Драйвер работает с одним и тем же уровнем привилегий, и в режиме ядра нет границ доверия.

Если Windows работает на виртуальной машине, эти предположения не применяются. Виртуальные ВФ могут быть переданы под контроль непривилегированной виртуальной машины. Тем не менее, оборудование должно быть проверено на безопасность, чтобы это не повлияло на безопасность или производительность системы.

Когда драйвер, работающий на VF, запрашивает чтение или запись пространства конфигурации, этот запрос принимается стеком виртуализации и отправляется в драйвер PF SR-IOV устройства. Водитель PF несет ответственность за ответ на эти запросы и предоставление данных для VF. Драйвер PF может время от времени требовать, чтобы запрос на чтение или запись конфигурации передавался на оборудование.

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

Диаграмма, показывающая виртуализацию PCI.

Требования к оборудованию

СистемаSR-IOV используемая для назначения устройств, должна соответствовать требованиям к SR-IOV сети и прямому назначению устройств. Система должна иметь IOMMU, который должен быть настроен таким образом, чтобы передать управление устройствами операционной системе, а PCIe ACS (Access Control Services) должен быть включен и настроен для использования операционной системой. Наконец, рассматриваемое устройство не должно использовать прерывания на основе линий и не должно требовать ATS (службы трансляции адресов).

Более подробная информация здесь:

Чтобы определить, поддерживает ли система назначение устройств, и будет ли конкретное устройство PCI работать для назначения устройств:

Запросы для SR-IOV устройств

GUID_DEVINTERFACE_VIRTUALIZABLE_DEVICE — это интерфейс класса устройств, который предоставляется драйверами для SR-IOV устройств. Этот идентификатор GUID позволяет запрашивать все стеки устройств, которые предоставляют различные таблицы функций, используемые для управления функциями устройства, связанными с виртуализацией. После того как драйвер зарегистрирует GUID, отдельные возможности обнаруживаются путем отправки IRP_MN_QUERY_INTERFACE. Водитель должен ответить на этот запрос GUID_SRIOV_DEVICE_INTERFACE_STANDARD. Водители также должны обрабатывать IOCTL_SRIOV_NOTIFICATION и IOCTL_SRIOV_EVENT_COMPLETE.

Драйвер для SR_IOV устройства, которое работает на привилегированной виртуальной машине, — это операционная система узла. Он владеет Plug-and-Play и управлением питанием для всей машины, а также предоставляет PCI Express SR-IOV Virtual Functions в непривилегированных виртуальных машинах, должен предоставлять GUID_SRIOV_DEVICE_INTERFACE_STANDARD (определено в заголовке Pcivirt.h). Этим драйвером может быть драйвер PCI Express SR-IOV Physical Function (PF), который создает FDO, или это может быть более низкий фильтр на этом узле устройства в случае, когда FDO управляется драйвером порта.

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

В реализации EVT_WDF_DRIVER_DEVICE_ADD драйвера PF выполните следующие задачи:

  • После вызова WdfDeviceCreate для создания объекта функционального устройства (FDO) вызовите WdfDeviceCreateDeviceInterface для регистрации GUID_DEVINTERFACE_VIRTUALIZABLE_DEVICE. Это позволяет стеку виртуализации извлекать дескриптор устройства на SR-IOV устройство.
  • Обнажите GUID_SRIOV_DEVICE_INTERFACE_STANDARD.
    • Инициализируйте структуру SRIOV_DEVICE_INTERFACE_STANDARD и установите ее в указатели функций обратного вызова, реализованных драйвером PF.
    • Настройте структуру, вызвав WDF_QUERY_INTERFACE_CONFIG_INIT.
    • Зарегистрируйте интерфейс в FDO, вызвав WdfDeviceAddQueryInterface.
// Make the device visible as an assignable device.
//
status = WdfDeviceCreateDeviceInterface(
    fdo,
    &GUID_DEVINTERFACE_VIRTUALIZABLE_DEVICE,
    NULL);
if (!NT_SUCCESS(status))
{
    TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT,
                "Failed to create interface: %!STATUS!",
                status);
    goto Cleanup;
}

//
// Expose SRIOV_DEVICE_INTERFACE_STANDARD
//
RtlZeroMemory(&sriovInterface, sizeof(sriovInterface));
sriovInterface.Size = sizeof(sriovInterface);
sriovInterface.Version = 1;
sriovInterface.Context = deviceContext;
sriovInterface.InterfaceReference = Virtualization_ReferenceInterface;
sriovInterface.InterfaceDereference = Virtualization_DereferenceInterface;
sriovInterface.ReadVfConfig = Virtualization_ReadConfig;
sriovInterface.WriteVfConfig = Virtualization_WriteConfig;
sriovInterface.ReadVfConfigBlock = Virtualization_ReadBlock;
sriovInterface.WriteVfConfigBlock = Virtualization_WriteBlock;
sriovInterface.ResetVf = Virtualization_ResetFunction;
sriovInterface.SetVfPowerState = Virtualization_SetPowerState;
sriovInterface.GetDeviceLocation = Virtualization_GetDeviceLocation;
sriovInterface.GetVendorAndDevice = Virtualization_GetVendorAndDevice;
sriovInterface.QueryProbedBars = Virtualization_QueryProbedBars;
sriovInterface.QueryLuid = Virtualization_QueryLuid;


WDF_QUERY_INTERFACE_CONFIG_INIT(&qiConfig,
                                (PINTERFACE)&sriovInterface,
                                &GUID_SRIOV_DEVICE_INTERFACE_STANDARD,
                                NULL);

status = WdfDeviceAddQueryInterface(fdo, &qiConfig);

if (!NT_SUCCESS(status))
{
    TraceEvents(TRACE_LEVEL_ERROR, DBG_INIT,
                "WdfDeviceAddQueryInterface failed: %!STATUS!\n",
                status);
    goto Cleanup;
}

Обработка событий Plug and Play

Стек виртуализации отвечает за отправку соответствующих сообщений на виртуальную машину, ожидание ответа (с тайм-аутом) и в случае отсутствия ответа виртуальной машины, а также за применение соответствующих действий, таких как наложение вето на событие PnP или неожиданное удаление устройства из непривилегированной виртуальной машины. Драйверы PF, реализующие GUID_DEVINTERFACE_VIRTUALIZABLE_DEVICE, также должны обрабатывать эти запросы управления вводом-выводом, которые позволяют стеку виртуализации реагировать на события PnP.

  • Стек виртуализации сначала отправляет IOCTL_SRIOV_ATTACH на устройство. Это уведомляет устройство о том, что стек виртуализации должен быть уведомлен об определенных событиях PnP.

  • Это действует до тех пор, пока стек виртуализации не отправит IOCTL_SRIOV_DETACH.

  • Стек виртуализации запрашивает устройства о событиях PnP, отправляя IOCTL_SRIOV_NOTIFICATION запросы. Драйвер PF может сообщить стеку виртуализации о событии PnP, выполнив запрос IOCTL_SRIOV_NOTIFICATION.

  • Стек виртуализации разблокирует эти события, отправляя IOCTL_SRIOV_EVENT_COMPLETE.

pcivirt.h содержит следующие программные интерфейсы:

IoCTLs

 
IOCTL_SRIOV_ATTACH

Запрос указывает, что стек виртуализации хочет зарегистрировать события Plug and Play, полученные устройством SR-IOV.
IOCTL_SRIOV_DETACH

Запрос указывает, что стек виртуализации хочет отменить регистрацию для событий Plug and Play (ранее зарегистрированных через запрос IOCTL_SRIOV_ATTACH).
IOCTL_SRIOV_EVENT_COMPLETE

Запрос указывает, что стек виртуализации или устройство SR-IOV получило одно из событий, перечисленных в SRIOV_PF_EVENT.
IOCTL_SRIOV_INVALIDATE_BLOCK

Запрос IOCTL_SRIOV_INVALIDATE_BLOCK указывает, что стек виртуализации хочет сбросить содержимое указанного блока конфигурации.
IOCTL_SRIOV_MITIGATED_RANGE_UPDATE

Запрос IOCTL_SRIOV_MITIGATED_RANGE_UPDATE указывает, что стек виртуализации хочет обновиться до диапазонов устранения рисков.
IOCTL_SRIOV_NOTIFICATION

Запрос указывает, что стек виртуализации хочет получать уведомления при возникновении одного из событий, перечисленных в SRIOV_PF_EVENT.
IOCTL_SRIOV_PROXY_QUERY_LUID

Этот запрос предоставляет локальный уникальный идентификатор устройства SR_IOV, реализующего интерфейс.
IOCTL_SRIOV_QUERY_MITIGATED_RANGE_COUNT

Запрос определяет диапазоны сопоставленных с памятью операций ввода-вывода, которые должны быть устранены.
IOCTL_SRIOV_QUERY_MITIGATED_RANGES

Запрос определяет определенные диапазоны, на которые должны размещаться перехваты.

Функции обратного вызова

 
READ_WRITE_MITIGATED_REGISTER

Считывает или записывает данные в адресные пространства с устранением рисков.
SRIOV_GET_DEVICE_LOCATION

Извлекает сведения о текущем расположении устройства PCI на шине, например сегмент PCI, шина, номер устройства и функции.
SRIOV_GET_MMIO_REQUIREMENTS

Эта функция обратного вызова не поддерживается.
SRIOV_GET_RESOURCE_FOR_BAR

Возвращает преобразованный ресурс для определенного базового регистра адресов (BAR).
SRIOV_GET_VENDOR_AND_DEVICE_IDS

Предоставляет поставщику и идентификатору устройства для виртуальной функции PCI Express SR-IOV (VF) для создания более универсального идентификатора Plug and Play для VF. Эти идентификаторы нельзя считывать непосредственно из пространства конфигурации VF.
SRIOV_QUERY_LUID

Возвращает локальный уникальный идентификатор устройства SR-IOV.
SRIOV_QUERY_LUID_VF

Возвращает SR-IOV виртуальную функцию PCI Express (VF) с уникальным идентификатором.
SRIOV_QUERY_PROBED_BARS

Запрашивает данные, считывающие данные из базовых регистров адресов физической функции (BAR), если значение -1 были записаны в них в первую очередь.
SRIOV_QUERY_PROBED_BARS_2

Запрашивает данные, считывающие данные из указанных базовых регистров виртуальных функций (BAR) PCI Express SR-IOV ( VF), если значение -1 были записаны в них первым.
SRIOV_QUERY_VF_LUID

Возвращает локальный уникальный идентификатор функции PCI Express SR-IOV Virtual Function (VF).
SRIOV_READ_BLOCK

Считывает данные из указанного блока конфигурации pci Express SR-IOV виртуальной функции (VF).
SRIOV_READ_CONFIG

Считывает данные из пространства конфигурации указанной функции PCI Express SR-IOV Virtual Function (VF).
SRIOV_RESET_FUNCTION

Сбрасывает указанную виртуальную функцию PCI Express SR-IOV (VF).
SRIOV_SET_POWER_STATE

Задает состояние питания указанной функции PCI Express SR-IOV Virtual Function (VF).
SRIOV_WRITE_BLOCK

Записывает данные в указанный блок конфигурации pci Express SR-IOV виртуальной функции (VF).
SRIOV_WRITE_CONFIG

Записывает данные конфигурации в виртуальную функцию PCI Express SR-IOV (VF).

Структуры

 
MITIGABLE_DEVICE_INTERFACE

Сохраняет указатели функций на функции обратного вызова, реализованные драйвером физической функции (PF) для мимичивого интерфейса устройства.
SRIOV_DEVICE_INTERFACE_STANDARD

Сохраняет указатели функций на функции обратного вызова, реализованные драйвером физической функции (PF) в стеке устройств для устройства SR-IOV.
SRIOV_DEVICE_INTERFACE_STANDARD_2

Сохраняет указатели функций на функции обратного вызова, реализованные драйвером физической функции (PF) в стеке устройств для устройства SR-IOV. Это расширенная версия SRIOV_DEVICE_INTERFACE_STANDARD.
SRIOV_INVALIDATE_BLOCK

Содержит сведения о блоке конфигурации. Эта структура используется в запросе IOCTL_SRIOV_INVALIDATE_BLOCK.
SRIOV_MITIGATED_RANGE_COUNT_INPUT

Эта структура используется в качестве входного буфера для запроса IOCTL_SRIOV_QUERY_MITIGATED_RANGE_COUNT, чтобы определить диапазоны сопоставленного с памятью пространства ввода-вывода, которое необходимо устранить.
SRIOV_MITIGATED_RANGE_COUNT_OUTPUT

Эти структуры — это выходной буфер, полученный запросом IOCTL_SRIOV_QUERY_MITIGATED_RANGE_COUNT, который содержит массив диапазонов пространства ввода-вывода, сопоставленного с памятью, которое должно быть устранено.
SRIOV_MITIGATED_RANGE_UPDATE_INPUT

Эта структура используется в качестве входного буфера для запроса IOCTL_SRIOV_MITIGATED_RANGE_UPDATE, чтобы указать виртуальную функцию (VF), пространство ввода-вывода, сопоставленное с памятью, которое должно быть устранено.
SRIOV_MITIGATED_RANGE_UPDATE_OUTPUT

Эти структуры — это выходной буфер, полученный запросом IOCTL_SRIOV_MITIGATED_RANGE_UPDATE, указывающим виртуальную функцию (VF), память которой была устранена.
SRIOV_MITIGATED_RANGES_INPUT

Эта структура представляет собой входной буфер в запросе IOCTL_SRIOV_QUERY_MITIGATED_RANGES, чтобы получить определенные диапазоны, на которые должны размещаться перехваты.
SRIOV_MITIGATED_RANGES_OUTPUT

Эта структура представляет собой выходной буфер, полученный запросом IOCTL_SRIOV_QUERY_MITIGATED_RANGES, чтобы получить определенные диапазоны, на которые должны размещаться перехваты.
SRIOV_PNP_EVENT_COMPLETE

Сохраняет состояние события, которое драйвер SR-IOV физической функции (PF) должен задать для даже завершения Plug and Play. Эта структура используется в входном буфере запроса IOCTL_SRIOV_EVENT_COMPLETE.
SRIOV_PROXY_QUERY_LUID_OUTPUT

Сохраняет локальный уникальный идентификатор устройства SR_IOV, реализующего интерфейс. Эта структура представляет собой выходной буфер для запроса IOCTL_SRIOV_PROXY_QUERY_LUID.

Перечисления

 
SRIOV_PF_EVENT

Определяет значения событий для устройства SR-IOV.