ARM'ы тоже разные бывают: в одноплатниках требуется сбрасывать кеш явно, а в серверных, как пишут, память обычно когерентна с устройствами.
Драйвера в Linux часто требуют небольшой участок когерентной памяти (для кольцевого буфера из примеров в статье), а для основного I/O используют Linux DMA API, аккуратно обмазывая им все обращения, и эти dma_map*() и dma_sync*() уже разворачиваются в обращения к IOMMU (при необходимости) и в операции с кешом (при необходимости): для x86 это будут no-op, а для ARM и RISC-V будет код из linux/arch/*/include/asm/cacheflush.h
Так, кажется, недостаёт расписать выводы в конце, ради чего вообще статья писалась :) Дополним! А пока --- в виде комментария.
Для тех, кто дизайнит свою СнК с поддержкой PCIe:
Рабочий линуксовый драйвер это ещё не гарантия успеха без дополнительных приседаний.
Если часть основной памяти завести в первые 4ГиБ физических адресов (как это можно увидеть в /proc/iomem любой 64-битной x86-машины), то это избавит от проблем с 32-битными реликтами, как программными, так и аппаратными (мы вот не сразу к этому пришли!).
Без участка когерентной памяти будет очень больно с текущей реализаций драйверов в ядре Linux (и это не будет исправляться). Имейте возможность хотя бы отключить кеши для выбранного региона, и отдайте его под DMA.
Очень поможет завести два региона под BAR'ы: один в первых 4ГиБ (для MMIO), другой (большой) --- уже дальше (опять же, мы сначала ударились об это, затем исправили).
Следите чтобы карте хватило битности чтобы адресовать всю доступную память машины, иначе придётся применять замедляющие техники (SWIOTLB).
У некоторых карт есть т.н. Expansion ROM --- двоичный машинный x86-код --- который необходимо исполнить для инициализации устройства. Но в случае RX 550 на RISC-V это не потребовалось.
В целом да, но количество предварительной подготовки (необходимости патчить linux) зависит от конкретной СнК.
В случае Hifive Unmatched, где подсистема памяти хоть и медленная, зато когерентная, т.е. не требуется вызывать cache_flush() перед и после DMA-операций периферии и выделять пулы под DMA, карточка Radeon просто заработала с ванильным ядром, и OpenGL-демки в Qt запустились в Wayland.
А итоговая оценка в терминах Perfect, Pass, Fail уже выводится.
Вижу, что есть официальная сборка pciutils под винду от мейнтейнера пакета. Под рукой нашлась win10, бегло посмотрел: на этом конкретном ПК простого запуска из-под администратора недостаточно, пришлось перебирать методы доступа к регистрам конфигурационного пространства (ключом -A), единственным потенциально рабочим выглядит windbg, но для этого нужно до-установить что-то. Позже, во второй заход, погляжу ещё раз. Ну и нужно будет добавить поддержку этого ключа в pcilmr, по аналогии с lspci и setpci, тогда будет работать в точности как в Linux и BSD.
С самого начала решили что инструмент будем публиковать как Open Source, потому LMT оставался как дополнительный источник информации. Но смотреть начинали, столкнулись с ярким колоритом, ЕВПОЧЯ :)
В то же время pciutils написан на C, имеет минимум зависимостей, легко доступен в пакетных менеджерах многих дистрибутивов Linux, BSD и даже OpenEmbedded.
Про 8GT/s, он же Gen3: если нет под рукой особенных утилит и отладчиков от производителя (Intel в некоторых случаях позволяет построить глаз для Gen3), но поддерживается AER, то, например, можно пустить нагрузку и следить за счётчиками, не набегают ли слишком быстро.
Наличие ошибок покажут "плюсы" в UESta и CESta (uncorrectable errors, correctable errors) в функциональности AER в lspci, а счётичики ведёт драйвер в /sys/bus/pci/devices/XXXX:XX:XX.X/aer_*
Это могут быть чипсет и внутренняя периферия вроде встроенной графики, которые хоть и видятся системой как отдельные PCIe-устройства, но находятся на одном чипе с процессором. Потому функциональность LM только для соблюдения стандарта.
Из "ноутбучного" железа NVMe обычно соглашается по-настоящему промаржиниться.
ARM'ы тоже разные бывают: в одноплатниках требуется сбрасывать кеш явно, а в серверных, как пишут, память обычно когерентна с устройствами.
Драйвера в Linux часто требуют небольшой участок когерентной памяти (для кольцевого буфера из примеров в статье), а для основного I/O используют Linux DMA API, аккуратно обмазывая им все обращения, и эти
dma_map*()
иdma_sync*()
уже разворачиваются в обращения к IOMMU (при необходимости) и в операции с кешом (при необходимости): для x86 это будут no-op, а для ARM и RISC-V будет код изlinux/arch/*/include/asm/cacheflush.h
Так, кажется, недостаёт расписать выводы в конце, ради чего вообще статья писалась :) Дополним! А пока --- в виде комментария.
Для тех, кто дизайнит свою СнК с поддержкой PCIe:
Рабочий линуксовый драйвер это ещё не гарантия успеха без дополнительных приседаний.
Если часть основной памяти завести в первые 4ГиБ физических адресов (как это можно увидеть в
/proc/iomem
любой 64-битной x86-машины), то это избавит от проблем с 32-битными реликтами, как программными, так и аппаратными (мы вот не сразу к этому пришли!).Без участка когерентной памяти будет очень больно с текущей реализаций драйверов в ядре Linux (и это не будет исправляться). Имейте возможность хотя бы отключить кеши для выбранного региона, и отдайте его под DMA.
Очень поможет завести два региона под BAR'ы: один в первых 4ГиБ (для MMIO), другой (большой) --- уже дальше (опять же, мы сначала ударились об это, затем исправили).
Следите чтобы карте хватило битности чтобы адресовать всю доступную память машины, иначе придётся применять замедляющие техники (SWIOTLB).
Обрабатывайте драйвером статусные биты ошибок :)
У некоторых карт есть т.н. Expansion ROM --- двоичный машинный x86-код --- который необходимо исполнить для инициализации устройства. Но в случае RX 550 на RISC-V это не потребовалось.
Дорога приключений действительно была извилистая :)
А ведь от SMBus/I2C далеко не уйти, так можно (обычно) вычитать out of band из PCIe-карты информацию FRU, иногда даже пообщаться по MCTP.
В целом да, но количество предварительной подготовки (необходимости патчить linux) зависит от конкретной СнК.
В случае Hifive Unmatched, где подсистема памяти хоть и медленная, зато когерентная, т.е. не требуется вызывать
cache_flush()
перед и после DMA-операций периферии и выделять пулы под DMA, карточка Radeon просто заработала с ванильным ядром, и OpenGL-демки в Qt запустились в Wayland.Но вот если на руках что-то более замысловатое, то могут понадобиться "приседания", про них даже был доклад полгода назад: https://www.youtube.com/watch?v=fbjjwkb_dfY
А итоговая оценка в терминах Perfect, Pass, Fail уже выводится.
Вижу, что есть официальная сборка pciutils под винду от мейнтейнера пакета. Под рукой нашлась win10, бегло посмотрел: на этом конкретном ПК простого запуска из-под администратора недостаточно, пришлось перебирать методы доступа к регистрам конфигурационного пространства (ключом
-A
), единственным потенциально рабочим выглядит windbg, но для этого нужно до-установить что-то. Позже, во второй заход, погляжу ещё раз. Ну и нужно будет добавить поддержку этого ключа в pcilmr, по аналогии с lspci и setpci, тогда будет работать в точности как в Linux и BSD.С самого начала решили что инструмент будем публиковать как Open Source, потому LMT оставался как дополнительный источник информации. Но смотреть начинали, столкнулись с ярким колоритом, ЕВПОЧЯ :)
В то же время pciutils написан на C, имеет минимум зависимостей, легко доступен в пакетных менеджерах многих дистрибутивов Linux, BSD и даже OpenEmbedded.
Про 8GT/s, он же Gen3: если нет под рукой особенных утилит и отладчиков от производителя (Intel в некоторых случаях позволяет построить глаз для Gen3), но поддерживается AER, то, например, можно пустить нагрузку и следить за счётчиками, не набегают ли слишком быстро.
Наличие ошибок покажут "плюсы" в UESta и CESta (uncorrectable errors, correctable errors) в функциональности AER в lspci, а счётичики ведёт драйвер в /sys/bus/pci/devices/XXXX:XX:XX.X/aer_*
Это могут быть чипсет и внутренняя периферия вроде встроенной графики, которые хоть и видятся системой как отдельные PCIe-устройства, но находятся на одном чипе с процессором. Потому функциональность LM только для соблюдения стандарта.
Из "ноутбучного" железа NVMe обычно соглашается по-настоящему промаржиниться.
В выводе lspci на экране можно в LnkSta разглядеть 2.5GT/s x4, это Gen1.