Доброго времени суток!
Я разрабатываю устройство на основе FPGA с поддержкой PCI Express (PCIe), которое должно работать под управлением Linux OS, поэтому я также пишу драйвер ядра Linux. Одной из особенностей устройства является его способность записывать данные в оперативную память хост-системы Linux в режиме прямого доступа к памяти (DMA) с использованием самого простого механизма:
Драйвер устройства выделяет непрерывный участок памяти (128 КБ) и получает DMA (bus) адрес для этого участка.
Драйвер записывает DMA-адрес в устройство FPGA PCIe.
Устройство FPGA PCIe просто генерирует транзакции по записи в память с адресом, начиная с этого DMA-адреса (конечно же, драйвер устанавливает бит Bus Master).
Всё работает отлично на простом персональном компьютере с одним процессором под управлением Ubuntu OS. Но когда я пытаюсь запустить тот же код (как rtl, так и драйвер/приложение для Linux) на сервере Supermicro с двумя физическими процессорами Intel, компьютер зависает прямо на транзакции записи в память, генерируемой моим устройством.
Вот некоторый код из драйвера:
// использую 64 битную адресацию
if (!dma_set_mask_and_coherent(&pdev->dev, DMA_BIT_MASK(64)))
printk(KERN_WARNING "%s: using 64bit DMA addressing\n", DRIVER_NAME);
...
// выделение и отображение памяти
struct page *dma_pages;
dma_pages = alloc_pages_node(NUMA_NO_NODE, GFP_ATOMIC | __GFP_NOWARN | __GFP_COMP | __GFP_MEMALLOC, mem_order);
virt_addr = (unsigned long)page_address(dma_pages);
// этот dma адрес передается в устройство
dma_addr = dma_map_single(&fpga_dev->pdev->dev, virt_addr, size, DMA_BIDIRECTIONAL);
Что я уже попробовал на сервере:
Проверил линк PCIe, все в порядке. CPU может читать/писать регистры FPGA и передавать данные в FPGA.
Отключил IOMMU при загрузке ядра Linux (iommu=off intel_iommu amd_iommu=off).
Отключил Intel VT-d в BIOS.
Попробовал экспериментировать с NUMA (включал/выключал, пробовал выделять память на разных узлах - близким к устройству и не очень).
Проверил разные слоты PCIe, разные процессоры. Теперь карта FPGA подключена к слоту, где ранее корректно работала другая PCIe-карта (сетевой адаптер).
Я много гуглил и даже обсудил этот вопрос с ChatGPT - безуспешно. Есть ли идеи, что делать дальше?
В чем может быть разница между персональным компьютером с одним CPU (где всё работает нормально) и сервером Supermicro с двумя физическими процессорами Intel?