aboutsummaryrefslogtreecommitdiffstats
path: root/arch/sparc64/kernel/mdesc.c
diff options
context:
space:
mode:
authorDavid S. Miller <davem@sunset.davemloft.net>2007-07-13 19:03:42 -0400
committerDavid S. Miller <davem@sunset.davemloft.net>2007-07-16 07:04:40 -0400
commit4f0234f4f9da485ecb9729af1b88567700fd4767 (patch)
tree7073115c86dbf4e691ddac12f5c9ce1c58ce53be /arch/sparc64/kernel/mdesc.c
parentb3e13fbeb9ac1eb8e7b0791bf56e1775c692972b (diff)
[SPARC64]: Initial LDOM cpu hotplug support.
Only adding cpus is supports at the moment, removal will come next. When new cpus are configured, the machine description is updated. When we get the configure request we pass in a cpu mask of to-be-added cpus to the mdesc CPU node parser so it only fetches information for those cpus. That code also proceeds to update the SMT/multi-core scheduling bitmaps. cpu_up() does all the work and we return the status back over the DS channel. CPUs via dr-cpu need to be booted straight out of the hypervisor, and this requires: 1) A new trampoline mechanism. CPUs are booted straight out of the hypervisor with MMU disabled and running in physical addresses with no mappings installed in the TLB. The new hvtramp.S code sets up the critical cpu state, installs the locked TLB mappings for the kernel, and turns the MMU on. It then proceeds to follow the logic of the existing trampoline.S SMP cpu bringup code. 2) All calls into OBP have to be disallowed when domaining is enabled. Since cpus boot straight into the kernel from the hypervisor, OBP has no state about that cpu and therefore cannot handle being invoked on that cpu. Luckily it's only a handful of interfaces which can be called after the OBP device tree is obtained. For example, rebooting, halting, powering-off, and setting options node variables. CPU removal support will require some infrastructure changes here. Namely we'll have to process the requests via a true kernel thread instead of in a workqueue. workqueues run on a per-cpu thread, but when unconfiguring we might need to force the thread to execute on another cpu if the current cpu is the one being removed. Removal of a cpu also causes the kernel to destroy that cpu's workqueue running thread. Another issue on removal is that we may have interrupts still pointing to the cpu-to-be-removed. So new code will be needed to walk the active INO list and retarget those cpus as-needed. Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/sparc64/kernel/mdesc.c')
-rw-r--r--arch/sparc64/kernel/mdesc.c53
1 files changed, 38 insertions, 15 deletions
diff --git a/arch/sparc64/kernel/mdesc.c b/arch/sparc64/kernel/mdesc.c
index 9e5088d563cc..3f79940a2939 100644
--- a/arch/sparc64/kernel/mdesc.c
+++ b/arch/sparc64/kernel/mdesc.c
@@ -434,6 +434,22 @@ static void __init report_platform_properties(void)
434 if (v) 434 if (v)
435 printk("PLATFORM: max-cpus [%lu]\n", *v); 435 printk("PLATFORM: max-cpus [%lu]\n", *v);
436 436
437#ifdef CONFIG_SMP
438 {
439 int max_cpu, i;
440
441 if (v) {
442 max_cpu = *v;
443 if (max_cpu > NR_CPUS)
444 max_cpu = NR_CPUS;
445 } else {
446 max_cpu = NR_CPUS;
447 }
448 for (i = 0; i < max_cpu; i++)
449 cpu_set(i, cpu_possible_map);
450 }
451#endif
452
437 mdesc_release(hp); 453 mdesc_release(hp);
438} 454}
439 455
@@ -451,9 +467,9 @@ static int inline find_in_proplist(const char *list, const char *match, int len)
451 return 0; 467 return 0;
452} 468}
453 469
454static void __init fill_in_one_cache(cpuinfo_sparc *c, 470static void __devinit fill_in_one_cache(cpuinfo_sparc *c,
455 struct mdesc_handle *hp, 471 struct mdesc_handle *hp,
456 u64 mp) 472 u64 mp)
457{ 473{
458 const u64 *level = mdesc_get_property(hp, mp, "level", NULL); 474 const u64 *level = mdesc_get_property(hp, mp, "level", NULL);
459 const u64 *size = mdesc_get_property(hp, mp, "size", NULL); 475 const u64 *size = mdesc_get_property(hp, mp, "size", NULL);
@@ -496,7 +512,8 @@ static void __init fill_in_one_cache(cpuinfo_sparc *c,
496 } 512 }
497} 513}
498 514
499static void __init mark_core_ids(struct mdesc_handle *hp, u64 mp, int core_id) 515static void __devinit mark_core_ids(struct mdesc_handle *hp, u64 mp,
516 int core_id)
500{ 517{
501 u64 a; 518 u64 a;
502 519
@@ -529,7 +546,7 @@ static void __init mark_core_ids(struct mdesc_handle *hp, u64 mp, int core_id)
529 } 546 }
530} 547}
531 548
532static void __init set_core_ids(struct mdesc_handle *hp) 549static void __devinit set_core_ids(struct mdesc_handle *hp)
533{ 550{
534 int idx; 551 int idx;
535 u64 mp; 552 u64 mp;
@@ -554,7 +571,8 @@ static void __init set_core_ids(struct mdesc_handle *hp)
554 } 571 }
555} 572}
556 573
557static void __init mark_proc_ids(struct mdesc_handle *hp, u64 mp, int proc_id) 574static void __devinit mark_proc_ids(struct mdesc_handle *hp, u64 mp,
575 int proc_id)
558{ 576{
559 u64 a; 577 u64 a;
560 578
@@ -573,8 +591,8 @@ static void __init mark_proc_ids(struct mdesc_handle *hp, u64 mp, int proc_id)
573 } 591 }
574} 592}
575 593
576static void __init __set_proc_ids(struct mdesc_handle *hp, 594static void __devinit __set_proc_ids(struct mdesc_handle *hp,
577 const char *exec_unit_name) 595 const char *exec_unit_name)
578{ 596{
579 int idx; 597 int idx;
580 u64 mp; 598 u64 mp;
@@ -595,13 +613,14 @@ static void __init __set_proc_ids(struct mdesc_handle *hp,
595 } 613 }
596} 614}
597 615
598static void __init set_proc_ids(struct mdesc_handle *hp) 616static void __devinit set_proc_ids(struct mdesc_handle *hp)
599{ 617{
600 __set_proc_ids(hp, "exec_unit"); 618 __set_proc_ids(hp, "exec_unit");
601 __set_proc_ids(hp, "exec-unit"); 619 __set_proc_ids(hp, "exec-unit");
602} 620}
603 621
604static void __init get_one_mondo_bits(const u64 *p, unsigned int *mask, unsigned char def) 622static void __devinit get_one_mondo_bits(const u64 *p, unsigned int *mask,
623 unsigned char def)
605{ 624{
606 u64 val; 625 u64 val;
607 626
@@ -619,8 +638,8 @@ use_default:
619 *mask = ((1U << def) * 64U) - 1U; 638 *mask = ((1U << def) * 64U) - 1U;
620} 639}
621 640
622static void __init get_mondo_data(struct mdesc_handle *hp, u64 mp, 641static void __devinit get_mondo_data(struct mdesc_handle *hp, u64 mp,
623 struct trap_per_cpu *tb) 642 struct trap_per_cpu *tb)
624{ 643{
625 const u64 *val; 644 const u64 *val;
626 645
@@ -637,7 +656,7 @@ static void __init get_mondo_data(struct mdesc_handle *hp, u64 mp,
637 get_one_mondo_bits(val, &tb->nonresum_qmask, 2); 656 get_one_mondo_bits(val, &tb->nonresum_qmask, 2);
638} 657}
639 658
640static void __init mdesc_fill_in_cpu_data(void) 659void __devinit mdesc_fill_in_cpu_data(cpumask_t mask)
641{ 660{
642 struct mdesc_handle *hp = mdesc_grab(); 661 struct mdesc_handle *hp = mdesc_grab();
643 u64 mp; 662 u64 mp;
@@ -658,6 +677,8 @@ static void __init mdesc_fill_in_cpu_data(void)
658#ifdef CONFIG_SMP 677#ifdef CONFIG_SMP
659 if (cpuid >= NR_CPUS) 678 if (cpuid >= NR_CPUS)
660 continue; 679 continue;
680 if (!cpu_isset(cpuid, mask))
681 continue;
661#else 682#else
662 /* On uniprocessor we only want the values for the 683 /* On uniprocessor we only want the values for the
663 * real physical cpu the kernel booted onto, however 684 * real physical cpu the kernel booted onto, however
@@ -696,7 +717,6 @@ static void __init mdesc_fill_in_cpu_data(void)
696 717
697#ifdef CONFIG_SMP 718#ifdef CONFIG_SMP
698 cpu_set(cpuid, cpu_present_map); 719 cpu_set(cpuid, cpu_present_map);
699 cpu_set(cpuid, phys_cpu_present_map);
700#endif 720#endif
701 721
702 c->core_id = 0; 722 c->core_id = 0;
@@ -719,6 +739,7 @@ void __init sun4v_mdesc_init(void)
719{ 739{
720 struct mdesc_handle *hp; 740 struct mdesc_handle *hp;
721 unsigned long len, real_len, status; 741 unsigned long len, real_len, status;
742 cpumask_t mask;
722 743
723 (void) sun4v_mach_desc(0UL, 0UL, &len); 744 (void) sun4v_mach_desc(0UL, 0UL, &len);
724 745
@@ -742,5 +763,7 @@ void __init sun4v_mdesc_init(void)
742 cur_mdesc = hp; 763 cur_mdesc = hp;
743 764
744 report_platform_properties(); 765 report_platform_properties();
745 mdesc_fill_in_cpu_data(); 766
767 cpus_setall(mask);
768 mdesc_fill_in_cpu_data(mask);
746} 769}