[VMM Core] - NMI to cause run code in R0 Guest

Discussions related to using the OSE version of VirtualBox.
Post Reply
C0reDev
Posts: 8
Joined: 28. Sep 2017, 14:24

[VMM Core] - NMI to cause run code in R0 Guest

Post by C0reDev »

Hi there,
I'm running virtual box on Windows host with Windows guest. When I dump the IDT in guest and I dump the IDT in host - it's not the same (of course).
My understanding of interrupts is as follows:
When an NMI occurs in Guest - a VMEXIT is performed in order to treat the interrupt in root mode and then come back to guest via VMRESUME.
When an NMI occurs in Host - there is still a VMEXIT from guest in order to treat it.

My question is:
When a specific NMI occurs, on a bare-metal machine there is a handler in the IDT that runs a registered handler in Ring 0. Because it's a registered handler, and the registration occurs in non-root mode im my case (in guest context), the handler will be registered in guest's IDT but not in Host's IDT. (Dumping IDT in both environments shows different IDTs).
Is there a way to make the guest run that handler in it's IDT on VMRESUME? Maybe some field in VMCS?
I want to run that code in non-root mode Ring 0, because the guest has registered this handler and its invisible to the host.

Thank you,
~C0reDev~
michaln
Oracle Corporation
Posts: 2973
Joined: 19. Dec 2007, 15:45
Primary OS: MS Windows 7
VBox Version: PUEL
Guest OSses: Any and all
Contact:

Re: [VMM Core] - NMI to cause run code in R0 Guest

Post by michaln »

There is no way to forward NMIs from host to guest. There is a way to inject NMIs from host to guest under user control (VBoxManage debugvm <vm> injectnmi), and it is possible for a guest to send an NMI IPI using the local APIC. The latter is something which e.g. Windows tends to do under certain circumstances. In either case the guest's NMI handler will be invoked.
C0reDev
Posts: 8
Joined: 28. Sep 2017, 14:24

Re: [VMM Core] - NMI to cause run code in R0 Guest

Post by C0reDev »

I'll explain a bit more:
I was able to add PMI (performance monitoring interrupt) through vbox, how ever it runs directly on the physical cpu. In windows there is a PMI handler that is registered on the IDT whenever PMI occurs. Ergo, on a bare metal machine, each time PMI occurs, Windows runs my own code that is registered as a PMI handler. Under VM, the handler is registered only on guest's context. Moreover, the PMI occurs on the physical CPU.
Running VBoxManage debugvm <vm> injectnmi - means I have to start a new process in windows' host each time PMI occurs, it is very slow for me. Also, I fail to see how IPI helps me here.
What I would've liked to do is to know whether there is something already implemented so that I can inject that NMI (number 0xfe in windows IDT) so that my guest's handler will run on each PMI automatically.
Worst case scenario, I would have to implement such functionality, but I want few directions to get along with the concept and most of all - the source code.
Note: Adding some kind of PMI handler on the host is possible, also to interact with vbox.
--
P.S
I also assume that each time the host gets a PMI it causes VMEXIT now matter what. If this is not the case, and it is no "bypassable" by adding host PMI handler - its not relevant to me. Am I wrong with this assumption?
Last edited by socratis on 8. Oct 2017, 10:51, edited 1 time in total.
Reason: Removed unnecessary verbatim quote of the whole previous message.
michaln
Oracle Corporation
Posts: 2973
Joined: 19. Dec 2007, 15:45
Primary OS: MS Windows 7
VBox Version: PUEL
Guest OSses: Any and all
Contact:

Re: [VMM Core] - NMI to cause run code in R0 Guest

Post by michaln »

There's no separate "PMI", if I remember correctly there's an APIC LVT which maps the performance monitoring interrupt to something. If the performance monitoring interrupt is an NMI or a regular maskable interrupt then yes, it will cause a VM exit. That is correct. There is no existing way to "bounce" that interrupt into the VM.
C0reDev
Posts: 8
Joined: 28. Sep 2017, 14:24

Re: [VMM Core] - NMI to cause run code in R0 Guest

Post by C0reDev »

michaln wrote:There's no separate "PMI", if I remember correctly there's an APIC LVT which maps the performance monitoring interrupt to something. If the performance monitoring interrupt is an NMI or a regular maskable interrupt then yes, it will cause a VM exit. That is correct. There is no existing way to "bounce" that interrupt into the VM.
I look for a way to implement it if there is no existing way to do so.
What about Posted-Interrupt Requests? Is this a lead? Maybe other ideas?
Maybe if PMI cause a VM exit, I could raise a bit and the event will be treated in guest (non-root mode) - if I understood it right.

Image

Thanks.
michaln
Oracle Corporation
Posts: 2973
Joined: 19. Dec 2007, 15:45
Primary OS: MS Windows 7
VBox Version: PUEL
Guest OSses: Any and all
Contact:

Re: [VMM Core] - NMI to cause run code in R0 Guest

Post by michaln »

C0reDev wrote:What about Posted-Interrupt Requests? Is this a lead? Maybe other ideas?
Yes and no. VirtualBox doesn't support that at this time, you probably don't have the hardware for it, and it wouldn't work for NMIs anyway.
Maybe if PMI cause a VM exit, I could raise a bit and the event will be treated in guest (non-root mode) - if I understood it right.
It would be possible for the handler on the host to trigger an interrupt in the guest. There is no existing support for that in VirtualBox because it's not expected that the guest OS would want to handle host interrupts.
C0reDev
Posts: 8
Joined: 28. Sep 2017, 14:24

Re: [VMM Core] - NMI to cause run code in R0 Guest

Post by C0reDev »

michaln wrote:
C0reDev wrote:What about Posted-Interrupt Requests? Is this a lead? Maybe other ideas?
Yes and no. VirtualBox doesn't support that at this time, you probably don't have the hardware for it, and it wouldn't work for NMIs anyway.
What about PMIs? (number 0xfe in LVT, whereas external NMI is 0x2 if I recall correctly)
michaln wrote:
C0reDev wrote:Maybe if PMI cause a VM exit, I could raise a bit and the event will be treated in guest (non-root mode) - if I understood it right.
It would be possible for the handler on the host to trigger an interrupt in the guest. There is no existing support for that in VirtualBox because it's not expected that the guest OS would want to handle host interrupts.
How? Using posted-interrupt requests or in another way?
I could try to figure out how to implement it if you say there is no existing support for it. Of course if you have a clue or leads on what to implement or where to "play with the source", anything could be helpful :)

Thank you
michaln
Oracle Corporation
Posts: 2973
Joined: 19. Dec 2007, 15:45
Primary OS: MS Windows 7
VBox Version: PUEL
Guest OSses: Any and all
Contact:

Re: [VMM Core] - NMI to cause run code in R0 Guest

Post by michaln »

There is currently no mechanism for forwarding PMIs in VirtualBox, or any support for performance monitoring in a VM for that matter.

Injecting interrupts (and NMIs to a lesser extent) is something the VMM does a lot. For NMIs there is a way to trigger that externally, for other interrupts there isn't because there's never been any use case for it. In fact if users were allowed to inject random interrupts, they would quite likely confuse the guest OS and/or the emulated hardware.

See DBGFR3InjectNMI for how NMIs are injected. For normal interrupts it's nowhere near that simple because a) you need an interrupt vector, and b) you have to decide if you want to inject interrupts on the interrupt controller level or the CPU level. Big difference.

Basically with NMIs, the guest OS will either handle it or not, but with other interrupts you really have to know what you're doing or you will only mess it up.
Post Reply