diff options
author | Eric Auger <eric.auger@redhat.com> | 2019-08-23 13:33:30 -0400 |
---|---|---|
committer | Marc Zyngier <maz@kernel.org> | 2019-08-25 06:02:52 -0400 |
commit | 3109741a8d773b91eec4a1f7764c97a1176ec32d (patch) | |
tree | eaf4b6f30e5d5d290bf2b4ad51d52263c549b3b2 /virt | |
parent | 926c61568d0b2e57254e92290369d4539568f8cc (diff) |
KVM: arm/arm64: vgic: Use a single IO device per redistributor
At the moment we use 2 IO devices per GICv3 redistributor: one
one for the RD_base frame and one for the SGI_base frame.
Instead we can use a single IO device per redistributor (the 2
frames are contiguous). This saves slots on the KVM_MMIO_BUS
which is currently limited to NR_IOBUS_DEVS (1000).
This change allows to instantiate up to 512 redistributors and may
speed the guest boot with a large number of VCPUs.
Signed-off-by: Eric Auger <eric.auger@redhat.com>
Signed-off-by: Marc Zyngier <maz@kernel.org>
Diffstat (limited to 'virt')
-rw-r--r-- | virt/kvm/arm/vgic/vgic-init.c | 1 | ||||
-rw-r--r-- | virt/kvm/arm/vgic/vgic-mmio-v3.c | 81 |
2 files changed, 24 insertions, 58 deletions
diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c index 9175bfd83263..958e2f0d2207 100644 --- a/virt/kvm/arm/vgic/vgic-init.c +++ b/virt/kvm/arm/vgic/vgic-init.c | |||
@@ -193,7 +193,6 @@ int kvm_vgic_vcpu_init(struct kvm_vcpu *vcpu) | |||
193 | int i; | 193 | int i; |
194 | 194 | ||
195 | vgic_cpu->rd_iodev.base_addr = VGIC_ADDR_UNDEF; | 195 | vgic_cpu->rd_iodev.base_addr = VGIC_ADDR_UNDEF; |
196 | vgic_cpu->sgi_iodev.base_addr = VGIC_ADDR_UNDEF; | ||
197 | 196 | ||
198 | INIT_LIST_HEAD(&vgic_cpu->ap_list_head); | 197 | INIT_LIST_HEAD(&vgic_cpu->ap_list_head); |
199 | raw_spin_lock_init(&vgic_cpu->ap_list_lock); | 198 | raw_spin_lock_init(&vgic_cpu->ap_list_lock); |
diff --git a/virt/kvm/arm/vgic/vgic-mmio-v3.c b/virt/kvm/arm/vgic/vgic-mmio-v3.c index fdcfb7ae4491..7dfd15dbb308 100644 --- a/virt/kvm/arm/vgic/vgic-mmio-v3.c +++ b/virt/kvm/arm/vgic/vgic-mmio-v3.c | |||
@@ -517,7 +517,8 @@ static const struct vgic_register_region vgic_v3_dist_registers[] = { | |||
517 | VGIC_ACCESS_32bit), | 517 | VGIC_ACCESS_32bit), |
518 | }; | 518 | }; |
519 | 519 | ||
520 | static const struct vgic_register_region vgic_v3_rdbase_registers[] = { | 520 | static const struct vgic_register_region vgic_v3_rd_registers[] = { |
521 | /* RD_base registers */ | ||
521 | REGISTER_DESC_WITH_LENGTH(GICR_CTLR, | 522 | REGISTER_DESC_WITH_LENGTH(GICR_CTLR, |
522 | vgic_mmio_read_v3r_ctlr, vgic_mmio_write_v3r_ctlr, 4, | 523 | vgic_mmio_read_v3r_ctlr, vgic_mmio_write_v3r_ctlr, 4, |
523 | VGIC_ACCESS_32bit), | 524 | VGIC_ACCESS_32bit), |
@@ -542,44 +543,42 @@ static const struct vgic_register_region vgic_v3_rdbase_registers[] = { | |||
542 | REGISTER_DESC_WITH_LENGTH(GICR_IDREGS, | 543 | REGISTER_DESC_WITH_LENGTH(GICR_IDREGS, |
543 | vgic_mmio_read_v3_idregs, vgic_mmio_write_wi, 48, | 544 | vgic_mmio_read_v3_idregs, vgic_mmio_write_wi, 48, |
544 | VGIC_ACCESS_32bit), | 545 | VGIC_ACCESS_32bit), |
545 | }; | 546 | /* SGI_base registers */ |
546 | 547 | REGISTER_DESC_WITH_LENGTH(SZ_64K + GICR_IGROUPR0, | |
547 | static const struct vgic_register_region vgic_v3_sgibase_registers[] = { | ||
548 | REGISTER_DESC_WITH_LENGTH(GICR_IGROUPR0, | ||
549 | vgic_mmio_read_group, vgic_mmio_write_group, 4, | 548 | vgic_mmio_read_group, vgic_mmio_write_group, 4, |
550 | VGIC_ACCESS_32bit), | 549 | VGIC_ACCESS_32bit), |
551 | REGISTER_DESC_WITH_LENGTH(GICR_ISENABLER0, | 550 | REGISTER_DESC_WITH_LENGTH(SZ_64K + GICR_ISENABLER0, |
552 | vgic_mmio_read_enable, vgic_mmio_write_senable, 4, | 551 | vgic_mmio_read_enable, vgic_mmio_write_senable, 4, |
553 | VGIC_ACCESS_32bit), | 552 | VGIC_ACCESS_32bit), |
554 | REGISTER_DESC_WITH_LENGTH(GICR_ICENABLER0, | 553 | REGISTER_DESC_WITH_LENGTH(SZ_64K + GICR_ICENABLER0, |
555 | vgic_mmio_read_enable, vgic_mmio_write_cenable, 4, | 554 | vgic_mmio_read_enable, vgic_mmio_write_cenable, 4, |
556 | VGIC_ACCESS_32bit), | 555 | VGIC_ACCESS_32bit), |
557 | REGISTER_DESC_WITH_LENGTH_UACCESS(GICR_ISPENDR0, | 556 | REGISTER_DESC_WITH_LENGTH_UACCESS(SZ_64K + GICR_ISPENDR0, |
558 | vgic_mmio_read_pending, vgic_mmio_write_spending, | 557 | vgic_mmio_read_pending, vgic_mmio_write_spending, |
559 | vgic_v3_uaccess_read_pending, vgic_v3_uaccess_write_pending, 4, | 558 | vgic_v3_uaccess_read_pending, vgic_v3_uaccess_write_pending, 4, |
560 | VGIC_ACCESS_32bit), | 559 | VGIC_ACCESS_32bit), |
561 | REGISTER_DESC_WITH_LENGTH_UACCESS(GICR_ICPENDR0, | 560 | REGISTER_DESC_WITH_LENGTH_UACCESS(SZ_64K + GICR_ICPENDR0, |
562 | vgic_mmio_read_pending, vgic_mmio_write_cpending, | 561 | vgic_mmio_read_pending, vgic_mmio_write_cpending, |
563 | vgic_mmio_read_raz, vgic_mmio_uaccess_write_wi, 4, | 562 | vgic_mmio_read_raz, vgic_mmio_uaccess_write_wi, 4, |
564 | VGIC_ACCESS_32bit), | 563 | VGIC_ACCESS_32bit), |
565 | REGISTER_DESC_WITH_LENGTH_UACCESS(GICR_ISACTIVER0, | 564 | REGISTER_DESC_WITH_LENGTH_UACCESS(SZ_64K + GICR_ISACTIVER0, |
566 | vgic_mmio_read_active, vgic_mmio_write_sactive, | 565 | vgic_mmio_read_active, vgic_mmio_write_sactive, |
567 | NULL, vgic_mmio_uaccess_write_sactive, | 566 | NULL, vgic_mmio_uaccess_write_sactive, |
568 | 4, VGIC_ACCESS_32bit), | 567 | 4, VGIC_ACCESS_32bit), |
569 | REGISTER_DESC_WITH_LENGTH_UACCESS(GICR_ICACTIVER0, | 568 | REGISTER_DESC_WITH_LENGTH_UACCESS(SZ_64K + GICR_ICACTIVER0, |
570 | vgic_mmio_read_active, vgic_mmio_write_cactive, | 569 | vgic_mmio_read_active, vgic_mmio_write_cactive, |
571 | NULL, vgic_mmio_uaccess_write_cactive, | 570 | NULL, vgic_mmio_uaccess_write_cactive, |
572 | 4, VGIC_ACCESS_32bit), | 571 | 4, VGIC_ACCESS_32bit), |
573 | REGISTER_DESC_WITH_LENGTH(GICR_IPRIORITYR0, | 572 | REGISTER_DESC_WITH_LENGTH(SZ_64K + GICR_IPRIORITYR0, |
574 | vgic_mmio_read_priority, vgic_mmio_write_priority, 32, | 573 | vgic_mmio_read_priority, vgic_mmio_write_priority, 32, |
575 | VGIC_ACCESS_32bit | VGIC_ACCESS_8bit), | 574 | VGIC_ACCESS_32bit | VGIC_ACCESS_8bit), |
576 | REGISTER_DESC_WITH_LENGTH(GICR_ICFGR0, | 575 | REGISTER_DESC_WITH_LENGTH(SZ_64K + GICR_ICFGR0, |
577 | vgic_mmio_read_config, vgic_mmio_write_config, 8, | 576 | vgic_mmio_read_config, vgic_mmio_write_config, 8, |
578 | VGIC_ACCESS_32bit), | 577 | VGIC_ACCESS_32bit), |
579 | REGISTER_DESC_WITH_LENGTH(GICR_IGRPMODR0, | 578 | REGISTER_DESC_WITH_LENGTH(SZ_64K + GICR_IGRPMODR0, |
580 | vgic_mmio_read_raz, vgic_mmio_write_wi, 4, | 579 | vgic_mmio_read_raz, vgic_mmio_write_wi, 4, |
581 | VGIC_ACCESS_32bit), | 580 | VGIC_ACCESS_32bit), |
582 | REGISTER_DESC_WITH_LENGTH(GICR_NSACR, | 581 | REGISTER_DESC_WITH_LENGTH(SZ_64K + GICR_NSACR, |
583 | vgic_mmio_read_raz, vgic_mmio_write_wi, 4, | 582 | vgic_mmio_read_raz, vgic_mmio_write_wi, 4, |
584 | VGIC_ACCESS_32bit), | 583 | VGIC_ACCESS_32bit), |
585 | }; | 584 | }; |
@@ -609,9 +608,8 @@ int vgic_register_redist_iodev(struct kvm_vcpu *vcpu) | |||
609 | struct vgic_dist *vgic = &kvm->arch.vgic; | 608 | struct vgic_dist *vgic = &kvm->arch.vgic; |
610 | struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu; | 609 | struct vgic_cpu *vgic_cpu = &vcpu->arch.vgic_cpu; |
611 | struct vgic_io_device *rd_dev = &vcpu->arch.vgic_cpu.rd_iodev; | 610 | struct vgic_io_device *rd_dev = &vcpu->arch.vgic_cpu.rd_iodev; |
612 | struct vgic_io_device *sgi_dev = &vcpu->arch.vgic_cpu.sgi_iodev; | ||
613 | struct vgic_redist_region *rdreg; | 611 | struct vgic_redist_region *rdreg; |
614 | gpa_t rd_base, sgi_base; | 612 | gpa_t rd_base; |
615 | int ret; | 613 | int ret; |
616 | 614 | ||
617 | if (!IS_VGIC_ADDR_UNDEF(vgic_cpu->rd_iodev.base_addr)) | 615 | if (!IS_VGIC_ADDR_UNDEF(vgic_cpu->rd_iodev.base_addr)) |
@@ -633,52 +631,31 @@ int vgic_register_redist_iodev(struct kvm_vcpu *vcpu) | |||
633 | vgic_cpu->rdreg = rdreg; | 631 | vgic_cpu->rdreg = rdreg; |
634 | 632 | ||
635 | rd_base = rdreg->base + rdreg->free_index * KVM_VGIC_V3_REDIST_SIZE; | 633 | rd_base = rdreg->base + rdreg->free_index * KVM_VGIC_V3_REDIST_SIZE; |
636 | sgi_base = rd_base + SZ_64K; | ||
637 | 634 | ||
638 | kvm_iodevice_init(&rd_dev->dev, &kvm_io_gic_ops); | 635 | kvm_iodevice_init(&rd_dev->dev, &kvm_io_gic_ops); |
639 | rd_dev->base_addr = rd_base; | 636 | rd_dev->base_addr = rd_base; |
640 | rd_dev->iodev_type = IODEV_REDIST; | 637 | rd_dev->iodev_type = IODEV_REDIST; |
641 | rd_dev->regions = vgic_v3_rdbase_registers; | 638 | rd_dev->regions = vgic_v3_rd_registers; |
642 | rd_dev->nr_regions = ARRAY_SIZE(vgic_v3_rdbase_registers); | 639 | rd_dev->nr_regions = ARRAY_SIZE(vgic_v3_rd_registers); |
643 | rd_dev->redist_vcpu = vcpu; | 640 | rd_dev->redist_vcpu = vcpu; |
644 | 641 | ||
645 | mutex_lock(&kvm->slots_lock); | 642 | mutex_lock(&kvm->slots_lock); |
646 | ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, rd_base, | 643 | ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, rd_base, |
647 | SZ_64K, &rd_dev->dev); | 644 | 2 * SZ_64K, &rd_dev->dev); |
648 | mutex_unlock(&kvm->slots_lock); | 645 | mutex_unlock(&kvm->slots_lock); |
649 | 646 | ||
650 | if (ret) | 647 | if (ret) |
651 | return ret; | 648 | return ret; |
652 | 649 | ||
653 | kvm_iodevice_init(&sgi_dev->dev, &kvm_io_gic_ops); | ||
654 | sgi_dev->base_addr = sgi_base; | ||
655 | sgi_dev->iodev_type = IODEV_REDIST; | ||
656 | sgi_dev->regions = vgic_v3_sgibase_registers; | ||
657 | sgi_dev->nr_regions = ARRAY_SIZE(vgic_v3_sgibase_registers); | ||
658 | sgi_dev->redist_vcpu = vcpu; | ||
659 | |||
660 | mutex_lock(&kvm->slots_lock); | ||
661 | ret = kvm_io_bus_register_dev(kvm, KVM_MMIO_BUS, sgi_base, | ||
662 | SZ_64K, &sgi_dev->dev); | ||
663 | if (ret) { | ||
664 | kvm_io_bus_unregister_dev(kvm, KVM_MMIO_BUS, | ||
665 | &rd_dev->dev); | ||
666 | goto out; | ||
667 | } | ||
668 | |||
669 | rdreg->free_index++; | 650 | rdreg->free_index++; |
670 | out: | 651 | return 0; |
671 | mutex_unlock(&kvm->slots_lock); | ||
672 | return ret; | ||
673 | } | 652 | } |
674 | 653 | ||
675 | static void vgic_unregister_redist_iodev(struct kvm_vcpu *vcpu) | 654 | static void vgic_unregister_redist_iodev(struct kvm_vcpu *vcpu) |
676 | { | 655 | { |
677 | struct vgic_io_device *rd_dev = &vcpu->arch.vgic_cpu.rd_iodev; | 656 | struct vgic_io_device *rd_dev = &vcpu->arch.vgic_cpu.rd_iodev; |
678 | struct vgic_io_device *sgi_dev = &vcpu->arch.vgic_cpu.sgi_iodev; | ||
679 | 657 | ||
680 | kvm_io_bus_unregister_dev(vcpu->kvm, KVM_MMIO_BUS, &rd_dev->dev); | 658 | kvm_io_bus_unregister_dev(vcpu->kvm, KVM_MMIO_BUS, &rd_dev->dev); |
681 | kvm_io_bus_unregister_dev(vcpu->kvm, KVM_MMIO_BUS, &sgi_dev->dev); | ||
682 | } | 659 | } |
683 | 660 | ||
684 | static int vgic_register_all_redist_iodevs(struct kvm *kvm) | 661 | static int vgic_register_all_redist_iodevs(struct kvm *kvm) |
@@ -828,8 +805,8 @@ int vgic_v3_has_attr_regs(struct kvm_device *dev, struct kvm_device_attr *attr) | |||
828 | iodev.base_addr = 0; | 805 | iodev.base_addr = 0; |
829 | break; | 806 | break; |
830 | case KVM_DEV_ARM_VGIC_GRP_REDIST_REGS:{ | 807 | case KVM_DEV_ARM_VGIC_GRP_REDIST_REGS:{ |
831 | iodev.regions = vgic_v3_rdbase_registers; | 808 | iodev.regions = vgic_v3_rd_registers; |
832 | iodev.nr_regions = ARRAY_SIZE(vgic_v3_rdbase_registers); | 809 | iodev.nr_regions = ARRAY_SIZE(vgic_v3_rd_registers); |
833 | iodev.base_addr = 0; | 810 | iodev.base_addr = 0; |
834 | break; | 811 | break; |
835 | } | 812 | } |
@@ -987,21 +964,11 @@ int vgic_v3_redist_uaccess(struct kvm_vcpu *vcpu, bool is_write, | |||
987 | int offset, u32 *val) | 964 | int offset, u32 *val) |
988 | { | 965 | { |
989 | struct vgic_io_device rd_dev = { | 966 | struct vgic_io_device rd_dev = { |
990 | .regions = vgic_v3_rdbase_registers, | 967 | .regions = vgic_v3_rd_registers, |
991 | .nr_regions = ARRAY_SIZE(vgic_v3_rdbase_registers), | 968 | .nr_regions = ARRAY_SIZE(vgic_v3_rd_registers), |
992 | }; | 969 | }; |
993 | 970 | ||
994 | struct vgic_io_device sgi_dev = { | 971 | return vgic_uaccess(vcpu, &rd_dev, is_write, offset, val); |
995 | .regions = vgic_v3_sgibase_registers, | ||
996 | .nr_regions = ARRAY_SIZE(vgic_v3_sgibase_registers), | ||
997 | }; | ||
998 | |||
999 | /* SGI_base is the next 64K frame after RD_base */ | ||
1000 | if (offset >= SZ_64K) | ||
1001 | return vgic_uaccess(vcpu, &sgi_dev, is_write, offset - SZ_64K, | ||
1002 | val); | ||
1003 | else | ||
1004 | return vgic_uaccess(vcpu, &rd_dev, is_write, offset, val); | ||
1005 | } | 972 | } |
1006 | 973 | ||
1007 | int vgic_v3_line_level_info_uaccess(struct kvm_vcpu *vcpu, bool is_write, | 974 | int vgic_v3_line_level_info_uaccess(struct kvm_vcpu *vcpu, bool is_write, |