Ядро Linux делает недействительными записи TLB

В ядре Linux я написал код, напоминающий copy_page_range (mm/memory.c), поэтому копируйте память из одного процесса в другой с оптимизацией COW. Адреса назначения и источника могут быть смещены на PAGE_SIZE, и COW все еще работает. Однако я заметил, что в пользовательской программе, когда я копирую с одного и того же адреса источника на разные адреса назначения, TLB не очищается должным образом. На высоком уровне мой код пользовательского уровня делает следующее (я копирую ровно одну страницу, 0x1000 байт на моей машине за раз):

SRC=0x20000000

  1. Напишите в SRC (позвоните на соответствующую страницу page1).
  2. Системный вызов для копирования SRC в 0x30000000 в процессе назначения. Теперь адрес процесса src 0x20000000 и адрес процесса назначения 0x30000000 указывают на одну и ту же страницу (page1).
  3. Напишите что-нибудь другое в SRC (это должно вызвать ошибку страницы для обработки COW). Предположим, исходный адрес теперь указывает на page2.
  4. Системный вызов для копирования SRC в 0x30001000 в процессе назначения.

На данный момент должны существовать две отдельные страницы: SRC 0x20000000 page2 DST 0x30000000 page1 DST 0x30001000 page2

Я обнаружил, что на шаге 3, когда я записываю что-то другое в src 0x20000000, ошибка страницы не генерируется. После проверки фактические сопоставления страниц следующие: SRC 0x20000000 page1 DST 0x30000000 page1 DST 0x30001000 page1

В моем коде, если я вызываю flush_tlb_page и передаю исходный адрес, пользовательский код работает, как и ожидалось, с правильными сопоставлениями страниц. Поэтому я убежден, что неправильно поддерживаю TLB. В copy_page_range ядро ​​вызывает mmu_notifier_invalidate_range_start/end до и после изменения таблиц страниц. Я делаю то же самое и дважды проверил, действительно ли я передаю правильный struct_mm и адреса в mmu_notifier_invalidate_range_start/end. Эта функция не справляется с очисткой tlb?

Итак, буквально, когда я закончил набирать это, я проверил dup_mmap и понял, что основной вызывающий объект copy_page_range, dup_mmap (kernel/fork.c), вызывает flush_tlb_mm. Я предполагаю, что должен вызывать flush_cache_range и flush_tlb_range до и после моего кода ядра. Это правильно? Что именно делает mmu_notifier_invalidate_range_start/end?


person Chris    schedule 05.12.2011    source источник


Ответы (1)


Да, если вы делаете что-то, что изменяет таблицы страниц, вам нужно убедиться, что TLB признан недействительным, как требуется.

mmu_notifier_invalidate_range_start/end просто вызывают обработчики уведомлений MMU; эти хуки существуют только для того, чтобы можно было сообщить другому коду ядра, когда происходит аннулирование TLB. Единственными местами, где настраиваются уведомители MMU, являются

  • KVM (аппаратная виртуализация) использует их для управления заменой страниц; ему необходимо знать об аннулировании TLB хоста, чтобы виртуализированный гостевой MMU синхронизировался с хостом.
  • GRU (драйвер для специализированного оборудования в огромных системах SGI) использует уведомители MMU для синхронизации таблиц сопоставления в оборудовании GRU с MMU ЦП.

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

person Roland    schedule 05.12.2011
comment
не могли бы вы немного рассказать о mmu_notifiers? Я застрял на том, используются ли эти хуки только ядром для информирования kvm/vmm или наоборот? используются ли эти ловушки для всех страниц или только для тех страниц, которые используются VMM. если да, то как они регистрируются? - person incompetent; 26.08.2015