LINUX.ORG.RU

Смена физического адреса буфера в пространстве пользователя

 ,


0

4

Доброго времени суток.

Столкнулся со следующей проблемой:

Есть Soc от Xilinx с ARM ядрами. Ось Petalinux. Ядро 4.14. В пространстве ядра есть самописный драйвер DMA, задача которого считать из SHARE MEMORY в буфер приложения в пространстве пользователя. Сейчас это делается следующем образом:

  1. выделяется статический буфер в приложение в пространстве пользователя.

  2. Через ioctrl передаётся виртуальный адрес буфера в драйвер в пространстве ядра и драйвер берёт буфер через get_user_pages по виртуальному адресу. Это работает НО, периодически я вижу, что система поменяла в пространстве пользователя связку виртуального и физического адреса и как следствие в драйвере в пространстве ядра уже не валидные страницы из пространства пользователя.

Вопрос: как это обойти?


Ответ на: комментарий от Heven

Посмотри на https://github.com/ikwzm/udmabuf может там есть полезный код.

В kernel API наверняка есть возможность зафиксировать в памяти физические страницы соответствующие некоторому виртуальному адресу. В драйвере при получения ioctl нужно лочить страницы страницы, а потом не забывать освобождать.

Драйвер нужно переписывать. Нельзя так свободно обращаться с физической памятью.

vel ★★★★★ ()
Ответ на: комментарий от Heven

Дык делать нужно немного по другому.

Драйвер такого устройста должен позволять делать mmap.

Память в которую пишут через dma нужно выделять в ядре, а в пространстве пользователя делается mmap(). т.е. нет копирования данных из ядра в юзерспейс.

Собственно это и делает https://github.com/ikwzm/udmabuf

Но это костль. Все это должен делать сам драйвер устройства.

vel ★★★★★ ()
Ответ на: комментарий от Heven

Кто такой r5?

Странно, что через mmap меняется скорость. Я не знаком с устройством MMU на arm.

Если погуглить «Linux DMA from User Space Xilinx Forums» то там есть .pdf на котором все достаточно подробно расписано. Правда про скорость не сказано.

Во! наконец нашел про dma в userspace без mmap https://stackoverflow.com/questions/3333959/mapping-dma-buffers-to-userspace

vel ★★★★★ ()
Ответ на: комментарий от vel

Cortex-R5 - real-time embedded processors. Эти ядра общаются с FPGA и кладут инфу в shared memory. На A53 ядрах вертится собственно Linux который через DMA в Kernel Space вычитывает из shared memory данные для дальнейшей обработки в User Space.

Касательно https://stackoverflow.com/questions/3333959/mapping-dma-buffers-to-userspace. Собственно так мы и делаем, это работает и на нужной скорости. Но периодически когда делаем get_user_pages по виртуальному адресу, который передал через ioctrl User Space, то в структуре страниц физический адрес перестаёт соответствовать связке виртуальный - физический адрес буфера в User Space. И кто его меняет пока не понятно. Пробовали отключить ASLR, не помогло.

Heven ()
Ответ на: комментарий от Heven

Но периодически когда делаем get_user_pages по виртуальному адресу, который передал через ioctrl User Space, то в структуре страниц физический адрес перестаёт соответствовать связке виртуальный - физический адрес буфера в User Space. И кто его меняет пока не понятно.

Мда. Удачи тебе с отладкой этого монстра.

Учитывая, что A53 многоядерный, то ко всему прибавляются проблемы SMP и «интеллект» компиляторов.

vel ★★★★★ ()
Ответ на: комментарий от Heven

Cortex-R5 - real-time embedded processors. Эти ядра общаются с FPGA и кладут инфу в shared memory. На A53 ядрах вертится собственно Linux который через DMA в Kernel Space вычитывает из shared memory данные для дальнейшей обработки в User Space.

зачем какой-то отдельный процессор с DMA - смапить общую память в юзерспейс a53 и использовать блокировки доступа как это делает v4l2, никакой задержки нет вообще.

anonymous ()
Ответ на: комментарий от Heven

Не совсем плонял

мне тоже не совсем понятно что в данном случае «SHARE MEMORY» ?

В пространстве ядра есть самописный драйвер DMA, задача которого считать из SHARE MEMORY в буфер приложения в пространстве пользователя

это локальный буфер FIFO или это буфер с рандомным доступом во внешней памяти DRAM или в локальной SRAM ? Если буфер в RAM то можно смапить его в дресное пространство процесса CPU и не делать бесполезное копирование.

anonymous ()
Ответ на: комментарий от Heven

SHARE MEMORY - кусок RAM зарезервированный в дереве конфигурации для межпроцессорного общения между R5 и A53.

так и не понятно - для чего вы копируете из этого буфера данные в буфер в юзерспейс ? mmap позволяет через /dev/mem отобразить любую физически адресуемую память в пространство пользователя без всяких копирований. Например смапить 16 кбайт физически непрерывного буфера

#define MAP_SIZE 0x4000UL /* 16K */
#define MAP_MASK (MAP_SIZE - 1)

void *mmap_16K(unsigned long paddr)
{
	int fd;
	void *map_base;

	if ((fd = open("/dev/mem", O_RDWR | O_SYNC)) == -1) {
		perror("open");
		return (void *) -1;
	}

	map_base = mmap(0, MAP_SIZE, PROT_READ | PROT_WRITE, MAP_SHARED,
			fd, (off_t)(paddr & ~MAP_MASK));
	if (map_base == (void *) -1) {
		perror("mmap");
	}

	close(fd);
	return map_base;
}
anonymous ()