from http://blog.csdn.net/huangkangying/article/details/8143641
SMM系列(1)-- SMM基本概念
SMM的定义:SMM, System Management Mode, 即系统管理模式。在intel 386SL, intel486SL引入的一种特殊的操作模式,在这种模式下,可以执行高级电源管理,硬件控制和运行OEM代码。它对于操作系统而言是完全透明的,也就是说操作系统并不知道CPU什么时候会进入和退出SMM。
基本术语:
SMM: System Management Mode
SMI: System Management Interrupt
SMRAM: System Management RAM
C-SEG: Compatibility Segment, 在Legacy Mode下,0xA0000~0xC0000这段地址空间被用作SMRAM和VGA Frame Buffer
H-SEG: High Segment
T-SEG: 用作4GB以下的SMRAM, 可以提供扩展的SMRAM空间
SMM的特权级:
SMM拥有最高的特权等级,因此在SMM下可以执行各种特权指令和IO操作。进入SMM的方式是当收到SMI(System Management Interrupt)时,而执行RSM指令则可以退出SMM。
SMM也其模式的切换:
关于SMI:
SMI是进入SMM的唯一途径,SMI可以由处理器的SMI#管脚有效或者是APIC(Advanced Program Interface Controller)总线的SMI信息。 它是不可屏蔽的中断,独立于其它形式的中断。
SMI的中断优先级是3, 而debug breakpoint是4, NMI是5, 当然最高的还是Reset, 它的中断优先级是1
关于SMRAM:
由于SMM的特殊性,所以进入SMM后的程序是运行在SMRAM中的,而不是随便找一段内存就可以运行。这当然是出于安全的考虑,毕竟SMM有最高的优先级,如果在哪儿都可以运行,那么其它的程序改动了内存里的一点东西,也会影响到SMM,如果这个改动是恶意的,那后果就不堪设想了。
由上图可以看出SMRAM的一个大致结构了,SMRAM的大小不是无限大的,它最初只有64KB,其起始地址是SMBASE(这个值保存在一个专门的寄存器中),在SMBASE+0x8000H处开始存放的是SMI的中断处理程序。而在SMRAM的高地址处存放着处理器进入SMM时的状态信息,这些信息在处理器退出SMM时会被恢复到处理器中。
SMBASE开机时的默认值是0x30000H,一般BIOS会把它重定位到0xA0000H处。
SMM系列(2)-- SMI中断运行环境
保存现场在上一节“SMM的基本概念”中已经讲到,在进入SMI中断处理程序之时,会将处理器的状态信息保存到SMRAM中,然后再退出中断处理函数时恢复现场。
运行环境的初始化
在保存完现场后,紧接着就会对寄存器的信息做一些相应的修改,这就是初始化SMI handler的运行环境。
其实主要是设置一些寄存器的初值:
通用寄存器对程序没有什么影响,所以不用做初始化。
EFLAGS初始化为0x2H,即所有的标志清零,bit1恒为1。
EIP为0x8000H, 即CS:[EIP]处刚好为SMI handler的第一条指令。
CR0的PE(保护),EM, TS, PG(分页)初清零。处理器工作于Big-Real-Mode下。这里与Real Mode最大的区别是,其地址偏移可以
到达32位,因此可以访问4GB的内存空间。
CR4被全部清零,全部扩展功能被取消
DR7(Bit10恒为1),禁止断点。
地址模式
刚才讲到,在SMI Handler下,处理器工作于Big-Real-Mode下,PE, PG标志被清除了,线性地址被当作物理地址来对待。
在SMM中,操作数默认的位数是16 bits,因此在实模式下,SMRAM的最大访问空间为1MB,但我们可以通过override prefixes的方式
访问到超过1MB的地址空间。具体解析如下:
在实模式下,段地址寄存器中的值不是用来指向一个段描述符表,而是直接用来参于运算。
比如:CS=0x1000, Offset=0xFFFF, 那么我们实际得到的物理地址是:0x1FFFF。
但是如果: CS=0xFFFF, Offset=0xFFFF,那么我们得到:
(0xFFFF << 4) + 0xFFFF = 0x10FFEF
这个值在实模式下是超过了1MB的,超出的部分被截掉,变成0xFFEF
所以,我们有必要先来了解一下Override Prefix了。
由Intel的spec中我们可以看到Instruction Prefix是可选的。只有操作码部分是必须的。
不同的prefix可以完成不同的附加功能。
比如:
2EH : CS segment override prefix.
36H : SS segment override prefix.
3EH : DS segment override prefix.
26H : ES segment override prefix.
64H : FS segment override prefix.
65H : GS segment override prefix.
其中:
67H: Address - Size Override Prefix
这个prefix可以用来完成16 bit 和 32 bit 之间的切换。
具体操作时我们可以使用32位寄存器间接寻址来做:
SMM系列(3)-- SMM的中断处理以及SMBASE重定向
SMM的中断处理当处理器进入SMM时,所有的硬件中断都将被禁止。
IF标识被清零,禁用可屏蔽中断。
TF标识被清零,禁用单步中断。
DR7被清零,禁用断点中断。
另外NMI, SMI, A20M也会被block.
应该记住的一点是,SMM是不可重入的。但是,SMM会锁存进入后的第一个SMI或NMI, 并且在退出SMM后的第一条指令前执行。
软中断在SMM中是没有被屏蔽的,如果要开启调试中断,则置位DR0-3, DR7。
但是在使用中断之前,应该在SMM中先初始化好中断向量表,这个表应该和实模式中的一样。
中断向量表中的每个中断4个字节,包含CS和IP。但由于SMM中,CS和IP都是16位的,这样一来就无法访问到高于1MB的地址
空间。如果返回地址高于1MB,那么它的CS和IP都会被截断,现有的解决办法是在返回时修改返回地址。但最好还是不要在SMM
中使用中断。
退出SMM
退出SMM的唯一方法就是执行RSM指令。在退出时,处理器会被SMRAM中保存的中断上下文恢复到相应的寄存器中去,并且对
当前的状态做检查,如果检测到无效状态,如:CR4的保留位置1,CR0状态冲突,则系统会进入到shutdown状态。这shutdown
状态下,系统不再响应SMI#信号,一直保持这个状态到RESET#, INIT#或NMI#信号出现。
关于退出时的特殊功能:
在退出SMM状态时,有三种特殊功能:
- Auto Halt Restart
- I/O instruction Restart
- SMBASE relocation
Auto Halt Restart
如图所示,进入SMM时检查当前是否是Halt状态设置Auto Halt Restart标志位。退出SMM时检查该位的状态。
具体的行为如下图所示:
I/O Instruction Restart
在介绍i/o instruction restart 这个概念之前,先了解一个概念,SMM版本标识域。
这个标识域位于SMRAM偏移0x7EFC这个位置上,SMM Revision Identifier主要用于标识SMM的版本号。
而第16位和17位则分别是I/O instruction restart 和 SMBASE relocation的标识位。只有置位这些位才能使用
特殊功能。
对于I/O Instruction Restart, 它主要是用于这样一种场情之下,当处理器要对一个掉电的设备进行I/O操作时,它
会先进入SMM使能这个设备,当这个设备正常工作后,处理器退出SMM,但它需要进行前面没有执行的I/O操作。
这时就需要I/O instruction restart。
SMBASE relocation
SMBASE重定向,就是要将SMRAM改变到另外一个地方。比如说1MB以上。这个功能主要是通过修改SMBASE 域来实现的。
当进入SMM这前,CPU从SMBASE寄存器中取出SMBASE的值。用这个值找到SMI handler。在SMI handler中,SMBASE被保存在SMBASE域中,程序可以修改SMBASE域的值。在退出SMM时, 处理器会将SMBASE域中的值恢复到SMBASE寄存器中,从而实现relocation。