sysenter/sysexit 系統調用的機制:
在 Intel 的軟件開(kāi)發(fā)者手冊第二、三卷(Vol.2B,Vol.3)中,4.8.7 節是關(guān)于 sysenter/sysexit 指令的詳細描述。手冊中說(shuō)明,sysenter 指令可用于特權級 3 的用戶(hù)代碼調用特權級 0 的系統內核代碼,而 SYSEXIT 指令則用于特權級 0 的系統代碼返回用戶(hù)空間中。sysenter 指令可以在 3,2,1 這三個(gè)特權級別調用(Linux 中只用到了特權級 3),而 SYSEXIT 指令只能從特權級 0 調用。
執行 sysenter 指令的系統必須滿(mǎn)足兩個(gè)條件:1.目標 Ring 0 代碼段必須是平坦模式(Flat Mode)的 4GB 的可讀可執行的非一致代碼段。2.目標 RING0 堆棧段必須是平坦模式(Flat Mode)的 4GB 的可讀可寫(xiě)向上擴展的棧段。
在 Intel 的手冊中,還提到了 sysenter/sysexit 和 int n/iret 指令的一個(gè)區別,那就是 sysenter/sysexit 指令并不成對,sysenter 指令并不會(huì )把 SYSEXIT 所需的返回地址壓棧,sysexit 返回的地址并不一定是 sysenter 指令的下一個(gè)指令地址。調用 sysenter/sysexit 指令地址的跳轉是通過(guò)設置一組特殊寄存器實(shí)現的。這些寄存器包括:
SYSENTER_CS_MSR - 用于指定要執行的 Ring 0 代碼的代碼段選擇符,由它還能得出目標 Ring 0 所用堆棧段的段選擇符;
SYSENTER_EIP_MSR - 用于指定要執行的 Ring 0 代碼的起始地址;
SYSENTER_ESP_MSR-用于指定要執行的Ring 0代碼所使用的棧指針
這些寄存器可以通過(guò) wrmsr 指令來(lái)設置,執行 wrmsr 指令時(shí),通過(guò)寄存器 edx、eax 指定設置的值,edx 指定值的高 32 位,eax 指定值的低 32 位,在設置上述寄存器時(shí),edx 都是 0,通過(guò)寄存器 ecx 指定填充的 MSR 寄存器,sysenter_CS_MSR、sysenter_ESP_MSR、sysenter_EIP_MSR 寄存器分別對應 0x174、0x175、0x176,需要注意的是,wrmsr 指令只能在 Ring 0 執行。
這里還要介紹一個(gè)特性,就是 Ring0、Ring3 的代碼段描述符和堆棧段描述符在全局描述符表 GDT 中是順序排列的,這樣只需知道 SYSENTER_CS_MSR 中指定的 Ring0 的代碼段描述符,就可以推算出 Ring0 的堆棧段描述符以及 Ring3 的代碼段描述符和堆棧段描述符。
在 Ring3 的代碼調用了 sysenter 指令之后,CPU 會(huì )做出如下的操作:
1.將 SYSENTER_CS_MSR 的值裝載到 cs 寄存器
2.將 SYSENTER_EIP_MSR 的值裝載到 eip 寄存器
3.將 SYSENTER_CS_MSR 的值加 8(Ring0 的堆棧段描述符)裝載到 ss 寄存器。
4.將 SYSENTER_ESP_MSR 的值裝載到 esp 寄存器
5.將特權級切換到 Ring0
6.如果 EFLAGS 寄存器的 VM 標志被置位,則清除該標志
7.開(kāi)始執行指定的 Ring0 代碼
在 Ring0 代碼執行完畢,調用 SYSEXIT 指令退回 Ring3 時(shí),CPU 會(huì )做出如下操作:
1.將 SYSENTER_CS_MSR 的值加 16(Ring3 的代碼段描述符)裝載到 cs 寄存器
2.將寄存器 edx 的值裝載到 eip 寄存器
3.將 SYSENTER_CS_MSR 的值加 24(Ring3 的堆棧段描述符)裝載到 ss 寄存器
4.將寄存器 ecx 的值裝載到 esp 寄存器
5.將特權級切換到 Ring3
6.繼續執行 Ring3 的代碼
由此可知,在調用 SYSENTER 進(jìn)入 Ring0 之前,一定需要通過(guò) wrmsr 指令設置好 Ring0 代碼的相關(guān)信息,在調用 SYSEXIT 之前,還要保證寄存器edx、ecx 的正確性
聯(lián)系客服