[转载]long mode 模式下的中断服务例程

在 long mode 下,gate 是 16 字节的,并取消了对 task gate 的支持。即 IDT 的 entry 是 16 字节的,所以:gate = IDTR.base + vector * 16。

  在 long mode 下,code segment descriptor 的 L、D、C 以及 DPL 有效,其它域无效。由于 base 强制为 0,中断服务例程的入口地址就是 gate.offset,这个 offset 是 64 位值。code segment descriptor 的 L = 1 && D = 0,代表 code segment 是 64 位代码。

1、索引 gate 和 code segment descriptor

gate = IDTR.base + vector * 16;
temp_descriptor = get_descriptor(gate.selector, GDT /* LDT */);

同样,以 gate.selector 可以找到 code segment descriptor。

2、gate descriptor 和 code segment descriptor 的检查
  processor 将对 gate 和 code segment descriptor 进行检查

if (gate.type == INTERRUPT_GATE || gate.type == TRAP_GATE) {
} else {   /* #GP 异常 */ }  
if (IS_CANONICAL(gate.offset)) {                /* is canonical-address ? */
} else {   /* #GP */ }
if (temp_descriptor.L == 1 && temp_descriptor.D == 0) {            /* 64 bit */
} else {   /* #GP 异常 */ }

  processor 对 gate 额外检查 offset 是否是 canonical-address 地址形式。processor 还将对 code segment descriptor 的 L 和 D 属性进行检查,是否为 64 位代码。

3、权限 check
  DPLg 是 gate.DPL,DPLs 是 code segment descripotr.DPL

if (CPL <= DPLg && D >= DPLs) {   /* 通过,允许访问 */ } else {   /* 失败, #GP 异常 */ }

4、stack 切换      在 long mode 下的 interrupt/trap gate 增加了 IST 域,代表 1 ~ 7 stack pointer ID 值。允许在 interrupt/trap 提供自定义的 stack pointer,分别为:IST1 ~ IST7。

old_SS = SS; old_RSP = RSP;
if (gate.IST) {   SS = NULL;   RSP = TSS.IST[gate.IST].RSP;         /* Intrrupt Stack Table */
} else {
  SS = NULL:   RSP = TSS.stack[temp_descriptor.DPL].RSP;       /* stack pointer */ }
RSP |= 0xFFFFFFFF_FFFFFFF0;                /* 调整 stack 为 16 字节对齐 */
push64(old_SS); push64(old_RSP);
push64(RFlags);
push64(CS); push64(RIP);
if (ERROR_CODE) {   push64(error_code); }

(1)如果,interrupt/trap gate 的 IST 不为 0 无论是否有权限的改变,都将发生 stack 切换,以便使用 gate 提供的 IST 指针,若 gate.IST 为 0 的话,将沿有以前的的 stack 切换模式:在权限改变时发生 stack 切换。
(2)long mode 下的 stack 以 16 字节对齐,processor 额外将 RSP 调整为 16 字节对齐。
(3)SS 将被加载为 NULL selector,即:0x0000(selector),在 long mode 下的 stack 切换中 SS 被加载为 NULL-selector 是不会产生 #GP 异常的。
(4)旧的 SS & RSP、Eflags、CS & RIP 将被入栈,SS、CS 在 8 字节边界上,多余补 0 。Rflags 的高 32 位补 0 入栈。
(5)同样若是 exception 例程则入栈 error code
---------------------------------------------------------------------------------   在 long mode 下的 TSS segment 是 64 位的,其中有 6 个 RSP 指针域,构成一个 Interrupt Stack Table 表,分别为:IST1 ~ IST7,这 6 个 RSP 由 interrupt / trap gate descriptor 中的 IST 域来索引获取。   gate 中的 IST 域值为 001 ~ 111,相应地指出在 TSS 中的 IST 值。当 gate.IST 为 0 时,表示在 gate 中不提供对 IST 的索引,还是按原来的获取 stack pointer 方式。

5、Rflags 寄存器的处理

Rflags.NT = 0; Rflags.RF = 0; Rflags.TF = 0;
if (gate == INTERRUPT_GATE) {   Rflags.IF = 0; } else if (gate == TRAP_GATE) {
}

同样,processor 需将 NT、TF、RF 清为 0,在 interuupt gate 下 IF 清 0, trap-gate 下不修改 IF 标志。long mode 下不支持 virtual-8086 mode,对 VM 标志不修改。

6、加载 code segment descriptor
  和 x86 下一样,code segment selector 和 descriptor 被加载到 CS 中,但是仅 CS.L、CS.D、CS.P、CS.C 和 CS.DPL 有效,其它域无效,CS.base 被强制为 0,CS.limit 被强制为 FFFFFFFF_FFFFFFFF   CS.RPL 被更新为 code segment descriptor 的 DPL,即为当前的 CPL。  
7、执行中断服务例程      由于 CS.base 被强制为 0,因此 gate.offset 就是实际的中断服务例程入口地址。
  RIP = gate.offset 然后执行 CS:RIP 处理的中断服务例程。

8、中断服务例程的返回
  若返回到 64 bit 模式时,processor 处理将和 x86 的情形一样。但是在 64 bit 的中断服务例程里需使用 iretq 指令。
情景提示:

  由于 iret 指令在 64 bit 模式下 default operand-size 是 32 位的,这不同于 ret 指令。ret 指令的 default operand-size 是 64 位。所以,中断返回时需使用 iretq 指令,即:使用指令前缀 REX.W(48) 将 iret 调整为 iretq

7.1.3.7.1、 compatibility 模式与 64 bit 模式之间的切换
  由于 long mode 下有 compatiblity 与 64 bit 两种子模式,那么在 x64 版本的 64 位 OS 里就有可能存在 compatibility 与 64 bit 模式之间的切换情况发生。   64 位 OS 核心运行在 64 bit 模式下,当系统加载的是原 x86 下的 32 位用户程序,processor 将从 64 bit 切换到 compatiblity 模式。32 位软件返回 OS 时,从 compatibility 模式切换回 64 bit 模式。

  当原 x86 程序中使用 int 陷入系统服务例程时,processor 从 compatibility 模式切换到 64 bit 模式,从 3 级切换到 0 级代码。

时间: 2024-11-06 16:37:42

[转载]long mode 模式下的中断服务例程的相关文章

[转载]long mode 模式下 system/gate descriptor 的疑惑

1. 32 位的 system descriptor 与 64 位的 system descriptor (1)compatibility 模式下,LDT / TSS descriptor 还是原来的 32 位的 descriptor,与原来 x86 的 LDT / TSS 意义一致. (2)64 bit 模式下,LDT / TSS descriptor 扩展为 64 位的 descriptor. descriptor 的 type 被相应改烃.由原来的 32 bit-LDT 改为 64 bit

IA-32 保护模式下寄存器一览

最近在看张银奎先生的<调试软件>一书,想将关键的技术记录下来,以便日后查阅,也分享给想看之人吧. 1 通用寄存器 EAX,EBX,ECX,EDX:用于运算的通用寄存器,可以使用AX,BX等16位或AL,AH等8位短寄存器,访问长寄存器的相应地址 ESP,EBP:Extended Stack/Base Pointer,指栈顶和当前栈的起始地址 ESI,EDI:源和目标寄存器,比如在循环操作中,与ECX组合,分别表示计数器(ECX),起始数(ESI),目标数(EDI) 64位扩展通用寄存器:RAX

80x86保护模式下IDT和中断调用过程分析

1.中断描述符表(IDT),将每个异常或中断向量分别与它们的处理过程联系起来.与GDT和LDT类似,IDT也是由8字节长度的描述符组成.IDT空描述符的存在标志位必须是0.IDT表可以驻留在线性地址空间的任何地方,处理器使用IDTR寄存器来定位IDT表的位置. LIDT指令可以把内存中的限长值和基地址操作数加载到IDTR寄存器中,该指令仅能由当前特权级CPL是0的代码执行,通常被用于创建IDT时的操作系统初始化代码中.SIDT作用相反,但可以在任何特权级执行. 2.IDT描述符 IDT表中可以存

在Debug模式下中断, 在Release模式下跳出当前函数的断言

在Debug模式下中断, 在Release模式下跳出当前函数的断言 #ifdef DEBUG #define __breakPoint_on_debug asm("int3") #else #define __breakPoint_on_debug #endif // 验证 #define UXY_ASSERT_RETURN_ON_RELEASE( __condition, __desc, ... ) \ metamacro_if_eq(0, metamacro_argcount(__

一种Linux下共享中断的处理方法

前段时间调试一款芯片的时候,碰到一个奇怪的问题:只要在板卡上插入一个PS2键盘,启动内核时系统就可能会进入串口中断函数去执行,过一会系统就panic不往下继续执行.后来经过分析出现问题时的panic的堆栈,借助EJTAG工具,读到这个时候的串口的中断状态位,竟然发现串口并没有真正产生中断.那么,串口本身没有中断,内核怎么又会跑到串口的中断服务函数去执行呢? 我们知道Linux的中断可以分为I/O 中断 .时钟中断和处理器核间中断.其中I/O中断是Linux 系统响应外部IO事件的重要方式.尽管不

Apache Spark技术实战之8:Standalone部署模式下的临时文件清理

未经本人同意严禁转载,徽沪一郎. 概要 在Standalone部署模式下,Spark运行过程中会创建哪些临时性目录及文件,这些临时目录和文件又是在什么时候被清理,本文将就这些问题做深入细致的解答. 从资源使用的方面来看,一个进程运行期间会利用到这四个方面的资源,分别是CPU,内存,磁盘和网络.进程退出之后,CPU,内存和网络都会由操作系统负责释放掉,但是运行过程中产生临时文件如果进程自己不在退出之前有效清除,就会留下一地鸡毛,浪费有效的存储空间. 部署时的第三方依赖 再提出具体的疑问之前,先回顾

Apache Spark源码走读之15 -- Standalone部署模式下的容错性分析

欢迎转载,转载请注明出处,徽沪一郎. 概要 本文就standalone部署方式下的容错性问题做比较细致的分析,主要回答standalone部署方式下的包含哪些主要节点,当某一类节点出现问题时,系统是如何处理的. Standalone部署的节点组成 介绍Spark的资料中对于RDD这个概念涉及的比较多,但对于RDD如何运行起来,如何对应到进程和线程的,着墨的不是很多. 在实际的生产环境中,Spark总是会以集群的方式进行运行的,其中standalone的部署方式是所有集群方式中最为精简的一种,另外

大钟的ios开发之旅(2)————简单说说ios中ARC与非ARC模式下的property的变量修饰词

/******************************************************************************************** * author:[email protected]大钟 * E-mail:[email protected] *site:http://www.idealpwr.com/ *深圳市动力思维科技发展有限公司 * http://blog.csdn.net/conowen * 注:本文为原创,仅作为学习交流使用,转

Android KK后为何工厂模式下无法adb 无法重新启动机器 ?

前言 欢迎大家我分享和推荐好用的代码段~~ 声明          欢迎转载,但请保留文章原始出处: CSDN:http://www.csdn.net 雨季o莫忧离:http://blog.csdn.net/luckkof 正文 KK 以后 为何工厂模式下无法adb reboot ? 正常情况下adb reboot 能够重新启动. [Keyword] adb reboot, factory mode, 工厂模式, 工厂模式无法重新启动 [版本号约束] android 4.4,  KK 或者KK