X86 有没有办法确定SMM中断已经发生?

X86 有没有办法确定SMM中断已经发生?,x86,hardware,intel,X86,Hardware,Intel,是否有方法确定,对于某些编程定义的间隔,当前core上是否发生了条目?从Nehalem开始,称为MSR\u SMI\u COUNT的MSR寄存器0x34统计自系统启动以来发生的SMI数。它是只读的,特定于英特尔。您可以使用/dev/cpu/CPUNUM/MSR接口在用户模式下从该寄存器或任何其他MSR寄存器读取可编程性。有几个工具使用该界面显示SMI计数,包括sudo rdmsr-a 0x34和turbostat sudo turbostat-msr 0x34 我从turbostat源代码/so

是否有方法确定,对于某些编程定义的间隔,当前core上是否发生了条目?

从Nehalem开始,称为MSR\u SMI\u COUNT的MSR寄存器0x34统计自系统启动以来发生的SMI数。它是只读的,特定于英特尔。您可以使用/dev/cpu/CPUNUM/MSR接口在用户模式下从该寄存器或任何其他MSR寄存器读取可编程性。有几个工具使用该界面显示SMI计数,包括sudo rdmsr-a 0x34和turbostat sudo turbostat-msr 0x34

我从turbostat源代码/source/tools/power/x86/turbostat/turbostat.c中提取了这段代码。get_msr_fd函数返回msr文件的文件描述符。get_msr函数接受CPU号、msr_SMI_计数的msr偏移量0x34以及指向64位位置的指针,该位置将保存msr的值,尽管msr_SMI_计数是32位计数器且保留了较高的32位

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;
}

SMI可能每秒发生多次,也可能长时间不发生。但观察MSR_SMI_计数变化的一种方法是发出同步SMI。通常,这可以通过将一些8位值写入I/O端口0xB2或0xB3来完成。您可以参考芯片组手册来确定哪些I/O端口可能触发SMI。

从Nehalem开始,MSR寄存器0x34(称为MSR_SMI_COUNT)统计自系统启动以来发生的SMI数。它是只读的,特定于英特尔。您可以使用/dev/cpu/CPUNUM/MSR接口在用户模式下从该寄存器或任何其他MSR寄存器读取可编程性。有几个工具使用该界面显示SMI计数,包括sudo rdmsr-a 0x34和turbostat sudo turbostat-msr 0x34

我从turbostat源代码/source/tools/power/x86/turbostat/turbostat.c中提取了这段代码。get_msr_fd函数返回msr文件的文件描述符。get_msr函数接受CPU号、msr_SMI_计数的msr偏移量0x34以及指向64位位置的指针,该位置将保存msr的值,尽管msr_SMI_计数是32位计数器且保留了较高的32位

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;
}

SMI可能每秒发生多次,也可能长时间不发生。但观察MSR_SMI_计数变化的一种方法是发出同步SMI。通常,这可以通过将一些8位值写入I/O端口0xB2或0xB3来完成。您可以参考芯片组手册,确定哪些I/O端口可能触发SMI。

turbostat 17.06.23版默认包含每核SMI列。另外,根据TSC的-help示例,添加新列的语法是turbostat-addMSR0x34、u64、cpu、delta、SMM。我没有看到该列或SMI列中的任何计数,在没有其他参数的情况下运行,只是显示一个vmstat样式的输出,每5秒打印一行:另一个更简单?触发SMI的方法是通过LAPIC传递。IDK如果Linux有一个特定的函数,那么原生的apic mem writeAPIC ICR。。。我认为APIC_ICR只能在内核模式下写入,对吗?就像我在回答中提到的I/O端口一样。@HadiBrais是的,仅在内核模式下。除非某些驱动程序将其公开,但这将是非常危险的。turbostat版本17.06.23默认包含每个核心SMI列。另外,根据TSC的-help示例,添加新列的语法是turbostat-addMSR0x34、u64、cpu、delta、SMM。我没有看到该列或SMI列中的任何计数,在没有其他参数的情况下运行,只是显示一个vmstat样式的输出,每5秒打印一行:另一个更简单?触发SMI的方法是通过LAPIC传递。IDK如果Linux有一个特定的函数,那么原生的apic mem writeAPIC ICR。。。我认为APIC_ICR只能在内核模式下写入,对吗?就像我在回答中提到的I/O端口一样。@HadiBrais是的,仅在内核模式下。除非有司机把它暴露出来,但那是非常危险的。