diff options
Diffstat (limited to 'arch/x86/kvm/lapic.c')
-rw-r--r-- | arch/x86/kvm/lapic.c | 48 |
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 | ||
1867 | void 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 | |||
1863 | void kvm_lapic_init(void) | 1895 | void 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 */ |