|
[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index] Re: [Xen-devel] [PATCH 6/7] xen/arm: Dissociate logical and hardware CPU ID
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@xxxxxxxxxx>
> ---
> 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?
> + 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.
> +
> + 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.
> + }
> +}
> +
> /* 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?
> +
> 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 {
_______________________________________________
Xen-devel mailing list
Xen-devel@xxxxxxxxxxxxx
http://lists.xen.org/xen-devel
|
![]() |
Lists.xenproject.org is hosted with RackSpace, monitoring our |