History

KVM: x86: Add KVM exit for IOAPIC EOIs

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.

Steve Rutherford committed 11 years ago

Commit 7543a631 parent 49df6396 files · +48 −8Browse files

Unified · Split

6 files
  1. Documentation/virtual/kvm/api.txt +12 −0
  2. arch/x86/include/asm/kvm_host.h +2 −0
  3. arch/x86/kvm/lapic.c +17 −7
  4. arch/x86/kvm/x86.c +11 −0
  5. include/linux/kvm_host.h +1 −1
  6. include/uapi/linux/kvm.h +5 −0
Documentation/virtual/kvm/api.txt+12−0
@@ -3309,6 +3309,18 @@ Valid values for 'type' are: · 3308 unmodified lines
33093309 to ignore the request, or to gather VM memory core dump and/or
33103310 reset/shutdown of the VM.
33113311
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+
33123324 /* Fix the size of the union. */
33133325 char padding[256];
33143326 };
arch/x86/include/asm/kvm_host.h+2−0
@@ -574,6 +574,8 @@ struct kvm_vcpu_arch { · 573 unmodified lines
574574 struct {
575575 bool pv_unhalted;
576576 } pv;
577+
578+ int pending_ioapic_eoi;
577579 };
578580
579581 struct kvm_lpage_info {
arch/x86/kvm/lapic.c+17−7
@@ -877,15 +877,25 @@ static bool kvm_ioapic_handles_vector(struct kvm_lapic *apic, int vector) · 876 unmodified lines
877877
878878 static void kvm_ioapic_send_eoi(struct kvm_lapic *apic, int vector)
879879 {
880− if (kvm_ioapic_handles_vector(apic, vector)) {
881− int trigger_mode;
882− if (apic_test_vector(vector, apic->regs + APIC_TMR))
883− trigger_mode = IOAPIC_LEVEL_TRIG;
884− else
885− trigger_mode = IOAPIC_EDGE_TRIG;
880+ int trigger_mode;
881+
882+ /* Eoi the ioapic only if the ioapic doesn't own the vector. */
883+ if (!kvm_ioapic_handles_vector(apic, vector))
884+ return;
886885
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;
888891 }
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);
889899 }
890900
891901 static int apic_set_eoi(struct kvm_lapic *apic)
arch/x86/kvm/x86.c+11−0
@@ -6271,6 +6271,17 @@ static int vcpu_enter_guest(struct kvm_vcpu *vcpu) · 6270 unmodified lines
62716271 kvm_pmu_handle_event(vcpu);
62726272 if (kvm_check_request(KVM_REQ_PMI, vcpu))
62736273 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+ }
62746285 if (kvm_check_request(KVM_REQ_SCAN_IOAPIC, vcpu))
62756286 vcpu_scan_ioapic(vcpu);
62766287 if (kvm_check_request(KVM_REQ_APIC_PAGE_RELOAD, vcpu))
include/linux/kvm_host.h+1−1
@@ -140,6 +140,7 @@ static inline bool is_error_page(struct page *page) · 139 unmodified lines
140140 #define KVM_REQ_APIC_PAGE_RELOAD 25
141141 #define KVM_REQ_SMI 26
142142 #define KVM_REQ_HV_CRASH 27
143+#define KVM_REQ_IOAPIC_EOI_EXIT 28
143144
144145 #define KVM_USERSPACE_IRQ_SOURCE_ID 0
145146 #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
11461147 }
11471148 #endif /* CONFIG_HAVE_KVM_CPU_RELAX_INTERCEPT */
11481149 #endif
1149−
include/uapi/linux/kvm.h+5−0
@@ -183,6 +183,7 @@ struct kvm_s390_skeys { · 182 unmodified lines
183183 #define KVM_EXIT_EPR 23
184184 #define KVM_EXIT_SYSTEM_EVENT 24
185185 #define KVM_EXIT_S390_STSI 25
186+#define KVM_EXIT_IOAPIC_EOI 26
186187
187188 /* For KVM_EXIT_INTERNAL_ERROR */
188189 /* Emulate instruction failed. */
@@ -333,6 +334,10 @@ struct kvm_run { · 144 unmodified lines
333334 __u8 sel1;
334335 __u16 sel2;
335336 } s390_stsi;
337+ /* KVM_EXIT_IOAPIC_EOI */
338+ struct {
339+ __u8 vector;
340+ } eoi;
336341 /* Fix the size of the union. */
337342 char padding[256];
338343 };

Keyboard shortcuts

General

Show keyboard shortcuts
?
Focus the current search
/

Issues and pull requests

Open filters
f

Issues, pull requests and Inbox

Select next item
j↓
Select previous item
k↑
Open selected item
Enter
Dismiss filters or clear selection
Esc

Repository code

Go to file
t