Partager via


En-tête pcivirt.h

Guide de référence pour l’utilisation des interfaces utilisées pour exposer des VF à une machine virtuelle.

Les périphériques conformes à la spécification PCI Express Single-Root I/O Virtualization (SR-IOV) peuvent fournir plusieurs interfaces au périphérique. Ces interfaces, appelées fonctions virtuelles (VF), sont indépendantes et sont fournies par l’interface initiale du périphérique, connue sous le nom de fonction physique (PF). Par exemple, une carte réseau Ethernet qui prend en charge SR-IOV peut être conçue pour avoir un commutateur avec un port Ethernet physique (connecté au fil physique) et de nombreux ports Ethernet virtuels.

L’espace de configuration du PF permet au pilote PF de gérer les ressources PCI du VF, y compris l’espace d’E/S mappé en mémoire et les interruptions signalées par message. Étant donné que les VF sont un sous-ensemble d’un périphérique complet, ils peuvent être moins coûteux à exposer dans le matériel qu’une fonction traditionnelle dans un boîtier multifonction. Cela permet au fabricant d’appareils de créer davantage d’interfaces et de gérer de manière centralisée les ressources partagées.

Lorsque Windows s’exécute directement sur le matériel de la machine, les pilotes de périphériques participent aux opérations liées au Plug-and-Play, à la gestion de l’alimentation, à la gestion des interruptions et à d’autres tâches. Un pilote de bus Windows approuvé et un protocole HAL (Hardware Abstraction Layer) possèdent la configuration du bus et configurent l’intégralité du bus. Le pilote s’exécute dans le même niveau de privilèges et il n’y a pas de limites de confiance en mode noyau.

Lorsque Windows s’exécute sur une machine virtuelle, ces hypothèses ne s’appliquent pas. Les VF peuvent être placés sous le contrôle d’une machine virtuelle non privilégiée. Cependant, la sécurité du matériel doit être vérifiée afin de ne pas affecter la sécurité ou les performances du système.

Lorsqu’un pilote s’exécutant sur le VF demande une lecture ou une écriture d’un espace de configuration, la demande est reçue par la pile de virtualisation et envoyée au pilote PF du périphérique SR-IOV. Il est de la responsabilité du pilote PF de répondre à ces demandes et de fournir des détails pour le VF. Le pilote PF peut parfois exiger qu’une demande de lecture ou d’écriture de configuration soit transmise au matériel.

La pile utilise une MMU d’E/S pour différencier le trafic provenant des différentes interfaces exposées par l’appareil, en appliquant une stratégie sur les régions de mémoire auxquelles un appareil peut accéder et quelles interruptions il peut générer.

Schéma illustrant la virtualisation PCI.

Configuration matérielle requise

Le système à utiliser pour SR-IOV'attribution de périphérique doit répondre aux exigences de mise en réseau SR-IOV et d’attribution directe de périphérique. Le système doit disposer d’un IOMMU, celui-ci doit être configuré pour donner le contrôle des périphériques au système d’exploitation, et PCIe ACS (Access Control Services) doit être activé et configuré pour être utilisé par le système d’exploitation. Enfin, l’appareil en question ne doit pas utiliser d’interruptions basées sur la ligne et ne doit pas nécessiter d’ATS (Address Translation Services).

Plus d’informations ici :

Pour déterminer si un système prend en charge l’attribution de périphériques et si un périphérique PCI particulier fonctionnera pour l’attribution de périphériques :

Interrogation de SR-IOV appareils

GUID_DEVINTERFACE_VIRTUALIZABLE_DEVICE s’agit d’une interface de classe de périphérique fournie par les pilotes pour SR-IOV périphériques. Ce GUID permet d’interroger toutes les piles de périphériques qui exposent les différentes tables de fonctions utilisées pour gérer les fonctionnalités liées à la virtualisation du périphérique. Une fois que le pilote a enregistré le GUID, les fonctionnalités individuelles sont découvertes par l’envoi de IRP_MN_QUERY_INTERFACE. Le conducteur doit répondre à cette demande par GUID_SRIOV_DEVICE_INTERFACE_STANDARD. Les conducteurs doivent également gérer IOCTL_SRIOV_NOTIFICATION et IOCTL_SRIOV_EVENT_COMPLETE.

Le système d’exploitation hôte est le pilote d’un périphérique SR_IOV qui s’exécute dans une machine virtuelle privilégiée. Il possède le Plug-and-Play et la gestion de l’alimentation pour une machine entière, et expose les fonctions PCI Express SR-IOV virtuelles dans les machines virtuelles non privilégiées, doit fournir le GUID_SRIOV_DEVICE_INTERFACE_STANDARD (défini dans l’en-tête Pcivirt.h). Il peut s’agir d’un pilote PF (SR-IOV de fonction physique PCI Express) qui crée le FDO, ou d’un filtre inférieur sur ce nœud de périphérique dans le cas où le FDO est géré par un pilote de port.

L’interface de périphérique est requise pour que le pilote puisse accéder à l’espace de configuration des VF.

Dans l’implémentation EVT_WDF_DRIVER_DEVICE_ADD du pilote PF, effectuez les tâches suivantes :

  • Après avoir appelé WdfDeviceCreate pour créer la fonction objet de périphérique (FDO), appelez WdfDeviceCreateDeviceInterface pour enregistrer GUID_DEVINTERFACE_VIRTUALIZABLE_DEVICE. Cela permet à la pile de virtualisation de récupérer un descripteur de périphérique sur le périphérique SR-IOV.
  • Exposez le GUID_SRIOV_DEVICE_INTERFACE_STANDARD.
    • Initialisez une structure SRIOV_DEVICE_INTERFACE_STANDARD et définissez les membres sur les pointeurs de fonction des fonctions de rappel implémentées par le pilote PF.
    • Configurez la structure en appelant WDF_QUERY_INTERFACE_CONFIG_INIT.
    • Enregistrez l’interface auprès du FDO en appelant 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;
}

Gestion des événements Plug and Play

La pile de virtualisation est chargée d’envoyer les messages appropriés à la machine virtuelle, d’attendre la réponse (avec un délai d’expiration) et en cas de machine virtuelle qui ne répond pas, et d’appliquer les actions appropriées, telles que le veto à l’événement PnP ou la suppression surprise du périphérique de la machine virtuelle non privilégiée. Les pilotes PF qui implémentent GUID_DEVINTERFACE_VIRTUALIZABLE_DEVICE doivent également gérer ces demandes de contrôle d’E/S qui permettent à la pile de virtualisation de réagir aux événements PnP.

  • La pile de virtualisation envoie d’abord IOCTL_SRIOV_ATTACH à l’appareil. Cela informe l’appareil que la pile de virtualisation doit être informée de certains événements PnP.

  • Cette fonction est active jusqu’à ce que la pile de virtualisation envoie IOCTL_SRIOV_DETACH.

  • La pile de virtualisation interroge les périphériques sur les événements PnP en envoyant des requêtes IOCTL_SRIOV_NOTIFICATION. Le pilote PF peut informer la pile de virtualisation d’un événement PnP en complétant la demande IOCTL_SRIOV_NOTIFICATION.

  • La pile de virtualisation débloque ces événements en envoyant des IOCTL_SRIOV_EVENT_COMPLETE.

pcivirt.h contient les interfaces de programmation suivantes :

IOCTLs

 
IOCTL_SRIOV_ATTACH

La demande indique que la pile de virtualisation souhaite s’inscrire aux événements Plug-and-Play reçus par l’appareil SR-IOV.
IOCTL_SRIOV_DETACH

La requête indique que la pile de virtualisation souhaite annuler l’inscription pour les événements Plug-and-Play (précédemment inscrits via la demande de IOCTL_SRIOV_ATTACH).
IOCTL_SRIOV_EVENT_COMPLETE

La demande indique que la pile de virtualisation ou l’appareil SR-IOV a reçu l’un des événements répertoriés dans SRIOV_PF_EVENT.
IOCTL_SRIOV_INVALIDATE_BLOCK

La requête IOCTL_SRIOV_INVALIDATE_BLOCK indique que la pile de virtualisation souhaite réinitialiser le contenu du bloc de configuration spécifié.
IOCTL_SRIOV_MITIGATED_RANGE_UPDATE

La requête IOCTL_SRIOV_MITIGATED_RANGE_UPDATE indique que la pile de virtualisation souhaite effectuer une mise à jour vers les plages d’atténuation.
IOCTL_SRIOV_NOTIFICATION

La demande indique que la pile de virtualisation souhaite être avertie lorsqu’un des événements répertoriés dans SRIOV_PF_EVENT se produit.
IOCTL_SRIOV_PROXY_QUERY_LUID

Cette demande fournit l’identificateur unique local de l’appareil SR_IOV implémentant l’interface.
IOCTL_SRIOV_QUERY_MITIGATED_RANGE_COUNT

La requête détermine les plages d’espace d’E/S mappé en mémoire qui doivent être atténuées.
IOCTL_SRIOV_QUERY_MITIGATED_RANGES

La requête détermine les plages spécifiques sur lesquelles les intercepts doivent être placés.

Fonctions de rappel

 
READ_WRITE_MITIGATED_REGISTER

Lit ou écrit dans des espaces d’adressage atténués.
SRIOV_GET_DEVICE_LOCATION

Récupère des informations sur l’emplacement actuel de l’appareil PCI sur le bus, telles que le segment PCI, le bus, l’appareil et le numéro de fonction.
SRIOV_GET_MMIO_REQUIREMENTS

Cette fonction de rappel n’est pas prise en charge.
SRIOV_GET_RESOURCE_FOR_BAR

Obtient la ressource traduite pour un registre d’adresses de base (BAR) spécifique.
SRIOV_GET_VENDOR_AND_DEVICE_IDS

Fournit le fournisseur et l’ID de périphérique d’une fonction virtuelle (VF) PCI Express SR-IOV à utiliser pour générer un ID Plug-and-Play plus générique pour le VF. Ces ID ne peuvent pas être lus directement à partir de l’espace de configuration du VF.
SRIOV_QUERY_LUID

Obtient l’identificateur unique local de l’appareil SR-IOV.
SRIOV_QUERY_LUID_VF

Obtient la fonction virtuelle PCI Express SR-IOV (VF) en fonction unique.
SRIOV_QUERY_PROBED_BARS

Interroge les données lues à partir des registres d’adresses de base de la fonction physique (PF) si la valeur -1 ont été écrites pour la première fois.
SRIOV_QUERY_PROBED_BARS_2

Interroge les données lues à partir des registres d’adresses de base PCI Express SR-IOV (VF) spécifiés si la valeur -1 ont été écrites pour la première fois.
SRIOV_QUERY_VF_LUID

Obtient l’identificateur unique local de la fonction virtuelle PCI Express SR-IOV (VF).
SRIOV_READ_BLOCK

Lit les données du bloc de configuration spécifié d’une fonction virtuelle PCI Express SR-IOV (VF).
SRIOV_READ_CONFIG

Lit les données de l’espace de configuration de la fonction virtuelle PCI Express SR-IOV spécifiée.
SRIOV_RESET_FUNCTION

Réinitialise la fonction virtuelle PCI Express SR-IOV spécifiée.
SRIOV_SET_POWER_STATE

Définit l’état d’alimentation de la fonction virtuelle PCI Express SR-IOV spécifiée.
SRIOV_WRITE_BLOCK

Écrit des données dans le bloc de configuration spécifié d’une fonction virtuelle PCI Express SR-IOV (VF).
SRIOV_WRITE_CONFIG

Écrit des données de configuration dans une fonction virtuelle PCI Express SR-IOV (VF).

Structures

 
MITIGABLE_DEVICE_INTERFACE

Stocke les pointeurs de fonction vers les fonctions de rappel implémentées par le pilote de fonction physique (PF) pour l’interface de périphérique mitigable.
SRIOV_DEVICE_INTERFACE_STANDARD

Stocke les pointeurs de fonction vers les fonctions de rappel implémentées par le pilote de fonction physique (PF) dans la pile d’appareils pour l’appareil SR-IOV.
SRIOV_DEVICE_INTERFACE_STANDARD_2

Stocke les pointeurs de fonction vers les fonctions de rappel implémentées par le pilote de fonction physique (PF) dans la pile d’appareils pour l’appareil SR-IOV. Il s’agit d’une version étendue de SRIOV_DEVICE_INTERFACE_STANDARD.
SRIOV_INVALIDATE_BLOCK

Contient les informations de bloc de configuration. Cette structure est utilisée dans une requête IOCTL_SRIOV_INVALIDATE_BLOCK.
SRIOV_MITIGATED_RANGE_COUNT_INPUT

Cette structure est utilisée comme mémoire tampon d’entrée pour la requête IOCTL_SRIOV_QUERY_MITIGATED_RANGE_COUNT pour déterminer les plages d’espace d’E/S mappés en mémoire qui doivent être atténuées.
SRIOV_MITIGATED_RANGE_COUNT_OUTPUT

Cette structure est la mémoire tampon de sortie reçue par la requête IOCTL_SRIOV_QUERY_MITIGATED_RANGE_COUNT qui contient un tableau de plages d’espaces d’E/S mappés en mémoire qui doivent être atténués.
SRIOV_MITIGATED_RANGE_UPDATE_INPUT

Cette structure est utilisée comme mémoire tampon d’entrée pour la requête IOCTL_SRIOV_MITIGATED_RANGE_UPDATE pour indiquer la fonction virtuelle (VF) dont l’espace d’E/S mappé en mémoire doit être atténué.
SRIOV_MITIGATED_RANGE_UPDATE_OUTPUT

Cette structure est la mémoire tampon de sortie reçue par la requête IOCTL_SRIOV_MITIGATED_RANGE_UPDATE qui indique la fonction virtuelle (VF) dont l’espace d’E/S mappé en mémoire a été atténué.
SRIOV_MITIGATED_RANGES_INPUT

Cette structure est la mémoire tampon d’entrée dans la requête IOCTL_SRIOV_QUERY_MITIGATED_RANGES pour obtenir les plages spécifiques sur lesquelles les interceptions doivent être placées.
SRIOV_MITIGATED_RANGES_OUTPUT

Cette structure est la mémoire tampon de sortie reçue par la demande de IOCTL_SRIOV_QUERY_MITIGATED_RANGES pour obtenir les plages spécifiques sur lesquelles les intercepts doivent être placés.
SRIOV_PNP_EVENT_COMPLETE

Stocke l’état d’un événement que le pilote SR-IOV fonction physique (PF) doit définir pour la saisie semi-automatique du plug-and-play. Cette structure est utilisée dans la mémoire tampon d’entrée de la requête IOCTL_SRIOV_EVENT_COMPLETE.
SRIOV_PROXY_QUERY_LUID_OUTPUT

Stocke l’identificateur unique local de l’appareil SR_IOV implémentant l’interface. Cette structure est la mémoire tampon de sortie de la requête IOCTL_SRIOV_PROXY_QUERY_LUID.

Énumérations

 
SRIOV_PF_EVENT

Définit les valeurs d’événement pour l’appareil SR-IOV.