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~
[VMM Core] - NMI to cause run code in R0 Guest
-
- 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
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.
Re: [VMM Core] - NMI to cause run code in R0 Guest
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?
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.
Reason: Removed unnecessary verbatim quote of the whole previous message.
-
- 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
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.
Re: [VMM Core] - NMI to cause run code in R0 Guest
I look for a way to implement it if there is no existing way to do so.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.
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.
Thanks.
-
- 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
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.C0reDev wrote:What about Posted-Interrupt Requests? Is this a lead? Maybe other ideas?
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.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.
Re: [VMM Core] - NMI to cause run code in R0 Guest
What about PMIs? (number 0xfe in LVT, whereas external NMI is 0x2 if I recall correctly)michaln wrote: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.C0reDev wrote:What about Posted-Interrupt Requests? Is this a lead? Maybe other ideas?
How? Using posted-interrupt requests or in another way?michaln wrote: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 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.
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
-
- 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
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.
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.