smp.c (819a88263d5dbe398edd59cc1cf725ed1fdcfd79) smp.c (0f0783365cbb7ec13a8f02198f6e1a146d94a5a9)
1/*
2 * SMP initialisation and IPI support
3 * Based on arch/arm/kernel/smp.c
4 *
5 * Copyright (C) 2012 ARM Ltd.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
1/*
2 * SMP initialisation and IPI support
3 * Based on arch/arm/kernel/smp.c
4 *
5 * Copyright (C) 2012 ARM Ltd.
6 *
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
10 *
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
15 *
16 * You should have received a copy of the GNU General Public License
17 * along with this program. If not, see <http://www.gnu.org/licenses/>.
18 */
19
20#include <linux/acpi.h>
20#include <linux/delay.h>
21#include <linux/init.h>
22#include <linux/spinlock.h>
23#include <linux/sched.h>
24#include <linux/interrupt.h>
25#include <linux/cache.h>
26#include <linux/profile.h>
27#include <linux/errno.h>

--- 285 unchanged lines hidden (view full) ---

313 do_post_cpus_up_work();
314}
315
316void __init smp_prepare_boot_cpu(void)
317{
318 set_my_cpu_offset(per_cpu_offset(smp_processor_id()));
319}
320
21#include <linux/delay.h>
22#include <linux/init.h>
23#include <linux/spinlock.h>
24#include <linux/sched.h>
25#include <linux/interrupt.h>
26#include <linux/cache.h>
27#include <linux/profile.h>
28#include <linux/errno.h>

--- 285 unchanged lines hidden (view full) ---

314 do_post_cpus_up_work();
315}
316
317void __init smp_prepare_boot_cpu(void)
318{
319 set_my_cpu_offset(per_cpu_offset(smp_processor_id()));
320}
321
322static u64 __init of_get_cpu_mpidr(struct device_node *dn)
323{
324 const __be32 *cell;
325 u64 hwid;
326
327 /*
328 * A cpu node with missing "reg" property is
329 * considered invalid to build a cpu_logical_map
330 * entry.
331 */
332 cell = of_get_property(dn, "reg", NULL);
333 if (!cell) {
334 pr_err("%s: missing reg property\n", dn->full_name);
335 return INVALID_HWID;
336 }
337
338 hwid = of_read_number(cell, of_n_addr_cells(dn));
339 /*
340 * Non affinity bits must be set to 0 in the DT
341 */
342 if (hwid & ~MPIDR_HWID_BITMASK) {
343 pr_err("%s: invalid reg property\n", dn->full_name);
344 return INVALID_HWID;
345 }
346 return hwid;
347}
348
321/*
349/*
350 * Duplicate MPIDRs are a recipe for disaster. Scan all initialized
351 * entries and check for duplicates. If any is found just ignore the
352 * cpu. cpu_logical_map was initialized to INVALID_HWID to avoid
353 * matching valid MPIDR values.
354 */
355static bool __init is_mpidr_duplicate(unsigned int cpu, u64 hwid)
356{
357 unsigned int i;
358
359 for (i = 1; (i < cpu) && (i < NR_CPUS); i++)
360 if (cpu_logical_map(i) == hwid)
361 return true;
362 return false;
363}
364
365/*
322 * Initialize cpu operations for a logical cpu and
323 * set it in the possible mask on success
324 */
325static int __init smp_cpu_setup(int cpu)
326{
327 if (cpu_read_ops(cpu))
328 return -ENODEV;
329
330 if (cpu_ops[cpu]->cpu_init(cpu))
331 return -ENODEV;
332
333 set_cpu_possible(cpu, true);
334
335 return 0;
336}
337
366 * Initialize cpu operations for a logical cpu and
367 * set it in the possible mask on success
368 */
369static int __init smp_cpu_setup(int cpu)
370{
371 if (cpu_read_ops(cpu))
372 return -ENODEV;
373
374 if (cpu_ops[cpu]->cpu_init(cpu))
375 return -ENODEV;
376
377 set_cpu_possible(cpu, true);
378
379 return 0;
380}
381
382static bool bootcpu_valid __initdata;
383static unsigned int cpu_count = 1;
384
385#ifdef CONFIG_ACPI
338/*
386/*
387 * acpi_map_gic_cpu_interface - parse processor MADT entry
388 *
389 * Carry out sanity checks on MADT processor entry and initialize
390 * cpu_logical_map on success
391 */
392static void __init
393acpi_map_gic_cpu_interface(struct acpi_madt_generic_interrupt *processor)
394{
395 u64 hwid = processor->arm_mpidr;
396
397 if (hwid & ~MPIDR_HWID_BITMASK || hwid == INVALID_HWID) {
398 pr_err("skipping CPU entry with invalid MPIDR 0x%llx\n", hwid);
399 return;
400 }
401
402 if (!(processor->flags & ACPI_MADT_ENABLED)) {
403 pr_err("skipping disabled CPU entry with 0x%llx MPIDR\n", hwid);
404 return;
405 }
406
407 if (is_mpidr_duplicate(cpu_count, hwid)) {
408 pr_err("duplicate CPU MPIDR 0x%llx in MADT\n", hwid);
409 return;
410 }
411
412 /* Check if GICC structure of boot CPU is available in the MADT */
413 if (cpu_logical_map(0) == hwid) {
414 if (bootcpu_valid) {
415 pr_err("duplicate boot CPU MPIDR: 0x%llx in MADT\n",
416 hwid);
417 return;
418 }
419 bootcpu_valid = true;
420 return;
421 }
422
423 if (cpu_count >= NR_CPUS)
424 return;
425
426 /* map the logical cpu id to cpu MPIDR */
427 cpu_logical_map(cpu_count) = hwid;
428
429 cpu_count++;
430}
431
432static int __init
433acpi_parse_gic_cpu_interface(struct acpi_subtable_header *header,
434 const unsigned long end)
435{
436 struct acpi_madt_generic_interrupt *processor;
437
438 processor = (struct acpi_madt_generic_interrupt *)header;
439 if (BAD_MADT_ENTRY(processor, end))
440 return -EINVAL;
441
442 acpi_table_print_madt_entry(header);
443
444 acpi_map_gic_cpu_interface(processor);
445
446 return 0;
447}
448#else
449#define acpi_table_parse_madt(...) do { } while (0)
450#endif
451
452/*
339 * Enumerate the possible CPU set from the device tree and build the
340 * cpu logical map array containing MPIDR values related to logical
341 * cpus. Assumes that cpu_logical_map(0) has already been initialized.
342 */
453 * Enumerate the possible CPU set from the device tree and build the
454 * cpu logical map array containing MPIDR values related to logical
455 * cpus. Assumes that cpu_logical_map(0) has already been initialized.
456 */
343void __init of_smp_init_cpus(void)
457void __init of_parse_and_init_cpus(void)
344{
345 struct device_node *dn = NULL;
458{
459 struct device_node *dn = NULL;
346 unsigned int i, cpu = 1;
347 bool bootcpu_valid = false;
348
349 while ((dn = of_find_node_by_type(dn, "cpu"))) {
460
461 while ((dn = of_find_node_by_type(dn, "cpu"))) {
350 const u32 *cell;
351 u64 hwid;
462 u64 hwid = of_get_cpu_mpidr(dn);
352
463
353 /*
354 * A cpu node with missing "reg" property is
355 * considered invalid to build a cpu_logical_map
356 * entry.
357 */
358 cell = of_get_property(dn, "reg", NULL);
359 if (!cell) {
360 pr_err("%s: missing reg property\n", dn->full_name);
464 if (hwid == INVALID_HWID)
361 goto next;
465 goto next;
362 }
363 hwid = of_read_number(cell, of_n_addr_cells(dn));
364
466
365 /*
366 * Non affinity bits must be set to 0 in the DT
367 */
368 if (hwid & ~MPIDR_HWID_BITMASK) {
369 pr_err("%s: invalid reg property\n", dn->full_name);
467 if (is_mpidr_duplicate(cpu_count, hwid)) {
468 pr_err("%s: duplicate cpu reg properties in the DT\n",
469 dn->full_name);
370 goto next;
371 }
372
373 /*
470 goto next;
471 }
472
473 /*
374 * Duplicate MPIDRs are a recipe for disaster. Scan
375 * all initialized entries and check for
376 * duplicates. If any is found just ignore the cpu.
377 * cpu_logical_map was initialized to INVALID_HWID to
378 * avoid matching valid MPIDR values.
379 */
380 for (i = 1; (i < cpu) && (i < NR_CPUS); i++) {
381 if (cpu_logical_map(i) == hwid) {
382 pr_err("%s: duplicate cpu reg properties in the DT\n",
383 dn->full_name);
384 goto next;
385 }
386 }
387
388 /*
389 * The numbering scheme requires that the boot CPU
390 * must be assigned logical id 0. Record it so that
391 * the logical map built from DT is validated and can
392 * be used.
393 */
394 if (hwid == cpu_logical_map(0)) {
395 if (bootcpu_valid) {
396 pr_err("%s: duplicate boot cpu reg property in DT\n",

--- 7 unchanged lines hidden (view full) ---

404 * cpu_logical_map has already been
405 * initialized and the boot cpu doesn't need
406 * the enable-method so continue without
407 * incrementing cpu.
408 */
409 continue;
410 }
411
474 * The numbering scheme requires that the boot CPU
475 * must be assigned logical id 0. Record it so that
476 * the logical map built from DT is validated and can
477 * be used.
478 */
479 if (hwid == cpu_logical_map(0)) {
480 if (bootcpu_valid) {
481 pr_err("%s: duplicate boot cpu reg property in DT\n",

--- 7 unchanged lines hidden (view full) ---

489 * cpu_logical_map has already been
490 * initialized and the boot cpu doesn't need
491 * the enable-method so continue without
492 * incrementing cpu.
493 */
494 continue;
495 }
496
412 if (cpu >= NR_CPUS)
497 if (cpu_count >= NR_CPUS)
413 goto next;
414
415 pr_debug("cpu logical map 0x%llx\n", hwid);
498 goto next;
499
500 pr_debug("cpu logical map 0x%llx\n", hwid);
416 cpu_logical_map(cpu) = hwid;
501 cpu_logical_map(cpu_count) = hwid;
417next:
502next:
418 cpu++;
503 cpu_count++;
419 }
504 }
505}
420
506
421 /* sanity check */
422 if (cpu > NR_CPUS)
423 pr_warning("no. of cores (%d) greater than configured maximum of %d - clipping\n",
424 cpu, NR_CPUS);
507/*
508 * Enumerate the possible CPU set from the device tree or ACPI and build the
509 * cpu logical map array containing MPIDR values related to logical
510 * cpus. Assumes that cpu_logical_map(0) has already been initialized.
511 */
512void __init smp_init_cpus(void)
513{
514 int i;
425
515
516 if (acpi_disabled)
517 of_parse_and_init_cpus();
518 else
519 /*
520 * do a walk of MADT to determine how many CPUs
521 * we have including disabled CPUs, and get information
522 * we need for SMP init
523 */
524 acpi_table_parse_madt(ACPI_MADT_TYPE_GENERIC_INTERRUPT,
525 acpi_parse_gic_cpu_interface, 0);
526
527 if (cpu_count > NR_CPUS)
528 pr_warn("no. of cores (%d) greater than configured maximum of %d - clipping\n",
529 cpu_count, NR_CPUS);
530
426 if (!bootcpu_valid) {
531 if (!bootcpu_valid) {
427 pr_err("DT missing boot CPU MPIDR, not enabling secondaries\n");
532 pr_err("missing boot CPU MPIDR, not enabling secondaries\n");
428 return;
429 }
430
431 /*
432 * We need to set the cpu_logical_map entries before enabling
433 * the cpus so that cpu processor description entries (DT cpu nodes
434 * and ACPI MADT entries) can be retrieved by matching the cpu hwid
435 * with entries in cpu_logical_map while initializing the cpus.

--- 241 unchanged lines hidden ---
533 return;
534 }
535
536 /*
537 * We need to set the cpu_logical_map entries before enabling
538 * the cpus so that cpu processor description entries (DT cpu nodes
539 * and ACPI MADT entries) can be retrieved by matching the cpu hwid
540 * with entries in cpu_logical_map while initializing the cpus.

--- 241 unchanged lines hidden ---