Compartir a través de


Encabezado pcivirt.h

Guía de referencia para el uso de interfaces utilizadas que exponen VF a una máquina virtual.

Los dispositivos que cumplen con la especificación PCI Express Single-Root I/O Virtualization (SR-IOV) pueden proporcionar varias interfaces al dispositivo. Estas interfaces, conocidas como funciones virtuales (VF), son independientes y se proporcionan a través de la interfaz inicial del dispositivo, conocida como función física (PF). Por ejemplo, una NIC Ethernet que admite SR-IOV puede diseñarse para tener un conmutador con un puerto Ethernet físico (conectado al cable físico) y muchos puertos Ethernet virtuales.

El espacio de configuración del PF permite que el controlador PF administre los recursos PCI del VF, incluido el espacio de E/S asignado a la memoria y las interrupciones señalizadas por mensajes. Dado que los VF son un subconjunto de un dispositivo completo, pueden ser menos costosos de exponer en hardware que una función tradicional en un paquete multifunción. Esto permite al fabricante del dispositivo crear más interfaces y administrar los recursos compartidos de forma centralizada.

Cuando Windows se ejecuta directamente en el hardware de la máquina, los controladores de dispositivos participan en operaciones relacionadas con Plug and Play, administración de energía, administración de interrupciones y otras tareas. Un controlador de bus de Windows de confianza y la capa de abstracción de hardware (HAL) poseen la configuración del bus y configuran todo el bus. El controlador se ejecuta dentro del mismo nivel de privilegio y no hay límites de confianza en el modo kernel.

Cuando Windows se ejecuta en una máquina virtual (VM), esas suposiciones no se aplican. Las VF se pueden poner bajo el control de una máquina virtual sin privilegios. Sin embargo, se debe comprobar la seguridad del hardware para que la seguridad o el rendimiento del sistema no se vean afectados.

Cuando un controlador que se ejecuta en el VF solicita una lectura o escritura del espacio de configuración, la pila de virtualización recibe la solicitud y la envía al controlador PF del dispositivo SR-IOV. Es responsabilidad del controlador PF responder a esas solicitudes y proporcionar detalles para el VF. En ocasiones, el controlador PF puede requerir que una solicitud de lectura o escritura de configuración se pase al hardware.

La pila usa una MMU de E/S para diferenciar el tráfico procedente de las distintas interfaces que expone el dispositivo, aplicando la directiva sobre las regiones de memoria a las que un dispositivo puede acceder y a qué interrupciones puede generar.

Diagrama que muestra la virtualización PCI.

Requisitos de hardware

El sistema que se utilizará para la asignación de dispositivos SR-IOV debe cumplir con los requisitos para la red SR-IOV y la asignación directa de dispositivos. El sistema debe tener una IOMMU, esa IOMMU debe estar configurada para ceder el control de los dispositivos al sistema operativo, y PCIe ACS (Servicios de control de acceso) debe estar habilitado y configurado para su uso por el sistema operativo. Por último, el dispositivo en cuestión no debe utilizar interrupciones basadas en línea y no debe requerir ATS (Servicios de traducción de direcciones).

Más información aquí:

Para determinar si un sistema admite la asignación de dispositivos y si un dispositivo PCI en particular funcionará para la asignación de dispositivos:

Consulta de dispositivos SR-IOV

GUID_DEVINTERFACE_VIRTUALIZABLE_DEVICE es una interfaz de clase de dispositivo que proporcionan los controladores para SR-IOV dispositivos. Este GUID proporciona una manera de consultar todas las pilas de dispositivos que exponen las distintas tablas de funciones que se usan para administrar las características relacionadas con la virtualización del dispositivo. Una vez que el controlador registra el GUID, se detectan las funcionalidades individuales mediante el envío de IRP_MN_QUERY_INTERFACE. El conductor debe responder a esa solicitud con GUID_SRIOV_DEVICE_INTERFACE_STANDARD. Los conductores también deben manejar IOCTL_SRIOV_NOTIFICATION y IOCTL_SRIOV_EVENT_COMPLETE.

Un controlador para un dispositivo SR_IOV, que se ejecuta en una máquina virtual con privilegios, es el sistema operativo host. Posee Plug-and-Play y administración de energía para una máquina completa, y expone PCI Express SR-IOV Virtual Functions en máquinas virtuales sin privilegios, debe proporcionar el GUID_SRIOV_DEVICE_INTERFACE_STANDARD (definido en el encabezado Pcivirt.h). Ese controlador puede ser PCI Express SR-IOV controlador de función física (PF) que crea el FDO, o puede ser un filtro inferior en ese nodo de dispositivo en el caso de que un controlador de puerto administre el FDO.

La interfaz del dispositivo es necesaria para que el controlador pueda acceder al espacio de configuración de los VF.

En la implementación EVT_WDF_DRIVER_DEVICE_ADD del controlador PF, realice estas tareas:

  • Después de llamar a WdfDeviceCreate para crear el objeto de dispositivo de función (FDO), llame a WdfDeviceCreateDeviceInterface para registrar GUID_DEVINTERFACE_VIRTUALIZABLE_DEVICE. Esto permite que la pila de virtualización recupere un identificador de dispositivo en el dispositivo SR-IOV.
  • Exponga el GUID_SRIOV_DEVICE_INTERFACE_STANDARD.
    • Inicialice una estructura SRIOV_DEVICE_INTERFACE_STANDARD y establezca los miembros en punteros de función de las funciones de devolución de llamada implementadas por el controlador PF.
    • Configure la estructura llamando a WDF_QUERY_INTERFACE_CONFIG_INIT.
    • Registre la interfaz con FDO llamando a 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;
}

Control de eventos Plug and Play

La pila de virtualización es responsable de enviar los mensajes adecuados a la máquina virtual, esperar la respuesta (con un tiempo de espera) y, en caso de que la máquina virtual no responda, y aplicar las acciones adecuadas, como vetar el evento PnP o eliminar por sorpresa el dispositivo de la máquina virtual sin privilegios. Los controladores PF que implementan GUID_DEVINTERFACE_VIRTUALIZABLE_DEVICE también deben controlar estas solicitudes de control de E/S que permiten que la pila de virtualización reaccione a los eventos PnP.

  • La pila de virtualización envía primero IOCTL_SRIOV_ATTACH al dispositivo. Esto notifica al dispositivo que la pila de virtualización debe ser notificada sobre ciertos eventos PnP.

  • Esto está en vigor hasta que la pila de virtualización envía IOCTL_SRIOV_DETACH.

  • La pila de virtualización consulta a los dispositivos sobre eventos PnP mediante el envío de solicitudes IOCTL_SRIOV_NOTIFICATION. El controlador PF puede informar a la pila de virtualización de un evento PnP completando la solicitud IOCTL_SRIOV_NOTIFICATION.

  • La pila de virtualización desbloquea esos eventos mediante el envío de IOCTL_SRIOV_EVENT_COMPLETE.

pcivirt.h contiene las siguientes interfaces de programación:

IOCTLs

 
IOCTL_SRIOV_ATTACH

La solicitud indica que la pila de virtualización quiere registrarse para los eventos Plug and Play recibidos por el dispositivo SR-IOV.
IOCTL_SRIOV_DETACH

La solicitud indica que la pila de virtualización quiere anular el registro de los eventos Plug and Play (registrados anteriormente a través de la solicitud de IOCTL_SRIOV_ATTACH).
IOCTL_SRIOV_EVENT_COMPLETE

La solicitud indica que la pila de virtualización o el dispositivo SR-IOV recibió uno de los eventos enumerados en SRIOV_PF_EVENT.
IOCTL_SRIOV_INVALIDATE_BLOCK

La solicitud IOCTL_SRIOV_INVALIDATE_BLOCK indica que la pila de virtualización quiere restablecer el contenido del bloque de configuración especificado.
IOCTL_SRIOV_MITIGATED_RANGE_UPDATE

La solicitud IOCTL_SRIOV_MITIGATED_RANGE_UPDATE indica que la pila de virtualización quiere actualizar a los intervalos de mitigación.
IOCTL_SRIOV_NOTIFICATION

La solicitud indica que la pila de virtualización quiere recibir una notificación cuando se produce uno de los eventos enumerados en SRIOV_PF_EVENT.
IOCTL_SRIOV_PROXY_QUERY_LUID

Esta solicitud proporciona el identificador único local del dispositivo SR_IOV que implementa la interfaz.
IOCTL_SRIOV_QUERY_MITIGATED_RANGE_COUNT

La solicitud determina los intervalos de espacio de E/S asignados a memoria que deben mitigarse.
IOCTL_SRIOV_QUERY_MITIGATED_RANGES

La solicitud determina los intervalos específicos en los que se deben colocar las interceptaciones.

Funciones de devolución de llamada

 
READ_WRITE_MITIGATED_REGISTER

Lee o escribe en espacios de direcciones mitigados.
SRIOV_GET_DEVICE_LOCATION

Recupera información sobre la ubicación actual del dispositivo PCI en el bus, como segmento PCI, bus, dispositivo y número de función.
SRIOV_GET_MMIO_REQUIREMENTS

Esta función de devolución de llamada no se admite.
SRIOV_GET_RESOURCE_FOR_BAR

Obtiene el recurso traducido para un registro de direcciones base (BAR) específico.
SRIOV_GET_VENDOR_AND_DEVICE_IDS

Proporciona el proveedor y el identificador de dispositivo para una función virtual de PCI Express SR-IOV (VF) que se usará para generar un identificador de Plug and Play más genérico para VF. Estos identificadores no se pueden leer directamente desde el espacio de configuración de VF.
SRIOV_QUERY_LUID

Obtiene el identificador único local del dispositivo SR-IOV.
SRIOV_QUERY_LUID_VF

Obtiene la función virtual (VF) de PCI Express SR-IOV dada un identificador único.
SRIOV_QUERY_PROBED_BARS

Consulta los datos leídos de la dirección base (PF) de la función física registra (BAR) si el valor -1 se escribió en ellos primero.
SRIOV_QUERY_PROBED_BARS_2

Consulta los datos leídos de la dirección base de PCI Express SR-IOV virtual Function (VF) especificadas registra (BAR) si el valor -1 se escribió en ellos primero.
SRIOV_QUERY_VF_LUID

Obtiene el identificador único local de pci Express SR-IOV función virtual (VF).
SRIOV_READ_BLOCK

Lee los datos del bloque de configuración especificado de una función virtual (VF) de PCI Express SR-IOV.
SRIOV_READ_CONFIG

Lee los datos del espacio de configuración del pci Express especificado SR-IOV función virtual (VF).
SRIOV_RESET_FUNCTION

Restablece la función virtual (VF) de PCI Express SR-IOV especificada.
SRIOV_SET_POWER_STATE

Establece el estado de energía del pci express especificado SR-IOV función virtual (VF).
SRIOV_WRITE_BLOCK

Escribe datos en el bloque de configuración especificado de una función virtual (VF) de PCI Express SR-IOV.
SRIOV_WRITE_CONFIG

Escribe datos de configuración en una función virtual (VF) de PCI Express SR-IOV.

Estructuras

 
MITIGABLE_DEVICE_INTERFACE

Almacena punteros de función para las funciones de devolución de llamada implementadas por el controlador de función física (PF) para la interfaz de dispositivo mitigable.
SRIOV_DEVICE_INTERFACE_STANDARD

Almacena punteros de función para las funciones de devolución de llamada implementadas por el controlador de función física (PF) en la pila de dispositivos del dispositivo de SR-IOV.
SRIOV_DEVICE_INTERFACE_STANDARD_2

Almacena punteros de función para las funciones de devolución de llamada implementadas por el controlador de función física (PF) en la pila de dispositivos del dispositivo de SR-IOV. Se trata de una versión extendida de SRIOV_DEVICE_INTERFACE_STANDARD.
SRIOV_INVALIDATE_BLOCK

Contiene la información del bloque de configuración. Esta estructura se usa en una solicitud IOCTL_SRIOV_INVALIDATE_BLOCK.
SRIOV_MITIGATED_RANGE_COUNT_INPUT

Esta estructura se usa como búfer de entrada para la solicitud de IOCTL_SRIOV_QUERY_MITIGATED_RANGE_COUNT para determinar los intervalos de espacio de E/S asignados a memoria que se deben mitigar.
SRIOV_MITIGATED_RANGE_COUNT_OUTPUT

Estas estructuras son el búfer de salida recibido por la solicitud de IOCTL_SRIOV_QUERY_MITIGATED_RANGE_COUNT que contiene una matriz de intervalos de espacio de E/S asignado a memoria que se debe mitigar.
SRIOV_MITIGATED_RANGE_UPDATE_INPUT

Esta estructura se usa como un búfer de entrada para la solicitud de IOCTL_SRIOV_MITIGATED_RANGE_UPDATE para indicar la función virtual (VF) cuyo espacio de E/S asignado a memoria debe mitigarse.
SRIOV_MITIGATED_RANGE_UPDATE_OUTPUT

Esta estructura es el búfer de salida recibido por la solicitud de IOCTL_SRIOV_MITIGATED_RANGE_UPDATE que indica la función virtual (VF) cuyo espacio de E/S asignado a memoria se ha mitigado.
SRIOV_MITIGATED_RANGES_INPUT

Esta estructura es el búfer de entrada de la solicitud de IOCTL_SRIOV_QUERY_MITIGATED_RANGES para obtener los intervalos específicos en los que se deben colocar las interceptaciones.
SRIOV_MITIGATED_RANGES_OUTPUT

Esta estructura es el búfer de salida recibido por la solicitud de IOCTL_SRIOV_QUERY_MITIGATED_RANGES para obtener los intervalos específicos en los que se deben colocar las interceptaciones.
SRIOV_PNP_EVENT_COMPLETE

Almacena el estado de un evento que el controlador de función física (PF) de SR-IOV debe establecer para la finalización uniforme de Plug and Play. Esta estructura se usa en el búfer de entrada de la solicitud IOCTL_SRIOV_EVENT_COMPLETE.
SRIOV_PROXY_QUERY_LUID_OUTPUT

Almacena el identificador único local del dispositivo SR_IOV que implementa la interfaz. Esta estructura es el búfer de salida de la solicitud de IOCTL_SRIOV_PROXY_QUERY_LUID.

Enumeraciones

 
SRIOV_PF_EVENT

Define los valores de evento para el dispositivo SR-IOV.