← Documents Documentation/PCI/pci-iov-howto.rst GitHub 원문 ↗

Linux 6.18.37 · PCI

PCI Express I/O virtualization HOWTO

SR-IOV의 PF·VF 모델과 driver API·sysfs 방식의 VF enable, auto-probe 및 PF driver callback을 설명합니다.

Source pathDocumentation/PCI/pci-iov-howto.rst
Source versionLinux v6.18.37
TranslationDUJINLABS 전문 번역 + 해설

요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.

1. 요약·해설

원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.

요약·해설

pci-iov-howto.rst:1-171

SR-IOV는 하나의 PF가 고유 Routing ID와 PCI memory를 가진 여러 VF를 동적으로 노출하게 합니다.

새 device에는 PF별 `sriov_numvfs` sysfs 방식이 권장되며, VF를 enable하기 전에 `sriov_drivers_autoprobe`로 host driver 자동 bind 여부를 정합니다.

PF driver는 probe·remove와 `.sriov_configure`에서 `pci_enable_sriov()`와 `pci_disable_sriov()`를 사용합니다.

2. 영어 원문 전체

번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.

원문 전체 펼치기
1 .. SPDX-License-Identifier: GPL-2.0
2 .. include:: <isonum.txt>
3
4 ====================================
5 PCI Express I/O Virtualization Howto
6 ====================================
7
8 :Copyright: |copy| 2009 Intel Corporation
9 :Authors: - Yu Zhao <yu.zhao@intel.com>
10 - Donald Dutile <ddutile@redhat.com>
11
12 Overview
13 ========
14
15 What is SR-IOV
16 --------------
17
18 Single Root I/O Virtualization (SR-IOV) is a PCI Express Extended
19 capability which makes one physical device appear as multiple virtual
20 devices. The physical device is referred to as Physical Function (PF)
21 while the virtual devices are referred to as Virtual Functions (VF).
22 Allocation of the VF can be dynamically controlled by the PF via
23 registers encapsulated in the capability. By default, this feature is
24 not enabled and the PF behaves as traditional PCIe device. Once it's
25 turned on, each VF's PCI configuration space can be accessed by its own
26 Bus, Device and Function Number (Routing ID). And each VF also has PCI
27 Memory Space, which is used to map its register set. VF device driver
28 operates on the register set so it can be functional and appear as a
29 real existing PCI device.
30
31 User Guide
32 ==========
33
34 How can I enable SR-IOV capability
35 ----------------------------------
36
37 Multiple methods are available for SR-IOV enablement.
38 In the first method, the device driver (PF driver) will control the
39 enabling and disabling of the capability via API provided by SR-IOV core.
40 If the hardware has SR-IOV capability, loading its PF driver would
41 enable it and all VFs associated with the PF. Some PF drivers require
42 a module parameter to be set to determine the number of VFs to enable.
43 In the second method, a write to the sysfs file sriov_numvfs will
44 enable and disable the VFs associated with a PCIe PF. This method
45 enables per-PF, VF enable/disable values versus the first method,
46 which applies to all PFs of the same device. Additionally, the
47 PCI SRIOV core support ensures that enable/disable operations are
48 valid to reduce duplication in multiple drivers for the same
49 checks, e.g., check numvfs == 0 if enabling VFs, ensure
50 numvfs <= totalvfs.
51 The second method is the recommended method for new/future VF devices.
52
53 How can I use the Virtual Functions
54 -----------------------------------
55
56 The VF is treated as hot-plugged PCI devices in the kernel, so they
57 should be able to work in the same way as real PCI devices. The VF
58 requires device driver that is same as a normal PCI device's.
59
60 Developer Guide
61 ===============
62
63 SR-IOV API
64 ----------
65
66 To enable SR-IOV capability:
67
68 (a) For the first method, in the driver::
69
70 int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn);
71
72 'nr_virtfn' is number of VFs to be enabled.
73
74 (b) For the second method, from sysfs::
75
76 echo 'nr_virtfn' > \
77 /sys/bus/pci/devices/<DOMAIN:BUS:DEVICE.FUNCTION>/sriov_numvfs
78
79 To disable SR-IOV capability:
80
81 (a) For the first method, in the driver::
82
83 void pci_disable_sriov(struct pci_dev *dev);
84
85 (b) For the second method, from sysfs::
86
87 echo 0 > \
88 /sys/bus/pci/devices/<DOMAIN:BUS:DEVICE.FUNCTION>/sriov_numvfs
89
90 To enable auto probing VFs by a compatible driver on the host, run
91 command below before enabling SR-IOV capabilities. This is the
92 default behavior.
93 ::
94
95 echo 1 > \
96 /sys/bus/pci/devices/<DOMAIN:BUS:DEVICE.FUNCTION>/sriov_drivers_autoprobe
97
98 To disable auto probing VFs by a compatible driver on the host, run
99 command below before enabling SR-IOV capabilities. Updating this
100 entry will not affect VFs which are already probed.
101 ::
102
103 echo 0 > \
104 /sys/bus/pci/devices/<DOMAIN:BUS:DEVICE.FUNCTION>/sriov_drivers_autoprobe
105
106 Usage example
107 -------------
108
109 Following piece of code illustrates the usage of the SR-IOV API.
110 ::
111
112 static int dev_probe(struct pci_dev *dev, const struct pci_device_id *id)
113 {
114 pci_enable_sriov(dev, NR_VIRTFN);
115
116 ...
117
118 return 0;
119 }
120
121 static void dev_remove(struct pci_dev *dev)
122 {
123 pci_disable_sriov(dev);
124
125 ...
126 }
127
128 static int dev_suspend(struct device *dev)
129 {
130 ...
131
132 return 0;
133 }
134
135 static int dev_resume(struct device *dev)
136 {
137 ...
138
139 return 0;
140 }
141
142 static void dev_shutdown(struct pci_dev *dev)
143 {
144 ...
145 }
146
147 static int dev_sriov_configure(struct pci_dev *dev, int numvfs)
148 {
149 if (numvfs > 0) {
150 ...
151 pci_enable_sriov(dev, numvfs);
152 ...
153 return numvfs;
154 }
155 if (numvfs == 0) {
156 ....
157 pci_disable_sriov(dev);
158 ...
159 return 0;
160 }
161 }
162
163 static struct pci_driver dev_driver = {
164 .name = "SR-IOV Physical Function driver",
165 .id_table = dev_id_table,
166 .probe = dev_probe,
167 .remove = dev_remove,
168 .driver.pm = &dev_pm_ops,
169 .shutdown = dev_shutdown,
170 .sriov_configure = dev_sriov_configure,
171 };
172

3. 한국어 전문 번역

영어 원문의 문단 순서와 의미를 유지한 전체 번역입니다. 코드, 함수명, symbol과 URL은 원문 표기를 유지합니다.

문서 정보

1-14

저작권은 2009년 Intel Corporation에 있으며 저자는 Yu Zhao와 Donald Dutile입니다.

이 문서는 PCI Express Single Root I/O Virtualization(SR-IOV)의 사용자 절차와 driver 개발 API를 설명합니다.

.. SPDX-License-Identifier: GPL-2.0
.. include:: <isonum.txt>

====================================
PCI Express I/O Virtualization Howto
====================================

:Copyright: |copy| 2009 Intel Corporation
:Authors: - Yu Zhao <yu.zhao@intel.com>
          - Donald Dutile <ddutile@redhat.com>

Overview
========

SR-IOV, PF와 VF

15-30

Single Root I/O Virtualization(SR-IOV)은 하나의 physical device가 여러 virtual device처럼 보이게 하는 PCI Express Extended capability입니다.

Physical device는 Physical Function(PF), virtual device는 Virtual Function(VF)이라고 합니다. PF는 capability 내부 register를 통해 VF 할당을 동적으로 제어할 수 있습니다.

기본적으로 SR-IOV는 enable되지 않아 PF가 전통적인 PCIe device처럼 동작합니다. Enable하면 각 VF의 PCI configuration space를 고유 Bus·Device·Function Number, 즉 Routing ID로 접근할 수 있습니다.

각 VF에는 register set을 mapping하는 PCI Memory Space도 있습니다. VF device driver가 이 register set을 조작하므로 VF는 실제 PCI device처럼 기능하고 표시됩니다.

PF와 VF
구분PFVF
실체Physical deviceVirtual device
제어Capability register로 VF 할당PF가 생성·제거
주소기존 PCI Routing ID각 VF의 고유 Bus:Device.Function
RegisterPF PCI memory각 VF의 PCI Memory Space

SR-IOV가 physical function에서 여러 virtual function을 노출하는 방식입니다.

What is SR-IOV
--------------

Single Root I/O Virtualization (SR-IOV) is a PCI Express Extended
capability which makes one physical device appear as multiple virtual
devices. The physical device is referred to as Physical Function (PF)
while the virtual devices are referred to as Virtual Functions (VF).
Allocation of the VF can be dynamically controlled by the PF via
registers encapsulated in the capability. By default, this feature is
not enabled and the PF behaves as traditional PCIe device. Once it's
turned on, each VF's PCI configuration space can be accessed by its own
Bus, Device and Function Number (Routing ID). And each VF also has PCI
Memory Space, which is used to map its register set. VF device driver
operates on the register set so it can be functional and appear as a
real existing PCI device.

SR-IOV enable 방식

31-52

SR-IOV를 enable하는 방법은 여러 가지입니다.

첫 번째 방법은 PF driver가 SR-IOV core API로 capability를 enable·disable하는 것입니다. Hardware가 SR-IOV capability를 지원하면 PF driver를 load할 때 PF와 연결된 모든 VF를 enable할 수 있습니다. 일부 PF driver는 enable할 VF 수를 module parameter로 받습니다.

두 번째 방법은 PCIe PF의 sysfs file `sriov_numvfs`에 값을 써 연결된 VF를 enable·disable하는 것입니다. 첫 방법이 같은 device의 모든 PF에 적용되는 데 비해 이 방법은 PF마다 VF 수를 지정할 수 있습니다.

PCI SR-IOV core가 operation 유효성을 검사하므로 여러 driver가 같은 check를 반복하지 않아도 됩니다. 예를 들어 VF enable 시 현재 `numvfs == 0`인지, 요청 `numvfs <= totalvfs`인지 확인합니다.

새로운 VF device에는 두 번째 sysfs 방식이 권장됩니다.

SR-IOV enable 방식 비교
방식제어 주체적용 범위권장
PF driver APIPF driver같은 device의 모든 PF기존 driver
sriov_numvfsUser space + SR-IOV corePF별새 VF device

적용 범위와 검증 위치가 다릅니다.

User Guide
==========

How can I enable SR-IOV capability
----------------------------------

Multiple methods are available for SR-IOV enablement.
In the first method, the device driver (PF driver) will control the
enabling and disabling of the capability via API provided by SR-IOV core.
If the hardware has SR-IOV capability, loading its PF driver would
enable it and all VFs associated with the PF.  Some PF drivers require
a module parameter to be set to determine the number of VFs to enable.
In the second method, a write to the sysfs file sriov_numvfs will
enable and disable the VFs associated with a PCIe PF.  This method
enables per-PF, VF enable/disable values versus the first method,
which applies to all PFs of the same device.  Additionally, the
PCI SRIOV core support ensures that enable/disable operations are
valid to reduce duplication in multiple drivers for the same
checks, e.g., check numvfs == 0 if enabling VFs, ensure
numvfs <= totalvfs.
The second method is the recommended method for new/future VF devices.

Virtual Function 사용

53-59

Kernel은 VF를 hot-plug된 PCI device로 취급하므로 실제 PCI device와 같은 방식으로 동작해야 합니다.

VF에도 일반 PCI device와 마찬가지로 device driver가 필요합니다.

VF 노출
PF + SR-IOV capabilityVF enablePCI hotplug discoveryVF device driver

PF가 VF를 enable하면 kernel이 hotplug device로 발견하고 호환 driver가 bind합니다.

How can I use the Virtual Functions
-----------------------------------

The VF is treated as hot-plugged PCI devices in the kernel, so they
should be able to work in the same way as real PCI devices. The VF
requires device driver that is same as a normal PCI device's.

SR-IOV enable·disable API

60-89

Driver 방식으로 SR-IOV를 enable할 때는 `pci_enable_sriov()`를 호출합니다. `nr_virtfn`은 enable할 VF 수입니다.

int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn);

Sysfs 방식은 PF의 `sriov_numvfs`에 원하는 `nr_virtfn`을 기록합니다.

echo 'nr_virtfn' > \
/sys/bus/pci/devices/<DOMAIN:BUS:DEVICE.FUNCTION>/sriov_numvfs

Driver 방식으로 disable할 때는 `pci_disable_sriov()`를 호출합니다.

void pci_disable_sriov(struct pci_dev *dev);

Sysfs 방식으로 disable할 때는 같은 `sriov_numvfs`에 `0`을 기록합니다.

echo 0 > \
/sys/bus/pci/devices/<DOMAIN:BUS:DEVICE.FUNCTION>/sriov_numvfs
SR-IOV operation
동작DriverSysfs
Enablepci_enable_sriov(dev, nr_virtfn)sriov_numvfs = nr_virtfn
Disablepci_disable_sriov(dev)sriov_numvfs = 0

Driver API와 sysfs의 대응 관계입니다.

Developer Guide
===============

SR-IOV API
----------

To enable SR-IOV capability:

(a) For the first method, in the driver::

        int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn);

'nr_virtfn' is number of VFs to be enabled.

(b) For the second method, from sysfs::

        echo 'nr_virtfn' > \
        /sys/bus/pci/devices/<DOMAIN:BUS:DEVICE.FUNCTION>/sriov_numvfs

To disable SR-IOV capability:

(a) For the first method, in the driver::

        void pci_disable_sriov(struct pci_dev *dev);

(b) For the second method, from sysfs::

        echo  0 > \
        /sys/bus/pci/devices/<DOMAIN:BUS:DEVICE.FUNCTION>/sriov_numvfs

VF driver auto-probe

90-105

Host의 호환 driver가 VF를 자동 probe하게 하려면 SR-IOV capability를 enable하기 전에 `sriov_drivers_autoprobe`에 `1`을 기록합니다. 이것이 기본 동작입니다.

echo 1 > \
/sys/bus/pci/devices/<DOMAIN:BUS:DEVICE.FUNCTION>/sriov_drivers_autoprobe

자동 probe를 disable하려면 SR-IOV enable 전에 `0`을 기록합니다. 이 항목을 갱신해도 이미 probe된 VF에는 영향을 주지 않습니다.

echo 0 > \
/sys/bus/pci/devices/<DOMAIN:BUS:DEVICE.FUNCTION>/sriov_drivers_autoprobe
sriov_drivers_autoprobe
동작
1호환 host driver가 새 VF를 자동 probe, 기본값
0새 VF 자동 probe 안 함
기존 VF이미 probe된 VF는 값 변경의 영향 없음

VF enable 전에 설정해야 하며 기존 bind에는 소급되지 않습니다.

To enable auto probing VFs by a compatible driver on the host, run
command below before enabling SR-IOV capabilities. This is the
default behavior.
::

        echo 1 > \
        /sys/bus/pci/devices/<DOMAIN:BUS:DEVICE.FUNCTION>/sriov_drivers_autoprobe

To disable auto probing VFs by a compatible driver on the host, run
command below before enabling SR-IOV capabilities. Updating this
entry will not affect VFs which are already probed.
::

        echo  0 > \
        /sys/bus/pci/devices/<DOMAIN:BUS:DEVICE.FUNCTION>/sriov_drivers_autoprobe

PF driver 구현 예

106-171

예제는 PF driver의 생명주기와 `sriov_configure` callback에서 SR-IOV API를 사용하는 방식을 보여줍니다.

`dev_probe()`는 `pci_enable_sriov(dev, NR_VIRTFN)`으로 기본 VF 수를 enable하고, `dev_remove()`는 `pci_disable_sriov(dev)`로 정리합니다. Suspend·resume·shutdown callback은 device별 power-management 작업을 수행할 자리입니다.

`dev_sriov_configure()`는 `numvfs > 0`이면 그 수만큼 VF를 enable하고 성공 시 `numvfs`를 반환합니다. `numvfs == 0`이면 VF를 disable하고 `0`을 반환합니다.

마지막 `struct pci_driver`는 `.probe`, `.remove`, `.driver.pm`, `.shutdown`, `.sriov_configure`를 연결합니다.

static int dev_sriov_configure(struct pci_dev *dev, int numvfs)
{
        if (numvfs > 0) {
                pci_enable_sriov(dev, numvfs);
                return numvfs;
        }
        if (numvfs == 0) {
                pci_disable_sriov(dev);
                return 0;
        }
}

static struct pci_driver dev_driver = {
        .name = "SR-IOV Physical Function driver",
        .id_table = dev_id_table,
        .probe = dev_probe,
        .remove = dev_remove,
        .driver.pm = &dev_pm_ops,
        .shutdown = dev_shutdown,
        .sriov_configure = dev_sriov_configure,
};
PF driver callback
Callback역할
dev_probe기본 VF enable
dev_removeSR-IOV disable
dev_suspend/dev_resumePower management
dev_shutdownShutdown 처리
dev_sriov_configureSysfs 요청의 VF 수 적용

예제의 callback과 SR-IOV 역할입니다.

Usage example
-------------

Following piece of code illustrates the usage of the SR-IOV API.
::

        static int dev_probe(struct pci_dev *dev, const struct pci_device_id *id)
        {
                pci_enable_sriov(dev, NR_VIRTFN);

                ...

                return 0;
        }

        static void dev_remove(struct pci_dev *dev)
        {
                pci_disable_sriov(dev);

                ...
        }

        static int dev_suspend(struct device *dev)
        {
                ...

                return 0;
        }

        static int dev_resume(struct device *dev)
        {
                ...

                return 0;
        }

        static void dev_shutdown(struct pci_dev *dev)
        {
                ...
        }

        static int dev_sriov_configure(struct pci_dev *dev, int numvfs)
        {
                if (numvfs > 0) {
                        ...
                        pci_enable_sriov(dev, numvfs);
                        ...
                        return numvfs;
                }
                if (numvfs == 0) {
                        ....
                        pci_disable_sriov(dev);
                        ...
                        return 0;
                }
        }

        static struct pci_driver dev_driver = {
                .name =                "SR-IOV Physical Function driver",
                .id_table =        dev_id_table,
                .probe =        dev_probe,
                .remove =        dev_remove,
                .driver.pm =        &dev_pm_ops,
                .shutdown =        dev_shutdown,
                .sriov_configure = dev_sriov_configure,
        };