From: Yang, S. <she...@in...> - 2008-05-08 08:49:47
Attachments:
0003-KVM-VMX-Enable-NMI-with-in-kernel-irqchip.patch
|
From 4942a5c35c97e5edb6fe1303e04fb86f25cac345 Mon Sep 17 00:00:00 2001 From: Sheng Yang <she...@in...> Date: Thu, 8 May 2008 16:00:57 +0800 Subject: [PATCH 3/4] KVM: VMX: Enable NMI with in-kernel irqchip Signed-off-by: Sheng Yang <she...@in...> --- arch/x86/kvm/vmx.c | 133 +++++++++++++++++++++++++++++++++++++------- arch/x86/kvm/vmx.h | 12 ++++- arch/x86/kvm/x86.c | 1 + include/asm-x86/kvm_host.h | 1 + 4 files changed, 125 insertions(+), 22 deletions(-) diff --git a/arch/x86/kvm/vmx.c b/arch/x86/kvm/vmx.c index 26c4f02..55fe525 100644 --- a/arch/x86/kvm/vmx.c +++ b/arch/x86/kvm/vmx.c @@ -260,6 +260,12 @@ static inline int cpu_has_vmx_vpid(void) SECONDARY_EXEC_ENABLE_VPID); } +static inline int cpu_has_virtual_nmis(void) +{ + return (vmcs_config.pin_based_exec_ctrl & + PIN_BASED_VIRTUAL_NMIS); +} + static int __find_msr_index(struct vcpu_vmx *vmx, u32 msr) { int i; @@ -1068,7 +1074,7 @@ static __init int setup_vmcs_config(struct vmcs_config *vmcs_conf) u32 _vmentry_control = 0; min = PIN_BASED_EXT_INTR_MASK | PIN_BASED_NMI_EXITING; - opt = 0; + opt = PIN_BASED_VIRTUAL_NMIS; if (adjust_vmx_controls(min, opt, MSR_IA32_VMX_PINBASED_CTLS, &_pin_based_exec_control) < 0) return -EIO; @@ -2110,6 +2116,13 @@ static void vmx_inject_irq(struct kvm_vcpu *vcpu, int irq) irq | INTR_TYPE_EXT_INTR | INTR_INFO_VALID_MASK); } +static void vmx_inject_nmi(struct kvm_vcpu *vcpu) +{ + vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, + INTR_TYPE_NMI_INTR | INTR_INFO_VALID_MASK | NMI_VECTOR); + vcpu->arch.nmi_pending = 0; +} + static void kvm_do_inject_irq(struct kvm_vcpu *vcpu) { int word_index = __ffs(vcpu->arch.irq_summary); @@ -2146,9 +2159,11 @@ static void do_interrupt_requests(struct kvm_vcpu *vcpu, /* * Interrupts blocked. Wait for unblock. */ - cpu_based_vm_exec_control |= CPU_BASED_VIRTUAL_INTR_PENDING; + cpu_based_vm_exec_control |= + CPU_BASED_VIRTUAL_INTR_PENDING; else - cpu_based_vm_exec_control &= ~CPU_BASED_VIRTUAL_INTR_PENDING; + cpu_based_vm_exec_control &= + ~CPU_BASED_VIRTUAL_INTR_PENDING; vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, cpu_based_vm_exec_control); } @@ -2633,6 +2648,19 @@ static int handle_ept_violation(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) return 1; } +static int handle_nmi_window(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) +{ + u32 cpu_based_vm_exec_control; + + /* clear pending NMI */ + cpu_based_vm_exec_control = vmcs_read32(CPU_BASED_VM_EXEC_CONTROL); + cpu_based_vm_exec_control &= ~CPU_BASED_VIRTUAL_NMI_PENDING; + vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, cpu_based_vm_exec_control); + ++vcpu->stat.nmi_window_exits; + + return 1; +} + /* * The exit handlers return 1 if the exit was handled fully and guest execution * may resume. Otherwise they set the kvm_run parameter to indicate what needs @@ -2643,6 +2671,7 @@ static int (*kvm_vmx_exit_handlers[])(struct kvm_vcpu *vcpu, [EXIT_REASON_EXCEPTION_NMI] = handle_exception, [EXIT_REASON_EXTERNAL_INTERRUPT] = handle_external_interrupt, [EXIT_REASON_TRIPLE_FAULT] = handle_triple_fault, + [EXIT_REASON_NMI_WINDOW] = handle_nmi_window, [EXIT_REASON_IO_INSTRUCTION] = handle_io, [EXIT_REASON_CR_ACCESS] = handle_cr, [EXIT_REASON_DR_ACCESS] = handle_dr, @@ -2730,17 +2759,52 @@ static void enable_irq_window(struct kvm_vcpu *vcpu) vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, cpu_based_vm_exec_control); } +static void enable_nmi_window(struct kvm_vcpu *vcpu) +{ + u32 cpu_based_vm_exec_control; + + if (!cpu_has_virtual_nmis()) + return; + + cpu_based_vm_exec_control = vmcs_read32(CPU_BASED_VM_EXEC_CONTROL); + cpu_based_vm_exec_control |= CPU_BASED_VIRTUAL_NMI_PENDING; + vmcs_write32(CPU_BASED_VM_EXEC_CONTROL, cpu_based_vm_exec_control); +} + +static int vmx_nmi_enabled(struct kvm_vcpu *vcpu) +{ + u32 guest_intr = vmcs_read32(GUEST_INTERRUPTIBILITY_INFO); + return !(guest_intr & (GUEST_INTR_STATE_NMI | + GUEST_INTR_STATE_MOV_SS | + GUEST_INTR_STATE_STI)); +} + +static int vmx_irq_enabled(struct kvm_vcpu *vcpu) +{ + u32 guest_intr = vmcs_read32(GUEST_INTERRUPTIBILITY_INFO); + return (!(guest_intr & (GUEST_INTR_STATE_MOV_SS | + GUEST_INTR_STATE_STI)) && + (vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_IF)); +} + +static void enable_intr_window(struct kvm_vcpu *vcpu) +{ + if (vcpu->arch.nmi_pending) + enable_nmi_window(vcpu); + else if (kvm_cpu_has_interrupt(vcpu)) + enable_irq_window(vcpu); +} + static void vmx_intr_assist(struct kvm_vcpu *vcpu) { struct vcpu_vmx *vmx = to_vmx(vcpu); - u32 idtv_info_field, intr_info_field; - int has_ext_irq, interrupt_window_open; + u32 idtv_info_field, intr_info_field, exit_intr_info_field; int vector; update_tpr_threshold(vcpu); - has_ext_irq = kvm_cpu_has_interrupt(vcpu); intr_info_field = vmcs_read32(VM_ENTRY_INTR_INFO_FIELD); + exit_intr_info_field = vmcs_read32(VM_EXIT_INTR_INFO); idtv_info_field = vmx->idt_vectoring_info; if (intr_info_field & INTR_INFO_VALID_MASK) { if (idtv_info_field & INTR_INFO_VALID_MASK) { @@ -2748,8 +2812,7 @@ static void vmx_intr_assist(struct kvm_vcpu *vcpu) if (printk_ratelimit()) printk(KERN_ERR "Fault when IDT_Vectoring\n"); } - if (has_ext_irq) - enable_irq_window(vcpu); + enable_intr_window(vcpu); return; } if (unlikely(idtv_info_field & INTR_INFO_VALID_MASK)) { @@ -2759,30 +2822,56 @@ static void vmx_intr_assist(struct kvm_vcpu *vcpu) u8 vect = idtv_info_field & VECTORING_INFO_VECTOR_MASK; vmx_inject_irq(vcpu, vect); - if (unlikely(has_ext_irq)) - enable_irq_window(vcpu); + enable_intr_window(vcpu); return; } KVMTRACE_1D(REDELIVER_EVT, vcpu, idtv_info_field, handler); - vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, idtv_info_field); + /* + * SDM 3: 25.7.1.2 + * Clear bit "block by NMI" before VM entry if a NMI delivery + * faulted. + */ + if ((idtv_info_field & VECTORING_INFO_TYPE_MASK) + == INTR_TYPE_NMI_INTR && cpu_has_virtual_nmis()) + vmcs_write32(GUEST_INTERRUPTIBILITY_INFO, + vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) & + ~GUEST_INTR_STATE_NMI); + + vmcs_write32(VM_ENTRY_INTR_INFO_FIELD, idtv_info_field + & ~INTR_INFO_RESVD_BITS_MASK); vmcs_write32(VM_ENTRY_INSTRUCTION_LEN, vmcs_read32(VM_EXIT_INSTRUCTION_LEN)); if (unlikely(idtv_info_field & INTR_INFO_DELIVER_CODE_MASK)) vmcs_write32(VM_ENTRY_EXCEPTION_ERROR_CODE, vmcs_read32(IDT_VECTORING_ERROR_CODE)); - if (unlikely(has_ext_irq)) - enable_irq_window(vcpu); + enable_intr_window(vcpu); return; } - if (!has_ext_irq) + if (cpu_has_virtual_nmis()) { + /* + * SDM 3: 25.7.1.2 + * Re-set bit "block by NMI" before VM entry if vmexit caused by + * a guest IRET fault. + */ + if ((exit_intr_info_field & INTR_INFO_UNBLOCK_NMI) && + (exit_intr_info_field & INTR_INFO_VECTOR_MASK) != 8) + vmcs_write32(GUEST_INTERRUPTIBILITY_INFO, + vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) | + GUEST_INTR_STATE_NMI); + else if (vcpu->arch.nmi_pending) { + if (vmx_nmi_enabled(vcpu)) + vmx_inject_nmi(vcpu); + enable_intr_window(vcpu); + return; + } + + } + if (!kvm_cpu_has_interrupt(vcpu)) return; - interrupt_window_open = - ((vmcs_readl(GUEST_RFLAGS) & X86_EFLAGS_IF) && - (vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) & 3) == 0); - if (interrupt_window_open) { + if (vmx_irq_enabled(vcpu)) { vector = kvm_cpu_get_interrupt(vcpu); vmx_inject_irq(vcpu, vector); kvm_timer_intr_post(vcpu, vector); @@ -2943,7 +3032,8 @@ static void vmx_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) fixup_rmode_irq(vmx); vcpu->arch.interrupt_window_open = - (vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) & 3) == 0; + (vmcs_read32(GUEST_INTERRUPTIBILITY_INFO) & + (GUEST_INTR_STATE_STI | GUEST_INTR_STATE_MOV_SS)) == 0; asm("mov %0, %%ds; mov %0, %%es" : : "r"(__USER_DS)); vmx->launched = 1; @@ -2951,9 +3041,10 @@ static void vmx_vcpu_run(struct kvm_vcpu *vcpu, struct kvm_run *kvm_run) intr_info = vmcs_read32(VM_EXIT_INTR_INFO); /* We need to handle NMIs before interrupts are enabled */ - if ((intr_info & INTR_INFO_INTR_TYPE_MASK) == 0x200) { /* nmi */ + if ((intr_info & INTR_INFO_INTR_TYPE_MASK) == 0x200) { KVMTRACE_0D(NMI, vcpu, handler); - asm("int $2"); + if (!cpu_has_virtual_nmis()) + asm("int $2"); } } diff --git a/arch/x86/kvm/vmx.h b/arch/x86/kvm/vmx.h index 79d94c6..425a134 100644 --- a/arch/x86/kvm/vmx.h +++ b/arch/x86/kvm/vmx.h @@ -40,6 +40,7 @@ #define CPU_BASED_CR8_LOAD_EXITING 0x00080000 #define CPU_BASED_CR8_STORE_EXITING 0x00100000 #define CPU_BASED_TPR_SHADOW 0x00200000 +#define CPU_BASED_VIRTUAL_NMI_PENDING 0x00400000 #define CPU_BASED_MOV_DR_EXITING 0x00800000 #define CPU_BASED_UNCOND_IO_EXITING 0x01000000 #define CPU_BASED_USE_IO_BITMAPS 0x02000000 @@ -216,7 +217,7 @@ enum vmcs_field { #define EXIT_REASON_TRIPLE_FAULT 2 #define EXIT_REASON_PENDING_INTERRUPT 7 - +#define EXIT_REASON_NMI_WINDOW 8 #define EXIT_REASON_TASK_SWITCH 9 #define EXIT_REASON_CPUID 10 #define EXIT_REASON_HLT 12 @@ -251,7 +252,9 @@ enum vmcs_field { #define INTR_INFO_VECTOR_MASK 0xff /* 7:0 */ #define INTR_INFO_INTR_TYPE_MASK 0x700 /* 10:8 */ #define INTR_INFO_DELIVER_CODE_MASK 0x800 /* 11 */ +#define INTR_INFO_UNBLOCK_NMI 0x1000 /* 12 */ #define INTR_INFO_VALID_MASK 0x80000000 /* 31 */ +#define INTR_INFO_RESVD_BITS_MASK 0x7ffff000 #define VECTORING_INFO_VECTOR_MASK INTR_INFO_VECTOR_MASK #define VECTORING_INFO_TYPE_MASK INTR_INFO_INTR_TYPE_MASK @@ -259,9 +262,16 @@ enum vmcs_field { #define VECTORING_INFO_VALID_MASK INTR_INFO_VALID_MASK #define INTR_TYPE_EXT_INTR (0 << 8) /* external interrupt */ +#define INTR_TYPE_NMI_INTR (2 << 8) /* NMI */ #define INTR_TYPE_EXCEPTION (3 << 8) /* processor exception */ #define INTR_TYPE_SOFT_INTR (4 << 8) /* software interrupt */ +/* GUEST_INTERRUPTIBILITY_INFO flags. */ +#define GUEST_INTR_STATE_STI 0x00000001 +#define GUEST_INTR_STATE_MOV_SS 0x00000002 +#define GUEST_INTR_STATE_SMI 0x00000004 +#define GUEST_INTR_STATE_NMI 0x00000008 + /* * Exit Qualifications for MOV for Control Register Access */ diff --git a/arch/x86/kvm/x86.c b/arch/x86/kvm/x86.c index f95ebdb..16e9cd2 100644 --- a/arch/x86/kvm/x86.c +++ b/arch/x86/kvm/x86.c @@ -72,6 +72,7 @@ struct kvm_stats_debugfs_item debugfs_entries[] = { { "mmio_exits", VCPU_STAT(mmio_exits) }, { "signal_exits", VCPU_STAT(signal_exits) }, { "irq_window", VCPU_STAT(irq_window_exits) }, + { "nmi_window", VCPU_STAT(nmi_window_exits) }, { "halt_exits", VCPU_STAT(halt_exits) }, { "halt_wakeup", VCPU_STAT(halt_wakeup) }, { "hypercalls", VCPU_STAT(hypercalls) }, diff --git a/include/asm-x86/kvm_host.h b/include/asm-x86/kvm_host.h index 2df8416..277216c 100644 --- a/include/asm-x86/kvm_host.h +++ b/include/asm-x86/kvm_host.h @@ -344,6 +344,7 @@ struct kvm_vcpu_stat { u32 mmio_exits; u32 signal_exits; u32 irq_window_exits; + u32 nmi_window_exits; u32 halt_exits; u32 halt_wakeup; u32 request_irq_exits; -- 1.5.5 |
From: Avi K. <av...@qu...> - 2008-05-09 16:02:29
|
Yang, Sheng wrote: > From 4942a5c35c97e5edb6fe1303e04fb86f25cac345 Mon Sep 17 00:00:00 2001 > From: Sheng Yang <she...@in...> > Date: Thu, 8 May 2008 16:00:57 +0800 > Subject: [PATCH 3/4] KVM: VMX: Enable NMI with in-kernel irqchip > > > static void kvm_do_inject_irq(struct kvm_vcpu *vcpu) > { > int word_index = __ffs(vcpu->arch.irq_summary); > @@ -2146,9 +2159,11 @@ static void do_interrupt_requests(struct kvm_vcpu > *vcpu, > /* > * Interrupts blocked. Wait for unblock. > */ > - cpu_based_vm_exec_control |= CPU_BASED_VIRTUAL_INTR_PENDING; > + cpu_based_vm_exec_control |= > + CPU_BASED_VIRTUAL_INTR_PENDING; > else > - cpu_based_vm_exec_control &= ~CPU_BASED_VIRTUAL_INTR_PENDING; > + cpu_based_vm_exec_control &= > + ~CPU_BASED_VIRTUAL_INTR_PENDING; > This seems spurious. > /* We need to handle NMIs before interrupts are enabled */ > - if ((intr_info & INTR_INFO_INTR_TYPE_MASK) == 0x200) { /* nmi */ > + if ((intr_info & INTR_INFO_INTR_TYPE_MASK) == 0x200) { > KVMTRACE_0D(NMI, vcpu, handler); > - asm("int $2"); > + if (!cpu_has_virtual_nmis()) > + asm("int $2"); > } > } > That's a host nmi. So does the PIN_BASED_VIRTUAL_NMI mean NMIs are handled like unacked host interrupts? -- Do not meddle in the internals of kernels, for they are subtle and quick to panic. |
From: Yang, S. <she...@in...> - 2008-05-12 05:13:16
|
On Friday 09 May 2008 23:49:13 Avi Kivity wrote: > Yang, Sheng wrote: > > From 4942a5c35c97e5edb6fe1303e04fb86f25cac345 Mon Sep 17 00:00:00 2001 > > From: Sheng Yang <she...@in...> > > Date: Thu, 8 May 2008 16:00:57 +0800 > > Subject: [PATCH 3/4] KVM: VMX: Enable NMI with in-kernel irqchip > > > > > > static void kvm_do_inject_irq(struct kvm_vcpu *vcpu) > > { > > int word_index = __ffs(vcpu->arch.irq_summary); > > @@ -2146,9 +2159,11 @@ static void do_interrupt_requests(struct kvm_vcpu > > *vcpu, > > /* > > * Interrupts blocked. Wait for unblock. > > */ > > - cpu_based_vm_exec_control |= CPU_BASED_VIRTUAL_INTR_PENDING; > > + cpu_based_vm_exec_control |= > > + CPU_BASED_VIRTUAL_INTR_PENDING; > > else > > - cpu_based_vm_exec_control &= ~CPU_BASED_VIRTUAL_INTR_PENDING; > > + cpu_based_vm_exec_control &= > > + ~CPU_BASED_VIRTUAL_INTR_PENDING; > > This seems spurious. Sorry, seems I am too anxious to keep it in hand... I would like to check it much careful in the future. > > > /* We need to handle NMIs before interrupts are enabled */ > > - if ((intr_info & INTR_INFO_INTR_TYPE_MASK) == 0x200) { /* nmi */ > > + if ((intr_info & INTR_INFO_INTR_TYPE_MASK) == 0x200) { > > KVMTRACE_0D(NMI, vcpu, handler); > > - asm("int $2"); > > + if (!cpu_has_virtual_nmis()) > > + asm("int $2"); > > } > > } > > That's a host nmi. So does the PIN_BASED_VIRTUAL_NMI mean NMIs are > handled like unacked host interrupts? Not exactly. No host NMI here if Virtual_NMI is set. Copy from SDM 3B table 20-5: "If this control(Virtual NMIs) is 1, NMIs are never blocked and the “blocking by NMI” bit (bit 3) in the interruptibility-state field indicates “virtual-NMI blocking” (see Table 20-3). This control also interacts with the “NMI-window exiting” VM-execution control (see Section 20.6.2)." -- Thanks Yang, Sheng |
From: Avi K. <av...@qu...> - 2008-05-12 07:54:00
|
Yang, Sheng wrote: > On Friday 09 May 2008 23:49:13 Avi Kivity wrote: > >> Yang, Sheng wrote: >> >>> From 4942a5c35c97e5edb6fe1303e04fb86f25cac345 Mon Sep 17 00:00:00 2001 >>> From: Sheng Yang <she...@in...> >>> Date: Thu, 8 May 2008 16:00:57 +0800 >>> Subject: [PATCH 3/4] KVM: VMX: Enable NMI with in-kernel irqchip >>> >>> >>> static void kvm_do_inject_irq(struct kvm_vcpu *vcpu) >>> { >>> int word_index = __ffs(vcpu->arch.irq_summary); >>> @@ -2146,9 +2159,11 @@ static void do_interrupt_requests(struct kvm_vcpu >>> *vcpu, >>> /* >>> * Interrupts blocked. Wait for unblock. >>> */ >>> - cpu_based_vm_exec_control |= CPU_BASED_VIRTUAL_INTR_PENDING; >>> + cpu_based_vm_exec_control |= >>> + CPU_BASED_VIRTUAL_INTR_PENDING; >>> else >>> - cpu_based_vm_exec_control &= ~CPU_BASED_VIRTUAL_INTR_PENDING; >>> + cpu_based_vm_exec_control &= >>> + ~CPU_BASED_VIRTUAL_INTR_PENDING; >>> >> This seems spurious. >> > > Sorry, seems I am too anxious to keep it in hand... I would like to check it > much careful in the future. > > >>> /* We need to handle NMIs before interrupts are enabled */ >>> - if ((intr_info & INTR_INFO_INTR_TYPE_MASK) == 0x200) { /* nmi */ >>> + if ((intr_info & INTR_INFO_INTR_TYPE_MASK) == 0x200) { >>> KVMTRACE_0D(NMI, vcpu, handler); >>> - asm("int $2"); >>> + if (!cpu_has_virtual_nmis()) >>> + asm("int $2"); >>> } >>> } >>> >> That's a host nmi. So does the PIN_BASED_VIRTUAL_NMI mean NMIs are >> handled like unacked host interrupts? >> > > Not exactly. No host NMI here if Virtual_NMI is set. Copy from SDM 3B table > 20-5: > > "If this control(Virtual NMIs) is 1, NMIs are never blocked and the “blocking > by NMI” bit (bit 3) in the interruptibility-state field > indicates “virtual-NMI blocking” (see Table 20-3). This control also > interacts with the “NMI-window exiting” VM-execution control (see Section > 20.6.2)." > I still don't understand. What does "NMIs are never blocked" mean? what happens if an NMI occurs while in guest mode? Obviously we don't want it to be delivered to the guest. -- error compiling committee.c: too many arguments to function |
From: Yang, S. <she...@in...> - 2008-05-13 06:36:16
|
On Monday 12 May 2008 15:54:00 Avi Kivity wrote: > Yang, Sheng wrote: > > On Friday 09 May 2008 23:49:13 Avi Kivity wrote: > >> Yang, Sheng wrote: > >>> From 4942a5c35c97e5edb6fe1303e04fb86f25cac345 Mon Sep 17 00:00:00 2001 > >>> From: Sheng Yang <she...@in...> > >>> Date: Thu, 8 May 2008 16:00:57 +0800 > >>> Subject: [PATCH 3/4] KVM: VMX: Enable NMI with in-kernel irqchip > >>> > >>> > >>> static void kvm_do_inject_irq(struct kvm_vcpu *vcpu) > >>> { > >>> int word_index = __ffs(vcpu->arch.irq_summary); > >>> @@ -2146,9 +2159,11 @@ static void do_interrupt_requests(struct > >>> kvm_vcpu *vcpu, > >>> /* > >>> * Interrupts blocked. Wait for unblock. > >>> */ > >>> - cpu_based_vm_exec_control |= CPU_BASED_VIRTUAL_INTR_PENDING; > >>> + cpu_based_vm_exec_control |= > >>> + CPU_BASED_VIRTUAL_INTR_PENDING; > >>> else > >>> - cpu_based_vm_exec_control &= ~CPU_BASED_VIRTUAL_INTR_PENDING; > >>> + cpu_based_vm_exec_control &= > >>> + ~CPU_BASED_VIRTUAL_INTR_PENDING; > >> > >> This seems spurious. > > > > Sorry, seems I am too anxious to keep it in hand... I would like to check > > it much careful in the future. > > > >>> /* We need to handle NMIs before interrupts are enabled */ > >>> - if ((intr_info & INTR_INFO_INTR_TYPE_MASK) == 0x200) { /* nmi */ > >>> + if ((intr_info & INTR_INFO_INTR_TYPE_MASK) == 0x200) { > >>> KVMTRACE_0D(NMI, vcpu, handler); > >>> - asm("int $2"); > >>> + if (!cpu_has_virtual_nmis()) > >>> + asm("int $2"); > >>> } > >>> } > >> > >> That's a host nmi. So does the PIN_BASED_VIRTUAL_NMI mean NMIs are > >> handled like unacked host interrupts? > > > > Not exactly. No host NMI here if Virtual_NMI is set. Copy from SDM 3B > > table 20-5: > > > > "If this control(Virtual NMIs) is 1, NMIs are never blocked and the > > “blocking by NMI” bit (bit 3) in the interruptibility-state field > > indicates “virtual-NMI blocking” (see Table 20-3). This control also > > interacts with the “NMI-window exiting” VM-execution control (see Section > > 20.6.2)." > > I still don't understand. What does "NMIs are never blocked" mean? > what happens if an NMI occurs while in guest mode? Obviously we don't > want it to be delivered to the guest. Oops, I neglected it... When virtual_nmi is set, the host NMI would routed to handle_exception. And we would handle it there, by judged the vector number. I will posted the updated patchset soon. -- Thanks Yang, Sheng |
From: Yang, S. <she...@in...> - 2008-05-13 07:18:00
|
On Tuesday 13 May 2008 14:42:17 Yang, Sheng wrote: > On Monday 12 May 2008 15:54:00 Avi Kivity wrote: > > Yang, Sheng wrote: > > > On Friday 09 May 2008 23:49:13 Avi Kivity wrote: > > >> Yang, Sheng wrote: > > >>> From 4942a5c35c97e5edb6fe1303e04fb86f25cac345 Mon Sep 17 00:00:00 > > >>> 2001 From: Sheng Yang <she...@in...> > > >>> Date: Thu, 8 May 2008 16:00:57 +0800 > > >>> Subject: [PATCH 3/4] KVM: VMX: Enable NMI with in-kernel irqchip > > >>> > > >>> > > >>> static void kvm_do_inject_irq(struct kvm_vcpu *vcpu) > > >>> { > > >>> int word_index = __ffs(vcpu->arch.irq_summary); > > >>> @@ -2146,9 +2159,11 @@ static void do_interrupt_requests(struct > > >>> kvm_vcpu *vcpu, > > >>> /* > > >>> * Interrupts blocked. Wait for unblock. > > >>> */ > > >>> - cpu_based_vm_exec_control |= CPU_BASED_VIRTUAL_INTR_PENDING; > > >>> + cpu_based_vm_exec_control |= > > >>> + CPU_BASED_VIRTUAL_INTR_PENDING; > > >>> else > > >>> - cpu_based_vm_exec_control &= ~CPU_BASED_VIRTUAL_INTR_PENDING; > > >>> + cpu_based_vm_exec_control &= > > >>> + ~CPU_BASED_VIRTUAL_INTR_PENDING; > > >> > > >> This seems spurious. > > > > > > Sorry, seems I am too anxious to keep it in hand... I would like to > > > check it much careful in the future. > > > > > >>> /* We need to handle NMIs before interrupts are enabled */ > > >>> - if ((intr_info & INTR_INFO_INTR_TYPE_MASK) == 0x200) { /* nmi */ > > >>> + if ((intr_info & INTR_INFO_INTR_TYPE_MASK) == 0x200) { > > >>> KVMTRACE_0D(NMI, vcpu, handler); > > >>> - asm("int $2"); > > >>> + if (!cpu_has_virtual_nmis()) > > >>> + asm("int $2"); > > >>> } > > >>> } > > >> > > >> That's a host nmi. So does the PIN_BASED_VIRTUAL_NMI mean NMIs are > > >> handled like unacked host interrupts? > > > > > > Not exactly. No host NMI here if Virtual_NMI is set. Copy from SDM 3B > > > table 20-5: > > > > > > "If this control(Virtual NMIs) is 1, NMIs are never blocked and the > > > “blocking by NMI” bit (bit 3) in the interruptibility-state field > > > indicates “virtual-NMI blocking” (see Table 20-3). This control also > > > interacts with the “NMI-window exiting” VM-execution control (see > > > Section 20.6.2)." > > > > I still don't understand. What does "NMIs are never blocked" mean? > > what happens if an NMI occurs while in guest mode? Obviously we don't > > want it to be delivered to the guest. > > Oops, I neglected it... When virtual_nmi is set, the host NMI would routed > to handle_exception. And we would handle it there, by judged the vector > number. > > I will posted the updated patchset soon. Faint, misunderstood again... Seems the cold affact my thinking... Anyway, I will updated my patchset. Thanks! -- Thanks Yang, Sheng |