Виртуальная память в ARMv7

в 14:58, , рубрики: ARMv7, C, MMU, virtual memory, Программирование, системное программирование

Здравствуйте!

В статье обзорно описана система виртуальной памяти архитектуры ARMv7.

Заголовок спойлера
Здесь не рассмотрены тонкости кэширования, DMA, LPAE и подобное. За более подробным описанием можно обратиться к литературе в конце статьи.

Введение

Система виртуальной памяти выполняет несколько задач. Во-первых, она позволяет размещать пользовательские процессы в отдельных, изолированных друг от друга, пространствах памяти. Это позволяет повысить надежность системы, ошибки одного процесса не влияют на работу других процессов. Во-вторых, ОС может предоставить процессу больше памяти, чем имеется в системе. Неиспользуемые страницы памяти вытесняются в постоянное хранилище, а оттуда подгружаются нужные, образуя иллюзию большего объема памяти, чем реально имеется. В-третьих, непрерывное виртуальное пространство позволяет упростить написание пользовательского ПО. Все процессы исполняются в одинаковом пространстве, ОС скрывает от них реальную конфигурацию памяти в системе.

Определения

Далее в статье используются следующие определения:
Виртуальный адрес — адрес, используемый ядром процессора. Указатель стека, счетчик команд, регистр возврата используют виртуальный адрес.
Физический адрес — выходной адрес на шине процессора.
Страница — единица адресации виртуальной памяти.
Секция — аналог страницы, имеет больший размер.
Фрейм — единица адресации физической памяти.
Таблица страниц — массив записей для трансляции адресов.
ASID — идентификатор адресного пространства.
TLB — буфер быстрой трансляции адресов.
MMU — блок управления памятью.

TLB

TLB — это очень быстрый аппаратный буфер, содержащий в себе результаты последних трансляций адресов. Запрос ядра на трансляцию адреса страницы и текущий ASID поступает в TLB. Если там есть валидная запись, то проверяется разрешения на доступ к этой памяти, способ доступа и соответствующий адрес фрейма возвращается в блок MMU. Если доступ к памяти запрещен, то генерируется аппаратное исключение. Если произошел TLB miss(записи не нашлось), то дальнейшее поведение зависит от регистра TTBCR. Может быть выполнен поиск в таблицах страниц или сгенерировано исключение.

Важно отметить, что при манипуляциях с таблицами страниц необходимо корректно сбрасывать TLB, т.к. там может сохраниться неактуальная информация.

Обновление записей в TLB происходит прозрачно для программиста по алгоритму round-robin.
Так же есть возможность загрузить и закрепить некоторые записи в TLB для предотвращения их вытеснения.

image
Рис 1. TLB

Таблицы страниц

ARMv7 — 32-битная архитектура, поэтому нам доступно 4ГБ адресуемой виртуальной памяти.
Таблицы страниц разделены на 2 уровня — L1 и L2.

Таблица L1 описывает все 4Гб адресного пространства. Она состоит из 4096 записей длиной 32бит, каждая из которых описывает 1Мб. Записи в таблице выбираются старшими 12 битами виртуального адреса.

image
Рис. 2 Поиск записи в таблице L1

Таблица L1 расположена в физической памяти и выровнена на границу 16Кб. Есть 4 варианта этих записей: для описания страниц, секций и суперсекций. Ну и пустая запись, для памяти, которая еще не замаплена.

image
Рис. 3 Типы записей в L1

Биты 0 и 1 указывают на тип записи 00b-Fault, 01b — описатель страниц, 10b — описатель секций (и суперсекций).

Если физическая память разбивается на страницы, то в таблице L1 хранится адрес таблицы L2(физический, выровненный на 1Кб). Бит 9 определяется производителем(Implementation defined), биты [8:5] — для механизма доменов(Deprecated в ARMv7),SBZ — нули.

Если мы решим разбить память на секции, то в L1 необходимо записать соответствующий физический адрес. Секция напрямую ссылается на выровненную область физической памяти в 1Мб. Нет необходимости в таблице L2. Суперсекция это частный случай разбиения на секции, запись в L1 таблице должна повториться 16 раз, выравнивание выделенных блоков физической и виртуальной памяти так же 16Мб.

Таблица L2 состоит из 256 записей по 32бит. Она должна быть выровнена на 1Кб.

image
Рис. 4 Поиск записи в таблице L2

Индексы в таблице L2 формируются из средних 8 бит [19:12] виртуального адреса. Каждая запись таблицы содержит адрес фрейма.

image
Рис. 5 Типы записей в L2

Страницы могут быть двух размеров: 64Кб(Large page) и 4Кб(Small page).
Биты AP и APX устанавливают разрешения на чтение/запись в привилегированном/непривилегированном режиме (kernel/user). Биты TEX, C, B, S отвечают за тип памяти, ее кэширование и буферизацию чтения-записи. Бит nG — nonGlobal разрешает доступ к странице для всех процессов или же только для одного конкретного ASID'a.

Использование больших страниц позволяет сократить количество записей в TLB. Вместо 16 записей (4Кб*16=64Кб), там будет храниться всего одна. Однако в таблицу L2 надо внести 16 одинаковых записей.

Возможность адресовать разные размеры блоков позволяет, с одной стороны, выделять память с нужной гранулярностью, с другой стороны, сократить количество обращений к таблицам страниц в относительно медленную память.

Регистры

Для управления системой(в т.ч. блоком MMU) в архитектуре ARM предназначен специальный сопроцессор CP15. К управлению памятью относятся полтора десятка его регистов. Нас интересуют несколько из них — Control, TTBR0/1, TTBCR, ContextID.

В регистре Control младший бит отвечает за вкл/выкл MMU, все просто.

Пара регистров TTBR0/1 содержат физические адреса таблиц первого уровня. По этим адресам блок MMU начинает поиск нужной страницы.

Регистр TTBCR позволяет поделить всё адресное пространство на 2 части между TTBR0 и TTBR1. Каждый из них будет транслировать свою часть адресов. Для задания размера используются биты [2:0]. Записаное число (от 0 до 7 десятичных) маскирует старшую часть виртуальных адресов. Если его значение «0» — все адреса транслируются через TTBR0. Если «1» — маскируется 31бит адреса и нижние 2Гб виртуального пространства проходят через TTBR0, верхние — через TTBR1. «2» — маскируются 31 и 30бит и получается деление на 1Гб и 3Гб соответственно. Таким образом, нижнюю часть адресов можно использовать для пользовательских приложений, перегружая регистр TTBR0 для нового процесса, а верхнюю часть оставить для системных нужд.

image
Рис. 6 Разделение адресного пространства

Биты [5:4] отвечают за поведение при TLB miss — поиск в таблицах страниц или исключение.
Регистр ContextID содержит поле ASID для текущего процесса. Его нужно менять совместно с содержимым регистра TTBR0 при смене контекста.

Address Translation

Алгоритм преобразования виртуальных адресов в физический следующий:

  • Поиск запрошенного виртуального адреса и ASID в буфере TLB
  • Если в TLB нет необходимого адреса, то происходит аппаратный поиск в таблицах страниц

Если ранее ядро уже запрашивало виртуальную страницу, то она сохраняется в TLB. В этом случае блок MMU достает ее из кэша и не требуется ничего делать. Если же страница запрашивается первый раз(или ее вытеснили оттуда — TLB не очень большой), то просходит поиск в таблицах L1-L2. Таким образом сопоставление виртуального и физического адреса происходит следующим образом:

  • В регистре TTBR0TTBR1 ищется адрес таблицы L1.
  • Старшие 10 бит виртуального адреса образуют индекс в таблице.
  • а)Если запись соответствует секции(суперсекции), то проверяются атрибуты секции и, если все Ок, результирующий физический адрес составляется из базового адреса секции(суперсекции) и младших 20(24) бит виртуального адреса.
    Заголовок спойлера

    image
    Рис. 7 Трансляция адресов в суперсекции

    б)Если запись это таблица L2, то поиск продолжается в ней. Средняя часть виртуального адреса страницы образует индекс таблицы.

    Заголовок спойлера

    image
    Рис. 8 Трансляция адресов в таблице L2

  • Происходит обновление TLB

Итого, подсистема виртуальной памяти состоит из следующих частей:

  • Несколько управляющих регистров CP15
  • Таблицы страниц, содержащие правила трансляции адресов
  • TLB — кэш удачных трансляций
  • MMU — блок, занимающийся трансляцией адресов.

Литература

ARM Architecture Reference Manual ARMv7-A and ARMv7-R edition
ARM Cortex-A Series Programmer’s Guide

Автор: zloe_morkoffko

Источник

* - обязательные к заполнению поля


https://ajax.googleapis.com/ajax/libs/jquery/3.4.1/jquery.min.js