Tak, wymagają kodu maszynowego i wszystkich operandów pamięci.
Czy CPU nie powinien uzyskiwać dostępu do stron pamięci sekwencyjnie, tzn. Najpierw przeczytać instrukcję, a następnie uzyskać dostęp do operandu pamięci?
Tak, logicznie, co się dzieje, ale wyjątek błędu strony przerywa ten 2-etapowy proces i odrzuca wszelkie postępy. Procesor nie ma sposobu na zapamiętanie instrukcji, która była w środku, kiedy wystąpił błąd strony.
Gdy moduł obsługi błędów strony powróci po przetworzeniu prawidłowego błędu strony, RIP = adres instrukcji powodującej błąd, więc procesor próbuje wykonać ją od nowa .
Dopuszczalne byłoby, aby system operacyjny zmodyfikował kod maszynowy instrukcji powodującej błąd i oczekiwał, że wykona inną instrukcję później iret
niż program obsługi błędów stronicowania (lub innego wyjątku lub procedury obsługi przerwań). AFAIK wymaga architektonicznie, aby CPU powtórzył pobieranie kodu z CS: RIP w przypadku, o którym mówisz. (Zakładając, że nawet wraca do błędu CS: RIP zamiast planować inny proces podczas oczekiwania na dysk z uszkodzeniem strony twardej lub dostarczanie SIGSEGV do procedury obsługi sygnału z powodu błędu nieprawidłowej strony).
Prawdopodobnie jest to również wymagane architektonicznie do wejścia / wyjścia hiperwizora. I nawet jeśli nie jest to wyraźnie zabronione na papierze, nie tak działają procesory.
@torek komentuje, że niektóre mikroprocesory (CISC) częściowo dekodują instrukcje i zrzucają stan mikroprocesora na błąd strony , ale x86 nie jest taki.
Kilka instrukcji jest przerywalnych i może dokonywać częściowych postępów, takich jak rep movs
(memcpy w puszce) i innych instrukcji łańcuchowych, lub gromadzić ładunki / sklepy rozproszone. Ale jedynym mechanizmem jest aktualizacja rejestrów architektonicznych, takich jak RCX / RSI / RDI dla operacji łańcuchowych, lub rejestrów docelowych i masek dla gromadzeń (np. Instrukcja dla AVX2vpgatherdd
). Nieprzestrzeganie kodu operacji / dekodowania powoduje ukryty rejestr wewnętrzny i ponowne uruchomienie go po przejściu do procedury obsługi błędów strony. Są to instrukcje, które wykonują wiele różnych dostępu do danych.
Należy również pamiętać, że x86 (jak większość ISA) gwarantuje, że instrukcje są niepodzielne na wrt. przerwania / wyjątki: albo w pełni się zdarzają, albo w ogóle nie zdarzają się przed przerwaniem. Przerwanie instrukcji montażu podczas jej działania . Tak więc na przykład add [mem], reg
konieczne byłoby odrzucenie ładunku, jeśli część sklepu uległa awarii, nawet bez lock
prefiksu.
Najgorszy przypadek liczby stron w przestrzeni użytkownika gościa, które mogą wykonać postęp, może wynosić 6 (plus osobne poddrzewa tabeli stron jądra gościa dla każdego z nich):
movsq
lub movsw
instrukcja 2-bajtowa obejmująca granicę strony, więc obie strony są potrzebne do jej odkodowania.
- operand źródłowy qword
[rsi]
również podział strony
- qword operand docelowy
[rdi]
również podział strony
Jeśli którakolwiek z tych 6 stron ulegnie awarii, wrócimy do pierwszej.
rep movsd
jest także instrukcją 2-bajtową, a zrobienie postępu na jednym jej etapie wymagałoby takich samych wymagań. Podobne przypadki, takie jak push [mem]
lub pop [mem]
mogą być skonstruowane z niewłaściwie wyrównanym stosem.
Jednym z powodów (lub korzyści dodatkowych) dla / spowodowania, aby gromadzenie ładunków / rozproszenie sklepów było „przerywalne” (aktualizowanie wektora maski wraz z ich postępem), jest unikanie zwiększania tego minimalnego poziomu zajmowanego miejsca w celu wykonania pojedynczej instrukcji. Również w celu poprawy wydajności obsługi wielu błędów podczas jednego zbierania lub rozpraszania.
@Brandon wskazuje w komentarzach, że gość będzie potrzebował swoich tabel stron w pamięci , a podziały stron w przestrzeni użytkownika mogą być również podziałami 1GiB, więc obie strony znajdują się w różnych poddrzewach PML4 najwyższego poziomu. Aby przejść do następnego kroku, przejdź do strony sprzętowej. Sytuacja, w której ta patologia nie wystąpi przypadkowo.
TLB (i elementy wewnętrzne walkera) mogą buforować niektóre dane tabeli stron i nie są wymagane do ponownego uruchomienia przejścia strony od zera, chyba że system operacyjny to zrobił invlpg
lub nie ustawił nowego katalogu stron najwyższego poziomu CR3. Żadne z nich nie jest konieczne przy zmianie strony z nieobecnej na prezentowaną; x86 na papierze gwarantuje, że nie jest potrzebne (więc „negatywne buforowanie” nieobecnych PTE jest niedozwolone, przynajmniej niewidoczne dla oprogramowania). Dlatego procesor może nie VMexit, nawet jeśli niektóre strony fizycznej strony tabeli gościa nie są faktycznie obecne.
Liczniki wydajności PMU można włączyć i skonfigurować tak, że instrukcja wymaga również zdarzenia perf do zapisu w buforze PEBS dla tej instrukcji. Gdy maska licznika jest skonfigurowana do liczenia tylko instrukcji przestrzeni użytkownika, a nie jądra, może być tak, że próbuje przepełnić licznik i przechowywać próbkę w buforze za każdym razem, gdy wracasz do przestrzeni użytkownika, powodując błąd strony.