x86 - Disabling/Enabling interrupts on x86 architectures
问题描述
I am using NetBSD 5.1 for x86 systems. While studying some driver related code, I see that we use splraise and spllower to block or allow interrupts. I searched some of the mechanisms on internet to understand how these mechanisms work in reality. Did not get any real info on that.
When I disassembled I got the mechanism but still do not understand how all these assembly instruction yield me the result. I know x86 instruction individually, but not how the whole stuff works in its entirety.
Need your help in understanding its principles for x86 system. I understand that we need to disable Interrupt Enable (IE) bit, but this assembly seems to be doing more than just this work. Need help.
(gdb) x/50i splraise
0xc0100d40: mov 0x4(%esp),%edx
0xc0100d44: mov %fs:0x214,%eax
0xc0100d4a: cmp %edx,%eax
0xc0100d4c: ja 0xc0100d55
0xc0100d4e: mov %edx,%fs:0x214
0xc0100d55: ret
0xc0100d56: lea 0x0(%esi),%esi
0xc0100d59: lea 0x0(%edi,%eiz,1),%edi
(gdb) p spllower
$38 = {<text variable, no debug info>} 0xc0100d60
0xc0100d60: mov 0x4(%esp),%ecx
0xc0100d64: mov %fs:0x214,%edx
0xc0100d6b: cmp %edx,%ecx
0xc0100d6d: push %ebx
0xc0100d6e: jae,pn 0xc0100d8f
0xc0100d71: mov %fs:0x210,%eax
0xc0100d77: test %eax,%fs:0x244(,%ecx,4)
0xc0100d7f: mov %eax,%ebx
0xc0100d81: jne,pn 0xc0100d91
0xc0100d84: cmpxchg8b %fs:0x210
0xc0100d8c: jne,pn 0xc0100d71
0xc0100d8f: pop %ebx
0xc0100d90: ret
0xc0100d91: pop %ebx
0xc0100d92: jmp 0xc0100df0
0xc0100d97: mov %esi,%esi
0xc0100d99: lea 0x0(%edi,%eiz,1),%edi
0xc0100da0: mov 0x4(%esp),%ecx
0xc0100da4: mov %fs:0x214,%edx
0xc0100dab: cmp %edx,%ecx
0xc0100dad: push %ebx
0xc0100dae: jae,pn 0xc0100dcf
0xc0100db1: mov %fs:0x210,%eax
0xc0100db7: test %eax,%fs:0x244(,%ecx,4)
0xc0100dbf: mov %eax,%ebx
0xc0100dc1: jne,pn 0xc0100dd1
0xc0100dc4: cmpxchg8b %fs:0x210
0xc0100dcc: jne,pn 0xc0100db1
0xc0100dcf: pop %ebx
0xc0100dd0: ret
0xc0100dd1: pop %ebx
0xc0100dd2: jmp 0xc0100df0
0xc0100dd7: mov %esi,%esi
0xc0100dd9: lea 0x0(%edi,%eiz,1),%edi
0xc0100de0: nop
0xc0100de1: jmp 0xc0100df0
The code seems to be using a helper function cx8_spllower starting at address 0xc0100da0.
解决方案
[E|R]FLAGS.IE
使用 eg清除CLI
会禁用 CPU 上的所有(可屏蔽)中断。出于多种原因,它可能是不可取的(例如,您希望允许一些,或者您可能不希望CLI
在 VM 中进行虚拟化开销)。
实现目标的另一种方法是告诉中断控制器(旧的 8259 PIC 或 Pentium APIC/IOAPIC)您不想为优先级低于某个级别的中断提供服务。为此,您需要与控制器进行通信,这本身可能会产生额外的开销(与真实和虚拟硬件的通信都很慢)。
后者的一种变体是将当前中断级别/优先级保留在一个变量中并让中断进入,但仅真正服务于那些级别/优先级不低于该变量中当前中断的那些。那些未服务的将被标记为待处理,并且当当前级别/优先级下降到足够低时将得到完全服务。这就是为什么splraise()
比spllower()
.
此级别/优先级变量似乎在不同位置和代码版本中的命名不同:(CPL
不要与 CPU 的当前特权级别混淆)、SPL
(?) ILEVEL
、。
这是我目前对实现的有限理解。还有更多细节。
以下是我找到并用于答案的一些线索:
推荐阅读
- php - 以 HTML 和 PHP 显示的会话开始时间
- ionic3 - Ionic 3 onNotificationClicked() 不订阅 Cordova 地理围栏插件
- java - this.getContext() 可能为空,在使用自定义适配器的片段中
- apache-flink - Flink 可查询状态错误
- security - 执行 npm audit 的建议后没有任何变化
- python - 如何在一次热编码 sklearn 后保留列名?
- markdown - 我可以在降价中重用内容(单一来源)吗?
- tfs - 在 TFS 2018 中找不到配置功能向导
- asp.net-mvc - 在插入实体框架中排除模型的属性
- android - Android 设备监视器不显示任何进程