Когда именно происходит сбой TLB?
Это может произойти в любое время, даже если операционная система или гипервизор этого не запрашивали.Это четко указано в руководстве Intel, том 3, раздел 4.10.2.2:
Процессоры не должны реализовывать какие-либо TLB.Процессоры, которые реализуют TLB, могут лишить законной силы любую запись TLB в любое время.Программное обеспечение не должно полагаться на существование TLB или на сохранение записей TLB.
Насколько я знаю, в руководстве AMD нет такого утверждения.Но также не дается никаких гарантий относительно срока хранения TLB, поэтому мы можем сделать то же самое для процессоров AMD.
Таким образом, невозможно дать полный ответ на вопрос в целом.Но на уровне ISA некоторые операции могут выполнять уничтожение TLB (см. Руководство Intel V3 4.10.4 и руководство AMD V2 5.5.2), что делает недействительными одну или несколько записей TLB в одном или нескольких локальных или удаленных кэшах TLB (в другихлогические ядра того же ЦП и всех других типов процессоров, которые имеют TLB и совместно используют одно и то же адресное пространство физической памяти).
Обратите также внимание, что любая запись структуры подкачки может быть кэширована, даже если к ней не обращалисьотставная инструкция.Это может произойти из-за спекулятивного выполнения или предварительной выборки MMU.Поэтому, как правило, любая запись может быть кэширована или аннулирована в любое время.Конечно, существуют конкретные гарантии, чтобы кеши MMU могли управляться и поддерживаться согласованными со структурами подкачки в памяти.
Кто выполняет фактическое уничтожение TLB?Является ли это ядром (если да, где я могу найти код, который выполняет сброс?) Или ЦП (если это так, что запускает действие), или это оба (ядро выполняет инструкцию, которая вызывает прерывание, котороепо очереди заставляет ЦП выполнять сброс TLB)
Как я уже говорил, сам ЦП может в любое время аннулировать любую запись.Кроме того, программное обеспечение с текущим уровнем привилегий (CPL) = 0 может выполнять любые операции, связанные с управлением TLB.
Введение в недействительность TLB в ядре Linux
Ядро Linux определяет TLB-инвалидационные функции, которые не зависят от архитектуры (/arch/x86/mm/tlb.c) и функции, которые зависят от архитектуры (/arch/x86/include/asm/tlbflush.h).Это потому, что разные архитектуры предлагают совершенно разные механизмы для управления TLB.Чтобы увидеть некоторые примеры того, как ядро Linux выполняет недействительные TLB, обратитесь к перечислению tlb_flush_reason
(комментарии мои):
enum tlb_flush_reason {
// The memory descriptor structure mm of the current process is about to change.
// This occurs when switching between threads of different processes.
// Note that when mm changes, the ASID changes as well (CR3[11:0]).
// I'd rather not discuss when context switches occur because it's a whole different topic.
// TLB shootdown only occurs for the current logical core.
// The kernel sometimes can optimize away TLB flushes on a process-context switch.
TLB_FLUSH_ON_TASK_SWITCH,
// Another logical core has sent a request to the current logical core
// to perform a TLB shootdown on its TLB caches.
// This occurs due to a KVM hypercall. See TLB_REMOTE_SEND_IPI.
TLB_REMOTE_SHOOTDOWN,
// Occurs when one or more pages have been recently unmapped.
// Affects only the local TLBs.
TLB_LOCAL_SHOOTDOWN,
// This occurs when making changes to the paging structures.
// Affects only the local TLBs.
TLB_LOCAL_MM_SHOOTDOWN,
// Occurs when the current logical core uses a KVM hypercall to request
// from other logical cores to perform TLB shootdowns on their respective TLBs.
TLB_REMOTE_SEND_IPI,
// This equals to the number of reasons. Currently not used.
NR_TLB_FLUSH_REASONS,
};
В других случаях ядро сбрасывает TLB.Трудно составить полный список, и я не думаю, что кто-то создал такой список.
Ядро Linux реализует ленивую технику сброса TLB.Основная идея заключается в том, что при изменении структур подкачки процесса ядро пытается отложить сбой TLB до того момента, когда поток из этого процесса должен быть запланирован для выполнения в режиме использования.
LinuxВ настоящее время ядро использует один из следующих четырех методов для очистки TLB, связанных с текущим логическим ядром, когда это необходимо:
- Записать в CR3 текущее значение CR3.Хотя это не меняет значение в CR3, оно инструктирует логическое ядро сбрасывать все неглобальные записи TLB, имеющие тот же PCID, что и в CR3.
- Отключить CR4.PGE, а затем записать в CR4текущее значение CR4, а затем включить CR4.PGE.Это приводит к сбросу всех записей TLB для всех идентификаторов PCID и глобальных записей.Этот метод не используется, если поддерживается INVPCID.
- Делать недействительными записи TLB для данного PCID и виртуального адреса, используя тип инструкции INVPCID 0.
- Делать недействительными все записи TLB, включая глобальные и все PCID, используяТип инструкции INVPCID 2.
Другие типы INVPCID в настоящее время не используются.