1 /*
2 * CDDL HEADER START
3 *
4 * The contents of this file are subject to the terms of the
5 * Common Development and Distribution License (the "License").
6 * You may not use this file except in compliance with the License.
7 *
8 * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
9 * or http://www.opensolaris.org/os/licensing.
10 * See the License for the specific language governing permissions
11 * and limitations under the License.
12 *
13 * When distributing Covered Code, include this CDDL HEADER in each
14 * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
15 * If applicable, add the following below this CDDL HEADER, with the
16 * fields enclosed by brackets "[]" replaced with your own identifying
17 * information: Portions Copyright [yyyy] [name of copyright owner]
18 *
19 * CDDL HEADER END
20 */
21 /*
22 * Copyright 2009 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 #include <sys/types.h>
27 #include <sys/sysmacros.h>
28 #include <sys/open.h>
29 #include <sys/param.h>
30 #include <sys/vm_machparam.h>
31 #include <sys/machparam.h>
32 #include <sys/systm.h>
33 #include <sys/signal.h>
34 #include <sys/cred.h>
35 #include <sys/user.h>
36 #include <sys/proc.h>
37 #include <sys/vnode.h>
38 #include <sys/uio.h>
39 #include <sys/buf.h>
40 #include <sys/file.h>
41 #include <sys/kmem.h>
42 #include <sys/stat.h>
43 #include <sys/stream.h>
44 #include <sys/stropts.h>
45 #include <sys/strsubr.h>
46 #include <sys/poll.h>
47 #include <sys/debug.h>
48 #include <sys/conf.h>
49 #include <sys/ddi.h>
50 #include <sys/sunddi.h>
51 #include <sys/errno.h>
52 #include <sys/modctl.h>
53 #include <sys/x_call.h>
54 #include <sys/cpuvar.h>
55 #include <sys/machcpuvar.h>
56 #include <sys/machsystm.h>
57
58 #include <sys/pda.h>
59 #include <sys/starfire.h>
60 #include <sys/idn.h>
61 #include <sys/idn_xf.h>
62
63 kmutex_t idn_xf_mutex; /* to serialize hardware access */
64 /*
65 * This data structure is referenced during the cross-call
66 * update of the CICs. The semaphore is used for synchronization
67 * when waiting for completion of the respective operation.
68 * We want IDNCIC_TIMEOUT ticks for all the cpus to check-in
69 * before we bail out and fail the operation.
70 */
71 #define IDNCIC_TIMEOUT (30*hz)
72 #define IDNCIC_TIMECHK (hz/3)
73 #define IDNCIC_UNKNOWN 0
74 #define IDNCIC_OK 1 /* values for xf_errcic */
75 #define IDNCIC_ERR 2
76 #define IDNCIC_BUSY 3
77
78 #ifdef DEBUG
79 #define NCICREGS 3 /* smmask, smbar, smlar */
80 #define CICREG_SMMASK 0
81 #define CICREG_SMBAR 1
82 #define CICREG_SMLAR 2
83
84 #define RESET_CIC_HISTORY() \
85 (xf_cicboards = xf_cicbuses = 0, \
86 bzero(xf_cicregs, sizeof (xf_cicregs)))
87
88 #define UPDATE_CIC_HISTORY(reg, brd, bus, val) \
89 (BOARDSET_ADD(xf_cicboards, (brd)), \
90 BOARDSET_ADD(xf_cicbuses, (bus)), \
91 xf_cicregs[brd][bus][reg] = (val))
92
93 #define DUMP_CIC_HISTORY() \
94 { \
95 if (idn_debug & IDNDBG_XF) { \
96 int _bd, _bs; \
97 procname_t _proc = "dump_cic_history"; \
98 for (_bd = 0; _bd < MAX_BOARDS; _bd++) { \
99 if (!BOARD_IN_SET(xf_cicboards, _bd)) \
100 continue; \
101 for (_bs = 0; _bs < MAX_ABUSES; _bs++) { \
102 if (!BOARD_IN_SET(xf_cicbuses, _bs)) \
103 continue; \
104 printf("%s: (bd.bs = %d.%d) m/b/l = " \
105 "%x/%x/%x\n", _proc, _bd, _bs, \
106 xf_cicregs[_bd][_bs][CICREG_SMMASK], \
107 xf_cicregs[_bd][_bs][CICREG_SMBAR], \
108 xf_cicregs[_bd][_bs][CICREG_SMLAR]); \
109 } \
110 } \
111 DEBUG_DELAY(); \
112 } \
113 }
114
115 /*
116 * Globally updated during CIC reg updates. Everybody has
117 * a unique location, so no concern about updates stepping
118 * on each other.
119 */
120 static ushort_t xf_cicboards, xf_cicbuses;
121 static uint_t xf_cicregs[MAX_BOARDS][MAX_ABUSES][NCICREGS];
122 #else /* DEBUG */
123 #define RESET_CIC_HISTORY()
124 #define UPDATE_CIC_HISTORY(reg, brd, bus, val)
125 #define DUMP_CIC_HISTORY()
126 #endif /* DEBUG */
127
128 struct idnxf_cic_info { /* protected by idn_xf_mutex */
129 /* 0 */ short xf_abus_mask;
130 /* 2 */ boardset_t xf_boardset;
131 /* 4 */ uint_t xf_smbase;
132 /* 8 */ uint_t xf_smlimit;
133 /* c */ int xf_doadd;
134
135 /* 10 */ int xf_count; /* atomically updated */
136 /* 14 */ time_t xf_start_time;
137 /* 18 */ kcondvar_t xf_cv;
138 /* 1a */ short xf_errtimer;
139 /* 1c */ int xf_errcnt; /* atomically updated */
140
141 /* 20 */ uchar_t xf_errcic[MAX_BOARDS][MAX_ABUSES];
142
143 /* 60 */ kmutex_t xf_mutex;
144 }; /* sizeof = 0x68 = 104 (26X) */
145
146 static struct idnxf_cic_info idnxf_cic_info;
147 #ifdef DEBUG
148 static uint_t o_idn_debug;
149 #endif /* DEBUG */
150
151 int idn_check_cpu_per_board = 1;
152
153 static int pc_prep_cic_buffer(int cpuid, uint_t cicdata);
154 static int cic_write_sm_mask(int board, int bus, boardset_t sm_mask);
155 static int cic_write_sm_bar(int board, int bus, uint_t sm_bar);
156 static int cic_write_sm_lar(int board, int bus, uint_t sm_lar);
157 static int cic_get_smmask_bit(void);
158 static int pc_write_madr(pda_handle_t ph,
159 int lboard, int rboard, uint_t madr);
160 static boardset_t get_boardset(pda_handle_t ph, int *nboards);
161 static int verify_smregs(int brd, int bus, boardset_t smmask,
162 uint_t smbase, uint_t smlimit);
163 static void idnxf_shmem_wakeup(void *arg);
164 static void idnxf_shmem_update_one(uint64_t arg1, uint64_t arg2);
165 static int idnxf_shmem_update_all(pda_handle_t ph,
166 boardset_t boardset, uint_t smbase,
167 uint_t smlimit, int doadd);
168
169 #define PHYSIO_ST(paddr, val) (stphysio((paddr), (val)))
170 #define PHYSIO_LD(paddr) (ldphysio(paddr))
171 #define PHYSIO_STH(paddr, val) (sthphysio((paddr), (val)))
172 #define PHYSIO_LDH(paddr) (ldhphysio(paddr))
173
174 #ifdef DEBUG
175 #define DEBUG_DELAY() (drv_usecwait(5000)) /* 5 ms */
176 #else /* DEBUG */
177 #define DEBUG_DELAY()
178 #endif /* DEBUG */
179
180
181 /*
182 * ---------------------------------------------------------------------
183 */
184 boardset_t
cic_read_domain_mask(int board,int bus)185 cic_read_domain_mask(int board, int bus)
186 {
187 u_longlong_t csr_addr;
188 boardset_t domain_mask;
189 procname_t proc = "cic_read_domain_mask";
190
191 ASSERT(CPUID_TO_BOARDID(CPU->cpu_id) == board);
192
193 csr_addr = MAKE_CIC_CSR_PA(board, CSR_TYPE_CIC, CIC_DOMAIN_MASK_ADDR,
194 bus);
195 PR_XF("%s: (bd=%d, bs=%d) csr_addr = 0x%llx\n",
196 proc, board, bus, csr_addr);
197
198 domain_mask = (boardset_t)PHYSIO_LDH(csr_addr);
199
200 return (domain_mask);
201 }
202
203 boardset_t
cic_read_sm_mask(int board,int bus)204 cic_read_sm_mask(int board, int bus)
205 {
206 u_longlong_t csr_addr;
207 boardset_t sm_mask;
208 procname_t proc = "cic_read_sm_mask";
209
210 ASSERT(CPUID_TO_BOARDID(CPU->cpu_id) == board);
211
212 csr_addr = MAKE_CIC_CSR_PA(board, CSR_TYPE_CIC, CIC_SM_MASK_ADDR,
213 bus);
214 PR_XF("%s: (bd=%d, bs=%d) csr_addr = 0x%llx\n",
215 proc, board, bus, csr_addr);
216
217 sm_mask = (boardset_t)PHYSIO_LDH(csr_addr);
218
219 return (sm_mask);
220 }
221
222 static int
cic_write_sm_mask(int board,int bus,boardset_t sm_mask)223 cic_write_sm_mask(int board, int bus, boardset_t sm_mask)
224 {
225 u_longlong_t csr_addr;
226 int cnt;
227 procname_t proc = "cic_write_sm_mask";
228
229 ASSERT(CPUID_TO_BOARDID(CPU->cpu_id) == board);
230
231 sm_mask &= 0xffff;
232 /*
233 * Before we can write to the CIC, we need to set
234 * up the CIC write data buffer in the PC.
235 */
236 if (pc_prep_cic_buffer(CPU->cpu_id, (uint_t)sm_mask) < 0)
237 return (-1);
238
239 /*
240 * Now we can write to the CIC.
241 */
242 csr_addr = MAKE_CIC_CSR_PA(board, CSR_TYPE_CIC, CIC_SM_MASK_ADDR,
243 bus);
244 PR_XF("%s: (bd=%d, bs=%d) csr_addr = 0x%llx\n",
245 proc, board, bus, csr_addr);
246 PR_XF("%s: writing sm_mask = 0x%x\n",
247 proc, (ushort_t)sm_mask);
248
249 UPDATE_CIC_HISTORY(CICREG_SMMASK, board, bus, sm_mask);
250
251 PHYSIO_STH(csr_addr, (ushort_t)sm_mask);
252 /*
253 * Read back for verification.
254 */
255 for (cnt = 0; (PHYSIO_LDH(csr_addr) != sm_mask) && (cnt < 10); cnt++)
256 ;
257
258 return ((cnt == 10) ? -1 : 0);
259 }
260
261 uint_t
cic_read_sm_bar(int board,int bus)262 cic_read_sm_bar(int board, int bus)
263 {
264 u_longlong_t csr_addr;
265 uint_t sm_bar;
266 procname_t proc = "cic_read_sm_bar";
267
268 ASSERT(CPUID_TO_BOARDID(CPU->cpu_id) == board);
269
270 csr_addr = MAKE_CIC_CSR_PA(board, CSR_TYPE_CIC, CIC_SM_BAR_MSB_ADDR,
271 bus);
272 PR_XF("%s:MSB: (bd=%d, bs=%d) csr_addr = 0x%llx\n",
273 proc, board, bus, csr_addr);
274
275 sm_bar = (uint_t)PHYSIO_LDH(csr_addr);
276 sm_bar <<= 16;
277
278 csr_addr = MAKE_CIC_CSR_PA(board, CSR_TYPE_CIC, CIC_SM_BAR_LSB_ADDR,
279 bus);
280 PR_XF("%s:LSB: (bd=%d, bs=%d) csr_addr = 0x%llx\n",
281 proc, board, bus, csr_addr);
282
283 sm_bar |= (uint_t)PHYSIO_LDH(csr_addr);
284
285 return (sm_bar);
286 }
287
288 static int
cic_write_sm_bar(int board,int bus,uint_t sm_bar)289 cic_write_sm_bar(int board, int bus, uint_t sm_bar)
290 {
291 int cnt;
292 u_longlong_t csr_addr;
293 uint_t sm_bar_lsb, sm_bar_msb;
294 procname_t proc = "cic_write_sm_bar";
295
296 ASSERT(CPUID_TO_BOARDID(CPU->cpu_id) == board);
297
298 sm_bar_lsb = sm_bar & 0xffff;
299 sm_bar_msb = (sm_bar >> 16) & 0xffff;
300
301 /*
302 * Before we can write to the CIC, we need to set
303 * up the CIC write data buffer in the PC.
304 */
305 if (pc_prep_cic_buffer(CPU->cpu_id, sm_bar_msb) < 0)
306 return (-1);
307
308 csr_addr = MAKE_CIC_CSR_PA(board, CSR_TYPE_CIC, CIC_SM_BAR_MSB_ADDR,
309 bus);
310 PR_XF("%s:MSB: (bd=%d, bs=%d) csr_addr = 0x%llx\n",
311 proc, board, bus, csr_addr);
312 PR_XF("%s:MSB: sm_bar[31:16] = 0x%x\n",
313 proc, (ushort_t)sm_bar_msb);
314
315 UPDATE_CIC_HISTORY(CICREG_SMBAR, board, bus, sm_bar);
316
317 PHYSIO_STH(csr_addr, (ushort_t)sm_bar_msb);
318 for (cnt = 0;
319 ((uint_t)PHYSIO_LDH(csr_addr) != sm_bar_msb) && (cnt < 10);
320 cnt++)
321 ;
322 if (cnt == 10) {
323 cmn_err(CE_WARN,
324 "IDN: 500: failed to write sm_bar (msb) (0x%x)",
325 (uint_t)sm_bar_msb);
326 return (-1);
327 }
328
329 /*
330 * Now to LSB portion.
331 */
332 if (pc_prep_cic_buffer(CPU->cpu_id, sm_bar_lsb) < 0)
333 return (-1);
334
335 csr_addr = MAKE_CIC_CSR_PA(board, CSR_TYPE_CIC, CIC_SM_BAR_LSB_ADDR,
336 bus);
337 PR_XF("%s:LSB: (bd=%d, bs=%d) csr_addr = 0x%llx\n",
338 proc, board, bus, csr_addr);
339 PR_XF("%s:LSB: sm_bar[15:0] = 0x%x\n",
340 proc, (ushort_t)sm_bar_lsb);
341
342 PHYSIO_STH(csr_addr, (ushort_t)sm_bar_lsb);
343 for (cnt = 0;
344 ((uint_t)PHYSIO_LDH(csr_addr) != sm_bar_lsb) && (cnt < 10);
345 cnt++)
346 ;
347 if (cnt == 10) {
348 cmn_err(CE_WARN,
349 "IDN: 500: failed to write sm_bar (lsb) (0x%x)",
350 (uint_t)sm_bar_lsb);
351 return (-1);
352 }
353
354 return (0);
355 }
356
357 uint_t
cic_read_sm_lar(int board,int bus)358 cic_read_sm_lar(int board, int bus)
359 {
360 u_longlong_t csr_addr;
361 uint_t sm_lar;
362 procname_t proc = "cic_read_sm_lar";
363
364 ASSERT(CPUID_TO_BOARDID(CPU->cpu_id) == board);
365
366 csr_addr = MAKE_CIC_CSR_PA(board, CSR_TYPE_CIC, CIC_SM_LAR_MSB_ADDR,
367 bus);
368 PR_XF("%s:MSB: (bd=%d, bs=%d) csr_addr = 0x%llx\n",
369 proc, board, bus, csr_addr);
370
371 sm_lar = (uint_t)PHYSIO_LDH(csr_addr);
372 sm_lar <<= 16;
373
374 csr_addr = MAKE_CIC_CSR_PA(board, CSR_TYPE_CIC, CIC_SM_LAR_LSB_ADDR,
375 bus);
376 PR_XF("%s:LSB: (bd=%d, bs=%d) csr_addr = 0x%llx\n",
377 proc, board, bus, csr_addr);
378
379 sm_lar |= (uint_t)PHYSIO_LDH(csr_addr);
380
381 return (sm_lar);
382 }
383
384 static int
cic_write_sm_lar(int board,int bus,uint_t sm_lar)385 cic_write_sm_lar(int board, int bus, uint_t sm_lar)
386 {
387 int cnt;
388 u_longlong_t csr_addr;
389 uint_t sm_lar_lsb, sm_lar_msb;
390 procname_t proc = "cic_write_sm_lar";
391
392 ASSERT(CPUID_TO_BOARDID(CPU->cpu_id) == board);
393
394 sm_lar_lsb = sm_lar & 0xffff;
395 sm_lar_msb = (sm_lar >> 16) & 0xffff;
396
397 /*
398 * Before we can write to the CIC, we need to set
399 * up the CIC write data buffer in the PC.
400 */
401 if (pc_prep_cic_buffer(CPU->cpu_id, sm_lar_msb) < 0)
402 return (-1);
403
404 csr_addr = MAKE_CIC_CSR_PA(board, CSR_TYPE_CIC, CIC_SM_LAR_MSB_ADDR,
405 bus);
406 PR_XF("%s:MSB: (bd=%d, bs=%d) csr_addr = 0x%llx\n",
407 proc, board, bus, csr_addr);
408 PR_XF("%s:MSB: sm_lar[31:16] = 0x%x\n",
409 proc, (ushort_t)sm_lar_msb);
410
411 UPDATE_CIC_HISTORY(CICREG_SMLAR, board, bus, sm_lar);
412
413 PHYSIO_STH(csr_addr, (ushort_t)sm_lar_msb);
414 for (cnt = 0;
415 ((uint_t)PHYSIO_LDH(csr_addr) != sm_lar_msb) && (cnt < 10);
416 cnt++)
417 ;
418 if (cnt == 10) {
419 cmn_err(CE_WARN,
420 "IDN: 501: failed to write sm_lar (msb) (0x%x)",
421 (uint_t)sm_lar_msb);
422 return (-1);
423 }
424
425 /*
426 * Now to LSB portion.
427 */
428 if (pc_prep_cic_buffer(CPU->cpu_id, sm_lar_lsb) < 0)
429 return (-1);
430
431 csr_addr = MAKE_CIC_CSR_PA(board, CSR_TYPE_CIC, CIC_SM_LAR_LSB_ADDR,
432 bus);
433 PR_XF("%s:LSB: (bd=%d, bs=%d) csr_addr = 0x%llx\n",
434 proc, board, bus, csr_addr);
435 PR_XF("%s:LSB: sm_lar[15:0] = 0x%x\n",
436 proc, (ushort_t)sm_lar_lsb);
437
438 PHYSIO_STH(csr_addr, (ushort_t)sm_lar_lsb);
439 for (cnt = 0;
440 ((uint_t)PHYSIO_LDH(csr_addr) != sm_lar_lsb) && (cnt < 10);
441 cnt++)
442 ;
443 if (cnt == 10) {
444 cmn_err(CE_WARN,
445 "IDN: 501: failed to write sm_lar (lsb) (0x%x)",
446 (uint_t)sm_lar_lsb);
447 return (-1);
448 }
449
450 return (0);
451 }
452
453 static int
cic_get_smmask_bit(void)454 cic_get_smmask_bit(void)
455 {
456 u_longlong_t csr_addr;
457 int board;
458 uint_t config1;
459 procname_t proc = "cic_get_smmask_bit";
460
461 affinity_set(CPU_CURRENT);
462
463 board = CPUID_TO_BOARDID(CPU->cpu_id);
464 /*
465 * Now that I'm stuck on this cpu I can go look at this
466 * board's CIC registers.
467 */
468 csr_addr = MAKE_CIC_CSR_PA(board, CSR_TYPE_CIC, CIC_CONFIG1_ADDR, 0);
469 PR_XF("%s: (bd=%d) csr_addr = 0x%llx (via cpu %d)\n",
470 proc, board, csr_addr, (int)CPU->cpu_id);
471
472 config1 = (uint_t)PHYSIO_LDH(csr_addr);
473
474 config1 = CIC_CONFIG1_SMMASK_BIT(config1);
475
476 affinity_clear();
477
478 return (config1);
479 }
480
481 static int
pc_prep_cic_buffer(int cpuid,uint_t cicdata)482 pc_prep_cic_buffer(int cpuid, uint_t cicdata)
483 {
484 int rv;
485 int brd, port;
486 u_longlong_t csr_addr;
487 register int cnt;
488 procname_t proc = "pc_prep_cic_buffer";
489
490
491 ASSERT(CPU->cpu_id == cpuid);
492
493 port = cpuid % plat_max_cpu_units_per_board();
494 brd = CPUID_TO_BOARDID(cpuid);
495
496 csr_addr = STARFIRE_PC_CICBUF_ADDR(brd, port);
497
498 /*
499 * csr_addr now points to CIC write buffer which resides
500 * in PC register space.
501 */
502 PR_XF("%s: (cpu=%d) csr_addr = 0x%llx\n", proc, cpuid, csr_addr);
503
504 PHYSIO_ST(csr_addr, cicdata);
505
506 /*
507 * Now we need to read back the data to guarantee
508 * it got there. Part of the PC protocol.
509 */
510 for (cnt = 0; (PHYSIO_LD(csr_addr) != cicdata) && (cnt < 10);
511 cnt++)
512 ;
513
514 rv = 0;
515 if (cnt == 10) {
516 cmn_err(CE_WARN,
517 "IDN: 502: unable to store data (0x%x) to "
518 "CIC buffer (0x%llx)",
519 cicdata, csr_addr);
520 rv = -1;
521 } else if (cnt >= 1) {
522 PR_XF("%s: MULTIPLE READS (cpu=%d) cnt = %d\n",
523 proc, cpuid, cnt);
524 }
525
526 return (rv);
527 }
528
529 /*
530 * --------------------------------------------------
531 * Write the given MC address decoding register contents (madr) of
532 * the respective remote board (rboard) into all the PCs located on
533 * the local board (lboard).
534 * --------------------------------------------------
535 */
536 static int
pc_write_madr(pda_handle_t ph,int lboard,int rboard,uint_t madr)537 pc_write_madr(pda_handle_t ph, int lboard, int rboard, uint_t madr)
538 {
539 u_longlong_t pc_madr_addr;
540 register int p, ioc;
541 register ushort_t procset, iocset;
542 int rv = 0;
543 uint_t rd_madr;
544 board_desc_t *lbp;
545 procname_t proc = "pc_write_madr";
546
547 lbp = pda_get_board_info(ph, lboard);
548
549 ASSERT(lbp);
550 ASSERT((lbp->bda_board & BDAN_MASK) == BDAN_GOOD);
551
552 procset = lbp->bda_proc;
553 iocset = lbp->bda_ioc;
554
555 /*
556 * Update the PCs for the cpus.
557 */
558 for (p = 0; p < MAX_PROCMODS; procset >>= 4, p++) {
559 int i;
560
561 if (!((procset & BDAN_MASK) == BDAN_GOOD))
562 continue;
563
564 pc_madr_addr = (u_longlong_t)STARFIRE_PC_MADR_ADDR(lboard,
565 rboard, p);
566
567 /*
568 * On this first iteration of updating the PC
569 * we need to turn off the MADR VALID bit so that
570 * there's no accidental usage of the entry before
571 * all four bytes have been updated in the PC.
572 */
573 if (madr != 0) {
574 /*
575 * Need to clear valid bit on first
576 * go around.
577 */
578 madr &= ~STARFIRE_PC_MADR_VALIDBIT;
579 }
580 PR_XF("%s: write madr(0x%x) to pc_addr(0x%llx) "
581 "[lb=%d, rb=%d, cpu=%d]\n",
582 proc, madr, pc_madr_addr, lboard, rboard, p);
583 DEBUG_DELAY();
584
585 for (i = 0; i < 20; i++) {
586 PHYSIO_ST(pc_madr_addr, madr);
587 /*
588 * Read back for sanity check.
589 */
590 rd_madr = PHYSIO_LD(pc_madr_addr);
591 if (madr == rd_madr)
592 break;
593 }
594 if (i > 0) {
595 PR_XF("%s: WARNING: (1) lb=%d, rb=%d, "
596 "madr=0x%x (i=%d)\n",
597 proc, lboard, rboard, madr, i);
598 }
599 if (rd_madr != madr) {
600 cmn_err(CE_WARN,
601 "IDN: 503: (invalidate) failed to update "
602 "PC madr (expected 0x%x, actual 0x%x)",
603 madr, rd_madr);
604 rv++;
605 continue;
606 }
607 if (madr == 0) {
608 continue;
609 } else {
610 /*
611 * Turn the valid bit back on.
612 */
613 madr |= STARFIRE_PC_MADR_VALIDBIT;
614 }
615 PR_XF("%s: write madr(0x%x) to pc_addr(0x%llx) "
616 "[lb=%d, rb=%d, cpu=%d]\n",
617 proc, madr, pc_madr_addr, lboard, rboard, p);
618 DEBUG_DELAY();
619
620 for (i = 0; i < 20; i++) {
621 PHYSIO_ST(pc_madr_addr, madr);
622 /*
623 * Read back for sanity check.
624 */
625 rd_madr = PHYSIO_LD(pc_madr_addr);
626 if (madr == rd_madr)
627 break;
628 }
629 if (i > 0) {
630 PR_XF("%s: WARNING: (2) lb=%d, rb=%d, "
631 "madr=0x%x (i=%d)\n",
632 proc, lboard, rboard, madr, i);
633 }
634 if (rd_madr != madr) {
635 cmn_err(CE_WARN,
636 "IDN: 503: (validate) failed to update "
637 "PC madr (expected 0x%x, actual 0x%x)",
638 madr, rd_madr);
639 rv++;
640 }
641 }
642 /*
643 * Update the PCs for the iocs.
644 */
645 for (ioc = 0; ioc < MAX_IOCS; iocset >>= 4, ioc++) {
646 int i;
647
648 if (!((iocset & BDAN_MASK) == BDAN_GOOD))
649 continue;
650
651 pc_madr_addr = (u_longlong_t)STARFIRE_PC_MADR_ADDR(lboard,
652 rboard, ioc + 4);
653
654 if (madr != 0) {
655 /*
656 * Need to clear valid bit on first
657 * go around.
658 */
659 madr &= ~STARFIRE_PC_MADR_VALIDBIT;
660 }
661 PR_XF("%s: write madr(0x%x) to iopc_madr_addr(0x%llx) "
662 "[lb=%d, rb=%d, ioc=%d]\n",
663 proc, madr, pc_madr_addr, lboard, rboard, ioc);
664 DEBUG_DELAY();
665
666 for (i = 0; i < 20; i++) {
667 PHYSIO_ST(pc_madr_addr, madr);
668 /*
669 * Read back for sanity check.
670 */
671 rd_madr = PHYSIO_LD(pc_madr_addr);
672 if (madr == rd_madr)
673 break;
674 }
675 if (i > 0) {
676 PR_XF("%s: WARNING: (3) lb=%d, rb=%d, "
677 "madr=0x%x (i=%d)\n",
678 proc, lboard, rboard, madr, i);
679 }
680 if (rd_madr != madr) {
681 cmn_err(CE_WARN,
682 "IDN: 504: (invalidate) failed to update "
683 "IOPC madr (expected 0x%x, actual 0x%x)",
684 madr, rd_madr);
685 rv++;
686 continue;
687 }
688
689 if (madr == 0) {
690 continue;
691 } else {
692 /*
693 * Turn the valid bit back on.
694 */
695 madr |= STARFIRE_PC_MADR_VALIDBIT;
696 }
697
698 PR_XF("%s: write madr(0x%x) to iopc_madr_addr(0x%llx) "
699 "[lb=%d, rb=%d, ioc=%d]\n",
700 proc, madr, pc_madr_addr, lboard, rboard, ioc);
701 DEBUG_DELAY();
702
703 for (i = 0; i < 20; i++) {
704 PHYSIO_ST(pc_madr_addr, madr);
705 /*
706 * Read back for sanity check.
707 */
708 rd_madr = PHYSIO_LD(pc_madr_addr);
709 if (madr == rd_madr)
710 break;
711 }
712 if (i > 0) {
713 PR_XF("%s: WARNING: (4) lb=%d, rb=%d, "
714 "madr=0x%x (i=%d)\n",
715 proc, lboard, rboard, madr, i);
716 }
717 if (rd_madr != madr) {
718 cmn_err(CE_WARN,
719 "IDN: 504: (validate) failed to update "
720 "IOPC madr (expected 0x%x, actual 0x%x)",
721 madr, rd_madr);
722 rv++;
723 }
724 }
725
726 return (rv ? -1 : 0);
727 }
728
729 /*
730 * --------------------------------------------------
731 * Read the array of MC address decoding registers from one of the
732 * PCs on the local board (lboard) into the given in array (mc_adr).
733 * --------------------------------------------------
734 */
735 void
pc_read_madr(pda_handle_t ph,int lboard,uint_t mc_adr[],int local_only)736 pc_read_madr(pda_handle_t ph, int lboard, uint_t mc_adr[], int local_only)
737 {
738 u_longlong_t pc_madr_addr;
739 register int p, ioc;
740 register ushort_t procset, iocset;
741 int brd;
742 board_desc_t *lbp;
743
744 lbp = pda_get_board_info(ph, lboard);
745
746 ASSERT(lbp);
747 ASSERT((lbp->bda_board & BDAN_MASK) == BDAN_GOOD);
748
749 procset = lbp->bda_proc;
750 iocset = lbp->bda_ioc;
751
752 for (p = 0; p < MAX_PROCMODS; procset >>= 4, p++)
753 if ((procset & BDAN_MASK) == BDAN_GOOD)
754 break;
755
756 if (p == MAX_PROCMODS) {
757 /*
758 * Couldn't find a PC off a cpu, let's check the
759 * IOCs.
760 */
761 for (ioc = 0; ioc < MAX_IOCS; iocset >>= 4, ioc++)
762 if ((iocset & BDAN_MASK) == BDAN_GOOD)
763 break;
764 if (ioc == MAX_IOCS) {
765 cmn_err(CE_WARN,
766 "IDN: 505: board %d missing any valid PCs",
767 lboard);
768 return;
769 }
770 p = ioc + 4;
771 }
772
773 pc_madr_addr = (u_longlong_t)STARFIRE_PC_MADR_ADDR(lboard, 0, p);
774 /*
775 * pc_madr_addr = Starts at entry for board 0.
776 */
777 for (brd = 0; brd < MAX_BOARDS; brd++) {
778 /*
779 * It's possible our local PC may have old entries to
780 * AWOL domains. Only want to pay attention to PC
781 * entries corresponding to our boards.
782 */
783 lbp = pda_get_board_info(ph, brd);
784 if (!local_only || ((lbp->bda_board & BDAN_MASK) == BDAN_GOOD))
785 mc_adr[brd] = PHYSIO_LD(pc_madr_addr);
786 else
787 mc_adr[brd] = 0;
788
789 pc_madr_addr += ((u_longlong_t)1 <<
790 STARFIRE_PC_MADR_BOARD_SHIFT);
791 }
792 }
793
794 /*
795 * --------------------------------------------------
796 * Read the MC address decoding register contents for all
797 * possible boards and store the results in their respective
798 * slot in mc_adr. Keep a count of non-zero MC ADRs and
799 * return that.
800 * --------------------------------------------------
801 */
802 void
mc_get_adr_all(pda_handle_t ph,uint_t mc_adr[],int * nmcadr)803 mc_get_adr_all(pda_handle_t ph, uint_t mc_adr[], int *nmcadr)
804 {
805 int brd;
806 uint_t madr[MAX_BOARDS];
807
808 /*
809 * Note that each PC has a complete copy of all MC contents
810 * and so all we have to do is read one PC rather than
811 * each of the MCs in the system.
812 */
813 brd = CPUID_TO_BOARDID(CPU->cpu_id);
814 pc_read_madr(ph, brd, madr, 1);
815
816 *nmcadr = 0;
817 for (brd = 0; brd < MAX_BOARDS; brd++)
818 if ((mc_adr[brd] = madr[brd]) != 0)
819 (*nmcadr)++;
820 }
821
822 static boardset_t
get_boardset(pda_handle_t ph,int * nboards)823 get_boardset(pda_handle_t ph, int *nboards)
824 {
825 int brd;
826 int nbrds = 0;
827 boardset_t bmask;
828
829 if (nboards != NULL)
830 *nboards = 0;
831
832 bmask = 0;
833 for (brd = 0; brd < MAX_BOARDS; brd++) {
834 if (pda_board_present(ph, brd)) {
835 bmask |= 1 << brd;
836 nbrds++;
837 }
838 }
839 if (nboards != NULL)
840 *nboards = (short)nbrds;
841
842 return (bmask);
843 }
844
845 int
update_local_hw_config(idn_domain_t * ldp,struct hwconfig * loc_hw)846 update_local_hw_config(idn_domain_t *ldp, struct hwconfig *loc_hw)
847 {
848 procname_t proc = "update_local_hw_config";
849
850 ASSERT(IDN_DLOCK_IS_EXCL(ldp->domid));
851 ASSERT(IDN_GLOCK_IS_EXCL());
852 ASSERT(ldp == &idn_domain[idn.localid]);
853
854 if (ldp->dhw.dh_boardset != loc_hw->dh_boardset) {
855 int c;
856
857 PR_PROTO("%s: NEW HW CONFIG (old_bset = 0x%x, "
858 "new_bset = 0x%x)\n",
859 proc, ldp->dhw.dh_boardset, loc_hw->dh_boardset);
860
861 PR_PROTO("%s: clearing boardset 0x%x\n", proc,
862 ldp->dhw.dh_boardset & ~loc_hw->dh_boardset);
863 PR_PROTO("%s: setting boardset 0x%x\n", proc,
864 loc_hw->dh_boardset & ~ldp->dhw.dh_boardset);
865
866 idn.dc_boardset &= ~ldp->dhw.dh_boardset;
867 idn.dc_boardset |= loc_hw->dh_boardset;
868 for (c = 0; c < NCPU; c++) {
869 if (CPU_IN_SET(ldp->dcpuset, c)) {
870 CPUSET_DEL(idn.dc_cpuset, c);
871 }
872 }
873 CPUSET_OR(idn.dc_cpuset, cpu_ready_set);
874
875 bcopy(loc_hw, &ldp->dhw, sizeof (ldp->dhw));
876 ldp->dcpuset = cpu_ready_set;
877 ldp->dcpu = cpu0.cpu_id;
878 ldp->dncpus = (int)ncpus;
879 ldp->dvote.v.nmembrds = ldp->dhw.dh_nmcadr - 1;
880 ldp->dvote.v.ncpus = (int)ldp->dncpus - 1;
881 ldp->dvote.v.board = CPUID_TO_BOARDID(CPU->cpu_id);
882
883 return (1);
884 } else {
885 PR_PROTO("%s: NO change detected\n", proc);
886 return (0);
887 }
888 }
889
890 int
get_hw_config(struct hwconfig * loc_hw)891 get_hw_config(struct hwconfig *loc_hw)
892 {
893 pda_handle_t ph;
894 boardset_t domainset;
895 int bd;
896 int nmcadr;
897 int nboards;
898 procname_t proc = "get_hw_config";
899
900 ASSERT(loc_hw != NULL);
901
902 bzero(loc_hw, sizeof (*loc_hw));
903 /*
904 * See if sm_mask is writable.
905 * XXX - Should be the same for all CIC's. Do we
906 * we need to verify?
907 */
908 if (cic_get_smmask_bit() == 0) {
909 /*
910 * If smmask is not writable, we can not allow
911 * IDN operations.
912 */
913 cmn_err(CE_WARN,
914 "IDN: 506: cic sm_mask is not writeable");
915 return (-1);
916 }
917 /*
918 * Map in the post2obp structure so we can find
919 * valid boards and hardware asics.
920 */
921 ph = pda_open();
922 if (ph == (pda_handle_t)NULL) {
923 cmn_err(CE_WARN,
924 "IDN: 507: failed to map-in post2obp structure");
925 return (-1);
926 } else if (!pda_is_valid(ph)) {
927 cmn_err(CE_WARN, "IDN: 508: post2obp checksum invalid");
928 pda_close(ph);
929 return (-1);
930 }
931 /*
932 * Need to read the MC address decoding registers
933 * so that they can be given to other domains.
934 */
935 loc_hw->dh_boardset = get_boardset(ph, &nboards);
936 loc_hw->dh_nboards = (short)nboards;
937 ASSERT(loc_hw->dh_boardset & (1 << CPUID_TO_BOARDID(CPU->cpu_id)));
938
939 mc_get_adr_all(ph, loc_hw->dh_mcadr, &nmcadr);
940 loc_hw->dh_nmcadr = (short)nmcadr;
941
942 affinity_set(CPU_CURRENT);
943 /*
944 * There will always be a bus 0 (logical).
945 */
946 bd = CPUID_TO_BOARDID(CPU->cpu_id);
947 domainset = (boardset_t)cic_read_domain_mask(bd, 0);
948 affinity_clear();
949
950 if (!idn_cpu_per_board(ph, cpu_ready_set, loc_hw)) {
951 pda_close(ph);
952 return (-1);
953 }
954
955 pda_close(ph);
956
957
958 #ifdef DEBUG
959 {
960 int brd;
961
962 for (brd = 0; brd < MAX_BOARDS; brd++)
963 if (loc_hw->dh_mcadr[brd] != 0) {
964 PR_XF("%s: brd %d, mc = 0x%x\n",
965 proc, brd, loc_hw->dh_mcadr[brd]);
966 }
967 }
968 #endif /* DEBUG */
969
970 if ((loc_hw->dh_boardset != domainset) || (loc_hw->dh_nmcadr < 1))
971 return (-1);
972 else
973 return (0);
974 }
975
976 /*
977 * Function called via timeout() to wakeup a possibly stuck
978 * idnxf_shmem_update_all() should not all cpus check-in after a
979 * x-call to update their respective CICs.
980 */
981 /*ARGSUSED0*/
982 static void
idnxf_shmem_wakeup(void * arg)983 idnxf_shmem_wakeup(void *arg)
984 {
985 struct idnxf_cic_info *idnxfp = (struct idnxf_cic_info *)arg;
986 int count;
987 int expired;
988 procname_t proc = "idnxf_shmem_wakeup";
989
990 expired = ((ddi_get_lbolt() - idnxfp->xf_start_time) >=
991 IDNCIC_TIMEOUT) ? 1 : 0;
992
993 if ((count = idnxfp->xf_count) == 0) {
994 /*
995 * Everybody has finished. Wakeup the requester.
996 */
997 mutex_enter(&idnxfp->xf_mutex);
998 cv_signal(&idnxfp->xf_cv);
999 mutex_exit(&idnxfp->xf_mutex);
1000
1001 } else if ((count > 0) && expired) {
1002 /*
1003 * There are still active cic updaters and time
1004 * has expired. Bail on them.
1005 */
1006 idnxfp->xf_errtimer = 1;
1007 #ifdef DEBUG
1008 /*
1009 * Special debug case since idn_debug
1010 * may have been temporarily cleared
1011 * during xc_some.
1012 */
1013 if ((idn_debug | o_idn_debug) & IDNDBG_REGS)
1014 printf("%s: TIMEOUT...bailing on %d lost CIC "
1015 "updates...\n", proc, count);
1016 #endif /* DEBUG */
1017
1018 ATOMIC_SUB(idnxfp->xf_count, count);
1019
1020 mutex_enter(&idnxfp->xf_mutex);
1021 cv_signal(&idnxfp->xf_cv);
1022 mutex_exit(&idnxfp->xf_mutex);
1023
1024 } else {
1025 (void) timeout(idnxf_shmem_wakeup, (caddr_t)idnxfp,
1026 (clock_t)IDNCIC_TIMECHK);
1027 }
1028 }
1029
1030 /*
1031 * Called indirectly from idnxf_shmem_update_all() via a xcall
1032 * for the recepient cpu to update the CICs on its respective
1033 * board.
1034 * IMPORTANT: NO console output from this routine!!
1035 */
1036 static void
idnxf_shmem_update_one(uint64_t arg1,uint64_t arg2)1037 idnxf_shmem_update_one(uint64_t arg1, uint64_t arg2)
1038 {
1039 struct idnxf_cic_info *idnxfp = (struct idnxf_cic_info *)arg1;
1040 time_t start_time = (time_t)arg2;
1041 int rv, cpuid, brd, bus;
1042 boardset_t smmask;
1043
1044
1045 cpuid = CPU->cpu_id;
1046 brd = CPUID_TO_BOARDID(cpuid);
1047
1048 if (idnxfp->xf_start_time != start_time) {
1049 /*
1050 * Ooops! Not my place to intrude.
1051 */
1052 idnxf_cic_info.xf_errcic[brd][0] = IDNCIC_BUSY;
1053 ATOMIC_INC(idnxf_cic_info.xf_errcnt);
1054
1055 goto done;
1056 }
1057
1058 /*
1059 * We're executing out of the context of a cross-call
1060 * so we're effectively bound! :)
1061 */
1062 for (bus = 0; bus < MAX_ABUSES; bus++) {
1063 /*
1064 * XXX - need to worry about shuffle??
1065 */
1066 if (!(idnxfp->xf_abus_mask & (1 << bus)))
1067 continue;
1068 smmask = cic_read_sm_mask(brd, bus);
1069
1070 if (idnxfp->xf_doadd) {
1071 smmask |= idnxfp->xf_boardset;
1072 (void) cic_write_sm_mask(brd, bus, smmask);
1073
1074 if (idnxfp->xf_smbase != (uint_t)-1) {
1075 (void) cic_write_sm_bar(brd, bus,
1076 idnxfp->xf_smbase);
1077 (void) cic_write_sm_lar(brd, bus,
1078 idnxfp->xf_smlimit);
1079 }
1080 /*
1081 * Verify data got there!
1082 */
1083 rv = verify_smregs(brd, bus, smmask, idnxfp->xf_smbase,
1084 idnxfp->xf_smlimit);
1085 } else {
1086 smmask &= ~idnxfp->xf_boardset;
1087 (void) cic_write_sm_mask(brd, bus, smmask);
1088
1089 if (!smmask) {
1090 /*
1091 * Update the LAR first so that we effectively
1092 * disable the register without possibly
1093 * opening the window to transaction we
1094 * don't care about. Updating the LAR first
1095 * will guarantee we effectively turn it
1096 * off immediately.
1097 */
1098 (void) cic_write_sm_lar(brd, bus, 0);
1099 (void) cic_write_sm_bar(brd, bus, 1);
1100
1101 rv = verify_smregs(brd, bus, smmask, 1, 0);
1102 } else {
1103 rv = verify_smregs(brd, bus, smmask,
1104 (uint_t)-1, (uint_t)-1);
1105 }
1106 }
1107 if (rv) {
1108 idnxf_cic_info.xf_errcic[brd][bus] = IDNCIC_ERR;
1109 ATOMIC_INC(idnxf_cic_info.xf_errcnt);
1110 } else {
1111 idnxf_cic_info.xf_errcic[brd][bus] = IDNCIC_OK;
1112 }
1113 }
1114
1115 done:
1116 ATOMIC_DEC(idnxf_cic_info.xf_count);
1117 }
1118
1119 static int
idnxf_shmem_update_all(pda_handle_t ph,boardset_t boardset,uint_t smbase,uint_t smlimit,int doadd)1120 idnxf_shmem_update_all(pda_handle_t ph, boardset_t boardset,
1121 uint_t smbase, uint_t smlimit, int doadd)
1122 {
1123 cpuset_t target_cpuset;
1124 int target_count;
1125 int rv = 0;
1126 int c, brd, bus;
1127 short abus_mask;
1128 time_t start_time;
1129 procname_t proc = "idnxf_shmem_update_all";
1130
1131
1132 ASSERT(MUTEX_HELD(&idn_xf_mutex));
1133
1134 pda_get_busmask(ph, &abus_mask, NULL);
1135
1136 CPUSET_ZERO(target_cpuset);
1137 target_count = 0;
1138 /*
1139 * Build a cpuset of target cpus (one per board) to
1140 * be used to send the CIC update xcall.
1141 */
1142 for (brd = 0; brd < MAX_BOARDS; brd++) {
1143 /*
1144 * Need to target an available cpu on the target board
1145 * so that we can look at the CICs on that board.
1146 */
1147 c = board_to_ready_cpu(brd, cpu_ready_set);
1148
1149 if (c == -1) {
1150 /*
1151 * If there's no cpu on this board, no
1152 * need to update the CICs.
1153 */
1154 continue;
1155 }
1156 CPUSET_ADD(target_cpuset, c);
1157 target_count++;
1158 }
1159
1160 if (CPUSET_ISNULL(target_cpuset)) {
1161 PR_REGS("%s: NO target cpus to update!!\n", proc);
1162 return (0);
1163 }
1164
1165 RESET_CIC_HISTORY();
1166
1167 /*
1168 * Broadcast out the CIC update request and then
1169 * sit back and wait for dinner to arrive!
1170 * Let's set up the global structure all the xcall
1171 * recepients will read.
1172 */
1173 start_time = ddi_get_lbolt();
1174 /*
1175 * Set the start time. Make sure it's different
1176 * then the previous run.
1177 */
1178 if (start_time <= idnxf_cic_info.xf_start_time)
1179 start_time++;
1180 idnxf_cic_info.xf_start_time = start_time;
1181
1182 idnxf_cic_info.xf_abus_mask = abus_mask;
1183 idnxf_cic_info.xf_boardset = boardset;
1184 idnxf_cic_info.xf_smbase = smbase;
1185 idnxf_cic_info.xf_smlimit = smlimit;
1186 idnxf_cic_info.xf_doadd = doadd;
1187 idnxf_cic_info.xf_count = target_count;
1188 idnxf_cic_info.xf_errcnt = 0;
1189 idnxf_cic_info.xf_errtimer = 0;
1190 bzero(&idnxf_cic_info.xf_errcic, sizeof (idnxf_cic_info.xf_errcic));
1191
1192 /*
1193 * Broadcast out the xcall to do the task.
1194 */
1195 #ifdef DEBUG
1196 {
1197 uint_t tu32, tl32;
1198
1199 tu32 = UPPER32_CPUMASK(target_cpuset);
1200 tl32 = LOWER32_CPUMASK(target_cpuset);
1201 PR_REGS("%s: (start %ld) broadcasting CIC - "
1202 "%s to cpus 0x%x.%0x\n",
1203 proc, start_time, doadd ? "LINK" : "UNLINK",
1204 tu32, tl32);
1205 }
1206
1207 /*
1208 * Can't dump debug during cross-calls.
1209 */
1210 o_idn_debug = idn_debug;
1211 idn_debug = 0;
1212 #endif /* DEBUG */
1213
1214 xc_attention(target_cpuset);
1215
1216 xc_some(target_cpuset, idnxf_shmem_update_one,
1217 (uint64_t)&idnxf_cic_info, (uint64_t)start_time);
1218
1219 xc_dismissed(target_cpuset);
1220
1221 ASSERT(idnxf_cic_info.xf_count == 0);
1222
1223 #ifdef DEBUG
1224 idn_debug = o_idn_debug;
1225 o_idn_debug = 0;
1226 #endif /* DEBUG */
1227
1228 PR_REGS("%s: waiting for completion of %d CIC - %s...\n",
1229 proc, idnxf_cic_info.xf_count, doadd ? "LINKS" : "UNLINKS");
1230 PR_REGS("%s: CIC - %s have checked IN.\n",
1231 proc, doadd ? "LINKS" : "UNLINKS");
1232
1233 /*
1234 * Modifying xf_start_time effectively disables any
1235 * possible outstanding xcall's since they don't touch
1236 * idnxf_cic_info unless their given start_time matches
1237 * that in the idnxf_cic_info structure.
1238 */
1239 idnxf_cic_info.xf_start_time++;
1240
1241 PR_REGS("%s: xf_errcnt = %d, xf_errtimer = %d\n",
1242 proc, idnxf_cic_info.xf_errcnt, idnxf_cic_info.xf_errtimer);
1243 DUMP_CIC_HISTORY();
1244 /*
1245 * Should errors be fatal? (panic).
1246 */
1247 rv = 0;
1248 for (c = 0; c < NCPU; c++) {
1249 if (!CPU_IN_SET(target_cpuset, c))
1250 continue;
1251 brd = CPUID_TO_BOARDID(c);
1252
1253 for (bus = 0; bus < MAX_ABUSES; bus++) {
1254
1255 if (!(abus_mask & (1 << bus)))
1256 continue;
1257
1258 switch (idnxf_cic_info.xf_errcic[brd][bus]) {
1259 case IDNCIC_UNKNOWN:
1260 /*
1261 * Unknown is only an error if the
1262 * timer expired.
1263 */
1264 if (!idnxf_cic_info.xf_errtimer)
1265 break;
1266 cmn_err(CE_WARN,
1267 "IDN: 509: CPU %d never responded "
1268 "to CIC update", c);
1269 /*FALLTHROUGH*/
1270
1271 case IDNCIC_ERR:
1272 cmn_err(CE_WARN,
1273 "IDN: 510: failed write-smregs "
1274 "(bd=%d, bs=%d, sm(bar=0x%x, "
1275 "lar=0x%x))",
1276 brd, bus, smbase, smlimit);
1277 rv++;
1278 break;
1279
1280 case IDNCIC_BUSY:
1281 cmn_err(CE_WARN, "IDN: 511: update-one "
1282 "(cpu=%d, bd=%d) time conflict",
1283 c, brd);
1284 /*
1285 * Should never occur. Not fatal,
1286 * just continue.
1287 */
1288 break;
1289
1290 default:
1291 PR_REGS("%s: board %d, bus %d "
1292 "(bar=0x%x,lar=0x%x) - update OK\n",
1293 proc, brd, bus, smbase, smlimit);
1294 break;
1295 }
1296 }
1297 }
1298
1299 return (rv ? -1 : 0);
1300 }
1301
1302 /*
1303 * Add the respective boardset/base/limit/mcadr's to the local
1304 * domain's hardware configuration with respect to the SMR.
1305 *
1306 * is_master Indicates remote domain is a master.
1307 */
1308 int
idnxf_shmem_add(int is_master,boardset_t boardset,pfn_t pfnbase,pfn_t pfnlimit,uint_t * mcadr)1309 idnxf_shmem_add(int is_master, boardset_t boardset, pfn_t pfnbase,
1310 pfn_t pfnlimit, uint_t *mcadr)
1311 {
1312 int rv = 0;
1313 register int brd, rbrd;
1314 register boardset_t localboardset;
1315 uint_t madr;
1316 uint_t smbase, smlimit;
1317 pda_handle_t ph;
1318 procname_t proc = "idnxf_shmem_add";
1319
1320
1321 localboardset = idn_domain[idn.localid].dhw.dh_boardset;
1322
1323 ASSERT(localboardset && boardset && ((localboardset & boardset) == 0));
1324 ASSERT(is_master ? (pfnbase && pfnlimit && mcadr) : 1);
1325
1326 if (pfnbase != PFN_INVALID) {
1327 smbase = (uint_t)PFN_TO_SMADDR(pfnbase);
1328 smlimit = (uint_t)PFN_TO_SMADDR(pfnlimit);
1329 } else {
1330 smbase = smlimit = (uint_t)-1;
1331 }
1332 PR_REGS("%s: is_master=%d, boardset=0x%x, smbase=0x%x, smlimit=%x\n",
1333 proc, is_master, boardset, smbase, smlimit);
1334
1335 /*
1336 * Need to serialize hardware access so we don't have multiple
1337 * threads attempting to access hardware regs simulataneously.
1338 * This should not be a significant performance penalty since
1339 * the hardware is only touched when domains are linking or
1340 * unlinking.
1341 */
1342 mutex_enter(&idn_xf_mutex);
1343
1344 /*
1345 * Map in the post2obp structure so we can find
1346 * bus config information.
1347 */
1348 ph = pda_open();
1349 if (ph == (pda_handle_t)NULL) {
1350 cmn_err(CE_WARN,
1351 "IDN: 507: failed to map-in post2obp structure");
1352 rv = -1;
1353 goto done;
1354
1355 } else if (!pda_is_valid(ph)) {
1356 cmn_err(CE_WARN, "IDN: 508: post2obp checksum invalid");
1357 rv = -1;
1358 goto done;
1359 }
1360 /*
1361 * Take a checkpoint in bbsram for diagnostic purposes.
1362 */
1363 CHECKPOINT_OPENED(IDNSB_CHKPT_SMR, boardset, 1);
1364
1365 rv = idnxf_shmem_update_all(ph, boardset, smbase, smlimit, 1);
1366
1367 if (rv || (is_master == 0))
1368 goto done;
1369
1370 /*
1371 * If this is a slave (i.e. remote domain is_master),
1372 * then we need to deprogram our PCs.
1373 */
1374 PR_REGS("%s: updating PC regs (lboardset=0x%x, rboardset=0x%x)\n",
1375 proc, localboardset, boardset);
1376
1377 for (brd = 0; brd < MAX_BOARDS; brd++) {
1378
1379 if (!BOARD_IN_SET(localboardset, brd))
1380 continue;
1381 /*
1382 * If this is a slave (i.e. remote domain is_master),
1383 * then we need to program our PCs.
1384 */
1385 for (rbrd = 0; rbrd < MAX_BOARDS; rbrd++) {
1386
1387 if ((madr = mcadr[rbrd]) == 0)
1388 continue;
1389
1390 ASSERT(BOARD_IN_SET(boardset, rbrd));
1391 /*
1392 * Write the MC adr for the respective
1393 * remote board (rbrd) into the PCs of
1394 * the given local board (brd).
1395 */
1396 if (pc_write_madr(ph, brd, rbrd, madr) < 0) {
1397 cmn_err(CE_WARN,
1398 "IDN: 512: failed [add] write-madr "
1399 "(bd=%d, rbd=%d, madr=0x%x)",
1400 brd, rbrd, madr);
1401 rv = -1;
1402 goto done;
1403 }
1404 }
1405 }
1406
1407 done:
1408 if (ph)
1409 pda_close(ph);
1410
1411 mutex_exit(&idn_xf_mutex);
1412 /*
1413 * XXX
1414 *
1415 * Failure here is fatal. Disable IDN?
1416 * NOn-zero return value will at least prevent
1417 * linkage with domain - probably sufficient.
1418 */
1419 return (rv);
1420 }
1421
1422 /*
1423 * Remove the respective boardset from the local domain's
1424 * hardware configuration with respect to the SMR.
1425 *
1426 * is_master Indicates remote domain is a master.
1427 */
1428 int
idnxf_shmem_sub(int is_master,boardset_t boardset)1429 idnxf_shmem_sub(int is_master, boardset_t boardset)
1430 {
1431 int rv = 0;
1432 register int brd, rbrd;
1433 register boardset_t localboardset;
1434 pda_handle_t ph;
1435 procname_t proc = "idnxf_shmem_sub";
1436
1437 localboardset = idn_domain[idn.localid].dhw.dh_boardset;
1438
1439 ASSERT(localboardset && boardset && ((localboardset & boardset) == 0));
1440
1441 PR_REGS("%s: is_master=%d, boardset=0x%x\n",
1442 proc, is_master, boardset);
1443
1444 /*
1445 * Need to serialize hardware access so we don't have multiple
1446 * threads attempting to access hardware regs simulataneously.
1447 * This should not be a significant performance penalty since
1448 * the hardware is only touched when domains are linking or
1449 * unlinking.
1450 */
1451 mutex_enter(&idn_xf_mutex);
1452
1453 /*
1454 * Map in the post2obp structure so we can find
1455 * bus config information.
1456 */
1457 ph = pda_open();
1458 if (ph == (pda_handle_t)NULL) {
1459 cmn_err(CE_WARN,
1460 "IDN: 507: failed to map-in post2obp structure");
1461 rv = -1;
1462 goto done;
1463
1464 } else if (!pda_is_valid(ph)) {
1465 cmn_err(CE_WARN, "IDN: 508: post2obp checksum invalid");
1466 rv = -1;
1467 goto done;
1468 }
1469 /*
1470 * Take a checkpoint in bbsram for diagnostic purposes.
1471 */
1472 CHECKPOINT_CLOSED(IDNSB_CHKPT_SMR, boardset, 2);
1473
1474 rv = idnxf_shmem_update_all(ph, boardset, (uint_t)-1, (uint_t)-1, 0);
1475
1476 if (rv || (is_master == 0))
1477 goto done;
1478
1479 /*
1480 * If this is a slave (i.e. remote domain is_master),
1481 * then we need to deprogram our PCs.
1482 */
1483 PR_REGS("%s: reseting PC regs (lboardset=0x%x, rboardset=0x%x)\n",
1484 proc, localboardset, boardset);
1485
1486 for (brd = 0; brd < MAX_BOARDS; brd++) {
1487
1488 if (!BOARD_IN_SET(localboardset, brd))
1489 continue;
1490
1491 for (rbrd = 0; rbrd < MAX_BOARDS; rbrd++) {
1492
1493 if (!BOARD_IN_SET(boardset, rbrd))
1494 continue;
1495 /*
1496 * Clear the MC adr for the respective
1497 * remote board (rbrd) into the PCs of
1498 * the given local board (brd).
1499 */
1500 if (pc_write_madr(ph, brd, rbrd, 0) < 0) {
1501 cmn_err(CE_WARN,
1502 "IDN: 512: failed [del] write-madr "
1503 "(bd=%d, rbd=%d, madr=0x%x)",
1504 brd, rbrd, 0);
1505 rv = -1;
1506 goto done;
1507 }
1508 }
1509 }
1510
1511 done:
1512 if (ph)
1513 pda_close(ph);
1514 mutex_exit(&idn_xf_mutex);
1515
1516 return (rv);
1517 }
1518
1519 /*
1520 * We cannot cross-trap cpu_flush_ecache since it references
1521 * %g7 via CPU. It's possible that %g7 may not be set up
1522 * when the trap comes in, and could thus cause a crash.
1523 * Well...at least that's what has been happening when I
1524 * tried x-calls within an xc_attention (KMISS) panic.
1525 * Instead we use cross-calls. However, since we can't
1526 * xc_attention around a cross-call, we have not guaranteed
1527 * way of knowing the operation succeeded. To synchronize
1528 * this flush operation across cpus, we use a semaphore
1529 * which is V'd by the receiving cpus and P'd by the caller
1530 * initiating the all-cpus flush.
1531 */
1532 /*ARGSUSED0*/
1533 void
idn_flush_ecache(uint64_t arg1,uint64_t arg2)1534 idn_flush_ecache(uint64_t arg1, uint64_t arg2)
1535 {
1536 extern void cpu_flush_ecache(void);
1537
1538 cpu_flush_ecache();
1539 /*
1540 * Paranoia...Give things a chance to drain.
1541 */
1542 drv_usecwait(500000); /* 500 msec */
1543 }
1544 /*
1545 * Flush the ecache's of all the cpus within this domain of
1546 * any possible SMR references.
1547 * This logic is borrowed from ecc.c:cpu_flush_ecache().
1548 */
1549 void
idnxf_flushall_ecache()1550 idnxf_flushall_ecache()
1551 {
1552 cpuset_t local_cpuset;
1553 procname_t proc = "idnxf_flushall_ecache";
1554
1555
1556 PR_XF("%s: flushing ecache (cpu_ready_set = 0x%x.%x)\n", proc,
1557 UPPER32_CPUMASK(cpu_ready_set), LOWER32_CPUMASK(cpu_ready_set));
1558
1559 CHECKPOINT_CACHE_CLEAR_DEBUG(1);
1560 CHECKPOINT_CACHE_STEP_DEBUG(0x1, 2);
1561
1562 local_cpuset = cpu_ready_set;
1563
1564 xc_attention(local_cpuset);
1565
1566 /*
1567 * We tell each cpu to do a flush and then we hit
1568 * a semaphore to synchronize with all of them
1569 * to guarantee they have completed the flush before
1570 * we continue on. We have to do this type of
1571 * sychronization since we can't xc_attention around
1572 * a cross-call.
1573 */
1574 CHECKPOINT_CACHE_STEP_DEBUG(0x2, 3);
1575
1576 xc_all(idn_flush_ecache, 0, 0);
1577
1578 CHECKPOINT_CACHE_STEP_DEBUG(0x4, 4);
1579
1580 xc_dismissed(local_cpuset);
1581
1582 CHECKPOINT_CACHE_STEP_DEBUG(0x8, 5);
1583 }
1584
1585 /*
1586 * --------------------------------------------------
1587 */
1588 static int
verify_smregs(int brd,int bus,boardset_t smmask,uint_t smbase,uint_t smlimit)1589 verify_smregs(int brd, int bus, boardset_t smmask, uint_t smbase, uint_t
1590 smlimit)
1591 {
1592 int rv = 0;
1593 uint_t smreg;
1594
1595 if (smmask != (boardset_t)-1) {
1596 smreg = (uint_t)cic_read_sm_mask(brd, bus);
1597 if (smreg != (uint_t)smmask) {
1598 cmn_err(CE_WARN,
1599 "IDN: 513: sm-mask error "
1600 "(expected = 0x%x, actual = 0x%x)",
1601 (uint_t)smmask, smreg);
1602 rv++;
1603 }
1604 }
1605
1606 if (smbase != (uint_t)-1) {
1607 smreg = cic_read_sm_bar(brd, bus);
1608 if (smreg != smbase) {
1609 cmn_err(CE_WARN,
1610 "IDN: 514: sm-base error "
1611 "(expected = 0x%x, actual = 0x%x)",
1612 smbase, smreg);
1613 rv++;
1614 }
1615 }
1616
1617 if (smlimit != (uint_t)-1) {
1618 smreg = cic_read_sm_lar(brd, bus);
1619 if (smreg != smlimit) {
1620 cmn_err(CE_WARN,
1621 "IDN: 515: sm-limit error "
1622 "(expected = 0x%x, actual = 0x%x)",
1623 smlimit, smreg);
1624 rv++;
1625 }
1626 }
1627
1628 return (rv ? -1 : 0);
1629 }
1630
1631 /*
1632 * -------------------------------------------------------------
1633 */
1634 int
idn_cpu_per_board(pda_handle_t ph,cpuset_t cset,struct hwconfig * hwp)1635 idn_cpu_per_board(pda_handle_t ph, cpuset_t cset, struct hwconfig *hwp)
1636 {
1637 int b, err = 0;
1638 boardset_t bset, cpu_bset;
1639 board_desc_t *lbp;
1640
1641 if (!idn_check_cpu_per_board)
1642 return (1);
1643
1644 bset = hwp->dh_boardset;
1645 CPUSET_TO_BOARDSET(cset, cpu_bset);
1646
1647 /*
1648 * Every board has at least one cpu, we're happy.
1649 */
1650 if (cpu_bset == bset)
1651 return (1);
1652
1653 /*
1654 * Well, not all boards had cpus. That's okay so
1655 * long as they don't have memory also.
1656 * Get rid of the boards that have a cpu.
1657 */
1658 bset &= ~cpu_bset;
1659 /*
1660 * None of the remaining boards in the set shold have mem.
1661 */
1662 err = 0;
1663
1664 /*
1665 * A NULL post2obp pointer indicates we're checking
1666 * the config of a remote domain. Since we can't
1667 * look at the post2obp of the remote domain, we'll
1668 * have to trust what he passed us in his config.
1669 */
1670 if (ph && !pda_is_valid(ph)) {
1671 cmn_err(CE_WARN, "IDN: 508: post2obp checksum invalid");
1672 return (0);
1673 }
1674
1675 for (b = 0; b < MAX_BOARDS; b++) {
1676 if (!BOARD_IN_SET(bset, b))
1677 continue;
1678
1679 lbp = ph ? pda_get_board_info(ph, b) : NULL;
1680
1681 if ((lbp &&
1682 (BDA_NBL(lbp->bda_board, BDA_MC_NBL) == BDAN_GOOD)) ||
1683 (!lbp && hwp->dh_mcadr[b])) {
1684 err++;
1685 cmn_err(CE_WARN,
1686 "IDN: 516: (%s) board %d has memory, "
1687 "but no CPUs - CPU per memory board REQUIRED",
1688 ph ? "local" : "remote", b);
1689 }
1690 }
1691
1692 return (err ? 0 : 1);
1693 }
1694