Чтение адреса из структуры возможностей MSI


Можно ли найти расположение структуры возможностей MSI, связанной с конкретным прерыванием? В частности, мне нужно знать адрес PCI, который при записи вызывает прерывание.

Прерывания MSI можно легко инициализировать с помощью функции pci_alloc_irq_vectors(9), но это просто предоставляет номер irq и не ссылается на структуру возможностей.

Для справки структура возможностей описана в этом документе: https://pcisig.com/sites/default/files/specification_documents/msi-x_ecn.pdf

1 3

1 ответ:

Похоже, что вы хотите иметь возможность написать это значение самостоятельно и создать прерывание. Это не совсем то, как работает MSI (хотя это все еще возможно). С помощью MSI (или MSI-X) вы в основном программируете устройство PCI с адресом, на который оно должно генерировать запись данных и значение данных для записи туда, когда должно быть сгенерировано прерывание.

Это не гарантирует AFAIK, что вы можете вызвать то же самое прерывание самостоятельно, написав по адресу. Тем не менее, как правило, адрес, заданный в MSI, является местоположением в адресном пространстве, контролируемом контроллером прерываний (который обычно реализован как само устройство PCI), и значение данных сообщает контроллеру прерываний, какое прерывание инициировать. Таким образом, по всей вероятности, вы можете записать одно и то же значение в один и тот же адрес физической памяти и таким образом создать одно и то же прерывание.

В любом случае, предполагая, что вы знаете, какое устройство PCI генерирует прерывание, вы можете найти структуру возможностей MSI и следовательно, вы можете прочитать то, с чем он был запрограммирован. Это очень просто сделать.

Возможности PCI (которые различаются в зависимости от устройства) организованы в связанный список в конфигурационном пространстве устройства. Начало списка всегда задается байтом со смещением 0x34 в пространстве конфигурации устройства. Это байтовое значение дает вам смещение в пространстве первой структуры данных возможностей.

Каждая возможность состоит из ОДНОБАЙТОВОГО идентификатора типа возможности, за которым следует один байт указателя "следующая возможность", за которым следуют данные различной длины, характерные для этой возможности. Таким образом, начиная со смещения 0x34, вы можете перейти через возможности.

Чтобы увидеть это в действии на любой машине linux, вы можете запустить lspci. Присвоение ему флага -v (который можно повторить, чтобы получить больше и больше деталей) дает вам аннотированное представление пространства конфигурации. Вы также можете добавить -xxxx, чтобы получить полный шестнадцатеричный дамп конфигурационного пространства, и таким образом следовать по цепочке возможностей самостоятельно. (Кстати, ты нужно запустить его с sudo, чтобы получить все детали возможностей.)

В ядре есть интерфейсы, которые сделают это за вас: вы можете использовать pci_find_capability, чтобы найти смещение нужной вам возможности. Вы можете, конечно, также найти возможность самостоятельно, начав с pci_read_config_byte со смещением 0x34 и следуя по списку.

После того, как вы нашли возможность MSI, вы интерпретируете ее содержимое в соответствии с документом, который вы цитировали выше. Вы бы использовали pci_read_config_byte (/word/dword) чтобы получить доступ части структуры данных о возможностях.