Пролог
Я любитель операционной системы, а мое ядро работает на 80486+ и уже поддерживает виртуальную память.
Начиная с 80386, семейство процессоров x86 от Intel и их различных клонов поддерживает виртуальную память с пейджингом. Хорошо известно, что когда бит PG
в CR0
установлен, процессор использует преобразование виртуального адреса. Затем регистр CR3
указывает на каталог страницы верхнего уровня, который является корнем для 2-4 уровней структуры таблицы страниц, которые отображают виртуальные адреса на физические адреса.
Процессор не обращается к этим таблицам для каждого генерируемого виртуального адреса, а вместо этого кэширует их в структуре, называемой Translation Lookaside Buffer или TLB. Однако при внесении изменений в таблицы страниц TLB необходимо очистить. На 80386 процессорах этот флеш будет сделан
перезагрузка (MOV
) CR3
с адресом каталога страницы верхнего уровня или переключателем задачи. Это якобы безоговорочно сбрасывает все записи TLB. Насколько я понимаю, для системы виртуальной памяти было бы идеально всегда перезагружать CR3 после любого изменения.
Это расточительно, так как TLB теперь выкидывает полностью хорошие записи, поэтому в процессорах 80486 была введена инструкция INVLPG
. INVLPG
приведет к аннулированию записи TLB, соответствующей адресу операнда источника.
Однако, начиная с Pentium Pro, у нас также есть глобальные страницы, которые не сбрасываются при переходе на CR3
или переключатель задачи; и AMD x86-64 ISA говорит, что некоторые структуры таблицы страниц верхнего уровня могут быть кэшированы и не аннулированы INVLPG
. Чтобы получить согласованную картину того, что необходимо и что не нужно на каждой ISA, действительно нужно было бы загрузить 1000-страничный лист для множества ISA, выпущенных с 80-х годов, чтобы прочитать пару страниц в нем, и даже тогда документы, похоже, быть особенно расплывчатым относительно недействительности TLB и того, что произойдет, если TLB не является должным образом недействительным.
Вопрос
Для простоты можно предположить, что мы говорим об однопроцессорной системе. Кроме того, можно предположить, что после изменения структур страницы требуется без переключения задач. (таким образом, INVLPG
всегда предположительно является по крайней мере хорошим выбором, поскольку перезагрузка регистра CR3
).
Базовое предположение состоит в том, что после каждого изменения таблиц страниц и каталогов страниц необходимо перезагрузить CR3
, и такая система будет правильной. Однако, если вы хотите избежать излишней очистки TLB, вам нужно ответить на 2 вопроса:
-
При условии, что
INVLPG
поддерживается в ISA, после каких изменений можно безопасно использовать его вместо перезагрузкиCR3
? Например. "Если один отменить одностраничный фрейм (установить соответствующую запись таблицы, чтобы он не присутствовал), всегда можно использоватьINVLPG
"? -
Какие изменения можно внести в таблицы и каталоги, не касаясь либо
CR3
, либо выполняяINVLPG
? Например. "Если страница не отображается вообще (нет), можно записать PTE сPresent=1
для нее, не смывая TLB вообще"?
Даже после прочтения довольно большого количества документов ISA и всего, что связано с INVLPG
здесь, в Stack Overflow, я лично не уверен ни в каких примерах, которые я представил там. В самом деле, один заметный пост прямо сказал об этом: "Я не знаю точно, когда вы должны использовать его, а когда не следует". Таким образом, оцениваются любые определенные, правильные примеры, предпочтительно документированные, и для IA32 или x86-64, которые вы можете дать.