У меня есть существующий код, который принимает список struct page *
и создает таблицу дескрипторов для совместного использования памяти с устройством. Верхний уровень этого кода в настоящее время ожидает буфер, выделенный с vmalloc
или из пространства пользователя, и использует vmalloc_to_page
для получения соответствующего struct page *
.
Теперь верхний слой должен справляться со всеми видами памяти, а не только с памятью, полученной через vmalloc
. Это может быть буфер, полученный с помощью kmalloc
, указатель внутри стека потока ядра или другие случаи, о которых я не знаю. Единственная гарантия, которую я имею, состоит в том, что вызывающая сторона этого верхнего уровня должна гарантировать, что рассматриваемый буфер памяти сопоставлен с пространством ядра в этой точке (то есть это действительно для доступа к buffer[i]
для всех 0<=i<size
в этой точке). Как получить struct page*
, соответствующий произвольному указателю?
Помещая его в псевдокод, я получаю следующее:
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
проверяет, является ли адрес действительным виртуальным адресом (fodder для virt_to_page
; сюда входит kmalloc(GFP_KERNEL)
и стеки ядра). А как насчет других случаев: глобальные буферы, большой объем памяти (это придет однажды, хотя я могу пока игнорировать это), возможно, другие виды, о которых я не знаю? Так что я мог бы переформулировать свой вопрос как:
- Каковы все зоны памяти в ядре?
- Как мне их отличить?
- Как получить информацию о сопоставлении страниц для каждого из них?
Если это имеет значение, код выполняется на ARM (с MMU), а версия ядра по крайней мере 2.6.26.