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 --- |