2011-12-05 23 views
6

W jądrze Linuxa napisałem kod przypominający copy_page_range (mm/memory.c), dzięki czemu można skopiować pamięć z jednego procesu do drugiego dzięki optymalizacji COW. Adres docelowy i adres źródłowy mogą być przesunięte o PAGE_SIZE, a COW nadal działa. Zauważyłem jednak, że w programie użytkownika podczas kopiowania z tego samego adresu źródłowego do różnych adresów docelowych, TLB nie wydaje się być poprawnie przepłukane. Na wysokim poziomie, mój kod poziom użytkownik wykonuje następujące (I skopiować dokładnie jedną stronę, 0x1000 bajtów na moim komputerze, w czasie):Jądro Linuxa Unieważniające wpisy TLB

src = 0x20000000

  1. Napisz do SRC (wezwanie powiązany strona page1).
  2. Syscall do skopiowania kodu SRC do 0x30000000 w procesie docelowym. Teraz adres procesu src 0x20000000 i adres procesu docelowego 0x30000000 wskazują tę samą stronę (page1).
  3. Napisz coś innego niż SRC (powinno to wywołać błąd strony, aby obsłużyć COW). Załóżmy, że adres źródłowy wskazuje teraz na page2.
  4. Syscall do skopiowania kodu SRC do 0x30001000 w procesie docelowym.

W tym momencie dwie oddzielne strony powinny istnieć: SRC 0x20000000 page2 DST 0x30000000 page1 DST 0x30001000 page2

Uważam, że w etapie 3, gdy piszę coś innego do src 0x20000000, bez widoku błąd jest generowany. Po inspekcji, rzeczywiste mapowanie strona to: SRC 0x20000000 page1 DST 0x30000000 page1 DST 0x30001000 page1

W moim kodu, jeśli zadzwonię flush_tlb_page i przekazać adres źródłowy, kod użytkownik działa zgodnie z oczekiwaniami z odpowiednich przekształceń stronie . Jestem więc przekonany, że nie utrzymuję TLB poprawnie. W kodzie copy_page_range jądro wywołuje mmu_notifier_invalidate_range_start/end przed i po zmianie tablic stron. Robię dokładnie to samo i dwukrotnie sprawdzam, czy rzeczywiście przekazuję poprawną strukturę struct_mm i adresy do mmu_notifier_invalidate_range_start/end. Czy ta funkcja nie działa podczas przepłukiwania tlb?

Ok, tak dosłownie jak skończyłem pisanie tego, sprawdziłem dup_mmap i zrozumiał, że podstawowym wywołujący copy_page_range, dup_mmap (kernel/fork.c), wzywa flush_tlb_mm. Zgaduję, że powinienem zadzwonić pod flush_cache_range i flush_tlb_range przed i po moim kodzie jądra. Czy to jest poprawne? Co dokładnie robi mmu_notifier_invalidate_range_start/end?

Odpowiedz

8

Tak, jeśli robisz coś, co zmienia tabele stron, musisz się upewnić, że TLB zostanie unieważnione zgodnie z wymaganiami.

tylko wywołują haki zgłaszającego MMU; te haki istnieją tylko po to, aby można było poinformować inny kod jądra, gdy odbywa się unieważnianie TLB. Jedynymi miejscami, które utworzone są powiadamiający MMU

  • KVM (sprzętowe wspomaganie wirtualizacji) wykorzystuje je do obsługi wymieniając stron; musi wiedzieć o unieważnieniach TLB hosta, aby wirtualny MMU gości był zsynchronizowany z hostem.
  • GRU (sterownik specjalizowanego sprzętu w dużych systemach SGI) używa powiadomień MMU, aby tabele odwzorowań w sprzęcie GRU były zsynchronizowane z jednostką MMU procesora.

Ale prawie każde miejsce, które nazywasz hakerami MMU, powinieneś również wywoływać funkcje TLB, jeśli jądro jeszcze tego nie robi.

+0

czy możesz wyjaśnić trochę o mmu_notifiers? Utknąłem na tym, czy te haczyki są używane tylko przez jądro do informowania kvm/vmm lub vice versa? czy te haki są używane dla wszystkich stron, czy tylko z tych stron, które są używane przez VMM. jeśli tak, w jaki sposób są one zarejestrowane? – shami