3

Starting from Windows 10 1809, OS generates lots of software SMIs.
We are running our real time application on separate processor core and each SMI generates unpredictable delay. Before 1809 it was always possible to disable SMIs in BIOS.
Call stack in Windows looks like:

hal!HalEfiGetEnvironmentVariable+0x56       
hal!HalGetEnvironmentVariableEx+0xb572      
nt!IopGetEnvironmentVariableHal+0x2a        
nt!IoGetEnvironmentVariableEx+0x85          
nt!ExpGetFirmwareEnvironmentVariable+0x91   
nt!ExGetFirmwareEnvironmentVariable+0x110ce3
nt!NtQuerySystemEnvironmentValueEx+0x6e     

SMI is generated by OUT instruction into port 0xb2. It is required to read UEFI variables from NVRAM. When BIOS is in legacy mode, there is no SMIs.

Is it possible to configure Windows, so it will not access UEFI variables using SMIs?

2 Answers2

2

The short answer is NO, it is not possible to configure Windows to not generate SW SMIs on UEFI Variable accesses, because those SMIs are not generated by Windows. The SMIs are generated inside the firmware.

All UEFI-aware OSes read/write UEFI variables via GetVariable() and SetVariable() services, which are part of Runtime Services exposed by a UEFI firmware to the OS via System Table - see UEFI Spec, section 8. The current implementation of Variable Services in most firmware is to process the actual Get/Set variable requests inside SMM, for security reasons.

So it is the device's firmware that's responsible for generating SW SMIs, not the OS. However, the OS and some system services/applications absolutely need to work with UEFI variables as it is how a UEFI-aware OS is supposed to run on a UEFI firmware.

sun2sirius
  • 455
  • 2
  • 10
  • I think the reasoning in this answer is wrong. It is true that the SMIs are not generated by Windows, but they *are* generated in response to an operation performed by Windows, which is the access to port 0xb2. If it is possible to configure Windows to not access that port, then the SMIs would not occur. – prl Jan 01 '20 at 02:44
  • Even if it is necessary for Windows to access UEFI variables, it is certainly not necessary for it to access them at such a frequency that would have an impact on a real-time application. – prl Jan 01 '20 at 02:48
  • 1
    @prl, Windows *does not* access port 0xb2. *The firmware* outputs to 0xb2 in response to UEFI variable access. Although both Ubuntu and Windows are able to boot without variables, I would not call them not necessary – most likely some features won’t work correctly. Windows does not access UEFI variables frequently; there is a bulk of read/write during boot, but then it goes quiet and only makes accesses as necessary. I do not think it is practically possible to disable variables or block 0xb2 accesses in Windows and keep it stable. I'd focus on finding who accesses variables in the system. – sun2sirius Jan 03 '20 at 07:13
  • @vladimir-pustovalov, if you need any additional info on this subject I'll add to my answer, just let me know. If it clearly answers your question, could you please mark it accepted? Thanks – sun2sirius Jan 03 '20 at 07:42
  • 1
    @sun2sirius Thanks for an answer. It is clear that SMM is the only safe mode to read UEFI, but it is real performance degradation. I understand that OS can read/write NVRAM during load/shutdown, but why it is used in run-time? If there is no hidden registry key, than the only way to disable SMI is to adding hooks on such API calls. – Vladimir Pustovalov Jan 03 '20 at 08:19
  • @sun2sirius you are right. It is firmware code which accesses UEFI variables. We saw it from call stack. But normally Windows provides opportunity to disable performance impact calls, via bcdedit or registry. But we found nothing about it. – Vladimir Pustovalov Jan 03 '20 at 08:30
  • 1
    @vladimir-pustovalov, you may want to try going up the call stack to see who is making those kernel calls for UEFI variables. I just now built a test BIOS that displays all variable accesses, and booted Windows - I saw one burst on boot, then a few min later another burst. But then it never happened again, I waited for over an hour. – sun2sirius Jan 03 '20 at 08:35
  • 1
    You can also look at the stack frame of the GetEnvironmentVariable() call to see the variable name and GUID - that may give you an idea why it is accessed. It is definitely not normal. Then you may be able to find the component that reads the variable and see it you can disable of configure it better. – sun2sirius Jan 03 '20 at 08:37
  • @sun2sirius The simplest way to reproduce it is to press Windows key and search something. – Vladimir Pustovalov Jan 03 '20 at 08:44
  • 1
    Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/205280/discussion-between-sun2sirius-and-vladimir-pustovalov). – sun2sirius Jan 03 '20 at 08:52
  • @sun2sirius, yes I my first comment was misstated. Thanks for setting me straight. I should have said: the SMIs are not generated by Windows, but they are generated in response to an operation performed by Windows, which is the access to UEFI variables. If it is possible to configure Windows to not access UEFI variables, then the SMIs would not occur. ... Based on your subsequent comments, I think we both agree that Windows should not be doing this with this frequency, and it is probably some driver or service that could be disabled or fixed. – prl Jan 03 '20 at 09:10
  • 1
    @prl - agreed, this is somehow specific to Vladimir's environment as I cannot see this issue with my firmware and Windows install. – sun2sirius Jan 03 '20 at 09:16
  • @sun2sirius. I've added detailed stack trace to the chat. – Vladimir Pustovalov Jan 04 '20 at 18:05
1

On processors that supports AMD-V (e.g. AMD Processors, Hygon Processors), the answer is yes, but in kernel mode. There are two instructions called stgi and clgi, where stgi sets the GIF and clgi clears the GIF. The GIF is used to control the interrupt behaviors so that one may enter absolute atomic operations. As defined in AMD-V, Internal SMIs (e.g. I/O Trapping) are discarded and External SMIs (e.g. from external hardware, or IPIs by APIC) are held pending when GIF is cleared. Make sure you enabled the SVME bit in EFER MSR as you are to execute these instructions.

If you would like to make it happen in a more generic way, which does not rely on AMD-V, you may try to get your code into SMI handler, in that SMIs which occurs later will be latched while processor is in SMM.

Reference:
Chapter 10.3.3 "Exceptions and Interrupts", Volume 2 "System Programming", AMD64 Architecture Programmer's Manual.
Chapter 15.17 "Global Interrupt Flag, STGI and CLGI Instructions", Volume 2 "System Programming", AMD64 Architecture Programmer's Manual.
https://www.amd.com/system/files/TechDocs/24593.pdf