aboutsummaryrefslogtreecommitdiffstats
path: root/arch/x86/kvm/lapic.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/x86/kvm/lapic.c')
-rw-r--r--arch/x86/kvm/lapic.c48
1 files changed, 40 insertions, 8 deletions
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 02b51dd4e4ad..a8e9369f41c5 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -731,7 +731,11 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
731 case APIC_DM_INIT: 731 case APIC_DM_INIT:
732 if (!trig_mode || level) { 732 if (!trig_mode || level) {
733 result = 1; 733 result = 1;
734 vcpu->arch.mp_state = KVM_MP_STATE_INIT_RECEIVED; 734 /* assumes that there are only KVM_APIC_INIT/SIPI */
735 apic->pending_events = (1UL << KVM_APIC_INIT);
736 /* make sure pending_events is visible before sending
737 * the request */
738 smp_wmb();
735 kvm_make_request(KVM_REQ_EVENT, vcpu); 739 kvm_make_request(KVM_REQ_EVENT, vcpu);
736 kvm_vcpu_kick(vcpu); 740 kvm_vcpu_kick(vcpu);
737 } else { 741 } else {
@@ -743,13 +747,13 @@ static int __apic_accept_irq(struct kvm_lapic *apic, int delivery_mode,
743 case APIC_DM_STARTUP: 747 case APIC_DM_STARTUP:
744 apic_debug("SIPI to vcpu %d vector 0x%02x\n", 748 apic_debug("SIPI to vcpu %d vector 0x%02x\n",
745 vcpu->vcpu_id, vector); 749 vcpu->vcpu_id, vector);
746 if (vcpu->arch.mp_state == KVM_MP_STATE_INIT_RECEIVED) { 750 result = 1;
747 result = 1; 751 apic->sipi_vector = vector;
748 vcpu->arch.sipi_vector = vector; 752 /* make sure sipi_vector is visible for the receiver */
749 vcpu->arch.mp_state = KVM_MP_STATE_SIPI_RECEIVED; 753 smp_wmb();
750 kvm_make_request(KVM_REQ_EVENT, vcpu); 754 set_bit(KVM_APIC_SIPI, &apic->pending_events);
751 kvm_vcpu_kick(vcpu); 755 kvm_make_request(KVM_REQ_EVENT, vcpu);
752 } 756 kvm_vcpu_kick(vcpu);
753 break; 757 break;
754 758
755 case APIC_DM_EXTINT: 759 case APIC_DM_EXTINT:
@@ -1860,6 +1864,34 @@ int kvm_lapic_enable_pv_eoi(struct kvm_vcpu *vcpu, u64 data)
1860 addr); 1864 addr);
1861} 1865}
1862 1866
1867void kvm_apic_accept_events(struct kvm_vcpu *vcpu)
1868{
1869 struct kvm_lapic *apic = vcpu->arch.apic;
1870 unsigned int sipi_vector;
1871
1872 if (!kvm_vcpu_has_lapic(vcpu))
1873 return;
1874
1875 if (test_and_clear_bit(KVM_APIC_INIT, &apic->pending_events)) {
1876 kvm_lapic_reset(vcpu);
1877 kvm_vcpu_reset(vcpu);
1878 if (kvm_vcpu_is_bsp(apic->vcpu))
1879 vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
1880 else
1881 vcpu->arch.mp_state = KVM_MP_STATE_INIT_RECEIVED;
1882 }
1883 if (test_and_clear_bit(KVM_APIC_SIPI, &apic->pending_events) &&
1884 vcpu->arch.mp_state == KVM_MP_STATE_INIT_RECEIVED) {
1885 /* evaluate pending_events before reading the vector */
1886 smp_rmb();
1887 sipi_vector = apic->sipi_vector;
1888 pr_debug("vcpu %d received sipi with vector # %x\n",
1889 vcpu->vcpu_id, sipi_vector);
1890 kvm_vcpu_deliver_sipi_vector(vcpu, sipi_vector);
1891 vcpu->arch.mp_state = KVM_MP_STATE_RUNNABLE;
1892 }
1893}
1894
1863void kvm_lapic_init(void) 1895void kvm_lapic_init(void)
1864{ 1896{
1865 /* do not patch jump label more than once per second */ 1897 /* do not patch jump label more than once per second */