요약·해설과 원문, 전문 번역을 서로 분리했습니다. API 이름, symbol, source path는 원문 표기를 사용합니다.
1. 요약·해설
원문의 핵심 논리와 kernel programming 관점의 보충 설명입니다. 아래의 전문 번역과는 별도로 작성했습니다.
2. 영어 원문 전체
번역 기준이 된 Linux v6.18.37 원문입니다. 줄 번호는 이 버전의 파일 좌표입니다.
원문 전체 펼치기
.. SPDX-License-Identifier: GPL-2.0
.. include:: <isonum.txt>
====================================
PCI Express I/O Virtualization Howto
====================================
:Copyright: |copy| 2009 Intel Corporation
:Authors: - Yu Zhao <[email protected]>
- Donald Dutile <[email protected]>
Overview
========
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.
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.
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.
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
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
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,
};
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 <[email protected]>
- Donald Dutile <[email protected]>
Overview
========
SR-IOV, PF와 VF
15-30Single 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처럼 기능하고 표시됩니다.
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-52SR-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 방식이 권장됩니다.
적용 범위와 검증 위치가 다릅니다.
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-59Kernel은 VF를 hot-plug된 PCI device로 취급하므로 실제 PCI device와 같은 방식으로 동작해야 합니다.
VF에도 일반 PCI device와 마찬가지로 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-89Driver 방식으로 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
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-105Host의 호환 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
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,
};
예제의 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,
};
요약·해설
pci-iov-howto.rst:1-171SR-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()`를 사용합니다.