DMA на FPGA не может получить доступ к памяти ядра, выделенной с флагом GFP_KERNEL - PullRequest
0 голосов

Сначала я хотел бы дать краткое описание сценария, над которым я работаю.

То, что я пытаюсь выполнить, - это загрузить данные изображения из моего приложения из пользовательского пространства и передать их через PCIe напользовательский механизм ускорения, расположенный внутри платы FPGA.

Технические характеристики моего хост-компьютера:

  • Процессор Intel Xeon с 16 ГБ ОЗУ.
  • 64-разрядная версия Debian Linux сверсия ядра 4.18.

ПЛИС является платой разработки Virtex 7 KC705.FPGA использует контроллер PCIe (мост) для связи между инфраструктурой PCIe и интерфейсом AXI FPGA.Кроме того, FPGA оснащена механизмом DMA, который должен считывать данные через контроллер PCIe из памяти ядра и направлять их в ускоритель.

Поскольку в будущих реализациях я хотел бы сделать несколько выделений ядрадо 256M я настроил свое ядро ​​для поддержки CMA и DMA Contiguous Allocator.Согласно dmesg я могу проверить, что моя система резервирует при запуске область CMA.

Относительно процедуры ускорения:

  1. Драйвер первоначально выделяет память ядра 4M с помощью dma_alloc_coherent () сGFP_KERNEL флаг.Это распределение находится внутри диапазона CMA.
  2. Затем из моего пользовательского приложения я вызываю mmap с флагами READ_PROT / WRITE_PROT и MAP_SHARED / MAP_LOCKED, чтобы отобразить ранее выделенную память CMA и загрузить туда данные изображения.
  3. Как только данные изображения загружены, я пересылаю физический адрес dma_addr_t выделенной памяти CMA и запускаю DMA для передачи данных в ускоритель.Когда ускорение завершено, предполагается, что DMA записывает обработанные данные обратно в ту же выделенную память ядра CMA.
  4. По завершении приложение пользовательского пространства считывает обработанные данные из памяти CMA и сохраняет их в .bmpфайл.Когда я проверяю «обработанное» изображение, оно совпадает с исходным.Я предполагаю, что обработанные данные никогда не записывались в память CMA.

Существует ли какая-либо защита памяти, которая не позволяет выполнять запись в память CMA при использовании флага GFP_KERNEL?

Интересным фактом является то, что когда я выделяю память ядра с помощью dma_alloc_coherent, но с помощью либо GFP_ATOMIC, либо GFP_DMA, обработанные данные правильно записываются в память ядра, но, к сожалению, выделенная память не принадлежит диапазону области CMA.

Что не так в моей реализации?Пожалуйста, дайте мне знать, если вам нужна дополнительная информация!

1 Ответ

0 голосов

Чтобы использовать mmap (), я принял метод операций с файлами debugfs.Сначала я открываю файл debugfs следующим образом:

shared_image_data_file = open("/sys/kernel/debug/shared_image_data_mmap_value", O_RDWR);

shared_image_data_mmap_value - это мой файл debugfs, который создается в моем драйвере ядра, а shared_image_data_file - это простоinteger.

Затем я вызываю mmap () из пространства пользователя следующим образом:

    kernel_address = (unsigned int *)mmap(0, (4 * MBYTE), PROT_READ | PROT_WRITE, MAP_SHARED | MAP_LOCKED, shared_image_data_file, 0);

Когда я вызываю функцию mmap () в пространстве пользователя, операция файла mmap моего файла debugfs выполняетследующая функция в драйвере ядра:

dma_mmap_coherent(&dev->dev, vma, shared_image_data_virtual_address, shared_image_data_physical_address, length);

shared_image_data_virtual_address является указателем типа uint_64_t, в то время как shared_image_data_physical_address имеет тип dma_addr_t, и они были созданы ранее, когда яиспользовал следующий код для выделения памяти в пространстве ядра:

shared_image_data_virtual_address = dma_alloc_coherent(&dev->dev, 4 * MBYTE, &shared_image_data_physical_address, GFP_KERNEL);

Адрес, который я передаю в DMA ПЛИС, - shared_image_data_physical_address .

Я надеюсь, чтовышесказанное полезно.

Спасибо!

...