[转载]使用 TSS selector 进行任务切换
2015-01-29 17:45
344 查看
指令:
call 0x20:00000000 jmp 0x20:00000000
-----------------------------------
selector 0x20 是个 TSS descriptor 的 selector。
TSS descriptor 与 segment descriptor 的格式一致,不同的是 type,在 x86 和 long mode 的 compatibility 模式下有: available/busy 16-TSS 和 available/busy 32-TSS。
当成功将 TSS descriptor 加载到 TR 寄存器后,processor 将 available TSS 置为 busy TSS,在返回时将 busy TSS 置为 available TSS。
1、索引查找 TSS descriptor
TSS selector 在 GDT 里索引 TSS descriptor,其方法和 segment / gate dscriptor 的查找一致。
2、TSS 的 limit & type check
TSS segment 大小必须能容纳所有的 processor state,整个 TSS segment 的大小是 104 个字节,在加载 TSS descriptor 进入 TR 之前,processor 检查 TSS descriptor 中的 limit 必须大于或等于 67h(104 字节)。若否,则产生 #TS 异常。 processor 也检查 TSS descriptor 的 type 是否为 available 类型。若为 busy 类型,则产生 #GP 异常。
3、权限的 check
所需的权限是:CPL <= DPL && RPL <= DPL
4、保存 old-task 的 processor state
在执行加载 TSS descriptor 到 TR 之前,processor 将执行一项很重要的工作:保存 old-task 的执行环境(processor 的状态)在当前的 TSS segment 中。 当前的 TSS segment 就是 old-task 的 TSS segment,在没加载 new-task 的 TSS 进入 TR 之前。
执行环境包括: (1)GPRs (2)segment registers (3)Eflags (4)LDTR 和 CR3 (5)EIP
5、加载 TSS descriptor
通过一系列的 processor 检查后,processor 加载 TSS descriptor 进入 TR 寄存器。
TSS descriptor 加载到 TR 寄存器相应的域。 并且,processor 将 TSS descriptor 的 type 置为 BUSY 状态,防止再调用该 TSS descriptor CR0.TS 也被置为 1,防止在 task 切换时执行 x87 or SSE(media)指令。
6、加载 processor state 信息
TSS descriptor 加载进 TR,processor 将加载新任务保存在 TSS 的 processor 状态信息。 包括: (1)GPRs 加载 (2)segment registers 加载 (3)Eflags 加载 (4)LDTR 和 CR3 加载
7、设置 EFLAGS.NT 和 TSS.link 域
使用 call 指令调用 TSS selector,processor 将置 Eflags.NT 为 1,表示当前的 task 被嵌套调用。而使用 jmp 指令则不会置 Eflags.NT 为 1。
jmp 指令不支持 Task-Nesting 因此不改变 Eflags.NT 域,使用 call 指令还将当前 TSS 的 link 域设为 old-task 的 TSS selector,这样,当前使用 iret 指令返回时,将通过 old-task 的 TSS selector 返回到 old-task。
7、执行新 task
同样,processor 加载新的 task EIP 进入 EIP 寄存器,执行新的 task 代码。新的 CS 被加载时,CPL 就是新的 CS.RPL。
8、返回 old-task
new-task 执行完毕通过 ret 或 iret 指令返回到 old-task。
在 caller 中:
使用 call TSS_selector 来切换到 new-task。
(1)使用 ret 指令返回 在 new-task 中使用 ret 指令返回和一般的 caller / callee 之间返回并无两样。程序将返回到 next 处。
(2)使用 iret 指令返回 使用 Eflags.NT 的目的是让 iret 来返回,当使用 iret 指令返回时,processor 将检查 Eflags.NT 是否为 1 ,若 Eflags.NT = 1 则表示当前 task 被嵌套。 程序将返回到 TSS.link 的 TSS selector 指向的 TSS descriptor,这个 TSS descriptor 就是 old-task 的 TSS descriptor,这里又进行另一次的任务切换到 old-task。
----------------------------------------------------------
使用 ret 与 iret 的不同就是:用 ret 返回时,当前的 processor 还是当前的 state,使用 iret 返回时,将加载保存在 TSS 的 processor state。 也就是说,ret 返回 old-task 还是沿用 new-task 的 processor 状态。iret 返回到 old-task 使用的是原来保存在 old-task 的 TSS 的 processor 状态。
使用的 iret 的另一个功能: 当 Eflags.NT = 1 时:由于 iret 将返回到 TSS.link 的 TSS selector,进行一次任务切换。若这个 TSS selector 是刻意构造的别有用途的 TSS 时,可以进行一次别有用途的 task 切换。
7.1.3.4.1、 long mode 下的 TSS 切换情形
在 long mode 下已经不支持使用 TSS 来切换 task ,包括 TSS selector 和 task gate。使用 call / jmp TSS_selector 将产生 #GP 异常。
call 0x20:00000000 jmp 0x20:00000000
-----------------------------------
selector 0x20 是个 TSS descriptor 的 selector。
TSS descriptor 与 segment descriptor 的格式一致,不同的是 type,在 x86 和 long mode 的 compatibility 模式下有: available/busy 16-TSS 和 available/busy 32-TSS。
当成功将 TSS descriptor 加载到 TR 寄存器后,processor 将 available TSS 置为 busy TSS,在返回时将 busy TSS 置为 available TSS。
1、索引查找 TSS descriptor
TSS selector 在 GDT 里索引 TSS descriptor,其方法和 segment / gate dscriptor 的查找一致。
2、TSS 的 limit & type check
TSS segment 大小必须能容纳所有的 processor state,整个 TSS segment 的大小是 104 个字节,在加载 TSS descriptor 进入 TR 之前,processor 检查 TSS descriptor 中的 limit 必须大于或等于 67h(104 字节)。若否,则产生 #TS 异常。 processor 也检查 TSS descriptor 的 type 是否为 available 类型。若为 busy 类型,则产生 #GP 异常。
if (temp_descriptor.type == BUSY) { goto do_#GP_exception; } if (temp_descriptor.limit < 0x67) { goto do_#TS_exception; } |
所需的权限是:CPL <= DPL && RPL <= DPL
if (RPL <= DPL && CPL <= DPL) { /* 通过,允许访问 */ } else { /* 失败,#GP 异常 */ } |
在执行加载 TSS descriptor 到 TR 之前,processor 将执行一项很重要的工作:保存 old-task 的执行环境(processor 的状态)在当前的 TSS segment 中。 当前的 TSS segment 就是 old-task 的 TSS segment,在没加载 new-task 的 TSS 进入 TR 之前。
执行环境包括: (1)GPRs (2)segment registers (3)Eflags (4)LDTR 和 CR3 (5)EIP
5、加载 TSS descriptor
通过一系列的 processor 检查后,processor 加载 TSS descriptor 进入 TR 寄存器。
TR.selector = TSS_selector; TR.limit = temp_descriptor.limit; TR.base = temp_descriptor.base; TR.attribute = temp_descriptor; TSS_descriptor.type = BUSY_32; CR0.TS = 1; |
6、加载 processor state 信息
TSS descriptor 加载进 TR,processor 将加载新任务保存在 TSS 的 processor 状态信息。 包括: (1)GPRs 加载 (2)segment registers 加载 (3)Eflags 加载 (4)LDTR 和 CR3 加载
7、设置 EFLAGS.NT 和 TSS.link 域
使用 call 指令调用 TSS selector,processor 将置 Eflags.NT 为 1,表示当前的 task 被嵌套调用。而使用 jmp 指令则不会置 Eflags.NT 为 1。
if (opcode == CALL) { /* 使用 call 指令 */ Eflags.NT = 1; /* 置 NT 位为 1 */ TSS.link = old_TSS; /* link 域为 old task 的 TSS selector */ } |
7、执行新 task
同样,processor 加载新的 task EIP 进入 EIP 寄存器,执行新的 task 代码。新的 CS 被加载时,CPL 就是新的 CS.RPL。
8、返回 old-task
new-task 执行完毕通过 ret 或 iret 指令返回到 old-task。
在 caller 中:
... ... call 0x20:0x0000000 next: ... ... |
(1)使用 ret 指令返回 在 new-task 中使用 ret 指令返回和一般的 caller / callee 之间返回并无两样。程序将返回到 next 处。
(2)使用 iret 指令返回 使用 Eflags.NT 的目的是让 iret 来返回,当使用 iret 指令返回时,processor 将检查 Eflags.NT 是否为 1 ,若 Eflags.NT = 1 则表示当前 task 被嵌套。 程序将返回到 TSS.link 的 TSS selector 指向的 TSS descriptor,这个 TSS descriptor 就是 old-task 的 TSS descriptor,这里又进行另一次的任务切换到 old-task。
----------------------------------------------------------
使用 ret 与 iret 的不同就是:用 ret 返回时,当前的 processor 还是当前的 state,使用 iret 返回时,将加载保存在 TSS 的 processor state。 也就是说,ret 返回 old-task 还是沿用 new-task 的 processor 状态。iret 返回到 old-task 使用的是原来保存在 old-task 的 TSS 的 processor 状态。
使用的 iret 的另一个功能: 当 Eflags.NT = 1 时:由于 iret 将返回到 TSS.link 的 TSS selector,进行一次任务切换。若这个 TSS selector 是刻意构造的别有用途的 TSS 时,可以进行一次别有用途的 task 切换。
7.1.3.4.1、 long mode 下的 TSS 切换情形
在 long mode 下已经不支持使用 TSS 来切换 task ,包括 TSS selector 和 task gate。使用 call / jmp TSS_selector 将产生 #GP 异常。
相关文章推荐
- 使用 TSS selector 进行任务切换
- [转载]x86 的 TSS 任务切换机制
- 关于利用任务状态段TSS进行进程切换的一点说明
- 如何用TSS进行任务切换?我切换不成功:((内有汇编代码/as86)‹‹12
- 我用iret进行任务切换时,系统出现异常,来帮我看看是什么问题
- 使用NUnit在.Net编程中进行单元测试(转载)
- 使用NUnit在.Net编程中进行单元测试【转载】
- 使用VFS进行SFTP网络传输----转载
- 使用ApplicationDeployment 类以编程方面对ClickOnce程序进行更新 【转载】
- [5] 使用 TestLink 进行测试管理 『转载』
- 使用Ant进行项目构建之一:环境搭建 (转载)
- [转载]HOWTO 使用 vim 的 minibuf 来切换缓冲区
- [转载] 在Eclipse中使用SWT进行界面设计
- 转载:使用思维导图来进行超强记忆的12项原则
- 转载--Ajax学习---使用 JSON 进行数据传输
- 完美的使用 DISTINCT 和 ORDER BY 使用第三个字段进行排序(转载)
- 使用PowerDesigner进行代码生成(转载)
- 使用 JSF 架构进行设计(转载)
- (转载)在Eclipse中使用JUnit4进行单元测试(中级篇)
- 转载 使用ActiveReport for .net 进行报表开发