What is System Management Mode?

System Management Mode (SMM) is the highest-privilege execution mode on an x86-64 processor which is a special-purpose operating mode. It can only be entered by a non-maskable, non-preemptible hardware interrupt (the System Management Interrupt, or SMI) that the processor services between instruction boundaries and that is completely invisible to the operating system and hypervisor.

When an SMI is asserted, every logical processor in the platform is interrupted, saves its architectural state into a protected memory region (SMRAM),then switches to a separate operating environment defined by a new address space. The system management software (SMI handler) starts execution in that environment. The critical code and data of the SMI handler reside in a physical memory region (SMRAM) within that address space. When the firmware is done, each processor executes the RSM instruction, which atomically restores the saved state and resumes the interrupted instruction stream. Neither the OS nor the hypervisor can observe, intercept, or prevent this.

Because of that power, SMM is simultaneously:

  • The platform's mechanism for hardware errata workarounds, RAS/error handling, thermal and power management, legacy device emulation, and authenticated variable/flash storage;

AND

  • The platform's most valuable attack surface, since code executing in SMM can read and write all of physical memory, all MSRs, and all I/O.

The latest platform initialization specification (UEFI Forum) Volume 4 abstracts SMM behind a processor-neutral "Management Mode" (MM) architecture, so that the same code can sit on top of x86 SMM or ARM TrustZone. However, this paper describes SMM exclusively for the X64 architecture. IA32, AArch64/TrustZone, RISC-V, and LoongArch implementations of Management Mode are out of scope and are not discussed.

SMRAM and SMI Entry Point

When a logical processor recognizes an SMI, it waits for the current instruction to retire. The current state is saved to SMRAM, set/clears appropriate bits in the control registers, disables interrupts, sets the code segment registers with details of SMBASE and sets RIP to the SMM Entry point without any firmware involvement.

Each processor needs its own save area, stack, and entry code, so firmware allocates one fixed-size tile per CPU in SMRAM and relocates each processor's SMBASE to it. Below is the EDK2 implementation of the fixed-size tile:

Offset from SMBASE

Contents

0x8000

SMI entry vector — a per-CPU copy of the entry template

0xFB00

Processor SMM Descriptor — GDT pointer and segment selectors (firmware-defined)

0xFC00

SMRAM state save map, 1 KiB, written by hardware

0xFEF8

SMBASE field inside the save map — write it, then RSM, to relocate

SMRAM's protection is enforced by hardware. The memory controller hides the region outside SMM, and the per-processor SMRR registers make the range uncacheable from outside SMM. Once the lock bits are set, the configuration cannot change until the next platform reset.

Boot Time initialization

SMM Foundation is loaded during the DXE phase and lets SMM drivers call UEFI boot services until Ready-To-Lock. Below are the four SMM initialization steps in the EDK2 implementation:

  1. The SMM IPL opens SMRAM, builds its heap, loads the Foundation into SMRAM, and registers the Foundation's entry point with the CPU driver.
  2. SMBASE relocation. Every processor shares the default SMBASE of 0x30000 at reset, so an SMI taken then would have all cores executing at one address on one stack. Firmware sends a directed SMI to one processor at a time; each writes its assigned tile base into its own save map and executes RSM and it is this RSM that performs the SMBASE relocation.
  3. Per-CPU handler installation. The entry-vector template is copied into each tile and binary-patched with that CPU's SMBASE, stack, page-table root, and CET configuration. Patching is required because the template is copied to an arbitrary address.
  4. SMM driver dispatch. The Foundation walks the firmware volumes, resolves SMM dependency expressions against its private protocol database, and loads each SMM driver into SMRAM.

Servicing an SMI (Multiprocessor Rendezvous)

Since an SMI is broadcast to every logical processor, the first C code reached is a rendezvous. One processor acts as BSP; the rest waits. The BSP waits for the APs. The wait is implemented as a two-phase timeout that sends directed SMIs to any stragglers, then closes the door, synchronizes MTRRs across all processors, and enters the Foundation.

The Foundation dispatches handlers in three tiers: root handlers (called on every SMI, responsible for quiescing their interrupt sources), child controller handlers, and leaf handlers that do the work.

OS-visible code can reach SMM through UEFI defined EFI_MM_COMMUNICATION_PROTOCOL. To reach SMM using this method the caller places a request in a non-SMRAM buffer and triggers a software SMI. The SMM Foundation must re-validate everything inside SMM before use, make sure that the buffer must lie entirely outside of SMRAM, must not overlap the firmware's own structures, and must be large enough for the header it claims.

Security

SMM's security is built in by hardware as an attacker executing code in SMM has defeated Secure Boot, hypervisor isolation, and the OS kernel at once. SMM's security model rests entirely on the memory controller's ability to make SMRAM invisible outside of SMM.

However, it is firmware's responsibility to:

  1. Lock SMM configuration before any 3rd party code (Including Option ROM drivers) is executed
  2. SMM code do not fetch code outside of SMRR.
  3. Consider everything outside of SMRAM as hostile: Copy the whole request into SMRAM, then validate, then act. Never trust a pointer or length that arrived in a communication buffer.
  4. Minimize the attack surface. Every registered handler is an entry point. Enable SMI handler profiling and audit what actually ships

Conclusion

System Management Mode on x86-64 is a remarkable piece of engineering. A hardware interrupt that saves a complete 64-bit architectural state, drops every processor in the system inside a memory region the OS cannot see, and all of them running 64-bit, paged, stack-protected firmware with a full protocol database, a heap, and multiprocessor dispatch services.

This is the only mechanism the architecture provides for a class of problems that genuinely must be solved below the OS. The engineering task is to keep it small, keep it verified, and keep it locked.

References:

  • UEFI Platform Initialization (PI) Specification, Version 1.9, Volume 4: Management Mode Core Interface: https://uefi.org/specs/PI/1.9/
  • Intel® 64 and IA-32 Architectures Software Developer's Manual, Volume 3C, "System Management Mode"
  • EDK II reference implementation GitHub: https://github.com/tianocore/edk2
  • EDK II reference implementation: MdeModulePkg/Core/PiSmmCore/PiSmmCore.inf (the MM Foundation)
  • EDK II reference implementation: UefiCpuPkg/PiSmmCpuDxeSmm/PiSmmCpuDxeSmm.inf (the X64 CPU driver)
  • UEFI Specification 2.11: https://uefi.org/specs/UEFI/2.11/