File: /usr/src/linux/arch/ia64/sn/io/ml_SN_init.c
1 /* $Id$
2 *
3 * This file is subject to the terms and conditions of the GNU General Public
4 * License. See the file "COPYING" in the main directory of this archive
5 * for more details.
6 *
7 * Copyright (C) 1992 - 1997, 2000 Silicon Graphics, Inc.
8 * Copyright (C) 2000 by Colin Ngam
9 */
10
11 #include <linux/types.h>
12 #include <linux/config.h>
13 #include <linux/slab.h>
14 #include <asm/sn/sgi.h>
15 #include <asm/sn/iograph.h>
16 #include <asm/sn/invent.h>
17 #include <asm/sn/hcl.h>
18 #include <asm/sn/labelcl.h>
19 #include <asm/sn/nodemask.h>
20 #include <asm/sn/sn_private.h>
21 #include <asm/sn/klconfig.h>
22 #include <asm/sn/sn_cpuid.h>
23 #include <asm/sn/synergy.h>
24
25
26 #if defined (CONFIG_SGI_IP35) || defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_GENERIC)
27 #include <asm/sn/sn1/ip27config.h>
28 #include <asm/sn/sn1/hubdev.h>
29 #include <asm/sn/sn1/sn1.h>
30 #endif /* CONFIG_SGI_IP35 || CONFIG_IA64_SGI_SN1 */
31
32
33 extern int numcpus;
34 extern char arg_maxnodes[];
35 extern cpuid_t master_procid;
36 extern void * kmem_alloc_node(register size_t, register int , cnodeid_t);
37 extern synergy_da_t *Synergy_da_indr[];
38
39 extern int hasmetarouter;
40
41 int maxcpus;
42 cpumask_t boot_cpumask;
43 hubreg_t region_mask = 0;
44
45
46 extern xwidgetnum_t hub_widget_id(nasid_t);
47
48 static int fine_mode = 0;
49
50 static cnodemask_t hub_init_mask; /* Mask of cpu in a node doing init */
51 static volatile cnodemask_t hub_init_done_mask;
52 /* Node mask where we wait for
53 * per hub initialization
54 */
55 spinlock_t hub_mask_lock; /* Lock for hub_init_mask above. */
56
57 extern int valid_icache_reasons; /* Reasons to flush the icache */
58 extern int valid_dcache_reasons; /* Reasons to flush the dcache */
59 extern int numnodes;
60 extern u_char miniroot;
61 extern volatile int need_utlbmiss_patch;
62 extern void iograph_early_init(void);
63
64 nasid_t master_nasid = INVALID_NASID;
65
66
67 /*
68 * mlreset(int slave)
69 * very early machine reset - at this point NO interrupts have been
70 * enabled; nor is memory, tlb, p0, etc setup.
71 *
72 * slave is zero when mlreset is called for the master processor and
73 * is nonzero thereafter.
74 */
75
76
77 void
78 mlreset(int slave)
79 {
80 if (!slave) {
81 /*
82 * We are the master cpu and node.
83 */
84 master_nasid = get_nasid();
85 set_master_bridge_base();
86 FIXME("mlreset: Enable when we support ioc3 ..");
87 #ifdef LATER
88 if (get_console_nasid() == master_nasid)
89 /* Set up the IOC3 */
90 ioc3_mlreset((ioc3_cfg_t *)KL_CONFIG_CH_CONS_INFO(master_nasid)->config_base,
91 (ioc3_mem_t *)KL_CONFIG_CH_CONS_INFO(master_nasid)->memory_base);
92
93 /*
94 * Initialize Master nvram base.
95 */
96 nvram_baseinit();
97
98 fine_mode = is_fine_dirmode();
99 #endif /* LATER */
100
101 /* We're the master processor */
102 master_procid = smp_processor_id();
103 master_nasid = cpuid_to_nasid(master_procid);
104
105 /*
106 * master_nasid we get back better be same as one from
107 * get_nasid()
108 */
109 ASSERT_ALWAYS(master_nasid == get_nasid());
110
111 #ifdef LATER
112
113 /*
114 * Activate when calias is implemented.
115 */
116 /* Set all nodes' calias sizes to 8k */
117 for (i = 0; i < maxnodes; i++) {
118 nasid_t nasid;
119 int sn;
120
121 nasid = COMPACT_TO_NASID_NODEID(i);
122
123 /*
124 * Always have node 0 in the region mask, otherwise CALIAS accesses
125 * get exceptions since the hub thinks it is a node 0 address.
126 */
127 for (sn=0; sn<NUM_SUBNODES; sn++) {
128 REMOTE_HUB_PI_S(nasid, sn, PI_REGION_PRESENT, (region_mask | 1));
129 REMOTE_HUB_PI_S(nasid, sn, PI_CALIAS_SIZE, PI_CALIAS_SIZE_8K);
130 }
131
132 /*
133 * Set up all hubs to havew a big window pointing at
134 * widget 0.
135 * Memory mode, widget 0, offset 0
136 */
137 REMOTE_HUB_S(nasid, IIO_ITTE(SWIN0_BIGWIN),
138 ((HUB_PIO_MAP_TO_MEM << IIO_ITTE_IOSP_SHIFT) |
139 (0 << IIO_ITTE_WIDGET_SHIFT)));
140 }
141 #endif /* LATER */
142
143 /* Set up the hub initialization mask and init the lock */
144 CNODEMASK_CLRALL(hub_init_mask);
145 CNODEMASK_CLRALL(hub_init_done_mask);
146
147 spin_lock_init(&hub_mask_lock);
148
149 /* early initialization of iograph */
150 iograph_early_init();
151
152 /* Initialize Hub Pseudodriver Management */
153 hubdev_init();
154
155 #ifdef LATER
156 /*
157 * Our IO system doesn't require cache writebacks. Set some
158 * variables appropriately.
159 */
160 cachewrback = 0;
161 valid_icache_reasons &= ~(CACH_AVOID_VCES | CACH_IO_COHERENCY);
162 valid_dcache_reasons &= ~(CACH_AVOID_VCES | CACH_IO_COHERENCY);
163
164 /*
165 * make sure we are running with the right rev of chips
166 */
167 verify_snchip_rev();
168
169 /*
170 * Since we've wiped out memory at this point, we
171 * need to reset the ARCS vector table so that it
172 * points to appropriate functions in the kernel
173 * itself. In this way, we can maintain the ARCS
174 * vector table conventions without having to actually
175 * keep redundant PROM code in memory.
176 */
177 he_arcs_set_vectors();
178 #endif /* LATER */
179
180 } else { /* slave != 0 */
181 /*
182 * This code is performed ONLY by slave processors.
183 */
184
185 }
186 }
187
188
189 /* XXX - Move the meat of this to intr.c ? */
190 /*
191 * Set up the platform-dependent fields in the nodepda.
192 */
193 void init_platform_nodepda(nodepda_t *npda, cnodeid_t node)
194 {
195 hubinfo_t hubinfo;
196 int sn;
197 cnodeid_t i;
198 ushort *numcpus_p;
199
200 extern void router_map_init(nodepda_t *);
201 extern void router_queue_init(nodepda_t *,cnodeid_t);
202 extern void intr_init_vecblk(nodepda_t *, cnodeid_t, int);
203
204 #if defined(DEBUG)
205 extern spinlock_t intr_dev_targ_map_lock;
206 extern uint64_t intr_dev_targ_map_size;
207
208 /* Initialize the lock to access the device - target cpu mapping
209 * table. This table is explicitly for debugging purposes only and
210 * to aid the "intrmap" idbg command
211 */
212 if (node == 0) {
213 /* Make sure we do this only once .
214 * There is always a cnode 0 present.
215 */
216 intr_dev_targ_map_size = 0;
217 spin_lock_init(&intr_dev_targ_map_lock);
218 }
219 #endif /* DEBUG */
220 /* Allocate per-node platform-dependent data */
221 hubinfo = (hubinfo_t)kmem_alloc_node(sizeof(struct hubinfo_s), GFP_ATOMIC, node);
222
223 ASSERT_ALWAYS(hubinfo);
224 npda->pdinfo = (void *)hubinfo;
225 hubinfo->h_nodepda = npda;
226 hubinfo->h_cnodeid = node;
227 hubinfo->h_nasid = COMPACT_TO_NASID_NODEID(node);
228
229 spin_lock_init(&hubinfo->h_crblock);
230
231 hubinfo->h_widgetid = hub_widget_id(hubinfo->h_nasid);
232 npda->xbow_peer = INVALID_NASID;
233 /* Initialize the linked list of
234 * router info pointers to the dependent routers
235 */
236 npda->npda_rip_first = NULL;
237 /* npda_rip_last always points to the place
238 * where the next element is to be inserted
239 * into the list
240 */
241 npda->npda_rip_last = &npda->npda_rip_first;
242 npda->dependent_routers = 0;
243 npda->module_id = INVALID_MODULE;
244
245 /*
246 * Initialize the subnodePDA.
247 */
248 for (sn=0; sn<NUM_SUBNODES; sn++) {
249 SNPDA(npda,sn)->prof_count = 0;
250 SNPDA(npda,sn)->next_prof_timeout = 0;
251 intr_init_vecblk(npda, node, sn);
252 }
253
254 npda->vector_unit_busy = 0;
255
256 spin_lock_init(&npda->vector_lock);
257 mutex_init_locked(&npda->xbow_sema); /* init it locked? */
258 spin_lock_init(&npda->fprom_lock);
259
260 spin_lock_init(&npda->node_utlbswitchlock);
261 npda->ni_error_print = 0;
262 #ifdef LATER
263 if (need_utlbmiss_patch) {
264 npda->node_need_utlbmiss_patch = 1;
265 npda->node_utlbmiss_patched = 1;
266 }
267 #endif
268
269 /*
270 * Clear out the nasid mask.
271 */
272 for (i = 0; i < NASID_MASK_BYTES; i++)
273 npda->nasid_mask[i] = 0;
274
275 for (i = 0; i < numnodes; i++) {
276 nasid_t nasid = COMPACT_TO_NASID_NODEID(i);
277
278 /* Set my mask bit */
279 npda->nasid_mask[nasid / 8] |= (1 << nasid % 8);
280 }
281
282 #ifdef LATER
283 npda->node_first_cpu = get_cnode_cpu(node);
284 #endif
285
286 if (npda->node_first_cpu != CPU_NONE) {
287 /*
288 * Count number of cpus only if first CPU is valid.
289 */
290 numcpus_p = &npda->node_num_cpus;
291 *numcpus_p = 0;
292 for (i = npda->node_first_cpu; i < MAXCPUS; i++) {
293 if (CPUID_TO_COMPACT_NODEID(i) != node)
294 break;
295 else
296 (*numcpus_p)++;
297 }
298 } else {
299 npda->node_num_cpus = 0;
300 }
301
302 /* Allocate memory for the dump stack on each node
303 * This is useful during nmi handling since we
304 * may not be guaranteed shared memory at that time
305 * which precludes depending on a global dump stack
306 */
307 #ifdef LATER
308 npda->dump_stack = (uint64_t *)kmem_zalloc_node(DUMP_STACK_SIZE,VM_NOSLEEP,
309 node);
310 ASSERT_ALWAYS(npda->dump_stack);
311 ASSERT(npda->dump_stack);
312 #endif
313 /* Initialize the counter which prevents
314 * both the cpus on a node to proceed with nmi
315 * handling.
316 */
317 #ifdef LATER
318 npda->dump_count = 0;
319
320 /* Setup the (module,slot) --> nic mapping for all the routers
321 * in the system. This is useful during error handling when
322 * there is no shared memory.
323 */
324 router_map_init(npda);
325
326 /* Allocate memory for the per-node router traversal queue */
327 router_queue_init(npda,node);
328 npda->sbe_info = kmem_zalloc_node_hint(sizeof (sbe_info_t), 0, node);
329 ASSERT(npda->sbe_info);
330
331 #ifdef CONFIG_SGI_IP35 || CONFIG_IA64_SGI_SN1 || CONFIG_IA64_GENERIC
332 /*
333 * Initialize bte info pointers to NULL
334 */
335 for (i = 0; i < BTES_PER_NODE; i++) {
336 npda->node_bte_info[i] = (bteinfo_t *)NULL;
337 }
338 #endif
339 #endif /* LATER */
340 }
341
342 /* XXX - Move the interrupt stuff to intr.c ? */
343 /*
344 * Set up the platform-dependent fields in the processor pda.
345 * Must be done _after_ init_platform_nodepda().
346 * If we need a lock here, something else is wrong!
347 */
348 // void init_platform_pda(pda_t *ppda, cpuid_t cpu)
349 void init_platform_pda(cpuid_t cpu)
350 {
351 hub_intmasks_t *intmasks;
352 #ifdef LATER
353 cpuinfo_t cpuinfo;
354 #endif
355 int i;
356 cnodeid_t cnode;
357 synergy_da_t *sda;
358 int which_synergy;
359
360 #ifdef LATER
361 /* Allocate per-cpu platform-dependent data */
362 cpuinfo = (cpuinfo_t)kmem_alloc_node(sizeof(struct cpuinfo_s), GFP_ATOMIC, cputocnode(cpu));
363 ASSERT_ALWAYS(cpuinfo);
364 ppda->pdinfo = (void *)cpuinfo;
365 cpuinfo->ci_cpupda = ppda;
366 cpuinfo->ci_cpuid = cpu;
367 #endif
368
369 cnode = cpuid_to_cnodeid(cpu);
370 which_synergy = cpuid_to_synergy(cpu);
371 sda = Synergy_da_indr[(cnode * 2) + which_synergy];
372 // intmasks = &ppda->p_intmasks;
373 intmasks = &sda->s_intmasks;
374
375 #ifdef LATER
376 ASSERT_ALWAYS(&ppda->p_nodepda);
377 #endif
378
379 /* Clear INT_PEND0 masks. */
380 for (i = 0; i < N_INTPEND0_MASKS; i++)
381 intmasks->intpend0_masks[i] = 0;
382
383 /* Set up pointer to the vector block in the nodepda. */
384 /* (Cant use SUBNODEPDA - not working yet) */
385 intmasks->dispatch0 = &Nodepdaindr[cnode]->snpda[cpuid_to_subnode(cpu)].intr_dispatch0;
386 intmasks->dispatch1 = &Nodepdaindr[cnode]->snpda[cpuid_to_subnode(cpu)].intr_dispatch1;
387
388 /* Clear INT_PEND1 masks. */
389 for (i = 0; i < N_INTPEND1_MASKS; i++)
390 intmasks->intpend1_masks[i] = 0;
391
392
393 #ifdef LATER
394 /* Don't read the routers unless we're the master. */
395 ppda->p_routertick = 0;
396 #endif
397
398 }
399
400 #if (defined(CONFIG_SGI_IP35) || defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_GENERIC)) && !defined(BRINGUP) /* protect low mem for IP35/7 */
401 #error "need protect_hub_calias, protect_nmi_handler_data"
402 #endif
403
404 #ifdef LATER
405 /*
406 * For now, just protect the first page (exception handlers). We
407 * may want to protect more stuff later.
408 */
409 void
410 protect_hub_calias(nasid_t nasid)
411 {
412 paddr_t pa = NODE_OFFSET(nasid) + 0; /* page 0 on node nasid */
413 int i;
414
415 for (i = 0; i < MAX_REGIONS; i++) {
416 if (i == nasid_to_region(nasid))
417 continue;
418 }
419 }
420
421 /*
422 * Protect the page of low memory used to communicate with the NMI handler.
423 */
424 void
425 protect_nmi_handler_data(nasid_t nasid, int slice)
426 {
427 paddr_t pa = NODE_OFFSET(nasid) + NMI_OFFSET(nasid, slice);
428 int i;
429
430 for (i = 0; i < MAX_REGIONS; i++) {
431 if (i == nasid_to_region(nasid))
432 continue;
433 }
434 }
435 #endif /* LATER */
436
437
438 #ifdef LATER
439 /*
440 * Protect areas of memory that we access uncached by marking them as
441 * poisoned so the T5 can't read them speculatively and erroneously
442 * mark them dirty in its cache only to write them back with old data
443 * later.
444 */
445 static void
446 protect_low_memory(nasid_t nasid)
447 {
448 /* Protect low memory directory */
449 poison_state_alter_range(KLDIR_ADDR(nasid), KLDIR_SIZE, 1);
450
451 /* Protect klconfig area */
452 poison_state_alter_range(KLCONFIG_ADDR(nasid), KLCONFIG_SIZE(nasid), 1);
453
454 /* Protect the PI error spool area. */
455 poison_state_alter_range(PI_ERROR_ADDR(nasid), PI_ERROR_SIZE(nasid), 1);
456
457 /* Protect CPU A's cache error eframe area. */
458 poison_state_alter_range(TO_NODE_UNCAC(nasid, CACHE_ERR_EFRAME),
459 CACHE_ERR_AREA_SIZE, 1);
460
461 /* Protect CPU B's area */
462 poison_state_alter_range(TO_NODE_UNCAC(nasid, CACHE_ERR_EFRAME)
463 ^ UALIAS_FLIP_BIT,
464 CACHE_ERR_AREA_SIZE, 1);
465 #error "SN1 not handled correctly"
466 }
467 #endif /* LATER */
468
469 /*
470 * per_hub_init
471 *
472 * This code is executed once for each Hub chip.
473 */
474 void
475 per_hub_init(cnodeid_t cnode)
476 {
477 uint64_t done;
478 nasid_t nasid;
479 nodepda_t *npdap;
480 #if defined(CONFIG_SGI_IP35) || defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_GENERIC) /* SN1 specific */
481 ii_icmr_u_t ii_icmr;
482 ii_ibcr_u_t ii_ibcr;
483 #endif
484 #ifdef LATER
485 int i;
486 #endif
487
488 nasid = COMPACT_TO_NASID_NODEID(cnode);
489
490 ASSERT(nasid != INVALID_NASID);
491 ASSERT(NASID_TO_COMPACT_NODEID(nasid) == cnode);
492
493 /* Grab the hub_mask lock. */
494 spin_lock(&hub_mask_lock);
495
496 /* Test our bit. */
497 if (!(done = CNODEMASK_TSTB(hub_init_mask, cnode))) {
498
499 /* Turn our bit on in the mask. */
500 CNODEMASK_SETB(hub_init_mask, cnode);
501 }
502
503 #if defined(SN0_HWDEBUG)
504 hub_config_setup();
505 #endif
506 /* Release the hub_mask lock. */
507 spin_unlock(&hub_mask_lock);
508
509 /*
510 * Do the actual initialization if it hasn't been done yet.
511 * We don't need to hold a lock for this work.
512 */
513 if (!done) {
514 npdap = NODEPDA(cnode);
515
516 #if defined(CONFIG_IA64_SGI_SYNERGY_PERF)
517 /* initialize per-node synergy perf instrumentation */
518 npdap->synergy_perf_enabled = 0; /* off by default */
519 npdap->synergy_perf_lock = SPIN_LOCK_UNLOCKED;
520 npdap->synergy_perf_freq = SYNERGY_PERF_FREQ_DEFAULT;
521 npdap->synergy_inactive_intervals = 0;
522 npdap->synergy_active_intervals = 0;
523 npdap->synergy_perf_data = NULL;
524 npdap->synergy_perf_first = NULL;
525 #endif /* CONFIG_IA64_SGI_SYNERGY_PERF */
526
527 npdap->hub_chip_rev = get_hub_chiprev(nasid);
528
529 #ifdef LATER
530 for (i = 0; i < CPUS_PER_NODE; i++) {
531 cpu = cnode_slice_to_cpuid(cnode, i);
532 if (!cpu_enabled(cpu))
533 SET_CPU_LEDS(nasid, i, 0xf);
534 }
535 #endif /* LATER */
536
537 #if defined(CONFIG_SGI_IP35) || defined(CONFIG_IA64_SGI_SN1) || defined(CONFIG_IA64_GENERIC) /* SN1 specific */
538
539 /*
540 * Set the total number of CRBs that can be used.
541 */
542 ii_icmr.ii_icmr_regval= 0x0;
543 ii_icmr.ii_icmr_fld_s.i_c_cnt = 0xF;
544 REMOTE_HUB_S(nasid, IIO_ICMR, ii_icmr.ii_icmr_regval);
545
546 /*
547 * Set the number of CRBs that both of the BTEs combined
548 * can use minus 1.
549 */
550 ii_ibcr.ii_ibcr_regval= 0x0;
551 ii_ibcr.ii_ibcr_fld_s.i_count = 0x8;
552 REMOTE_HUB_S(nasid, IIO_IBCR, ii_ibcr.ii_ibcr_regval);
553
554 /*
555 * Set CRB timeout to be 10ms.
556 */
557 REMOTE_HUB_S(nasid, IIO_ICTP, 0x1000 );
558 REMOTE_HUB_S(nasid, IIO_ICTO, 0xff);
559
560 #endif /* SN0_HWDEBUG */
561
562
563
564 /* Reserve all of the hardwired interrupt levels. */
565 intr_reserve_hardwired(cnode);
566
567 /* Initialize error interrupts for this hub. */
568 hub_error_init(cnode);
569
570 #ifdef LATER
571 /* Set up correctable memory/directory ECC error interrupt. */
572 install_eccintr(cnode);
573
574 /* Protect our exception vectors from accidental corruption. */
575 protect_hub_calias(nasid);
576
577 /* Enable RT clock interrupts */
578 hub_rtc_init(cnode);
579 hub_migrintr_init(cnode); /* Enable migration interrupt */
580 #endif /* LATER */
581
582 spin_lock(&hub_mask_lock);
583 CNODEMASK_SETB(hub_init_done_mask, cnode);
584 spin_unlock(&hub_mask_lock);
585
586 } else {
587 /*
588 * Wait for the other CPU to complete the initialization.
589 */
590 while (CNODEMASK_TSTB(hub_init_done_mask, cnode) == 0) {
591 /*
592 * On SNIA64 we should never get here ..
593 */
594 printk("WARNING: per_hub_init: Should NEVER get here!\n");
595 /* LOOP */
596 ;
597 }
598 }
599 }
600
601 extern void
602 update_node_information(cnodeid_t cnodeid)
603 {
604 nodepda_t *npda = NODEPDA(cnodeid);
605 nodepda_router_info_t *npda_rip;
606
607 /* Go through the list of router info
608 * structures and copy some frequently
609 * accessed info from the info hanging
610 * off the corresponding router vertices
611 */
612 npda_rip = npda->npda_rip_first;
613 while(npda_rip) {
614 if (npda_rip->router_infop) {
615 npda_rip->router_portmask =
616 npda_rip->router_infop->ri_portmask;
617 npda_rip->router_slot =
618 npda_rip->router_infop->ri_slotnum;
619 } else {
620 /* No router, no ports. */
621 npda_rip->router_portmask = 0;
622 }
623 npda_rip = npda_rip->router_next;
624 }
625 }
626
627 hubreg_t
628 get_region(cnodeid_t cnode)
629 {
630 if (fine_mode)
631 return COMPACT_TO_NASID_NODEID(cnode) >> NASID_TO_FINEREG_SHFT;
632 else
633 return COMPACT_TO_NASID_NODEID(cnode) >> NASID_TO_COARSEREG_SHFT;
634 }
635
636 hubreg_t
637 nasid_to_region(nasid_t nasid)
638 {
639 if (fine_mode)
640 return nasid >> NASID_TO_FINEREG_SHFT;
641 else
642 return nasid >> NASID_TO_COARSEREG_SHFT;
643 }
644
645