Linux — отображение памяти пользовательского пространства в коде ядра

Я пишу фрагмент кода, который должен хранить 10 КБ памяти, расположенной по определенному физическому адресу, до того, как SOC отключится.

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

Я пытался использовать io-remap, но он (очевидно) не работает в неядерном пространстве.

есть ли API для этого? я должен использовать кмап?

заранее спасибо


person Strudle    schedule 27.11.2012    source источник
comment
Можете ли вы определить, какие области памяти зарезервировать во время загрузки (в функции U-Boot?), исключить эти области из (действительного) списка памяти, а затем написать драйвер, который действительно отображает и использует эту специальную память? stackoverflow.com/questions/11580285/   -  person sawdust    schedule 28.11.2012
comment
я могу исключить память из ATAG во время загрузки, но как мне отобразить эти области? ioremap раньше не работал. может быть, потому что эта область была частью другого пространства памяти?   -  person Strudle    schedule 29.11.2012
comment
io-remap... не... работает с пространством вне ядра — пространство памяти ядра и пользователя относится к виртуальной памяти. ioremap() необходимо предоставить диапазон физических адресов. Имейте в виду, что использование слова «память» без определителя «виртуальный» или «физический» может привести к двусмысленности или путанице. Возможно, вам нужно пересмотреть и проанализировать, почему ioremap() не работает. Вот еще один вопрос и ответ, связанный с выделением физической памяти для использования драйвером ядра: access-with-busy-m/12557974#12557974" title="после добавления области памяти запроса мой драйвер терпит неудачу при каждом первом доступе с занятой m"> stackoverflow.com/questions/12516603/   -  person sawdust    schedule 30.11.2012
comment
@JonathanLeffler. Ваши правки, особенно этот физический адрес находится в пользовательском пространстве, не имеют смысла и, вероятно, искажают проблемы.   -  person sawdust    schedule 30.11.2012
comment
@опилки: хорошо; тогда исправьте, пожалуйста. Неважно, я откачу его и пусть кто-нибудь еще попробует.   -  person Jonathan Leffler    schedule 30.11.2012


Ответы (2)


Похоже на периферийное устройство с отображением памяти. Для жесткой привязки к вашему ядру в initdata будет добавлена ​​запись, которая переходит в iotable_init(). Например, arch/arm/mach-vexpress/ct-ca9x4.c ct_ca9x4_io_desc[]. Это создает виртуальное физическое сопоставление. Тогда код ядра мог бы использовать writel с виртуальным адресом для записи туда.

person Joe Kul    schedule 27.11.2012
comment
на самом деле адресное пространство - это первые 10 КБ каждого выбранного чипа DRAM, и они могут меняться в зависимости от настройки платы. Итак, я должен сделать это во время выполнения. я не могу сказать местоположение адресного пространства во время компиляции. - person Strudle; 28.11.2012
comment
В разделе stackoverflow.com/ есть полезная информация. вопросы/7894160/. Но н.б. Это очень сложная область программирования, и вы вряд ли получите нужный вам ответ в таком ограниченном пространстве... - person Joe Kul; 28.11.2012

Нашел ответ

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

вот пример выделения одной страницы

void *virt_addr_ptr
struct page **my_page = kmalloc(sizeof (*my_page), GFP_KERNEL);
my_page = phys_to_page(phys_addr_ptr);
virt_addr_ptr = vmap(my_page, 1, VM_MAP, PAGE_KERNEL);

/*now its possible to access this space */
memcpy(store_buffer, virt_addr_ptr, store_size);
person Strudle    schedule 06.12.2012
comment
Вы сделали это в пользовательской среде или в модуле ядра? - person Joe C; 21.06.2013
comment
Надеюсь, этот пост не слишком мертв для редактирования. my_page = phys_to_page(phys_addr_ptr); должно быть *my_page = phys_to_page(phys_addr_ptr); из-за возврата phys_to_page() как struct page * - person d4r3llo5; 24.08.2016