如何在Windows中禁用软件SMI(系统管理中断)

如何在Windows中禁用软件SMI(系统管理中断),windows,kernel,uefi,Windows,Kernel,Uefi,从Windows 10 1809开始,操作系统生成大量软件SMI。 我们在独立的处理器内核上运行实时应用程序,每个SMI都会产生不可预测的延迟。1809年之前,始终可以在BIOS中禁用SMI。 Windows中的调用堆栈如下所示: hal!HalEfiGetEnvironmentVariable+0x56 hal!HalGetEnvironmentVariableEx+0xb572 nt!IopGetEnvironmentVariableHal+0x2a

从Windows 10 1809开始,操作系统生成大量软件SMI。
我们在独立的处理器内核上运行实时应用程序,每个SMI都会产生不可预测的延迟。1809年之前,始终可以在BIOS中禁用SMI。
Windows中的调用堆栈如下所示:

hal!HalEfiGetEnvironmentVariable+0x56       
hal!HalGetEnvironmentVariableEx+0xb572      
nt!IopGetEnvironmentVariableHal+0x2a        
nt!IoGetEnvironmentVariableEx+0x85          
nt!ExpGetFirmwareEnvironmentVariable+0x91   
nt!ExGetFirmwareEnvironmentVariable+0x110ce3
nt!NtQuerySystemEnvironmentValueEx+0x6e     
SMI由OUT指令生成到端口0xb2。需要从NVRAM读取UEFI变量。当BIOS处于传统模式时,没有SMI


是否可以配置Windows,使其不会使用SMI访问UEFI变量?

简短的回答是否,无法将Windows配置为不在UEFI变量访问上生成SW SMI,因为这些SMI不是由Windows生成的。SMI在固件内部生成

所有支持UEFI的操作系统通过GetVariable()和SetVariable()服务读取/写入UEFI变量,这是UEFI固件通过系统表向操作系统公开的运行时服务的一部分-请参阅UEFI规范第8节。出于安全原因,大多数固件中的变量服务的当前实现是在SMM中处理实际的Get/Set变量请求


因此,负责生成软件SMI的是设备固件,而不是操作系统。但是,操作系统和一些系统服务/应用程序绝对需要使用UEFI变量,因为UEFI感知操作系统应该如何在UEFI固件上运行。

我认为您不能,因为它是UEFI\BIOS的一部分flows@prl,Windows不访问端口0xb2。固件输出到0xb2以响应UEFI变量访问。虽然Ubuntu和Windows都可以在没有变量的情况下启动,但我不认为它们是不必要的——很可能有些功能无法正常工作。Windows不经常访问UEFI变量;在引导过程中会有大量的读/写操作,但随后会变得安静,只在必要时进行访问。我认为实际上不可能在Windows中禁用变量或阻止0xb2访问并保持其稳定。我的重点是找出谁访问系统中的变量。@sun2sirius谢谢你的回答。显然,SMM是读取UEFI的唯一安全模式,但它确实会降低性能。我知道操作系统可以在加载/关闭期间读取/写入NVRAM,但为什么在运行时使用它呢?如果没有隐藏的注册表项,那么禁用SMI的唯一方法就是在此类API调用上添加挂钩。@vladimir pustovalov,您可能希望尝试向上调用堆栈,以查看是谁对UEFI变量进行了这些内核调用。我刚刚构建了一个测试BIOS,它显示了所有的变量访问和启动的窗口——我在启动时看到了一个突发事件,几分钟后又看到了另一个突发事件。但后来再也没有发生过,我等了一个多小时。您还可以查看GetEnvironmentVariable()调用的堆栈框架,查看变量名和GUID,这可能会让您了解访问它的原因。这绝对不正常。然后您可以找到读取变量的组件并查看它,您可以禁用或更好地配置它。