SMM是什么
SMM全称System Manage Mode。
从名字也可以大致看出,它是x86平台CPU的一种模式,该模式用来做系统管理的操作,具体来说,可以参考《64-ia-32-architectures-software-developer-system-programming-manual.pdf》中的说明:
以上也只是Intel建议的在SMM下应该做的事情,而实际用来做什么,就只能看你写的具体代码了。
总览
下面简单说明SMM的基本特性:
1. 通常只在BIOS下实现,OS基本不需要特别关注SMM;
2. SMM的处理代码和数据在特定的内存中,这段内存被称为SMRAM;
3. 要进入SMM模式,只能通过SMI(System Manager Interrupt,系统管理中断),SMI可以通过SMI#引脚和APIC中断来产生,且SMI是不可屏蔽的中断;
4. 要退出SMM,只能通过RSM指令(RSM只能在SMM中用):
5. 进入SMM之后,普通的中断都被屏蔽掉了;
6. 进入SMM模式之后执行环境就到了实模式下,分页也被Disable掉了(CR0.PE=0,CR0.PG=0),此时内存访问最大到4G;
7. SMM是不可重入的,意思是当你在SMM模式之后就不会再接收SMI了;
进入和退出SMM
先贴一张CPU各个模式之间的转换:
前面已经说过,当CPU接收到SMI中断或者SMI#引脚被触发,则CPU开始处理SMI,具体过程如下:
1. 等待所有已触发的指令都执行完毕;
2. 将当前执行环境保存到SMRAM中;
3. CPU发送信号给外部的电路,告知有SMI处理程序在执行;
4. 进入SMM并进行相应的CPU级别的初始化;这里有一个很重要的步骤,即初始化SMM下的系统执行环境,简单的说就是给一大堆寄存器赋值,如下所示:
5. 开始执行SMI处理程序。
当在SMI句柄中使用了RSM指令,CPU就开始推出SMM,具体过程如下:
1. CPU从SMRAM中读取之前存入到进入SMM之前的执行环境;
2. CPU发送信号告知要退出SMM模式了;
3. 退出SMM回到之前被中断的程序。
SMRAM
SMRAM的全称是System Manager RAM,前面的内容已经提到过它,关于SMRAM的用处的所有说明如下:
1. 存放进入SMM之前的系统执行环境;
2. 存放SMI处理程序代码和数据;
3. 存放系统配置等信息;
4. 存放OEM信息;
由于SMM下CPU只能访问4G以下的空间,所以SMRAM也在4G以下。
SMRAM的基地址被称为SMBASE,它有一个默认值是30000H,SMRAM的大小默认是64K;无论是SMRAM的基地址还是大小,都是可以重新分配的。
SMRAM内部被分成几个不同的部分,用来完成不同的功能,比如存放代码,比如存放状态,等等,如下图所示:
其中状态存放的位置是从上往下扩展的,以32位系统为例(32位和64位执行环境是有差异的,所以对应的寄存器个数也有差异),它存放了如下的内容:
上表中的第三列表示SMI处理程序是否可以写该寄存器,如果可写且被写了,那么退出SMM模式之后的执行环境实际上也就被修改了。
从上表中还可以看到一些问题,比如CR4寄存器没有被保存下来,实际上在前面已经说过进入到SMM之后CR4的PE和PG位会被清零(实际上是整个寄存器都被清零了)。虽然CR4没有被保存到SMRAM中,但是当CPU退出SMM时,CR4的值还是会恢复进入SMM之前的值。像这样的值还有不少,这里不一一说明。
总之没有在上表中值,在SMM下读不了,这里不是说CR4等寄存器的值读不到,而只是进入SMM之前的CR4等寄存器的值无法获取。
最后关于SMRAM的重定位,可以通过上表中的某个寄存器来确定,即SMBASE:
要使重定位有效,大致的流程是这样的:
1. 进入到SMM中(此时使用的SMBASE还是30000H);
2. 设置SMBASE Filed的值(从上面的表中可看到该值是可写的);
3. 通过RSM退出SMM模式,当退出SMM模式时,SMBASE Filed中的值会被写入到CPU内部的存放SMBASE的寄存器;
4. 此后如果再次进入SMM,则使用的基地址就是新设置的SMBASE值了。
关于如何设置SMRAM的大小,没有找到具体的说明......
以上是对SMM模式的简单说明。
实际上还有很多的东西没有提到,比如SMM和VM的关系,SMM和多核的关系,等等。
最重要的是SMM实际如何使用也没有讲到,这些等有条件的话再补上。