• SYSRET


      SYSRET指令与SYSCALL指令是一对。它从OS System-call 例程返回到三环的用户代码。从RCX中加载IRP,之后从R11中加载RLFAGS。如果是64位操作数的大小,SYSRET仍然保持在64位模式;否则,它进入兼容模式,只有低32位的寄存器会被加载。

      SYSRET加载CS和SS选择子使用IA32_STAR[63:48] MSR。然而,CS与SS描述符缓存不会从段选择子指定的描述符加载。相反,这描述符缓冲加载使用固定的值。看Operaton节来查找更多细节。OS软件负责确保段选择子指定的段描述符加载进段选择子缓存。这SYSRET指令并不会对此负责。

      SYSRET指令并不会修改栈指针(ESP或RSP)。由于某些原因,系统必须要切换用户栈,这OS可能加载用户栈指针(如何它在SYSCALL之后保存)在执行SYSRET之前;相同地,用户代码可能加载栈指针(如果它在SYSCALL调用之前保存)在SYSRET之后控制。

      如果OS加载栈指针在执行SYSRET之前,它必须确保在恢复栈指针和成功执行SYSRET之间的中断和异常并不会使用用户栈来调用。可以使用如下方法来正确的执行:

    • 外部中断  OS可以阻止外部中断通过清除EFLAGS.IF位,在加载用户栈之前。
    • 不可屏蔽中断(NMIs)。这OS可以确保 NMI 处理例程调用正确的栈通过使用中断栈表(IST)机制,对于 gate2(NMI)在IDT表中。(see Section 6.14.5, “Interrupt
      Stack Table,” in Intel® 64 and IA-32 Architectures Software Developer’s Manual, Volume 3A).
    • General-protection 异常(#GP). 这SYSRET指令生成 #GP(0)如何这个RCX值是不合法的。这OS可以定位正确的地址通过下面一个或多个方法:

      • 在执行SYSRET指令之前,确保RCX值是合法数。
      • 使用Paing来确保SYSCALL指令从来不会保存一个不合法的值进入RCX。
      • 使用IST机制对gate13(#GP)在IDT中。

    指令顺序:SYSRET之后的指令可能被读取进内存,在这个指令执行完成之前,但是他们将不会得到执行知道SYSRET之前的指令完全得到执行。

    个人解读感悟:如果之前搞懂了SYSCALL指令,则SYSRET指令并不难读。这里涉及一个Gate 与 IST 机制,之前不了结果,以及GP保护的细节,我们之后找时间给读一遍,这块很好理解的。

    Operation
    IF (CS.L ≠ 1 ) or (IA32_EFER.LMA ≠ 1) or (IA32_EFER.SCE ≠ 1)
    (* Not in 64-Bit Mode or SYSCALL/SYSRET not enabled in IA32_EFER *)
    THEN #UD; FI;
    IF (CPL ≠ 0) THEN #GP(0); FI;
    IF (operand size is 64-bit)
    THEN (* Return to 64-Bit Mode *)
    IF (RCX is not canonical) THEN #GP(0);
    RIP ← RCX;
    ELSE (* Return to Compatibility Mode *)
    RIP ← ECX;
    FI;
    RFLAGS ← (R11 & 3C7FD7H) | 2; (* Clear RF, VM, reserved bits; set bit 1 *)
    IF (operand size is 64-bit)
    THEN CS.Selector ← IA32_STAR[63:48]+16;
    ELSE CS.Selector ← IA32_STAR[63:48];
    FI;
    CS.Selector ← CS.Selector OR 3; (* RPL forced to 3 *)
    (* Set rest of CS to a fixed value *)
    CS.Base ← 0; (* Flat segment *)
    CS.Limit ← FFFFFH; (* With 4-KByte granularity, implies a 4-GByte limit *)
    CS.Type ← 11; (* Execute/read code, accessed *)
    CS.S ← 1;
    CS.DPL ← 3;
    CS.P ← 1;
    IF (operand size is 64-bit)
    THEN (* Return to 64-Bit Mode *)
    CS.L ← 1; (* 64-bit code segment *)
    CS.D ← 0; (* Required if CS.L = 1 *)
    ELSE (* Return to Compatibility Mode *)
    CS.L ← 0; (* Compatibility mode *)
    CS.D ← 1; (* 32-bit code segment *)
    FI;
    CS.G ← 1; (* 4-KByte granularity *)
    CPL ← 3;
    SS.Selector ← (IA32_STAR[63:48]+8) OR 3; (* RPL forced to 3 *)
    (* Set rest of SS to a fixed value *)
    SS.Base ← 0; (* Flat segment *)
    SS.Limit ← FFFFFH; (* With 4-KByte granularity, implies a 4-GByte limit *)
    SS.Type ← 3; (* Read/write data, accessed *)
    SS.S ← 1;
    SS.DPL ← 3;
    SS.P ← 1;
    SS.B ← 1; (* 32-bit stack segment*)
    SS.G ← 1; (* 4-KByte granularity *)
    Flags Affected
    All.
    Protected Mode Exceptions
    #UD The SYSRET instruction is not recognized in protected mode.SYSRET—Return From Fast System Call
    INSTRUCTION SET REFERENCE, M-U
    4-672 Vol. 2B
    Real-Address Mode Exceptions
    #UD The SYSRET instruction is not recognized in real-address mode.
    Virtual-8086 Mode Exceptions
    #UD The SYSRET instruction is not recognized in virtual-8086 mode.
    Compatibility Mode Exceptions
    #UD The SYSRET instruction is not recognized in compatibility mode.
    64-Bit Mode Exceptions
    #UD If IA32_EFER.SCE = 0.
    If the LOCK prefix is used.
    #GP(0) If CPL ≠ 0.
    If the return is to 64-bit mode and RCX contains a non-canonical address


  • 相关阅读:
    C#学习记录(一)
    C#学习记录(五)第一次上机实验
    C#学习记录(四)
    C#学习记录(三)
    统计代码行数
    夜深了
    写在岁末的烟花易冷
    c语言|博客作业02
    c语言I博客作业03
    设计模式之模板方法模式
  • 原文地址:https://www.cnblogs.com/onetrainee/p/13512707.html
Copyright © 2020-2023  润新知