Condividi tramite


intestazione pcivirt.h

Guida di riferimento per l'uso di interfacce usate per esporre le macchine virtuali a una macchina virtuale.

I dispositivi conformi alla specifica PCI Express Single-Root I/O Virtualization (SR-IOV) possono fornire più interfacce al dispositivo. Queste interfacce, note come Funzioni virtuali (VFS), sono indipendenti e vengono fornite tramite l'interfaccia del dispositivo iniziale, nota come funzione fisica (PF). Ad esempio, una scheda di interfaccia di rete Ethernet che supporta SR-IOV può essere progettata per avere un commutatore con una porta Ethernet fisica (connessa al cavo fisico) e molte porte Ethernet virtuali.

Lo spazio di configurazione di PF consente al driver PF di gestire le risorse PCI di VF, tra cui lo spazio di I/O mappato alla memoria e gli interruzioni con segnale di messaggio. Poiché le macchine virtuali sono un subset di un dispositivo completo, possono essere meno costose da esporre nell'hardware rispetto a una funzione tradizionale in un pacchetto multi-funzione. Ciò consente al creatore di dispositivi di creare più interfacce e di gestire tutte le risorse condivise centralmente.

Quando Windows è in esecuzione direttamente sull'hardware del computer, i driver di dispositivo partecipano alle operazioni correlate alla Plug and Play, alla gestione delle energia, alla gestione degli interruzioni e ad altre attività. Un driver del bus windows attendibile e Hardware Abstraction Layer (HAL) è una configurazione del bus e configurare l'intero bus. Il driver viene eseguito all'interno dello stesso livello di privilegio e non sono presenti limiti di attendibilità in modalità kernel.

Quando Windows è in esecuzione in una macchina virtuale (VM), tali presupposti non si applicano. Le macchine virtuali possono essere inserite sotto il controllo di una macchina virtuale non con privilegi. Tuttavia, l'hardware deve essere controllato in modo che la sicurezza o le prestazioni del sistema non siano interessate.

Quando un driver in esecuzione sul VF richiede una lettura o una scrittura dello spazio di configurazione, la richiesta viene ricevuta dallo stack di virtualizzazione e inviata al driver PF del dispositivo SR-IOV. È responsabilità del driver PF rispondere a tali richieste e fornire dettagli per la VF. Il driver PF può richiedere occasionalmente che una richiesta di lettura o scrittura di configurazione passata all'hardware.

Lo stack usa un MMU di I/O per distinguere il traffico proveniente dalle varie interfacce esposte dal dispositivo, applicando criteri su quali aree di memoria un dispositivo può accedere e quali interruzioni possono generare.

Virtualizzazione PCI.

Requisiti hardware

Il sistema da usare per l'assegnazione di dispositivi SR-IOV deve soddisfare i requisiti per la rete SR-IOV e l'assegnazione diretta del dispositivo. Il sistema deve avere un IOMMU, che IOMMU deve essere configurato per concedere il controllo dei dispositivi al sistema operativo e PCIe ACS (Controllo di accesso Services) deve essere abilitato e configurato per l'uso dal sistema operativo. Infine, il dispositivo in questione non deve usare interruzioni basate su riga e non deve richiedere ATS (Address Translation Services).

Ulteriori informazioni sono disponibili qui:

Tutto quello che volevi sapere su SR-IOV in Hyper-V. Parte 1

Assegnazione di dispositivi discreti - Descrizione e sfondo

Per determinare se un sistema supporta l'assegnazione del dispositivo e se un determinato dispositivo PCI funzionerà per l'assegnazione del dispositivo:

Script di assegnazione di dispositivi discreti

Esecuzione di query per dispositivi SR-IOV

GUID_DEVINTERFACE_VIRTUALIZABLE_DEVICE è un'interfaccia della classe di dispositivo fornita dai driver per i dispositivi SR-IOV. Questo GUID consente di eseguire query per tutti gli stack di dispositivi che espongono le varie tabelle delle funzioni usate per gestire le funzionalità correlate alla virtualizzazione del dispositivo. Dopo aver registrato il GUID, vengono individuate singole funzionalità inviando IRP_MN_QUERY_INTERFACE. Il driver deve rispondere a tale richiesta con GUID_SRIOV_DEVICE_INTERFACE_STANDARD. I driver devono anche gestire IOCTL_SRIOV_NOTIFICATION e IOCTL_SRIOV_EVENT_COMPLETE.

Un driver per un dispositivo SR_IOV, che viene eseguito in una macchina virtuale con privilegi è il sistema operativo host. Possiede plug-and-play e risparmio energia per un intero computer ed espone funzioni virtuali PCI Express SR-IOV in macchine virtuali non con privilegi, deve fornire la GUID_SRIOV_DEVICE_INTERFACE_STANDARD (definita nell'intestazione Pcivirt.h). Tale driver potrebbe essere un driver PCI Express SR-IOV Physical Function (PF) che crea l'oggetto FDO oppure potrebbe essere un filtro inferiore su tale nodo del dispositivo nel caso in cui l'oggetto FDO sia gestito da un driver di porta.

L'interfaccia del dispositivo è necessaria in modo che il driver possa accedere allo spazio di configurazione delle macchine virtuali.

Nell'implementazione del driver PF EVT_WDF_DRIVER_DEVICE_ADD eseguire queste attività:

  • Dopo aver chiamato WdfDeviceCreate per creare l'oggetto del dispositivo funzione (FDO), chiamare WdfDeviceCreateDeviceInterface per registrare GUID_DEVINTERFACE_VIRTUALIZABLE_DEVICE. Ciò consente allo stack di virtualizzazione di recuperare un handle di dispositivo nel dispositivo SR-IOV.
  • Esporre l'GUID_SRIOV_DEVICE_INTERFACE_STANDARD.
    • Inizializzare una struttura SRIOV_DEVICE_INTERFACE_STANDARD e impostare membri su puntatori di funzione delle funzioni di callback implementate dal driver PF.
    • Configurare la struttura chiamando WDF_QUERY_INTERFACE_CONFIG_INIT.
    • Registrare l'interfaccia con l'oggetto FDO chiamando 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;
    }

Gestione degli eventi Plug and Play

Lo stack di virtualizzazione è responsabile dell'invio dei messaggi appropriati alla macchina virtuale, in attesa della risposta (con timeout) e nel caso di macchina virtuale non risponde e di applicazione di azioni appropriate, ad esempio il veto dell'evento PnP o la rimozione di sorpresa del dispositivo dalla macchina virtuale non con privilegi. I driver PF che implementano GUID_DEVINTERFACE_VIRTUALIZABLE_DEVICE devono gestire anche queste richieste di controllo di I/O che consentono allo stack di virtualizzazione di reagire agli eventi PnP.

  • Lo stack di virtualizzazione invia prima IOCTL_SRIOV_ATTACH al dispositivo. Questo notifica al dispositivo che lo stack di virtualizzazione deve ricevere una notifica su determinati eventi PnP.

  • Ciò è effettivo fino a quando lo stack di virtualizzazione invia IOCTL_SRIOV_DETACH.

  • Lo stack di virtualizzazione esegue una query sui dispositivi sugli eventi PnP inviando richieste di IOCTL_SRIOV_NOTIFICATION. Il driver PF può informare lo stack di virtualizzazione di un evento PnP completando la richiesta di IOCTL_SRIOV_NOTIFICATION.

  • Lo stack di virtualizzazione sblocca tali eventi inviando IOCTL_SRIOV_EVENT_COMPLETE.

pcivirt.h contiene le interfacce di programmazione seguenti:

IOCTL

 
IOCTL_SRIOV_ATTACH

La richiesta indica che lo stack di virtualizzazione vuole registrare per gli eventi Plug and Play ricevuti dal dispositivo SR-IOV.
IOCTL_SRIOV_DETACH

La richiesta indica che lo stack di virtualizzazione vuole annullare la registrazione per gli eventi di Plug and Play (precedentemente registrati tramite la richiesta di IOCTL_SRIOV_ATTACH).
IOCTL_SRIOV_EVENT_COMPLETE

La richiesta indica che lo stack di virtualizzazione o il dispositivo SR-IOV ha ricevuto uno degli eventi elencati in SRIOV_PF_EVENT.
IOCTL_SRIOV_INVALIDATE_BLOCK

La richiesta di IOCTL_SRIOV_INVALIDATE_BLOCK indica che lo stack di virtualizzazione vuole reimpostare il contenuto del blocco di configurazione specificato.
IOCTL_SRIOV_MITIGATED_RANGE_UPDATE

La richiesta di IOCTL_SRIOV_MITIGATED_RANGE_UPDATE indica che lo stack di virtualizzazione vuole aggiornare agli intervalli di mitigazione.
IOCTL_SRIOV_NOTIFICATION

La richiesta indica che lo stack di virtualizzazione vuole ricevere una notifica quando si verifica uno degli eventi elencati in SRIOV_PF_EVENT.
IOCTL_SRIOV_PROXY_QUERY_LUID

Questa richiesta fornisce l'identificatore univoco locale del dispositivo SR_IOV che implementa l'interfaccia.
IOCTL_SRIOV_QUERY_MITIGATED_RANGE_COUNT

La richiesta determina gli intervalli di spazio di I/O mappati alla memoria che devono essere ridotti.
IOCTL_SRIOV_QUERY_MITIGATED_RANGES

La richiesta determina gli intervalli specifici in cui devono essere inseriti gli intercettamenti.

Funzioni di callback

 
READ_WRITE_MITIGATED_REGISTER

Legge o scrive in spazi di indirizzi ridotti.
SRIOV_GET_DEVICE_LOCATION

Recupera informazioni sulla posizione corrente del dispositivo PCI nel bus, ad esempio PCI Segment, Bus, Dispositivo e Numero di funzione.
SRIOV_GET_MMIO_REQUIREMENTS

Questa funzione di callback non è supportata.
SRIOV_GET_RESOURCE_FOR_BAR

Ottiene la risorsa tradotta per un registro indirizzi di base specifico (BAR).
SRIOV_GET_VENDOR_AND_DEVICE_IDS

Fornisce l'ID fornitore e dispositivo per una funzione virtuale PCI Express SR-IOV (VF) da usare per generare un ID Plug and Play più generico per il VF. Questi ID non possono essere letti direttamente dallo spazio di configurazione di VF.
SRIOV_QUERY_LUID

Ottiene l'identificatore univoco locale del dispositivo SR-IOV.
SRIOV_QUERY_LUID_VF

Ottiene la funzione virtuale PCI Express SR-IOV (VF) data un identificatore univoco.
SRIOV_QUERY_PROBED_BARS

Esegue query sui dati letti dall'indirizzo di base (PF) della funzione fisica se il valore -1 è stato scritto prima.
SRIOV_QUERY_PROBED_BARS_2

Esegue query sui dati letti dalla funzione virtuale PCI Express SR-IOV (VF) specificata se il valore -1 è stato scritto prima.
SRIOV_QUERY_VF_LUID

Ottiene l'identificatore univoco locale della funzione virtuale PCI Express SR-IOV (VF).
SRIOV_READ_BLOCK

Legge i dati dal blocco di configurazione specificato di una funzione virtuale PCI Express SR-IOV (VF).
SRIOV_READ_CONFIG

Legge i dati dallo spazio di configurazione della funzione virtuale PCI Express SR-IOV specificata.
SRIOV_RESET_FUNCTION

Reimposta la funzione virtuale PCI Express SR-IOV specificata.
SRIOV_SET_POWER_STATE

Imposta lo stato di alimentazione della funzione virtuale PCI Express SR-IOV specificata.
SRIOV_WRITE_BLOCK

Scrive i dati nel blocco di configurazione specificato di una funzione virtuale PCI Express SR-IOV (VF).
SRIOV_WRITE_CONFIG

Scrive i dati di configurazione in una funzione virtuale PCI Express SR-IOV (VF).

Strutture

 
MITIGABLE_DEVICE_INTERFACE

Archivia i puntatori alle funzioni di callback implementati dal driver della funzione fisica (PF) per l'interfaccia del dispositivo mitigable.
SRIOV_DEVICE_INTERFACE_STANDARD

Archivia i puntatori alle funzioni di callback implementati dal driver della funzione fisica (PF) nello stack di dispositivi per il dispositivo SR-IOV.
SRIOV_DEVICE_INTERFACE_STANDARD_2

Archivia i puntatori alle funzioni di callback implementati dal driver della funzione fisica (PF) nello stack di dispositivi per il dispositivo SR-IOV. Si tratta di una versione estesa di SRIOV_DEVICE_INTERFACE_STANDARD.
SRIOV_INVALIDATE_BLOCK

Contiene le informazioni sul blocco di configurazione. Questa struttura viene usata in una richiesta di IOCTL_SRIOV_INVALIDATE_BLOCK.
SRIOV_MITIGATED_RANGE_COUNT_INPUT

Questa struttura viene usata come buffer di input per la richiesta di IOCTL_SRIOV_QUERY_MITIGATED_RANGE_COUNT per determinare gli intervalli di spazio di I/O mappati alla memoria che devono essere ridotti.
SRIOV_MITIGATED_RANGE_COUNT_OUTPUT

Questa struttura è il buffer di output ricevuto dalla richiesta di IOCTL_SRIOV_QUERY_MITIGATED_RANGE_COUNT che contiene una matrice di intervalli di spazi di I/O mappati dalla memoria che devono essere ridotti.
SRIOV_MITIGATED_RANGE_UPDATE_INPUT

Questa struttura viene usata come buffer di input per la richiesta di IOCTL_SRIOV_MITIGATED_RANGE_UPDATE per indicare la funzione virtuale (VF) lo spazio di I/O mappato alla memoria che deve essere mitigato.
SRIOV_MITIGATED_RANGE_UPDATE_OUTPUT

Questa struttura è il buffer di output ricevuto dalla richiesta di IOCTL_SRIOV_MITIGATED_RANGE_UPDATE che indica la funzione virtuale (VF) la cui spazio di I/O mappato alla memoria è stato attenuato.
SRIOV_MITIGATED_RANGES_INPUT

Questa struttura è il buffer di input nella richiesta di IOCTL_SRIOV_QUERY_MITIGATED_RANGES per ottenere gli intervalli specifici in cui devono essere posizionati gli intercettamenti.
SRIOV_MITIGATED_RANGES_OUTPUT

Questa struttura è il buffer di output ricevuto dalla richiesta di IOCTL_SRIOV_QUERY_MITIGATED_RANGES per ottenere gli intervalli specifici in cui devono essere posizionate le intercettazioni.
SRIOV_PNP_EVENT_COMPLETE

Archivia lo stato per un evento che il driver SR-IOV Physical Function (PF) deve essere impostato per Plug and Play completamento uniforme. Questa struttura viene usata nel buffer di input della richiesta di IOCTL_SRIOV_EVENT_COMPLETE.
SRIOV_PROXY_QUERY_LUID_OUTPUT

Archivia l'identificatore univoco locale del dispositivo SR_IOV che implementa l'interfaccia. Questa struttura è il buffer di output per la richiesta di IOCTL_SRIOV_PROXY_QUERY_LUID.

Enumerazioni

 
SRIOV_PF_EVENT

Definisce i valori di evento per il dispositivo SR-IOV.