2 * This file is subject to the terms and conditions of the GNU General
3 * Public License. See the file "COPYING" in the main directory of this
4 * archive for more details.
6 * Copyright (C) 2000 - 2001 by Kanoj Sarcar (kanoj@sgi.com)
7 * Copyright (C) 2000 - 2001 by Silicon Graphics, Inc.
10 #include <linux/config.h>
11 #include <linux/kernel.h>
12 #include <linux/init.h>
13 #include <linux/sched.h>
14 #include <linux/mmzone.h> /* for numnodes */
17 #include <asm/pgalloc.h>
18 #include <asm/pgtable.h>
19 #include <asm/sn/types.h>
20 #include <asm/sn/sn0/addrs.h>
21 #include <asm/sn/sn0/hubni.h>
22 #include <asm/sn/sn0/hubio.h>
23 #include <asm/sn/klconfig.h>
24 #include <asm/sn/ioc3.h>
25 #include <asm/mipsregs.h>
26 #include <asm/sn/gda.h>
27 #include <asm/sn/intr.h>
28 #include <asm/current.h>
30 #include <asm/processor.h>
31 #include <asm/mmu_context.h>
32 #include <asm/thread_info.h>
33 #include <asm/sn/launch.h>
34 #include <asm/sn/sn_private.h>
35 #include <asm/sn/sn0/ip27.h>
36 #include <asm/sn/mapped_kernel.h>
37 #include <asm/sn/sn0/addrs.h>
38 #include <asm/sn/gda.h>
40 #define CPU_NONE (cpuid_t)-1
43 * The following should work till 64 nodes, ie 128p SN0s.
45 #define CNODEMASK_CLRALL(p) (p) = 0
46 #define CNODEMASK_TSTB(p, bit) ((p) & (1ULL << (bit)))
47 #define CNODEMASK_SETB(p, bit) ((p) |= 1ULL << (bit))
49 cpumask_t boot_cpumask;
53 static spinlock_t hub_mask_lock = SPIN_LOCK_UNLOCKED;
54 static cnodemask_t hub_init_mask;
55 static atomic_t numstarted = ATOMIC_INIT(1);
56 static int router_distance;
57 nasid_t master_nasid = INVALID_NASID;
59 cnodeid_t nasid_to_compact_node[MAX_NASIDS];
60 nasid_t compact_to_nasid_node[MAX_COMPACT_NODES];
61 cnodeid_t cpuid_to_compact_node[MAXCPUS];
62 char node_distances[MAX_COMPACT_NODES][MAX_COMPACT_NODES];
64 hubreg_t get_region(cnodeid_t cnode)
67 return COMPACT_TO_NASID_NODEID(cnode) >> NASID_TO_FINEREG_SHFT;
69 return COMPACT_TO_NASID_NODEID(cnode) >> NASID_TO_COARSEREG_SHFT;
72 static void gen_region_mask(hubreg_t *region_mask, int maxnodes)
77 for (cnode = 0; cnode < maxnodes; cnode++) {
78 (*region_mask) |= 1ULL << get_region(cnode);
82 int is_fine_dirmode(void)
84 return (((LOCAL_HUB_L(NI_STATUS_REV_ID) & NSRI_REGIONSIZE_MASK)
85 >> NSRI_REGIONSIZE_SHFT) & REGIONSIZE_FINE);
88 nasid_t get_actual_nasid(lboard_t *brd)
95 /* find out if we are a completely disabled brd. */
96 hub = (klhub_t *)find_first_component(brd, KLSTRUCT_HUB);
99 if (!(hub->hub_info.flags & KLINFO_ENABLE)) /* disabled node brd */
100 return hub->hub_info.physid;
102 return brd->brd_nasid;
105 /* Tweak this for maximum number of CPUs to activate */
106 static int max_cpus = NR_CPUS;
108 int do_cpumask(cnodeid_t cnode, nasid_t nasid, cpumask_t *boot_cpumask,
111 static int tot_cpus_found = 0;
117 brd = find_lboard((lboard_t *)KL_CONFIG_INFO(nasid), KLTYPE_IP27);
120 acpu = (klcpu_t *)find_first_component(brd, KLSTRUCT_CPU);
122 cpuid = acpu->cpu_info.virtid;
123 /* cnode is not valid for completely disabled brds */
124 if (get_actual_nasid(brd) == brd->brd_nasid)
125 cpuid_to_compact_node[cpuid] = cnode;
126 if (cpuid > *highest)
128 /* Only let it join in if it's marked enabled */
129 if ((acpu->cpu_info.flags & KLINFO_ENABLE) &&
130 (tot_cpus_found != max_cpus)) {
131 CPUMASK_SETB(*boot_cpumask, cpuid);
135 acpu = (klcpu_t *)find_component(brd, (klinfo_t *)acpu,
138 brd = KLCF_NEXT(brd);
140 brd = find_lboard(brd,KLTYPE_IP27);
148 cpuid_t cpu_node_probe(cpumask_t *boot_cpumask, int *numnodes)
150 int i, cpus = 0, highest = 0;
155 * Initialize the arrays to invalid nodeid (-1)
157 for (i = 0; i < MAX_COMPACT_NODES; i++)
158 compact_to_nasid_node[i] = INVALID_NASID;
159 for (i = 0; i < MAX_NASIDS; i++)
160 nasid_to_compact_node[i] = INVALID_CNODEID;
161 for (i = 0; i < MAXCPUS; i++)
162 cpuid_to_compact_node[i] = INVALID_CNODEID;
165 for (i = 0; i < MAX_COMPACT_NODES; i++) {
166 if ((nasid = gdap->g_nasidtable[i]) == INVALID_NASID) {
169 compact_to_nasid_node[i] = nasid;
170 nasid_to_compact_node[nasid] = i;
172 cpus += do_cpumask(i, nasid, boot_cpumask, &highest);
177 * Cpus are numbered in order of cnodes. Currently, disabled
178 * cpus are not numbered.
184 int cpu_enabled(cpuid_t cpu)
188 return CPUMASK_TSTB(boot_cpumask, cpu) != 0;
194 void init_topology_matrix(void);
195 void dump_topology(void);
198 master_nasid = get_nasid();
199 fine_mode = is_fine_dirmode();
202 * Probe for all CPUs - this creates the cpumask and
203 * sets up the mapping tables.
205 CPUMASK_CLRALL(boot_cpumask);
206 maxcpus = cpu_node_probe(&boot_cpumask, &numnodes);
207 printk("Discovered %d cpus on %d nodes\n", maxcpus, numnodes);
209 init_topology_matrix();
212 gen_region_mask(®ion_mask, numnodes);
213 CNODEMASK_CLRALL(hub_init_mask);
215 setup_replication_mask(numnodes);
218 * Set all nodes' calias sizes to 8k
220 for (i = 0; i < numnodes; i++) {
223 nasid = COMPACT_TO_NASID_NODEID(i);
226 * Always have node 0 in the region mask, otherwise
227 * CALIAS accesses get exceptions since the hub
228 * thinks it is a node 0 address.
230 REMOTE_HUB_S(nasid, PI_REGION_PRESENT, (region_mask | 1));
231 #ifdef CONFIG_REPLICATE_EXHANDLERS
232 REMOTE_HUB_S(nasid, PI_CALIAS_SIZE, PI_CALIAS_SIZE_8K);
234 REMOTE_HUB_S(nasid, PI_CALIAS_SIZE, PI_CALIAS_SIZE_0);
239 * Set up all hubs to have a big window pointing at
240 * widget 0. Memory mode, widget 0, offset 0
242 REMOTE_HUB_S(nasid, IIO_ITTE(SWIN0_BIGWIN),
243 ((HUB_PIO_MAP_TO_MEM << IIO_ITTE_IOSP_SHIFT) |
244 (0 << IIO_ITTE_WIDGET_SHIFT)));
250 void intr_clear_bits(nasid_t nasid, volatile hubreg_t *pend, int base_level,
253 volatile hubreg_t bits;
256 /* Check pending interrupts */
257 if ((bits = HUB_L(pend)) != 0)
258 for (i = 0; i < N_INTPEND_BITS; i++)
260 LOCAL_HUB_CLR_INTR(base_level + i);
263 void intr_clear_all(nasid_t nasid)
265 REMOTE_HUB_S(nasid, PI_INT_MASK0_A, 0);
266 REMOTE_HUB_S(nasid, PI_INT_MASK0_B, 0);
267 REMOTE_HUB_S(nasid, PI_INT_MASK1_A, 0);
268 REMOTE_HUB_S(nasid, PI_INT_MASK1_B, 0);
269 intr_clear_bits(nasid, REMOTE_HUB_ADDR(nasid, PI_INT_PEND0),
270 INT_PEND0_BASELVL, "INT_PEND0");
271 intr_clear_bits(nasid, REMOTE_HUB_ADDR(nasid, PI_INT_PEND1),
272 INT_PEND1_BASELVL, "INT_PEND1");
275 void sn_mp_setup(void)
282 for (cnode = 0; cnode < numnodes; cnode++) {
284 init_platform_nodepda();
286 intr_clear_all(COMPACT_TO_NASID_NODEID(cnode));
289 for (cpu = 0; cpu < maxcpus; cpu++) {
295 void per_hub_init(cnodeid_t cnode)
297 extern void pcibr_setup(cnodeid_t);
301 nasid = COMPACT_TO_NASID_NODEID(cnode);
303 spin_lock(&hub_mask_lock);
305 if (!(done = CNODEMASK_TSTB(hub_init_mask, cnode))) {
306 /* Turn our bit on in the mask. */
307 CNODEMASK_SETB(hub_init_mask, cnode);
309 * Do the actual initialization if it hasn't been done yet.
310 * We don't need to hold a lock for this work.
313 * Set CRB timeout at 5ms, (< PI timeout of 10ms)
315 REMOTE_HUB_S(nasid, IIO_ICTP, 0x800);
316 REMOTE_HUB_S(nasid, IIO_ICTO, 0xff);
319 #ifdef CONFIG_REPLICATE_EXHANDLERS
321 * If this is not a headless node initialization,
322 * copy over the caliased exception handlers.
324 if (get_compact_nodeid() == cnode) {
325 extern char except_vec0, except_vec1_r10k;
326 extern char except_vec2_generic, except_vec3_generic;
328 memcpy((void *)(KSEG0 + 0x100), &except_vec2_generic,
330 memcpy((void *)(KSEG0 + 0x180), &except_vec3_generic,
332 memcpy((void *)KSEG0, &except_vec0, 0x80);
333 memcpy((void *)KSEG0 + 0x080, &except_vec1_r10k, 0x80);
334 memcpy((void *)(KSEG0 + 0x100), (void *) KSEG0, 0x80);
335 memcpy((void *)(KSEG0 + 0x180), &except_vec3_generic,
341 spin_unlock(&hub_mask_lock);
345 * This is similar to hard_smp_processor_id().
347 cpuid_t getcpuid(void)
351 klcpu = nasid_slice_to_cpuinfo(get_nasid(),LOCAL_HUB_L(PI_CPU_NUM));
352 return klcpu->cpu_info.virtid;
355 void per_cpu_init(void)
357 extern void install_cpu_nmi_handler(int slice);
358 extern void load_mmu(void);
359 static int is_slave = 0;
360 int cpu = smp_processor_id();
361 cnodeid_t cnode = get_compact_nodeid();
363 TLBMISS_HANDLER_SETUP();
367 clear_c0_status(ST0_IM);
370 if (smp_processor_id()) /* master can't do this early, no kmalloc */
371 install_cpuintr(cpu);
372 /* Install our NMI handler if symmon hasn't installed one. */
373 install_cpu_nmi_handler(cputoslice(cpu));
375 install_tlbintr(cpu);
377 set_c0_status(SRB_DEV0 | SRB_DEV1);
379 clear_c0_status(ST0_BEV);
380 if (current_cpu_data.isa_level == MIPS_CPU_ISA_IV)
381 set_c0_status(ST0_XX);
382 set_c0_status(ST0_KX|ST0_SX|ST0_UX);
385 atomic_inc(&numstarted);
391 cnodeid_t get_compact_nodeid(void)
397 * Map the physical node id to a virtual node id (virtual node ids
400 return NASID_TO_COMPACT_NODEID(nasid);
406 * Takes as first input the PROM assigned cpu id, and the kernel
407 * assigned cpu id as the second.
409 static void alloc_cpupda(cpuid_t cpu, int cpunum)
414 node = get_cpu_cnode(cpu);
415 nasid = COMPACT_TO_NASID_NODEID(node);
417 cputonasid(cpunum) = nasid;
418 cputocnode(cpunum) = node;
419 cputoslice(cpunum) = get_cpu_slice(cpu);
420 cpu_data[cpunum].p_cpuid = cpu;
423 static struct task_struct * __init fork_by_hand(void)
427 * don't care about the eip and regs settings since
428 * we'll never reschedule the forked task.
430 return copy_process(CLONE_VM|CLONE_IDLETASK, 0, ®s, 0, NULL, NULL);
433 static int __init do_boot_cpu(int cpu, int num_cpus)
435 extern void smp_bootstrap(void);
436 cpuid_t mycpuid = getcpuid();
437 struct task_struct *idle;
439 if (cpu == mycpuid) {
440 alloc_cpupda(cpu, num_cpus);
444 /* Skip holes in CPU space */
445 if (!CPUMASK_TSTB(boot_cpumask, cpu))
449 * The following code is purely to make sure
450 * Linux can schedule processes on this slave.
452 idle = fork_by_hand();
454 panic("failed fork for CPU %d", cpu);
457 * We remove it from the pidhash and the runqueue
458 * once we got the process:
460 init_idle(idle, cpu);
462 alloc_cpupda(cpu, num_cpus);
464 unhash_process(idle);
467 * Launch a slave into smp_bootstrap(). It doesn't take an
468 * argument, and we set sp to the kernel stack of the newly
469 * created idle process, gp to the proc struct so that
470 * current_thread_info() will work.
472 LAUNCH_SLAVE(cputonasid(num_cpus),cputoslice(num_cpus),
473 (launch_proc_t)MAPPED_KERN_RW_TO_K0(smp_bootstrap),
474 0, (void *)((unsigned long)idle->thread_info +
475 KERNEL_STACK_SIZE - 32), (void *)idle);
478 * Now optimistically set the mapping arrays. We
479 * need to wait here, verify the cpu booted up, then
480 * fire up the next cpu.
482 __cpu_number_map[cpu] = num_cpus;
483 __cpu_logical_map[num_cpus] = cpu;
484 CPUMASK_SETB(cpu_online_map, cpu);
487 * Wait this cpu to start up and initialize its hub,
488 * and discover the io devices it will control.
490 * XXX: We really want to fire up launch all the CPUs
491 * at once. We have to preserve the order of the
492 * devices on the bridges first though.
494 while (atomic_read(&numstarted) != num_cpus);
499 void __init smp_boot_cpus(void)
505 init_new_context(current, &init_mm);
506 current_thread_info()->cpu = 0;
507 smp_tune_scheduling();
510 /* Master has already done per_cpu_init() */
511 install_cpuintr(smp_processor_id());
517 replicate_kernel_text(numnodes);
519 for (cpu = 0; cpu < maxcpus; cpu++) {
520 num_cpus += do_boot_cpu(cpu, num_cpus);
524 Wait logic goes here.
526 for (cnode = 0; cnode < numnodes; cnode++) {
528 if (cnodetocpu(cnode) == -1) {
529 printk("Initializing headless hub,cnode %d", cnode);
540 #else /* CONFIG_SMP */
541 void __init start_secondary(void)
543 /* XXX Why do we need this empty definition at all? */
545 #endif /* CONFIG_SMP */
548 #define rou_rflag rou_flags
550 void router_recurse(klrou_t *router_a, klrou_t *router_b, int depth)
556 if (router_a->rou_rflag == 1)
559 if (depth >= router_distance)
562 router_a->rou_rflag = 1;
564 for (port = 1; port <= MAX_ROUTER_PORTS; port++) {
565 if (router_a->rou_port[port].port_nasid == INVALID_NASID)
568 brd = (lboard_t *)NODE_OFFSET_TO_K0(
569 router_a->rou_port[port].port_nasid,
570 router_a->rou_port[port].port_offset);
572 if (brd->brd_type == KLTYPE_ROUTER) {
573 router = (klrou_t *)NODE_OFFSET_TO_K0(NASID_GET(brd), brd->brd_compts[0]);
574 if (router == router_b) {
575 if (depth < router_distance)
576 router_distance = depth;
579 router_recurse(router, router_b, depth + 1);
583 router_a->rou_rflag = 0;
586 int node_distance(nasid_t nasid_a, nasid_t nasid_b)
590 lboard_t *brd, *dest_brd;
592 klrou_t *router, *router_a = NULL, *router_b = NULL;
594 /* Figure out which routers nodes in question are connected to */
595 for (cnode = 0; cnode < numnodes; cnode++) {
596 nasid = COMPACT_TO_NASID_NODEID(cnode);
598 if (nasid == -1) continue;
600 brd = find_lboard_class((lboard_t *)KL_CONFIG_INFO(nasid),
607 if (brd->brd_flags & DUPLICATE_BOARD)
610 router = (klrou_t *)NODE_OFFSET_TO_K0(NASID_GET(brd), brd->brd_compts[0]);
611 router->rou_rflag = 0;
613 for (port = 1; port <= MAX_ROUTER_PORTS; port++) {
614 if (router->rou_port[port].port_nasid == INVALID_NASID)
617 dest_brd = (lboard_t *)NODE_OFFSET_TO_K0(
618 router->rou_port[port].port_nasid,
619 router->rou_port[port].port_offset);
621 if (dest_brd->brd_type == KLTYPE_IP27) {
622 if (dest_brd->brd_nasid == nasid_a)
624 if (dest_brd->brd_nasid == nasid_b)
629 } while ( (brd = find_lboard_class(KLCF_NEXT(brd), KLTYPE_ROUTER)) );
632 if (router_a == NULL) {
633 printk("node_distance: router_a NULL\n");
636 if (router_b == NULL) {
637 printk("node_distance: router_b NULL\n");
641 if (nasid_a == nasid_b)
644 if (router_a == router_b)
647 router_distance = 100;
648 router_recurse(router_a, router_b, 2);
650 return router_distance;
653 void init_topology_matrix(void)
655 nasid_t nasid, nasid2;
658 for (row = 0; row < MAX_COMPACT_NODES; row++)
659 for (col = 0; col < MAX_COMPACT_NODES; col++)
660 node_distances[row][col] = -1;
662 for (row = 0; row < numnodes; row++) {
663 nasid = COMPACT_TO_NASID_NODEID(row);
664 for (col = 0; col < numnodes; col++) {
665 nasid2 = COMPACT_TO_NASID_NODEID(col);
666 node_distances[row][col] = node_distance(nasid, nasid2);
671 void dump_topology(void)
675 lboard_t *brd, *dest_brd;
681 printk("************** Topology ********************\n");
684 for (col = 0; col < numnodes; col++)
685 printk("%02d ", col);
687 for (row = 0; row < numnodes; row++) {
688 printk("%02d ", row);
689 for (col = 0; col < numnodes; col++)
690 printk("%2d ", node_distances[row][col]);
694 for (cnode = 0; cnode < numnodes; cnode++) {
695 nasid = COMPACT_TO_NASID_NODEID(cnode);
697 if (nasid == -1) continue;
699 brd = find_lboard_class((lboard_t *)KL_CONFIG_INFO(nasid),
706 if (brd->brd_flags & DUPLICATE_BOARD)
708 printk("Router %d:", router_num);
711 router = (klrou_t *)NODE_OFFSET_TO_K0(NASID_GET(brd), brd->brd_compts[0]);
713 for (port = 1; port <= MAX_ROUTER_PORTS; port++) {
714 if (router->rou_port[port].port_nasid == INVALID_NASID)
717 dest_brd = (lboard_t *)NODE_OFFSET_TO_K0(
718 router->rou_port[port].port_nasid,
719 router->rou_port[port].port_offset);
721 if (dest_brd->brd_type == KLTYPE_IP27)
722 printk(" %d", dest_brd->brd_nasid);
723 if (dest_brd->brd_type == KLTYPE_ROUTER)
728 } while ( (brd = find_lboard_class(KLCF_NEXT(brd), KLTYPE_ROUTER)) );
733 #define brd_widgetnum brd_slot
734 #define NODE_OFFSET_TO_KLINFO(n,off) ((klinfo_t*) TO_NODE_CAC(n,off))
744 gdap = (gda_t *)GDA_ADDR(get_nasid());
745 if (gdap->g_magic != GDA_MAGIC) {
746 printk("dumpklcfg_cmd: Invalid GDA MAGIC\n");
750 for (cnode = 0; cnode < MAX_COMPACT_NODES; cnode ++) {
751 nasid = gdap->g_nasidtable[cnode];
753 if (nasid == INVALID_NASID)
756 printk("\nDumpping klconfig Nasid %d:\n", nasid);
758 lbptr = KL_CONFIG_INFO(nasid);
761 printk(" %s, Nasid %d, Module %d, widget 0x%x, partition %d, NIC 0x%x lboard 0x%lx",
762 "board name here", /* BOARD_NAME(lbptr->brd_type), */
763 lbptr->brd_nasid, lbptr->brd_module,
764 lbptr->brd_widgetnum,
765 lbptr->brd_partition,
766 (lbptr->brd_nic), lbptr);
767 if (lbptr->brd_flags & DUPLICATE_BOARD)
770 for (i = 0; i < lbptr->brd_numcompts; i++) {
772 kli = NODE_OFFSET_TO_KLINFO(NASID_GET(lbptr), lbptr->brd_compts[i]);
773 printk(" type %2d, flags 0x%04x, diagval %3d, physid %4d, virtid %2d: %s\n",
780 /* COMPONENT_NAME(kli->struct_type)); */
782 lbptr = KLCF_NEXT(lbptr);
787 /* Useful to print router maps also */
789 for (cnode = 0; cnode < MAX_COMPACT_NODES; cnode ++) {
793 nasid = gdap->g_nasidtable[cnode];
794 if (nasid == INVALID_NASID)
796 lbptr = KL_CONFIG_INFO(nasid);
800 lbptr = find_lboard_class(lbptr, KLCLASS_ROUTER);
803 if (!KL_CONFIG_DUPLICATE_BOARD(lbptr)) {
804 printk("%llx -> \n", lbptr->brd_nic);
805 kr = (klrou_t *)find_first_component(lbptr,
807 for (i = 1; i <= MAX_ROUTER_PORTS; i++) {
808 printk("[%d, %llx]; ",
809 kr->rou_port[i].port_nasid,
810 kr->rou_port[i].port_offset);
814 lbptr = KLCF_NEXT(lbptr);