Re: NMI Injection to Guest

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



Hi Gleb,

Another problem on AMD processors.

After each vm-exit, I need to check if this vm-exit is due to NMI. For
vmx.c, I add the check in vmx_complete_interrupts().

The code snippet is:

3539         if ((exit_intr_info & INTR_INFO_INTR_TYPE_MASK) ==
INTR_TYPE_NMI_INTR &&
3540             (exit_intr_info & INTR_INFO_VALID_MASK)) {
3541
3542                 printk(KERN_INFO "kvm-oprofile: vm exit due to NMI.\n");
3543
3544                 /* indicate vm-exit due to conter overflow */
3545                 vcpu->vm_exit_on_cntr_overflow = 1;
3546         }

This works on Intel chips.

I did the similar check in svm_complete_interrupts().

2501 static void svm_complete_interrupts(struct vcpu_svm *svm)
2502 {
2503         u8 vector;
2504         int type;
2505         u32 exitintinfo = svm->vmcb->control.exit_int_info;
2506         struct kvm_vcpu *vcpu = &svm->vcpu;
2507
2508         if (svm->vcpu.arch.hflags & HF_IRET_MASK)
2509                 svm->vcpu.arch.hflags &= ~(HF_NMI_MASK | HF_IRET_MASK);
2510
2511         svm->vcpu.arch.nmi_injected = false;
2512         kvm_clear_exception_queue(&svm->vcpu);
2513         kvm_clear_interrupt_queue(&svm->vcpu);
2514
2515         if (!(exitintinfo & SVM_EXITINTINFO_VALID))
2516                 return;
2517
2518         vector = exitintinfo & SVM_EXITINTINFO_VEC_MASK;
2519         type = exitintinfo & SVM_EXITINTINFO_TYPE_MASK;
2520
2521         /* kvm-oprofile */
2522         if (type == SVM_EXITINTINFO_TYPE_NMI) {
2523
2524                 printk(KERN_INFO "kvm-oprofile:
counter_overflowed & vm exit.\n");
2525                 vcpu->vm_exit_on_cntr_overflow = 1;
2526         }

However, this part (2522 to 2526) never got executed. By using qemu
monitor, I managed to inject NMI to the guests. But this check, after
vm-exit due to NMI, does not succeed.


Thanks,
Jiaqing

2009/7/30 Jiaqing Du <jiaqing@xxxxxxxxx>:
> Hi Gleb,
>
> My code works by setting "vcpu->arch.nmi_pending = 1;" inside
> vcpu_enter_guest().
>
>
> Thanks,
> Jiaqing
>
> 2009/7/27 Gleb Natapov <gleb@xxxxxxxxxx>:
>> On Sun, Jul 26, 2009 at 09:25:34PM +0200, Jiaqing Du wrote:
>>> Hi Gleb,
>>>
>>> Thanks for your reply.
>>>
>>> 2009/7/26 Gleb Natapov <gleb@xxxxxxxxxx>:
>>> > On Sat, Jul 25, 2009 at 10:46:39PM +0200, Jiaqing Du wrote:
>>> >> Hi list,
>>> >>
>>> >> I'm trying to extend OProfile to support guest profiling. One step of
>>> >> my work is to push an NMI to the guest(s) when a performance counter
>>> >> overflows. Please correct me if the following is not correct:
>>> >>
>>> >> counter overflow --> NMI to host --> VM exit --> "int $2" to handle
>>> >> NMI on host --> ...   --> VM entry --> NMI to guest
>>> >>
>>> > Correct except the last step (--> NMI to guest). Host nmi is not
>>> > propagated to guests.
>>>
>>> Yes. I need to add some code to propagate host NMI to guests.
>>> >
>>> >> On the path between VM-exit and VM-entry, I want to push an NMI to the
>>> >> guest. I tried to put the following code on the path, but never
>>> >> succeeded. Various wired things happened, such as KVM hangs, guest
>>> >> kernel oops, and host hangs. I tried both code with Linux 2.6.30 and
>>> >> version 88.
>>> >>
>>> >> if (vmx_nmi_allowed())  { vmx_inject_nmi(); }
>>> >>
>>> >> Any suggestions? Where is the right place to push an NMI and what are
>>> >> the necessary checks?
>>> > Call kvm_inject_nmi(vcpu). And don't forget to vcpu_load(vcpu) before
>>> > doing it. See kvm_vcpu_ioctl_nmi().
>>>
>>> Based on the code with Linux 2.6.30, what kvm_inject_nmi(vcpu) does is
>>> just set vcpu->arch.nmi_pending to 1. kvm_vcpu_ioctl_nmi() puts
>>> vcpu_load() before the setting and vcpu_put() after it.
>>>
>>> I need to push host NMI to guests between a VM-exit and a VM-entry
>>> after that. The VM-exit is due to an NMI caused by performance counter
>>> overflow. The following code with vcpu_enter_guest(), which is
>>> surrounded by a vcpu_load() and vcpu_put(), checks this
>>> vcpu->arch.nmi_pending and other related flags to decide whether an
>>> NMI should be pushed to guests.
>>>
>>>       if (vcpu->arch.exception.pending)
>>>               __queue_exception(vcpu);
>>>       else if (irqchip_in_kernel(vcpu->kvm))
>>>               kvm_x86_ops->inject_pending_irq(vcpu);
>>>       else
>>>               kvm_x86_ops->inject_pending_vectors(vcpu, kvm_run);
>>>
>>> What I did is given below:
>>>
>>> 3097 static int vcpu_enter_guest(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run)
>>> 3098 {
>>>                ... ...
>>>
>>> 3156         if (kvm_vm_exit_on_cnt_overflow) {
>>> 3157                 vcpu->arch.nmi_pending = 1;
>>> 3158         }
>>> 3159
>>> 3160         if (vcpu->arch.exception.pending)
>>> 3161                 __queue_exception(vcpu);
>>> 3162         else if (irqchip_in_kernel(vcpu->kvm))
>>> 3163                 kvm_x86_ops->inject_pending_irq(vcpu);
>>> 3164         else
>>> 3165                 kvm_x86_ops->inject_pending_vectors(vcpu, kvm_run);
>>>
>>>               ... ....
>>> 3236 }
>>>
>>> In vcpu_enter_guest(), before this part of code is reached,
>>> vcpu->arch.nmi_pending is set to 1 if the VM-exit is due to
>>> performance counter overflow. Still, no NMIs are seen by the guests. I
>>> also tried to put this "vcpu->arch.nmi_pending = 1;" somewhere else on
>>> the path between a VM-exit and VM-entry, it does not seem to work
>>> neither. Only vmx_inject_nmi() manages to push NMIs to guests, but
>>> without right sanity checks, it causes various wired host and guest
>>> behaviors.
>>>
>>> To inject NMIs on the path between a VM-exit and VM-entry, what's to try next?
>>>
>> If you set vcpu->arch.nmi_pending here there vmx_inject_nmi() will be
>> called inside kvm_x86_ops->inject_pending_irq(vcpu) (if there is not
>> pending exceptions or interrupt at that moment), so if NMI is not
>> injected either you have a bug somewhere (why kvm_vm_exit_on_cnt_overflow
>> is global?) or you guest ignores NMIs. Does your guest react to NMI if
>> you send it via qemu monitor (type "nmi 0" in qemu monitor).
>>
>> Post you code here, may be I'll see something.
>>
>> --
>>                        Gleb.
>>
>
--
To unsubscribe from this list: send the line "unsubscribe kvm" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html

[Index of Archives]     [KVM ARM]     [KVM ia64]     [KVM ppc]     [Virtualization Tools]     [Spice Development]     [Libvirt]     [Libvirt Users]     [Linux USB Devel]     [Linux Audio Users]     [Yosemite Questions]     [Linux Kernel]     [Linux SCSI]     [XFree86]
  Powered by Linux