xref: /titanic_44/usr/src/uts/sun4u/starfire/io/idn_xf.c (revision db8b037b5616a366b7dfdc01ef9552f02f9adfdd)
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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
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