On Mon, Apr 04, 2022, Maciej S. Szmigiero wrote: > On 4.04.2022 18:49, Sean Christopherson wrote: > > On Mon, Apr 04, 2022, Maxim Levitsky wrote: > > In svm_update_soft_interrupt_rip(), snapshot all information regardless of whether > > or not nrips is enabled: > > > > svm->soft_int_injected = true; > > svm->soft_int_csbase = svm->vmcb->save.cs.base; > > svm->soft_int_old_rip = old_rip; > > svm->soft_int_next_rip = rip; > > > > if (nrips) > > kvm_rip_write(vcpu, old_rip); > > > > if (static_cpu_has(X86_FEATURE_NRIPS)) > > svm->vmcb->control.next_rip = rip; > > > > and then in svm_complete_interrupts(), change the linear RIP matching code to look > > for the old rip in the nrips case and stuff svm->vmcb->control.next_rip on match. > > > > bool soft_int_injected = svm->soft_int_injected; > > unsigned soft_int_rip; > > > > svm->soft_int_injected = false; > > > > if (soft_int_injected) { > > if (nrips) > > soft_int_rip = svm->soft_int_old_rip; > > else > > soft_int_rip = svm->soft_int_next_rip; > > } > > > > ... > > > > if soft_int_injected && type == SVM_EXITINTINFO_TYPE_EXEPT && > > kvm_is_linear_rip(vcpu, soft_int_rip + svm->soft_int_csbase)) { > > if (nrips) > > svm->vmcb->control.next_rip = svm->soft_int_next_rip; > > else > > kvm_rip_write(vcpu, svm->soft_int_old_rip); > > } > > > > > > > > Despite what the svm_update_soft_interrupt_rip() name might suggest this > handles only *soft exceptions*, not *soft interrupts* > (which are injected by svm_inject_irq() and also need proper next_rip > management). Yeah, soft interrupts are handled in the next patch. I couldn't come up with a less awful name. > Also, I'm not sure that even the proposed updated code above will > actually restore the L1-requested next_rip correctly on L1 -> L2 > re-injection (will review once the full version is available). Spoiler alert, it doesn't. Save yourself the review time. :-) The missing piece is stashing away the injected event on nested VMRUN. Those events don't get routed through the normal interrupt/exception injection code and so the next_rip info is lost on the subsequent #NPF. Treating soft interrupts/exceptions like they were injected by KVM (which they are, technically) works and doesn't seem too gross. E.g. when prepping vmcb02 if (svm->nrips_enabled) vmcb02->control.next_rip = svm->nested.ctl.next_rip; else if (boot_cpu_has(X86_FEATURE_NRIPS)) vmcb02->control.next_rip = vmcb12_rip; if (is_evtinj_soft(vmcb02->control.event_inj)) { svm->soft_int_injected = true; svm->soft_int_csbase = svm->vmcb->save.cs.base; svm->soft_int_old_rip = vmcb12_rip; if (svm->nrips_enabled) svm->soft_int_next_rip = svm->nested.ctl.next_rip; else svm->soft_int_next_rip = vmcb12_rip; } And then the VMRUN error path just needs to clear soft_int_injected.