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

Re: [Xen-devel] [PATCH v3 02/24] xen/arm: Divide GIC initialization in 2 parts



On Tue, 13 Jan 2015, Julien Grall wrote:
> Currently the function to translate IRQ from the device tree is set
> unconditionally  to be able to be able to retrieve serial/timer IRQ before the
> GIC has been initialized.
> 
> It assumes that the xlate function won't never changed. We may also need to
> have the primary interrupt controller very early.
> 
> Rework the gic initialization in 2 parts:
>     - gic_preinit: Get the interrupt controller device tree node and set
> up GIC and xlate callbacks
>     - gic_init: Initialize the interrupt controller and the boot CPU
>     interrupts.
> 
> The former function will be called just after the IRQ subsystem as been
> initialized.
> 
> Signed-off-by: Julien Grall <julien.grall@xxxxxxxxxx>

Acked-by: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx>


> ---
>     Changes in v3:
>         - Patch was previously sent in a separate series [1]
>         - Reorder the function to avoid forward declaration
>         - Make gic-v3 driver compliant to the new interface
>         - Remove spurious field addition in gicv2 structure
> 
>     Changelog based on the separate series:
> 
>     Changes in v3:
>         - Patch added.
> 
>     [1] https://patches.linaro.org/33313/
> ---
>  xen/arch/arm/gic-v2.c     | 70 ++++++++++++++++++++++---------------------
>  xen/arch/arm/gic-v3.c     | 75 
> ++++++++++++++++++++++++-----------------------
>  xen/arch/arm/gic.c        | 16 ++++++++--
>  xen/arch/arm/setup.c      |  3 +-
>  xen/include/asm-arm/gic.h |  8 +++++
>  5 files changed, 100 insertions(+), 72 deletions(-)
> 
> diff --git a/xen/arch/arm/gic-v2.c b/xen/arch/arm/gic-v2.c
> index 15916c9..016b0fd 100644
> --- a/xen/arch/arm/gic-v2.c
> +++ b/xen/arch/arm/gic-v2.c
> @@ -655,37 +655,10 @@ static hw_irq_controller gicv2_guest_irq_type = {
>      .set_affinity = gicv2_irq_set_affinity,
>  };
>  
> -const static struct gic_hw_operations gicv2_ops = {
> -    .info                = &gicv2_info,
> -    .secondary_init      = gicv2_secondary_cpu_init,
> -    .save_state          = gicv2_save_state,
> -    .restore_state       = gicv2_restore_state,
> -    .dump_state          = gicv2_dump_state,
> -    .gicv_setup          = gicv2v_setup,
> -    .gic_host_irq_type   = &gicv2_host_irq_type,
> -    .gic_guest_irq_type  = &gicv2_guest_irq_type,
> -    .eoi_irq             = gicv2_eoi_irq,
> -    .deactivate_irq      = gicv2_dir_irq,
> -    .read_irq            = gicv2_read_irq,
> -    .set_irq_properties  = gicv2_set_irq_properties,
> -    .send_SGI            = gicv2_send_SGI,
> -    .disable_interface   = gicv2_disable_interface,
> -    .update_lr           = gicv2_update_lr,
> -    .update_hcr_status   = gicv2_hcr_status,
> -    .clear_lr            = gicv2_clear_lr,
> -    .read_lr             = gicv2_read_lr,
> -    .write_lr            = gicv2_write_lr,
> -    .read_vmcr_priority  = gicv2_read_vmcr_priority,
> -    .read_apr            = gicv2_read_apr,
> -    .make_dt_node        = gicv2_make_dt_node,
> -};
> -
> -/* Set up the GIC */
> -static int __init gicv2_init(struct dt_device_node *node, const void *data)
> +static int __init gicv2_init(void)
>  {
>      int res;
> -
> -    dt_device_set_used_by(node, DOMID_XEN);
> +    const struct dt_device_node *node = gicv2_info.node;
>  
>      res = dt_device_get_address(node, 0, &gicv2.dbase, NULL);
>      if ( res || !gicv2.dbase || (gicv2.dbase & ~PAGE_MASK) )
> @@ -708,9 +681,6 @@ static int __init gicv2_init(struct dt_device_node *node, 
> const void *data)
>          panic("GICv2: Cannot find the maintenance IRQ");
>      gicv2_info.maintenance_irq = res;
>  
> -    /* Set the GIC as the primary interrupt controller */
> -    dt_interrupt_controller = node;
> -
>      /* TODO: Add check on distributor, cpu size */
>  
>      printk("GICv2 initialization:\n"
> @@ -755,8 +725,42 @@ static int __init gicv2_init(struct dt_device_node 
> *node, const void *data)
>  
>      spin_unlock(&gicv2.lock);
>  
> +    return 0;
> +}
> +
> +const static struct gic_hw_operations gicv2_ops = {
> +    .info                = &gicv2_info,
> +    .init                = gicv2_init,
> +    .secondary_init      = gicv2_secondary_cpu_init,
> +    .save_state          = gicv2_save_state,
> +    .restore_state       = gicv2_restore_state,
> +    .dump_state          = gicv2_dump_state,
> +    .gicv_setup          = gicv2v_setup,
> +    .gic_host_irq_type   = &gicv2_host_irq_type,
> +    .gic_guest_irq_type  = &gicv2_guest_irq_type,
> +    .eoi_irq             = gicv2_eoi_irq,
> +    .deactivate_irq      = gicv2_dir_irq,
> +    .read_irq            = gicv2_read_irq,
> +    .set_irq_properties  = gicv2_set_irq_properties,
> +    .send_SGI            = gicv2_send_SGI,
> +    .disable_interface   = gicv2_disable_interface,
> +    .update_lr           = gicv2_update_lr,
> +    .update_hcr_status   = gicv2_hcr_status,
> +    .clear_lr            = gicv2_clear_lr,
> +    .read_lr             = gicv2_read_lr,
> +    .write_lr            = gicv2_write_lr,
> +    .read_vmcr_priority  = gicv2_read_vmcr_priority,
> +    .read_apr            = gicv2_read_apr,
> +    .make_dt_node        = gicv2_make_dt_node,
> +};
> +
> +/* Set up the GIC */
> +static int __init gicv2_preinit(struct dt_device_node *node, const void 
> *data)
> +{
>      gicv2_info.hw_version = GIC_V2;
> +    gicv2_info.node = node;
>      register_gic_ops(&gicv2_ops);
> +    dt_irq_xlate = gic_irq_xlate;
>  
>      return 0;
>  }
> @@ -769,7 +773,7 @@ static const struct dt_device_match gicv2_dt_match[] 
> __initconst =
>  
>  DT_DEVICE_START(gicv2, "GICv2", DEVICE_GIC)
>          .dt_match = gicv2_dt_match,
> -        .init = gicv2_init,
> +        .init = gicv2_preinit,
>  DT_DEVICE_END
>  
>  /*
> diff --git a/xen/arch/arm/gic-v3.c b/xen/arch/arm/gic-v3.c
> index 2ddcbab..f650756 100644
> --- a/xen/arch/arm/gic-v3.c
> +++ b/xen/arch/arm/gic-v3.c
> @@ -1141,37 +1141,13 @@ static const hw_irq_controller gicv3_guest_irq_type = 
> {
>      .set_affinity = gicv3_irq_set_affinity,
>  };
>  
> -static const struct gic_hw_operations gicv3_ops = {
> -    .info                = &gicv3_info,
> -    .save_state          = gicv3_save_state,
> -    .restore_state       = gicv3_restore_state,
> -    .dump_state          = gicv3_dump_state,
> -    .gicv_setup          = gicv_v3_init,
> -    .gic_host_irq_type   = &gicv3_host_irq_type,
> -    .gic_guest_irq_type  = &gicv3_guest_irq_type,
> -    .eoi_irq             = gicv3_eoi_irq,
> -    .deactivate_irq      = gicv3_dir_irq,
> -    .read_irq            = gicv3_read_irq,
> -    .set_irq_properties  = gicv3_set_irq_properties,
> -    .send_SGI            = gicv3_send_sgi,
> -    .disable_interface   = gicv3_disable_interface,
> -    .update_lr           = gicv3_update_lr,
> -    .update_hcr_status   = gicv3_hcr_status,
> -    .clear_lr            = gicv3_clear_lr,
> -    .read_lr             = gicv3_read_lr,
> -    .write_lr            = gicv3_write_lr,
> -    .read_vmcr_priority  = gicv3_read_vmcr_priority,
> -    .read_apr            = gicv3_read_apr,
> -    .secondary_init      = gicv3_secondary_cpu_init,
> -    .make_dt_node        = gicv3_make_dt_node,
> -};
> -
>  /* Set up the GIC */
> -static int __init gicv3_init(struct dt_device_node *node, const void *data)
> +static int __init gicv3_init(void)
>  {
>      struct rdist_region *rdist_regs;
>      int res, i;
>      uint32_t reg;
> +    const struct dt_device_node *node = gicv3_info.node;
>  
>      if ( !cpu_has_gicv3 )
>      {
> @@ -1179,8 +1155,6 @@ static int __init gicv3_init(struct dt_device_node 
> *node, const void *data)
>          return -ENODEV;
>      }
>  
> -    dt_device_set_used_by(node, DOMID_XEN);
> -
>      res = dt_device_get_address(node, 0, &gicv3.dbase, &gicv3.dbase_size);
>      if ( res || !gicv3.dbase )
>          panic("GICv3: Cannot find a valid distributor address");
> @@ -1232,9 +1206,6 @@ static int __init gicv3_init(struct dt_device_node 
> *node, const void *data)
>          panic("GICv3: Cannot find the maintenance IRQ");
>      gicv3_info.maintenance_irq = res;
>  
> -    /* Set the GIC as the primary interrupt controller */
> -    dt_interrupt_controller = node;
> -
>      for ( i = 0; i < gicv3.rdist_count; i++ )
>      {
>          /* map dbase & rdist regions */
> @@ -1269,15 +1240,47 @@ static int __init gicv3_init(struct dt_device_node 
> *node, const void *data)
>      res = gicv3_cpu_init();
>      gicv3_hyp_init();
>  
> -    gicv3_info.hw_version = GIC_V3;
> -    /* Register hw ops*/
> -    register_gic_ops(&gicv3_ops);
> -
>      spin_unlock(&gicv3.lock);
>  
>      return res;
>  }
>  
> +static const struct gic_hw_operations gicv3_ops = {
> +    .info                = &gicv3_info,
> +    .init                = gicv3_init,
> +    .save_state          = gicv3_save_state,
> +    .restore_state       = gicv3_restore_state,
> +    .dump_state          = gicv3_dump_state,
> +    .gicv_setup          = gicv_v3_init,
> +    .gic_host_irq_type   = &gicv3_host_irq_type,
> +    .gic_guest_irq_type  = &gicv3_guest_irq_type,
> +    .eoi_irq             = gicv3_eoi_irq,
> +    .deactivate_irq      = gicv3_dir_irq,
> +    .read_irq            = gicv3_read_irq,
> +    .set_irq_properties  = gicv3_set_irq_properties,
> +    .send_SGI            = gicv3_send_sgi,
> +    .disable_interface   = gicv3_disable_interface,
> +    .update_lr           = gicv3_update_lr,
> +    .update_hcr_status   = gicv3_hcr_status,
> +    .clear_lr            = gicv3_clear_lr,
> +    .read_lr             = gicv3_read_lr,
> +    .write_lr            = gicv3_write_lr,
> +    .read_vmcr_priority  = gicv3_read_vmcr_priority,
> +    .read_apr            = gicv3_read_apr,
> +    .secondary_init      = gicv3_secondary_cpu_init,
> +    .make_dt_node        = gicv3_make_dt_node,
> +};
> +
> +static int __init gicv3_preinit(struct dt_device_node *node, const void 
> *data)
> +{
> +    gicv3_info.hw_version = GIC_V3;
> +    gicv3_info.node = node;
> +    register_gic_ops(&gicv3_ops);
> +    dt_irq_xlate = gic_irq_xlate;
> +
> +    return 0;
> +}
> +
>  static const struct dt_device_match gicv3_dt_match[] __initconst =
>  {
>      DT_MATCH_GIC_V3,
> @@ -1286,7 +1289,7 @@ static const struct dt_device_match gicv3_dt_match[] 
> __initconst =
>  
>  DT_DEVICE_START(gicv3, "GICv3", DEVICE_GIC)
>          .dt_match = gicv3_dt_match,
> -        .init = gicv3_init,
> +        .init = gicv3_preinit,
>  DT_DEVICE_END
>  
>  /*
> diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
> index d1ab6b5..63147f3 100644
> --- a/xen/arch/arm/gic.c
> +++ b/xen/arch/arm/gic.c
> @@ -163,8 +163,10 @@ int gic_irq_xlate(const u32 *intspec, unsigned int 
> intsize,
>      return 0;
>  }
>  
> -/* Set up the GIC */
> -void __init gic_init(void)
> +/* Find the interrupt controller and set up the callback to translate
> + * device tree IRQ.
> + */
> +void __init gic_preinit(void)
>  {
>      int rc;
>      struct dt_device_node *node;
> @@ -189,6 +191,16 @@ void __init gic_init(void)
>      if ( !num_gics )
>          panic("Unable to find compatible GIC in the device tree");
>  
> +    /* Set the GIC as the primary interrupt controller */
> +    dt_interrupt_controller = node;
> +    dt_device_set_used_by(node, DOMID_XEN);
> +}
> +
> +/* Set up the GIC */
> +void __init gic_init(void)
> +{
> +    if ( gic_hw_ops->init() )
> +        panic("Failed to initialize the GIC drivers");
>      /* Clear LR mask for cpu0 */
>      clear_cpu_lr_mask();
>  }
> diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
> index 4d242e0..18227f6 100644
> --- a/xen/arch/arm/setup.c
> +++ b/xen/arch/arm/setup.c
> @@ -740,10 +740,11 @@ void __init start_xen(unsigned long boot_phys_offset,
>  
>      vm_init();
>      dt_unflatten_host_device_tree();
> -    dt_irq_xlate = gic_irq_xlate;
>  
>      init_IRQ();
>  
> +    gic_preinit();
> +
>      dt_uart_init();
>      console_init_preirq();
>      console_init_ring();
> diff --git a/xen/include/asm-arm/gic.h b/xen/include/asm-arm/gic.h
> index 73ca3cf..6286c71 100644
> --- a/xen/include/asm-arm/gic.h
> +++ b/xen/include/asm-arm/gic.h
> @@ -229,6 +229,10 @@ extern void gic_remove_from_queues(struct vcpu *v, 
> unsigned int virtual_irq);
>  
>  /* Accept an interrupt from the GIC and dispatch its handler */
>  extern void gic_interrupt(struct cpu_user_regs *regs, int is_fiq);
> +/* Find the interrupt controller and set up the callback to translate
> + * device tree IRQ.
> + */
> +extern void gic_preinit(void);
>  /* Bring up the interrupt controller, and report # cpus attached */
>  extern void gic_init(void);
>  /* Bring up a secondary CPU's per-CPU GIC interface */
> @@ -281,11 +285,15 @@ struct gic_info {
>      uint8_t nr_lrs;
>      /* Maintenance irq number */
>      unsigned int maintenance_irq;
> +    /* Pointer to the device tree node representing the interrupt controller 
> */
> +    const struct dt_device_node *node;
>  };
>  
>  struct gic_hw_operations {
>      /* Hold GIC HW information */
>      const struct gic_info *info;
> +    /* Initialize the GIC and the boot CPU */
> +    int (*init)(void);
>      /* Save GIC registers */
>      void (*save_state)(struct vcpu *);
>      /* Restore GIC registers */
> -- 
> 2.1.4
> 

_______________________________________________
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®.