Почему ваш вызов remap_pfn_range вызывает ошибку ядра ()
Вызов макроса BUG_ON
в remap_pfn_range
согласно здесь
2277 BUG_ON(addr >= end);
remap_pfn_range
звонит remap_pud_range
который звонит remap_pmd_range
который звонит remap_pte_range
.
Последующие звонки на BUG_ON
или VM_BUG_ON
с remap_pmd_range
здесь
2191 VM_BUG_ON(pmd_trans_huge(*pmd));
и от remap_pte_range
здесь
2171 BUG_ON(!pte_none(*pte));
BUG_ON
макрос определен здесь
в
#define BUG_ON(condition) do { if (unlikely(condition)) BUG(); } while(0)
где макрос BUG
определен выше это для печати сообщения и паники.
unlikely
макрос определен здесь
как # define unlikely(x) (__builtin_expect(!!(x), 0))
.
Таким образом, когда целевой адрес пользователя, начинающийся с addr
, больше или равен end
, который определяется как end = addr + PAGE_ALIGN(size);
, BUG_ON возвращает 1 и вызывает BUG.
или когда pmd_trans_huge
как определено здесь
153 #ifdef CONFIG_TRANSPARENT_HUGEPAGE
154 static inline int pmd_trans_splitting(pmd_t pmd)
155 {
156 return pmd_val(pmd) & _PAGE_SPLITTING;
157 }
158
159 static inline int pmd_trans_huge(pmd_t pmd)
160 {
161 return pmd_val(pmd) & _PAGE_PSE;
162 }
163
164 static inline int has_transparent_hugepage(void)
165 {
166 return cpu_has_pse;
167 }
возвращает 0, это происходит, когда CONFIG_TRANSPARENT_HUGEPAGE не настроен в ядре или если
значение pmd
(метадат страницы) или & _PAGE_PSE
Или когда pte_none
возвращает 1, если соответствующая запись не существует, и 0, если она существует.
Поэтому !pte_none
возвращает 0, когда соответствующая запись в таблице страниц не существует, и 1 в другом случае, когда условие перешло в BUG_ON
.
Если запись таблицы страниц уже существует, то происходит вызов макроса BUG
.
Что произойдет, если указать меньший объем памяти, чем! ГБ, который превышает 300 МБ, скажем, 500 МБ или 800 МБ?
Таким образом, либо ваш начальный адрес больше, чем ваш конечный адрес, либо вы CONFIG_TRANSPARENT_HUGEPAGE
не настроены в ядре, либо вы ссылаетесь на то, что метаданные страницы не существуют или записи таблицы страниц уже существуют.
Уточняя из комментариев, вы обращаетесь к remap_pfn_range
ссылкам на указатели записи таблицы страниц или *pte
, которые уже указывают на запись таблицы страниц или pte
.
Это означает, что set_pte_at(mm, addr, pte, pte_mkspecial(pfn_pte(pfn, prot)));
потерпит неудачу, так как указатель pte уже указывает на запись таблицы страниц и, следовательно, не может быть установлен в pte
, то есть pte_mkspecial(pfn_pte(pfn, prot))
.
Обход виртуального адреса 1G / 3G
См. Следующую статью Большой объем памяти в ядре Linux
См. Следующий список рассылки post , в котором обсуждаются некоторые дополнительные сведения о HIGHMEM с минимальным объемом ОЗУ 1 ГБ.
Информация о сопоставлении виртуального адресного пространства ядра и ядра с пользовательской землей
Один способ отобразить виртуальные адреса ядра и не-ядра (возвращаемые vmalloc ()) в пространство пользователя - использовать remap_pfn_range
. См. Linux Memory Mapping для получения дополнительной информации.
Другим способом, который заменил использование обработчика nopage на старых ядрах, является vm_insert_page
функция
Дополнительные ресурсы включают в себя: