long mode 模式下的中断服务例程
来源:互联网 发布:网络不安全事件 编辑:程序博客网 时间:2024/06/04 19:27
转自:点击打开链接
在 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 级代码。
- long mode 模式下的中断服务例程
- long mode 模式下 system/gate descriptor 的疑惑
- long mode 下的 interrupt/trap gate
- long mode 下的 call gate
- ISR 中断服务例程
- 中断服务例程 学习
- ISR 中断服务例程
- 中断处理程序&中断服务例程
- 中断处理程序&中断服务例程
- 中断处理程序&中断服务例程
- 中断处理程序与中断服务例程
- 中断处理程序&中断服务例程
- 中断处理程序与中断服务例程
- long mode 下的 TSS 和 task gate
- 1.1 启动BIOS,准备实模式下的中断向量表和中断服务程序
- 关于S12的中断例程
- INT9h 中断例程的安装
- SharedPreferences的模式 mode
- oracle 游标
- Linux Kernel 排程機制介紹
- 整合IIS和Tomcat失败之后,原网站打不开,出现Service Unavailable 解决办法!!
- Cocos2d-x CCTMXTiledMap类
- 工作笔记1
- long mode 模式下的中断服务例程
- oracle10g init.ora参数文件内容
- 使用 int n 调用系统例程
- 使用 task gate 进行任务切换
- 使用 TSS selector 进行任务切换
- 选择 conforming 还是 non-conforming ?
- long mode 模式下 system/gate descriptor 的疑惑
- 通过 call gate 访问目标 code segment
- 【iOS-Cocos2d游戏开发之九】讲解CCSpriteBatchNode与TP工具的”.pvr.ccz”,”.plist”共用的终极精灵优化及注意事项!