I had to exit interrupt handler without iretq too. But that was very special case. There is no way to block #NMI in Intel VMX root mode unlike at AMD SVM where you can (using CLGI instruction). While my hypervisor accepted #NMI I wanted to let the CPU in #NMI blocking mode to prevent more #NMI to arrive as I was able to inject only 1 #NMI into guest during every VM entry. These #NMI came as IPIs from different cpus/cores where hyper-v was running as a child under nested environment. At the end I solved my problem but during observation and development I had to try that way to leave #NMI blocked so I had to avoid iretq as iretq unblocks #NMI.
I used this way at the end of my #NMI handler:
Code:
push rax
; now the stack looks this way:
; qword [rsp+8*0] RAX
; qword [rsp+8*1] RIP
; word [rsp+8*2] CS
; qword [rsp+8*3] RFLAGS
; qword [rsp+8*4] RSP
; word [rsp+8*5] SS
; this leaves interrupt handler and lets NMIs blocked:
mov rax,rsp
lss rsp,[rax+8*4] ; load RSP from qword [rax+8*4] and SS from [rax+8*4+8]
push qword [rax+8*3]
popf
push qword [rax+8*2] ; CS
push qword [rax+8*1] ; RIP
mov rax,[rax+8*0] ; restore RAX
retf