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.c49
1 files changed, 39 insertions, 10 deletions
diff --git a/arch/x86/kvm/lapic.c b/arch/x86/kvm/lapic.c
index 0cefba28c864..fbb0e6df121b 100644
--- a/arch/x86/kvm/lapic.c
+++ b/arch/x86/kvm/lapic.c
@@ -548,7 +548,7 @@ int kvm_apic_set_irq(struct kvm_vcpu *vcpu, struct kvm_lapic_irq *irq,
548} 548}
549 549
550int kvm_pv_send_ipi(struct kvm *kvm, unsigned long ipi_bitmap_low, 550int kvm_pv_send_ipi(struct kvm *kvm, unsigned long ipi_bitmap_low,
551 unsigned long ipi_bitmap_high, int min, 551 unsigned long ipi_bitmap_high, u32 min,
552 unsigned long icr, int op_64_bit) 552 unsigned long icr, int op_64_bit)
553{ 553{
554 int i; 554 int i;
@@ -571,18 +571,31 @@ int kvm_pv_send_ipi(struct kvm *kvm, unsigned long ipi_bitmap_low,
571 rcu_read_lock(); 571 rcu_read_lock();
572 map = rcu_dereference(kvm->arch.apic_map); 572 map = rcu_dereference(kvm->arch.apic_map);
573 573
574 if (min > map->max_apic_id)
575 goto out;
574 /* Bits above cluster_size are masked in the caller. */ 576 /* Bits above cluster_size are masked in the caller. */
575 for_each_set_bit(i, &ipi_bitmap_low, BITS_PER_LONG) { 577 for_each_set_bit(i, &ipi_bitmap_low,
576 vcpu = map->phys_map[min + i]->vcpu; 578 min((u32)BITS_PER_LONG, (map->max_apic_id - min + 1))) {
577 count += kvm_apic_set_irq(vcpu, &irq, NULL); 579 if (map->phys_map[min + i]) {
580 vcpu = map->phys_map[min + i]->vcpu;
581 count += kvm_apic_set_irq(vcpu, &irq, NULL);
582 }
578 } 583 }
579 584
580 min += cluster_size; 585 min += cluster_size;
581 for_each_set_bit(i, &ipi_bitmap_high, BITS_PER_LONG) { 586
582 vcpu = map->phys_map[min + i]->vcpu; 587 if (min > map->max_apic_id)
583 count += kvm_apic_set_irq(vcpu, &irq, NULL); 588 goto out;
589
590 for_each_set_bit(i, &ipi_bitmap_high,
591 min((u32)BITS_PER_LONG, (map->max_apic_id - min + 1))) {
592 if (map->phys_map[min + i]) {
593 vcpu = map->phys_map[min + i]->vcpu;
594 count += kvm_apic_set_irq(vcpu, &irq, NULL);
595 }
584 } 596 }
585 597
598out:
586 rcu_read_unlock(); 599 rcu_read_unlock();
587 return count; 600 return count;
588} 601}
@@ -1331,9 +1344,8 @@ EXPORT_SYMBOL_GPL(kvm_lapic_reg_read);
1331 1344
1332static int apic_mmio_in_range(struct kvm_lapic *apic, gpa_t addr) 1345static int apic_mmio_in_range(struct kvm_lapic *apic, gpa_t addr)
1333{ 1346{
1334 return kvm_apic_hw_enabled(apic) && 1347 return addr >= apic->base_address &&
1335 addr >= apic->base_address && 1348 addr < apic->base_address + LAPIC_MMIO_LENGTH;
1336 addr < apic->base_address + LAPIC_MMIO_LENGTH;
1337} 1349}
1338 1350
1339static int apic_mmio_read(struct kvm_vcpu *vcpu, struct kvm_io_device *this, 1351static int apic_mmio_read(struct kvm_vcpu *vcpu, struct kvm_io_device *this,
@@ -1345,6 +1357,15 @@ static int apic_mmio_read(struct kvm_vcpu *vcpu, struct kvm_io_device *this,
1345 if (!apic_mmio_in_range(apic, address)) 1357 if (!apic_mmio_in_range(apic, address))
1346 return -EOPNOTSUPP; 1358 return -EOPNOTSUPP;
1347 1359
1360 if (!kvm_apic_hw_enabled(apic) || apic_x2apic_mode(apic)) {
1361 if (!kvm_check_has_quirk(vcpu->kvm,
1362 KVM_X86_QUIRK_LAPIC_MMIO_HOLE))
1363 return -EOPNOTSUPP;
1364
1365 memset(data, 0xff, len);
1366 return 0;
1367 }
1368
1348 kvm_lapic_reg_read(apic, offset, len, data); 1369 kvm_lapic_reg_read(apic, offset, len, data);
1349 1370
1350 return 0; 1371 return 0;
@@ -1904,6 +1925,14 @@ static int apic_mmio_write(struct kvm_vcpu *vcpu, struct kvm_io_device *this,
1904 if (!apic_mmio_in_range(apic, address)) 1925 if (!apic_mmio_in_range(apic, address))
1905 return -EOPNOTSUPP; 1926 return -EOPNOTSUPP;
1906 1927
1928 if (!kvm_apic_hw_enabled(apic) || apic_x2apic_mode(apic)) {
1929 if (!kvm_check_has_quirk(vcpu->kvm,
1930 KVM_X86_QUIRK_LAPIC_MMIO_HOLE))
1931 return -EOPNOTSUPP;
1932
1933 return 0;
1934 }
1935
1907 /* 1936 /*
1908 * APIC register must be aligned on 128-bits boundary. 1937 * APIC register must be aligned on 128-bits boundary.
1909 * 32/64/128 bits registers must be accessed thru 32 bits. 1938 * 32/64/128 bits registers must be accessed thru 32 bits.