Управление страницами в 64-разрядных архитектурах Linux

В 32-разрядных микропроцессорах обычно применяется двухуровневая схема управления страницами. Однако двухуровневое управление страницами не подходит для компьютеров с 64-разрядной архитектурой. Чтобы понять, почему это так, проведем мысленный эксперимент.
Пусть для начала страница имеет стандартный размер 4 Кбайт. Поскольку 1 Кбайт покрывает интервал из 210 адресов, 4 Кбайт вмещает в себя 212 адресов, и поле offset имеет длину 12 битов. Остается 52 бита линейного адреса на поля Table и Directory. Если мы решим использовать только 48 из 64 битов для адресации (это ограничение создает нам комфортное адресное пространство в 256 Тбайт!), оставшиеся 48-12 = 36 битов следует поделить между полями Table и Directory. Отведя под каждое поле 18 битов, мы получим, что каталог страниц и Таблицы Страниц каждого процесса будут содержать по 218 записей, т. е. более 256 000.
По этой причине все системы аппаратного управления страницами для 64-разрядных процессоров используют дополнительные уровни управления страницами. Количество используемых уровней зависит от типа процессора. Сводка основных характеристик систем аппаратного управления памятью, используемых на некоторых 64-разрядных платформах, поддерживаемых операционной системой Linux. Операционной системе Linux удалось подобрать общую модель управления страницами, которая годится для большинства поддерживаемых систем аппаратного управления страницами.
Аппаратный кэш
Тактовая частота современных микропроцессоров измеряется в гигагерцах, а время доступа чипов динамической оперативной памяти находится в пределах сотен тактовых циклов. Это означает, что процессор сильно задерживается при выполнении инструкций, требующих выборки операндов из памяти и/или сохранения результатов в памяти.
Аппаратные кэши были созданы для сглаживания несоответствия в скорости работы между процессором и оперативной памятью. Они основаны на хорошо известном принципе локальности, который справедлив как для программ, так и для данных. Он заключается в том, что в силу циклической структуры программ и размещения их данных в линейных массивах, адреса, близкие к тем, что были использованы недавно, имеют высокую вероятность использования в ближайшем будущем. Поэтому имеет смысл использовать компактную и более быструю память для хранения недавно использованного кода и данных. С этой целью в архитектуре 80×86 был создан новый блок, называемый строкой (line). Он состоит из нескольких десятков смежных байтов, которые передаются в монопольном режиме между медленной динамической оперативной памятью и быстрой статической оперативной памятью, применяемой для реализации кэшей.
Кэш помещается между блоком управления страницами и основной памятью. Он состоит из памяти аппаратного кэша и контроллера кэша. Память кэша содержит строки памяти. Контроллер кэша содержит массив записей, по одной на каждую строку памяти кэша. Биты физического адреса памяти обычно разбиваются на три группы: старшие биты соответствуют тегу, средние — индексу подмножества контроллера кэша, а младшие — смещению внутри строки.
При обращении к ячейке оперативной памяти процессор извлекает индекс подмножества из физического адреса и сравнивает теги всех строк в подмножестве со старшими битами физического адреса. Если строка, у которой тег совпадает со старшими битами адреса, найдена, говорят, что процессор попал в кэш; в противном случае процессор промахнулся.
Когда имеет место попадание в кэш, контроллер кэша ведет себя в зависимости от типа доступа. В случае операции чтения контроллер выбирает данные из строки кэша и пересылает их в регистр процессора. Обращения к оперативной памяти не происходит, и время работы процессора экономится. Собственно, поэтому и был изобретен кэш. Для операции записи контроллер может прибегнуть к одной из двух базовых стратегий: сквозная запись и обратная запись. При сквозной записи контроллер записывает данные как в оперативную память, так и в строку кэша, фактически выключая кэш для операций записи. При обратной записи достигается немедленный эффект, поскольку только строка кэша обновляется, а содержимое оперативной памяти не меняется. Естественно, оперативная память тоже, в конце концов, должна быть обновлена. Контроллер кэша записывает строку кэша обратно в оперативную память, только когда процессор выполняет инструкцию, требующую сброса записей кэша, или когда генерируется аппаратный сигнал FLUSH (как правило, после промаха мимо кэша).
Если произошел промах мимо кэша, строка кэша в случае необходимости записывается в память, а в запись кэша заносится корректная строка из оперативной памяти.
В многопроцессорных системах у каждого процессора есть отдельный аппаратный кэш, и, следовательно, требуется дополнительная электронная схема для синхронизации содержимого кэшей. Каждый процессор имеет свой аппаратный кэш. Однако сейчас обновление отнимает больше времени. Как только процессор модифицирует свой аппаратный кэш, он должен проверить, хранятся ли те же данные в остальных аппаратных кэшах. Если хранятся, он должен известить те процессоры о необходимости обновления их кэшей соответствующими значениями. Такая деятельность часто называется отслеживанием кэшей. К счастью, все делается на аппаратном уровне и не имеет никакого отношения к ядру.
В настоящее время технология кэшей бурно развивается. Например, первые модели Pentium включали в себя единственный кэш, который назывался L1-кэшем. Последующие модели имели также более крупные и более медленные кэши. Согласованность между уровнями кэшей достигается аппаратно. Linux игнорирует эти аппаратные подробности и предполагает наличие одного кэша.
Флаг cd процессорного регистра его используется для включения или выключения кэша. Флаг nw в том же регистре определяет, какая стратегия используется для кэшей — сквозная запись или обратная запись.
Еще одна интересная особенность кэша Pentium состоит в том, что он позволяет операционной системе ассоциировать с каждым страничным кадром индивидуальную политику управления кэшем. Для этой цели каждая запись каталога страниц и каждая запись Таблицы Страниц содержит два флага: pcd (Page Cache Disable, отключить кэш страниц), который определяет, должен ли кэш быть включен или выключен при обращении к данным в страничном кадре, и pwt (Page Write — Through, Сквозная запись страницы), который определяет выбор стратегии при записи данных в страничный кадр. Linux сбрасывает флаги pcd и pwt во всех записях каталогов страниц и Таблиц Страниц, и в результате включается кэширование всех страничных кадров и во всех случаях применяется стратегия обратной записи.