- 保護機制概述:
- 保護機制是可靠的多任務運行環境所必須的。它可用於保護各個任務免受相互之間的干擾。在軟件開發的任何階段都可以使用段級和頁級保護來協助尋找和檢測設計問題和錯誤。當程序對錯誤內存空間執行一次非期望的引用,保護機制可以阻止這種操作並且報告此類事件。
- 保護機制可以被用於分段和分頁機制。處理器寄存器的2個比特位定義了當前執行程序的特權級,稱爲當前特權級CPL(Current Privilege Level)。分段和分頁地址轉換過程中,處理器將對CPL進行驗證。
- 通過設置控制寄存器CR0 的PE 標誌(位 0)可以讓處理器工作在保護模式下,從而也就開啓了分段保護機制。一旦進入保護模式,處理器中並不存在明確的控制標誌來停止或者啓用保護機制。不過基於特權級的保護機制部分可以通過把所有段選擇符和段描述符的特權級都設置爲0級來隱含地關閉。這種呢處理方式可以在段之間禁止特權級保護壁壘,但是其他段長度和段類型等保護機制仍然起作用。
- 設置控制寄存器CR0的PG 標誌(位31)可以開啓分頁機制,同時也開啓了分頁保護機制。同樣,處理器中也沒有相關的標誌用來分頁開啓條件下禁止或開啓頁級別保護機制。但是通過設置每個頁目錄項和頁表現的讀/寫(R/W)標誌和用戶/超級用戶(U/S)標誌,我們可以禁止頁級保護機制。設置這兩個標誌可以使得每個頁面都可以被任意讀/寫,因此實際上也就禁止了頁級保護。
- 對於分段保護機制,處理器使用段寄存器中選擇符(RPL 和 CPL)和段描述符中各個字段執行保護驗證。對於分頁機制,則主要利用頁目錄和頁表項中的R/W 和 U/S 標誌來實現保護操作。
- 段級別保護
- 在保護模式下,80x86 提供了段級和頁級保護機制。這種保護機制根據特權級(4級段保護和 2級頁保護)提供了對某些段和頁面的訪問限制能力。例如,操作系統代碼和數據存放在要比普通應用程序具有高特權級的段中。此後處理器的保護機制將會限制應用程序只能按照受控制的和規定的方式訪問操作系統的代碼和數據。
- 當使用保護機制時,每個內存引用都將受到檢查以驗證內存引用符合各種保護要求。因爲檢查操作是與地址變換同時並行操作,所以處理器性能並沒有受到影響。所進行的保護檢查可分爲以下幾類:
- 段界限檢查;
- 段類型檢查;
- 特權級檢查;
- 可尋址範圍限制;
- 過程入口點限制;
- 指令集限制.
- 所有違反保護的操作都將導致產生一個異常。下面各節描述保護模式下的保護機制。
- 段限長Limit 檢查
- 段描述符的段限長(或稱段界限)字段用於防止程序或過程尋址到段外內存位置。段限長的有效值依賴於顆粒度G 標誌的設置狀態。對於數據段,段限長還與標誌E (擴展方向)和標誌B(默認棧指針大小和/或上界限)有關。E 標誌是數據段類型的段描述符中類型字段的一個比特位。
- 當G 標誌清零時(字節顆粒度),有效的段長度是20 bit 的段描述符中段限長字段Limit的值。在這種情況下,Limit的範圍從 0 到0xfFFFF(2^20 = 1MB)。當G 標誌置位時(4KB 頁顆粒度),處理器把Limit 字段的值乘上一個因子 4K。在這種情況下,有效的Limit範圍是從0xFFF 到 0xffffFFFF(2^32 = 4GB)。請注意,當設置了 G 標誌時,段偏移(地址)的低12 bit 不會與Limit 進行對照檢查。例如,當段限長Limit 等於 0時,偏移值 0 到 0xFFF 仍然是有效的。
- 除了下擴段意外的所有段類型,有效Limit 的值是段中允許被訪問的最後一個地址,它要比段長度小 1個 字節。任何超出段限長字段指定的有效地址範圍都將導致產生一個一般保護異常。
- 對於下擴數據段,段限長具有同樣的功能,但其含義不同。這裏,段限長指定了段中最後一個不允許訪問的地址,因此在設置了B 標誌的情況下,有效偏移範圍是從(有效段偏移+1) 到 0xffff FFFF ; 當B 清零時,有效偏移值範圍是從(有效段偏移+1) 到 0xFFFF 。當下擴段的段限長爲0 時,段會有最大長度。
- 除了對段限長進行檢查,處理器也會檢查描述符表的長度。GDTR ,IDTR 和LDTR 寄存器中包含有 16bit 的限長值,處理器用它來防止程序在描述符的外面選擇描述符。描述符表的限長值指明瞭表中最後一個有效字節。因爲每個描述符是 8 字節長,因此含有N 個描述符項的表應該具有限長值 8N -1.
- 選擇符可以具有 0值。這樣的選擇符指向GDT 表中的第一個不用的描述符項。儘管這個空選擇符可以被加載進一個段寄存器中,但是任何使用這種描述符引用內存的企圖都將產生一個一般保護性異常。
- 段類型TYPE 檢查
- 除了應用程序代碼和數據段有描述符以外,處理器還有系統段和門兩種描述符類型。這些數據結構用於管理任務以及異常和中斷。 請注意,並非所有的描述符都定義一個段,門描述符中存放有指向一個過程入口點的指針。段描述符在兩個地方含有類型信息,即描述符中的S 標誌和類型字段 TYPE。 處理器利用這些信息對由於非法使用段或門導致的編程錯誤進行檢測。
- S 標誌用於指出一個描述符是系統類型的還是代碼或者數據類型的。TYPE 字段另外提供了 4 個 bit 用於定義代碼,數據和系統描述符的各種類型。 以前的表給出了代碼和數據描述符TYPE 字段的編碼; 另一個表給出了系統描述符TYPE 字段的編碼。
- 當操作段選擇符和段描述符時,處理器會隨時檢查類型信息。主要在以下兩種情況下檢查類型信息:
- 當一個描述符的選擇符加載進一個段寄存器中。此時某些段寄存器只能存放特定類型的描述符,例如:
- CS 寄存器中只能被加載進一個可執行段的選擇符;
- 不可讀可執行段的選擇符不能被加載進數據段寄存器中;
- 只有可可數據段的選擇符才能被加載進SS 寄存器中。
- 當指令訪問一個段,而該段的描述符已經加載進段寄存器中。指令只能使用某些預定義的方法來訪問某些段。
- 任何指令不能寫一個可執行段;
- 任何指令不能寫一個可寫位沒有置位的數據段;
- 任何指令不能讀一個可執行段,除非可執行段設置了可讀標誌。
- 當一個描述符的選擇符加載進一個段寄存器中。此時某些段寄存器只能存放特定類型的描述符,例如:
- 特權級
- 處理器的段保護機制可以識別 4 個特權級(或特權層 R0~R3) 0級到3級。數值越大,特權越小。下圖示出了這些特權級如何被解釋成保護環形式。環中心(保留給最高級的代碼,數據和堆棧)用於含有最緊要軟件的段,通常用於操作系統核心部分。中間兩個環用於較爲緊要的軟件。只使用 2個特權級的系統應該使用 R0 以及R3.
- 處理器利用特權級來防止運行在較低特權級的程序或任務訪問具有較高特權級的一個段,除非是在受控的條件下。當處理器檢測到一個違反特權級的操作時候,它就會產生一個一般保護性異常。
- 爲了各個代碼段和數據段之間進行特權級檢測處理,處理器可以識別以下三種類型的特權級:
- 當前特權級CPL(Current Privilege Level)。CPL是當前正在執行程序或任務的特權級。它存放在CS 和SS段寄存器中的位0 和 位1中。通常,CPL等於當前代碼段的特權級。當程序把控制轉移到另一個具有不同特權級的代碼段中時,處理器就會改變CPL。當訪問一個一致性(conforming)代碼段時,則處理器對CPL的設置有些不同。特權級值高於(即低特權級)或等於一致代碼段DPL 的任何段 都可以訪問一致代碼段。並且當處理器訪問一個特權級不同於CPL的一致代碼段時,CPL並不會被修改一致代碼段的DPL(Descriptor Privilege Level)。
- DPL 是一個段或門的特權級。它存放在段或門描述符的DPL 字段中。在當前執行代碼段試圖訪問一個段或者門時,段或門的DPL 會用來與CPL 以及段 或門選擇符中RPL (見下面說明)作比較。根據被訪問的段或門的類型不同,DPL也有不同的含義:
- 數據段(Data Segment)。其DPL 指出允許訪問本數據段的程序或任務應具有的最大特權級數值。例如,如果數據段的特權級DPL 是1,那麼只有運行在CPL 爲0 或 1的程序可以訪問這個段。
- 非一致代碼段(Nonconforming code segment)(不使用調用門)。其DPL 指出程序或任務訪問該段必須具有的特權級。例如,如果某個非一致代碼段的DPL 是 0,那麼只有運行在CPL 爲 0的程序能夠訪問這個段。
- 調用門(Call Gate)。其DPL 指出訪問調用門的當前執行程序或任務可處於的最大特權級數值。(這與數據段的訪問規則相同)。
- 一致和非一致代碼段(通過調用門訪問)。其DPL 指出允許訪問本代碼段的程序或任務應具有的最小特權級數值。例如,如果一致代碼段的DPL 是2,那麼運行在CPL 爲 0的程序就不能訪問這個代碼段。
- 任務狀態段TSS。其DPL 指出訪問TSS 的當前執行程序或任務可處於的最大特權級數值。(這與數據段的訪問規則相同)。
- 請求特權級RPL (Request Privilege Level).PRL 是一種賦予段選擇符的超越特權級,它存放在選擇符的位 0 和 位 1中。處理器會同時檢查RPL 和CPL,以確定是否允許訪問一個段。即使程序或者任務具有足夠的特權級(CPL)來訪問一個段,但是如果提供的RPL 特權級不足的話訪問也將被拒絕。也即如果段選擇符的RPL 其數值大於CPL,那麼RPL將覆蓋CPL(而使用RPL作爲檢查比較的特權級),反之也然。即始終取RPL 和CPL 中數值最大的特權級作爲訪問段時的比較對象。因此,,RPL 可以用來確保高特權級的代碼不會代表應用程序去訪問一個段,除非應用程序自己具有訪問這個段的權限。
- 當段描述符的段選擇符被加載進一個段寄存器時就會進行特權級檢查操作,但用於數據訪問的檢查方式和那些用於在代碼段之間進行程序控制轉移的檢查方式不一樣。因此下面分兩種訪問情況來考慮。
- 訪問數據段時的特權級檢查
- 爲了訪問數據段中的操作數,數據段的段選擇符必須被加載進數據段寄存器(DS,ES,FS,GS)或堆棧段寄存器(SS)中。(可以使用指令MOV, POP,LDS,LES,LFS,LGS,LSS來加載段寄存器)。在把一個段選擇符加載進段寄存器中之前,處理器會進行特權級檢查,見下圖所示。它會把當前運行程序或任務的CPL ,段選擇符的RPL 和段描述符的DPL進行比較.。只有當段的DPL數值大於或等於CPL 和RPL 兩者時候,處理器纔會把選擇符加載進段寄存器中。否則就會產生一個一般保護異常,並且不加載段選擇符。
- 可知一個程序或任務可尋址的區域隨着其CPL 改變而變化。
- 當CPL 是 0時,此時所有特權級上的數據段都可被訪問;
- 當CPL 是1 時,只有特權級 R1-R3的數據段可被訪問;
- 當CPL 是 3時,只有處於特權級3 的數據段可被訪問。
- 另外,有可能會把數據保護在代碼段中。例如,當代碼和數據是在ROM中時。因此,有些時候我們會需要訪問代碼段中的數據。此時可以使用以下方法來訪問代碼段中的數據:
- 把非一致可讀代碼段的選擇符加載進一個數據段寄存器中。
- 把一致可讀代碼段的選擇符加載進一個數據段寄存器中。
- 使用代碼段覆蓋前綴(CS)來讀取一個選擇符已經在CS 寄存器中的可讀代碼段。
- 訪問數據段的相同規則也適用方法1.方法2則是總是有效的,因爲一致代碼段的特權級等同於CPL,而不管代碼段的DPL。方法3 也總是有效的,因爲CS 寄存器選擇的代碼段的DPL 與CPL 相同。
- 當使用堆棧段選擇符加載SS 段寄存器時 也會執行特權級檢查。這裏與堆棧段相關的所有特權級必須與CPL 匹配。也即,CPL,堆棧段選擇符的RPL 以及堆棧段描述符的DPL 都必須相同。如果RPL 或DPL與CPL 不同,處理器就會產生一個一般保護性異常。
- 代碼段之間轉移控制時的特權級檢查
- 對於將程序控制權從一個代碼段轉移到另一個代碼段,目標代碼段的段選擇符必須加載進代碼段寄存器(CS)中。作爲這個加載過程的一部分,處理器會檢查目標代碼段的段描述符並執行各種限長,類型和特權級檢查。如果這些檢查都通過了,則目標代碼段選擇符就會加載進CS 寄存器,於是程序的控制權就被轉移到新代碼段中,程序將從EIP 寄存器指向的指令處開始執行。
- 程序的控制轉移使用指令 JMP,RET, INT 和IRET 以及異常和中斷機制來實現。異常和中斷時一些特殊實現,將在後面描述,本節主要說明 JMP, CALL 和RET 指令的實現方法。 JMP 和CALL 指令可以利用以下四種方法之一來引用另外一個代碼段:
- 目標操作數含有目標代碼段的段選擇符;
- 目標操作數指向一個調用門描述符,而該描述符中含有目標代碼段的選擇符;
- 目標操作數指向一個TSS ,而該TSS 中含有目標代碼段的選擇符;
- 目標操作數指向一個任務門,該任務門指向一個TSS,而該TSS中含有目標代碼段的選擇符;
- 直接調用或跳轉到代碼段
- JMP,CALL 呵呵RET 指令的近轉移形式只是在當前代碼段中執行程序控制轉移,因此不會執行特權級檢查。JMP CALL 或RET 指令的遠轉移形式會把 控制轉移到另外一個代碼段中,因此處理器一定會執行特權級檢查。
- 當不通過調用門把程序控制權轉移到另一個代碼段時,處理器會驗證4種 特權級和類型信息,見下圖所示:
- 當前特權級CPL。(這裏,CPL 是執行調用的代碼段的特權級,即含有執行調用或跳轉程序的代碼段的CPL)。
- 含有被調用過程的目的代碼段描述符中的描述符特權級DPL。
- 目的代碼段的段選擇符中的請求特權級RPL。
- 目的代碼段描述符中的一致性標誌C。它確定了一個代碼段是非一致代碼段還是一致代碼段。處理器檢查CPL,RPL和DPL 的規則依賴於一致標誌C的設置狀態。當訪問非一致代碼段時(C=0),調用者(程序)的CPL 必須等於目的代碼段的DPL,否則將會產生一般保護異常。指向非一致代碼段的段選擇符的RPL 對檢查所起的作用有限。RPL 在數值上必須小於或等於調用者的CPL 才能使得控制轉移成功完成。當非一致代碼段的段選擇符被加載進CS 寄存器中時,特權級字段不會改變,即使】它仍然是調用者的CPL。即使段選擇符的RPL 與CPL 不同,這也是正確的。
- 當訪問一致代碼段時(C=1),調用者的CPL 可以在數值上大於或等於目的代碼段的DPL。僅當CPL < DPL 時,處理器纔會產生一般保護異常。對於訪問一致代碼段,處理器忽略對RPL 的檢查。對於一致代碼段,DPL 表示調用者對代碼段進行成功調用可以處於的最低數值特權級。
- 當程序控制被轉移到一個一致代碼段中,CPL 並不改變,即使目的代碼段的DPL 在數值上小於CPL。這是CPL 與 可能與當前代碼段DPL 不相同的唯一一種情況。同樣,由於CPL 沒有改變,因此堆棧也不會切換。
- 大多數代碼段都是非一致代碼段。對於這些段,程序的控制權只能轉移到具有相同特權級的代碼段中,除非轉移是通過一個調用門進行,見下面說明。
- 門描述符
- 爲了對具有不同特權級的代碼段提供受控的訪問,處理器提供了稱爲門描述符的特殊描述符集。共有4種門描述符:
- 調用門(Call Gate),類型TYPE =12;
- 陷阱門(Trap Gate),類型TYPE =15;
- 中斷門(Interrupt Gate),類型TYPE =14;
- 任務門(Task Gate), 類型TYPE = 5。
- 任務門用於任務切換,將在後面任務管理一節說明。陷阱門和中斷門是調用門的特殊類,專門用於調用異常和中斷的處理程序,這裏僅說明調用門的使用方法。
- 調用門用於在不同特權級之間實現受控的程序控制轉移。它們通常僅用於使用特權級保護機制的操作系統中。下圖給出了調用門描述符的格式。調用門描述符可以存放在GDT 或 LDT 中,但是不能放在中斷描述符IDT 中。一個調用門主要具有以下幾個功能:
- 指定要訪問的代碼段;
- 在指定代碼段中定義過程(程序)的一個入口點;
- 指定訪問過程的調用者需要具備的特權級;
- 若會發生堆棧切換,它會指定在堆棧之間需要複製的可選參數個數;
- 指明調用門描述符是否有效。
- 調用門中的段選擇符字段指定要訪問的代碼段。偏移值字段指定段中入口點。這個入口點通常是指定過程的第一條指令。DPL 字段指定調用門的特權級,從而指定通過調用門訪問特定過程所要求的特權級。標誌P 指明調用門描述符是否有效。參數個數字段(param Count)指明在發生堆棧齊輝時從調用者堆棧複製到新堆棧中的參數個數。Linux 內核中並沒有用到調用門。這裏對調用門進行說明是爲了下一節介紹利用中斷和異常門進行處理作準備。
- 爲了對具有不同特權級的代碼段提供受控的訪問,處理器提供了稱爲門描述符的特殊描述符集。共有4種門描述符:
- 通過調用門訪問代碼段
- 爲了訪問調用門,我們需要爲CALL 或 JMP 指令的操作數提供一個遠指針。該指針中的段選擇符用於指定調用門,而指針的偏移值雖然需要單CPU 並不會用它。該偏移值可以設置爲任意值。見下圖所示。
- 當處理器訪問調用門時,它會使用調用門中的段選擇符來定位目的代碼段的段描述符。然後CPU 會把代碼段描述符的基地址與調用門中的偏移值進行組合,形成代碼段中指定程序入口點的線性地址。
- 通過調用門進行程序控制轉移時,CPU 會對 4種不同的特權級進行檢查,以確定控制轉移的有效性,見下圖所示:
- 當前特權級CPL;
- 調用門選擇符中的請求特權級RPL;
- 調用門描述符中的描述符特權級DPL;
- 目的代碼段描述符中的DPL;
- 另外,目的代碼段描述符中的一致性標誌C 也會受到檢查。
- 使用CALL 指令和JMP 指令分別具有不同的特權級檢測規則,見下圖所示。調用門描述符的DPL 字段指明瞭調用程序能夠訪問調用門的數值最大的特權級(最小特權級),即爲了訪問調用門,調用者程序的特權級CPL 必須小於 或等於調用門的DPL 。 調用門段選擇符的RPL 也需同調用這的CPL 遵守同樣的規則,即RPL 也必須小於或等於調用門的DPL。
- 如果調用這與調用門之間的特權級檢查成功通過,CPU就會接着把調用者的CPL 與代碼段描述符的DPL 進行比較檢查。在這方面,CALL 指令和JMP 指令的檢查規則就不同了。只有CALL指令可以通過調用門把程序控制轉移到特權級更高的非一致性代碼段中,即可以轉移到DPL 小於CPL 的非一致性代碼段中去執行。而JMP 指令只能通過調用門把控制轉移到DPL 等於CPL 的非一致性代碼段中。但CALL 指令和JMP 指令都可以把控制轉移到更高特權級的一致性代碼段中,即轉移到DPL 小於或等於 CPL 的一致性代碼段中。
- 如果一個調用把控制轉移到了更高特權級的非一致代碼段中,那麼CPL 就會被設置爲目的代碼段的DPL值,並且會引起堆棧切換。但是如果一個調用或跳轉把控制轉移到更高級別的一致性代碼段上,那麼CPL 並不會改變,並且也不會引起堆棧切換。
- 調用門可以讓一個代碼段中的過程被不同特權級的程序訪問。例如,位於一個代碼段中的操作系統代碼可能含有操作系統自身和應用軟件都允許訪問的代碼(比如處理字符I/O的代碼)。因此可以爲這些過程設置一個所有特權級代碼都能訪問的調用門。另外可以專門爲僅用於操作系統的代碼設置一些更高特權級的調用門。
- 堆棧切換
- 每當調用門用於把程序控制轉移到一個更高級別的非一致性代碼段時,CPU 會自動切換到目的代碼段特權級的堆棧去執行棧切換操作的目的是爲了防止高特權級程序由於棧空間不足而引起崩潰,同時也爲了防止低特權級程序通過共享的堆棧有意或無意地干擾高特權級的程序。
- 每個人物必須定義最多3個棧。一個用於運行在特權級3的應用程序代碼,其他分別用於用到的特權級R2 ,R1,和R0.如果一個系統中只使用了R3 和R0 兩個特權級,那麼每個人物就只需要設置兩個棧。每個棧都位於不同的段中,並且使用段選擇符和段中偏移值指定。
- 特權級R0,R1,R2的堆棧的初始指針值都存放在當前運行人物的TSS段中。TSS段中這些指針都是隻讀值。在人物運行時CPU 並不會修改它們。當調用更高特權級程序時,CPU 才用它們來建立新堆棧。當從調用過程返回時,相應棧就不存在了。下一次再調用該過程時,就又會再次使用TSS 中的初始指針值 建立一個新棧。
- 操作系統需要負責爲所有用到的特權級建立堆棧和堆棧段描述符,並且在任務的TSS中設置初始指針值。每個棧必須可讀可寫,並且具有足夠的空間來存放以下一些信息:
- 調用過程的SS,ESP,CS和EIP寄存器內存;
- 被調用過程的參數和臨時變量所需使用的空間。
- 當隱含調用一個異常或中斷過程時標誌寄存器EFLAGS 和出錯碼使用的空間。
- 由於一個過程可調用其它過程,因此每個棧必須有足夠大的空間來容納多幀(多套)上述信息。
- 當通過調用門執行一個過程調用而造成特權級改變時,CPU 就會執行以下步驟切換堆棧並開始在新的特權級上執行被調用過程(見下圖所示)
- 使用目的代碼段的DPL (即新的CPL)從TSS中選擇新棧的指針。從當前TSS中讀取新棧的段選擇符和棧指針。在讀取段選擇符,棧指針或棧段描述符過程中,任何違反段界限的錯誤都將導致產生一個無效TSS異常;
- 檢查棧段描述符特權級和類型是否有效,若無效者同樣產生一個無效TSS異常。
- 臨時保存SS 和ESP 寄存器的當前值,把新棧的 段選擇符和棧指針加載到SS 和ESP 中。然後把臨時保存的SS 和ESP 內容壓入新棧中。
- 把調用門描述符中指定參數個數的參數從調用過程棧複製到新棧中。調用門中參數個數值最大爲31,如果個數爲0,則表示無參數,不需複製。
- 把返回指令指針(即當前CS 和EIP 內容)壓人新棧。把新(目的)代碼段選擇符加載到CS中,同時把調用門中偏移值(新指令指針)加載到EIP中。最後開始執行被調用過程。
- 從被調用過程返回
- 指令RET 用於執行近返回(near return),同特權級遠返回(far return) 和不同特權級的遠返回。該指令用於從使用CALL 指令調用的過程中返回。近返回僅在當前代碼段中轉移程序控制權,因此CPU 僅進行界限檢查。對於相同特權級的遠返回,CPU 同時從堆棧中彈出返回代碼段的選擇符和返回指令指針。由於通常情況下這兩個指針是CALL 指令壓人棧中,因此它們應該是有效的。但是CPU 還是會執行特權級檢查以應付當前過程可能修改指針值或 堆棧出現問題時的情況。
- 會發生特權級改變的遠返回近允許返回到低特權級程序中,即返回到的代碼段DPL 在數值上要大於CPL。CPU 會使用CS 寄存器中選擇符的RPL 字段來確定是否要求返回到低特權級。如果RPL 的數值要比CPL 大,就會執行特權級之間的返回操作。當執行遠返回到一個調用過程時,CPU 會執行以下步驟:
- 檢查保存的CS 寄存器中RPL 字段值,以確定在返回時特權級是否需要改變。
- 彈出並使用被調用過程堆棧上的值加載CS 和EIP 寄存器。在此過程中 會對代碼段描述符和代碼段選擇符的RPL 進行特權級與類型檢查。
- 如果RET 指令包含一個參數個數操作數並且返回操作會改變特權級,那麼就在彈出棧中CS 和EIP 值之後把參數個數值加到ESP 寄存器值中,以跳過(丟棄)被調用者棧上的參數。此時ESP 寄存器指向原來保存的調用者堆棧的指針 SS 和ESP。
- 把保存的SS 和ESP 值加載到SS 和ESP 寄存器中,從而切換回調用者的堆棧。而此時被調用者堆棧的SS 和ESP值被拋棄。
- 如果RET 指令包含一個參數個數操作數,則把參數個數值加到ESP 寄存器值中,以跳過(丟棄)調用者棧上的參數
- 檢查段寄存器DS,ES,FS和GS 的內容。如果其中有指向DPL 小於新CPL 的段(一致代碼段除外),那麼CPU 就會用NULL 選擇符加載這個段寄存器。
- 頁級保護
- 頁目錄和頁表表項中的讀寫標誌R/W 和用戶/超級用戶標誌 U/S提供了分段機制保護屬性的一個子集。分頁機制只識別兩級權限。特權級R0 ,R1,R2 被歸類爲超級用戶級。而特權級R3 被作爲普通用戶級。普通用戶級的頁面可以被標誌成只讀/可執行或刻度/可寫/可執行。超級用戶級的頁面對於超級用戶來講總是可讀/可寫/可執行的,但普通用戶不可訪問,見下表所示。對於分段機制,在最外層用戶級執行的程序只能訪問用戶級的頁面,但是在任何超級用戶層(R0,R1,R2)執行的程序不僅可以訪問用戶層的頁面,頁可以訪問超級用戶層的頁面。與分段機制不同的是,在內層超級用戶級執行的程序對任何頁面都具有可讀/可寫/可執行權限,包括那些在用戶級標註爲只讀/可執行的頁面。
- 正如在整個80x86 地址轉換機制中分頁機制是在分段機制之後實施一樣,頁級保護也是在分段機制提供的保護措施之後發揮作用。首先,所有段級保護被檢查和測試。如果通過檢查,就會再進行頁級保護檢查。例如,僅當一個字節位於R3 執行的程序可訪問的段中,並且處於標誌位用戶級頁面中時,這個內存中的字節才能被R3 級別上的程序訪問。 僅當分段和分頁都允許寫時,才能對頁面執行寫操作。如果一個段是讀/寫類型的段,但是地址對應的相應頁面被標註爲只讀/可執行,那麼還是不能對頁面執行寫操作。如果段的類型是隻讀/可執行,那麼不管對應頁面被賦予任何保護屬性,頁面始終是沒有寫權限的。可見分段和分頁的保護機制就像電子線路中的串行線路,其中那個開關沒有合上線路都不會通。
- 類似地,一個頁面的保護屬性由頁目錄和頁表中表項的“串行”或“與操作”構成,見下表所示。頁表表項中的U/S標誌和R/W標誌應用於該表項映射的單個頁面。頁目錄項中的U/S和R/W標誌則對該目錄項所映射的所有頁面起作用。頁目錄和頁表的組合保護屬性由兩者屬性的“與”(AND) 操作構成,因此保護措施非常嚴格。
- 修改頁表項的軟件問題
- 分頁轉換緩衝要求所有系統都需遵守以下規則,爲了避免每次內存應用都要訪問駐留內存的頁表,從而加快速度,最近使用的線性到物理地址的轉換信息被保存在處理器內的頁轉換告訴緩衝中。處理器在訪問內存中的頁表之前會首先利用緩衝中的信息。只有當必要的轉換信息不再高速緩衝中時,處理器纔會搜尋內存中的頁目錄和頁表。頁轉換高速緩衝作用類似於前面描述的加速段轉換的段寄存器的影子描述符寄存器。頁轉換高速緩衝的另一個屬於稱爲轉換查找緩衝TLB(Translation Lookaside Buffer)。
- 80x86 處理器並沒有維護頁轉換高速緩衝和頁表中數據的相關性,但是需要操作系統軟件來確保它們一致。即處理器並不知道什麼時候頁表被軟件修改過了。因此操作系統必須在改動過頁表之後刷新高速緩衝以確保兩者一致。通過簡單地重新加載寄存器CR3,我們就可以完成對高速緩衝的刷新操作。
- 有一種特殊情況,在這種情況下修改頁表項不需要刷新頁轉換高速緩衝。頁即當不存在頁面的表項被修改時,即使把P 標誌從 0 改成 1 來標註表項對頁轉換有效,也不需要刷新高速緩衝。因爲無效的表項不糊被存入高速緩衝中。所以在把一個頁面從磁盤調入內存以使頁面存在時,我們不需要刷新頁轉換高速緩衝.
- 組合頁級和段級保護
- 當啓用了分頁機制,CPU 會首先執行段級保護,然後再處理頁級保護。如果CPU 在任何一級檢測到一個保護違規錯誤,則會放棄內存訪問併產生一個異常。如果是段機制產生的異常,那麼就不會再產生一個頁異常。
- 頁級保護不能替代或忽略段級保護。例如,若一個代碼段被設定爲不可寫,那麼代碼段被分頁後,即使頁面的R/W標誌被設置成可讀可寫也不會讓頁面可寫。 此時段級保護檢查會阻止任何對頁面的寫操作企圖。 頁級別保護可被用來增強段級別保護。 例如,如果一個可讀可寫數據段被分頁,那麼頁級保護機制可用來對個別頁面進行寫保護。
保護機制(個人理解)
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.