2011-12-05 22 views
6

Nel kernel linux, ho scritto codice che assomiglia a copy_page_range (mm/memoria.c) in modo da copiare la memoria da un processo a un altro con l'ottimizzazione COW. Gli indirizzi di destinazione e di origine possono essere compensati da PAGE_SIZE e la COW funziona ancora. Ho notato, tuttavia, che in un programma utente quando copio dallo stesso indirizzo sorgente a diversi indirizzi di destinazione, il TLB non sembra essere stato scaricato correttamente. Ad alto livello, il mio codice livello utente esegue le seguenti operazioni (copio esattamente una pagina, 0x1000 byte sulla mia macchina, alla volta):Kernel Linux Invalidazione voci TLB

SRC = 0x20000000

  1. Scrivi SRC (chiamare il associato pagina page1).
  2. Syscall per copiare SRC in 0x30000000 nel processo di destinazione. Ora, l'indirizzo di processo src 0x20000000 e l'indirizzo del processo di destinazione 0x30000000 puntano alla stessa pagina (page1).
  3. Scrivere qualcosa di diverso da SRC (questo dovrebbe attivare un errore di pagina per gestire la COW). Si supponga che l'indirizzo di origine ora punti a page2.
  4. Syscall per copiare SRC in 0x30001000 nel processo di destinazione.

A questo punto, dovrebbero esistere due pagine separate: SRC 0x20000000 page2 DST 0x30000000 page1 DST 0x30001000 page2

trovo che al punto 3, quando scrivo qualcosa di diverso in src 0x20000000, nessuna pagina errore è generato. Al momento dell'ispezione, le mappature di pagina reali sono: SRC 0x20000000 page1 DST 0x30000000 page1 DST 0x30001000 page1

Nel mio codice, se chiamo flush_tlb_page e passare l'indirizzo di origine, il codice utente funziona come previsto con le mappature di pagina corretta . Quindi sono convinto di non mantenere correttamente il TLB. In copy_page_range, il kernel chiama mmu_notifier_invalidate_range_start/end prima e dopo altera le tabelle di pagina. Sto facendo esattamente la stessa cosa e ho ricontrollato che sto davvero passando la struct_mm e gli indirizzi corretti a mmu_notifier_invalidate_range_start/end. Questa funzione non gestisce lo svuotamento del tlb?

Ok, così letteralmente come ho finito scrivendo questo, ho controllato dup_mmap e si rese conto che il chiamante primario di copy_page_range, dup_mmap (kernel/fork.c), chiama flush_tlb_mm. Sto indovinando che dovrei chiamare flush_cache_range e flush_tlb_range prima e dopo il mio codice del kernel. È corretto? Che cosa fa esattamente mmu_notifier_invalidate_range_start/end?

risposta

8

Sì, se si sta facendo qualcosa che modifica le tabelle delle pagine, è necessario assicurarsi che il TLB sia invalidato come richiesto.

mmu_notifier_invalidate_range_start/end stanno chiamando ganci di notifica MMU; questi hook esistono solo in modo che possa essere detto altro codice del kernel quando si verifica l'invalidazione TLB. Gli unici posti che configurano i notificatori MMU sono

  • KVM (virtualizzazione assistita hardware) li utilizza per gestire le pagine di scambio; ha bisogno di conoscere le invalidazioni TLB dell'host per mantenere la MMU guest virtuale sincronizzata con l'host.
  • GRU (driver per hardware specializzato in enormi sistemi SGI) utilizza notificatori MMU per mantenere le tabelle di mapping nell'hardware GRU in sincronia con la CPU MMU.

Ma praticamente qualsiasi posto che si chiama ganci di notifica MMU, si dovrebbe anche chiamare le funzioni di shootdown TLB se il kernel non lo sta già facendo per voi.

+0

puoi spiegare un po 'su mmu_notifiers? Sono bloccato sul fatto che questi hook siano usati solo dal kernel per informare kvm/vmm o viceversa è anche vero? se questi hook vengono utilizzati per tutte le pagine o solo per quelle pagine che vengono utilizzate da VMM. se sì, come sono registrati? – shami