LINUX.ORG.RU

Обработка mmap-функции драйвером устройства

 


0

1

Преамбула. Есть устройство, с какими-то физ. адресами на PCI-E. Есть большое желание из юзерлендного приложения работать с устройством напрямую, прямо писать/читать регистры (не говорите, что плохо, это надо, гигабайты в сек.), передавать данные из юзерспейса в кернел и обратно без лишних copy_to_user/copy_from_user, вызовов ioctl и т.п..

Для этого драйвер создает устройство «/dev/mydev», которое реализует функции struct file_operations : .open, .release, .unlocked_ioctl, .compat_ioctl и .mmap. Приложение открывает устройство «/dev/mydev» и все функции работают нормально, в dmesg видна печать, но не .mmap. Туда управление просто не попадает.

Вот, примерный аналог того, что я пытаюсь сделать https://www.sobyte.net/post/2022-03/mmap/

Не приходит в модуль mmap. Я делал драйвер в «/dev/» символьным устройством, miscdevice, осталось только блочным (ну символьное то не имеет конечного размера и lseek и mmap ему по логике не нужны). Я пробовал замапить «/dev/sda» в память - неа.

Раньше я через mmap мапил известные (lsusb) физ. адреса PCI карты через «/dev/mem», могу дать пример. Но тут надо без «/dev/mem», со своим устройством, чтобы оно мапило свою память.

Upd1. Да, и драйвер выделяет непрерывную физ.память/вирт.память.ядра через kmalloc, а лучше как сейчас через alloc_pages. Их будет юзать DMA.



Последнее исправление: bugs-bunny (всего исправлений: 1)

Ты смотрел libpciaccess?

https://gitlab.freedesktop.org/xorg/lib/libpciaccess

Там есть примерно то что тебе нужно:

int pci_device_map_range(struct pci_device *dev, pciaddr_t base,
    pciaddr_t size, unsigned map_flags, void **addr);

hateyoufeel ★★★★★
()
Последнее исправление: hateyoufeel (всего исправлений: 2)
Ответ на: комментарий от mrjaggers

есть какие-то сетевухи вроде которые байпасят ядерный стек.

Есть, в основном от Intel и еще пяток компаний. А Realtec вроде бы и нет. Технология называется DPDK. Там и приложения специфические с этими сетевухами работают, специально внутри себя весь сетевой стек тащат и DPDK библиотеку под конкретное устройство, этакий монолит под конкретную задачу типа роутера, впн-сервера, ни под что другое не заточенный. Может эти монстры и запускаются вместо /bin/init единственным процессом.

bugs-bunny
() автор топика
Ответ на: комментарий от hateyoufeel

Спасибо. В конечном варианте это наверное будут адреса на PCI устройстве, но пока что модуль выделяет физ память alloc_page-ом.

С VFIO, что тут предложили, идея интересная, более универсальный вариант кажется.

bugs-bunny
() автор топика

Все оказалось просто. Я свое устройство открывал open("/dev/mydev", 0);. И все норм было даж с ioctl на IORW запросы, т.е. с чтением/записью. В тесте устройства все устраивало, если б не этот затык.

Запустил тест с strace - увидел, что на open вызывается openac("/dev/mydev", O_READONLY), а на mmap возвращается -EACCESS в errorcode.

Сделал fdev = open( "/dev/mydev", O_RDWR, S_IRUSR|S_IWUSR ); - все стало ОК. Осталось недоумение, почему mmap такая честь? Это ж не write вызывал, и вообще лез не в файл, а в устройство, mmap-пленную память можно было б пометить в страницах процесса как r, но на чтение давать.

bugs-bunny
() автор топика