Adds KVM_EXIT_IOAPIC_EOI which allows the kernel to EOI level-triggered IOAPIC interrupts. Uses a per VCPU exit bitmap to decide whether or not the IOAPIC needs to be informed (which is identical to the EOI_EXIT_BITMAP field used by modern x86 processors, but can also be used to elide kvm IOAPIC EOI exits on older processors). [Note: A prototype using ResampleFDs found that decoupling the EOI from the VCPU's thread made it possible for the VCPU to not see a recent EOI after reentering the guest. This does not match real hardware.] Compile tested for Intel x86.
Unified · Split
| @@ -3309,6 +3309,18 @@ Valid values for 'type' are: · 3308 unmodified lines | |||
| 3309 | to ignore the request, or to gather VM memory core dump and/or | 3309 | to ignore the request, or to gather VM memory core dump and/or |
| 3310 | reset/shutdown of the VM. | 3310 | reset/shutdown of the VM. |
| 3311 | 3311 | ||
| 3312 | /* KVM_EXIT_IOAPIC_EOI */ | ||
| 3313 | struct { | ||
| 3314 | __u8 vector; | ||
| 3315 | } eoi; | ||
| 3316 | |||
| 3317 | Indicates that the VCPU's in-kernel local APIC received an EOI for a | ||
| 3318 | level-triggered IOAPIC interrupt. This exit only triggers when the | ||
| 3319 | IOAPIC is implemented in userspace (i.e. KVM_CAP_SPLIT_IRQCHIP is enabled); | ||
| 3320 | the userspace IOAPIC should process the EOI and retrigger the interrupt if | ||
| 3321 | it is still asserted. Vector is the LAPIC interrupt vector for which the | ||
| 3322 | EOI was received. | ||
| 3323 | |||
| 3312 | /* Fix the size of the union. */ | 3324 | /* Fix the size of the union. */ |
| 3313 | char padding[256]; | 3325 | char padding[256]; |
| 3314 | }; | 3326 | }; |
| @@ -574,6 +574,8 @@ struct kvm_vcpu_arch { · 573 unmodified lines | |||
| 574 | struct { | 574 | struct { |
| 575 | bool pv_unhalted; | 575 | bool pv_unhalted; |
| 576 | } pv; | 576 | } pv; |
| 577 | |||
| 578 | int pending_ioapic_eoi; | ||
| 577 | }; | 579 | }; |
| 578 | 580 | ||
| 579 | struct kvm_lpage_info { | 581 | struct kvm_lpage_info { |
| @@ -877,15 +877,25 @@ static bool kvm_ioapic_handles_vector(struct kvm_lapic *apic, int vector) · 876 unmodified lines | |||
| 877 | 877 | ||
| 878 | static void kvm_ioapic_send_eoi(struct kvm_lapic *apic, int vector) | 878 | static void kvm_ioapic_send_eoi(struct kvm_lapic *apic, int vector) |
| 879 | { | 879 | { |
| 880 | if (kvm_ioapic_handles_vector(apic, vector)) { | 880 | int trigger_mode; |
| 881 | int trigger_mode; | 881 | |
| 882 | if (apic_test_vector(vector, apic->regs + APIC_TMR)) | 882 | /* Eoi the ioapic only if the ioapic doesn't own the vector. */ |
| 883 | trigger_mode = IOAPIC_LEVEL_TRIG; | 883 | if (!kvm_ioapic_handles_vector(apic, vector)) |
| 884 | else | 884 | return; |
| 885 | trigger_mode = IOAPIC_EDGE_TRIG; | ||
| 886 | 885 | ||
| 887 | kvm_ioapic_update_eoi(apic->vcpu, vector, trigger_mode); | 886 | /* Request a KVM exit to inform the userspace IOAPIC. */ |
| 887 | if (irqchip_split(apic->vcpu->kvm)) { | ||
| 888 | apic->vcpu->arch.pending_ioapic_eoi = vector; | ||
| 889 | kvm_make_request(KVM_REQ_IOAPIC_EOI_EXIT, apic->vcpu); | ||
| 890 | return; | ||
| 888 | } | 891 | } |
| 892 | |||
| 893 | if (apic_test_vector(vector, apic->regs + APIC_TMR)) | ||
| 894 | trigger_mode = IOAPIC_LEVEL_TRIG; | ||
| 895 | else | ||
| 896 | trigger_mode = IOAPIC_EDGE_TRIG; | ||
| 897 | |||
| 898 | kvm_ioapic_update_eoi(apic->vcpu, vector, trigger_mode); | ||
| 889 | } | 899 | } |
| 890 | 900 | ||
| 891 | static int apic_set_eoi(struct kvm_lapic *apic) | 901 | static int apic_set_eoi(struct kvm_lapic *apic) |
| @@ -6271,6 +6271,17 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu) · 6270 unmodified lines | |||
| 6271 | kvm_pmu_handle_event(vcpu); | 6271 | kvm_pmu_handle_event(vcpu); |
| 6272 | if (kvm_check_request(KVM_REQ_PMI, vcpu)) | 6272 | if (kvm_check_request(KVM_REQ_PMI, vcpu)) |
| 6273 | kvm_pmu_deliver_pmi(vcpu); | 6273 | kvm_pmu_deliver_pmi(vcpu); |
| 6274 | if (kvm_check_request(KVM_REQ_IOAPIC_EOI_EXIT, vcpu)) { | ||
| 6275 | BUG_ON(vcpu->arch.pending_ioapic_eoi > 255); | ||
| 6276 | if (test_bit(vcpu->arch.pending_ioapic_eoi, | ||
| 6277 | (void *) vcpu->arch.eoi_exit_bitmap)) { | ||
| 6278 | vcpu->run->exit_reason = KVM_EXIT_IOAPIC_EOI; | ||
| 6279 | vcpu->run->eoi.vector = | ||
| 6280 | vcpu->arch.pending_ioapic_eoi; | ||
| 6281 | r = 0; | ||
| 6282 | goto out; | ||
| 6283 | } | ||
| 6284 | } | ||
| 6274 | if (kvm_check_request(KVM_REQ_SCAN_IOAPIC, vcpu)) | 6285 | if (kvm_check_request(KVM_REQ_SCAN_IOAPIC, vcpu)) |
| 6275 | vcpu_scan_ioapic(vcpu); | 6286 | vcpu_scan_ioapic(vcpu); |
| 6276 | if (kvm_check_request(KVM_REQ_APIC_PAGE_RELOAD, vcpu)) | 6287 | if (kvm_check_request(KVM_REQ_APIC_PAGE_RELOAD, vcpu)) |
| @@ -140,6 +140,7 @@ static inline bool is_error_page(struct page *page) · 139 unmodified lines | |||
| 140 | #define KVM_REQ_APIC_PAGE_RELOAD 25 | 140 | #define KVM_REQ_APIC_PAGE_RELOAD 25 |
| 141 | #define KVM_REQ_SMI 26 | 141 | #define KVM_REQ_SMI 26 |
| 142 | #define KVM_REQ_HV_CRASH 27 | 142 | #define KVM_REQ_HV_CRASH 27 |
| 143 | #define KVM_REQ_IOAPIC_EOI_EXIT 28 | ||
| 143 | 144 | ||
| 144 | #define KVM_USERSPACE_IRQ_SOURCE_ID 0 | 145 | #define KVM_USERSPACE_IRQ_SOURCE_ID 0 |
| 145 | #define KVM_IRQFD_RESAMPLE_IRQ_SOURCE_ID 1 | 146 | #define KVM_IRQFD_RESAMPLE_IRQ_SOURCE_ID 1 |
| @@ -1146,4 +1147,3 @@ static inline void kvm_vcpu_set_dy_eligible(struct kvm_vcpu *vcpu, bool val) · 1000 unmodified lines | |||
| 1146 | } | 1147 | } |
| 1147 | #endif /* CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT */ | 1148 | #endif /* CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT */ |
| 1148 | #endif | 1149 | #endif |
| 1149 | |||
| @@ -183,6 +183,7 @@ struct kvm_s390_skeys { · 182 unmodified lines | |||
| 183 | #define KVM_EXIT_EPR 23 | 183 | #define KVM_EXIT_EPR 23 |
| 184 | #define KVM_EXIT_SYSTEM_EVENT 24 | 184 | #define KVM_EXIT_SYSTEM_EVENT 24 |
| 185 | #define KVM_EXIT_S390_STSI 25 | 185 | #define KVM_EXIT_S390_STSI 25 |
| 186 | #define KVM_EXIT_IOAPIC_EOI 26 | ||
| 186 | 187 | ||
| 187 | /* For KVM_EXIT_INTERNAL_ERROR */ | 188 | /* For KVM_EXIT_INTERNAL_ERROR */ |
| 188 | /* Emulate instruction failed. */ | 189 | /* Emulate instruction failed. */ |
| @@ -333,6 +334,10 @@ struct kvm_run { · 144 unmodified lines | |||
| 333 | __u8 sel1; | 334 | __u8 sel1; |
| 334 | __u16 sel2; | 335 | __u16 sel2; |
| 335 | } s390_stsi; | 336 | } s390_stsi; |
| 337 | /* KVM_EXIT_IOAPIC_EOI */ | ||
| 338 | struct { | ||
| 339 | __u8 vector; | ||
| 340 | } eoi; | ||
| 336 | /* Fix the size of the union. */ | 341 | /* Fix the size of the union. */ |
| 337 | char padding[256]; | 342 | char padding[256]; |
| 338 | }; | 343 | }; |