On Fri, Apr 13, 2018 at 10:20:49AM +0200, Eric Auger wrote:
> At the moment KVM supports a single rdist region. We want to
> support several separate rdist regions so let's introduce a list
> of them. This patch currently only cares about a single
> entry in this list as the functionality to register several redist
> regions is not yet there. So this only translates the existing code
> into something functionally similar using that new data struct.
>
> The redistributor region handle is stored in the vgic_cpu structure
> to allow later computation of the TYPER last bit.
>
> Signed-off-by: Eric Auger
Reviewed-by: Christoffer Dall
> ---
> include/kvm/arm_vgic.h | 14 +
> virt/kvm/arm/vgic/vgic-init.c | 16 --
> virt/kvm/arm/vgic/vgic-kvm-device.c | 13 ++--
> virt/kvm/arm/vgic/vgic-mmio-v3.c| 42
> -
> virt/kvm/arm/vgic/vgic-v3.c | 20 +++---
> 5 files changed, 79 insertions(+), 26 deletions(-)
>
> diff --git a/include/kvm/arm_vgic.h b/include/kvm/arm_vgic.h
> index 24f0394..e5c16d1 100644
> --- a/include/kvm/arm_vgic.h
> +++ b/include/kvm/arm_vgic.h
> @@ -200,6 +200,14 @@ struct vgic_its {
>
> struct vgic_state_iter;
>
> +struct vgic_redist_region {
> + uint32_t index;
> + gpa_t base;
> + uint32_t count; /* number of redistributors or 0 if single region */
> + uint32_t free_index; /* index of the next free redistributor */
> + struct list_head list;
> +};
> +
> struct vgic_dist {
> boolin_kernel;
> boolready;
> @@ -219,10 +227,7 @@ struct vgic_dist {
> /* either a GICv2 CPU interface */
> gpa_t vgic_cpu_base;
> /* or a number of GICv3 redistributor regions */
> - struct {
> - gpa_t vgic_redist_base;
> - gpa_t vgic_redist_free_offset;
> - };
> + struct list_head rd_regions;
> };
>
> /* distributor enabled */
> @@ -310,6 +315,7 @@ struct vgic_cpu {
>*/
> struct vgic_io_device rd_iodev;
> struct vgic_io_device sgi_iodev;
> + struct vgic_redist_region *rdreg;
>
> /* Contains the attributes and gpa of the LPI pending tables. */
> u64 pendbaser;
> diff --git a/virt/kvm/arm/vgic/vgic-init.c b/virt/kvm/arm/vgic/vgic-init.c
> index c52f03d..6456371 100644
> --- a/virt/kvm/arm/vgic/vgic-init.c
> +++ b/virt/kvm/arm/vgic/vgic-init.c
> @@ -167,8 +167,11 @@ int kvm_vgic_create(struct kvm *kvm, u32 type)
> kvm->arch.vgic.vgic_model = type;
>
> kvm->arch.vgic.vgic_dist_base = VGIC_ADDR_UNDEF;
> - kvm->arch.vgic.vgic_cpu_base = VGIC_ADDR_UNDEF;
> - kvm->arch.vgic.vgic_redist_base = VGIC_ADDR_UNDEF;
> +
> + if (type == KVM_DEV_TYPE_ARM_VGIC_V2)
> + kvm->arch.vgic.vgic_cpu_base = VGIC_ADDR_UNDEF;
> + else
> + INIT_LIST_HEAD(&kvm->arch.vgic.rd_regions);
>
> out_unlock:
> for (; vcpu_lock_idx >= 0; vcpu_lock_idx--) {
> @@ -303,6 +306,7 @@ int vgic_init(struct kvm *kvm)
> static void kvm_vgic_dist_destroy(struct kvm *kvm)
> {
> struct vgic_dist *dist = &kvm->arch.vgic;
> + struct vgic_redist_region *rdreg, *next;
>
> dist->ready = false;
> dist->initialized = false;
> @@ -311,6 +315,14 @@ static void kvm_vgic_dist_destroy(struct kvm *kvm)
> dist->spis = NULL;
> dist->nr_spis = 0;
>
> + if (kvm->arch.vgic.vgic_model == KVM_DEV_TYPE_ARM_VGIC_V3) {
> + list_for_each_entry_safe(rdreg, next, &dist->rd_regions, list) {
> + list_del(&rdreg->list);
> + kfree(rdreg);
> + }
> + INIT_LIST_HEAD(&dist->rd_regions);
> + }
> +
> if (vgic_supports_direct_msis(kvm))
> vgic_v4_teardown(kvm);
> }
> diff --git a/virt/kvm/arm/vgic/vgic-kvm-device.c
> b/virt/kvm/arm/vgic/vgic-kvm-device.c
> index 10ae6f3..e7b5a86 100644
> --- a/virt/kvm/arm/vgic/vgic-kvm-device.c
> +++ b/virt/kvm/arm/vgic/vgic-kvm-device.c
> @@ -66,6 +66,7 @@ int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64
> *addr, bool write)
> int r = 0;
> struct vgic_dist *vgic = &kvm->arch.vgic;
> phys_addr_t *addr_ptr, alignment;
> + uint64_t undef_value = VGIC_ADDR_UNDEF;
>
> mutex_lock(&kvm->lock);
> switch (type) {
> @@ -84,7 +85,9 @@ int kvm_vgic_addr(struct kvm *kvm, unsigned long type, u64
> *addr, bool write)
> addr_ptr = &vgic->vgic_dist_base;
> alignment = SZ_64K;
> break;
> - case KVM_VGIC_V3_ADDR_TYPE_REDIST:
> + case KVM_VGIC_V3_ADDR_TYPE_REDIST: {
> + struct vgic_redist_region *rdreg;
> +
> r = vgic_check_type(kvm, KVM_DEV_TYPE_ARM_VGIC_V3);
> if (r)
> break;
> @@ -92,8 +95,14 @@ int kvm_vgic_addr(struct kvm *kvm, uns