osdev.labedz.org

System przerwań i wyjątków

Przerwania i wyjątki są to najczęściej nieprzewidywalne zmiany w przepływie wykonywanego programu. Służą do obsługi zdarzeń zewnętrznych, wyjątków, oraz raportowania błędów. Różnica między przerwaniem a wyjątkiem polega na tym, iż przerwanie obsługuje zdarzenia, które wykonują się asynchronicznie w stosunku do pracy procesora, a wyjątek powstaje w wyniku detekcji przez procesor stanu, który nastąpił w wyniku odstępstwa od normalnego toku programu, a który należy obsłużyć w odpowiedniej procedurze.

W procesorze Intel386 istnieją dwa źródła przerwań zewnętrznych i dwa źródła wyjątków:

  • przerwania
    • maskowalne, które są sygnalizowane procesorowi przez ustawienie odpowiedniego stanu na nóżce INTR
    • niemaskowalne, które są sygnalizowane procesorowi przez ustawienie odpowiedniego stanu na nóżce NMI (ang. non-maskable interrupts)
  • wyjątki
    • wykryte przez procesor, dzielone też na pułapki, błędy i wyjątki przerwania (ang. aborts)
    • programowe, wywoływane przez wykonanie instrukcji wyjątku; często też nazywane przerwaniami programowymi, lecz są traktowane przez procesor jako wyjątki

Procesor łączy każdy rodzaj przerwania i wyjątku z odpowiednim numerem identyfikacyjnym. Przerwaniom NMI i warunkom przydzielony jest zakres identyfikatora od wartości 0 do 31. Nie każdy numer z tego zakresu jest aktualnie używany przez procesor - niektóre zostały nieprzydzielone i są zarezerwowane przez firmę Intel w celu przyszłych rozszerzeń procesora.

Identyfikator przerwania maskowalnego jest zdefiniowany przez zewnętrzny kontroler przerwań (np. programowalny kontroler przerwań Intel 8259A). Przydział przerwań odbywa się w sposób programowy - istnieje możliwość przypisania odpowiedniego przerwania do identyfikatorów z zakresu od 32 do 255.

IDOpisIDOpisIDpis
0Dzielenie przez zero7Brak koprocesora14Błąd strony
1Wyjątek pracy krokowej8Błąd podwójny15(zarezerwowane)
2Przerwanie NMI9(zarezerwowane)16Błąd koprocesora
3Punkt kontrolny10Błędny TSS17 - 31(zarezerwowane)
4Przepełnienie11Brak segmentu32 - 255Przerwania zewnętrzne
5'BOUND'12Wyjątek stosu
6Błędna instrukcja13Błąd ochrony
Tabela: Przydział identyfikatorów do przerwań i wyjątków

Wyjątki są klasyfikowane jako błędy, pułapki i wyjątki przerwania w zależności od sposobu ich zgłaszania i tego czy instrukcja, która je wywołała może zostać ponownie wykonana. Błędy (ang. Faults) są wyjątkami zgłaszanymi przed właściwym wykonaniem instrukcji lub też w trakcie jej wykonywania. Stan procesora po obsłudze błędu jest taki jak przed wykonaniem feralnej instrukcji, tak więc istnieje możliwość jej ponownego wykonania. Pułapki są zgłaszane w ramach danej instrukcji, zaraz po jej wykonaniu, natomiast gdy procesor nie jest w stanie określić instrukcji która spowodowała stan wyjątkowy, ani też powtórnie uruchomić programu, wywołuje wówczas wyjątek przerwania. Służy on najczęściej do sygnalizowania błędów typu uszkodzenie sprzętowa lub niewłaściwe wartości zawarte w newralgicznych strukturach systemowych.

Procesor obsługuje przerwanie/wyjątek tylko pomiędzy zakończeniem wykonywania jednej instrukcji a rozpoczęciem następnej. Kiedy użyty jest przedrostek powtarzania (np. instrukcje operacji na ciągach), przerwanie może być wykonane pomiędzy poszczególnymi krokami powtórki.

W niektórych przypadkach wywołanie przerwania/wyjątku jest przez procesor odsuwane w czasie. Dzieje się to w przypadku wykonywania obsługi przerwania niemaskowalnego - procesor ignoruje przychodzące w tym czasie sygnały NMI, aż do wykonania instrukcji IRET.

Przyjęcie przez procesor maskowalnych przerwań zewnętrznych zależy od ustawienia flagi IF. Kiedy IF ma wartość zero wszystkie przerwania zewnętrzne są ignorowane, natomiast kiedy IF ma wartość jeden, przerwania są obsługiwane normalnie. Instrukcje ustawiania i zerowania flagi przerwania może wykonywać jedynie te zadanie, którego obecny poziom uprzywilejowania jest mniejszy lub równy co do wartości flagi IOPL, w przeciwnym przypadku zostanie wygenerowany wyjątek.

Ponieważ istnieje możliwość wykonania jedynie jednego przerwania naraz, procesor posiada mechanizm ustalania priorytetu przychodzących przerwań. Jeżeli nadejdzie przerwanie w trakcie obsługi innego, to procesor, w zależności od priorytetów obu przerwań, albo obsługuje nadal bieżące, albo też przerywa jego działanie i zaczyna obsługę nowego. Procesor po skończeniu obsługi przerwania z wyższym priorytetu wraca do kontynuowania obsługi przerwania z priorytetem niższym.

Procesor znajduje odpowiedni deskryptor przerwania lub wyjątku poprzez tablicę deskryptorów przerwań IDT. Podobnie jak GDT i LDT, tablica deskryptorów przerwań jest tablicą zawierającą 8-bajtowe deskryptory, jednakże w tym przypadku pierwszy element może być wykorzystany. W celu znalezienia odpowiedniego deskryptora przerwania procesor mnoży wartość identyfikatora przez osiem. Ponieważ jest tylko 256 identyfikatorów, tablica deskryptorów przerwań może posiadać nie więcej niż 256 wpisów. Mniejsza liczba jest dozwolona - wpisy są niezbędne jedynie dla tych przerwań, które spodziewamy się otrzymywać.

Tablica IDT może zawierać trzy różne typy deskryptorów: bramkę zadań (Rysunek), bramkę przerwania (ang. interrupt gate) i bramkę pułapki (ang. trap gate) (Rysunek).

Deskryptor bramki przerwania
Rys. Deskryptor bramki przerwania

Jeżeli bit T/I jest ustawiony to deskryptor opisuje bramkę pułapki, w przeciwnym wypadku bramkę przerwania.

Wywołanie przerwania, którego deskryptorem jest bramka przerwania lub bramka pułapki powoduje podobne zachowanie procesora jak podczas wywołania 'bramki wywołania' instrukcją CALL. Bramka przerwania i bramka pułapki wskazują pośrednio na procedurę, które ma być wykonana w kontekście bieżącego zadania. Pole selektora wskazuje na deskryptor segmentu wykonywalnego znajdującego się w tablicy GDT, bądź też w aktualnej tablicy LDT.

Wywołanie przerwania, którego deskryptorem jest bramka zadania, powoduje zachowanie procesora podobne jak podczas wywołania bramki zadania instrukcją CALL. Bramka zadania wskazuje pośrednio na segment TSS znajdujący się w GDT. Nadejście przerwania w takim przypadku powoduje przełączenie zadania. Rozwiązanie te często stosuje się kiedy procedura obsługi zadania ma być zupełnie odizolowana od innych zadań poprzez nadanie jej oddzielnej przestrzeni adresowej (oddzielne LDT lub ).

Jeśli wystąpi przełączenie zadania w przerwaniu, które posiada kod błędu, procesor automatycznie umieszcza go na stosie o odpowiednim poziomie uprzywilejowania, zgodnym z tym jaki ma pierwsza instrukcja w wywoływanej procedurze.

Wraz z wyjątkiem, który odnosi się do określonego rejestru, procesor umieszcza na stosie procedury obsługi wyjątku, kod błędu.

Format kodu błędu
Rys. Format kodu błędu

Procesor ustawia bit EX w kodzie błędu, jeżeli zdarzenie, które go spowodował było zewnętrzne w stosunku do programu jaki się wykonywał w czasie jego zajścia. Bit jest ustawiany kiedy indeks selektora odnosi się do deskryptora bramki zawartego w IDT. Jeżeli bit nie jest ustawiony, wtedy bit T/I określa czy indeks dotyczy globalnej tablicy deskryptorów (dla wartości zero) czy też tablicy lokalnej (dla wartości jeden).