Re: [Xen-devel] [RFC PATCH v2 12/26] ARM: vGICv3: handle virtual LPI pending and property tables

2017-01-05 Thread Stefano Stabellini
On Thu, 22 Dec 2016, Andre Przywara wrote:
> Allow a guest to provide the address and size for the memory regions
> it has reserved for the GICv3 pending and property tables.
> We sanitise the various fields of the respective redistributor
> registers and map those pages into Xen's address space to have easy
> access.

Many comments still unaddressed


> Signed-off-by: Andre Przywara 
> ---
>  xen/arch/arm/vgic-v3.c   | 202 
> ---
>  xen/arch/arm/vgic.c  |   4 +
>  xen/include/asm-arm/domain.h |   8 +-
>  xen/include/asm-arm/vgic.h   |   4 +
>  4 files changed, 203 insertions(+), 15 deletions(-)
> 
> diff --git a/xen/arch/arm/vgic-v3.c b/xen/arch/arm/vgic-v3.c
> index 0ffde74..b981d4e 100644
> --- a/xen/arch/arm/vgic-v3.c
> +++ b/xen/arch/arm/vgic-v3.c
> @@ -20,12 +20,14 @@
>  
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
>  #include 
>  #include 
>  #include 
> +#include 
>  #include 
>  #include 
>  #include 
> @@ -229,12 +231,14 @@ static int __vgic_v3_rdistr_rd_mmio_read(struct vcpu 
> *v, mmio_info_t *info,
>  goto read_reserved;
>  
>  case VREG64(GICR_PROPBASER):
> -/* LPI's not implemented */
> -goto read_as_zero_64;
> +if ( !vgic_reg64_check_access(dabt) ) goto bad_width;
> +*r = vgic_reg64_extract(v->domain->arch.vgic.rdist_propbase, info);
> +return 1;
>  
>  case VREG64(GICR_PENDBASER):
> -/* LPI's not implemented */
> -goto read_as_zero_64;
> +if ( !vgic_reg64_check_access(dabt) ) goto bad_width;
> +*r = vgic_reg64_extract(v->arch.vgic.rdist_pendbase, info);
> +return 1;
>  
>  case 0x0080:
>  goto read_reserved;
> @@ -302,11 +306,6 @@ bad_width:
>  domain_crash_synchronous();
>  return 0;
>  
> -read_as_zero_64:
> -if ( !vgic_reg64_check_access(dabt) ) goto bad_width;
> -*r = 0;
> -return 1;
> -
>  read_as_zero_32:
>  if ( dabt.size != DABT_WORD ) goto bad_width;
>  *r = 0;
> @@ -331,6 +330,143 @@ read_unknown:
>  return 1;
>  }
>  
> +static uint64_t vgic_sanitise_field(uint64_t reg, uint64_t field_mask,
> +int field_shift,
> +uint64_t (*sanitise_fn)(uint64_t))
> +{
> +uint64_t field = (reg & field_mask) >> field_shift;
> +
> +field = sanitise_fn(field) << field_shift;
> +return (reg & ~field_mask) | field;
> +}
> +
> +/* We want to avoid outer shareable. */
> +static uint64_t vgic_sanitise_shareability(uint64_t field)
> +{
> +switch (field) {
> +case GIC_BASER_OuterShareable:
> +return GIC_BASER_InnerShareable;
> +default:
> +return field;
> +}
> +}
> +
> +/* Avoid any inner non-cacheable mapping. */
> +static uint64_t vgic_sanitise_inner_cacheability(uint64_t field)
> +{
> +switch (field) {
> +case GIC_BASER_CACHE_nCnB:
> +case GIC_BASER_CACHE_nC:
> +return GIC_BASER_CACHE_RaWb;
> +default:
> +return field;
> +}
> +}
> +
> +/* Non-cacheable or same-as-inner are OK. */
> +static uint64_t vgic_sanitise_outer_cacheability(uint64_t field)
> +{
> +switch (field) {
> +case GIC_BASER_CACHE_SameAsInner:
> +case GIC_BASER_CACHE_nC:
> +return field;
> +default:
> +return GIC_BASER_CACHE_nC;
> +}
> +}
> +
> +static uint64_t sanitize_propbaser(uint64_t reg)
> +{
> +reg = vgic_sanitise_field(reg, GICR_PROPBASER_SHAREABILITY_MASK,
> +  GICR_PROPBASER_SHAREABILITY_SHIFT,
> +  vgic_sanitise_shareability);
> +reg = vgic_sanitise_field(reg, GICR_PROPBASER_INNER_CACHEABILITY_MASK,
> +  GICR_PROPBASER_INNER_CACHEABILITY_SHIFT,
> +  vgic_sanitise_inner_cacheability);
> +reg = vgic_sanitise_field(reg, GICR_PROPBASER_OUTER_CACHEABILITY_MASK,
> +  GICR_PROPBASER_OUTER_CACHEABILITY_SHIFT,
> +  vgic_sanitise_outer_cacheability);
> +
> +reg &= ~PROPBASER_RES0_MASK;
> +reg &= ~GENMASK(51, 48);
> +return reg;
> +}
> +
> +static uint64_t sanitize_pendbaser(uint64_t reg)
> +{
> +reg = vgic_sanitise_field(reg, GICR_PENDBASER_SHAREABILITY_MASK,
> +  GICR_PENDBASER_SHAREABILITY_SHIFT,
> +  vgic_sanitise_shareability);
> +reg = vgic_sanitise_field(reg, GICR_PENDBASER_INNER_CACHEABILITY_MASK,
> +  GICR_PENDBASER_INNER_CACHEABILITY_SHIFT,
> +  vgic_sanitise_inner_cacheability);
> +reg = vgic_sanitise_field(reg, GICR_PENDBASER_OUTER_CACHEABILITY_MASK,
> +  GICR_PENDBASER_OUTER_CACHEABILITY_SHIFT,
> +  vgic_sanitise_outer_cacheability);
> +
> +reg &= ~PENDBASER_RES0_MASK;
> +reg &= ~GENMASK(51, 48);
> +return reg;
> +}
> 

[Xen-devel] [RFC PATCH v2 12/26] ARM: vGICv3: handle virtual LPI pending and property tables

2016-12-22 Thread Andre Przywara
Allow a guest to provide the address and size for the memory regions
it has reserved for the GICv3 pending and property tables.
We sanitise the various fields of the respective redistributor
registers and map those pages into Xen's address space to have easy
access.

Signed-off-by: Andre Przywara 
---
 xen/arch/arm/vgic-v3.c   | 202 ---
 xen/arch/arm/vgic.c  |   4 +
 xen/include/asm-arm/domain.h |   8 +-
 xen/include/asm-arm/vgic.h   |   4 +
 4 files changed, 203 insertions(+), 15 deletions(-)

diff --git a/xen/arch/arm/vgic-v3.c b/xen/arch/arm/vgic-v3.c
index 0ffde74..b981d4e 100644
--- a/xen/arch/arm/vgic-v3.c
+++ b/xen/arch/arm/vgic-v3.c
@@ -20,12 +20,14 @@
 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
 #include 
 #include 
 #include 
+#include 
 #include 
 #include 
 #include 
@@ -229,12 +231,14 @@ static int __vgic_v3_rdistr_rd_mmio_read(struct vcpu *v, 
mmio_info_t *info,
 goto read_reserved;
 
 case VREG64(GICR_PROPBASER):
-/* LPI's not implemented */
-goto read_as_zero_64;
+if ( !vgic_reg64_check_access(dabt) ) goto bad_width;
+*r = vgic_reg64_extract(v->domain->arch.vgic.rdist_propbase, info);
+return 1;
 
 case VREG64(GICR_PENDBASER):
-/* LPI's not implemented */
-goto read_as_zero_64;
+if ( !vgic_reg64_check_access(dabt) ) goto bad_width;
+*r = vgic_reg64_extract(v->arch.vgic.rdist_pendbase, info);
+return 1;
 
 case 0x0080:
 goto read_reserved;
@@ -302,11 +306,6 @@ bad_width:
 domain_crash_synchronous();
 return 0;
 
-read_as_zero_64:
-if ( !vgic_reg64_check_access(dabt) ) goto bad_width;
-*r = 0;
-return 1;
-
 read_as_zero_32:
 if ( dabt.size != DABT_WORD ) goto bad_width;
 *r = 0;
@@ -331,6 +330,143 @@ read_unknown:
 return 1;
 }
 
+static uint64_t vgic_sanitise_field(uint64_t reg, uint64_t field_mask,
+int field_shift,
+uint64_t (*sanitise_fn)(uint64_t))
+{
+uint64_t field = (reg & field_mask) >> field_shift;
+
+field = sanitise_fn(field) << field_shift;
+return (reg & ~field_mask) | field;
+}
+
+/* We want to avoid outer shareable. */
+static uint64_t vgic_sanitise_shareability(uint64_t field)
+{
+switch (field) {
+case GIC_BASER_OuterShareable:
+return GIC_BASER_InnerShareable;
+default:
+return field;
+}
+}
+
+/* Avoid any inner non-cacheable mapping. */
+static uint64_t vgic_sanitise_inner_cacheability(uint64_t field)
+{
+switch (field) {
+case GIC_BASER_CACHE_nCnB:
+case GIC_BASER_CACHE_nC:
+return GIC_BASER_CACHE_RaWb;
+default:
+return field;
+}
+}
+
+/* Non-cacheable or same-as-inner are OK. */
+static uint64_t vgic_sanitise_outer_cacheability(uint64_t field)
+{
+switch (field) {
+case GIC_BASER_CACHE_SameAsInner:
+case GIC_BASER_CACHE_nC:
+return field;
+default:
+return GIC_BASER_CACHE_nC;
+}
+}
+
+static uint64_t sanitize_propbaser(uint64_t reg)
+{
+reg = vgic_sanitise_field(reg, GICR_PROPBASER_SHAREABILITY_MASK,
+  GICR_PROPBASER_SHAREABILITY_SHIFT,
+  vgic_sanitise_shareability);
+reg = vgic_sanitise_field(reg, GICR_PROPBASER_INNER_CACHEABILITY_MASK,
+  GICR_PROPBASER_INNER_CACHEABILITY_SHIFT,
+  vgic_sanitise_inner_cacheability);
+reg = vgic_sanitise_field(reg, GICR_PROPBASER_OUTER_CACHEABILITY_MASK,
+  GICR_PROPBASER_OUTER_CACHEABILITY_SHIFT,
+  vgic_sanitise_outer_cacheability);
+
+reg &= ~PROPBASER_RES0_MASK;
+reg &= ~GENMASK(51, 48);
+return reg;
+}
+
+static uint64_t sanitize_pendbaser(uint64_t reg)
+{
+reg = vgic_sanitise_field(reg, GICR_PENDBASER_SHAREABILITY_MASK,
+  GICR_PENDBASER_SHAREABILITY_SHIFT,
+  vgic_sanitise_shareability);
+reg = vgic_sanitise_field(reg, GICR_PENDBASER_INNER_CACHEABILITY_MASK,
+  GICR_PENDBASER_INNER_CACHEABILITY_SHIFT,
+  vgic_sanitise_inner_cacheability);
+reg = vgic_sanitise_field(reg, GICR_PENDBASER_OUTER_CACHEABILITY_MASK,
+  GICR_PENDBASER_OUTER_CACHEABILITY_SHIFT,
+  vgic_sanitise_outer_cacheability);
+
+reg &= ~PENDBASER_RES0_MASK;
+reg &= ~GENMASK(51, 48);
+return reg;
+}
+
+/*
+ * Allow mapping some parts of guest memory into Xen's VA space to have easy
+ * access to it. This is to allow ITS configuration data to be held in
+ * guest memory and avoid using Xen memory for that.
+ */
+void *map_guest_pages(struct domain *d, paddr_t guest_addr, int nr_pages)
+{
+mfn_t onepage;
+mfn_t *pages;
+int i;
+void *ptr;
+
+/*