amd64中系统调用指令

amd64 Jul 01, 2020

syscall and sysret

使用syscall指令需要在IA32_EFER这个MSR寄存器开启SCE

进入长模式前 使用:

mov ecx, 0xC0000080               ; Read from the EFER MSR. 
rdmsr    
   
or eax, 0x00000101                ; Set the LME bit.
wrmsr

IA32_EFER寄存器如下图

syscall

syscall只能实现ring3 到 ring0的调用

使用前需要在MSR寄存器写入段寄存器值和入口地址

在64bit模式中 LSTAR寄存器指定了SYSCALL的入口地址

STAR寄存器的48-63位存放ring0的CS 和 SS(忽略)

SFMASK寄存器指定了SYSCALL SYSRET如何处理rflags

sysret

sysret只能实现ring0 到 ring3的调用

主要工作为

  1. 把RIP值设定成RCX
  2. 切换CS, 根据下面约定(64 bit)

3. rflags处理,RFLAGS由r11寄存器的值恢复

RFLAGS ← (R11 & 3C7FD7H) | 2;
(* Clear RF, VM, reserved bits; set bit 1 *)

swappgs

KernelGSBase 是一个MSR寄存器 等于是装一个GS寄存器值的变量

swappgs将KernelGSBase与当前GS段寄存器的base做交换

当用户态使用syscall进入内核,但syscall并不会自动处理内核栈,此时的rsp仍然是用户态的rsp, 系统调用不会使用用户态的栈, 可以把内核的一段临时空间放在KernelGSBase中,使用swappgs切换内核临时空间,在sysret前再次调用swappgs重新切换用户态的状态.

这里指的内核栈属于per CPU的内核临时空间

例如可以把用户态的rsp保存在临时空间,切换内核栈rsp,然后把用户态的rsp push到内核栈。

获取per CPU临时空间的指令 假设swappgs已经调用且KernelGSBase设置了正确的地址

Great! You've successfully subscribed.
Great! Next, complete checkout for full access.
Welcome back! You've successfully signed in.
Success! Your account is fully activated, you now have access to all content.