Окончательные Таблицы Страниц ядра при объеме памяти свыше 4096 Мбайт в Linux

Рассмотрим инициализацию Таблицы Страниц ядра на компьютерах с объемом памяти больше 4 Гбайт. Точнее говоря, мы будем иметь дело со следующей ситуацией:
- процессор поддерживает механизм расширения физических адресов (РАЕ);
- объем оперативной памяти превышает 4 Гбайт;
- ядро откомпилировано с поддержкой механизма РАЕ.
Хотя механизм РАЕ работает с 36-битовыми физическими адресами, линейные адреса по-прежнему имеют длину 32 бита. Как и в предыдущем случае, Linux отображает окно оперативной памяти размером 896 Мбайт в пространство линейных адресов ядра. Остальная память будет подвергаться динамическому отображению. Основное отличие от предыдущего случая состоит в применении трехуровневого управления страницами, так что глобальный каталог страниц инициализируется в цикле.
Предположим, некая функция ядра вызывает fix to virt (fix ioapic base o). Поскольку функция объявлена с атрибутом online, компилятор С не генерирует вызов функции fix to virt о, а вставляет ее код в вызывающую функцию. Кроме того, проверка значения индекса на этапе выполнения не производится. На самом деле, значение fix ioapic base o является константой и равно 3, так что компилятор может "обрезать" условный оператор, потому что его условие ложно на этапе компиляции. Если это условие истинно, или аргумент функции fix to virt о не является константой, компилятор выдает ошибку на этапе компоновки, потому что символ this fixmap does not exist нигде не определен. В конечном счете, компилятор вычисляет выражение 0xfffff000 - (page_shift) и заменяет вызов функции fix to virt о на постоянный линейный адрес 0xffffc000.
Чтобы связать физический адрес с фиксированно отображенным линейным адресом, ядро вызывает макросы set_fixmap(idx,phys) и set_fixmap_nocache (idx,phys). Оба макроса инициализируют запись Таблицы Страниц, соответствующую линейному адресу, вычисляемому функцией fix to virt (idx) физическим адресом phys. Заметим, что второй макрос, кроме прочего, устанавливает флаг pcd в записи Таблицы Страниц, тем самым отключая использование аппаратного кэша при обращении к данным в страничном кадре. Макрос ciear fixmap(idx) разрывает связь между фиксированно отображенным линейным адресом idx и физическим адресом.