Encabezado pcivirt.h

Guía de referencia para el uso de interfaces que se usan para exponer las máquinas virtuales a una máquina virtual.

Los dispositivos que se ajustan a la especificación pci Express Single-Root virtualización de E/S (SR-IOV) pueden proporcionar varias interfaces al dispositivo. Estas interfaces, conocidas como Funciones virtuales , son independientes y se proporcionan a través de la interfaz de dispositivo inicial, conocida como función física (PF). Por ejemplo, una NIC Ethernet compatible con SR-IOV se puede diseñar para tener un conmutador con un puerto Ethernet físico (conectado a la conexión física) y muchos puertos Ethernet virtuales.

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

Cuando Windows se ejecuta directamente en el hardware de la máquina, los controladores de dispositivo 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 una configuración de nivel de abstracción de hardware (HAL) propio de bus y configura todo el bus. El controlador se ejecuta en el mismo nivel de privilegios 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 máquinas virtuales se pueden poner bajo el control de una máquina virtual sin privilegios. Sin embargo, el hardware debe estar comprobado para que la seguridad o el rendimiento del sistema no se vean afectados.

Cuando un controlador que se ejecuta en el VF solicita un espacio de configuración de lectura o escritura, la pila de virtualización recibe la solicitud y se envía al controlador PF del dispositivo SR-IOV. Es responsabilidad del controlador PF responder a esas solicitudes y proporcionar detalles para el VF. El controlador PF puede requerir ocasionalmente que una solicitud de lectura o escritura de configuración que se pasa 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.

Virtualización PCI.

Requisitos de hardware

El sistema que se va a usar para la asignación de dispositivos SR-IOV debe cumplir los requisitos para las redes SR-IOV y la asignación directa de dispositivos. El sistema debe tener un IOMMU, que iomMU debe estar configurado para dar control de los dispositivos al sistema operativo, y PCIe ACS (Access Control Services) debe estar habilitado y configurado para su uso por parte del sistema operativo. Por último, el dispositivo en cuestión no debe usar interrupciones basadas en líneas y no debe requerir ATS (Servicios de traducción de direcciones).

Aquí puede encontrar más información:

Todo lo que quería saber sobre SR-IOV en Hyper-V. 1ª parte

Asignación discreta de dispositivos: descripción y fondo

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

Script discreto de asignación de dispositivos

Consulta de dispositivos SR-IOV

GUID_DEVINTERFACE_VIRTUALIZABLE_DEVICE es una interfaz de clase de dispositivo proporcionada por controladores para dispositivos SR-IOV. 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, las funcionalidades individuales se detectan mediante el envío de IRP_MN_QUERY_INTERFACE. El controlador debe responder a esa solicitud con GUID_SRIOV_DEVICE_INTERFACE_STANDARD. Los controladores también deben controlar 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 la administración de alimentación y plug-and-play para una máquina completa y expone las funciones virtuales PCI Express SR-IOV en máquinas virtuales sin privilegios, debe proporcionar el GUID_SRIOV_DEVICE_INTERFACE_STANDARD (definido en el encabezado Pcivirt.h). Ese controlador puede ser el controlador de función física (PF) PCI Express SR-IOV 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 las máquinas virtuales.

En la implementación del 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 de SRIOV_DEVICE_INTERFACE_STANDARD y establezca 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 el 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;
    }

Controlar eventos de 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 no responda la máquina virtual, y aplicar la acción adecuada, como el bloqueo del evento PnP o la eliminación sorpresa del 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 recibir notificaciones sobre determinados eventos PnP.

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

  • La pila de virtualización consulta 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 de 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:

IOCTL

 
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 previamente 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 recibieron 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 el segmento PCI, el bus, el dispositivo y el 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 PCI Express SR-IOV (VF) que se usará para generar un id. de Plug and Play más genérico para el 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 PCI Express SR-IOV (VF) 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ó primero en ellos.
SRIOV_QUERY_PROBED_BARS_2

Consulta los datos leídos desde los registros de direcciones base (BAR) de PCI Express SR-IOV especificados si el valor -1 se escribió primero en ellos.
SRIOV_QUERY_VF_LUID

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

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

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

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

Establece el estado de potencia de la función virtual PCI Express SR-IOV (VF) especificada.
SRIOV_WRITE_BLOCK

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

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

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 para el del dispositivo 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 para el del dispositivo 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 de IOCTL_SRIOV_INVALIDATE_BLOCK.
SRIOV_MITIGATED_RANGE_COUNT_INPUT

Esta estructura se usa como un 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

Esta estructura es 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 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 SR-IOV (PF) debe establecer para la finalización uniforme de Plug and Play. Esta estructura se usa en el búfer de entrada de la solicitud de 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.