Gdy wystąpi przerwanie, procesor wstrzymuje bieżący proces i wywołuje kod jądra, aby obsłużyć przerwanie. Skąd procesor wie, gdzie wejść do jądra?
Rozumiem, że istnieją procedury obsługi przerwań, które można zainstalować dla każdej linii przerwań. Ale ponieważ procesor wykonuje tylko „logikę przewodową”, musi istnieć pewne predefiniowane miejsce, które wskazuje albo na samą procedurę obsługi przerwań, albo jakiś kod, który wykonuje się przed funkcją obsługi (ponieważ może istnieć wiele procedur obsługi dla jednej linii przerwania, zakładam, że końcowy).
źródło
Tak, istnieje predefiniowane miejsce zawierające adres kodu, na który należy przejść: wektor przerwań . W zależności od procesora może to być określone miejsce w pamięci fizycznej (8088), określone miejsce w pamięci wirtualnej, rejestr procesora, miejsce w pamięci wskazane przez rejestr (ARM, 386),…
Szczegóły różnią się w zależności od procesora, ale głównymi wspólnymi elementami obsługi przerwań w procesorze są:
źródło
Pozostałe dwie odpowiedzi (w momencie pisania) mówią o przerwaniach i IDT. Jest to jednak poprawne w przypadku nowoczesnego procesora Intel, nie ma mniej niż trzy sposoby na wywołanie jądra.
Metoda nr 1: Przerwania.
To wyjaśniono powyżej. Ustawiasz pozycję w tabeli deskryptorów przerwań / wektorze przerwań, a następnie wykonujesz przerwanie programowe, aby wejść do jądra.
Główną zaletą tej metody jest to, że typowe jądro musi być w stanie obsłużyć przerwania i działa na archaicznym sprzęcie.
Metoda nr 2: Zadzwoń do bram.
Bramka jest specjalnym rodzajem selektora segmentu. Cel połączenia musi zostać załadowany do globalnej lub lokalnej tabeli deskryptorów segmentów (odpowiednio GDT i LDT). Jeśli następnie wykonasz instrukcję dalekiego połączenia, używając bramki jako segmentu (przesunięcie połączenia jest ignorowane), pozwala to na wywołanie bardziej uprzywilejowanego kodu. Bramki telefoniczne są niezwykle elastyczne; architektura IA-32 ma cztery poziomy przywilejów, a bramki wywoływania pozwalają na wywołanie dowolnego poziomu.
Nie wierzę, że Linux kiedykolwiek używał bramek połączeń, ale Windows 95 tak. Usługi jądra Win95 (
krnl386.exe
ikernel.dll
) faktycznie działały w trybie użytkownika (pierścień 3). Najwyższy poziom uprawnień (pierścień 0) został użyty tylko dla sterowników i mikrojądra, które wykonywało tylko przełączanie procesów. Wzywanie kierowców odbywało się za pomocą bramek. Umożliwiło to starszemu 16-bitowemu kodowi (którego było dużo!) Używanie sterowników Win95 tylko za pomocą standardowego dalekiego wywołania, tak jak zawsze.Niewystarczająca ochrona globalnej tabeli deskryptorów była przyczyną wielu exploitów Windows 95, którym udało się zainstalować własne bramki wywoływania, zapisując w pamięci.
Metoda nr 3: SYSCALL / SYSRET i SYSENTER / SYSEXIT
Są to dwa zestawy instrukcji, wymyślone niezależnie przez AMD i Intela, ale zasadniczo robią to samo. SYSCALL / SYSRET był pierwszy i był tylko AMD, SYSENTER / SYSEXIT był Intel, ale AMD go teraz wdraża. Więc opiszę SYSENTER / SYSEXIT.
W przeciwieństwie do bramek telefonicznych, SYSENTER może być użyty tylko do przeniesienia na dzwonek 0 i może być przeniesiony tylko do jednej lokalizacji. Ma jednak tę zaletę, że charakteryzuje się wyjątkowo niskim opóźnieniem, ponieważ w przeciwieństwie do połączenia lub przerwania nie dotyka stosu.
Lokalizacja przesyłania jest konfigurowana za pomocą trzech rejestrów specyficznych dla modelu: jednego dla informacji o segmencie i jednego dla wskaźnika instrukcji i wskaźnika stosu kodu jądra. Ponieważ nic nie jest „wypychane” na stos, kod trybu użytkownika jest odpowiedzialny za poinformowanie jądra, do którego ma wrócić, przekazując wskaźnik instrukcji return i wskaźnik stosu w rejestrach. Jądro jest odpowiedzialne za odtwarzanie wskaźnika stosu, a instrukcja SYSEXIT przywraca wskaźnik instrukcji.
Dalsze informacje na temat instrukcji SYSENTER i SYSEXIT.
źródło