У меня есть существующий код, который принимает список 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
проверяет, является ли адрес действительным виртуальным адресом (корм для virt_to_page
, включая kmalloc(GFP_KERNEL)
и стеки ядра). Что касается других случаев: глобальных буферов, высокой памяти (в один прекрасный день, хотя я могу игнорировать это сейчас), возможно, других видов, о которых я не знаю? Поэтому я мог бы переформулировать свой вопрос следующим образом:
- Каковы все типы зон памяти в ядре?
- Как мне рассказать друг другу?
- Как получить информацию о сопоставлении страниц для каждого из них?
Если это имеет значение, код работает в ARM (с MMU), а версия ядра - не менее 2.6.26.