Re: [PATCH v3 03/12] KVM: arm/arm64: Replace the single rdist region by a list

2018-04-24 Thread Christoffer Dall
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

[PATCH v3 03/12] KVM: arm/arm64: Replace the single rdist region by a list

2018-04-13 Thread Eric Auger
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 
---
 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, unsigned long type, u64 
*addr, bool write)
r = vgic_v3_set_redist_base(kvm, *addr);
goto out;
}
-   addr_ptr = &vgic->vgic_redist_base;
+