#define EXIT_REASON_EXTERNAL_INTERRUPT  1
 #define EXIT_REASON_TRIPLE_FAULT        2
 #define EXIT_REASON_INIT_SIGNAL                        3
+#define EXIT_REASON_SIPI_SIGNAL         4
 
 #define EXIT_REASON_INTERRUPT_WINDOW    7
 #define EXIT_REASON_NMI_WINDOW          8
        { EXIT_REASON_EXTERNAL_INTERRUPT,    "EXTERNAL_INTERRUPT" }, \
        { EXIT_REASON_TRIPLE_FAULT,          "TRIPLE_FAULT" }, \
        { EXIT_REASON_INIT_SIGNAL,           "INIT_SIGNAL" }, \
+       { EXIT_REASON_SIPI_SIGNAL,           "SIPI_SIGNAL" }, \
        { EXIT_REASON_INTERRUPT_WINDOW,      "INTERRUPT_WINDOW" }, \
        { EXIT_REASON_NMI_WINDOW,            "NMI_WINDOW" }, \
        { EXIT_REASON_TASK_SWITCH,           "TASK_SWITCH" }, \
 
 static int nested_check_guest_non_reg_state(struct vmcs12 *vmcs12)
 {
        if (CC(vmcs12->guest_activity_state != GUEST_ACTIVITY_ACTIVE &&
-              vmcs12->guest_activity_state != GUEST_ACTIVITY_HLT))
+              vmcs12->guest_activity_state != GUEST_ACTIVITY_HLT &&
+              vmcs12->guest_activity_state != GUEST_ACTIVITY_WAIT_SIPI))
                return -EINVAL;
 
        return 0;
         */
        nested_cache_shadow_vmcs12(vcpu, vmcs12);
 
-       /*
-        * If we're entering a halted L2 vcpu and the L2 vcpu won't be
-        * awakened by event injection or by an NMI-window VM-exit or
-        * by an interrupt-window VM-exit, halt the vcpu.
-        */
-       if ((vmcs12->guest_activity_state == GUEST_ACTIVITY_HLT) &&
-           !(vmcs12->vm_entry_intr_info_field & INTR_INFO_VALID_MASK) &&
-           !(vmcs12->cpu_based_vm_exec_control & CPU_BASED_NMI_WINDOW_EXITING) &&
-           !((vmcs12->cpu_based_vm_exec_control & CPU_BASED_INTR_WINDOW_EXITING) &&
-             (vmcs12->guest_rflags & X86_EFLAGS_IF))) {
+       switch (vmcs12->guest_activity_state) {
+       case GUEST_ACTIVITY_HLT:
+               /*
+                * If we're entering a halted L2 vcpu and the L2 vcpu won't be
+                * awakened by event injection or by an NMI-window VM-exit or
+                * by an interrupt-window VM-exit, halt the vcpu.
+                */
+               if (!(vmcs12->vm_entry_intr_info_field & INTR_INFO_VALID_MASK) &&
+                   !nested_cpu_has(vmcs12, CPU_BASED_NMI_WINDOW_EXITING) &&
+                   !(nested_cpu_has(vmcs12, CPU_BASED_INTR_WINDOW_EXITING) &&
+                     (vmcs12->guest_rflags & X86_EFLAGS_IF))) {
+                       vmx->nested.nested_run_pending = 0;
+                       return kvm_vcpu_halt(vcpu);
+               }
+               break;
+       case GUEST_ACTIVITY_WAIT_SIPI:
                vmx->nested.nested_run_pending = 0;
-               return kvm_vcpu_halt(vcpu);
+               vcpu->arch.mp_state = KVM_MP_STATE_INIT_RECEIVED;
+               break;
+       default:
+               break;
        }
+
        return 1;
 
 vmentry_failed:
                        return -EBUSY;
                nested_vmx_update_pending_dbg(vcpu);
                clear_bit(KVM_APIC_INIT, &apic->pending_events);
-               nested_vmx_vmexit(vcpu, EXIT_REASON_INIT_SIGNAL, 0, 0);
+               if (vcpu->arch.mp_state != KVM_MP_STATE_INIT_RECEIVED)
+                       nested_vmx_vmexit(vcpu, EXIT_REASON_INIT_SIGNAL, 0, 0);
+               return 0;
+       }
+
+       if (lapic_in_kernel(vcpu) &&
+           test_bit(KVM_APIC_SIPI, &apic->pending_events)) {
+               if (block_nested_events)
+                       return -EBUSY;
+
+               clear_bit(KVM_APIC_SIPI, &apic->pending_events);
+               if (vcpu->arch.mp_state == KVM_MP_STATE_INIT_RECEIVED)
+                       nested_vmx_vmexit(vcpu, EXIT_REASON_SIPI_SIGNAL, 0,
+                                               apic->sipi_vector & 0xFFUL);
                return 0;
        }
 
 
        if (vcpu->arch.mp_state == KVM_MP_STATE_HALTED)
                vmcs12->guest_activity_state = GUEST_ACTIVITY_HLT;
+       else if (vcpu->arch.mp_state == KVM_MP_STATE_INIT_RECEIVED)
+               vmcs12->guest_activity_state = GUEST_ACTIVITY_WAIT_SIPI;
        else
                vmcs12->guest_activity_state = GUEST_ACTIVITY_ACTIVE;
 
        msrs->misc_low |=
                MSR_IA32_VMX_MISC_VMWRITE_SHADOW_RO_FIELDS |
                VMX_MISC_EMULATED_PREEMPTION_TIMER_RATE |
-               VMX_MISC_ACTIVITY_HLT;
+               VMX_MISC_ACTIVITY_HLT |
+               VMX_MISC_ACTIVITY_WAIT_SIPI;
        msrs->misc_high = 0;
 
        /*