230 likes | 426 Views
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. IA-32e mode. 64-bit mode. Power on. Real mode. Protected mode. Compatibility
E N D
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 IA-32e mode 64-bit mode Power on Real mode Protected mode Compatibility mode System Management 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: x86 processor NMI SMI INTR INIT
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) ICR (lower 32-bits) destination short hand 01000 010 vector 0xFEEE0310 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 0x30000 BOOT_LOCN 0x07C00 RBDA 0x00400 IVT 0x00000
Classroom’s machines 4 GB physical memory 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 \ System Management memory CPU 0 0xDFFF0000 CPU 1 0xDFFE0000 CPU 2 0xDFFD0000 CPU 3 0xDFFC0000 0xDFF00000 We wrote our own ‘smlayout.cpp’ application to learn where the BIOS has placed these arenas in classroom’s machines The ROM-BIOS decides where to ‘relocate’ each processor’s SMRAM on a particular platform (not a ‘standard’, and not generally ‘documented’)
‘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 kernel space Linux operating system kernel standard runtime libraries file subsystem device driver module application program physical memory
The code-structure for ‘smram.c’ smram.c #include <linux/module.h> #include <linux/highmem.h> … char modname[ ] = “smram”; int my_major = 87; … MODULE_LICENSE(“GPL”); some header-files some global data this module’s ‘payload’ (its ‘method’ functions and its ‘file_operations’ structure) my_read() my_write() my_llseek() … my_fops required module administration functions module_init() module_exit()
‘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 ASCII code color attribute byte 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 These are the two bytes we normally see in the legacy VRAM space
‘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 ‘linker-script’ 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