У меня есть существующий код, который берет список struct page *
и создает таблицу дескрипторов для совместного использования памяти с устройством. Верхний уровень этого кода в настоящее время ожидает буфер, выделенный с помощью vmalloc
или из пользовательского пространства, и использует vmalloc_to_page
для получения соответствующей страницы структуры *
.
Теперь верхний уровень должен справляться со всеми видами памяти, а не только с памятью, полученной с помощью vmalloc
. Это может быть буфер, полученный с помощью kmalloc
, указатель внутри стека потока ядра или другие случаи, о которых я не знаю. Единственная гарантия, что у меня есть, это то, что вызывающий этот верхний уровень должен гарантировать, что рассматриваемый буфер памяти отображается в пространстве ядра в этой точке (т. Е. доступ к буферу [i]
допустим для всех 0 на данный момент). Как мне получить страницу структуры
*
, соответствующую произвольному указателю?
Поместив ее в псевдокод, у меня есть следующее:
lower_layer(struct page*);
upper_layer(void *buffer, size_t size) {
for (addr = buffer & PAGE_MASK; addr <= buffer + size; addr += PAGE_SIZE) {
struct page *pg = vmalloc_to_page(addr);
lower_layer(pg);
}
}
, и теперь мне нужно изменить upper_layer
для работы с любым допустимым буфером (без изменения lower_layer
).
Я обнаружил virt_to_page
, который Драйверы устройств Linux указывает, что работает на « логический адрес, [не] память из vmalloc
или верхняя память ». Кроме того, is_vmalloc_addr
проверяет, исходит ли адрес из vmalloc
, а virt_addr_valid
проверяет, является ли адрес действительным виртуальным адресом (источник для virt_to_page
; это включает kmalloc (GFP_KERNEL)
и стеки ядра). А как насчет других случаев: глобальные буферы, верхняя память (когда-нибудь она появится, хотя я могу ее пока игнорировать), возможно, другие типы, о которых я не знаю? Поэтому я мог бы переформулировать свой вопрос следующим образом:
Если это имеет значение, код работает на ARM (с MMU), а версия ядра не ниже 2.6.26.