2015-10-05 2 views
3

Согласно pgtable-2-level.h, ARM Linux имеет две версии PTE; Linux PTE и H/W PTE. Linux PTE хранится ниже смещения 1024 байта.Как ARM Linux подражает грязным, доступным и файловым битам PTE?

При обращении страничной ошибки в handle_pte_fault различной функции как pte_file, pte_mkdirty, pte_mkyoung, получить вызов с версией H/W PTE.

Но на самом деле ARM H/W не поддерживает грязный, доступный и бит файла в своем PTE.

Мой вопрос в том, как он проверяет грязный, доступный, бит файла страницы на H/W PTE? В идеале следует проверить этот бит на Linux PTE, который хранится ниже смещения 1024 байта?

ответ

4

Мой вопрос в том, как он проверяет грязный, доступный, бит файла страницы на H/W PTE?

TL; DR - они эмулируются путем устранения ошибки страницы при первоначальном доступе.

Ответов приведены в pgtable-2-level.h,

«Грязные» немного эмулируются только предоставление разрешения аппаратной записи тогда и только тогда страницы с пометкой «для записи» и «грязная» в Linux PTE. Это означает, что запись на чистую страницу приведет к ошибке разрешения, а уровень MMM Linux будет отмечать страницу грязной через handle_pte_fault(). Чтобы аппаратные средства могли заметить изменение разрешения, запись TLB должна быть разряжена, а ptep_set_access_flags() делает это для нас.

Чтобы принять грязного случая, начальные отображения MMU для страницы помечаются только для чтения. Когда процесс записывается на него, генерируется ошибка страницы. Это ссылочный номер handle_pte_fault, а основной код находится в fault.c as do_page_fault и вызывается общий handle_mm_fault, который в конечном итоге заканчивается на handle_pte_fault. Вы можете увидеть код,

if (flags & FAULT_FLAG_WRITE) { 
     if (!pte_write(entry)) 
      return do_wp_page(mm, vma, address, 
        pte, pmd, ptl, entry); 
     entry = pte_mkdirty(entry); /** Here is the dirty emulation. **/ 
} 

Таким образом, общий код Linux изучат разрешение страницы, увидеть его, предполагают, чтобы быть записываемые и вызвать pte_mkdirty пометить страницу как грязная; весь процесс запускается или эмулируется через обработчик ошибок. После того, как страница отмечена грязной в Linux PTE, ARM PTE помечен как записываемый, поэтому последующая запись не вызывает ошибку.

Доступ к идентичен, как только считывание и запись изначально будут неисправны. A файл бит также полностью не отображается, и при возникновении сбоя консультируется с Linux PTE, чтобы узнать, поддерживается ли он файлом или нет полностью unmapped ошибка страницы.

После того, как таблица оборудования обновлена ​​с новыми разрешениями и выполняется ведение бухгалтерского учета, программа пользовательского режима перезапускается в инструкции по сбою, и она не заметила разницу, кроме временного интервала для обработки ошибки.


ARM Linux использует 4k страниц и таблицы страниц ARM второго уровня являются 1k в размере (256 записей * 4 байта). Из pgtable-2-level.h комментарии,

Поэтому мы подправить реализацию немного - мы говорим Linux, что мы имеем 2048 записей в первом уровне, каждый из которых составляет 8 байт (IOW, два аппаратные указатели ко второму уровню.) Второй уровень содержит две аппаратные таблицы PTE, расположенные смежно, с предшествующими версиями Linux, которые содержат информацию о состоянии, требуемую Linux. Таким образом, мы получаем 512 записей на уровне «PTE».

Для того, чтобы использовать полную 4K страницу, PTE записи структурированы как,

  1. Linux PTE [п]
  2. Linux PTE [п + 1]
  3. ARM PTE [N]
  4. АРМ ПТЭ [N + 1]

Четыре 1k детали для полная страница 4k. Эти коллекции страниц должны управляться для каждого процесса, чтобы каждый из них обладал уникальным представлением о памяти, а часть информации используется для сохранения реальной ОЗУ. Функция cpu_set_pte_ext используется для изменения физических записей ARM. Поскольку каждая ревизия процессора ARM использует несколько разные структуры и функции таблиц, в поле processor function table есть запись, указывающая на процедуру ассемблера. Например, cpu_v7_set_pte_ext представляет собой ARMv7 или типичную оригинальную реализацию Cortex CPU. Эта процедура отвечает за проверку флагов Linux и соответственно обновление аппаратных бит. Как видно, r3 записывается в pte+2048 (смещение от Linux PTE на аппаратное PTE) в конце этой процедуры. Макрос ассемблера armv3_set_pte_ext в proc-marcos.S используется многими старыми вариантами процессора.

См: Tim's notes on ARM MM
                  Page table entry (PTE) descriptor in Linux kernel for ARM

+0

Спасибо за ваш ценный ответ, но снова мои сомнения и растерянность, как это pte_write() возвращает истину для чтения только страницы, что версия PTE проверяется макросом pte_write, это Linux PTE или ARM PTE? таким же образом изменился pte_mkdirty, в который вошли Linux PTE или ARM PTE? потому что из handle_mm_fault получает pte из pte_offset_map, кажется, что он возвращает ARM PTE, пожалуйста, исправьте меня, если я ошибаюсь. –

+0

На самом деле, это, кажется, новые вопросы. Я обновил свой ответ. Магия, которую вы ищете, - 'cpu_set_pte_ext', которая похожа на виртуальную функцию C++ и реализована по-разному для разнесенных бит ARM MMU (новые типы процессоров имеют расширенные функции). Тем не менее, они все распространены в письменной форме как для Linux PTE, так и для ARM PTE (+2048). –

+0

Linux работает только с значениями PTE Linux. Только когда они * совершены *, вызывается функция 'cpu_set_pte_ext', которая проверяет версию Linux и обновляет версию аппаратного обеспечения. Например, ['set_pte_at'] (https://git.kernel.org/cgit/linux/kernel/git/torvalds/linux.git/tree/arch/arm/include/asm/pgtable.h#n241) и несколько других мест, где инициализируется PTE. –

Смежные вопросы