Intel's System Management Mode

by Robert R. Collins

It might be tempting to assume that System Management Mode (SMM) on Intel's SL-enhanced microprocessors was nothing more than a marketing gimmick to sell a new feature that had already existed for ten years. A quick comparison of SMM and ICE mode (or the comparison of the undocumented instruction LOADALL to SMM's RSM instruction) could lead you to believe that SMM was nothing more than a legitimized ICE mode - and that RSM was nothing more than a documented form of the LOADALL instruction. However, as I have discovered, SMM was not a marketing gimmick, even though the similarities are striking. This column will be the first in a series discussing System Management Mode. This article will provide a prehistory of SMM oy comparing it to ICE mode.

In-Circuit Emulation: Prehistory of SMM

An in-circuit emulator (ICE) is used for low- level debugging. When an ICE is attached to a target system, a program may run at full speed, may be stopped and restarted, and can be single-stepped. An ICE has the ability to stop and restart any program from any execution mode - real, protected, and v86. An ICE even has the ability to debug a ROM BIOS before any software has been loaded, and set breakpoints anywhere in the ROM BIOS. The ICE has abilities that can't be achieved with any software-based debuggers. When program execution has been stopped, the ICE provides complete visibility of the microprocessor internals, undocumented descriptor structures (see http://www.x86.org/Productivity/DescriptorCache.html ), descriptor tables, paging tables, registers, memory, and more. An ICE is the ultimate debugger, and it carries a hefty $50,000 price tag.

There are two ways to enter ICE mode: internally and externally triggered. Internally, ICE mode is entered as the result of any debug breakpoint event. These events include debug register breakpoints, a TSS trap, the Trap Flag set, a write to any debug register (while DR7.GD=1), and the execution of the undocumented instruction ICEBP (see http://www.x86.org/secrets/opcodes/ICEBP.html ). All of these events normally result in a debug exception (Exception 01). When the ICE is connected, they may cause the debug exception, or they cause the ICE to halt emulation. This behavior is governed by an undocumented bit in DR7 (DR7.IR). (See Figure 1 for the location of DR7.IR, or http://www.x86.org/secrets/DR7.html for a description of all undocumented bits in DR7.) When DR7.IR=O, any debug exception will cause the INT-01 handler to be invoked. When DR7.IR=1, all debug exceptions will be redirected to the ICE; the ICE will halt execution and enter ICE mode. DR7.IR is automatically set by the ICE when debug breakpoints are specified, therefore no extra effort is needed to set this bit.

Figure 1 - DR7 Register Contents
31..30 29..28 27..26 25..24 23..22 21..20 19..18 17..16 15 14 13 12 11 10 09 08 07 06 05 04 03 02 01 00
Len
3
R/W
3
Len
2
R/W
2
Len
1
R/W
1
Len
0
R/W
0
TT TB GD IR Rsv Rsv GE LE G3 L3 G2 L2 G1 L1 G0 L0

ICE mode is also triggered externally by asserting an undocumented microprocessor pin. On the standard Intel 80386 DX, asserting the undocumented pin at location B6 will cause the microprocessor to halt emulation and enter ICE mode. Typically, the ICE asserts this pin in response to some type of bus event. A bus event is an event that can only be observed from analyzing the microprocessor pins (the bus). The ICE can set breakpoints for many types of bus events, including, but not limited to:

  • No bus activity for an extended period of time.
  • A prefetch at a specific address.
  • An I/O operation of a specified size (byte, word, dword) at a specified address.
  • A special microprocessor cycle (HALT, SHUTDOWN, INTERRUPT ACKNOWLEDGE, and so on).

Once the bus event occurs, the ICE hardware signals the microprocessor by asserting the undocumented "ICEBP" pin, which then causes the microprocessor to enter ICE mode.

Upon entrance to ICE mode, the microprocessor saves its entire state to an area of memory isolated from normal system memory. It is essential that enough of the processor state is saved to guarantee that a program can resume execution after leaving ICE mode. For this reason, the saved microprocessor state includes all program-visible registers (like EAX, EBX, CS, DS, and so on), internal data structures that can't be accessed by any x86 program (the descriptor cache registers), and system descriptors (GDT, IDT, LDT, and TR descriptors). Restoring all of these values is enough to guarantee that the microprocessor can be halted and restarted from any operating mode.

Hardware support of ICE mode is achieved through the implementation and use of a few undocumented microprocessor pins. ICE-mode memory isolation is achieved through the use of a few of these undocumented pins in cooperation with chipset support. Once in ICE mode, an output pin located at position C7 on the standard 80386 DX processor is asserted - much like the SMIACT# pin on SL-enhanced processors. Further memory isolation is achieved by having separate ADS#- and READY# pins for ICE mode. I termed these pins "IADS" and "IRDY" (my notes don't indicate whether they are active-high or active-low); they are located at positions E13 and F13, respectively. One effect of having separate ADS#- and READY# pins in ICE mode is bus-cycle transparency to a logic analyzer. When in ICE mode, the normal ADS# and READY# pins aren't asserted unless an ICE command is given to view memory or I/O. All code fetches and memory cycles to the supporting ICE program are performed using the IADS and IRDY pins. The logic analyzer doesn't recognize any bus cycles using these pins. Therefore, the microprocessor seems to disappear from the logic-analyzer trace when executing in ICE mode.

Once ICE mode begins, the processor immediately begins execution of the ICE- mode kernel. The microprocessor is operating in real mode, but all segment limits are set to 4 GB, and all segments are read/writable. The ICE stays in this mode, executing its own control software, until you command it to return to normal program execution. Once commanded, the ICE executes the undocumented LOAD- ALL instruction to restore the entire micro- processor state. (See http://www.x86.org/articles/loadall for a description of the LOADALL instruction.) LOADALL reads the table that was written at the entrance to ICE mode and restores the microprocessor to the exact state contained therein. Upon completion, the entire microprocessor state has been redefined and execution continues at the point indicated by the LOADALL table.

System Management Mode Overview

System Management Mode (SMM) is intended to be used for advanced power-management features and other operating-system-independent functions. The chipset is programmed to recognize many types of events and timeouts. When such an event occurs, the chipset asserts the SMI# input pin. At the next instruction boundary, the microprocessor saves its entire state and enters SMM.

As the microprocessor enters SMM, it asserts an output pin, SMIACT#. This pin serves notice to the chipset that the microprocessor is entering SMM. SMI# can be asserted at any time, during any process operating mode, except from within SMM itself. The chipset recognizes SMIACT# and redirects all subsequent memory cycles to a protected area of memory, reserved specifically for SMM. Immediately after receiving the SMI# input and asserting the SMIACT# output, the microprocessor begins to save its entire internal state to this protected memory area.

After the microprocessor state has been stored to memory, the special SMM handler begins to execute. The processor is in real mode, all segments have 4-GB limits, and all segments are read/writable. After the SMM code has executed, it's time to return to the previous operating environment. The program executes the RSM instruction to exit SMM. RSM reads the microprocessor state data from the state save map, and restores the entire microprocessor state. Like LOADALL, RSM performs virtually no checks on the data in the state save map. Upon completion of RSM, the entire microprocessor state has been redefined, and the previous program resumes execution right where it left off.

Comparing SMM and ICE Mode

When comparing ICE mode to System Management Mode, you could easily conclude that SMM was derived from ICE mode because their similarities are striking. Certainly, they have more similarities than differences. In reality, SMM appears to be both a subset and a superset of ICE mode. For the purposes of this comparison, I'll contrast 80386 ICE mode with Pentium SMM. Consider the following similarities:

  • Both modes use a microprocessor input pin to trigger invocation. On the 80386 DX, this undocumented pin is located at position B6. On SL-enhanced Intel microprocessors, this pin is named SMI#.
  • Both modes use a microprocessor output pin to indicate when in ICE or SMM mode. On the 80386 DX, this undocumented pin is located at position C7. On SL-enhanced Intel microprocessors, this pin is named SMIACT#.
  • Both modes may be entered from any processor mode at any time by asserting the applicable input pin.
  • Both modes have the ability to resume to any processor mode and to any CPL upon completion.
  • Both modes save the entire microprocessor state to a state-save map upon entrance.
  • The state-save map area is in a protected memory space, isolated from user memory.
  • Both modes restore the entire microprocessor state from the state-save map. Neither LOADALL nor the SMM- equivalent RSM instruction sanity check the data in the state save map upon resumption. On the 386 or 486, LOADALL doesn't validate any of the microprocessor state from the state-save data. Therefore it is possible to use LOADALL to perform microprocessor tricks that would otherwise be illegal. For example, you could enable paging, yet remain in real mode. SMM uses the RSM instruction to restore the microprocessor state. RSM does perform some minor sanity checks (like the real-mode paging check), but otherwise does little. Using either instruction, it is possible to change the access rights of segment descriptors to illegal values - like making the code segment writable in protected mode or setting the GDT access rights (which in theory don't exist) to Not-Present.
  • The ICE-mode LOADALL instruction on the 486 and the RSM instruction on all SL-enhanced microprocessors are disabled when operating outside of their respective operating modes. Both instructions generate an invalid opcode exception when executed outside of ICE mode and SMM, respectively.
  • The order in which the microprocessor state information is written is exactly the same, but the direction is different. ICE mode writes data from bottom to top, and SMM writes data from top to bottom (like a stack).
  • Both modes begin execution in real mode, with all segments as read/writable and having 4-GB limits.
  • Both modes begin execution of a special handler after the microprocessor state is saved.
  • The most compelling similarity of all is the state-save map. When viewed side-by-side, the state save map of ICE mode and SMM look virtually identical. Figure 2 compares the two state-save maps.
Figure 2 - Comparison of LOADALL and SMM State Save Map.
LOADALL Table SMM State Save Map
Offset Description Description Saved
Offset
SMM
State
Map
Offset
000 CR0 CR0 000 7FFC
004 EFLAGS CR3
EFLAGS
004
008
7FF8
7FF4
008 EIP EIP 00C 7FF0
00C EDI EDI 010 7FEC
010 ESI ESI 014 7FE8
014 EBP EBP 018 7FE4
018 ESP ESP 01C 7FE0
01C EBX EBX 020 7FDC
020 EDX EDX 024 7FD8
024 ECX ECX 028 7FD4
028 EAX EAX 02C 7FD0
02C DR6 DR6 030 7FCC
030 DR7 DR7 034 7FC8
034 TR TR 038 7FC4
038 LDT Register LDT Register 03C 7FC0
03C GS Register GS Register 040 7FBC
040 FS Register FS Register 044 7FB8
044 DS Register DS Register 048 7FB4
048 SS Register SS Register 04C 7FB0
04C CS Register CS Register 050 7FAC
050 ES Register ES Register 054 7FA8
054 TSS Descriptor Cache (12-bytes)* Reserved #1 (12-bytes) 058 7FA4
060 IDT Descriptor Cache (12-bytes)* Reserved #2 (12-bytes) 064 7F98
06C GDT Descriptor Cache (12-bytes)* Reserved #3 (12-bytes) 070 7F8C
078 LDT Descriptor Cache (12-bytes)* Reserved #4 (12-bytes) 07C 7F80
084 GS Descriptor Cache (12-bytes)* Reserved #5 (12-bytes) 088 7F74
090 FS Descriptor Cache (12-bytes)* Reserved #6 (12-bytes) 094 7F68
09C DS Descriptor Cache (12-bytes)* Reserved #7 (12-bytes) 0A0 7F5C
0A8 SS Descriptor Cache (12-bytes)* Reserved #8 (12-bytes) 0AC 7F50
0B4 CS Descriptor Cache (12-bytes)* Reserved #9 (12-bytes) 0B8 7F44
0C0 ES Descriptor Cache (12-bytes)* Reserved #10 (12-bytes) 0C4 7F38
    Unwritten #1 (4-bytes) 0D0 7F2C
    Reserved DWORD 0D4 7F28
    Reserved WORD 0D8 7F26
    Reserved WORD 0DA 7F24
    Unwritten #2 (16-bytes) 0DC 7F20
    Reserved DWORD 0EC 7F10
    Reserved DWORD 0F0 7F0C
    Reserved DWORD 0F4 7F08
    Reserved DWORD 0F8 7F04
    AutoHALT 0FC 7F02
    I/O Reserart 0FE 7F00
    SMM Revision Identifier 100 7EFC
    SMM Base Address 104 7EF8
* 4-bytes Access Rights, 4-bytes Base Addess, 4-bytes Limit.

There are also differences between the two modes:

  • Even though the order in which the microprocessor saves its state information is the same between ICE mode and SMM, they are stored in opposite directions. LOADALL uses ES:EDI as a pointer to the beginning of the LOADALL table and stores the contents in an upward direction. The SMM RSM instruction uses the internal SMBASE register as a pointer to the beginning of the SMM state-save map, and stores the contents in a downward direction - much like stack operations.
  • SMM can't be triggered internally by a debug event, or any microprocessor instruction (like ICEBP).
  • SMM can't transfer data between user memory and protected memory. The ICE does have this ability. The ICE uses the undocumented instruction UMOV (see http://www.x86.org/secrets/opcodes/UMOV.html for a description of UMOV) to transfer data between user memory and ICE memory. This instruction has been removed on all current Intel processors.
  • When SMM is entered from the HALT state, the SMM handler is notified of this condition from a flag in the state-save map. The SMM handler can modify this flag, which directs the RSM instruction to reenter the HALT state or continue execution after the HALT instruction. ICE mode has no analogous facility.
  • When SMM is entered as the result of an I/O instruction, the SMM handler can set a flag in the state-save map, which directs the RSM instruction to restart the I/O instruction. This mechanism even works to restart a string I/O instruction from the beginning of the string operation (REP OUTSB, for example). ICE mode has no analogous facility.
  • SMM has the ability to relocate its protected memory space. The SMBASE slot in the state save map may be modified. This value is read during the RSM instruction. When SMM is next entered, the SMRAM is located at this new address. ICE mode has no analogous facility.
  • ICE mode has changed over time, and no longer resembles SMM.
  • When the ICE is attached, the microprocessor emits branch-trace messages to help the ICE to reconstruct the execution traces. SMM has no analogous facility. (However, branch-trace messages may be enabled through another means on the Pentium Processor.)

Conclusions

When considering the reason for creating SMM, it's hard to ignore the slight differences between it and ICE mode. In many cases, it might seem that the differences represent an evolutionary change in ICE mode, and not a change in functional intentions. This might tend to reinforce the belief that SMM was a marketing gimmick, but such an assumption would be incorrect. Intel conceived of SMM as a means to perform functions, like power management or hardware emulation, independent of the current operating mode. Prior to SMM, it was impossible to perform such functions in a way that was independent of the operating system environment, or the operating mode of the microprocessor. SMM was seen as a means to address these problems. Once the SMM designers completed defining their requirements, they found that most of the microcode and hardware already existed in the microprocessor - as ICE mode. Naturally, they decided to leverage the existing facilities. This explains why SMM closely resembles ICE mode.

Others tried to follow Intel's lead. The IBM Blue Lightning and AMD 486 both introduced SMM. In their cases, however, they actually used their ICE mode and called it SMM. This design decision limited their abilities to debug SMM with an ICE. They could not use an ICE during SMM - whereas Intel could (as Intel ICE mode was still independent of SMM). AMD's use of the ICE microcode as SMM also lead to the SMM/ICE lawsuit from Intel - which Intel eventually won.

ICE mode and SMM are still evolving. ICE mode is now achieved through an entirely different mechanism. The new ICE mode is implemented via a special debug port and is now called probe mode (see http://www.x86.org/articles/probemd/ProbeMode.html for an overview of probe mode). The new ICE mode doesn't resemble SMM at all, doesn't use a state save map, or even execute any code of its own. SMM is also evolving. To address the limitations still inherent in SMM, Intel, Microsoft, and Toshiba are defining the successor to SMM and APM (Advanced Power Management). The new standard - ACPI (Advanced Configuration and Power Interface) - will address the current limitations, and result in a new software interface and modification to the current SMM (see http://www.teleport.com/-acpi/ for a description of ACPI).

In my next column, I will discuss many of the details of the Pentium SMM implementation and its associated secrets. You will learn what all of those "Reserved" areas in the state-save map are used for, and how the I/O restart feature can restart a string operation (REP OUTSB) from its beginning. In another future column, I'll discuss the caveats of SMM and how to avoid making mistakes when writing your own SMM handler.


Back to Dr. Dobb's Undocumented Corner home page