3. PCI Express I/O 虛擬化操作指南¶
- 版權:
© 2009 Intel Corporation
- 作者:
Yu Zhao <yu.zhao@intel.com>
Donald Dutile <ddutile@redhat.com>
3.1. 概述¶
3.1.1. 什麼是 SR-IOV¶
單根 I/O 虛擬化 (SR-IOV) 是一種 PCI Express 擴充套件功能,它使一個物理裝置表現為多個虛擬裝置。物理裝置被稱為物理功能 (PF),而虛擬裝置被稱為虛擬功能 (VF)。VF 的分配可以透過封裝在功能中的暫存器由 PF 動態控制。預設情況下,此功能未啟用,PF 表現為傳統的 PCIe 裝置。一旦開啟,每個 VF 的 PCI 配置空間可以透過其自身的匯流排、裝置和功能編號(路由 ID)進行訪問。每個 VF 也有 PCI 記憶體空間,用於對映其暫存器集。VF 裝置驅動程式在此暫存器集上操作,因此它可以正常工作並表現為一個真實存在的 PCI 裝置。
3.2. 使用者指南¶
3.2.1. 如何啟用 SR-IOV 功能¶
有多種方法可用於啟用 SR-IOV。第一種方法中,裝置驅動程式(PF 驅動程式)將透過 SR-IOV 核心提供的 API 來控制功能的啟用和停用。如果硬體具有 SR-IOV 功能,載入其 PF 驅動程式將啟用該功能以及與該 PF 相關聯的所有 VF。某些 PF 驅動程式需要設定一個模組引數來確定要啟用的 VF 數量。第二種方法中,寫入 sysfs 檔案 sriov_numvfs 將啟用和停用與 PCIe PF 相關聯的 VF。此方法實現了每個 PF 的 VF 啟用/停用值,而第一種方法適用於同一裝置的所有 PF。此外,PCI SRIOV 核心支援確保啟用/停用操作有效,以減少多個驅動程式中重複的相同檢查,例如,檢查 numvfs == 0(如果啟用 VF),確保 numvfs <= totalvfs。第二種方法是推薦用於新/未來 VF 裝置的方法。
3.2.2. 如何使用虛擬功能¶
VF 在核心中被視為熱插拔的 PCI 裝置,因此它們應該能夠像真實的 PCI 裝置一樣工作。VF 需要與普通 PCI 裝置相同的裝置驅動程式。
3.3. 開發者指南¶
3.3.1. SR-IOV API¶
啟用 SR-IOV 功能
對於第一種方法,在驅動程式中
int pci_enable_sriov(struct pci_dev *dev, int nr_virtfn);
‘nr_virtfn’ 是要啟用的 VF 數量。
對於第二種方法,透過 sysfs
echo 'nr_virtfn' > \ /sys/bus/pci/devices/<DOMAIN:BUS:DEVICE.FUNCTION>/sriov_numvfs
停用 SR-IOV 功能
對於第一種方法,在驅動程式中
void pci_disable_sriov(struct pci_dev *dev);
對於第二種方法,透過 sysfs
echo 0 > \ /sys/bus/pci/devices/<DOMAIN:BUS:DEVICE.FUNCTION>/sriov_numvfs
要在主機上透過相容驅動程式啟用 VF 的自動探測,請在啟用 SR-IOV 功能之前執行以下命令。這是預設行為。
echo 1 > \
/sys/bus/pci/devices/<DOMAIN:BUS:DEVICE.FUNCTION>/sriov_drivers_autoprobe
要在主機上透過相容驅動程式停用 VF 的自動探測,請在啟用 SR-IOV 功能之前執行以下命令。更新此條目不會影響已探測的 VF。
echo 0 > \
/sys/bus/pci/devices/<DOMAIN:BUS:DEVICE.FUNCTION>/sriov_drivers_autoprobe
3.3.2. 使用示例¶
以下程式碼片段演示了 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,
};