Is there a way to determine, for some progamatically defined interval, if a SMM entry has occurred on the current core?
1 Answers
Starting with Nehalem, the MSR register 0x34 (called MSR_SMI_COUNT
) counts the number of SMIs that occurred since the system was booted. It's read-only and Intel-specific. You can programmability read from this register (or any other MSR register) from user mode using the /dev/cpu/CPUNUM/msr
interface. There are several tools that use the interface to show the SMI count including msr-tools (sudo rdmsr -a 0x34
) and turbostat (sudo turbostat --msr 0x34
).
I've extracted this code from the turbostat source code (/source/tools/power/x86/turbostat/turbostat.c). The get_msr_fd
function returns the file descriptor of the msr
file. The get_msr
function accepts the CPU number, the MSR offset (0x34 for MSR_SMI_COUNT
), and a pointer to a 64-bit location that will hold the value of the MSR (although MSR_SMI_COUNT
is a 32-bit counter and the upper 32 bits are reserved).
int get_msr_fd(int cpu)
{
char pathname[32];
int fd;
fd = fd_percpu[cpu];
if (fd)
return fd;
sprintf(pathname, "/dev/cpu/%d/msr", cpu);
fd = open(pathname, O_RDONLY);
if (fd < 0)
err(-1, "%s open failed, try chown or chmod +r /dev/cpu/*/msr, or run as root", pathname);
fd_percpu[cpu] = fd;
return fd;
}
int get_msr(int cpu, off_t offset, unsigned long long *msr)
{
ssize_t retval;
retval = pread(get_msr_fd(cpu), msr, sizeof(*msr), offset);
if (retval != sizeof *msr)
err(-1, "cpu%d: msr offset 0x%llx read failed", cpu, (unsigned long long)offset);
return 0;
}
An SMI may occur multiple times per second or may not occur for a long period of time. But one way to observe a change in MSR_SMI_COUNT
is by issuing a synchronous SMI. Typically, this can be done by writing some 8-bit value to I/O port 0xB2 or 0xB3. You can refer to your chipset manual to determine which I/O ports may trigger an SMI.

- 22,259
- 3
- 54
- 95
-
2`turbostat` version 17.06.23 includes a per-core SMI column by default. Also, the syntax for adding a new column is `turbostat --add msr0x34,u64,cpu,delta,SMM` (I think, based on the --help example for TSC. I didn't see any counts from that or the SMI column, running with no other args to just show a `vmstat`-style output printing a block of rows every 5 seconds :) – Peter Cordes Jun 11 '18 at 21:18
-
1Another (easier?) way to trigger an SMI is to deliver it through the LAPIC. IDK if Linux has a specific function for that, `native_apic_mem_write(APIC_ICR, ...)` should do anyway. – Margaret Bloom Jun 12 '18 at 13:22
-
@MargaretBloom I think that APIC_ICR can only be written to in kernel mode, right? Just like the I/O ports I mentioned in the answer. – Hadi Brais Jun 12 '18 at 19:02
-
@HadiBrais Yes, only in kernel mode. Unless some driver exposes it, but that would be very dangerous. – Margaret Bloom Jun 12 '18 at 19:29