[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

Re: [Xen-devel] [PATCH v2 for 4.5] xen/arm: Add support for GICv3 for domU



On Mon, Nov 3, 2014 at 4:31 PM, Stefano Stabellini
<stefano.stabellini@xxxxxxxxxxxxx> wrote:
> On Sat, 1 Nov 2014, Julien Grall wrote:
>> The vGIC will emulate the same version as the hardware. The toolstack has
>> to retrieve the version of the vGIC in order to be able to create the
>> corresponding device tree node.
>>
>> A new DOMCTL has been introduced for ARM to configure the domain. For now
>> it only allow the toolstack to retrieve the version of vGIC.
>> This DOMCTL will be extend later to let the user choose the version of the
>> emulated GIC.
>>
>> Signed-off-by: Vijaya Kumar K <Vijaya.Kumar@xxxxxxxxxxxxxxxxxx>
>> Signed-off-by: Julien Grall <julien.grall@xxxxxxxxxx>
>> Cc: Ian Jackson <ian.jackson@xxxxxxxxxxxxx>
>> Cc: Jan Beulich <jbeulich@xxxxxxxx>
>> Cc: Daniel De Graaf <dgdegra@xxxxxxxxxxxxx>
>> Cc: Wei Liu <wei.liu2@xxxxxxxxxx>
>
> Reviewed-by: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx>

Tested with GICv3 platform.

>
>
>>     Changes in v2:
>>         - Use memcpu in xc_domain_configure
>>         - Rename the DOMCTL into domctl_arm_configuredomain
>>         - Drop arch_domain_create_pre. Will be reintroduced in Xen 4.6
>>         and fold the code in arch_domain_init_hw_description
>>         - Return -EOPNOTSUPP when the value of gic_version is not
>>         supported
>>
>> This patch is based on Vijay's GICv3 guest support patch [1] and my patch to
>> defer the initialization of the vGIC [2].
>>
>> Xen 4.5 has already support for the hardware GICv3. While it's possible to
>> boot and use DOM0, there is no guest support. The first version of this patch
>> has been sent a couple of months ago, but has never reached unstable for
>> various reasons (based on deferred series, lake of review at that time...).
>> Without it, platform with GICv3 support won't be able to boot any guest.
>>
>> The patch has been reworked to make it acceptable for Xen 4.5. Except the new
>> DOMCTL to retrieve the GIC version and one check. The code is purely GICv3.
>>
>> Features such as adding a new config option to let the user choose the GIC
>> version are deferred to Xen 4.6.
>>
>> It has been tested on both GICv2/GICv3 platform. And build tested for x86.
>>
>> [1] http://lists.xen.org/archives/html/xen-devel/2014-10/msg00583.html
>> [2] https://patches.linaro.org/34664/
>> ---
>>  tools/flask/policy/policy/modules/xen/xen.if |    2 +-
>>  tools/libxc/include/xenctrl.h                |    6 ++
>>  tools/libxc/xc_domain.c                      |   20 ++++++
>>  tools/libxl/libxl_arm.c                      |   97 
>> ++++++++++++++++++++++++--
>>  xen/arch/arm/domctl.c                        |   35 ++++++++++
>>  xen/arch/arm/gic-v3.c                        |   16 ++++-
>>  xen/include/public/arch-arm.h                |   16 +++++
>>  xen/include/public/domctl.h                  |   17 +++++
>>  xen/xsm/flask/hooks.c                        |    3 +
>>  xen/xsm/flask/policy/access_vectors          |    2 +
>>  10 files changed, 206 insertions(+), 8 deletions(-)
>>
>> diff --git a/tools/flask/policy/policy/modules/xen/xen.if 
>> b/tools/flask/policy/policy/modules/xen/xen.if
>> index 641c797..fa69c9d 100644
>> --- a/tools/flask/policy/policy/modules/xen/xen.if
>> +++ b/tools/flask/policy/policy/modules/xen/xen.if
>> @@ -49,7 +49,7 @@ define(`create_domain_common', `
>>                       getdomaininfo hypercall setvcpucontext 
>> setextvcpucontext
>>                       getscheduler getvcpuinfo getvcpuextstate getaddrsize
>>                       getaffinity setaffinity };
>> -     allow $1 $2:domain2 { set_cpuid settsc setscheduler setclaim 
>> set_max_evtchn set_vnumainfo get_vnumainfo psr_cmt_op };
>> +     allow $1 $2:domain2 { set_cpuid settsc setscheduler setclaim 
>> set_max_evtchn set_vnumainfo get_vnumainfo psr_cmt_op configure_domain };
>>       allow $1 $2:security check_context;
>>       allow $1 $2:shadow enable;
>>       allow $1 $2:mmu { map_read map_write adjust memorymap physmap pinpage 
>> mmuext_op };
>> diff --git a/tools/libxc/include/xenctrl.h b/tools/libxc/include/xenctrl.h
>> index 564e187..45e282c 100644
>> --- a/tools/libxc/include/xenctrl.h
>> +++ b/tools/libxc/include/xenctrl.h
>> @@ -483,6 +483,12 @@ int xc_domain_create(xc_interface *xch,
>>                       uint32_t flags,
>>                       uint32_t *pdomid);
>>
>> +#if defined(__arm__) || defined(__aarch64__)
>> +typedef xen_domctl_arm_configuredomain_t xc_domain_configuration_t;
>> +
>> +int xc_domain_configure(xc_interface *xch, uint32_t domid,
>> +                        xc_domain_configuration_t *config);
>> +#endif
>>
>>  /* Functions to produce a dump of a given domain
>>   *  xc_domain_dumpcore - produces a dump to a specified file
>> diff --git a/tools/libxc/xc_domain.c b/tools/libxc/xc_domain.c
>> index a9bcd4a..1aa1f45 100644
>> --- a/tools/libxc/xc_domain.c
>> +++ b/tools/libxc/xc_domain.c
>> @@ -48,6 +48,26 @@ int xc_domain_create(xc_interface *xch,
>>      return 0;
>>  }
>>
>> +#if defined(__arm__) || defined(__aarch64__)
>> +int xc_domain_configure(xc_interface *xch, uint32_t domid,
>> +                        xc_domain_configuration_t *config)
>> +{
>> +    int rc;
>> +    DECLARE_DOMCTL;
>> +
>> +    domctl.cmd = XEN_DOMCTL_arm_configure_domain;
>> +    domctl.domain = (domid_t)domid;
>> +    /* xc_domain_configure_t is an alias to xen_domctl_arm_configuredomain 
>> */
>> +    memcpy(&domctl.u.configuredomain, config, sizeof(*config));
>> +
>> +    rc = do_domctl(xch, &domctl);
>> +    if ( !rc )
>> +        memcpy(config, &domctl.u.configuredomain, sizeof(*config));
>> +
>> +    return rc;
>> +}
>> +#endif
>> +
>>  int xc_domain_cacheflush(xc_interface *xch, uint32_t domid,
>>                           xen_pfn_t start_pfn, xen_pfn_t nr_pfns)
>>  {
>> diff --git a/tools/libxl/libxl_arm.c b/tools/libxl/libxl_arm.c
>> index a122e4a..3dd6e7c 100644
>> --- a/tools/libxl/libxl_arm.c
>> +++ b/tools/libxl/libxl_arm.c
>> @@ -23,6 +23,18 @@
>>  #define DT_IRQ_TYPE_LEVEL_HIGH     0x00000004
>>  #define DT_IRQ_TYPE_LEVEL_LOW      0x00000008
>>
>> +static const char *gicv_to_string(uint8_t gic_version)
>> +{
>> +    switch (gic_version) {
>> +    case XEN_DOMCTL_CONFIG_GIC_V2:
>> +        return "V2";
>> +    case XEN_DOMCTL_CONFIG_GIC_V3:
>> +        return "V3";
>> +    default:
>> +        return "unknown";
>> +    }
>> +}
>> +
>>  int libxl__arch_domain_create(libxl__gc *gc, libxl_domain_config *d_config,
>>                                uint32_t domid)
>>  {
>> @@ -307,9 +319,9 @@ static int make_memory_nodes(libxl__gc *gc, void *fdt,
>>      return 0;
>>  }
>>
>> -static int make_intc_node(libxl__gc *gc, void *fdt,
>> -                          uint64_t gicd_base, uint64_t gicd_size,
>> -                          uint64_t gicc_base, uint64_t gicc_size)
>> +static int make_gicv2_node(libxl__gc *gc, void *fdt,
>> +                           uint64_t gicd_base, uint64_t gicd_size,
>> +                           uint64_t gicc_base, uint64_t gicc_size)
>>  {
>>      int res;
>>      const char *name = GCSPRINTF("interrupt-controller@%"PRIx64, gicd_base);
>> @@ -350,6 +362,57 @@ static int make_intc_node(libxl__gc *gc, void *fdt,
>>      return 0;
>>  }
>>
>> +static int make_gicv3_node(libxl__gc *gc, void *fdt)
>> +{
>> +    int res;
>> +    const uint64_t gicd_base = GUEST_GICV3_GICD_BASE;
>> +    const uint64_t gicd_size = GUEST_GICV3_GICD_SIZE;
>> +    const uint64_t gicr0_base = GUEST_GICV3_GICR0_BASE;
>> +    const uint64_t gicr0_size = GUEST_GICV3_GICR0_SIZE;
>> +    const char *name = GCSPRINTF("interrupt-controller@%"PRIx64, gicd_base);
>> +
>> +    res = fdt_begin_node(fdt, name);
>> +    if (res) return res;
>> +
>> +    res = fdt_property_compat(gc, fdt, 1,
>> +                              "arm,gic-v3");
>> +    if (res) return res;
>> +
>> +    res = fdt_property_cell(fdt, "#interrupt-cells", 3);
>> +    if (res) return res;
>> +
>> +    res = fdt_property_cell(fdt, "#address-cells", 0);
>> +    if (res) return res;
>> +
>> +    res = fdt_property(fdt, "interrupt-controller", NULL, 0);
>> +    if (res) return res;
>> +
>> +    res = fdt_property_cell(fdt, "redistributor-stride",
>> +                            GUEST_GICV3_RDIST_STRIDE);
>> +    if (res) return res;
>> +
>> +    res = fdt_property_cell(fdt, "#redistributor-regions",
>> +                            GUEST_GICV3_RDIST_REGIONS);
>> +    if (res) return res;
>> +
>> +    res = fdt_property_regs(gc, fdt, ROOT_ADDRESS_CELLS, ROOT_SIZE_CELLS,
>> +                            2,
>> +                            gicd_base, gicd_size,
>> +                            gicr0_base, gicr0_size);
>> +    if (res) return res;
>> +
>> +    res = fdt_property_cell(fdt, "linux,phandle", PHANDLE_GIC);
>> +    if (res) return res;
>> +
>> +    res = fdt_property_cell(fdt, "phandle", PHANDLE_GIC);
>> +    if (res) return res;
>> +
>> +    res = fdt_end_node(fdt);
>> +    if (res) return res;
>> +
>> +    return 0;
>> +}
>> +
>>  static int make_timer_node(libxl__gc *gc, void *fdt, const struct arch_info 
>> *ainfo)
>>  {
>>      int res;
>> @@ -456,6 +519,7 @@ int libxl__arch_domain_init_hw_description(libxl__gc *gc,
>>                                             libxl_domain_build_info *info,
>>                                             struct xc_dom_image *dom)
>>  {
>> +    xc_domain_configuration_t config;
>>      void *fdt = NULL;
>>      int rc, res;
>>      size_t fdt_size = 0;
>> @@ -471,8 +535,16 @@ int libxl__arch_domain_init_hw_description(libxl__gc 
>> *gc,
>>      ainfo = get_arch_info(gc, dom);
>>      if (ainfo == NULL) return ERROR_FAIL;
>>
>> +    LOG(DEBUG, "configure the domain");
>> +    config.gic_version = XEN_DOMCTL_CONFIG_GIC_DEFAULT;
>> +    if (xc_domain_configure(CTX->xch, dom->guest_domid, &config) != 0) {
>> +        LOG(ERROR, "counldn't configure the domain");
>> +        return ERROR_FAIL;
>> +    }
>> +
>>      LOG(DEBUG, "constructing DTB for Xen version %d.%d guest",
>>          vers->xen_version_major, vers->xen_version_minor);
>> +    LOG(DEBUG, "  - vGIC version: %s", gicv_to_string(config.gic_version));
>>
>>  /*
>>   * Call "call" handling FDR_ERR_*. Will either:
>> @@ -520,9 +592,22 @@ next_resize:
>>          FDT( make_psci_node(gc, fdt) );
>>
>>          FDT( make_memory_nodes(gc, fdt, dom) );
>> -        FDT( make_intc_node(gc, fdt,
>> -                            GUEST_GICD_BASE, GUEST_GICD_SIZE,
>> -                            GUEST_GICC_BASE, GUEST_GICD_SIZE) );
>> +
>> +        switch (config.gic_version) {
>> +        case XEN_DOMCTL_CONFIG_GIC_V2:
>> +            FDT( make_gicv2_node(gc, fdt,
>> +                                 GUEST_GICD_BASE, GUEST_GICD_SIZE,
>> +                                 GUEST_GICC_BASE, GUEST_GICC_SIZE) );
>> +            break;
>> +        case XEN_DOMCTL_CONFIG_GIC_V3:
>> +            FDT( make_gicv3_node(gc, fdt) );
>> +            break;
>> +        default:
>> +            LOG(ERROR, "Unknown how to create the DT node for gic_version = 
>> %d",
>> +                config.gic_version);
>> +            rc = ERROR_FAIL;
>> +            goto out;
>> +        }
>>
>>          FDT( make_timer_node(gc, fdt, ainfo) );
>>          FDT( make_hypervisor_node(gc, fdt, vers) );
>> diff --git a/xen/arch/arm/domctl.c b/xen/arch/arm/domctl.c
>> index 45974e7..5b8ff57 100644
>> --- a/xen/arch/arm/domctl.c
>> +++ b/xen/arch/arm/domctl.c
>> @@ -10,6 +10,8 @@
>>  #include <xen/errno.h>
>>  #include <xen/sched.h>
>>  #include <xen/hypercall.h>
>> +#include <asm/gic.h>
>> +#include <xen/guest_access.h>
>>  #include <public/domctl.h>
>>
>>  long arch_do_domctl(struct xen_domctl *domctl, struct domain *d,
>> @@ -30,6 +32,39 @@ long arch_do_domctl(struct xen_domctl *domctl, struct 
>> domain *d,
>>
>>          return p2m_cache_flush(d, s, e);
>>      }
>> +    case XEN_DOMCTL_arm_configure_domain:
>> +    {
>> +        uint8_t gic_version;
>> +
>> +        /*
>> +         * Xen 4.5: The vGIC is emulating the same version of the
>> +         * hardware GIC. Only the value XEN_DOMCTL_CONFIG_GIC_DEFAULT
>> +         * is allowed. The DOMCTL will return the actual version of the
>> +         * GIC.
>> +         */
>> +        if ( domctl->u.configuredomain.gic_version != 
>> XEN_DOMCTL_CONFIG_GIC_DEFAULT )
>> +            return -EOPNOTSUPP;
>> +
>> +        switch ( gic_hw_version() )
>> +        {
>> +        case GIC_V3:
>> +            gic_version = XEN_DOMCTL_CONFIG_GIC_V3;
>> +            break;
>> +        case GIC_V2:
>> +            gic_version = XEN_DOMCTL_CONFIG_GIC_V2;
>> +            break;
>> +        default:
>> +            BUG();
>> +        }
>> +
>> +        domctl->u.configuredomain.gic_version = gic_version;
>> +
>> +        /* TODO: Make the copy generic for all ARCH domctl */
>> +        if ( __copy_to_guest(u_domctl, domctl, 1) )
>> +            return -EFAULT;
>> +
>> +        return 0;
>> +    }
>>
>>      default:
>>          return subarch_do_domctl(domctl, d, u_domctl);
>> diff --git a/xen/arch/arm/gic-v3.c b/xen/arch/arm/gic-v3.c
>> index 91161a2..076aa62 100644
>> --- a/xen/arch/arm/gic-v3.c
>> +++ b/xen/arch/arm/gic-v3.c
>> @@ -906,7 +906,21 @@ static int gicv_v3_init(struct domain *d)
>>          d->arch.vgic.rdist_count = gicv3.rdist_count;
>>      }
>>      else
>> -        d->arch.vgic.dbase = GUEST_GICD_BASE;
>> +    {
>> +        d->arch.vgic.dbase = GUEST_GICV3_GICD_BASE;
>> +        d->arch.vgic.dbase_size = GUEST_GICV3_GICD_SIZE;
>> +
>> +        /* XXX: Only one Re-distributor region mapped for the guest */
>> +        BUILD_BUG_ON(GUEST_GICV3_RDIST_REGIONS != 1);
>> +
>> +        d->arch.vgic.rdist_count = GUEST_GICV3_RDIST_REGIONS;
>> +        d->arch.vgic.rdist_stride = GUEST_GICV3_RDIST_STRIDE;
>> +
>> +        /* The first redistributor should contain enough space for all CPUs 
>> */
>> +        BUILD_BUG_ON((GUEST_GICV3_GICR0_SIZE / GUEST_GICV3_RDIST_STRIDE) < 
>> MAX_VIRT_CPUS);
>> +        d->arch.vgic.rbase[0] = GUEST_GICV3_GICR0_BASE;
>> +        d->arch.vgic.rbase_size[0] = GUEST_GICV3_GICR0_SIZE;
>> +    }
>>
>>      d->arch.vgic.nr_lines = 0;
>>
>> diff --git a/xen/include/public/arch-arm.h b/xen/include/public/arch-arm.h
>> index eecc561..d7df274 100644
>> --- a/xen/include/public/arch-arm.h
>> +++ b/xen/include/public/arch-arm.h
>> @@ -373,11 +373,27 @@ typedef uint64_t xen_callback_t;
>>   */
>>
>>  /* Physical Address Space */
>> +
>> +/* vGIC mappings: Only one set of mapping is used by the guest.
>> + * Therefore they can overlap.
>> + */
>> +
>> +/* vGIC v2 mappings */
>>  #define GUEST_GICD_BASE   0x03001000ULL
>>  #define GUEST_GICD_SIZE   0x00001000ULL
>>  #define GUEST_GICC_BASE   0x03002000ULL
>>  #define GUEST_GICC_SIZE   0x00000100ULL
>>
>> +/* vGIC v3 mappings */
>> +#define GUEST_GICV3_GICD_BASE      0x03001000ULL
>> +#define GUEST_GICV3_GICD_SIZE      0x00010000ULL
>> +
>> +#define GUEST_GICV3_RDIST_STRIDE   0x20000ULL
>> +#define GUEST_GICV3_RDIST_REGIONS  1
>> +
>> +#define GUEST_GICV3_GICR0_BASE     0x03020000ULL    /* vCPU0 - vCPU15 */
>> +#define GUEST_GICV3_GICR0_SIZE     0x00200000ULL
>> +
>>  /* 16MB == 4096 pages reserved for guest to use as a region to map its
>>   * grant table in.
>>   */
>> diff --git a/xen/include/public/domctl.h b/xen/include/public/domctl.h
>> index 58b19e7..8da204e 100644
>> --- a/xen/include/public/domctl.h
>> +++ b/xen/include/public/domctl.h
>> @@ -68,6 +68,19 @@ struct xen_domctl_createdomain {
>>  typedef struct xen_domctl_createdomain xen_domctl_createdomain_t;
>>  DEFINE_XEN_GUEST_HANDLE(xen_domctl_createdomain_t);
>>
>> +#if defined(__arm__) || defined(__aarch64__)
>> +#define XEN_DOMCTL_CONFIG_GIC_DEFAULT   0
>> +#define XEN_DOMCTL_CONFIG_GIC_V2        1
>> +#define XEN_DOMCTL_CONFIG_GIC_V3        2
>> +/* XEN_DOMCTL_configure_domain */
>> +struct xen_domctl_arm_configuredomain {
>> +    /* IN/OUT parameters */
>> +    uint8_t gic_version;
>> +};
>> +typedef struct xen_domctl_arm_configuredomain 
>> xen_domctl_arm_configuredomain_t;
>> +DEFINE_XEN_GUEST_HANDLE(xen_domctl_arm_configuredomain_t);
>> +#endif
>> +
>>  /* XEN_DOMCTL_getdomaininfo */
>>  struct xen_domctl_getdomaininfo {
>>      /* OUT variables. */
>> @@ -1056,6 +1069,7 @@ struct xen_domctl {
>>  #define XEN_DOMCTL_set_vcpu_msrs                 73
>>  #define XEN_DOMCTL_setvnumainfo                  74
>>  #define XEN_DOMCTL_psr_cmt_op                    75
>> +#define XEN_DOMCTL_arm_configure_domain          76
>>  #define XEN_DOMCTL_gdbsx_guestmemio            1000
>>  #define XEN_DOMCTL_gdbsx_pausevcpu             1001
>>  #define XEN_DOMCTL_gdbsx_unpausevcpu           1002
>> @@ -1064,6 +1078,9 @@ struct xen_domctl {
>>      domid_t  domain;
>>      union {
>>          struct xen_domctl_createdomain      createdomain;
>> +#if defined(__arm__) || defined(__aarch64__)
>> +        struct xen_domctl_arm_configuredomain configuredomain;
>> +#endif
>>          struct xen_domctl_getdomaininfo     getdomaininfo;
>>          struct xen_domctl_getmemlist        getmemlist;
>>          struct xen_domctl_getpageframeinfo  getpageframeinfo;
>> diff --git a/xen/xsm/flask/hooks.c b/xen/xsm/flask/hooks.c
>> index 6d0fe72..846cf88 100644
>> --- a/xen/xsm/flask/hooks.c
>> +++ b/xen/xsm/flask/hooks.c
>> @@ -727,6 +727,9 @@ static int flask_domctl(struct domain *d, int cmd)
>>      case XEN_DOMCTL_psr_cmt_op:
>>          return current_has_perm(d, SECCLASS_DOMAIN2, DOMAIN2__PSR_CMT_OP);
>>
>> +    case XEN_DOMCTL_configure_domain:
>> +        return current_has_perm(d, SECCLASS_DOMAIN2, 
>> DOMAIN2__CONFIGURE_DOMAIN);
>> +
>>      default:
>>          printk("flask_domctl: Unknown op %d\n", cmd);
>>          return -EPERM;
>> diff --git a/xen/xsm/flask/policy/access_vectors 
>> b/xen/xsm/flask/policy/access_vectors
>> index de0c707..bfe2fa5 100644
>> --- a/xen/xsm/flask/policy/access_vectors
>> +++ b/xen/xsm/flask/policy/access_vectors
>> @@ -216,6 +216,8 @@ class domain2
>>      get_vnumainfo
>>  # XEN_DOMCTL_psr_cmt_op
>>      psr_cmt_op
>> +# XEN_DOMCTL_configure_domain
>> +    configure_domain
>>  }
>>
>>  # Similar to class domain, but primarily contains domctls related to HVM 
>> domains
>> --
>> 1.7.10.4
>>
>
> _______________________________________________
> Xen-devel mailing list
> Xen-devel@xxxxxxxxxxxxx
> http://lists.xen.org/xen-devel

_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel


 


Rackspace

Lists.xenproject.org is hosted with RackSpace, monitoring our
servers 24x7x365 and backed by RackSpace's Fanatical Support®.