Получить физический адрес буфера под Linux

Я использую ядро ​​Linux 3.3 на Microblaze от Xilinx с полным MMU. задача, которую я выполняю, требует, чтобы я знал следующее: мне нужно создать текстовый файл (буфер) и найти физический адрес этого буфера, и я не хочу, чтобы ядро ​​записывало этот файл в отдельные области памяти.

причина в том, что мне это нужно, потому что у меня есть механизм DMA, который выполняет потоковую передачу данных с заданного адреса физической памяти, поэтому мне нужно заставить Linux создать файл буфера именно в этом месте памяти, чтобы при записи данных в этот файл он немедленно передавался механизмом DMA на другое аппаратное ядро

Больше деталей:

моя система имеет 512 МБ ОЗУ DDR3, подключенного к системе через многопортовый контроллер памяти (MPMC) Xilinx. Базовый адрес этого контроллера памяти - 0x90000000, все устройства в памяти системы обращаются через этот контроллер, включая MicroBlaze, DMA Устройство, которое у меня есть, использует специальный интерфейс под названием Native Personality Interface (NPI) для связи с памятью на очень низком уровне, что приводит к очень высокой скорости работы.

Этот модуль NPI DMA изначально был разработан для использования в самом базовом встроенном ядре под названием "xilkernel", которое не поддерживало виртуальную память, ни MMU не был частью MicroBlaze, поэтому программист мог видеть, где будет находиться код ОС, и выбирать физическую память. адрес, такой как 0x91800000, в качестве адреса источника, с которого будет транслироваться DMA, тогда программист может поместить файл по этому точному адресу и запустить систему

Когда нам нужно было перенести проект для использования Linux вместо xilkernel, мы столкнулись с этой проблемой, у меня есть файлы на внешнем устройстве хранения, к которым я могу получить доступ как блочное устройство из Linux, и мне нужно переместить каждый файл в основную память (ОЗУ DDR3) и сделать поток DMA файлом. в настоящее время потоки DMA с фиксированного адреса, но я могу сделать его общим, если это необходимо.

2 ответа

Мне нужно заставить Linux создать файл буфера в этом месте памяти

Это невозможно. (На самом деле вы создали вопрос XY.)

Поскольку у вас есть оборудование, которое "передает данные с предварительно заданного адреса физической памяти", вы должны убедиться, что ядро ​​Linux не использует эту область памяти как часть своего пула памяти. Вы должны сообщить ядру, когда оно загружается, чтобы не использовать эту область памяти. Вы не сможете "освободить" или распределить буферы в этой конкретной области физической памяти, как только она станет частью пространства памяти, контролируемого ядром.

Наиболее общий метод исключения области памяти - это использование memmap= параметр в командной строке ядра.

memmap=nn[KMG]$ss[KMG]
        [KNL,ACPI] Mark specific memory as reserved.
        Region of memory to be used, from ss to ss+nn.
        Example: Exclude memory from 0x18690000-0x1869ffff
                 memmap=64K$0x18690000
                 or
                 memmap=0x10000$0x18690000

Некоторые архитектуры, такие как ARM с ATAG, имеют другие менее заметные и более безопасные методы резервирования областей физической памяти.

Каким-то образом вы должны предоставить адрес и размер этой области памяти драйверу устройства. Это может быть получено путем синтаксического анализа командной строки, или (большие пальцы вниз), жестко закодированы с помощью #defines.

Драйвер должен объявить свое использование области памяти путем вызова request_mem_region(),
Драйвер может отобразить эту область памяти в виртуальное адресное пространство, вызвав ioreamp(),

Поскольку драйвер предоставлен или уже знает физический адрес, это сделано. Поскольку физическая память была выделена, память является смежной. Вам нужно будет сконфигурировать MMU для отключения кеширования в этой области памяти. Тогда область памяти будет "DMAable".

Для обработки буферов для взаимодействия с контроллером DMA существуют специальные функции. Эти функции заботятся не только о преобразовании адресов, но и о когерентности кеша с памятью, такой как очистка кеша (запись данных в память перед отправкой) и аннулирование кеша (аннулирование кеша перед получением).

(1) Чтобы выделить буфер, получите виртуальный адрес и физический адрес:

void *dma_alloc_coherent(struct device *dev, size_t size,
                         dma_addr_t *dma_handle, gfp_t flag)

возвращаемое значение функции - это виртуальный адрес выделенного буфера, а указатель dma_handle сохраняет физический адрес выделенного буфера.

(2) Чтобы передать один буфер, выделенный устройству:

dma_addr_t dma_map_single(struct device *dev, void *ptr,
                          size_t size,
                          enum dma_data_direction dir)

Возвращаемое значение - это физический адрес буфера, а параметр dir - DMA_TO_DEVICE, ptr - виртуальный адрес буфера;

(3) Чтобы получить один буфер от устройства:

void dma_unmap_single(struct device *dev, dma_addr_t addr,
                            size_t size,
                            enum dma_data_direction dir)

Параметр dir - это DMA_FROM_DEVICE.

Примечание. Чтобы использовать три функции, связанные с dma, необходимо зарегистрировать устройство на одной определенной шине, которая имеет dma_map_ops, иначе эти три функции нельзя использовать.

Другие вопросы по тегам