2011-12-05 41 views
6

En el kernel de Linux, escribí código que se asemeja a copy_page_range (mm/memory.c) para copiar memoria de un proceso a otro con optimización COW. Las direcciones de origen y destino pueden ser compensadas por PAGE_SIZE y COW aún funciona. Noté, sin embargo, que en un programa de usuario cuando copio desde la misma dirección de origen a diferentes direcciones de destino, el TLB no parece ser lavado correctamente. En un nivel alto, mi código de nivel de usuario hace lo siguiente (copio exactamente una página, 0x1000 bytes en mi máquina, a la vez):Linux Kernel Invalidating TLB Entries

SRC = 0x20000000

  1. Escribir al SRC (llamar al asociado página page1).
  2. Syscall para copiar SRC en 0x30000000 en el proceso de destino. Ahora, la dirección del proceso src 0x20000000 y la dirección del proceso de destino 0x30000000 apuntan a la misma página (page1).
  3. Escriba algo diferente a SRC (esto debería desencadenar un error de página para manejar el COW). Supongamos que la dirección de origen ahora apunta al page2.
  4. Syscall para copiar SRC en 0x30001000 en el proceso de destino.

En este punto, deben existir dos páginas separadas: SRC 0x20000000 page2 DST 0x30000000 page1 DST 0x30001000 page2

Me parece que en el paso 3, cuando escribo algo diferente en src 0x20000000, no hay página la falla se genera. Tras la inspección, las asignaciones de página reales son: SRC 0x20000000 page1 DST 0x30000000 page1 DST 0x30001000 page1

En mi código, si llamo flush_tlb_page y pasar la dirección de origen, funciona el código de usuario como se esperaba con las asignaciones de página apropiados . Así que estoy convencido de que no estoy manteniendo correctamente el TLB. En copy_page_range, el kernel llama a mmu_notifier_invalidate_range_start/end antes y después de que altera las tablas de páginas. Estoy haciendo exactamente lo mismo y he verificado que estoy pasando las direcciones y struct_mm correctas al mmu_notifier_invalidate_range_start/end. ¿Esta función no maneja el enjuague del tlb?

Ok, por lo que, literalmente, al terminar de escribir esto, he comprobado dup_mmap y se dio cuenta de que la persona que llama primaria de copy_page_range, dup_mmap (kernel/fork.c), llama a flush_tlb_mm. Supongo que debo llamar al flush_cache_range y al flush_tlb_range antes y después de mi código del kernel. ¿Es esto correcto? ¿Qué hace exactamente mmu_notifier_invalidate_range_start/end?

Respuesta

8

Sí, si está haciendo algo que cambia las tablas de páginas, debe asegurarse de que el TLB se invalide según sea necesario.

mmu_notifier_invalidate_range_start/end están llamando a los ganchos del notificador MMU; estos enganches solo existen para que se pueda decir a otros códigos del kernel cuándo ocurre la invalidación de TLB. Los únicos lugares que configuran los notificadores de MMU son

  • KVM (virtualización asistida por hardware) los utiliza para manejar el intercambio de páginas; necesita conocer las invalidaciones de TLB del host para mantener la MMU invitada virtualizada sincronizada con el host.
  • GRU (controlador para hardware especializado en sistemas SGI grandes) utiliza notificadores MMU para mantener las tablas de asignación en el hardware GRU en sincronización con la CPU MMU.

Pero prácticamente en cualquier lugar al que llame ganchos del notificador MMU, también debería llamar a funciones de reducción de TLB si el kernel no lo está haciendo por usted.

+0

¿Puedes explicar un poco sobre mmu_notifiers? Estoy atascado en si estos ganchos son utilizados solo por kernel para informar kvm/vmm o viceversa también es cierto? si estos ganchos se usan para todas las páginas o solo aquellas que VMM utiliza. Si es así, ¿cómo están registrados? – shami