logo firmy Intel

Intel OPAE FPGA Linux Device Driver Architecture

intel-OPAE-FPGA-Linux-Device-Driver-Architecture-product

Architektura sterownika urządzenia OPAE Intel FPGA Linux

Sterownik Intel FPGA OPAE udostępnia interfejsy dla aplikacji przestrzeni użytkownika, umożliwiając konfigurację, enumerację, otwieranie i uzyskiwanie dostępu do akceleratorów FPGA na platformach wyposażonych w rozwiązania Intel FPGA. Ponadto umożliwia realizację funkcji zarządzania na poziomie systemu, takich jak rekonfiguracja FPGA, zarządzanie energią i wirtualizacja.

Architektura sprzętowa

Z punktu widzenia systemu operacyjnego view, sprzęt FPGA pojawia się jako zwykłe urządzenie PCIe. Pamięć urządzenia FPGA jest zorganizowana przy użyciu wstępnie zdefiniowanej struktury danych (Lista funkcji urządzenia). Funkcje obsługiwane przez urządzenie FPGA są udostępniane za pośrednictwem tych struktur danych, jak pokazano poniżej na poniższym rysunku:

Urządzenie FPGA PCIe

intel-OPAE-FPGA-Linux-Architektura-sterownika-urządzenia-fig- (1)

Sterownik obsługuje technologię PCIe SR-IOV, co pozwala na tworzenie funkcji wirtualnych (VF), za pomocą których można przypisywać poszczególne akceleratory do maszyn wirtualnych.

Korporacja intelektualna. Wszelkie prawa zastrzeżone. Intel, logo Intel i inne znaki Intel są znakami towarowymi firmy Intel Corporation lub jej podmiotów zależnych. Firma Intel gwarantuje wydajność swoich produktów FPGA i produktów półprzewodnikowych zgodnie z aktualnymi specyfikacjami zgodnie ze standardową gwarancją firmy Intel, ale zastrzega sobie prawo do wprowadzania zmian we wszelkich produktach i usługach w dowolnym czasie i bez powiadomienia. Firma Intel nie przyjmuje żadnej odpowiedzialności wynikającej z zastosowania lub wykorzystania jakichkolwiek informacji, produktów lub usług opisanych w niniejszym dokumencie, z wyjątkiem przypadków wyraźnie uzgodnionych na piśmie przez firmę Intel. Klientom firmy Intel zaleca się uzyskanie najnowszej wersji specyfikacji urządzenia przed poleganiem na opublikowanych informacjach oraz przed złożeniem zamówienia na produkty lub usługi.

Inne nazwy i marki mogą być własnością osób trzecich.

Wirtualizowane urządzenie FPGA PCIe

intel-OPAE-FPGA-Linux-Architektura-sterownika-urządzenia-fig- (2)

Silnik zarządzania FPGA (FME)
FPGA Management Engine wykonuje zarządzanie energią i temperaturą, raportowanie błędów, rekonfigurację, raportowanie wydajności i inne funkcje infrastruktury. Każdy FPGA ma jeden FME, do którego dostęp jest zawsze uzyskiwany za pośrednictwem Physical Function (PF). Aplikacje przestrzeni użytkownika mogą uzyskać wyłączny dostęp do FME za pomocą open() i zwolnić go za pomocą close() jako uprzywilejowany użytkownik (root).

Port
Port reprezentuje interfejs pomiędzy statyczną strukturą FPGA („FPGA Interface Manager (FIM)”) a częściowo rekonfigurowalnym regionem zawierającym funkcję akceleratora (AF). Port kontroluje komunikację oprogramowania z akceleratorem i udostępnia funkcje takie jak resetowanie i debugowanie. Urządzenie PCIe może mieć kilka portów, a każdy port można udostępnić za pomocą funkcji wirtualnej (VF), przypisując go za pomocą ioctl FPGA_FME_PORT_ASSIGN na urządzeniu FME.

Jednostka funkcji akceleratora (AF)

  • Jednostka funkcji akceleratora (AF) jest podłączona do portu i udostępnia obszar MMIO o wielkości 256 KB, który będzie wykorzystywany do przechowywania rejestrów sterujących specyficznych dla akceleratora.
  • Aplikacje przestrzeni użytkownika mogą uzyskać wyłączny dostęp do AFU podłączonego do portu za pomocą funkcji open() na urządzeniu portu i zwolnić go za pomocą funkcji close().
  • Aplikacje przestrzeni użytkownika mogą także mmap() przyspieszać regiony MMIO.

Częściowa rekonfiguracja
Jak wspomniano powyżej, akceleratory można rekonfigurować poprzez częściową rekonfigurację funkcji akceleratora (AF) file. Funkcja akceleratora (AF) musi zostać wygenerowana dla dokładnego FIM i docelowego regionu statycznego (Port) FPGA; w przeciwnym razie operacja rekonfiguracji zakończy się niepowodzeniem i może spowodować niestabilność systemu. Tę zgodność można sprawdzić, porównując identyfikator interfejsu zanotowany w nagłówku AF z identyfikatorem interfejsu udostępnionym przez FME za pośrednictwem sysfs. To sprawdzenie jest zwykle wykonywane przez przestrzeń użytkownika przed wywołaniem rekonfiguracji IOCTL.

Notatka:
Obecnie każdy program uzyskujący dostęp do FPGA, w tym te działające na wirtualizowanym hoście, musi zostać zamknięty przed próbą częściowej rekonfiguracji. Kroki będą następujące:

  1. Odładuj sterownik z gościa
  2. Odłącz VF od gościa
  3. Wyłącz SR-IOV
  4. Wykonaj częściową rekonfigurację
  5. Włącz SR-IOV
  6. Podłącz VF do gościa
  7. Załaduj sterownik w gościu

Wirtualizacja FPGA
Aby umożliwić dostęp do akceleratora z aplikacji uruchomionych na maszynie wirtualnej, należy przypisać odpowiedni port AFU do funkcji wirtualnej (VF), wykonując następujące kroki:

  1. PF domyślnie posiada wszystkie porty AFU. Każdy port, który musi zostać ponownie przypisany do VF, musi najpierw zostać zwolniony z PF przez ioctl FPGA_FME_PORT_RELEASE na urządzeniu FME.
  2. Po zwolnieniu N portów z PF, poniższe polecenie może zostać użyte do włączenia SRIOV i VF. Każdy VF posiada tylko jeden port z AFU. echo N > PCI_DEVICE_PATH/sriov_numvfs
  3. Przekaż dane przez VF do maszyn wirtualnych.
  4. Dostęp do AFU w VF można uzyskać z aplikacji w VM (używając tego samego sterownika, który znajduje się w VF).

Notatka:
FME nie może zostać przypisane do VF, w związku z czym PR i inne funkcje zarządzania są dostępne wyłącznie za pośrednictwem PF.

Organizacja kierowców

Sterownik urządzenia modułu PCIe

Organizacja kierowców

intel-OPAE-FPGA-Linux-Architektura-sterownika-urządzenia-fig- (3)

Urządzenia FPGA pojawiają się jako zwykłe urządzenia PCIe; w związku z tym sterownik urządzenia FPGA PCIe (intel-FPGA-PCI.ko) jest zawsze ładowany jako pierwszy po wykryciu FPGA PCIe PF lub VF. Ten sterownik odgrywa infrastrukturalną rolę w architekturze sterownika. On:

  • Tworzy urządzenie kontenerowe FPGA jako urządzenie nadrzędne urządzeń funkcyjnych.
  • Przechodzi przez listę funkcji urządzeń, która jest zaimplementowana w pamięci BAR urządzenia PCIe, aby odkryć urządzenia funkcji i ich podfunkcje, a także utworzyć dla nich urządzenia platformy w ramach urządzenia kontenerowego.
  • Obsługuje SR-IOV.
  • Wprowadza infrastrukturę urządzeń funkcji, która abstrahuje operacje dla podfunkcji i udostępnia typowe funkcje sterownikom urządzeń funkcji.

Funkcje sterownika urządzenia modułu PCIe

  • Zawiera wykrywanie PCIe, enumerację urządzeń i wykrywanie funkcji.
  • Tworzy katalogi sysfs dla urządzenia nadrzędnego, FPGA Management Engine (FME) i portu.
  • Tworzy wystąpienia sterownika platformy, powodując, że jądro Linux ładuje odpowiednie sterowniki modułów platformy.

Sterownik urządzenia modułu platformy FME

  • Zarządzanie energią i temperaturą, raportowanie błędów, raportowanie wydajności i inne funkcje infrastruktury. Dostęp do tych funkcji można uzyskać za pośrednictwem interfejsów sysfs udostępnianych przez sterownik FME.
  • Częściowa rekonfiguracja. Sterownik FME rejestruje FPGA Manager podczas inicjalizacji podfunkcji PR; po otrzymaniu od Ciebie ioctl FPGA_FME_PORT_PR wywołuje funkcję wspólnego interfejsu z FPGA Manager, aby ukończyć częściową rekonfigurację strumienia bitów do danego portu.
  • Zarządzanie portami dla wirtualizacji. Sterownik FME wprowadza dwa ioctle, FPGA_FME_PORT_RELEASE, który zwalnia dany port z PF; i FPGA_FME_PORT_ASSIGN, który przypisuje port z powrotem do PF. Po zwolnieniu portu z PF można go przypisać do VF za pośrednictwem interfejsów SR-IOV dostarczonych przez sterownik PCIe. Aby uzyskać więcej informacji, zapoznaj się z „FPGA Virtualization”.

Funkcje sterownika urządzenia modułu platformy FME

  • Tworzy węzeł urządzenia znakowego FME.
  • Tworzy system plików FME filei implementuje system FME sysfs file akcesoria.
  • Implementuje podsterowniki prywatnych funkcji FME.
  • Podsterowniki funkcji prywatnych FME:
    • Nagłówek FME
    • Zarządzanie temperaturą
    • Zarządzanie energią
    • Błąd globalny
    • Częściowa rekonfiguracja
    • Globalna wydajność

Sterownik urządzenia modułu platformy portu
Podobnie jak sterownik FME, sterownik portu FPGA (i AFU) (intel-fpga-afu. ko) jest badany po utworzeniu urządzenia platformy Port. Główną funkcją tego modułu jest zapewnienie interfejsu dla aplikacji przestrzeni użytkownika w celu uzyskania dostępu do poszczególnych akceleratorów, w tym podstawowej kontroli resetowania portu, eksportu regionu MMIO AFU, usługi mapowania bufora DMA, powiadomień UMsg(1) i funkcji zdalnego debugowania (patrz powyżej).

UMsg jest obsługiwany wyłącznie poprzez Acceleration Stack dla procesora Intel Xeon® ze zintegrowanym układem FPGA.

Funkcje sterownika urządzenia modułu platformy portu

  • Tworzy węzeł urządzenia znakowego portu.
  • Tworzy port sysfs filei implementuje port sysfs file akcesoria.
  • Implementuje podsterowniki funkcji portu prywatnego.
  • Podsterowniki funkcji prywatnych portu:
    • Nagłówek portu
    • AFU
    • Błąd portu
    • UMsg(2)
    • Dotknij sygnału

Numeracja urządzeń FPGA aplikacji
W tej sekcji przedstawiono sposób, w jaki aplikacje wyliczają urządzenie FPGA z hierarchii sysfs w /sys/class/fpga. W example poniżej, dwa urządzenia Intel FPGA są zainstalowane w hoście. Każde urządzenie FPGA ma jeden FME i dwa porty (AFU). Dla każdego urządzenia FPGA tworzony jest katalog urządzeń w /sys/class/fpga:

/sys/class/fpga/intel-fpga-dev.0
/sys/class/fpga/intel-fpga-dev.1

Każdy węzeł ma jeden FME i dwa porty (AFU) jako urządzenia podrzędne:
/sys/class/fpga/intel-fpga-dev.0/intel-fpga-fme.0
/sys/class/fpga/intel-fpga-dev.0/intel-fpga-port.0
/sys/class/fpga/intel-fpga-dev.0/intel-fpga-port.1
/sys/class/fpga/intel-fpga-dev.1/intel-fpga-fme.1
/sys/class/fpga/intel-fpga-dev.1/intel-fpga-port.2
/sys/class/fpga/intel-fpga-dev.1/intel-fpga-port.3

Ogólnie rzecz biorąc, interfejsy FME/Port sysfs nazywane są następująco:
/sys/class/fpga/intel-fpga-dev.i/intel-fpga-fme.j/
/sys/class/fpga/intel-fpga-dev.i/intel-fpga-port.k/

przy czym I kolejno numeruje wszystkie urządzenia kontenerowe, j kolejno numeruje FME, a k kolejno numeruje wszystkie porty.

Do węzłów urządzeń używanych dla funkcji ioctl() i mmap() można odwoływać się za pomocą:
/dev/intel-fpga-fme.j
/dev/intel-fpga-port.k

Wyliczanie sterowników PCIe
Ta sekcja daje ponadview przepływu kodu dla enumeracji urządzeń wykonywanej przez intel-fpga-pci.ko. Podświetlono główne struktury danych i funkcje. Ta sekcja jest najlepsza, gdy viewkorzystając z dołączonego kodu źródłowego (pcie.c).

Struktury danych wyliczeniowe

wyliczenie fpga_id_type {
IDENTYFIKATOR_RODZICA,
Identyfikator FME,
PORT_ID,
FPGA_ID_MAX
};
struktura statyczna idr fpga_ids[FPGA_ID_MAX];
struktura fpga_chardev_info {
const char *nazwa;
dev_t devt;
};
struktura fpga_chardev_info fpga_chrdevs[] = {
{ .name = FPGA_FEATURE_DEV_FME },
{ .name = FPGA_FEATURE_DEV_PORT },
};
statyczna struktura klasy *fpga_class;
statyczna struktura pci_device_id cci_pcie_id_tbl[] = {
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIe_DEVICE_ID_RCiEP0_MCP),},
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIe_DEVICE_ID_VF_MCP),},
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIe_DEVICE_ID_RCiEP0_SKX_P),},
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIe_DEVICE_ID_VF_SKX_P),},
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIe_DEVICE_ID_RCiEP0_DCP),},
{PCI_DEVICE(PCI_VENDOR_ID_INTEL, PCIe_DEVICE_ID_VF_DCP),},
{0,}
};
statyczna struktura pci_driver cci_pci_driver = {
.name = DRV_NAME,
.id_table = tabela_id_cci_pcie_tbl,
.probe = cci_pci_probe,
.usuń = cci_pci_remove,
.sriov_configure = cci_pci_sriov_configure
};
struktura cci_drvdata {
int identyfikator_urządzenia;
struktura urządzenia *fme_dev;
blokada struktury mutex;
struktura list_head port_dev_list;
int zwolniony_numer_portu;
struktura list_head regiony;
};
struktura build_feature_devs_info {
struktura pci_dev *pdev;
void __iomem *ioaddr;
void __iomem *ioend;
int bieżący_pasek;
pusta __iomem *pfme_hdr;
struktura urządzenia *parent_dev;
struktura platform_device *feature_dev;
};

Przepływ wyliczeń

  • Funkcja init_ccid_init()
    • Zainicjuj fpga_ids za pomocą idr_init().
    • Zainicjuj fpga_chrdevs[i].devt za pomocą alloc_chrdev_region().
    • Zainicjuj fpga_class za pomocą class_create().
    • sterownik_rejestru_pci(&cci_pci_driver);
  • cci_pci_probe()
    • Włącz urządzenie PCI, poproś o dostęp do jego regionów, ustaw tryb główny PCI i skonfiguruj DMA.
  • cci_pci_create_feature_devs() przydział_informacji_o_kompilacji_i_init()
    • Przydziel strukturę build_feature_devs_info i zainicjuj ją.
      .parent_dev jest ustawiony na nadrzędny katalog sysfs (intel-fpga-dev.id), który zawiera katalogi FME i Port sysfs.
  • parse_feature_list()
    • Zapoznaj się z listą funkcji urządzenia BAR0, aby poznać FME, port i ich prywatne funkcje.
  • parse_feature() parse_feature_afus() parse_feature_fme()
    • W przypadku napotkania FME:
  • informacje o kompilacji_utwórz_dev()
    • Przydziel urządzenie platformy dla FME, zapisując je w build_feature_devs_info.feature_dev.
    • feature_dev.id jest inicjowany wynikiem idr_alloc(fpga_ids[FME_ID],
    • feature_dev.parent jest ustawione na build_feature_devs_info.parent_dev.
    • Przydziel tablicę zasobów struktury w feature_dev.resource.
  • Przydziel strukturę feature_platform_data, zainicjuj ją i zapisz wskaźnik w feature_dev.dev.platform_data
    • utwórz_instancję_funkcji() informacje_o_kompilacji_dodaj_pod_funkcję()
    • Zainicjuj feature_dev.resource[FME_FEATURE_ID_HEADER].
    • dodaj_dane_platformy_funkcji()
    • Zainicjuj feature_platform_data.features[FME_FEATURE_ID_HEADER], wszystko oprócz .fops.
  • parse_feature() parse_feature_afus() parse_feature_port()
    • Gdy napotkany zostanie port:
  • informacje o kompilacji_utwórz_dev()
    • Przydziel urządzenie platformy dla portu i zapisz je w build_feature_devs_info.feature_dev.
    • feature_dev.id jest inicjowany wynikiem idr_alloc(fpga_ids[PORT_ID],
    • feature_dev.parent jest ustawione na build_feature_devs_info.parent_dev.
    • Przydziel tablicę zasobów struktury w feature_dev.resource.
    • Przydziel strukturę feature_platform_data, zainicjuj ją i zapisz wskaźnik w feature_dev.dev.platform_data
  • informacje o kompilacji_zatwierdź_dev()
    • Dodaj strukturę feature_platform_data.node dla portu do listy portów w strukturze cci_drvdata.port_dev_list
  • utwórz_instancję_funkcji() informacje_o_kompilacji_dodaj_pod_funkcję()
    • Zainicjuj feature_dev.resource[PORT_FEATURE_ID_HEADER].
  • dodaj_dane_platformy_funkcji()
    • Zainicjuj feature_platform_data.features[PORT_FEATURE_ID_HEADER], wszystko oprócz .fops.
  • parse_feature() parse_feature_afus() parse_feature_port_uafu()
    • W przypadku napotkania AFU:
  • utwórz_instancję_funkcji() informacje_o_kompilacji_dodaj_pod_funkcję()
    • Zainicjuj feature_dev.resource[PORT_FEATURE_ID_UAFU].
  • dodaj_dane_platformy_funkcji()
    • Zainicjuj feature_platform_data.features[PORT_FEATURE_ID_UAFU], wszystko oprócz .fops.
  • parse_feature() parse_feature_private() parse_feature_fme_private()
    • Gdy napotkana zostanie prywatna funkcja FME:
  • utwórz_instancję_funkcji() informacje_o_kompilacji_dodaj_pod_funkcję()
    • Zainicjuj feature_dev.resource[id].
  • dodaj_dane_platformy_funkcji()
    • Zainicjuj feature_platform_data.features[id], wszystko oprócz .fops.
  • parse_feature() parse_feature_private() parse_feature_port_private()
  • Gdy napotkana zostanie prywatna funkcja portu: * create_feature_instance() build_info_add_sub_feature() * Zainicjuj feature_dev.resource[id]. * feature_platform_data_add() Zainicjuj feature_platform_data.features[id], wszystko oprócz .fops.
  • parse_ports_from_fme()
    • Jeżeli sterownik jest ładowany w Funkcji Fizycznej (PF), to:
  • Uruchom przepływ parse_feature_list() na każdym porcie opisanym w nagłówku FME.
  • Użyj BAR wymienionego w każdym wpisie portu w nagłówku.

Inicjalizacja urządzenia platformy FME
Ta sekcja daje ponadview przepływu kodu dla inicjalizacji urządzenia FME wykonywanego przez intel-fpga-fme.ko. Główne struktury danych i funkcje są wyróżnione. Ta sekcja jest najlepsza, gdy viewkorzystając z dołączonego kodu źródłowego (fme-main.c).

Struktury danych urządzeń platformy FME

struktura feature_ops {
int (*init)(struktura urządzenia_platformowego *pdev, struktura funkcji *cecha);
int (*uinit)(struktura urządzenia_platformowego *pdev, struktura funkcji *cecha);
długie (*ioctl)(struktura urządzenia_platformowego *pdev, struktura funkcji *cecha,
unsigned int cmd, unsigned long arg);
int (*test)(struktura urządzenia_platformowego *pdev, struktura funkcji *cecha);
};
funkcja struktury {
const char *nazwa;
int indeks_zasobu;
void __iomem *ioaddr;
struktura feature_ops *ops;
};
struktura feature_platform_data {
struktura węzła list_head;
blokada struktury mutex;
unsigned long dev_status;
struktura cdev cdev;
struktura platform_device *dev;
unsigned int disable_count;
void *prywatny;
liczba całkowita;
int (*config_port)(struct platforma_device *, u32, bool);
struktura platformy_device *(*fpga_for_each_port)(struktura platformy_device *,
void *, int (*match)(struktura platform_device *, void *)); struktura
cecha cechy[0];
};
struktura perf_object {
identyfikator int;
const struct grupa_atrybutów **grupy_atrybutów;
struktura urządzenia *fme_dev;
struktura węzła list_head;
struktura list_head dzieci;
struktura kobject kobj;
};
struktura fpga_fme {
u8 identyfikator_portu;
u64 pr_err;
struktura urządzenia *dev_err;
struktura perf_object *perf_dev;
struktura feature_platform_data *pdata;
};

Przepływ inicjalizacji urządzenia platformy FME

Przepływ inicjalizacji FMEintel-OPAE-FPGA-Linux-Architektura-sterownika-urządzenia-fig- (4)

  • Plik fme_probe()
    • Zainicjuj strukturę fpga_fme i zapisz ją w polu feature_platform_data.private.
  • fme_probe() fpga_dev_feature_init() wystąpienie_funkcji_init()
    • Zapisz strukturę feature_ops w feature_platform_data.features dla każdej uzupełnionej funkcji.
    • Wywołaj funkcję testową, jeśli taka istnieje, ze struktury.
    • Wywołaj funkcję init ze struktury.
  • fme_probe() fpga_register_dev_ops()
    • Utwórz węzeł urządzenia znakowego FME, rejestrując strukturę file_operacje.

Inicjalizacja urządzenia platformy portu
Ta sekcja daje ponadview przepływu kodu dla inicjalizacji urządzenia portu wykonywanego przez intel-fpga-afu.ko. Podświetlono główne struktury danych i funkcje. Ta sekcja jest najlepsza, gdy viewkorzystając z dołączonego kodu źródłowego (afu.c).

Struktury danych urządzeń platformy portowej

struktura feature_ops {
int (*init)(struktura urządzenia_platformowego *pdev, struktura funkcji *cecha);
int (*uinit)(struktura urządzenia_platformowego *pdev, struktura funkcji *cecha);
długie (*ioctl)(struktura urządzenia_platformowego *pdev, struktura funkcji *cecha,
unsigned int cmd, unsigned long arg);
int (*test)(struktura urządzenia_platformowego *pdev, struktura funkcji *cecha);
};
funkcja struktury {
const char *nazwa;
int indeks_zasobu;
void __iomem *ioaddr;
struktura feature_ops *ops;
};
struktura feature_platform_data {
struktura węzła list_head;
blokada struktury mutex;
unsigned long dev_status;
struktura cdev cdev;
struktura platform_device *dev;
unsigned int disable_count;
void *prywatny;
liczba całkowita;
int (*config_port)(struct platforma_device *, u32, bool);
struktura platformy_device *(*fpga_for_each_port)(struktura platformy_device *,
void *, int (*match)(struct platforma_device *, void *));
cecha struktury cechy[0];
};
struktura fpga_afu_region {
indeks u32;
flagi u32;
rozmiar u64;
przesunięcie u64;
u64 fiz;
struktura węzła list_head;
};
struktura fpga_afu_dma_region {
u64 adres_użytkownika;
długość u64;
u64 iowa;
struktura strony **pages;
struktura rb_node węzeł;
bool w_użyciu;
};
struktura fpga_afu {
u64 przesunięcie_bieżące_regionu;
int liczba_regionów;
u8 liczba_umsgs;
struktura list_head regiony;
struktura rb_root dma_regions;
struktura feature_platform_data *pdata;
};

Przepływ inicjalizacji urządzenia platformy portu

Przepływ inicjalizacji portuintel-OPAE-FPGA-Linux-Architektura-sterownika-urządzenia-fig- (5)

  • afu_probe() afu_dev_init()
    • Zainicjuj strukturę fpga_afu i zapisz ją w polu feature_platform_data.private.
  • afu_probe() fpga_dev_feature_init() init_instancji_funkcji()
    • Zapisz strukturę feature_ops w feature_platform_data.features dla każdej uzupełnionej funkcji.
    • Wywołaj funkcję testową, jeśli taka istnieje, ze struktury.
    • Wywołaj funkcję init ze struktury.
  • afu_probe() fpga_register_dev_ops()
    • Utwórz węzeł urządzenia znakowego portu, rejestrując strukturę file_operacje.

Certyfikaty IOCTL FME
IOCTL-e wywoływane przy otwartym file deskryptor dla /dev/intel-fpga-fme.j FPGA_GET_API_VERSION — zwraca bieżącą wersję jako liczbę całkowitą, zaczynając od 0.

FPGA_CHECK_EXTENSION — obecnie nieobsługiwane.

FPGA_FME_PORT_RELEASE — arg jest wskaźnikiem do:

struktura fpga_fme_port_release {
__u32 argsz; // w: sizeof(struct fpga_fme_port_release)
__u32 flagi; // w: musi być 0
__u32 port_id; // in: identyfikator portu (od 0) do wydania.
};

FPGA_FME_PORT_ASSIGN — arg jest wskaźnikiem do:

struktura fpga_fme_port_assign {
__u32 argsz; // w: sizeof(struct fpga_fme_port_assign)
__u32 flagi; // w: musi być 0
__u32 port_id; // in: identyfikator portu (od 0) do przypisania. (musi być
wcześniej wydane przez FPGA_FME_PORT_RELEASE)
};

FPGA_FME_PORT_PR — arg jest wskaźnikiem do:

struktura fpga_fme_port_pr {
__u32 argsz; // w: sizeof(struct fpga_fme_port_pr)
__u32 flagi; // w: musi być 0
__u32 port_id; // w: identyfikator portu (od 0)
__u32 buffer_size; // in: rozmiar bufora strumienia bitów w bajtach. Musi być 4-bajtowy
wyrównany.
__u64 buffer_address; // in: adres procesu bufora strumienia bitów
__u64 status; // out: status błędu (maska ​​bitowa)
};

Port IOCTL
IOCTL-e wywoływane przy otwartym file deskryptor dla /dev/intel-fpga-port.k FPGA_GET_API_VERSION — zwraca bieżącą wersję jako liczbę całkowitą, zaczynając od 0. FPGA_CHECK_EXTENSION — obecnie nieobsługiwane.

FPGA_PORT_GET_INFO — arg jest wskaźnikiem do:

struktura fpga_port_info {
__u32 argsz; // w: sizeof(struct fpga_port_info)
__u32 flagi; // wyjście: zwraca 0
__u32 num_regions; // out: liczba regionów MMIO, 2 (1 dla AFU i 1 dla
(STP)
__u32 num_umsgs; // out: liczba UMsg obsługiwanych przez sprzęt
};

FPGA_PORT_GET_REGION_INFO — arg jest wskaźnikiem do:

struktura fpga_port_region_info {
__u32 argsz; // w: sizeof(struct fpga_port_region_info)
__u32 flagi; // wyjście: (maska ​​bitowa) { FPGA_REGION_READ, FPGA_REGION_WRITE,
FPGA_REGION_MMAP }
__u32 indeks; // w: FPGA_PORT_INDEX_UAFU lub FPGA_PORT_INDEX_STP
__u32 padding; // in: musi być 0
__u64 size; // out: rozmiar regionu MMIO w bajtach
__u64 offset; // out: offset regionu MMIO od początku urządzenia fd
};

FPGA_PORT_DMA_MAP — arg jest wskaźnikiem do:
struktura fpga_port_dma_map {
__u32 argsz; // w: sizeof(struct fpga_port_dma_map)
__u32 flagi; // w: musi być 0 __u64 user_addr; // w: proces wirtualny
adres. Musi być wyrównany do strony.
__u64 length; // in: długość mapowania w bajtach. Musi być wielokrotnością strony
rozmiar.
__u64 iova; // out: wirtualny adres IO };

FPGA_PORT_DMA_UNMAP — arg jest wskaźnikiem do:
struktura fpga_port_dma_unmap {
__u32 argsz; // w: sizeof(struct fpga_port_dma_unmap)
__u32 flagi; // w: musi być 0
__u64 iova; // w: wirtualny adres IO zwrócony przez poprzedni
Mapa_portu_FPGA_DMA };

  • FPGA_PORT_RESET — arg musi być NULL.
  • FPGA_PORT_UMSG_ENABLE — arg musi być NULL.
  • FPGA_PORT_UMSG_DISABLE — argumenty muszą być NULL.

FPGA_PORT_UMSG_SET_MODE — arg jest wskaźnikiem do:

struktura fpga_port_umsg_cfg {
__u32 argsz; // w: sizeof(struct fpga_port_umsg_cfg)
__u32 flagi; // w: musi być 0
__u32 hint_bitmap; // w: trybie podpowiedzi UMsg bitmap. Oznacza, które UMsg są
włączony.
};

FPGA_PORT_UMSG_SET_BASE_ADDR—

  • Przed wykonaniem tego ioctl należy wyłączyć UMsg.
  • Pole iova musi być buforem wystarczająco dużym dla wszystkich UMsg (num_umsgs * PAGE_SIZE).
    • Bufor jest oznaczony jako „w użyciu” przez zarządzanie buforem sterownika.
    • Jeśli iova ma wartość NULL, każdy poprzedni region nie jest oznaczony jako „w użyciu”.
  • arg jest wskaźnikiem do:
    struktura fpga_port_umsg_base_addr {
    • u32 argsz; // w: sizeof(struct fpga_port_umsg_base_addr)
    • u32 flags; // w: musi być 0
    • u64 iova; // w: wirtualny adres IO z FPGA_PORT_DMA_MAP. };

Notatka:

  • Aby wyczyścić błędy portu, musisz zapisać dokładną maskę bitową bieżących błędów, np.ample, błędy cat > wyczyść
  • UMsg jest obsługiwany wyłącznie poprzez Acceleration Stack dla procesorów Intel Xeon ze zintegrowanym układem FPGA.

system plików Files

Nagłówek FME sysfs files
intel-fpga-dev.i/intel-fpga-fme.j/

system plików file pole mmio typ dostęp
numer_portu fme_header.capability.liczba_portów liczba dziesiętna Tylko do odczytu
rozmiar_pamięci_podręcznej fme_header.capability.rozmiar_pamięci_podręcznej liczba dziesiętna Tylko do odczytu
wersja fme_header.capability.fabric_verid liczba dziesiętna Tylko do odczytu
identyfikator_gniazda fme_header.capability.socket_id liczba dziesiętna Tylko do odczytu
identyfikator_strumienia_bitów fme_header.id_strumienia_bitowego szesnastkowy uint64_t Tylko do odczytu
metadane_strumienia_bitów nagłówek_fme.bitstream_md szesnastkowy uint64_t Tylko do odczytu

Systemy zarządzania termicznego FME files
intel-fpga-dev.i/intel-fpga-fme.j/thermal_mgmt/

system plików file pole mmio typ dostęp
próg1 termiczny.próg.tmp_thshold1 liczba dziesiętna Użytkownik: Tylko do odczytu Root: Odczyt-zapis
próg2 termiczny.próg.tmp_thshold2 liczba dziesiętna Użytkownik: Tylko do odczytu Root: Odczyt-zapis
próg_wyzwolenia termiczny.próg.termiczny_wyzwolenie_thshold liczba dziesiętna Tylko do odczytu
próg1_osiągnięty termiczny.próg.thshold1_status liczba dziesiętna Tylko do odczytu
próg2_osiągnięty termiczny.próg.thshold2_status liczba dziesiętna Tylko do odczytu
próg1_polityka termiczny.próg.thshold_policy liczba dziesiętna Użytkownik: Tylko do odczytu Root: Odczyt-zapis
temperatura termiczny.rdsensor_fm1.fpga_temp liczba dziesiętna Tylko do odczytu

System zarządzania energią FME files
intel-fpga-dev.i/intel-fpga-fme.j/power_mgmt/

system plików file pole mmio typ dostęp
strawiony stan.mocy.moc_zużyta szesnastkowy uint64_t Tylko do odczytu
próg1 moc.próg.próg1 szesnastkowy uint64_t Użytkownik: Tylko do odczytu Root: Odczyt-zapis
próg2 moc.próg.próg2 szesnastkowy uint64_t Użytkownik: Tylko do odczytu Root: Odczyt-zapis
status_progu1 moc.próg.status_próg1 dziesiętny bez znaku Tylko do odczytu
status_progu2 moc.próg.status_próg2 dziesiętny bez znaku Tylko do odczytu
rtl power.status.fpga_latency_report dziesiętny bez znaku Tylko do odczytu

Błąd globalny FME sysfs files
intel-fpga-dev.i/intel-fpga-fme.j/błędy/

system plików file pole mmio typ dostęp
błędy pcie0 błąd.pcie0_err szesnastkowy uint64_t Czytaj-pisz
błędy pcie1 błąd.pcie1_err szesnastkowy uint64_t Czytaj-pisz
wstrzyknij_błąd błąd.ras_error_inj szesnastkowy uint64_t Czytaj-pisz

intel-fpga-dev.i/intel-fpga-fme.j/błędy/błędy-fme/

system plików file pole mmio typ dostęp
błędy błąd.fme_err szesnastkowy uint64_t Tylko do odczytu
pierwszy_błąd gerror.fme_first_err.err_reg_status szesnastkowy uint64_t Tylko do odczytu
następny_błąd gerror.fme_next_err.err_reg_status szesnastkowy uint64_t Tylko do odczytu
jasne Czyści błędy, first_error, next_error różne uint64_t Tylko do zapisu

Notatka:
Aby usunąć błędy FME, należy zapisać dokładną maskę bitową bieżących błędów, np.ampbłędy le cat > wyczyść.

Częściowa rekonfiguracja FME sysfs files
intel-fpga-dev.i/intel-fpga-fme.j/pr/

system plików file pole mmio typ dostęp
identyfikator_interfejsu pr.fme_pr_intfc_id0_h, pr.fme_pre_intfc_id0_l szesnastkowy 16-bajtowy Tylko do odczytu

FME Global Performance sysfs files
intel-fpga-dev.i/intel-fpga-fme.j/dperf/zegar

system plików file pole mmio typ dostęp
zegar gperf.clk.afu_interf_clock szesnastkowy uint64_t Tylko do odczytu

intel-fpga-dev.i/intel-fpga-fme.j/dperf/cache/ (Nie dotyczy stosu akceleracyjnego dla procesorów Intel Xeon z układami FPGA)

system plików file pole mmio typ dostęp
zamrażać gperf.ch_ctl.freeze liczba dziesiętna Czytaj-pisz
przeczytaj_trafienie gperf.CACHE_RD_TRAFIENIE szesnastkowy uint64_t Tylko do odczytu
odczyt_braku gperf.CACHE_RD_Brak szesnastkowy uint64_t Tylko do odczytu
napisz_uderzenie gperf.CACHE_WR_HIT szesnastkowy uint64_t Tylko do odczytu
zapis_chybienia gperf.CACHE_WR_MISS szesnastkowy uint64_t Tylko do odczytu
żądanie_wstrzymania gperf.CACHE_HOLD_REQ szesnastkowy uint64_t Tylko do odczytu
tx_req_stall gperf.CACHE_TX_REQ_STALL szesnastkowy uint64_t Tylko do odczytu
system plików file pole mmio typ dostęp
rx_req_stall gperf.CACHE_RX_REQ_STALL szesnastkowy uint64_t Tylko do odczytu
zawartość_portu_zapisu_danych gperf.CACHE_DATA_WR_PORT_CONTEN szesnastkowy uint64_t Tylko do odczytu
tag_zapisz_treść_portu gperf.CACHE_TAG_WR_PORT_CONTEN szesnastkowy uint64_t Tylko do odczytu

intel-fpga-dev.i/intel-fpga-fme.j/dperf/iommu/ (Nie dotyczy stosu akceleracyjnego dla procesorów Intel Xeon z układami FPGA)

system plików file pole mmio typ dostęp
zamrażać gperf.vtd_ctl.freeze liczba dziesiętna Użytkownik: Tylko do odczytu Root: Odczyt-zapis

intel-fpga-dev.i/intel-fpga-fme.j/dperf/iommu/afuk/ (Nie dotyczy stosu akceleracyjnego dla procesorów Intel Xeon z układami FPGA)

system plików file pole mmio typ dostęp
przeczytaj_transakcję gperf.VTD_AFU0_MEM_RD_TRANS szesnastkowy uint64_t Tylko do odczytu
napisz_transakcję gperf.VTD_AFU0_MEM_WR_TRANS szesnastkowy uint64_t Tylko do odczytu
tlb_odczytane_uderzenie gperf.VTD_AFU0_TLB_RD_TRAFIENIE szesnastkowy uint64_t Tylko do odczytu
tlb_zapisz_hit gperf.VTD_AFU0_TLB_WR_HIT szesnastkowy uint64_t Tylko do odczytu

intel-fpga-dev.i/intel-fpga-fme.j/dperf/fabric/

system plików file pole mmio typ dostęp
włączać gperf.fab_ctl.(włączone) liczba dziesiętna Użytkownik: Tylko do odczytu Root: Odczyt-zapis
zamrażać gperf.fab_ctl.freeze liczba dziesiętna Użytkownik: Tylko do odczytu Root: Odczyt-zapis
pcie0_odczyt gperf.FAB_PCIE0_RD szesnastkowy uint64_t Tylko do odczytu
pcie0_write gperf.FAB_PCIE0_WR szesnastkowy uint64_t Tylko do odczytu
pcie1_odczyt gperf.FAB_PCIE1_RD szesnastkowy uint64_t Tylko do odczytu
pcie1_write gperf.FAB_PCIE1_WR szesnastkowy uint64_t Tylko do odczytu
upi_odczyt gperf.FAB_UPI_RD szesnastkowy uint64_t Tylko do odczytu
upi_write gperf.FAB_UPI_WR szesnastkowy uint64_t Tylko do odczytu

intel-fpga-ev.i/intel-fpga/fme.j/dperf/fabric/portk/

system plików file pole mmio typ dostęp
pcie0_odczyt gperf.FAB_PCIE0_RD szesnastkowy uint64_t Tylko do odczytu
pcie0_write gperf.FAB_PCIE0_WR szesnastkowy uint64_t Tylko do odczytu
pcie1_odczyt gperf.FAB_PCIE1_RD szesnastkowy uint64_t Tylko do odczytu
pcie1_write gperf.FAB_PCIE1_WR szesnastkowy uint64_t Tylko do odczytu
upi_odczyt gperf.FAB_UPI_RD szesnastkowy uint64_t Tylko do odczytu
upi_write gperf.FAB_UPI_WR szesnastkowy uint64_t Tylko do odczytu

Nagłówek portu sysfs files
intel-fpga-dev.i/intel-fpga-port.k/

system plików file pole mmio typ dostęp
id port_header.capability.port_number liczba dziesiętna Tylko do odczytu
ltr port_header.control.tolerancja_opóźnienia liczba dziesiętna Tylko do odczytu

Nagłówek portu AFU sysfs files
intel-fpga-dev.i/intel-fpga-port.k/

system plików file pole mmio typ dostęp
afu_id afu_header.guid szesnastkowy 16-bajtowy Tylko do odczytu

Błąd portu sysfs files
intel-fpga-dev.i/intel-fpga-port.k/błędy/

system plików file pole mmio typ dostęp
błędy perror.port_error szesnastkowy uint64_t Tylko do odczytu
pierwszy_błąd perror.port_first_error szesnastkowy uint64_t Tylko do odczytu
first_malformed_req perror.malreq szesnastkowy 16-bajtowy Tylko do odczytu
jasne perror.(wszystkie błędy) różne uint64_t Tylko do zapisu

Notatka:
Aby wyczyścić błędy portu, należy zapisać dokładną maskę bitową bieżących błędów, np.ampbłędy le cat > wyczyść.

Historia rewizji

Wersja dokumentu Zmiany
2017.10.02 Pierwsze wydanie.

Przewodnik po architekturze sterownika urządzenia OPAE Intel FPGA Linux

Dokumenty / Zasoby

Intel OPAE FPGA Linux Device Driver Architecture [plik PDF] Instrukcja użytkownika
Architektura sterownika urządzenia FPGA systemu Linux firmy OPAE, OPAE FPGA, architektura sterownika urządzenia Linux, architektura sterownika, architektura

Odniesienia

Zostaw komentarz

Twój adres e-mail nie zostanie opublikowany. Wymagane pola są oznaczone *