Venturing into the x86’s System Management Mode An introduction to concepts needed for writing and testing an interrupt-handler for SMIs The x86 operating ‘modes’ Virtual 8086 mode 64-bit mode Power on Real mode Protected mode System Management mode IA-32e mode Compatibility mode Some purposes of SMM • Provide a ‘transparent’ mechanism for the hardware to perform various maintenance functions related to conservation of power or regulation of component temperatures • Allow ‘emulation’ of hardware behaviors when actual hardware is not installed or not functioning (e.g., keyboard-input via the network if a real keyboard is absent) SMM ‘transparency’ • To function without any operating system software being aware, the x86 processor enters System Management Mode when an external signal is delivered: NMI SMI INTR INIT x86 processor Using IPI messages • It is also possible to trigger an SMI using an Inter-Processor Interrupt (IPI) sent by one of the Local-APICs, by writing to its Interrupt Command Register ICR (upper 32-bits) destination 0xFEEE0310 ICR (lower 32-bits) short hand 01000 010 vector 0xFEEE0300 Delivery Mode = SMI A ‘private’ address-space • In response to an SMI signal, the CPU will switch to a otherwise inaccessible memory address-space, where it saves its current register-values and from which it fetches its subsequent machine-instructions • The usual protection-mechanisms, such as privilege-restrictions and limit-checks, are disabled (operates as in ‘real mode’) The CS and IP registers • Upon entry to SMM, the CS register gets modified (both its visible and hidden parts) and the IP register gets set to 0x00008000 • Initially, after a system-reset, the value of the SMBASE will be 0x00030000, but the SMI interrupt-handler can setup another value for any subsequent SMM entries – an essential step in multiple-CPU systems Initialization EBDA This arena must be relocated to private memory-space that doesn’t overlap any other processor’s SMM memory area Initial SMM segment BOOT_LOCN RBDA IVT 0x30000 0x07C00 0x00400 0x00000 Classroom’s machines one megabyte of the 4G physical memory is carved out for use only while a CPU is executing in System Management Mode and is not accessible during normal use The ROM-BIOS decides where to ‘relocate’ each processor’s SMRAM on a particular platform (not a ‘standard’, and not generally ‘documented’) CPU 0 CPU 1 CPU 2 CPU \ 3 0xDFFF0000 0xDFFE0000 0xDFFD0000 0xDFFC0000 System Management memory 0xDFF00000 4 GB physical memory We wrote our own ‘smlayout.cpp’ application to learn where the BIOS has placed these arenas in classroom’s machines ‘smram.c’ • We wrote this Linux device-driver module to provide our application-programs with a way to access the normally ‘inaccessible’ System Management Memory (details on this are from Intel’s MCH Data Sheet) • Some machines use a BIOS that ‘locks’ access to System Management Memory (such as the DELL machines in CS Labs) Using ‘fileview’ • Once you have compiled and installed our ‘smram.c’ device-driver, you can use the familiar ‘fileview’ utility to view the current contents of System Management Memory • You can also use ‘fileview’ to look at the graphics controller’s frame-buffer memory once you have compiled and installed our ‘vram.c’ device-driver System overview user space standard runtime libraries kernel space Linux operating system kernel file subsystem application program device driver module physical memory The code-structure for ‘smram.c’ smram.c some header-files some global data #include <linux/module.h> #include <linux/highmem.h> … char modname[ ] = “smram”; int my_major = 87; … my_read() my_write() my_llseek() … my_fops required module administration functions module_init() module_exit() MODULE_LICENSE(“GPL”); this module’s ‘payload’ (its ‘method’ functions and its ‘file_operations’ structure) ‘smidemo.s’ • We wrote our own ‘interrupt-handler’ code for any System Management Interrupts • We wanted it to do something simple that we would be able to perceive -- such as displaying a message on the screen • We encountered a number of obstacles, requiring an understanding of the MCH, the CRTC, the VRAM, and x86’s SMM Text-mode console • We normally use Linux’s graphical desktop environment – but a drawing message for the graphics display is quite complicated • So we can use Linux’s text-mode console • But Linux uses ‘hardware scrolling’ and the MCH blocks accesses to the usual VRAM in System Management Mode • So we had to overcome these obstacles The ATI frame-buffer The manufacturer’s of video display controllers do not always follow the same design-scheme for the arrangement of character-cells in text mode Our classroom machines have ATI (Advanced Technology, Incorporated) graphics hardware, where each character-cell is specified by a quadword (i.e., 8 bytes) from the frame-buffer memory. Byte 0 Byte 1 Byte 2 Byte 3 Byte 4 Byte 5 Byte 6 Byte 7 color ASCII attribute code byte These are the two bytes we normally see in the legacy VRAM space These bytes are not normally ‘mapped’ to the legacy memory-addresses 0xB8000-0xBFFFF but are used for storing the text-font bitmaps which the ASCII-codes reference in text-mode ‘hardware scrolling’ • Linux normally disregards the ROM-BIOS way of dividing text-mode display-memory into ‘pages’ which each correspond to one full text-mode screen-image – instead the Linux scheme moves a ‘window’ over the continuous segment of video memory 32-killobytes of text-mode video memory currently ‘visible’ screen current CRTC Start-Address (varies) Where to draw? • If we want to draw a message that will be visible on the current text-mode console, we need to use the current CRTC window and we need to draw each character (and color-attribute byte) to the first 2-bytes of quadword-sized frame-buffer locations 0 8 16 24 32 H E L L O Source-code ‘labels’ • Another obstacle we face is that assembly language labels are assigned their values based on the assumption that our code is residing at offset zero in the CS-segment, but in fact our SMI code will reside at the offset 0x8000 from the CS segment-base • So we either have to write a new ‘linkerscript’ or else adjust all offsets at runtime Avoid long jumps/calls/interrupts • If the BIOS has relocated the memory for System Management Mode to an address above the 1MB boundary, then we can’t freely allow instructions that modify the CS segment-register, since that will alter the ‘base-address’ field within the hidden part of the CS segment-register in a way that can’t be recovered using ‘real-mode’ style segment-register loads (20-bit addresses) Nevertheless… • We’ve overcome the numerous obstacles to a classroom demonstration of System Management Mode from within Linux: – Switch to a text console (CTRL-ALT-Fn) – Execute the Linux ‘setfont’ command – Install our ‘smram.ko’ kernel-module – Load our ‘smidemo.b’ (using ‘smiload’) – Execute our ‘issuesmi’ application In-class exercise • The Intel ‘SM Save State’ data-structure is described in Intel’s programmer manuals • Among the register-values automatically saved on entering System Management Mode is Control Register CR3 (used by the CPU to find the Level4 Page-Table) • It is saved at offset 0xfff0 from SMBASE • Can you display its (64-bit) value? Important! DON’T FORGET TO DO A ‘COLD RESTART’ BEFORE YOU GO HOME TONIGHT