LINUX.ORG.RU

vmalloc(9) -> struct page ?


0

0


Linux 2.6.x *в пределах модуля ядра*

где-то внутрях драйвера есть большой и толстый буфер выделенный через vmalloc(9) и есть необходимость достучаться до него через mmap(2). соотв. приходится отрабатывать операцию vm_operations_struct->nopage(). для чего очевидно необходимо преобразовать свой виртуальный адрес ядра "buffer + заданный offset" в конкретную страницу в лице структуры page и вернуть ее из nopage().

вопрос: как это сделать? на руках есть лишь то, что вернул vmalloc(9) и смещение в пределах выделенного буфера.

ps: я понимаю, что ответ "никак" и очевидно придется самому выделять, хранить и мапировать массив страниц, но может быть я все-таки что-то недоглядел в mm/vmalloc.c или еще где? например, если бы получить по заданному адресу его vm_struct то можно было бы найти страницу в pages и самому. только вот не экспортируется он, сволочь, ни vmlist ни vmlist_lock.. :-/

// wbr


впрочем, уже как-то не актуально бо ручное выделение массива страниц с последующим vmap()/vunmap() в ядро вполне устраивают.

// wbr

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

Ян, чего это вы? существует макрос vmalloc_to_page(), который вам отлично подойдет.

по поводу обработки nopage() с целью отмапить буффер - нескромный вопрос - почему бы не воспользоваться remap_pfn_range (предварительно выставив страницам бит PageReserved при помощи SetPageReserved()) ?

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

> Ян, чего это вы? существует макрос vmalloc_to_page(), который вам отлично подойдет.

да поздно уже, и так все заработало на ура.. впрочем, как вариант. разве что в моем варианте работает немного быстрее :)

> по поводу обработки nopage() с целью отмапить буффер - нескромный вопрос - почему бы не воспользоваться remap_pfn_range (предварительно выставив страницам бит PageReserved при помощи SetPageReserved()) ?

hm... AFAIU remap_pfn_range() не работает с памятью из-под vmalloc() в силу его сборно-соляночного происхождения, нет :-?

// wbr

klalafuda ★☆☆
() автор топика
Ответ на: комментарий от anonymous

> remap_pfn_range() отлично работает с vmalloc memory.

интересно как? можно пример кода? бо выделенные страницы памяти из под vmalloc() отнюдь не обязаны располагаться последовательно друг за другом в физической памяти.

ps: идти по выделенному буферу и для каждой странички вызывать свой remap_pfn_range()?

// wbr

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

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

Пример кода сейчас привести не могу - если только вечером или в обед.

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

а размер буфера какой? __get_free_pages() не прокатывает?

vmalloc() не прокатит с remap_pfn_range() - проверено. Но неужели нельзя обойтись без vmalloc()'а и костылей no_page?

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

> а размер буфера какой? __get_free_pages() не прокатывает?

порядка 50% RAM. а вообще, чем больше - тем лучше. характерный буфер 100..150Mb на 256RAM. очевидно, ни kmalloc() ни get_free_pages() тут уже не прокатывают бо найти такой большой массив страниц непрерывных в физической памяти они в принципе не могут и обламывают уже где-то на ~1Mb.

> vmalloc() не прокатит с remap_pfn_range() - проверено.

дык..

> Но неужели нельзя обойтись без vmalloc()'а и костылей no_page?

почему в сущности он кривой и костыль? какая вам разница, когда именно завести конкретное отображение в адресном пространстве процесса - полностью в момент вызова mmap(2) или же по запросу, когда процесс обратится к страничке? тем более, что на заданную страничку nopage() вызывается лишь один раз и последующие обращения процесса к этой области памяти идут уже без участия nopage() [иначе бы это был полный пипец]. оба варианта IMHO идеологически вполне эквивалентны.

// wbr

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

> оба варианта IMHO идеологически вполне эквивалентны.

другое дело, что я бы как минимум из эстетических соображений все-таки сделал бы полное отображение в пределах вызова mmap(2) и не возился бы с nopage(). возня конечно яйца выеденного не стоит, но как-то перегружено получается. но у меня сейчас нет времени и не стоит задача сделать чистое отображение в контексте mmap(2) зато нужен железно рабочий вариант so может быть как-нибудь потом посмотрю что и как.

// wbr

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

согласитесь что remap_pfn_range() сделать проще чем no_page(), другое дело что других вариантов в вашем случае я не вижу (50% RAM - это круто - ядрёное ядро получится :-)). и как с производительностью - из-за сборной солянки vmalloc()? кстати - а не забахать ли массив/список из __get_free_page() - максимум там 4М если не ошибаюсь (будет 64 элемента по 4М)? или это не прокатит?

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

> кстати - а не забахать ли массив/список из __get_free_page() - максимум там 4М если не ошибаюсь (будет 64 элемента по 4М)? или это не прокатит?

это делать AFAIU принципиально нельзя бо конга уже *после* вас загрузится модуль X и попросит "дайте мне 50 * PAGE_SIZE непрерывной памяти под DMA" ядро его обломает, бо все самые большие объёмы кто-то [мы] уже захапали под непонятно что. после этого начнут "непонятно почему" отваливаться USB драйвера и ещё куча других не очевидных прелестей.

нет уж, идя от задачи "нужен буфер в контексте ядра 100Mb, линейность в физической памяти не важна" лучше набрать массив свободных страниц разбросанных тут и сям а после отобразить их в единое виртуальное адресное пространство ядра [__get_free_page() + vmap()/vunmap()] как это собственно и делает vmalloc().

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

// wbr

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

в принципе (с одной стороны) всё это правильно, но как всё это скажется на производительности?

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

> Пример кода сейчас привести не могу - если только вечером или в обед.

"жаль конечно, что мы так и не услышали начальника транспортного цеха" (c) Аркадий Райкин

// wbr

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

Ну что же - вероятно "ещё не вечер". :-) (по большому счёту "вечер" для человека - это когда в деревянный ящик кладут и на 2 метра закапывают) а так...

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

>"жаль конечно, что мы так и не услышали начальника транспортного цеха" (c) Аркадий Райкин

Хотя я и не упомянутый anonymous, но вполне очевидно, что имелось в виду: for/vmalloc_to_page/get_page/page_to_phys/remap_pfn_range...

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

> Хотя я и не упомянутый anonymous, но вполне очевидно, что имелось в виду: for/vmalloc_to_page/get_page/page_to_phys/remap_pfn_range...

ну то-же в принципе вариант

// wbr

klalafuda ★☆☆
() автор топика
Вы не можете добавлять комментарии в эту тему. Тема перемещена в архив.