在 IA-32 架構中,protected mode 是標準的記憶體架構,不但支援 segmentation,還支援 paging。
首先,memory address 的轉換是必須要知道的,以下先用一張圖來說明:
在 protected mode 支援了複雜的 segmentation 機制,其中 segment 單元會將 logical address 轉為 32-bit linear address,而 paging 單元會將 32-bit linear address 轉為 32-bit physical address。
若是沒有 paging 的機制,則 logical address 會直接轉換為 32-bit physical address。
接著以下用一張圖說明 segment 單元將 logical address 轉為 32-bit linear address 的過程:
在 segment register 中儲存的是 segment descriptor table 的索引值,用來取得相對應的 segment descriptor;而 segment descriptor 中則包含了 32-bit segment base address、size、存取權限 .... 等資訊
【註】descriptor table 包含了許多 segment descriptor,而每一個 segment descriptor 都有其 index 作為識別。
除了之外,為了將 logical address 轉為相對應的 linear address,還需要加入一個 offset 值,而 offset 則可以是 16-bit 或是 32-bit 的數值。
Segment Registers
每一個 segment register 都分為 visible 與 invisible 兩個部分,而我們一般提到的 segment register 都是指其 visible 的部分(長度為 16 bits),也其為 segment selector,以下用一張圖來說明:
其中 segment selector 共分為三個部分:
- Index
使用 index 就可以取得在 local descriptor table(或是 global descriptor table) 中的 segment descriptor。
根據上面的圖,可以看出 index 的長度為 13 bits,因此可以從 descriptor table 取得 8192(213) 個不同的 segment descriptor - Table Indicator (TI)
用來決定哪種 descriptor table 要被使用:
0:global descriptor table
1:local descriptor table - Requester Privilege Level (RPL)
設定資料的存取權限之用。數值越小,存取權限越大,例如:Linux kernel 使用 0,而一般程式使用 3。
Segment Descriptors
顧名思義,segment descriptor 所提供的是 segment 的相關屬性,包含了 32-bit base address、20-bit segment 長度、各種控制、狀態資訊 .... 等等,以下用一張圖來表示:
以下針對上圖的各欄位進行說明:
Base Address
由上圖三個紅色部分所組成的,長度為 32-bit,因此最大可以指向實體記憶體空間為 4GB 的 segment。
而若要轉為 linear address,就必須要加上 offset 值。
G(granularity bit)
用來指定 segment size 的單位。
有兩種情況:
- G = 0,則每單位為 1 byte
- G = 1,則每單位為 4KB。
Segment Limit
由上圖的兩個藍色部分所組成,長度為 20-bit,用來指定每個 segment 的大小,但須搭配上面的 G bit,因此會有兩種情形:
- G = 0,則可定址空間為 1 byte ~ 1 MB(220 x 1 byte)
- G = 1,則可定址空間為 4 KB ~ 4 GB(220 x 4KB)
D/B bit
若在 CS(code segment) 中,此 bit 稱為 D bit。會有以下兩種情形:
- D = 0,則運算元與 offset 長度預設為 16 bits
- D = 1,則運算元與 offset 長度預設為 32 bits。
若在 DS(data segment) 中,此 bit 稱為 B bit,作為控制 stack 的長度與 stack pointer 之用。會有以下兩種情形:
- B = 0,則 stack 相關的操作會使用 SP register,而 stack 空間上限為 0xFFFF
- B = 1,則 stack 相關的操作會使用 ESP register,而 stack 空間上限為 0xFFFFFFFF。
S bit
用來判斷 segment 屬於 system segment 或是 application segment。會有以下兩種情形:
- S = 0,則屬於 system segment
- S = 1,則屬於 application(code or data) segment。
DPL(Descriptor Privilege Level)
定義 segment 的權限等級。
Type
用來判斷 segment 的類型。
以 application segment 為例,分為 code segment 與 data segment。
假設是 data segment(儲存資料的記憶體位址),Type 可以將其定義為 read-only、read-write .... 等等不同類型;若是 code segment(儲存指令的記憶體位址),則 Type 可以定義為 execute-only、execute/read-only .... 等等不同類型。
P bit
用來判斷是否此 segment 是存在的的。
假設 P = 1,當有 segment selector 讀進此 segment register 時,CPU 會產生 segment-not-present 的例外。
Segment Descriptor Table
segment descriptor table 即為儲存 segment descriptor 的陣列,其中的每個 segment descriptor 都有所屬的特定 index。
而 descriptor table 一共可以分為以下三種類型:
- GDT(Global Descriptor Table)
- LDT(Local Descriptor Table)
- IDT(Interrupt Descriptor Table)
每個 descriptor table 的大小介於 8 bytes ~ 64 KB 之間。
其中 IDT(Interrupt Descriptor Table) 是作為中斷處理之用;而 GDT(Global Descriptor Table) 與 LDT(Local Descriptor Table) 最多可以包含 213 = 8192 個長度為 8 bits 的 segment descriptor。
另外,每個 descriptor table 都有一個相對應的 register,而這個 register 作用是在於儲存 32-bit 的 linear base address 與 16-bit 的 descriptor table 大小,分別是:
- GDT => GDTR
- LDT => LDTR
這兩個 register 有指令可以使用他們(load => lgdt、lldt,store => sgdt、sldt),不過通常這個部分都是由 OS 來作。
最後描述一下 GDT 與 LDT 的差異所在:
- GDT(Global Descriptor Table)
數量只有一個,所有在系統中的 task 都可以使用此 table 中的 descriptor,通常 GDT 中所包含的都是給 OS 所用的 code 及 data。 - LDT(Local Descriptor Table)
數量可以有多個,每個 LDT 中所包含的 descriptor 都是屬於某支程式,而有些 LDT 的 descriptor 可能包含 code、data、stack .... 等等。
Segmentation Models
在 IA-32 架構下,單一 segment 最大可以擴展到 4GB。若是將 segment base address 設定為 0,並設定其 size 為 4 GB,就可以達成 segment 的大小為 4 GB 的目的,而這種作法在 UNIX 或 Linux 都見的到,稱為 flat model。
另外還有一種稱為 multisegment model,以下先用一張圖來表示:
一般的程式可能會使用超過 6 個 segment,在正常的情況下,相關的 segment 資訊都會讀入 segment descriptor 中(超過 6 個),但每一次可用的僅有 6 個 segment(因為僅有 6 個 segment register),若要啟用尚未使用的 segment,只要將指向 segment 的 selector 讀入 segment register,CPU 就可以從相對應的 descriptor table 中存取該 segment。
沒有留言:
張貼留言