追踨法蘭克

2016年5月24日 星期二

GDT - Global Descriptor Table

在SEC 階段,我們會設定一些暫存器,讓CPU動起來,且會把cache當作Ram來使用,讓此階段的assembly可以正常運作。

以x86為例: flat32.asm

這段程式做了三件事情
1. 初始化GDT (Global Descriptor Table)
2. 切換至16 bit Protected mode
3. 切換至32 bit Protected mode

align 16
_ModuleEntryPoint      PROC C PUBLIC
  ;
  ; Load the GDT table in GdtDesc
  ;
  mov     esi, OFFSET GdtDesc
  db      66h
  lgdt    fword ptr cs:[si]

  ;
  ; Transition to 16 bit protected mode
  ;
  mov     eax, cr0                   ; Get control register 0
  or      eax, 00000003h             ; Set PE bit (bit #0) & MP bit (bit #1)
  mov     cr0, eax                   ; Activate protected mode

  ;
  ; Now we're in 16 bit protected mode
  ; Set up the selectors for 32 bit protected mode entry
  ; 
  mov     ax, SYS_DATA_SEL
  mov     ds, ax
  mov     es, ax
  mov     fs, ax
  mov     gs, ax
  mov     ss, ax

  ;
  ; Transition to Flat 32 bit protected mode
  ; The jump to a far pointer causes the transition to 32 bit mode
  ;
  mov esi, offset ProtectedModeEntryLinearAddress
  jmp     fword ptr cs:[si]

_ModuleEntryPoint   ENDP


這一篇要探討Global Descriptor Table 是什麼用途。Global Descriptor Table (GDT)是定義於IA32架構,它包含所有entries來告訴CPU關於Memory Segment. 它類似於Interrupts Descriptor Table, 存在著包含task和interrupts descriptors.

GDT 使用LGDT組合語言指令來讀取。它預計GDT描述結構的位置。(將GDT 暫存器讀至memory 中)

GDTR:


 offset 是Table的本體,意思為分頁將應用的線性位址. Size是減1的大小。這是因為Size的最大值65535, 雖然GDT可達65536位元組 (8192 entries的最大值)  進一步說沒有GDT可以有大小為0.(1~65535)

Table 包含8 位元組的entries。每個entry具有複雜的結構。


Limit 0:15   => 該欄位包含0-15位元的限制。
Base 0:15 Base 16:23 Base 24:32 => Base是一個32位元值,包含線性位址segment開始的地方。

Limit,一個20位元的數值,表示最大可定址的單元(或者在1位元組為單位,或在分頁中)。因此,如果你選擇Page Granularity (4 KiB) 和Limit value 設置為0xFFFFF segment 將跨越全4 GiB位址空間。

以下是存取位元組(Access Byte)和Flag的結構.





這些位元欄位為:

  • Pr: Present bit. 它必須為 1 ,來表示於有效的選擇子(valid selectors)。
  • Privl: Privilege, 2 bits. 包含 ring level, 0 = 最高的 (kernel), 3 = 最小的 (user applications).
  • Ex: Executable bit. 如果 1 在這段代碼是可以執行的。即為代碼選擇器。如果為 0,它是資料選擇器。
  • DC: Direction bit/Conforming bit.
  • 資料選擇器的方向位元 ︰用來告知方向。0 表示segment 增加。1表示segment 減少。即為偏移量必須大於limit。
  • Conforming bit for code selectors:
  • 如果 1 在這段代碼可以從相等或更低的權限等級執行。例如,ring 3 中的代碼可以far-jump到 conformingcode 中ring 2 段。Privl 位代表的允許執行段的最高權限等級。例如中ring 0, 的代碼不能far-jump到符合標準的程式碼片段與 privl = = 0x2,雖然ring 2 和 3 中的代碼可以。注意權限等級仍然是相同的即。對 privl 的far-jump表單ring 3 = 2 段仍在ring 3 = 後跳。
  • 如果在這段代碼 0 只可以從ring 在 privl 中設置執行。
  • RW: Readable bit/Writable bit.
  • 可讀位元為代碼選擇器 ︰ 是否允許此段的讀存取權限。程式碼片段是永遠不會允許寫存取。
  • 可寫位元為資料選擇器 ︰ 是否允許此段的寫存取權限。資料段總是允許讀取存取。
  • Ac: Accessed bit. Just set to 0只是設置為 0。CPU 將此設置為 1 時存取部分。
  • Gr: Granularity bit. 如果為 0 的極限是 1 byte blocks (byte granularity), 如果 1 的限制是在 4 KiB  blocks (page granularity).
  • Sz: Size bit.如果為 0,選擇器定義了 16 位受保護的模式。如果 1 它定義了 32 位保護的模式。你可以一次用 16 位和 32 位的選擇器。

沒有留言:

張貼留言