【我所認知的BIOS】—>SMM
(System management mode 学习笔记)
By LightSeed
2009-9-11
1、System management mode综述
这篇文章里面我主要是谈谈对IA32的了解,而且也纯粹是笔记而已,没有太多的组织语言。
1.1 什么是SMM
SMM是一种特殊用途的运行模式,他是用来处理影响整个系统功能的模式。影响整个系统功能的东东大致有:电源管理,系统硬件的控制等,或者也可用用这个模式来处理专有OEM designed代码。这种模式的运行只面向系统固件,而不是由软件来申请使用的。SMM的好处有很多后主要有,它提供了一个比较清楚的,容易孤立的处理的环境。这种模式对于系统或应用软件是透明的(我的理解呀,透明就是没有任何影响的意思^^,如果不正确还往高手不吝指教)。
1.2 SMM能够完成的事情
当SMM通过SMI而被调用(或者说进入更合适点吧),处理器就会保存处理器的当前状态(处理器的上下文,发觉英文翻译过来真别扭,还是建议大家看E文原版比较好。-_-<),然后切换到SMRAM中这个独立的运行环境中来。当CPU的模式是SMM的时候,CPU去执行SMI handler代码,来完成相应的操作。比如:
①关闭未使用的磁盘驱动器或显示器,执行专有的代码;
②将整个系统进入挂起状态(suspended state)。
③处理DOS下的USB等等相关的东东。
④相关的定时器的刷新(在DOS下有Go Stop grant,的选择它也是通过SMI来计时的。)
⑤等等,,,用SMI来处理的相关操作真是太多了。这里例举不完。
当在SMI处理程序已完成其规定的操作后,它会执行恢复(RSM)指令。这指令会使处理器重新加载处理器之前已经保存了的上下文,切换到之前的保护模式或实模式下,恢复(应该说是进入SMM之前的程序,继续执行此程序)去执行中断应用程序(ISR)或操作系统程序(program)或任务(task)。
1.3 SMM的特点
SMM的以下机制(也许翻译成“特点”更加有味道),使之对于应用程序和操作系统而言都是透明的:
①进入SMM的唯一途径是触发了SMI信号。
②处理器执行SMM代码的时候是在一个单独的地址空间(SMRAM)下完成的,并且这段地址空间在其他模式下是绝对不能被访问的(inaccessible)。
③在进入SMM的时候,处理器保存了中断程序(interrupted program)或者任务(task)的上下文。
④通常由OS来处理的所有中断,在进入SMM后都会被disabled。(当然这里说的是通常,其实在后面我们会进一步探讨,这些中断也是可以打开的,只是要考虑的情况就比较多,比较复杂罢了。)
⑤RSM指令只能在SMM里执行。(有人会问,那如果在其他模式下执行RSM,结果会怎样呢?笔者觉得你可以尝试一下,结果你自然就知道了。^^)
SMM是类似于实地址模式中,不存在任何权限级别或地址映射。一个SMM的程序可以处理多达4G内存且可以执行所有I / O和指令。
2、SMM和SMI
2.1 SYSTEM MANAGEMENT INTERRUPT (SMI)系统管理中断
进入SMM的唯一途径是产生了SMI信号。这个信号会通过处理器的SMI# pin产生,或者直接从APIC bus上收到了SMI信号。SMI是一个不可屏蔽的外部中断,SMI的运作独立于处理器的其他中断,异常处理机制,本地(local)APIC。SMI的优先级要高于NMI(不可屏蔽中断)和可屏蔽中断。SMM是不可重入的,这就是说,当处理器在SMM里的时候,SMI是被disabled了的。
2.2 SMM和其他模式之间的联系
2.2.1 SMM和其他模式之间的切换
图1显示了SMM与其他处理器运行模式(保护模式,实模式和虚拟- 8086)之间的切换过程。SMI信号产生后,不管处理器是实模式,还是保护模式,甚至虚拟8086模式都会导致处理器切换到SMM。执行指令(RSM)后,处理器总是回到进入到SMM模式之前的那个模式。
图1 处理器各种模式之间的切换示意图
2.2.2 进入SMM
当处理器收到一个SMI信号,它会等待所有指令就绪,同时等待所有保存完成。处理器会保存它的上下文到SMRAM(后面小节会介绍),然后进入SMM的,并开始执行SMI handler(处理程序)。
当处理器在进入SMM的时候,它会通知处理器的外部硬件说:“SMM已经开始了”(或者SMI pin会呈三态。或者SMIACT#会被访问等等,只是各种处理器的表达方式不太一样罢了,但是宗旨都是一样的。这和我们人的语言比较相像,虽然我们和外国都说不同的语言,但是我们的目的都是相互交流。)。
SMI的优先级高于调试异常(debug exceptions)和外部中断。因此,如果NMI,可屏蔽硬件中断,或出现调试指令,和SMI同时向CPU发送信号的时候,只有SMI会被处理。随后CPU不再会响应SMI请求,因为处理器已经在SMM里面了。当处理器已经在SMM里面的时候,第一个SMI请求将会被锁存,并且当处理器执行RSM指令退出SMM后,马上会响应这个SMI(就是再一次进入SMM。)。不过需要说的是,当处理器在SMM中时它只能,仅仅只能锁存一个SMI信号。
2.2.3 退出SMM
退出SMM的唯一方法是执行RSM指令。RSM指令只能是在SMI的处理程序中有效;如果处理器没有处于SMM,而试图执行RSM指令,那么这将会导致操作码异常。
RSM指令可以恢复处理器的上下文,这些上下文的信息被做成镜像存入到SMRAM里面了。RSM就是通过加载这个镜像,恢复处理器的寄存器从而恢复状态的。然后处理器返回SMIACK信息到系统总线,并把控制权交还给被中断的程序。
RSM指令成功完成后,处理器会通知外部硬件SMM已经退出。对于不同的CPU有不同的反应这个和进入SMM的时候是相对应的。
如果处理器检测到无效的状态信息保存在SMRAM,它将会进入关闭状态并生成一个特殊的总线周期表明它已经关闭。这种关闭状态只发生在下列情况下:
①在写CR4的时候,控制寄存器CR4的预留位被设置为1。这种错误一般来说是不会发生的,除非SMI处理程序的代码修改了SMRAM保存处理器上下文区域的保存状态,从而修改了CR4的保存所在的位置。不过值得注意的是,它所在的位置也是无法读取或修改其保存状态的。
②一个非法的位组合写入到控制寄存器CR0,特别是PG设置为1和PE设置为0,或NW为1和CD设置为0。
③(仅对于奔腾处理器和英特尔486处理器)当执行RSM的时候,如果存入SMBASE地址寄存器的地址不是32Kbyte边界对齐。这条限制不适用P6系列处理器。
在关闭状态,英特尔处理器停止执行指令,直到RESET#,或NMI#的INT#是有效。然而在关闭状态,奔腾系列处理器可以识别SMI#信号,P6系列的处理器和Intel486处理器却不行。英特尔的任何系列的CPU均不支持使用SMI#把CPU从关闭状态恢复。处理器在这种情况下的反应是不明确的。在奔腾4和后来处理器上,关闭将抑制INTR和A20M,但不会改变任何其他抑制。在这些处理器上,如果在SMM的处理程序中没有做任何动作去解除对NMI的抑制,那么NMI将被一直抑制。
3、SMRAM
3.1 SMRAM的综述
当处理器在SMM里的时候,处理器执行代码和存储数据都是在SMRAM空间里发生的。SMRAM空间映射到处理器的物理地址空间,它可多达4GBytes。处理器使用这个空间来保存处理器的上下文和存储SMI的处理程序代码,数据和堆栈。它也可以用来存储系统管理信息(如系统配置和关闭设备的具体信息)和OEM的具体信息。
默认SMRAM大小为64Kbytes,并且它的开始会有一个物理基地址(又叫做SMBASE)。当然这一切都是在物理内存上的。SMBASE的默认值是30000H(硬件复位就是这个值。)。处理器会到[SMBASE+8000H]处去找SMI处理程序的第一条指令。 [SMBASE + FE00H]至[SMBASE + FFFFH]存储着处理器的状态。(见后面3.2的详细说明。)
该系统的逻辑是需要解码的SMRAM最低限度物理地址范围,自[SMBASE + 8000H]至[SMBASE + FFFFH]。如果需要的话,处理器可以解码更大的地址空间。SMRAM大小最小可是32 KB(笔者:知道这里是怎么来的么?其实就是8000H~FFFFH)最大可以是 4 Gbytes。
SMRAM位置可以通过改变SMBASE值来改变(后面会说。)。应当指出,在一个多处理器的系统中,所有处理器初始时SMBASE值相同(30000H)。初始化软件必须按顺序让每个处理器进入SMM并改变其SMBASE,以便它不和其他的处理器重叠。(笔者:在这里只是这么说而已,其实在后面的探讨中,我们会发现也不是说一定不能重叠,在某些情况下是可以重叠的。)
实际SMRAM的物理位置,可以在系统内存中,或在一个单独的RAM存储器里。当处理器收到一个SMI后,它产生一个SMI确认信号。(这和之前说的是同一回事。)
系统的逻辑可以使用SMI确认或SMIACT#引脚有效,来解码SMRAM重定向并访问他们(如果需要)。如果一个单独的RAM内存用于SMRAM,当处理器没有在SMM的时候,系统的逻辑应提供能映射到系统内存的SMRAM可编程方法。当处理器进入SMM后,并执行SMI处理程序之前,上句提的机制将使能启动程序来初始化SMRAM空间(因为它是load SMI处理程序的地方),
3.1 SMRAM State Save Map
当IA - 32处理器最初进入SMM,它会写入自己的状态到SMRAM的相应区域。([SMBASE + 8000H + 7FFFH]~[SMBASE + 8000H +7E00H])。存在这些地方的有些寄存器是只读的,并不得修改(修改这些寄存器将导致不可预知的行为,比如正如之前说的CR4)。SMI处理程序不应依赖任何存储在这个区域的数据的值。图2是SMRAM的大致描述。
图2 SMRAM的用处
图3是寄存器被保存示意图
图3 寄存器被保持的示意图
需要说明的是后面的这些寄存器也被保存了,但是是不可读的,并且他们在退出SMM后同样会被恢复:
①控制寄存器CR4(在SMM中是,这个寄存器被全部清零。)
②段选择子的隐藏部分被保存到了CS,DS,ES,FS,GS,和SS中。
下面的这些状态是不会自动保存和恢复的。他们是
①调试寄存器DR0~DR3。
②在x87 FPU的寄存器。
③MTRRs。
④控制寄存器CR2。
⑤MSR(P6系列处理器和Pentium处理器)TR3~TR7(奔腾和Intel486处理器)。
⑥陷阱控制器的状态。
⑦The machine-check architecture registers(不知道该怎么翻译>.<)。
⑧APIC内部中断状态(ISR,IRR等)。
⑨microcode(微代码)更新状态。
3.2 SMI HANGDLER的执行环境
保存完处理器的当前上下文后,处理器开始初始化其核心寄存器的value,正如表1所示。
表1
在处理器进入SMM的时候,PE和PG在控制寄存器CR0的标志(flag)被清除,这使的处理器是在一个类似的实模式的环境中。不过他们之间又有不少的差异,如下:
①SMRAM的寻址可以从从0到 FFFFFFFFH(4 Gbytes)不等。(在SMM下,物理地址扩展(使能CR4的PAE)不支持。)
②正常的64Kbyte实模式段界限提高到4 Gbytes。(直观去理解其实就是进入了Big real mode的模式了或者说Flat mode。)
③默认的操作数和地址大小为16位,这就限制了SMRAM地址空间的1Mbyte实地址模式界限。然而,操作数大小和地址大小可以通过覆盖前缀来访问超过1Mbyte的地址空间。(笔者:我的理解起是就是Big real mode的原理啦。只是这里表达的比较含蓄不好理解而已,起是就是指段选择子的隐藏部分,这是确定段基地址的。)
④如果使用32位操作数大小覆盖前缀,那么可以用近jmp或者call跳向可向4 GByte地址空间的任何地方。(CS:EIP去访问,理解其原理哦。)
⑤数据和堆栈可以被放在4 GByte的地址空间的任何地方。但如果他们被放在了1Mbyte以上的地方,那么他们只能被32位地址的寻址方式访问。同代码段一样,数据或堆栈段基址不能超过20位。(笔者:其实我想一般都会设成是0,这样比较方便访问和计算地址,Big real mode不也就是这样么?)
段寄存器CS的值是自动设置为30000