xen-devel.lists.xenproject.org archive mirror
 help / color / mirror / Atom feed
From: Julien Grall <julien.grall@linaro.org>
To: Ian Campbell <Ian.Campbell@citrix.com>
Cc: stefano.stabellini@eu.citrix.com, patches@linaro.org,
	xen-devel@lists.xen.org
Subject: Re: [PATCH 6/7] xen/arm: Dissociate logical and hardware CPU ID
Date: Tue, 10 Sep 2013 17:18:00 +0100	[thread overview]
Message-ID: <522F4638.3080807@linaro.org> (raw)
In-Reply-To: <1378733882.19967.136.camel@kazak.uk.xensource.com>

On 09/09/2013 02:38 PM, Ian Campbell wrote:
> t gOn Fri, 2013-08-30 at 14:30 +0100, Julien Grall wrote:
>> Introduce cpu_logical_map to associate a logical CPU ID to an hardware CPU ID.
>> This map will be filled during Xen boot via the device tree. Each CPU node
>> contains a "reg" property which contains the hardware ID (ie MPIDR[0:23]).
>>
>> Also move /cpus parsing later so we can use the dt_* API.
>>
>> Signed-off-by: Julien Grall <julien.grall@linaro.org>
>> ---
>>  xen/arch/arm/setup.c            |  109 ++++++++++++++++++++++++++++++++++++++-
>>  xen/arch/arm/smpboot.c          |    4 ++
>>  xen/common/device_tree.c        |   48 -----------------
>>  xen/include/asm-arm/processor.h |    4 ++
>>  4 files changed, 116 insertions(+), 49 deletions(-)
>>
>> diff --git a/xen/arch/arm/setup.c b/xen/arch/arm/setup.c
>> index 137a65e..fabad91 100644
>> --- a/xen/arch/arm/setup.c
>> +++ b/xen/arch/arm/setup.c
>> @@ -496,6 +496,111 @@ void __init setup_cache(void)
>>      cacheline_bytes = 1U << (4 + (ccsid & 0x7));
>>  }
>>  
>> +/* Parse the device tree and build the logical map array containing
>> + * MPIDR values related to logical cpus
>> + * Code base on Linux arch/arm/kernel/devtree.c
>> + */
>> +static void __init init_cpus_maps(void)
>> +{
>> +    register_t mpidr;
>> +    struct dt_device_node *cpus = dt_find_node_by_path("/cpus");
>> +    struct dt_device_node *cpu;
>> +    unsigned int i, j;
>> +    unsigned int cpuidx = 1;
>> +    u32 tmp_map[NR_CPUS] = { [0 ... NR_CPUS - 1] = MPIDR_INVALID };
> 
> This is potentially a fair bit of data on the stack? If yes then it
> could be static init data?

Rigth. I will move to init data.

> 
>> +    bool_t bootcpu_valid = 0;
>> +
>> +    mpidr = READ_SYSREG(MPIDR_EL1) & MPIDR_HWID_MASK;
> 
> boot_cpu_mpidr would have saved me wondering why the current CPU was so
> special.

boot_cpu_mpidr is filled a bit after. I will move init_cpus_map later.

>> +
>> +    if ( !cpus )
>> +    {
>> +        printk(XENLOG_WARNING "WARNING: Can't find /cpus in the device tree.\n"
>> +               "Using only 1 CPU\n");
>> +        return;
>> +    }
>> +
>> +    for_each_child_node( cpus, cpu )
>> +    {
>> +        u32 hwid;
>> +
>> +        if ( !dt_device_type_is_equal(cpu, "cpu") )
>> +            continue;
>> +
>> +        if ( !dt_property_read_u32(cpu, "reg", &hwid) )
>> +        {
>> +            printk(XENLOG_WARNING "cpu node `%s`: missing reg property\n",
>> +                   dt_node_full_name(cpu));
>> +            continue;
>> +        }
>> +
>> +        /*
>> +         * 8 MSBs must be set to 0 in the DT since the reg property
>> +         * defines the MPIDR[23:0]
>> +         */
>> +        if ( hwid & ~MPIDR_HWID_MASK )
>> +        {
>> +            printk(XENLOG_WARNING "cpu node `%s`: invalid hwid value (0x%x)\n",
>> +                   dt_node_full_name(cpu), hwid);
>> +            continue;
>> +        }
>> +
>> +        /*
>> +         * Duplicate MPIDRs are a recipe for disaster. Scan all initialized
>> +         * entries and check for duplicates. If any found just skip the node.
>> +         * temp values values are initialized to MPIDR_INVALID to avoid
>> +         * matching valid MPIDR[23:0] values.
>> +         */
>> +        for ( j = 0; j < cpuidx; j++ )
>> +        {
>> +            if ( tmp_map[j] == hwid )
>> +            {
>> +                printk(XENLOG_WARNING "cpu node `%s`: duplicate /cpu reg properties in the DT\n",
>> +                       dt_node_full_name(cpu));
>> +                continue;
>> +            }
>> +        }
>> +
>> +        /*
>> +         * Build a stashed array of MPIDR values. Numbering scheme requires
>> +         * that if detected the boot CPU must be assigned logical id 0. Other
>> +         * CPUs get sequential indexes starting from 1. If a CPU node
>> +         * with a reg property matching the boot CPU MPIDR is detected,
>> +         * this is recorded and so that the logical map build from DT is
>> +         * validated and can be used to set the map.
>> +         */
>> +        if ( hwid == mpidr )
>> +        {
>> +            i = 0;
>> +            bootcpu_valid = 1;
>> +        }
>> +        else
>> +            i = cpuidx++;
>> +
>> +        if ( cpuidx > NR_CPUS )
>> +        {
>> +            printk(XENLOG_WARNING "DT /cpu %u node greater than max cores %u, capping them\n",
>> +                   cpuidx, NR_CPUS);
>> +            cpuidx = NR_CPUS;
>> +            break;
>> +        }
>> +
>> +        tmp_map[i] = hwid;
>> +    }
>> +
>> +    if ( !bootcpu_valid )
>> +    {
>> +        printk(XENLOG_WARNING "DT missing boot CPU MPIDR[23:0]\n"
>> +               "Using only 1 CPU\n");
>> +        return;
>> +    }
>> +
>> +    for ( i = 0; i < cpuidx; i++ )
>> +    {
>> +        cpumask_set_cpu(i, &cpu_possible_map);
>> +        cpu_logical_map(i) = tmp_map[i];
> 
> For i == 0 this happens in smp_clear_cpu_maps too. You may as well start
> from 1.

Ok.

>> +    }
>> +}
>> +
>>  /* C entry point for boot CPU */
>>  void __init start_xen(unsigned long boot_phys_offset,
>>                        unsigned long fdt_paddr,
>> @@ -515,7 +620,6 @@ void __init start_xen(unsigned long boot_phys_offset,
>>          + (fdt_paddr & ((1 << SECOND_SHIFT) - 1));
>>      fdt_size = device_tree_early_init(device_tree_flattened);
>>  
>> -    cpus = smp_get_max_cpus();
>>      cmdline_parse(device_tree_bootargs(device_tree_flattened));
>>  
>>      setup_pagetables(boot_phys_offset, get_xen_paddr());
>> @@ -528,6 +632,9 @@ void __init start_xen(unsigned long boot_phys_offset,
>>      dt_uart_init();
>>      console_init_preirq();
>>  
>> +    init_cpus_maps();
>> +    cpus = smp_get_max_cpus();
> 
> It seems like anything which was previously using this should by now be
> using some sort of for_each_foo() helper over the apropriate bitmasks?

Yes. I will send a patch for that.

>> +
>>      system_state = SYS_STATE_boot;
>>  
>>      processor_id();
>> diff --git a/xen/arch/arm/smpboot.c b/xen/arch/arm/smpboot.c
>> index b6aea63..c0d25de 100644
>> --- a/xen/arch/arm/smpboot.c
>> +++ b/xen/arch/arm/smpboot.c
>> @@ -39,6 +39,9 @@ EXPORT_SYMBOL(cpu_possible_map);
>>  
>>  struct cpuinfo_arm cpu_data[NR_CPUS];
>>  
>> +/* CPU logical map: map xen cpuid to an MPIDR */
>> +u32 __cpu_logical_map[NR_CPUS] = { [0 ... NR_CPUS-1] = MPIDR_INVALID };
>> +
>>  /* Fake one node for now. See also include/asm-arm/numa.h */
>>  nodemask_t __read_mostly node_online_map = { { [0] = 1UL } };
>>  
>> @@ -82,6 +85,7 @@ smp_clear_cpu_maps (void)
>>      cpumask_clear(&cpu_online_map);
>>      cpumask_set_cpu(0, &cpu_online_map);
>>      cpumask_set_cpu(0, &cpu_possible_map);
>> +    cpu_logical_map(0) = READ_SYSREG(MPIDR_EL1) & MPIDR_HWID_MASK;
>>  }
>>  
>>  int __init
>> diff --git a/xen/common/device_tree.c b/xen/common/device_tree.c
>> index 5620b23..cc519af 100644
>> --- a/xen/common/device_tree.c
>> +++ b/xen/common/device_tree.c
>> @@ -118,18 +118,6 @@ static bool_t __init device_tree_node_matches(const void *fdt, int node,
>>          && (name[match_len] == '@' || name[match_len] == '\0');
>>  }
>>  
>> -static bool_t __init device_tree_type_matches(const void *fdt, int node,
>> -                                       const char *match)
>> -{
>> -    const void *prop;
>> -
>> -    prop = fdt_getprop(fdt, node, "device_type", NULL);
>> -    if ( prop == NULL )
>> -        return 0;
>> -
>> -    return !dt_node_cmp(prop, match);
>> -}
>> -
>>  static bool_t __init device_tree_node_compatible(const void *fdt, int node,
>>                                                   const char *match)
>>  {
>> @@ -348,40 +336,6 @@ 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;
>> -    u32 cpuid;
>> -    int len;
>> -
>> -    prop = fdt_get_property(fdt, node, "reg", &len);
>> -    if ( !prop )
>> -    {
>> -        early_printk("fdt: node `%s': missing `reg' property\n", name);
>> -        return;
>> -    }
>> -
>> -    if ( len < sizeof (cpuid) )
>> -    {
>> -        dt_printk("fdt: node `%s': `reg` property length is too short\n",
>> -                  name);
>> -        return;
>> -    }
>> -
>> -    cpuid = dt_read_number((const __be32 *)prop->data, 1);
>> -
>> -    /* TODO: handle non-contiguous CPU ID */
>> -    if ( cpuid >= NR_CPUS )
>> -    {
>> -        dt_printk("fdt: node `%s': reg(0x%x) >= NR_CPUS(%d)\n",
>> -                  name, cpuid, NR_CPUS);
>> -        return;
>> -    }
>> -    cpumask_set_cpu(cpuid, &cpu_possible_map);
>> -}
>> -
>>  static void __init process_multiboot_node(const void *fdt, int node,
>>                                            const char *name,
>>                                            u32 address_cells, u32 size_cells)
>> @@ -435,8 +389,6 @@ 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);
>>      else if ( device_tree_node_compatible(fdt, node, "xen,multiboot-module" ) )
>>          process_multiboot_node(fdt, node, name, address_cells, size_cells);
>>  
>> diff --git a/xen/include/asm-arm/processor.h b/xen/include/asm-arm/processor.h
>> index b884354..5bc7259 100644
>> --- a/xen/include/asm-arm/processor.h
>> +++ b/xen/include/asm-arm/processor.h
>> @@ -13,6 +13,7 @@
>>  #define MPIDR_AFF0_SHIFT    (0)
>>  #define MPIDR_AFF0_MASK     (0xff << MPIDR_AFF0_SHIFT)
>>  #define MPIDR_HWID_MASK     0xffffff
>> +#define MPIDR_INVALID       (~MPIDR_HWID_MASK)
>>  
>>  /* TTBCR Translation Table Base Control Register */
>>  #define TTBCR_EAE    0x80000000
>> @@ -234,6 +235,9 @@ extern void identify_cpu(struct cpuinfo_arm *);
>>  extern struct cpuinfo_arm cpu_data[];
>>  #define current_cpu_data cpu_data[smp_processor_id()]
>>  
>> +extern u32 __cpu_logical_map[];
>> +#define cpu_logical_map(cpu) __cpu_logical_map[cpu]
>> +
>>  union hsr {
>>      uint32_t bits;
>>      struct {
> 
> 


-- 
Julien Grall

  reply	other threads:[~2013-09-10 16:18 UTC|newest]

Thread overview: 27+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2013-08-30 13:30 [PATCH 0/7] Dissociate logical and gic/hardware CPUD ID Julien Grall
2013-08-30 13:30 ` [PATCH 1/7] xen/arm: Introduce MPIDR_HWID_MASK Julien Grall
2013-09-09 13:09   ` Ian Campbell
2013-09-09 14:06     ` Ian Campbell
2013-08-30 13:30 ` [PATCH 2/7] xen/arm: use cpumask_t to describe cpu mask in gic_route_dt_irq Julien Grall
2013-09-09 13:14   ` Ian Campbell
2013-09-10 15:09     ` Julien Grall
2013-08-30 13:30 ` [PATCH 3/7] xen/arm: Initialize correctly IRQ routing Julien Grall
2013-09-09 13:17   ` Ian Campbell
2013-09-10 15:26     ` Julien Grall
2013-09-10 15:29     ` Julien Grall
2013-09-10 15:36       ` Ian Campbell
2013-08-30 13:30 ` [PATCH 4/7] xen/arm: gic: Use the correct CPU ID Julien Grall
2013-09-09 13:28   ` Ian Campbell
2013-09-10 15:42     ` Julien Grall
2013-09-10 15:52       ` Ian Campbell
2013-09-10 16:45         ` Julien Grall
2013-09-10 16:48           ` Ian Campbell
2013-08-30 13:30 ` [PATCH 5/7] xen/arm: Fix assert in send_SGI_one Julien Grall
2013-09-09 13:30   ` Ian Campbell
2013-09-10 15:47     ` Julien Grall
2013-08-30 13:30 ` [PATCH 6/7] xen/arm: Dissociate logical and hardware CPU ID Julien Grall
2013-09-09 13:38   ` Ian Campbell
2013-09-10 16:18     ` Julien Grall [this message]
2013-08-30 13:30 ` [PATCH 7/7] xen/arm: Use the hardware ID TMP boot correctly secondary cpus Julien Grall
2013-09-09 13:40   ` Ian Campbell
2013-09-10 16:24     ` Julien Grall

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=522F4638.3080807@linaro.org \
    --to=julien.grall@linaro.org \
    --cc=Ian.Campbell@citrix.com \
    --cc=patches@linaro.org \
    --cc=stefano.stabellini@eu.citrix.com \
    --cc=xen-devel@lists.xen.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).