Re: [PATCH] KVM: nVMX: Fix the NMI IDT-vectoring info handling

2016-09-22 Thread Jan Kiszka
On 2016-09-22 11:45, Wanpeng Li wrote:
> 2016-09-22 17:37 GMT+08:00 Paolo Bonzini :
>>
>>
>> On 22/09/2016 05:34, Wanpeng Li wrote:
>>> - if (vmx->rmode.vm86_active) {
>>> - if (kvm_inject_realmode_interrupt(vcpu, NMI_VECTOR, 0) != 
>>> EMULATE_DONE)
>>> - kvm_make_request(KVM_REQ_TRIPLE_FAULT, vcpu);
>>> - return;
>>> + ++vcpu->stat.nmi_injections;
>>> + vmx->nmi_known_unmasked = false;
>>> + if (vmx->rmode.vm86_active) {
>>> + if (kvm_inject_realmode_interrupt(vcpu, NMI_VECTOR, 
>>> 0) != EMULATE_DONE)
>>> + kvm_make_request(KVM_REQ_TRIPLE_FAULT, vcpu);
>>> + return;
>>> + }
>>>   }
>>>   vmcs_write32(VM_ENTRY_INTR_INFO_FIELD,
>>>   INTR_TYPE_NMI_INTR | INTR_INFO_VALID_MASK | 
>>> NMI_VECTOR);
>>
>> Hi,
>>
>> the patch is mostly okay but the "if (vmx->rmode.vm86_active)" part
>> should be done also if the VCPU is in guest mode.  See
>> vmx_queue_exception for a similar example.
> 
> Thanks for pointing out. :)
> 
>>
>> I would like to know which processors lack virtual NMI support.  I'd
>> rather rip that code out...
> 
> At least the Sandy Bridge server on my hand supports Virtual NMIs, I
> don't have machine older than this.

IIRC, my last-but-one notebook was lacking vNMI, and that was a Core 2
Duo. Maybe there are embedded product out there relying on this
emulation, but I don't have any evidence.

Jan

-- 
Siemens AG, Corporate Technology, CT RDA ITP SES-DE
Corporate Competence Center Embedded Linux


Re: [PATCH] KVM: nVMX: Fix the NMI IDT-vectoring info handling

2016-09-22 Thread Wanpeng Li
2016-09-22 17:37 GMT+08:00 Paolo Bonzini :
>
>
> On 22/09/2016 05:34, Wanpeng Li wrote:
>> - if (vmx->rmode.vm86_active) {
>> - if (kvm_inject_realmode_interrupt(vcpu, NMI_VECTOR, 0) != 
>> EMULATE_DONE)
>> - kvm_make_request(KVM_REQ_TRIPLE_FAULT, vcpu);
>> - return;
>> + ++vcpu->stat.nmi_injections;
>> + vmx->nmi_known_unmasked = false;
>> + if (vmx->rmode.vm86_active) {
>> + if (kvm_inject_realmode_interrupt(vcpu, NMI_VECTOR, 0) 
>> != EMULATE_DONE)
>> + kvm_make_request(KVM_REQ_TRIPLE_FAULT, vcpu);
>> + return;
>> + }
>>   }
>>   vmcs_write32(VM_ENTRY_INTR_INFO_FIELD,
>>   INTR_TYPE_NMI_INTR | INTR_INFO_VALID_MASK | 
>> NMI_VECTOR);
>
> Hi,
>
> the patch is mostly okay but the "if (vmx->rmode.vm86_active)" part
> should be done also if the VCPU is in guest mode.  See
> vmx_queue_exception for a similar example.

Thanks for pointing out. :)

>
> I would like to know which processors lack virtual NMI support.  I'd
> rather rip that code out...

At least the Sandy Bridge server on my hand supports Virtual NMIs, I
don't have machine older than this.

Regards,
Wanpeng Li


Re: [PATCH] KVM: nVMX: Fix the NMI IDT-vectoring info handling

2016-09-22 Thread Paolo Bonzini


On 22/09/2016 05:34, Wanpeng Li wrote:
> - if (vmx->rmode.vm86_active) {
> - if (kvm_inject_realmode_interrupt(vcpu, NMI_VECTOR, 0) != 
> EMULATE_DONE)
> - kvm_make_request(KVM_REQ_TRIPLE_FAULT, vcpu);
> - return;
> + ++vcpu->stat.nmi_injections;
> + vmx->nmi_known_unmasked = false;
> + if (vmx->rmode.vm86_active) {
> + if (kvm_inject_realmode_interrupt(vcpu, NMI_VECTOR, 0) 
> != EMULATE_DONE)
> + kvm_make_request(KVM_REQ_TRIPLE_FAULT, vcpu);
> + return;
> + }
>   }
>   vmcs_write32(VM_ENTRY_INTR_INFO_FIELD,
>   INTR_TYPE_NMI_INTR | INTR_INFO_VALID_MASK | NMI_VECTOR);

Hi,

the patch is mostly okay but the "if (vmx->rmode.vm86_active)" part
should be done also if the VCPU is in guest mode.  See
vmx_queue_exception for a similar example.

I would like to know which processors lack virtual NMI support.  I'd
rather rip that code out...

Thanks,

Paolo


[PATCH] KVM: nVMX: Fix the NMI IDT-vectoring info handling

2016-09-21 Thread Wanpeng Li
From: Wanpeng Li 

Run kvm-unit-tests/eventinj.flat in L1:

Sending NMI to self
After NMI to self
FAIL: NMI

This test scenario is to test whether VMM can handle NMI IDT-vectoring info 
correctly.

At the beginning, L2 writes LAPIC to send a self NMI, the EPT page tables on 
both L1 
and L0 are empty so:

- The L2 accesses memory can generate EPT violation which can be intercepted by 
L0.

  The EPT violation vmexit occurred during delivery of this NMI, and the NMI 
info is 
  recorded in vmcs02's IDT-vectoring info.

- L0 walks L1's EPT12 and L0 sees the mapping is invalid, it injects the EPT 
violation into L1.

  The vmcs02's IDT-vectoring info is reflected to vmcs12's IDT-vectoring info 
since 
  it is a nested vmexit. 
  
- L1 receives the EPT violation, then fixes its EPT12.
- L1 executes VMRESUME to resume L2 which generates vmexit and causes L1 exits 
to L0.
- L0 emulates VMRESUME which is called from L1, then return to L2.

  L0 merges the requirement of vmcs12's IDT-vectoring info and injects it to L2 
through 
  vmcs02.

- The L2 re-executes the fault instruction and cause EPT violation again.
- Since the L1's EPT12 is valid, L0 can fix its EPT02
- L0 resume L2

  The EPT violation vmexit occurred during delivery of this NMI again, and the 
NMI info 
  is recorded in vmcs02's IDT-vectoring info. L0 should inject the NMI through 
vmentry 
  event injection since it is caused by EPT02's EPT violation.

However, vmx_inject_nmi() refuses to inject NMI from IDT-vectoring info if vCPU 
is in 
guest mode, this patch fix it by permitting to inject NMI from IDT-vectoring if 
it is 
the L0's responsibility to inject NMI from IDT-vectoring info to L2.

Cc: Paolo Bonzini 
Cc: Radim Krčmář 
Cc: Jan Kiszka 
Cc: Bandan Das 
Signed-off-by: Wanpeng Li 
---
 arch/x86/kvm/vmx.c | 41 -
 1 file changed, 20 insertions(+), 21 deletions(-)

diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c
index 813658d..c883d73 100644
--- a/arch/x86/kvm/vmx.c
+++ b/arch/x86/kvm/vmx.c
@@ -5309,28 +5309,27 @@ static void vmx_inject_nmi(struct kvm_vcpu *vcpu)
 {
struct vcpu_vmx *vmx = to_vmx(vcpu);
 
-   if (is_guest_mode(vcpu))
-   return;
-
-   if (!cpu_has_virtual_nmis()) {
-   /*
-* Tracking the NMI-blocked state in software is built upon
-* finding the next open IRQ window. This, in turn, depends on
-* well-behaving guests: They have to keep IRQs disabled at
-* least as long as the NMI handler runs. Otherwise we may
-* cause NMI nesting, maybe breaking the guest. But as this is
-* highly unlikely, we can live with the residual risk.
-*/
-   vmx->soft_vnmi_blocked = 1;
-   vmx->vnmi_blocked_time = 0;
-   }
+   if (!is_guest_mode(vcpu)) {
+   if (!cpu_has_virtual_nmis()) {
+   /*
+* Tracking the NMI-blocked state in software is built 
upon
+* finding the next open IRQ window. This, in turn, 
depends on
+* well-behaving guests: They have to keep IRQs 
disabled at
+* least as long as the NMI handler runs. Otherwise we 
may
+* cause NMI nesting, maybe breaking the guest. But as 
this is
+* highly unlikely, we can live with the residual risk.
+*/
+   vmx->soft_vnmi_blocked = 1;
+   vmx->vnmi_blocked_time = 0;
+   }
 
-   ++vcpu->stat.nmi_injections;
-   vmx->nmi_known_unmasked = false;
-   if (vmx->rmode.vm86_active) {
-   if (kvm_inject_realmode_interrupt(vcpu, NMI_VECTOR, 0) != 
EMULATE_DONE)
-   kvm_make_request(KVM_REQ_TRIPLE_FAULT, vcpu);
-   return;
+   ++vcpu->stat.nmi_injections;
+   vmx->nmi_known_unmasked = false;
+   if (vmx->rmode.vm86_active) {
+   if (kvm_inject_realmode_interrupt(vcpu, NMI_VECTOR, 0) 
!= EMULATE_DONE)
+   kvm_make_request(KVM_REQ_TRIPLE_FAULT, vcpu);
+   return;
+   }
}
vmcs_write32(VM_ENTRY_INTR_INFO_FIELD,
INTR_TYPE_NMI_INTR | INTR_INFO_VALID_MASK | NMI_VECTOR);
-- 
1.9.1