Как стать автором
Обновить

Комментарии 17

Если операционная система изменила PID процесса — потому что и ASID станет другим

Смена PID процесса — это что-то из области фантастики. Линуксные порты на архитектуры с ASID обычно назначают ASID динамически, например так: существует глобальный счётчик, разрядностью больше, чем аппаратный ASID. Когда нужен новый ASID счётчик увеличивается на 1, переполнение разрядов аппаратного ASID вызывает сброс TLB. Каждое адресное пространство (может быть одно у нескольких задач, например если это потоки одного приложения или ядра) описывается структурой, содержащей текущий назначенный ему ASID. Всякий раз, когда нужно активировать адресное пространство, старшие биты его ASID сравниваются с глобальным счётчиком. Если совпадают — ничего делать не надо, если нет — значит было переполнение, TLB был сброшен и адресному пространству нужен новый ASID.
Если нужной записи в TLB нет, то приходится искать ее в таблицах страниц, которые операционная система размещает в нетранслируемой области ОЗУ

В некоторых архитектурах (например xtensa) при наличии MMU трансляция выполняется всегда, но TLB состоит из двух частей: часть строк обновляется и программно и аппаратно, другая только программно. ОС должна поместить в правильное место TLB запись для каталога таблиц страниц.
Третий способ — избегать синонимов программно. Например, не использовать общие страницы. Или снова начать линковать программы в общее адресное пространство.

Или выделять регионы виртуальной памяти для общих страниц по адресам, кратным размеру канала кэша (так, что одинаковые смещения в регионе попадут в одинаковые строки кэша, даже для разных процессов). А при необходимости отобразить физическую страницу в пространство ядра, отображать её с учётом её кэш-цвета, т.е. по виртуальному адресу, младшие биты которого, в пределах размера канала кэша совпадают с физическим адресом страницы.
Хорошо пишите, интересно!
НЛО прилетело и опубликовало эту надпись здесь
Спасибо, интересно. А какие архитектуры кроме ARM используют VIVT кэш?
Раз уж эта тема всплыла, то какие именно архитектуры ARM используют VIVT кэш?
ARMv4 и ARMv5 используют VIVT для кэшей команд и данных. ARMv8 (64-битные АРМы) допускает использование VIVT-кэша команд.
Кэши в ARC 700 можно сконфигурировать как VIVT. Но вообще VIVT-кэши сейчас не очень-то популярны. А про более популярные варианты (PIPT и VIPT) будет в следующей части
достаточно знать, что ее загружает операционная система. Она же добавляет запись в таблицу страниц (но не в TLB),
Уже в который раз натыкаюсь на такое объяснение, но не пойму, что это еще за одна таблица и что именно в ней хранится.
Грубо говоря, таблица страниц — это структура данных, в которой содержатся сведения о том, по каким физическим адресам в памяти расположены виртуальные страницы (и расположены ли они вообще — они могут быть не в оперативке, а на диске), права доступа к ним и т.д.

Только операционная система может добавлять или удалять записи из этой таблицы. Каждая запись соответствует одной странице, поэтому записей очень много и таблица занимает много места. Кроме как в оперативную память поместить ее некуда, т.к. ее размер может быть несколько мегабайт. TLB — это как кэш-память для этой огромной таблицы, TLB хранит несколько наиболее часто используемых записей.
Спасибо за краткое объяснение. Вроде картина в голове сложилась.
У меня есть вопрос по поводу того, «что именно делает MMU».
Вы пишете:
Если нужной записи в TLB нет, то приходится искать ее в таблицах страниц, которые операционная система размещает в нетранслируемой области ОЗУ (чтобы не было промаха TLB при обработке предыдущего промаха). Поиск может быть реализован как аппаратно, так и программно — через обработчик исключения, называемого страничной ошибкой (page fault). Найденная запись добавляется в TLB, после чего команда, вызвавшая промах TLB, выполняется снова.

Я спрашиваю, потому что этот момент — момент того, что именно делает MMU для меня до сих пор остается загадкой. В приведенной цитате либо Вы ошибаетесь, либо я чего-то недопонимаю. Объясняю: page_fault это прерывание, которое возникает, если MMU лезет в таблицы (которые в ОЗУ) и не находит нужный PTE и физический адрес, вместо этого адреса там будет стоять флаг, что страница засвапирована, и её положение на диске. После этого возникает page fault и программный обработчик вытаскивает страницу с диска в память, физический адрес заносится в ту PTE и попытка трансляции повторяется. Так, что как я понимаю к TLB это вообще отношение имеет довольно косвенное…
Что я до конца не понимаю: когда виртуальный адрес приходит к MMU, MMU нужно его преобразовать в физический. Это делается, как Вы уже говорили, через те самые таблицы (PGD->PMD->PTE в Linux). При смене контекста в регистр CR3 (x86) кладется адрес таблиц для конкретного процесса (у каждого процесса свои таблицы преобразования виртуальных адресов в физические), отсюда MMU знает адрес таблиц в ОЗУ. Дальше MMU должна по идее сделать несколько обращений к памяти, чтобы пройти по иерархии PGD->PMD->PTE и вытащить физический адрес. Как выполняются эти обращения? В MMU есть какая-то аппаратная часть которая на вход контроллера памяти выдает запрос на чтение, или это как — то делается через процессор? Помогите мне понять. Спасибо.
Да, закралась неточность. Вместо «Поиск может быть реализован как аппаратно, так и программно — через обработчик исключения, называемого страничной ошибкой (page fault)» следует читать «Поиск может быть реализован как аппаратно, так и программно — через обработчик исключения, называемого промахом TLB (TLB miss)».

Соответственно, в случае программно реализованного поиска проход по иерархии таблиц (PGD->PMD->PTE в вашем случае) осуществляет обработчик промаха TLB (и уже из него можно прыгнуть в обработчик page fault-а). В случае аппаратно реализованного поиска в MMU добавляется специальная логика, которая делает то же самое, но быстрее. Но такое железо гораздо сложнее и вдобавок жестко завязано на конкретную структуру таблиц, то есть могут возникнуть проблемы с поддержкой операционок с нестандартной иерархией таблиц.

Спасибо! Читая книгу Таненбаума, у меня возник резонный вопрос: "А как быть, если в ОС крутятся несколько процессов и все они захотят обратиться к определенному месту в памяти?" Судя по изложенному там материалу, при обращении к одному адресу они должны были бы обратиться к одному адресу в физической памяти. "Но это полный бред" - подумал я и пошел гуглить. Благо наткнулся на вашу статью, где вы разъяснили по ASID. Жаль в книге об этом ни слова.

Зарегистрируйтесь на Хабре, чтобы оставить комментарий

Публикации