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

Re: [Xen-devel] [PATCH v3] xen/arm: get the number of cpus from device tree



On Thu, 2012-11-15 at 17:48 +0000, Stefano Stabellini wrote:
> The system might have fewer cpus than the GIC supports.
> 
> Changes in v3:
> - get cpu nodes matching the device_type property on the DT;
> - get the cpu ID from the reg property on the DT;
> - hook the DT cpu parsing in early_scan_node.
> 
> Changes in v2:
> - return always at least 1 cpu;
> - skip nodes with names that don't start with "cpu".
> 
> Signed-off-by: Stefano Stabellini <stefano.stabellini@xxxxxxxxxxxxx>

Acked + applied, thanks.

Small reject in xen/arch/arm/setup.c due to changes in the flush D-cache
patch (the panic on preposterous cahceline size at the start of
start_xen is gone). Please check I did the right thing!

> ---
>  xen/arch/arm/gic.c        |    4 +---
>  xen/arch/arm/gic.h        |    2 +-
>  xen/arch/arm/setup.c      |    5 ++++-
>  xen/arch/arm/smpboot.c    |   27 ++++++++++++++++++++-------
>  xen/common/device_tree.c  |   43 +++++++++++++++++++++++++++++++++++++++++++
>  xen/include/asm-arm/smp.h |    2 ++
>  6 files changed, 71 insertions(+), 12 deletions(-)
> 
> diff --git a/xen/arch/arm/gic.c b/xen/arch/arm/gic.c
> index 5f06e08..0c6fab9 100644
> --- a/xen/arch/arm/gic.c
> +++ b/xen/arch/arm/gic.c
> @@ -304,7 +304,7 @@ static void __cpuinit gic_hyp_disable(void)
>  }
>  
>  /* Set up the GIC */
> -int __init gic_init(void)
> +void __init gic_init(void)
>  {
>      /* XXX FIXME get this from devicetree */
>      gic.dbase = GIC_BASE_ADDRESS + GIC_DR_OFFSET;
> @@ -328,8 +328,6 @@ int __init gic_init(void)
>      gic.lr_mask = 0ULL;
>  
>      spin_unlock(&gic.lock);
> -
> -    return gic.cpus;
>  }
>  
>  /* Set up the per-CPU parts of the GIC for a secondary CPU */
> diff --git a/xen/arch/arm/gic.h b/xen/arch/arm/gic.h
> index b2e1d7f..1bf1b02 100644
> --- a/xen/arch/arm/gic.h
> +++ b/xen/arch/arm/gic.h
> @@ -147,7 +147,7 @@ extern int gic_route_irq_to_guest(struct domain *d, 
> unsigned int irq,
>  /* Accept an interrupt from the GIC and dispatch its handler */
>  extern void gic_interrupt(struct cpu_user_regs *regs, int is_fiq);
>  /* Bring up the interrupt controller, and report # cpus attached */
> -extern int gic_init(void);
> +extern void gic_init(void);
>  /* Bring up a secondary CPU's per-CPU GIC interface */
>  extern void gic_init_secondary_cpu(void);
>  /* Take down a CPU's per-CPU GIC interface */
> diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
> index a579a56..d5d845a 100644
> --- a/xen/arch/arm/setup.c
> +++ b/xen/arch/arm/setup.c
> @@ -189,10 +189,13 @@ void __init start_xen(unsigned long boot_phys_offset,
>      if ( cacheline_bytes < MIN_CACHELINE_BYTES )
>          panic("CPU has preposterously small cache lines");
>  
> +    smp_clear_cpu_maps();
> +
>      fdt = (void *)BOOT_MISC_VIRT_START
>          + (atag_paddr & ((1 << SECOND_SHIFT) - 1));
>      fdt_size = device_tree_early_init(fdt);
>  
> +    cpus = smp_get_max_cpus();
>      cmdline_parse(device_tree_bootargs(fdt));
>  
>      setup_pagetables(boot_phys_offset, get_xen_paddr());
> @@ -203,7 +206,7 @@ void __init start_xen(unsigned long boot_phys_offset,
>      console_init_preirq();
>  #endif
>  
> -    cpus = gic_init();
> +    gic_init();
>      make_cpus_ready(cpus, boot_phys_offset);
>  
>      percpu_init_areas();
> diff --git a/xen/arch/arm/smpboot.c b/xen/arch/arm/smpboot.c
> index f4fd512..93b7ded 100644
> --- a/xen/arch/arm/smpboot.c
> +++ b/xen/arch/arm/smpboot.c
> @@ -71,18 +71,31 @@ static void setup_cpu_sibling_map(int cpu)
>      cpumask_set_cpu(cpu, per_cpu(cpu_core_mask, cpu));
>  }
>  
> -
>  void __init
> -smp_prepare_cpus (unsigned int max_cpus)
> +smp_clear_cpu_maps (void)
>  {
> -    int i;
> -
> +    cpumask_clear(&cpu_possible_map);
>      cpumask_clear(&cpu_online_map);
>      cpumask_set_cpu(0, &cpu_online_map);
> +    cpumask_set_cpu(0, &cpu_possible_map);
> +}
>  
> -    cpumask_clear(&cpu_possible_map);
> -    for ( i = 0; i < max_cpus; i++ )
> -        cpumask_set_cpu(i, &cpu_possible_map);
> +int __init
> +smp_get_max_cpus (void)
> +{
> +    int i, max_cpus = 0;
> +
> +    for ( i = 0; i < nr_cpu_ids; i++ )
> +        if ( cpu_possible(i) )
> +            max_cpus++;
> +
> +    return max_cpus;
> +}
> +
> +
> +void __init
> +smp_prepare_cpus (unsigned int max_cpus)
> +{
>      cpumask_copy(&cpu_present_map, &cpu_possible_map);
>  
>      setup_cpu_sibling_map(0);
> diff --git a/xen/common/device_tree.c b/xen/common/device_tree.c
> index 3d1f0f4..da0af77 100644
> --- a/xen/common/device_tree.c
> +++ b/xen/common/device_tree.c
> @@ -18,6 +18,7 @@
>  #include <xen/mm.h>
>  #include <xen/stdarg.h>
>  #include <xen/string.h>
> +#include <xen/cpumask.h>
>  #include <asm/early_printk.h>
>  
>  struct dt_early_info __initdata early_info;
> @@ -41,6 +42,18 @@ bool_t device_tree_node_matches(const void *fdt, int node, 
> const char *match)
>          && (name[match_len] == '@' || name[match_len] == '\0');
>  }
>  
> +bool_t device_tree_type_matches(const void *fdt, int node, const char *match)
> +{
> +    int len;
> +    const void *prop;
> +
> +    prop = fdt_getprop(fdt, node, "device_type", &len);
> +    if ( prop == NULL )
> +        return 0;
> +
> +    return !strncmp(prop, match, len);
> +}
> +
>  static void __init get_val(const u32 **cell, u32 cells, u64 *val)
>  {
>      *val = 0;
> @@ -229,6 +242,34 @@ static void __init process_memory_node(const void *fdt, 
> int node,
>      }
>  }
>  
> +static void __init process_cpu_node(const void *fdt, int node,
> +                                    const char *name,
> +                                    u32 address_cells, u32 size_cells)
> +{
> +    const struct fdt_property *prop;
> +    const u32 *cell;
> +    paddr_t start, size;
> +
> +    if ( address_cells != 1 || size_cells != 0 )
> +    {
> +        early_printk("fdt: node `%s': invalid #address-cells or #size-cells",
> +                     name);
> +        return;
> +    }
> +
> +    prop = fdt_get_property(fdt, node, "reg", NULL);
> +    if ( !prop )
> +    {
> +        early_printk("fdt: node `%s': missing `reg' property\n", name);
> +        return;
> +    }
> +
> +    cell = (const u32 *)prop->data;
> +    device_tree_get_reg(&cell, address_cells, size_cells, &start, &size);
> +
> +    cpumask_set_cpu(start, &cpu_possible_map);
> +}
> +
>  static int __init early_scan_node(const void *fdt,
>                                    int node, const char *name, int depth,
>                                    u32 address_cells, u32 size_cells,
> @@ -236,6 +277,8 @@ static int __init early_scan_node(const void *fdt,
>  {
>      if ( device_tree_node_matches(fdt, node, "memory") )
>          process_memory_node(fdt, node, name, address_cells, size_cells);
> +    else if ( device_tree_type_matches(fdt, node, "cpu") )
> +        process_cpu_node(fdt, node, name, address_cells, size_cells);
>  
>      return 0;
>  }
> diff --git a/xen/include/asm-arm/smp.h b/xen/include/asm-arm/smp.h
> index a98032d..d4ed1cb 100644
> --- a/xen/include/asm-arm/smp.h
> +++ b/xen/include/asm-arm/smp.h
> @@ -22,6 +22,8 @@ extern void stop_cpu(void);
>  extern void
>  make_cpus_ready(unsigned int max_cpus, unsigned long boot_phys_offset);
>  
> +extern void smp_clear_cpu_maps (void);
> +extern int smp_get_max_cpus (void);
>  #endif
>  /*
>   * Local variables:



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