pcivirt.h 헤더

VF를 Virtual Machine에 노출하는 데 사용되는 인터페이스를 사용하기 위한 참조 가이드입니다.

PCI Express Single-Root SR-IOV(가상화) 사양을 준수하는 디바이스는 디바이스에 여러 인터페이스를 제공할 수 있습니다. VF(가상 함수)라고 하는 이러한 인터페이스는 독립적이며 PF(물리적 함수)라고 하는 초기 디바이스 인터페이스를 통해 제공됩니다. 예를 들어 SR-IOV를 지원하는 이더넷 NIC는 하나의 물리적 이더넷 포트(실제 와이어에 연결됨) 및 여러 가상 이더넷 포트가 있는 스위치를 사용하도록 설계할 수 있습니다.

PF의 구성 공간을 사용하면 PF 드라이버가 메모리 매핑된 I/O 공간 및 메시지 신호 인터럽트 등 VF의 PCI 리소스를 관리할 수 있습니다. VF는 전체 디바이스의 하위 집합이므로 다기능 패키지의 기존 함수보다 하드웨어에서 노출하는 비용이 저렴할 수 있습니다. 이를 통해 디바이스 제조업체는 더 많은 인터페이스를 빌드하고 공유 리소스를 중앙에서 관리할 수 있습니다.

Windows가 컴퓨터 하드웨어에서 직접 실행되는 경우 디바이스 드라이버는 플러그 앤 플레이, 전원 관리, 인터럽트 관리 및 기타 작업과 관련된 작업에 참여합니다. 신뢰할 수 있는 Windows 버스 드라이버 및 HAL(하드웨어 추상화 계층)은 버스 구성을 소유하고 전체 버스를 구성합니다. 드라이버는 동일한 권한 수준 내에서 실행되며 커널 모드에는 트러스트 경계가 없습니다.

Windows가 VM(가상 머신)에서 실행되는 경우 이러한 가정은 적용되지 않습니다. VF는 권한이 없는 VM의 제어 하에 배치할 수 있습니다. 그러나 시스템의 보안 또는 성능에 영향을 주지 않도록 하드웨어를 보안 검사해야 합니다.

VF에서 실행 중인 드라이버가 구성 공간을 읽거나 쓰도록 요청하면 가상화 스택에서 요청을 수신하고 SR-IOV 디바이스의 PF 드라이버로 전송됩니다. 이러한 요청에 응답하고 VF에 대한 세부 정보를 제공하는 것은 PF 드라이버의 책임입니다. PF 드라이버는 경우에 따라 하드웨어에 전달되는 구성 읽기 또는 쓰기 요청을 요구할 수 있습니다.

스택은 I/O MMU를 사용하여 디바이스가 노출하는 다양한 인터페이스에서 들어오는 트래픽을 구분하여 디바이스가 액세스할 수 있는 메모리 영역과 생성할 수 있는 중단에 대한 정책을 적용합니다.

PCI 가상화.

하드웨어 요구 사항

SR-IOV 디바이스 할당에 사용할 시스템은 SR-IOV 네트워킹 및 직접 디바이스 할당에 대한 요구 사항을 충족해야 합니다. 시스템에는 IOMMU가 있어야 하며, IOMMU는 운영 체제에 디바이스를 제어하도록 구성되어야 하며, 운영 체제에서 사용하도록 PCIe ACS(Access Control Services)를 사용하도록 설정하고 구성해야 합니다. 마지막으로, 해당 디바이스는 줄 기반 인터럽트 를 사용하지 않아야 하며 ATS(Address Translation Services)가 필요하지 않아야 합니다.

자세한 내용은 여기를 참조하세요.

Hyper-V의 SR-IOV에 대해 알고 싶었던 모든 것. 1부

불연속 디바이스 할당 - 설명 및 배경

시스템에서 디바이스 할당을 지원하는지 여부와 특정 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 처리해야 합니다.

권한 있는 VM에서 실행되는 SR_IOV 디바이스용 드라이버는 호스트 OS입니다. 전체 컴퓨터에 대한 플러그 앤 플레이 및 전원 관리를 소유하고, 권한이 없는 VM에 PCI Express SR-IOV 가상 함수를 노출하고, 헤더 Pcivirt.h에 정의된 GUID_SRIOV_DEVICE_INTERFACE_STANDARD 제공해야 합니다. 해당 드라이버는 FDO를 만드는 PCI Express SR-IOV PF(물리적 함수) 드라이버이거나, FDO가 포트 드라이버에서 관리되는 경우 해당 디바이스 노드에서 더 낮은 필터일 수 있습니다.

드라이버가 VF의 구성 공간에 액세스할 수 있도록 디바이스 인터페이스가 필요합니다.

PF 드라이버의 EVT_WDF_DRIVER_DEVICE_ADD 구현에서 다음 작업을 수행합니다.

  • WdfDeviceCreate를 호출하여 FDO(함수 디바이스 개체)를 만든 후 WdfDeviceCreateDeviceInterface를 호출하여 GUID_DEVINTERFACE_VIRTUALIZABLE_DEVICE 등록합니다. 이렇게 하면 가상화 스택이 SR-IOV 디바이스에 대한 디바이스 핸들을 검색할 수 있습니다.
  • GUID_SRIOV_DEVICE_INTERFACE_STANDARD 노출합니다.
    • SRIOV_DEVICE_INTERFACE_STANDARD 구조를 초기화하고 PF 드라이버에서 구현한 콜백 함수의 함수 포인터로 멤버를 설정합니다.
    • WDF_QUERY_INTERFACE_CONFIG_INIT 호출하여 구조를 구성합니다.
    • WdfDeviceAddQueryInterface를 호출하여 FDO에 인터페이스를 등록합니다.
    // 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;
    }

플러그 앤 플레이 이벤트 처리

가상화 스택은 VM에 적절한 메시지를 보내고, 회신(시간 제한 포함)을 기다리고, 응답하지 않는 VM의 경우 PnP 이벤트 거부 또는 권한이 없는 VM에서 디바이스를 깜짝 제거하는 등의 적절한 작업을 적용해야 합니다. GUID_DEVINTERFACE_VIRTUALIZABLE_DEVICE 구현하는 PF 드라이버는 가상화 스택이 PnP 이벤트에 반응할 수 있도록 하는 이러한 I/O 제어 요청도 처리해야 합니다.

  • 가상화 스택은 먼저 디바이스에 IOCTL_SRIOV_ATTACH 보냅니다. 이렇게 하면 가상화 스택에 특정 PnP 이벤트에 대한 알림을 받아야 한다는 알림이 디바이스에 표시됩니다.

  • 가상화 스택이 IOCTL_SRIOV_DETACH 보낼 때까지 적용됩니다.

  • 가상화 스택은 IOCTL_SRIOV_NOTIFICATION 요청을 전송하여 디바이스에서 PnP 이벤트에 대해 쿼리합니다. PF 드라이버는 IOCTL_SRIOV_NOTIFICATION 요청을 완료하여 PnP 이벤트의 가상화 스택에 알릴 수 있습니다.

  • 가상화 스택은 IOCTL_SRIOV_EVENT_COMPLETE 전송하여 해당 이벤트를 차단 해제합니다.

pcivirt.h에는 다음과 같은 프로그래밍 인터페이스가 포함되어 있습니다.

IOCTLs

 
IOCTL_SRIOV_ATTACH

요청은 가상화 스택이 SR-IOV 디바이스에서 수신한 플러그 앤 플레이 이벤트에 등록하려고 했음을 나타냅니다.
IOCTL_SRIOV_DETACH

요청은 가상화 스택이 플러그 앤 플레이 이벤트(이전에 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

요청은 완화해야 하는 메모리 매핑된 I/O 공간의 범위를 결정합니다.
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

VF에 대한 보다 일반적인 플러그 앤 플레이 ID를 생성하는 데 사용할 PCI Express SR-IOV VF(가상 함수)에 대한 공급업체 및 디바이스 ID를 제공합니다. 이러한 ID는 VF의 구성 공간에서 직접 읽을 수 없습니다.
SRIOV_QUERY_LUID

SR-IOV 디바이스의 로컬 고유 식별자를 가져옵니다.
SRIOV_QUERY_LUID_VF

고유 식별자가 지정된 PCI Express SR-IOV VF(가상 함수)를 가져옵니다.
SRIOV_QUERY_PROBED_BARS

값 -1이 먼저 기록된 경우 PF(실제 함수)의 기본 주소 레지스터(BAR)에서 읽은 데이터를 쿼리합니다.
SRIOV_QUERY_PROBED_BARS_2

값 -1이 먼저 기록된 경우 지정된 PCI Express SR-IOV VF(VF) 기본 주소 레지스터(BAR)에서 읽은 데이터를 쿼리합니다.
SRIOV_QUERY_VF_LUID

PCI Express SR-IOV VF(가상 함수)의 로컬 고유 식별자를 가져옵니다.
SRIOV_READ_BLOCK

PCI Express SR-IOV VF(가상 함수)의 지정된 구성 블록에서 데이터를 읽습니다.
SRIOV_READ_CONFIG

지정된 PCI Express SR-IOV VF(가상 함수)의 구성 공간에서 데이터를 읽습니다.
SRIOV_RESET_FUNCTION

지정된 PCI Express SR-IOV VF(가상 함수)를 다시 설정합니다.
SRIOV_SET_POWER_STATE

지정된 PCI Express SR-IOV 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

SR-IOV 디바이스의 디바이스 스택에 PF(물리적 함수) 드라이버에 의해 구현된 콜백 함수에 대한 함수 포인터를 저장합니다.
SRIOV_DEVICE_INTERFACE_STANDARD_2

SR-IOV 디바이스의 디바이스 스택에 PF(물리적 함수) 드라이버에 의해 구현된 콜백 함수에 대한 함수 포인터를 저장합니다. 확장된 버전의 SRIOV_DEVICE_INTERFACE_STANDARD.
SRIOV_INVALIDATE_BLOCK

구성 블록 정보를 포함합니다. 이 구조체는 IOCTL_SRIOV_INVALIDATE_BLOCK 요청에 사용됩니다.
SRIOV_MITIGATED_RANGE_COUNT_INPUT

이 구조는 IOCTL_SRIOV_QUERY_MITIGATED_RANGE_COUNT 요청에 대한 입력 버퍼로 사용하여 완화해야 하는 메모리 매핑된 I/O 공간의 범위를 결정합니다.
SRIOV_MITIGATED_RANGE_COUNT_OUTPUT

이 구조는 완화해야 하는 메모리 매핑 I/O 공간 범위의 배열을 포함하는 IOCTL_SRIOV_QUERY_MITIGATED_RANGE_COUNT 요청에 의해 수신되는 출력 버퍼입니다.
SRIOV_MITIGATED_RANGE_UPDATE_INPUT

이 구조는 메모리 매핑 I/O 공간을 완화해야 하는 VF(가상 함수)를 나타내기 위해 IOCTL_SRIOV_MITIGATED_RANGE_UPDATE 요청에 대한 입력 버퍼로 사용됩니다.
SRIOV_MITIGATED_RANGE_UPDATE_OUTPUT

이 구조는 메모리 매핑 I/O 공간이 완화된 VF(가상 함수)를 나타내는 IOCTL_SRIOV_MITIGATED_RANGE_UPDATE 요청에 의해 수신된 출력 버퍼입니다.
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(물리적 함수) 드라이버가 설정해야 하는 이벤트에 대한 상태 저장합니다. 이 구조체는 IOCTL_SRIOV_EVENT_COMPLETE 요청의 입력 버퍼에 사용됩니다.
SRIOV_PROXY_QUERY_LUID_OUTPUT

인터페이스를 구현하는 SR_IOV 디바이스의 로컬 고유 식별자를 저장합니다. 이 구조는 IOCTL_SRIOV_PROXY_QUERY_LUID 요청에 대한 출력 버퍼입니다.

열거형

 
SRIOV_PF_EVENT

SR-IOV 디바이스에 대한 이벤트 값을 정의합니다.