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