GDT

Czy to konieczne?

Do czego służy struktura GDT w systemie operacyjnym, pisałem już wcześniej. Przed przejściem do trybu chronionego, zdecydowanie przyda się nam zdefiniowanie owej tablicy ;) Dziś napiszę o budowie deskryptorów w niej zawartych.

Deskryptor

Deskryptor składa się z 64 bitów i ma dość skomplikowaną budowę. Powyżej widać jego zarysową strukturę. Teraz przyjrzyjmy się poszczególnym elementom:

  • Segment limit – długość segmentu, wyrażona w wielokrotności granularności (patrz poniżej). Limit służy w naturalny sposób ochronie. Warto zauważyć, że poszczególne bity znajdują się w dwóch miejscach struktury.
  • Base address – rozrzucone po strukturze pola składają się na adres bazowy (procesor składa je w jeden, 32 bitowy adres), czyli adres pierwszego bajta segmentu. Adres bazowy powinien być wyrównany do 16 bajtów w celu maksymalizacji wydajności.
  • Type – definiuje własności segmentu (czy do odczytu, zapisu itp.) w zależności czy segment ten jest segmentem systemowym (LDT, TSS, call-gate, interrupt-gate, trap-gate, task-gate), czy segmentem kodu/danych.  Ustawienia poszczególnych pól można znaleźć w tabelkach w podręcznikach Intela. W pewien sposób są to magiczne wartości, których sensu omawiać nie ma.
  • S flag – gdy S jest ustawione, to mamy do czynienia z segmentem kodu/danych. W przeciwnym razie jest to segment systemowy.
  • DPL – poziom uprzywilejowania, potrzebny do dostępu do segmentu. 0 to poziom najbardziej uprzywilejowany, 3 najmniej – zgodnie z tym, co opisałem tu.
  • P flag – stanowi o tym, czy segment jest ważny (ang. present). Nie można uzyskać dostępu do segmentu z wyczyszczoną flagą P – powoduje to wyjątek #NP. Pozwala na kontrolowanie załadowanych do pamięci segmentów.
  • D/B flag – mówiąc najkrócej, 1 oznacza segment 32 bitowy, a 0 – 16 bitowy. Dociekliwi mogą przeczytać więcej na ten temat w podręczniku Intela.
  • G flag – definiuje granularność – gdy flaga nieustawiona, limit wyrażony jest w 1 bajtowych blokach (segment ma maksymalnie 1 MiB), gdy ustawiona, limit wyrażony jest w jednostkach po 4 KiB (segment ma maksymalnie 4 GiB – w taki sposób uzyskuje się właśnie płaski model pamięci)
  • L flag – gdy flaga ustawiona, stanowi o tym, iż segment zawiera kod wykonywalny 64 bitowy. W przeciwnym wypadku mamy do czynienia z kodem 32 bitowym, wykonywanym w trybie zgodności. Gdy flaga L jest ustawiona, flaga D musi być nieustawiona.
  • AVL – bit nieużywany, dostępny dla oprogramowania systemowego

Ładowanie

Do załadowania GDT służy instrukcja lgdt. Instrukcja oczekuje pewnej struktury, która składa się z dwubajtowego rozmiaru tablicy pomniejszonego o 1 oraz czterobajtowego adresu samej tablicy.

Na koniec

Wszystko to może wyglądać na dość skomplikowane. W części 0x03 serii tworzenie systemu operacyjnego zobaczymy jednak, że nie taki diabeł straszny. Warto się już teraz zaprzyjaźnić z deskryptorami, gdyż są one bardzo typowym elementem architektury x86, z którym spotkamy się jeszcze wielokrotnie np. przy okazji wektora przerwań.

2 przemyślenia nt. „GDT”

Możliwość komentowania jest wyłączona.