intel-λογότυπο

intel OPAE FPGA Linux Device Driver Architecture

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

OPAE Intel FPGA Linux Device Driver Architecture

Το πρόγραμμα οδήγησης OPAE Intel FPGA παρέχει διεπαφές για εφαρμογές χώρου χρήστη για διαμόρφωση, απαρίθμηση, άνοιγμα και πρόσβαση σε επιταχυντές FPGA σε πλατφόρμες εξοπλισμένες με λύσεις Intel FPGA και ενεργοποιεί λειτουργίες διαχείρισης σε επίπεδο συστήματος, όπως αναδιαμόρφωση FPGA, διαχείριση ενέργειας και εικονικοποίηση.

Αρχιτεκτονική υλικού

Από την πλευρά του ΛΣ view, το υλικό FPGA εμφανίζεται ως κανονική συσκευή PCIe. Η μνήμη της συσκευής FPGA οργανώνεται χρησιμοποιώντας μια προκαθορισμένη δομή δεδομένων (Λίστα δυνατοτήτων συσκευής). Οι δυνατότητες που υποστηρίζονται από τη συσκευή FPGA εκτίθενται μέσω αυτών των δομών δεδομένων, όπως φαίνεται παρακάτω στην παρακάτω εικόνα:

Συσκευή FPGA PCIe

intel-OPAE-FPGA-Linux-Device-Driver-Architecture-fig- (1)

Το πρόγραμμα οδήγησης υποστηρίζει PCIe SR-IOV για τη δημιουργία Virtual Functions (VF) που μπορούν να χρησιμοποιηθούν για την εκχώρηση μεμονωμένων επιταχυντών σε εικονικές μηχανές.

Intel Corporation. Με την επιφύλαξη παντός δικαιώματος. Η ονομασία Intel, το λογότυπο Intel και άλλα σήματα Intel είναι εμπορικά σήματα της Intel Corporation ή των θυγατρικών της. Η Intel εγγυάται την απόδοση των προϊόντων FPGA και ημιαγωγών της σύμφωνα με τις τρέχουσες προδιαγραφές σύμφωνα με την τυπική εγγύηση της Intel, αλλά διατηρεί το δικαίωμα να κάνει αλλαγές σε οποιαδήποτε προϊόντα και υπηρεσίες ανά πάσα στιγμή χωρίς προειδοποίηση. Η Intel δεν αναλαμβάνει καμία ευθύνη ή ευθύνη που απορρέει από την εφαρμογή ή τη χρήση οποιασδήποτε πληροφορίας, προϊόντος ή υπηρεσίας που περιγράφεται στο παρόν, εκτός εάν συμφωνηθεί ρητά εγγράφως από την Intel. Συνιστάται στους πελάτες της Intel να λαμβάνουν την πιο πρόσφατη έκδοση των προδιαγραφών της συσκευής προτού βασιστούν σε οποιεσδήποτε δημοσιευμένες πληροφορίες και προτού υποβάλουν παραγγελίες για προϊόντα ή υπηρεσίες.

Άλλα ονόματα και επωνυμίες μπορούν να διεκδικηθούν ως ιδιοκτησία άλλων.

Εικονική συσκευή FPGA PCIe

intel-OPAE-FPGA-Linux-Device-Driver-Architecture-fig- (2)

Μηχανή διαχείρισης FPGA (FME)
Το FPGA Management Engine εκτελεί διαχείριση ισχύος και θερμικής ενέργειας, αναφορά σφαλμάτων, επαναδιαμόρφωση, αναφορά απόδοσης και άλλες λειτουργίες υποδομής. Κάθε FPGA έχει ένα FME, το οποίο είναι πάντα προσβάσιμο μέσω της Φυσικής Λειτουργίας (PF). Οι εφαρμογές χώρου χρήστη μπορούν να αποκτήσουν αποκλειστική πρόσβαση στο FME χρησιμοποιώντας το open() και να το απελευθερώσουν χρησιμοποιώντας το close() ως προνομιούχο χρήστη (root).

Λιμάνι
Μια Θύρα αντιπροσωπεύει τη διασύνδεση μεταξύ του στατικού υφάσματος FPGA (το "FPGA Interface Manager (FIM)") και μιας μερικώς αναδιαμορφώσιμης περιοχής που περιέχει μια Λειτουργία Επιταχυντή (AF). Η Θύρα ελέγχει την επικοινωνία από το λογισμικό στον επιταχυντή και εκθέτει λειτουργίες όπως η επαναφορά και ο εντοπισμός σφαλμάτων. Μια συσκευή PCIe μπορεί να έχει πολλές θύρες και κάθε θύρα μπορεί να εκτεθεί μέσω ενός VF εκχωρώντας το χρησιμοποιώντας το FPGA_FME_PORT_ASSIGN ioctl στη συσκευή FME.

Μονάδα Λειτουργίας Επιταχυντή (AF).

  • Μια μονάδα Λειτουργίας Επιταχυντή (AF) είναι συνδεδεμένη σε μια Θύρα και εκθέτει μια περιοχή MMIO 256K που θα χρησιμοποιηθεί για καταχωρητές ελέγχου ειδικούς για τον επιταχυντή.
  • Οι εφαρμογές χώρου χρήστη μπορούν να αποκτήσουν αποκλειστική πρόσβαση σε μια AFU συνδεδεμένη σε μια θύρα χρησιμοποιώντας την open() στη συσκευή Port και να την απελευθερώσουν χρησιμοποιώντας την close().
  • Οι εφαρμογές χώρου χρήστη μπορούν επίσης να επιταχύνουν τις περιοχές MMIO mmap().

Μερική αναδιαμόρφωση
Όπως αναφέρθηκε παραπάνω, οι επιταχυντές μπορούν να διαμορφωθούν εκ νέου μέσω μερικής επαναδιαμόρφωσης μιας Λειτουργίας Επιταχυντή (AF) file. Η Λειτουργία Επιταχυντή (AF) πρέπει να έχει δημιουργηθεί για το ακριβές FIM και τη στοχευμένη στατική περιοχή (Θύρα) του FPGA. Διαφορετικά, η λειτουργία επαναδιαμόρφωσης θα αποτύχει και πιθανώς θα προκαλέσει αστάθεια του συστήματος. Αυτή η συμβατότητα μπορεί να ελεγχθεί συγκρίνοντας το αναγνωριστικό διεπαφής που σημειώνεται στην κεφαλίδα AF με το αναγνωριστικό διεπαφής που εκτίθεται από το FME μέσω του sysfs. Αυτός ο έλεγχος γίνεται συνήθως από το χώρο χρήστη πριν καλέσετε την αναδιαμόρφωση IOCTL.

Σημείωμα:
Επί του παρόντος, κάθε πρόγραμμα λογισμικού που έχει πρόσβαση στο FPGA, συμπεριλαμβανομένων εκείνων που εκτελούνται σε έναν εικονικοποιημένο κεντρικό υπολογιστή, πρέπει να κλείσει πριν από την προσπάθεια μερικής αναδιάρθρωσης. Τα βήματα θα ήταν:

  1. Ξεφορτώστε το πρόγραμμα οδήγησης από τον επισκέπτη
  2. Αποσυνδέστε το VF από τον επισκέπτη
  3. Απενεργοποιήστε το SR-IOV
  4. Εκτελέστε μερική αναδιαμόρφωση
  5. Ενεργοποίηση SR-IOV
  6. Συνδέστε το VF στον επισκέπτη
  7. Φορτώστε τον οδηγό στον επισκέπτη

Εικονικοποίηση FPGA
Για να ενεργοποιήσετε την πρόσβαση σε έναν επιταχυντή από εφαρμογές που εκτελούνται σε VM, η αντίστοιχη θύρα AFU πρέπει να αντιστοιχιστεί σε ένα VF χρησιμοποιώντας τα ακόλουθα βήματα:

  1. Το PF κατέχει όλες τις θύρες AFU από προεπιλογή. Οποιαδήποτε θύρα πρέπει να αντιστοιχιστεί εκ νέου σε ένα VF πρέπει πρώτα να αποδεσμευτεί από το PF μέσω του FPGA_FME_PORT_RELEASE ioctl στη συσκευή FME.
  2. Μόλις απελευθερωθούν N θύρες από το PF, η παρακάτω εντολή μπορεί να χρησιμοποιηθεί για την ενεργοποίηση των SRIOV και VF. Κάθε VF διαθέτει μόνο μία θύρα με AFU. echo N > PCI_DEVICE_PATH/sriov_numvfs
  3. Περάστε μέσα από τα VF στα VM.
  4. Το AFU υπό VF είναι προσβάσιμο από εφαρμογές σε VM (χρησιμοποιώντας το ίδιο πρόγραμμα οδήγησης μέσα στο VF).

Σημείωμα:
Ένα FME δεν μπορεί να εκχωρηθεί σε ένα VF, επομένως το PR και άλλες λειτουργίες διαχείρισης είναι διαθέσιμες μόνο μέσω του PF.

Οργάνωση οδηγών

Πρόγραμμα οδήγησης συσκευής PCIe Module

Οργάνωση οδηγών

intel-OPAE-FPGA-Linux-Device-Driver-Architecture-fig- (3)

Οι συσκευές FPGA εμφανίζονται ως κανονικές συσκευές PCIe. Έτσι, το πρόγραμμα οδήγησης συσκευής FPGA PCIe (intel-FPGA-PCI.ko) φορτώνεται πάντα πρώτο μόλις εντοπιστεί ένα FPGA PCIe PF ή VF. Αυτό το πρόγραμμα οδήγησης παίζει έναν ρόλο υποδομής στην αρχιτεκτονική του προγράμματος οδήγησης. Το:

  • Δημιουργεί μια συσκευή κοντέινερ FPGA ως γονέα των συσκευών χαρακτηριστικών.
  • Περπατάει στη Λίστα δυνατοτήτων συσκευής, η οποία υλοποιείται στη μνήμη BAR της συσκευής PCIe, για να ανακαλύψει τις συσκευές χαρακτηριστικών και τις δευτερεύουσες δυνατότητες τους και να δημιουργήσει συσκευές πλατφόρμας για αυτές κάτω από τη συσκευή κοντέινερ.
  • Υποστηρίζει SR-IOV.
  • Παρουσιάζει την υποδομή συσκευών χαρακτηριστικών, η οποία αφαιρεί λειτουργίες για δευτερεύουσες δυνατότητες και εκθέτει κοινές λειτουργίες σε προγράμματα οδήγησης συσκευών χαρακτηριστικών.

Λειτουργίες προγράμματος οδήγησης συσκευής PCIe Module

  • Περιέχει ανακάλυψη PCIe, απαρίθμηση συσκευών και ανακάλυψη χαρακτηριστικών.
  • Δημιουργεί καταλόγους sysfs για τη γονική συσκευή, το FPGA Management Engine (FME) και τη Θύρα.
  • Δημιουργεί τις παρουσίες προγραμμάτων οδήγησης πλατφόρμας, αναγκάζοντας τον πυρήνα του Linux να φορτώσει τα αντίστοιχα προγράμματα οδήγησης της μονάδας πλατφόρμας.

Πρόγραμμα οδήγησης συσκευής μονάδας πλατφόρμας FME

  • Διαχείριση ισχύος και θερμικής ενέργειας, αναφορά σφαλμάτων, αναφορά απόδοσης και άλλες λειτουργίες υποδομής. Μπορείτε να έχετε πρόσβαση σε αυτές τις λειτουργίες μέσω διεπαφών sysfs που εκτίθενται από το πρόγραμμα οδήγησης FME.
  • Μερική αναδιαμόρφωση. Το πρόγραμμα οδήγησης FME καταχωρεί έναν διαχειριστή FPGA κατά την προετοιμασία της δευτερεύουσας δυνατότητας PR. Μόλις λάβει ένα FPGA_FME_PORT_PR ioctl από εσάς, καλεί την κοινή συνάρτηση διεπαφής από το FPGA Manager για να ολοκληρώσει τη μερική επαναδιαμόρφωση της ροής bit στη δεδομένη θύρα.
  • Διαχείριση θυρών για εικονικοποίηση. Το πρόγραμμα οδήγησης FME εισάγει δύο ioctls, FPGA_FME_PORT_RELEASE, τα οποία απελευθερώνουν τη δεδομένη θύρα από το PF. και FPGA_FME_PORT_ASSIGN, που εκχωρεί τη Θύρα πίσω στο PF. Μόλις η Θύρα απελευθερωθεί από το PF, μπορεί να αντιστοιχιστεί στο VF μέσω των διασυνδέσεων SR-IOV που παρέχονται από το πρόγραμμα οδήγησης PCIe. Για περισσότερες πληροφορίες, ανατρέξτε στην ενότητα «Εικονικοποίηση FPGA».

Λειτουργίες προγράμματος οδήγησης συσκευής μονάδας πλατφόρμας FME

  • Δημιουργεί τον κόμβο συσκευής χαρακτήρων FME.
  • Δημιουργεί το FME sysfs files και υλοποιεί το FME sysfs file αξεσουάρ.
  • Υλοποιεί τα δευτερεύοντα προγράμματα οδήγησης ιδιωτικών χαρακτηριστικών FME.
  • Υποπρογράμματα οδήγησης ιδιωτικών δυνατοτήτων FME:
    • Κεφαλίδα FME
    • Θερμική Διαχείριση
    • Διαχείριση ενέργειας
    • Παγκόσμιο Σφάλμα
    • Μερική αναδιαμόρφωση
    • Παγκόσμια Απόδοση

Πρόγραμμα οδήγησης συσκευής Port Platform Module
Παρόμοια με το πρόγραμμα οδήγησης FME, το πρόγραμμα οδήγησης θύρας FPGA (και AFU) (intel-fpga-afu. ko) εξετάζεται μόλις δημιουργηθεί η συσκευή πλατφόρμας Port. Η κύρια λειτουργία αυτής της ενότητας είναι να παρέχει μια διεπαφή για εφαρμογές χώρου χρήστη για πρόσβαση στους μεμονωμένους επιταχυντές, συμπεριλαμβανομένου του βασικού ελέγχου επαναφοράς στη θύρα, της εξαγωγής περιοχής AFU MMIO, της υπηρεσίας χαρτογράφησης buffer DMA, της ειδοποίησης UMsg(1) και των λειτουργιών απομακρυσμένου εντοπισμού σφαλμάτων ( βλέπε παραπάνω).

Το UMsg υποστηρίζεται μόνο μέσω του Acceleration Stack για επεξεργαστή Intel Xeon® με ενσωματωμένο FPGA.

Port Platform Module Device Driver Λειτουργίες

  • Δημιουργεί τον κόμβο συσκευής χαρακτήρων Port.
  • Δημιουργεί το Port sysfs files και υλοποιεί το Port sysfs file αξεσουάρ.
  • Υλοποιεί τα δευτερεύοντα προγράμματα οδήγησης χαρακτηριστικών Port private.
  • Υποπρογράμματα οδήγησης ιδιωτικών δυνατοτήτων θύρας:
    • Port Header
    • AFU
    • Σφάλμα θύρας
    • UMsg(2)
    • Πατήστε σήματος

Εφαρμογή FPGA Device Enumeration
Αυτή η ενότητα εισάγει τον τρόπο με τον οποίο οι εφαρμογές απαριθμούν τη συσκευή FPGA από την ιεραρχία sysfs στο /sys/class/fpga. Στην πρampΠαρακάτω, δύο συσκευές Intel FPGA είναι εγκατεστημένες στον κεντρικό υπολογιστή. Κάθε συσκευή FPGA έχει μία FME και δύο Θύρες (AFU). Για κάθε συσκευή FPGA, δημιουργείται ένας κατάλογος συσκευών στο /sys/class/fpga:

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

Κάθε κόμβος έχει ένα FME και δύο Θύρες (AFU) ως θυγατρικές συσκευές:
/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

Γενικά, οι διεπαφές FME/Port sysfs ονομάζονται ως εξής:
/sys/class/fpga/intel-fpga-dev.i/intel-fpga-fme.j/
/sys/class/fpga/intel-fpga-dev.i/intel-fpga-port.k/

με I να αριθμεί διαδοχικά όλες τις συσκευές κοντέινερ, j να αριθμεί διαδοχικά τα FME και k να αριθμεί διαδοχικά όλες τις θύρες.

Οι κόμβοι της συσκευής που χρησιμοποιούνται για ioctl() και mmap() μπορούν να αναφέρονται μέσω:
/dev/intel-fpga-fme.j
/dev/intel-fpga-port.k

Αριθμός προγραμμάτων οδήγησης PCIe
Αυτή η ενότητα δίνει ένα overview της ροής κώδικα για την απαρίθμηση συσκευών που εκτελείται από το intel-fpga-pci.ko. Επισημαίνονται οι κύριες δομές και λειτουργίες δεδομένων. Αυτή η ενότητα ακολουθείται καλύτερα όταν viewμε τον συνοδευτικό πηγαίο κώδικα (pcie.c).

Αριθμητικές Δομές Δεδομένων

enum fpga_id_type {
PARENT_ID,
FME_ID,
PORT_ID,
FPGA_ID_MAX
};
στατική δομή idr fpga_ids[FPGA_ID_MAX];
struct fpga_chardev_info {
const char *όνομα;
dev_t devt;
};
struct fpga_chardev_info fpga_chrdevs[] = {
{ .name = FPGA_FEATURE_DEV_FME },
{ .name = FPGA_FEATURE_DEV_PORT },
};
static struct class *fpga_class;
στατική δομή 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,}
};
στατική κατασκευή pci_driver cci_pci_driver = {
.name = DRV_NAME,
.id_table = cci_pcie_id_tbl,
.probe = cci_pci_probe,
.remove = cci_pci_remove,
.sriov_configure = cci_pci_sriov_configure
};
struct cci_drvdata {
int device_id;
struct συσκευή *fme_dev;
struct mutex κλειδαριά?
struct list_head port_dev_list;
int release_port_num;
struct list_head περιοχές?
};
struct build_feature_devs_info {
struct pci_dev *pdev;
void __iomem *ioaddr;
void __iomem *ioend;
int current_bar;
void __iomem *pfme_hdr;
struct συσκευή *parent_dev;
struct platform_device *feature_dev;
};

Ροή απαρίθμησης

  • ccidrv_init()
    • Αρχικοποιήστε τα fpga_ids χρησιμοποιώντας idr_init().
    • Αρχικοποιήστε το fpga_chrdevs[i].devt χρησιμοποιώντας alloc_chrdev_region().
    • Εκκινήστε το fpga_class χρησιμοποιώντας class_create().
    • pci_register_driver(&cci_pci_driver);
  • cci_pci_probe()
    • Ενεργοποιήστε τη συσκευή PCI, ζητήστε πρόσβαση στις περιοχές της, ορίστε την κύρια λειτουργία PCI και διαμορφώστε το DMA.
  • cci_pci_create_feature_devs() build_info_alloc_and_init()
    • Εκχωρήστε μια δομή build_feature_devs_info, αρχικοποιήστε την.
      Το .parent_dev έχει οριστεί σε έναν γονικό κατάλογο sysfs (intel-fpga-dev.id) που περιέχει τους καταλόγους FME και Port sysfs.
  • parse_feature_list()
    • Περπατήστε στη λίστα δυνατοτήτων συσκευής BAR0 για να ανακαλύψετε το FME, τη θύρα και τις ιδιωτικές τους λειτουργίες.
  • parse_feature() parse_feature_afus() parse_feature_fme()
    • Όταν αντιμετωπίζετε ένα FME:
  • build_info_create_dev()
    • Εκχωρήστε μια συσκευή πλατφόρμας για το FME, που αποθηκεύεται στο build_feature_devs_info.feature_dev.
    • Το feature_dev.id αρχικοποιείται στο αποτέλεσμα του idr_alloc(fpga_ids[FME_ID],
    • Το feature_dev.parent έχει οριστεί σε build_feature_devs_info.parent_dev.
    • Εκχωρήστε έναν πίνακα πόρων struct στο feature_dev.resource.
  • Εκχωρήστε μια δομή feature_platform_data, αρχικοποιήστε την και αποθηκεύστε έναν δείκτη στο feature_dev.dev.platform_data
    • create_feature_instance() build_info_add_sub_feature()
    • Εκκινήστε το feature_dev.resource[FME_FEATURE_ID_HEADER].
    • feature_platform_data_add()
    • Ξεκινήστε το feature_platform_data.features[FME_FEATURE_ID_HEADER], τα πάντα εκτός από .fops.
  • parse_feature() parse_feature_afus() parse_feature_port()
    • Όταν συναντήσετε μια θύρα:
  • build_info_create_dev()
    • Εκχωρήστε μια συσκευή πλατφόρμας για τη Θύρα, η οποία αποθηκεύεται στο build_feature_devs_info.feature_dev.
    • Το feature_dev.id αρχικοποιείται στο αποτέλεσμα του idr_alloc(fpga_ids[PORT_ID],
    • Το feature_dev.parent έχει οριστεί σε build_feature_devs_info.parent_dev.
    • Εκχωρήστε έναν πίνακα πόρων struct στο feature_dev.resource.
    • Εκχωρήστε μια δομή feature_platform_data, αρχικοποιήστε την και αποθηκεύστε έναν δείκτη στο feature_dev.dev.platform_data
  • build_info_commit_dev()
    • Προσθέστε το struct feature_platform_data.node για το Port στη λίστα των Ports στο struct cci_drvdata.port_dev_list
  • create_feature_instance() build_info_add_sub_feature()
    • Εκκινήστε το feature_dev.resource[PORT_FEATURE_ID_HEADER].
  • feature_platform_data_add()
    • Αρχικοποιήστε το feature_platform_data.features[PORT_FEATURE_ID_HEADER], τα πάντα εκτός από .fops.
  • parse_feature() parse_feature_afus() parse_feature_port_uafu()
    • Όταν αντιμετωπίζεται μια AFU:
  • create_feature_instance() build_info_add_sub_feature()
    • Εκκινήστε το feature_dev.resource[PORT_FEATURE_ID_UAFU].
  • feature_platform_data_add()
    • Ξεκινήστε το feature_platform_data.features[PORT_FEATURE_ID_UAFU], τα πάντα εκτός από .fops.
  • parse_feature() parse_feature_private() parse_feature_fme_private()
    • Όταν αντιμετωπίζετε μια ιδιωτική δυνατότητα FME:
  • create_feature_instance() build_info_add_sub_feature()
    • Αρχικοποίηση feature_dev.resource[id].
  • feature_platform_data_add()
    • Ξεκινήστε το feature_platform_data.features[id], τα πάντα εκτός από το .fops.
  • parse_feature() parse_feature_private() parse_feature_port_private()
  • Όταν αντιμετωπίζεται μια ιδιωτική δυνατότητα Port: * create_feature_instance() build_info_add_sub_feature() * Initialize feature_dev.resource[id]. * feature_platform_data_add() Εκκίνηση feature_platform_data.features[id], τα πάντα εκτός από .fops.
  • parse_ports_from_fme()
    • Εάν το πρόγραμμα οδήγησης είναι φορτωμένο στο Physical Function (PF), τότε:
  • Εκτελέστε τη ροή parse_feature_list() σε κάθε θύρα που περιγράφεται στην κεφαλίδα FME.
  • Χρησιμοποιήστε τη BAR που αναφέρεται σε κάθε καταχώρηση Port στην κεφαλίδα.

Αρχικοποίηση συσκευής πλατφόρμας FME
Αυτή η ενότητα δίνει ένα overview της ροής κώδικα για την προετοιμασία της συσκευής FME που εκτελείται από το intel-fpga-fme.ko. Οι κύριες δομές και λειτουργίες δεδομένων επισημαίνονται. Αυτή η ενότητα ακολουθείται καλύτερα όταν viewμε τον συνοδευτικό πηγαίο κώδικα (fme-main.c).

Δομές δεδομένων συσκευής πλατφόρμας FME

struct feature_ops {
int (*init)(struct platform_device *pdev, struct feature *feature);
int (*uinit)(struct platform_device *pdev, struct feature *feature);
long (*ioctl)(struct platform_device *pdev, struct feature *feature,
ανυπόγραφο int cmd, ανυπόγραφο μακρύ arg).
int (*test)(struct platform_device *pdev, struct feature *feature);
};
struct χαρακτηριστικό {
const char *όνομα;
int resource_index;
void __iomem *ioaddr;
struct feature_ops *ops;
};
struct feature_platform_data {
struct list_head node.
struct mutex κλειδαριά?
ανυπόγραφο long dev_status.
struct cdev cdev;
struct platform_device *dev;
ανυπόγραφο int disable_count;
void *private;
int num;
int (*config_port)(struct platform_device *, u32, bool);
struct platform_device *(*fpga_for_each_port)(struct platform_device *,
void *, int (*match)(struct platform_device *, void *)); struct
χαρακτηριστικά γνωρίσματα[0];
};
struct perf_object {
int id?
const struct χαρακτηριστικό_ομάδα **attr_groups;
struct συσκευή *fme_dev;
struct list_head node.
struct list_head παιδιά?
struct kobject kobj;
};
struct fpga_fme {
u8 port_id;
u64 pr_err;
struct συσκευή *dev_err;
struct perf_object *perf_dev;
struct feature_platform_data *pdata;
};

Ροή εκκίνησης συσκευής πλατφόρμας FME

Ροή εκκίνησης FMEintel-OPAE-FPGA-Linux-Device-Driver-Architecture-fig- (4)

  • fme_probe() fme_dev_init()
    • Αρχικοποιήστε μια δομή fpga_fme και αποθηκεύστε την στο πεδίο feature_platform_data.private.
  • fme_probe() fpga_dev_feature_init() feature_instance_init()
    • Αποθηκεύστε μια δομή feature_ops στα feature_platform_data.features για κάθε συμπληρωμένη δυνατότητα.
    • Καλέστε τη συνάρτηση δοκιμής, εάν υπάρχει, από τη δομή.
    • Καλέστε τη συνάρτηση init από τη δομή.
  • fme_probe() fpga_register_dev_ops()
    • Δημιουργήστε τον κόμβο συσκευής χαρακτήρων FME, καταχωρώντας μια δομή file_λειτουργίες.

Αρχικοποίηση συσκευής πλατφόρμας θύρας
Αυτή η ενότητα δίνει ένα overview της ροής κώδικα για την προετοιμασία της συσκευής θύρας που εκτελείται από το intel-fpga-afu.ko. Επισημαίνονται οι κύριες δομές και λειτουργίες δεδομένων. Αυτή η ενότητα ακολουθείται καλύτερα όταν viewμε τον συνοδευτικό πηγαίο κώδικα (afu.c).

Δομές δεδομένων συσκευής πλατφόρμας λιμένων

struct feature_ops {
int (*init)(struct platform_device *pdev, struct feature *feature);
int (*uinit)(struct platform_device *pdev, struct feature *feature);
long (*ioctl)(struct platform_device *pdev, struct feature *feature,
ανυπόγραφο int cmd, ανυπόγραφο μακρύ arg).
int (*test)(struct platform_device *pdev, struct feature *feature);
};
struct χαρακτηριστικό {
const char *όνομα;
int resource_index;
void __iomem *ioaddr;
struct feature_ops *ops;
};
struct feature_platform_data {
struct list_head node.
struct mutex κλειδαριά?
ανυπόγραφο long dev_status.
struct cdev cdev;
struct platform_device *dev;
ανυπόγραφο int disable_count;
void *private;
int num;
int (*config_port)(struct platform_device *, u32, bool);
struct platform_device *(*fpga_for_each_port)(struct platform_device *,
void *, int (*match)(struct platform_device *, void *));
struct χαρακτηριστικά γνωρίσματα[0];
};
δομή fpga_afu_region {
ευρετήριο u32;
σημαίες u32?
μέγεθος u64;
μετατόπιση u64;
u64 φυσ.
struct list_head node.
};
struct fpga_afu_dma_region {
u64 user_addr;
u64 μήκος?
u64 iova;
struct σελίδα **σελίδες;
struct rb_node node;
bool in_use;
};
δομή fpga_afu {
u64 region_cur_offset;
int num_regions;
u8 num_umsgs;
struct list_head περιοχές?
struct rb_root dma_regions;
struct feature_platform_data *pdata;
};

Ροή εκκίνησης συσκευής πλατφόρμας θύρας

Ροή εκκίνησης θύραςintel-OPAE-FPGA-Linux-Device-Driver-Architecture-fig- (5)

  • afu_probe() afu_dev_init()
    • Αρχικοποιήστε μια δομή fpga_afu και αποθηκεύστε την στο πεδίο feature_platform_data.private.
  • afu_probe() fpga_dev_feature_init() feature_instance_init()
    • Αποθηκεύστε μια δομή feature_ops στα feature_platform_data.features για κάθε συμπληρωμένη δυνατότητα.
    • Καλέστε τη συνάρτηση δοκιμής, εάν υπάρχει, από τη δομή.
    • Καλέστε τη συνάρτηση init από τη δομή.
  • afu_probe() fpga_register_dev_ops()
    • Δημιουργήστε τον κόμβο συσκευής χαρακτήρων Port, καταχωρώντας μια δομή file_λειτουργίες.

FME IOCTLs
IOCTL που καλούνται σε ανοιχτό file περιγραφέας για /dev/intel-fpga-fme.j FPGA_GET_API_VERSION—επιστρέφετε την τρέχουσα έκδοση ως ακέραιο, ξεκινώντας από το 0.

FPGA_CHECK_EXTENSION—δεν υποστηρίζεται αυτήν τη στιγμή.

FPGA_FME_PORT_RELEASE—το arg είναι δείκτης σε:

struct fpga_fme_port_release {
__u32 argsz; // σε: sizeof(struct fpga_fme_port_release)
__u32 σημαίες; // σε: πρέπει να είναι 0
__u32 port_id; // σε: αναγνωριστικό θύρας (από 0) για απελευθέρωση.
};

FPGA_FME_PORT_ASSIGN—το arg είναι ένας δείκτης σε ένα:

struct fpga_fme_port_assign {
__u32 argsz; // σε: sizeof(struct fpga_fme_port_assign)
__u32 σημαίες; // σε: πρέπει να είναι 0
__u32 port_id; // σε: αναγνωριστικό θύρας (από 0) για εκχώρηση. (πρέπει να ήταν
κυκλοφόρησε προηγουμένως από την FPGA_FME_PORT_RELEASE)
};

FPGA_FME_PORT_PR—το arg είναι δείκτης σε:

struct fpga_fme_port_pr {
__u32 argsz; // σε: sizeof(struct fpga_fme_port_pr)
__u32 σημαίες; // σε: πρέπει να είναι 0
__u32 port_id; // σε: αναγνωριστικό θύρας (από 0)
__u32 buffer_size; // σε: μέγεθος buffer ροής bit σε byte. Πρέπει να είναι 4 byte
ευθυγραμμισμένος.
__u64 buffer_address; // in: διεύθυνση διεργασίας της προσωρινής μνήμης bitstream
__u64 κατάσταση; // out: κατάσταση σφάλματος (bitmask)
};

Λιμάνι IOCTLs
IOCTL που καλούνται σε ανοιχτό file περιγραφέας για /dev/intel-fpga-port.k FPGA_GET_API_VERSION—επιστρέφετε την τρέχουσα έκδοση ως ακέραιο αριθμό, ξεκινώντας από το 0. FPGA_CHECK_EXTENSION—δεν υποστηρίζεται αυτήν τη στιγμή.

FPGA_PORT_GET_INFO—το arg είναι δείκτης σε:

struct fpga_port_info {
__u32 argsz; // σε: sizeof(struct fpga_port_info)
__u32 σημαίες; // out: επιστρέφει 0
__u32 num_regions; // out: αριθμός περιοχών MMIO, 2 (1 για AFU και 1 για
STP)
__u32 num_umsgs; // out: αριθμός των UMsg που υποστηρίζονται από το υλικό
};

FPGA_PORT_GET_REGION_INFO—το arg είναι ένας δείκτης σε:

struct fpga_port_region_info {
__u32 argsz; // σε: sizeof(struct fpga_port_region_info)
__u32 σημαίες; // out: (bitmask) { FPGA_REGION_READ, FPGA_REGION_WRITE,
FPGA_REGION_MMAP }
__u32 ευρετήριο; // σε: FPGA_PORT_INDEX_UAFU ή FPGA_PORT_INDEX_STP
__u32 padding; // σε: πρέπει να είναι 0
__u64 μέγεθος; // out: μέγεθος της περιοχής MMIO σε byte
__u64 μετατόπιση; // out: μετατόπιση της περιοχής MMIO από την έναρξη της συσκευής fd
};

FPGA_PORT_DMA_MAP—το arg είναι ένας δείκτης σε ένα:
struct fpga_port_dma_map {
__u32 argsz; // σε: sizeof(struct fpga_port_dma_map)
__u32 σημαίες; // in: πρέπει να είναι 0 __u64 user_addr; // σε: εικονική διαδικασία
διεύθυνση. Πρέπει να είναι ευθυγραμμισμένη με τη σελίδα.
__u64 μήκος; // σε: μήκος αντιστοίχισης σε byte. Πρέπει να είναι πολλαπλάσιο της σελίδας
μέγεθος.
__u64 iova; // out: εικονική διεύθυνση IO };

FPGA_PORT_DMA_UNMAP—το arg είναι ένας δείκτης σε ένα:
struct fpga_port_dma_unmap {
__u32 argsz; // σε: sizeof(struct fpga_port_dma_unmap)
__u32 σημαίες; // σε: πρέπει να είναι 0
__u64 iova; // in: Εικονική διεύθυνση IO που επιστράφηκε από προηγούμενη
FPGA_PORT_DMA_MAP };

  • FPGA_PORT_RESET—το arg πρέπει να είναι NULL.
  • FPGA_PORT_UMSG_ENABLE—το arg πρέπει να είναι NULL.
  • FPGA_PORT_UMSG_DISABLE—τα όρκια πρέπει να είναι NULL.

FPGA_PORT_UMSG_SET_MODE—το arg είναι δείκτης σε:

struct fpga_port_umsg_cfg {
__u32 argsz; // σε: sizeof(struct fpga_port_umsg_cfg)
__u32 σημαίες; // σε: πρέπει να είναι 0
__u32 hint_bitmap; // σε: UMsg bitmap λειτουργίας υπόδειξης. Υποδηλώνει ποια είναι τα UMsg
ενεργοποιημένη.
};

FPGA_PORT_UMSG_SET_BASE_ADDR—

  • Το UMsg πρέπει να είναι απενεργοποιημένο πριν από την έκδοση αυτού του ioctl.
  • Το πεδίο iova πρέπει να είναι για ένα buffer αρκετά μεγάλο για όλα τα UMsg (αριθμός_umsgs * PAGE_SIZE).
    • Το buffer επισημαίνεται ως "σε χρήση" από τη διαχείριση buffer του προγράμματος οδήγησης.
    • Εάν το iova είναι NULL, οποιαδήποτε προηγούμενη περιοχή δεν επισημαίνεται ως "σε χρήση".
  • Το arg είναι ένας δείκτης σε:
    struct fpga_port_umsg_base_addr {
    • u32 argsz; // σε: sizeof(struct fpga_port_umsg_base_addr)
    • σημαίες u32? // σε: πρέπει να είναι 0
    • u64 iova; // σε: εικονική διεύθυνση IO από FPGA_PORT_DMA_MAP. };

Σημείωμα:

  • Για να διαγράψετε τα σφάλματα της θύρας, πρέπει να γράψετε την ακριβή μάσκα bitmask των τρεχόντων σφαλμάτων, π.χ.ample, λάθη γάτας > σαφές
  • Το UMsg υποστηρίζεται μόνο μέσω του Acceleration Stack για επεξεργαστή Intel Xeon με ενσωματωμένο FPGA.

sysfs Files

Κεφαλίδα FME sysfs files
intel-fpga-dev.i/intel-fpga-fme.j/

sysfs file πεδίο mmio τύπος πρόσβαση
ports_num fme_header.capability.num_ports δεκαδικός ενθ Μόνο για ανάγνωση
cache_size fme_header.capability.cache_size δεκαδικός ενθ Μόνο για ανάγνωση
εκδοχή fme_header.capability.fabric_verid δεκαδικός ενθ Μόνο για ανάγνωση
socket_id fme_header.capability.socket_id δεκαδικός ενθ Μόνο για ανάγνωση
bitstream_id fme_header.bitstream_id εξάγωνο uint64_t Μόνο για ανάγνωση
bitstream_metadata fme_header.bitstream_md εξάγωνο uint64_t Μόνο για ανάγνωση

FME Thermal Management sysfs files
intel-fpga-dev.i/intel-fpga-fme.j/thermal_mgmt/

sysfs file πεδίο mmio τύπος πρόσβαση
κατώφλι 1 thermal.threshold.tmp_thshold1 δεκαδικός ενθ Χρήστης: Root μόνο για ανάγνωση: Read-write
κατώφλι 2 thermal.threshold.tmp_thshold2 δεκαδικός ενθ Χρήστης: Root μόνο για ανάγνωση: Read-write
threshold_trip thermal.threshold.therm_trip_thshold δεκαδικός ενθ Μόνο για ανάγνωση
threshold1_reached thermal.threshold.thshold1_status δεκαδικός ενθ Μόνο για ανάγνωση
threshold2_reached thermal.threshold.thshold2_status δεκαδικός ενθ Μόνο για ανάγνωση
threshold1_policy θερμικός. threshold.thshold_policy δεκαδικός ενθ Χρήστης: Root μόνο για ανάγνωση: Read-write
θερμοκρασία thermal.rdsensor_fm1.fpga_temp δεκαδικός ενθ Μόνο για ανάγνωση

FME Power Management sysfs files
intel-fpga-dev.i/intel-fpga-fme.j/power_mgmt/

sysfs file πεδίο mmio τύπος πρόσβαση
καταναλώνεται power.status.pwr_consumed εξάγωνο uint64_t Μόνο για ανάγνωση
κατώφλι 1 δύναμη.κατώφλι.κατώφλι1 εξάγωνο uint64_t Χρήστης: Root μόνο για ανάγνωση: Read-write
κατώφλι 2 δύναμη.κατώφλι.κατώφλι2 εξάγωνο uint64_t Χρήστης: Root μόνο για ανάγνωση: Read-write
threshold1_status power.threshold.threshold1_status δεκαδικό ανυπόγραφο Μόνο για ανάγνωση
threshold2_status power.threshold.threshold2_status δεκαδικό ανυπόγραφο Μόνο για ανάγνωση
rtl power.status.fpga_latency_report δεκαδικό ανυπόγραφο Μόνο για ανάγνωση

FME Global Error sysfs files
intel-fpga-dev.i/intel-fpga-fme.j/errors/

sysfs file πεδίο mmio τύπος πρόσβαση
pcie0_errors gerror.pcie0_err εξάγωνο uint64_t Διαβάζω γράφω
pcie1_errors gerror.pcie1_err εξάγωνο uint64_t Διαβάζω γράφω
inject_error gerror.ras_error_inj εξάγωνο uint64_t Διαβάζω γράφω

intel-fpga-dev.i/intel-fpga-fme.j/errors/fme-errors/

sysfs file πεδίο mmio τύπος πρόσβαση
λάθη gerror.fme_err εξάγωνο uint64_t Μόνο για ανάγνωση
first_error gerror.fme_first_err.err_reg_status εξάγωνο uint64_t Μόνο για ανάγνωση
επόμενο_σφάλμα gerror.fme_next_err.err_reg_status εξάγωνο uint64_t Μόνο για ανάγνωση
σαφής Διαγράφει σφάλματα, first_error, next_error διάφορα uint64_t Μόνο εγγραφή

Σημείωμα:
Για να διαγράψετε τα σφάλματα FME, πρέπει να γράψετε την ακριβή μάσκα bitmask των τρεχόντων σφαλμάτων, π.χ.ample cat errors > σαφής.

FME Μερική αναδιαμόρφωση sysfs files
intel-fpga-dev.i/intel-fpga-fme.j/pr/

sysfs file πεδίο mmio τύπος πρόσβαση
interface_id pr.fme_pr_intfc_id0_h, pr.fme_pre_intfc_id0_l εξάγωνο 16 byte Μόνο για ανάγνωση

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

sysfs file πεδίο mmio τύπος πρόσβαση
ρολόι gperf.clk.afu_interf_clock εξάγωνο uint64_t Μόνο για ανάγνωση

intel-fpga-dev.i/intel-fpga-fme.j/dperf/cache/ (Δεν ισχύει για Acceleration Stack για Intel Xeon CPU με FPGA)

sysfs file πεδίο mmio τύπος πρόσβαση
πάγωμα gperf.ch_ctl.freeze δεκαδικός ενθ Διαβάζω γράφω
read_hit gperf.CACHE_RD_HIT εξάγωνο uint64_t Μόνο για ανάγνωση
read_miss gperf.CACHE_RD_MISS εξάγωνο uint64_t Μόνο για ανάγνωση
write_hit gperf.CACHE_WR_HIT εξάγωνο uint64_t Μόνο για ανάγνωση
write_miss gperf.CACHE_WR_MISS εξάγωνο uint64_t Μόνο για ανάγνωση
hold_request gperf.CACHE_HOLD_REQ εξάγωνο uint64_t Μόνο για ανάγνωση
tx_req_stall gperf.CACHE_TX_REQ_STALL εξάγωνο uint64_t Μόνο για ανάγνωση
sysfs file πεδίο mmio τύπος πρόσβαση
rx_req_stall gperf.CACHE_RX_REQ_STALL εξάγωνο uint64_t Μόνο για ανάγνωση
data_write_port_contention gperf.CACHE_DATA_WR_PORT_CONTEN εξάγωνο uint64_t Μόνο για ανάγνωση
tag_write_port_contention gperf.CACHE_TAG_WR_PORT_CONTEN εξάγωνο uint64_t Μόνο για ανάγνωση

intel-fpga-dev.i/intel-fpga-fme.j/dperf/iommu/ (Δεν ισχύει για Acceleration Stack για επεξεργαστή Intel Xeon με FPGA)

sysfs file πεδίο mmio τύπος πρόσβαση
πάγωμα gperf.vtd_ctl.freeze δεκαδικός ενθ Χρήστης: Root μόνο για ανάγνωση: Read-write

intel-fpga-dev.i/intel-fpga-fme.j/dperf/iommu/afuk/ (Δεν ισχύει για Acceleration Stack για Intel Xeon CPU με FPGA)

sysfs file πεδίο mmio τύπος πρόσβαση
read_transaction gperf.VTD_AFU0_MEM_RD_TRANS εξάγωνο uint64_t Μόνο για ανάγνωση
write_transaction gperf.VTD_AFU0_MEM_WR_TRANS εξάγωνο uint64_t Μόνο για ανάγνωση
tlb_read_hit gperf.VTD_AFU0_TLB_RD_HIT εξάγωνο uint64_t Μόνο για ανάγνωση
tlb_write_hit gperf.VTD_AFU0_TLB_WR_HIT εξάγωνο uint64_t Μόνο για ανάγνωση

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

sysfs file πεδίο mmio τύπος πρόσβαση
καθιστώ ικανό gperf.fab_ctl.(ενεργοποιημένο) δεκαδικός ενθ Χρήστης: Root μόνο για ανάγνωση: Read-write
πάγωμα gperf.fab_ctl.freeze δεκαδικός ενθ Χρήστης: Root μόνο για ανάγνωση: Read-write
pcie0_read gperf.FAB_PCIE0_RD εξάγωνο uint64_t Μόνο για ανάγνωση
pcie0_write gperf.FAB_PCIE0_WR εξάγωνο uint64_t Μόνο για ανάγνωση
pcie1_read gperf.FAB_PCIE1_RD εξάγωνο uint64_t Μόνο για ανάγνωση
pcie1_write gperf.FAB_PCIE1_WR εξάγωνο uint64_t Μόνο για ανάγνωση
upi_read gperf.FAB_UPI_RD εξάγωνο uint64_t Μόνο για ανάγνωση
upi_write gperf.FAB_UPI_WR εξάγωνο uint64_t Μόνο για ανάγνωση

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

sysfs file πεδίο mmio τύπος πρόσβαση
pcie0_read gperf.FAB_PCIE0_RD εξάγωνο uint64_t Μόνο για ανάγνωση
pcie0_write gperf.FAB_PCIE0_WR εξάγωνο uint64_t Μόνο για ανάγνωση
pcie1_read gperf.FAB_PCIE1_RD εξάγωνο uint64_t Μόνο για ανάγνωση
pcie1_write gperf.FAB_PCIE1_WR εξάγωνο uint64_t Μόνο για ανάγνωση
upi_read gperf.FAB_UPI_RD εξάγωνο uint64_t Μόνο για ανάγνωση
upi_write gperf.FAB_UPI_WR εξάγωνο uint64_t Μόνο για ανάγνωση

Port Header sysfs files
intel-fpga-dev.i/intel-fpga-port.k/

sysfs file πεδίο mmio τύπος πρόσβαση
id port_header.capability.port_number δεκαδικός ενθ Μόνο για ανάγνωση
ltr port_header.control.latency_tolerance δεκαδικός ενθ Μόνο για ανάγνωση

Port AFU Header sysfs files
intel-fpga-dev.i/intel-fpga-port.k/

sysfs file πεδίο mmio τύπος πρόσβαση
afu_id afu_header.guid εξάγωνο 16 byte Μόνο για ανάγνωση

Σφάλμα θύρας sysfs files
intel-fpga-dev.i/intel-fpga-port.k/errors/

sysfs file πεδίο mmio τύπος πρόσβαση
λάθη perror.port_error εξάγωνο uint64_t Μόνο για ανάγνωση
first_error perror.port_first_error εξάγωνο uint64_t Μόνο για ανάγνωση
first_malformed_req πλάκα.malreq εξάγωνο 16 byte Μόνο για ανάγνωση
σαφής λάθος. (όλα τα λάθη) διάφορα uint64_t Μόνο εγγραφή

Σημείωμα:
Για να διαγράψετε τα σφάλματα Port, πρέπει να γράψετε την ακριβή μάσκα bitmask των τρεχόντων σφαλμάτων, π.χample cat errors > σαφής.

Ιστορικό αναθεώρησης

Έκδοση εγγράφου Αλλαγές
2017.10.02 Αρχική Έκδοση.

OPAE Intel FPGA Linux Device Driver Architecture Guide

Έγγραφα / Πόροι

intel OPAE FPGA Linux Device Driver Architecture [pdf] Οδηγός χρήστη
OPAE FPGA Linux Device Driver Architecture, OPAE FPGA, Linux Device Driver Architecture, Driver Architecture, Architecture

Αναφορές

Αφήστε ένα σχόλιο

Η διεύθυνση email σας δεν θα δημοσιευτεί. Τα υποχρεωτικά πεδία επισημαίνονται *