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 2008 Sun Microsystems, Inc. All rights reserved.
23 * Use is subject to license terms.
24 */
25
26 /*
27 * CPU functions to the Safari Configurator (gptwo_cpu)
28 */
29
30 #include <sys/types.h>
31 #include <sys/cred.h>
32 #include <sys/mman.h>
33 #include <sys/kmem.h>
34 #include <sys/conf.h>
35 #include <sys/ddi.h>
36 #include <sys/sunddi.h>
37 #include <sys/sunndi.h>
38 #include <sys/modctl.h>
39 #include <sys/stat.h>
40 #include <sys/param.h>
41 #include <sys/autoconf.h>
42 #include <sys/ksynch.h>
43 #include <sys/promif.h>
44 #include <sys/ndi_impldefs.h>
45 #include <sys/ddi_impldefs.h>
46 #include <sys/machsystm.h>
47 #include <sys/gp2cfg.h>
48 #include <sys/gptwo_cpu.h>
49 #include <sys/cheetahregs.h>
50
51 #ifdef DEBUG
52 int gptwo_cpu_debug = 0;
53
54 static void debug(char *, uintptr_t, uintptr_t,
55 uintptr_t, uintptr_t, uintptr_t);
56
57 #define GPTWO_DEBUG0(level, flag, s) if (gptwo_cpu_debug >= level) \
58 cmn_err(flag, s)
59 #define GPTWO_DEBUG1(level, flag, fmt, a1) if (gptwo_cpu_debug >= level) \
60 debug(fmt, (uintptr_t)(a1), 0, 0, 0, 0);
61 #define GPTWO_DEBUG2(level, flag, fmt, a1, a2) if (gptwo_cpu_debug >= level) \
62 debug(fmt, (uintptr_t)(a1), (uintptr_t)(a2), 0, 0, 0);
63 #define GPTWO_DEBUG3(level, flag, fmt, a1, a2, a3) \
64 if (gptwo_cpu_debug >= level) \
65 debug(fmt, (uintptr_t)(a1), (uintptr_t)(a2), (uintptr_t)(a3), 0, 0);
66 #else
67 #define GPTWO_DEBUG0(level, flag, s)
68 #define GPTWO_DEBUG1(level, flag, fmt, a1)
69 #define GPTWO_DEBUG2(level, flag, fmt, a1, a2)
70 #define GPTWO_DEBUG3(level, flag, fmt, a1, a2, a3)
71 #endif
72
73 /*
74 * Devinfo branch create arg
75 */
76 struct bca {
77 spcd_t *pcd;
78 uint_t portid;
79 uint_t cpuid;
80 uint_t coreid;
81 uint_t impl;
82 dev_info_t *new_child;
83 };
84
85 static dev_info_t *gptwocfg_create_cpu_node(dev_info_t *, spcd_t *,
86 uint_t, uint_t, uint_t, uint_t);
87 static dev_info_t *gptwocfg_create_mc_node(dev_info_t *, spcd_t *, uint_t);
88 static dev_info_t *gptwocfg_create_cmp_node(dev_info_t *, spcd_t *, uint_t);
89 static int gptwocfg_create_core_node(dev_info_t *, spcd_t *, uint_t, uint_t);
90 static int set_mc_props(dev_info_t *new_child, void *arg, uint_t flags);
91 static int set_cmp_props(dev_info_t *new_child, void *arg, uint_t flags);
92 static int set_cpu_props(dev_info_t *new_child, void *arg, uint_t flags);
93 static int set_cpu_common_props(dev_info_t *new_child, struct bca *bcp);
94 static int set_cpu_us3_props(dev_info_t *new_child, struct bca *bcp);
95 static int set_cpu_us4_props(dev_info_t *new_child, struct bca *bcp);
96 static void get_new_child(dev_info_t *rdip, void *arg, uint_t flags);
97
98
99 /*
100 * Module linkage information for the kernel.
101 */
102
103 extern struct mod_ops mod_miscops;
104
105 static struct modlmisc modlmisc = {
106 &mod_miscops, /* Type of module */
107 "gptwo->cpu configurator",
108 };
109
110 static struct modlinkage modlinkage = {
111 MODREV_1, (void *)&modlmisc, NULL
112 };
113
114 int
_init(void)115 _init(void)
116 {
117 int err = 0;
118
119 /* register device with the configurator */
120 gptwocfg_register_ops(SAFPTYPE_CPU, gptwocfg_configure_cpu, NULL);
121
122 if ((err = mod_install(&modlinkage)) != 0) {
123 GPTWO_DEBUG1(1, CE_WARN, "gptwo_cpu (CPU/MC Functions) "
124 "failed to load, error=%d\n", err);
125 gptwocfg_unregister_ops(SAFPTYPE_CPU);
126 } else {
127 GPTWO_DEBUG0(1, CE_WARN, "gptwo_cpu (CPU/MC Functions) "
128 "has been loaded.\n");
129 }
130 return (err);
131 }
132
133 int
_fini(void)134 _fini(void)
135 {
136 /* cleanup/freeup structs with configurator */
137 gptwocfg_unregister_ops(SAFPTYPE_CPU);
138 return (mod_remove(&modlinkage));
139 }
140
141 int
_info(struct modinfo * modinfop)142 _info(struct modinfo *modinfop)
143 {
144 return (mod_info(&modlinkage, modinfop));
145 }
146
147 gptwo_new_nodes_t *
gptwocfg_configure_cpu(dev_info_t * ap,spcd_t * pcd,uint_t portid)148 gptwocfg_configure_cpu(dev_info_t *ap, spcd_t *pcd, uint_t portid)
149 {
150 dev_info_t *cpu_node[AGENTS_PER_PORT], *mc_node[AGENTS_PER_PORT];
151 dev_info_t *cmp_node = NULL;
152 gptwo_new_nodes_t *new_nodes;
153 int nodes = 0;
154 int i, j = 0;
155 uint_t implementation;
156
157 GPTWO_DEBUG2(1, CE_CONT, "gptwocfg_configure_cpu: portid=%x pcd=%lx\n",
158 portid, pcd);
159
160 for (i = 0; i < AGENTS_PER_PORT; i++) {
161 cpu_node[i] = NULL;
162 mc_node[i] = NULL;
163 }
164
165 implementation = (pcd->spcd_ver_reg >> 32) & 0x000000000000ffff;
166
167 switch (implementation) {
168 case CHEETAH_IMPL:
169 case CHEETAH_PLUS_IMPL:
170 case JAGUAR_IMPL:
171 case PANTHER_IMPL:
172 break;
173 default:
174 cmn_err(CE_WARN, "Unsupported cpu implementation=0x%x : "
175 "skipping configure of portid=0x%x", implementation,
176 portid);
177 ASSERT(0);
178 return (NULL);
179 }
180
181 if (CPU_IMPL_IS_CMP(implementation)) {
182 if (cmp_node = gptwocfg_create_cmp_node(ap, pcd, portid))
183 nodes++;
184 else
185 return (NULL);
186 }
187
188 for (i = 0; i < AGENTS_PER_PORT; i++) {
189 if (pcd->spcd_agent[i] != SPCD_RSV_PASS)
190 continue;
191
192 if (cpu_node[i] = gptwocfg_create_cpu_node(cmp_node ?
193 cmp_node : ap, pcd, portid, pcd->spcd_cpuid[i], i,
194 implementation)) {
195 /*
196 * If the CPU is a CMP, the entire branch is
197 * manipulated using just the top node. Thus,
198 * the dips of the individual cores do not need
199 * to be held or stored in the new node list.
200 */
201 if (cmp_node) {
202 e_ddi_branch_rele(cpu_node[i]);
203 } else {
204 nodes++;
205 }
206 }
207 }
208
209 /* current implementations have 1 MC node per Safari port */
210 if (pcd->spcd_prsv == SPCD_RSV_PASS &&
211 (mc_node[0] = gptwocfg_create_mc_node(ap, pcd, portid)))
212 nodes++;
213
214 new_nodes = gptwocfg_allocate_node_list(nodes);
215
216 j = 0;
217 for (i = 0; i < AGENTS_PER_PORT; i++) {
218 if ((cpu_node[i] != NULL) && (!CPU_IMPL_IS_CMP(implementation)))
219 new_nodes->gptwo_nodes[j++] = cpu_node[i];
220 if (mc_node[i] != NULL)
221 new_nodes->gptwo_nodes[j++] = mc_node[i];
222 }
223
224 if (cmp_node)
225 new_nodes->gptwo_nodes[j++] = cmp_node;
226
227 return (new_nodes);
228 }
229
230
231 static dev_info_t *
gptwocfg_create_cmp_node(dev_info_t * ap,spcd_t * pcd,uint_t portid)232 gptwocfg_create_cmp_node(dev_info_t *ap, spcd_t *pcd, uint_t portid)
233 {
234 struct bca arg;
235 devi_branch_t b;
236
237 arg.pcd = pcd;
238 arg.portid = portid;
239 arg.cpuid = 0;
240 arg.coreid = 0;
241 arg.new_child = NULL;
242
243 b.arg = &arg;
244 b.type = DEVI_BRANCH_SID;
245 b.create.sid_branch_create = set_cmp_props;
246 b.devi_branch_callback = get_new_child;
247
248 if (e_ddi_branch_create(ap, &b, NULL, 0))
249 return (NULL);
250
251 return (arg.new_child);
252 }
253
254 /*ARGSUSED*/
255 static int
set_cmp_props(dev_info_t * new_child,void * arg,uint_t flags)256 set_cmp_props(dev_info_t *new_child, void *arg, uint_t flags)
257 {
258 struct bca *bap = (struct bca *)arg;
259 gptwo_regspec_t reg;
260 spcd_t *pcd;
261 uint_t portid;
262
263 pcd = bap->pcd;
264 portid = bap->portid;
265
266 GPTWO_DEBUG2(1, CE_CONT, "set_cmp_props: portid=%x pcd=%lx\n",
267 portid, pcd);
268
269 if (ndi_prop_update_string(DDI_DEV_T_NONE, new_child,
270 "name", "cmp") != DDI_SUCCESS) {
271 GPTWO_DEBUG0(1, CE_CONT, "set_cmp_props: failed to "
272 "create name property\n");
273 return (DDI_WALK_ERROR);
274 }
275
276 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child,
277 "portid", portid) != DDI_SUCCESS) {
278 GPTWO_DEBUG0(1, CE_CONT, "set_cmp_props: failed to "
279 "create portid property\n");
280 return (DDI_WALK_ERROR);
281 }
282
283 reg.gptwo_phys_hi = 0x400 | (portid >> 9);
284 reg.gptwo_phys_low = (portid << 23);
285 reg.gptwo_size_hi = 0;
286 reg.gptwo_size_low = 0x10000;
287
288 if (ndi_prop_update_int_array(DDI_DEV_T_NONE,
289 new_child, "reg", (int *)®,
290 sizeof (gptwo_regspec_t) / sizeof (int)) != DDI_SUCCESS) {
291 GPTWO_DEBUG0(1, CE_CONT, "set_cmp_props: failed to "
292 "create reg property\n");
293 return (DDI_WALK_ERROR);
294 }
295
296 return (DDI_WALK_TERMINATE);
297 }
298
299 static dev_info_t *
gptwocfg_create_cpu_node(dev_info_t * ap,spcd_t * pcd,uint_t portid,uint_t cpuid,uint_t coreid,uint_t impl)300 gptwocfg_create_cpu_node(dev_info_t *ap, spcd_t *pcd, uint_t portid,
301 uint_t cpuid, uint_t coreid, uint_t impl)
302 {
303 struct bca arg;
304 devi_branch_t b = {0};
305
306 arg.pcd = pcd;
307 arg.portid = portid;
308 arg.cpuid = cpuid;
309 arg.coreid = coreid;
310 arg.impl = impl;
311 arg.new_child = NULL;
312
313 b.arg = &arg;
314 b.type = DEVI_BRANCH_SID;
315 b.create.sid_branch_create = set_cpu_props;
316 b.devi_branch_callback = get_new_child;
317
318 if (e_ddi_branch_create(ap, &b, NULL, 0))
319 return (NULL);
320
321 return (arg.new_child);
322 }
323
324 /*ARGSUSED*/
325 static int
set_cpu_props(dev_info_t * new_child,void * arg,uint_t flags)326 set_cpu_props(dev_info_t *new_child, void *arg, uint_t flags)
327 {
328 struct bca *bcp = arg;
329 uint_t impl = bcp->impl;
330 int rc;
331
332 if (set_cpu_common_props(new_child, bcp) != DDI_WALK_CONTINUE)
333 return (DDI_WALK_ERROR);
334
335 switch (impl) {
336 case CHEETAH_IMPL:
337 case CHEETAH_PLUS_IMPL:
338 rc = set_cpu_us3_props(new_child, bcp);
339 break;
340 case JAGUAR_IMPL:
341 case PANTHER_IMPL:
342 rc = set_cpu_us4_props(new_child, bcp);
343 break;
344 default:
345 ASSERT(0);
346 return (DDI_WALK_ERROR);
347 }
348
349 return (rc);
350 }
351
352 /*
353 * Set properties common to cpu (non-CMP) and core (CMP) nodes.
354 *
355 * cpuid
356 * device_type
357 * manufacturer#
358 * implementation#
359 * mask#
360 * sparc-version
361 * clock-frequency
362 * #dtlb-entries
363 * #itlb-entries
364 */
365 static int
set_cpu_common_props(dev_info_t * new_child,struct bca * bcp)366 set_cpu_common_props(dev_info_t *new_child, struct bca *bcp)
367 {
368 uint_t cpuid, impl;
369 spcd_t *pcd;
370 int mask, manufacturer;
371
372 cpuid = bcp->cpuid;
373 pcd = bcp->pcd;
374 impl = bcp->impl;
375
376 mask = (pcd->spcd_ver_reg >> 24) & 0x00000000000000ff;
377 manufacturer = (pcd->spcd_ver_reg >> 48) & 0x000000000000ffff;
378
379 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child,
380 "cpuid", cpuid) != DDI_SUCCESS) {
381 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_common_props: failed "
382 "to create cpuid property\n");
383 return (DDI_WALK_ERROR);
384 }
385
386 if (ndi_prop_update_string(DDI_DEV_T_NONE, new_child,
387 "device_type", "cpu") != DDI_SUCCESS) {
388 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_common_props: failed "
389 "to create device_type property\n");
390 return (DDI_WALK_ERROR);
391 }
392
393 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child, "manufacturer#",
394 manufacturer) != DDI_SUCCESS) {
395 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_common_props: failed "
396 "to create manufacturer# property\n");
397 return (DDI_WALK_ERROR);
398 }
399
400 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child, "implementation#",
401 impl) != DDI_SUCCESS) {
402 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_common_props: failed "
403 "to create implementation# property\n");
404 return (DDI_WALK_ERROR);
405 }
406
407 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child, "mask#",
408 mask) != DDI_SUCCESS) {
409 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_common_props: failed "
410 "to create mask# property\n");
411 return (DDI_WALK_ERROR);
412 }
413
414 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child,
415 "sparc-version", 9) != DDI_SUCCESS) {
416 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_common_props: failed "
417 "to create sparc-version property\n");
418 return (DDI_WALK_ERROR);
419 }
420
421 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child,
422 "clock-frequency", (pcd->spcd_afreq * 1000000)) != DDI_SUCCESS) {
423 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_common_props: failed "
424 "to create clock-frequency property\n");
425 return (DDI_WALK_ERROR);
426 }
427
428 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child,
429 "#dtlb-entries", 0x10) != DDI_SUCCESS) {
430 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_common_props: failed "
431 "to create #dtlb-entries property\n");
432 return (DDI_WALK_ERROR);
433 }
434
435 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child,
436 "#itlb-entries", 0x10) != DDI_SUCCESS) {
437 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_common_props: failed "
438 "to create #itlb-entries property\n");
439 return (DDI_WALK_ERROR);
440 }
441
442 return (DDI_WALK_CONTINUE);
443 }
444
445 /*
446 * Set cpu node properties for Cheetah and Cheetah+.
447 *
448 * name
449 * portid
450 * reg
451 * icache-size
452 * icache-line-size
453 * icache-associativity
454 * dcache-size
455 * dcache-line-size
456 * dcache-associativity
457 * ecache-size
458 * ecache-line-size
459 * ecache-associativity
460 */
461 static int
set_cpu_us3_props(dev_info_t * new_child,struct bca * bcp)462 set_cpu_us3_props(dev_info_t *new_child, struct bca *bcp)
463 {
464 char *node_name;
465 gptwo_regspec_t reg;
466 int ecache_size, ecache_line_size;
467 int dimms, ecache_assoc;
468 spcd_t *pcd;
469 uint_t portid, impl;
470
471 pcd = bcp->pcd;
472 portid = bcp->portid;
473 impl = bcp->impl;
474
475 ASSERT(IS_CHEETAH(impl) || IS_CHEETAH_PLUS(impl));
476
477 switch (impl) {
478 case CHEETAH_IMPL:
479 ecache_assoc = CH_ECACHE_NWAY;
480 node_name = "SUNW,UltraSPARC-III";
481 break;
482 case CHEETAH_PLUS_IMPL:
483 /*
484 * Hard coding the ecache-associativity to 2 for Cheetah+.
485 * We probably should add this to the PCD.
486 */
487 ecache_assoc = CHP_ECACHE_NWAY;
488 node_name = "SUNW,UltraSPARC-III+";
489 break;
490 default:
491 GPTWO_DEBUG1(1, CE_CONT, "set_cpu_us3_props: invalid "
492 "implementation=0x%x\n", impl);
493 return (DDI_WALK_ERROR);
494 }
495
496 if (ndi_prop_update_string(DDI_DEV_T_NONE, new_child,
497 "name", node_name) != DDI_SUCCESS) {
498 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us3_props: failed "
499 "to create name property\n");
500 return (DDI_WALK_ERROR);
501 }
502
503 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child,
504 "portid", portid) != DDI_SUCCESS) {
505 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us3_props: failed "
506 "to create portid property\n");
507 return (DDI_WALK_ERROR);
508 }
509
510 reg.gptwo_phys_hi = 0x400 | (portid >> 9);
511 reg.gptwo_phys_low = (portid << 23);
512 reg.gptwo_size_hi = 0;
513 reg.gptwo_size_low = 0x10000;
514
515 if (ndi_prop_update_int_array(DDI_DEV_T_NONE,
516 new_child, "reg", (int *)®,
517 sizeof (gptwo_regspec_t) / sizeof (int)) != DDI_SUCCESS) {
518 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us3_props: failed "
519 "to create reg property\n");
520 return (DDI_WALK_ERROR);
521 }
522
523 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child,
524 "icache-size", CH_ICACHE_SIZE) != DDI_SUCCESS) {
525 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us3_props: failed "
526 "to create icache-size property\n");
527 return (DDI_WALK_ERROR);
528 }
529
530 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child,
531 "icache-line-size", CH_ICACHE_LSIZE) != DDI_SUCCESS) {
532 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us3_props: failed "
533 "to create icache-line-size property\n");
534 return (DDI_WALK_ERROR);
535 }
536
537 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child,
538 "icache-associativity", CH_ICACHE_NWAY) != DDI_SUCCESS) {
539 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us3_props: failed "
540 "to create icache-associativity property\n");
541 return (DDI_WALK_ERROR);
542 }
543
544 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child,
545 "dcache-size", CH_DCACHE_SIZE) != DDI_SUCCESS) {
546 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us3_props: failed "
547 "to create dcache-size property\n");
548 return (DDI_WALK_ERROR);
549 }
550
551 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child,
552 "dcache-line-size", CH_DCACHE_LSIZE) != DDI_SUCCESS) {
553 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us3_props: failed "
554 "to create dcache-line-size property\n");
555 return (DDI_WALK_ERROR);
556 }
557
558 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child,
559 "dcache-associativity", CH_DCACHE_NWAY) != DDI_SUCCESS) {
560 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us3_props: failed "
561 "to create dcache-associativity property\n");
562 return (DDI_WALK_ERROR);
563 }
564
565 /*
566 * Get the External Cache Size from the Common PCD.
567 */
568 ecache_size = pcd->spcd_cache * 0x100000;
569
570 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child,
571 "ecache-size", ecache_size) != DDI_SUCCESS) {
572 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us3_props: failed "
573 "to create ecache-line-size property\n");
574 return (DDI_WALK_ERROR);
575 }
576
577 switch (ecache_size) {
578 case CH_ECACHE_1M_SIZE:
579 ecache_line_size = 64;
580 break;
581 case CH_ECACHE_4M_SIZE:
582 ecache_line_size = 256;
583 break;
584 case CH_ECACHE_8M_SIZE:
585 ecache_line_size = 512;
586 break;
587 default:
588 GPTWO_DEBUG1(1, CE_CONT, "set_cpu_us3_props: invalid "
589 "ecache-size 0x%x\b", ecache_size);
590 return (DDI_WALK_ERROR);
591 }
592
593 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child,
594 "ecache-line-size", ecache_line_size) != DDI_SUCCESS) {
595 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us3_props: failed "
596 "to create ecache-line-size property\n");
597 return (DDI_WALK_ERROR);
598 }
599
600 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child,
601 "ecache-associativity", ecache_assoc) != DDI_SUCCESS) {
602 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us3_props: failed "
603 "to create ecache-associativity property\n");
604 return (DDI_WALK_ERROR);
605 }
606
607 /*
608 * Create the ecache-dimm-label property.
609 */
610 dimms = 0;
611
612 while ((pcd->sprd_ecache_dimm_label[dimms] != NULL) &&
613 (dimms < MAX_DIMMS_PER_PORT))
614 dimms++;
615
616 if (dimms) {
617 (void) ndi_prop_update_string_array(DDI_DEV_T_NONE, new_child,
618 "ecache-dimm-label", (char **)pcd->sprd_ecache_dimm_label,
619 dimms);
620 }
621
622 return (DDI_WALK_TERMINATE);
623 }
624
625 /*
626 * Set cmp core node properties for Jaguar and Panther.
627 *
628 * name
629 * compatible
630 * reg
631 * l1-icache-size
632 * l1-icache-line-size
633 * l1-icache-associativity
634 * l1-dcache-size
635 * l1-dcache-line-size
636 * l1-dcache-associativity
637 * l2-cache-size
638 * l2-cache-line-size
639 * l2-cache-associativity
640 * l2-cache-sharing
641 * l3-cache-size
642 * l3-cache-line-size
643 * l3-cache-associativity
644 * l3-cache-sharing
645 */
646 static int
set_cpu_us4_props(dev_info_t * new_child,struct bca * bcp)647 set_cpu_us4_props(dev_info_t *new_child, struct bca *bcp)
648 {
649 uint_t l1_icache_size, l1_icache_line_size;
650 uint_t l2_cache_size, l2_cache_line_size, l2_cache_assoc;
651 uint_t l2_cache_share;
652 uint_t pcd_cache_size;
653 uint_t coreid, impl;
654 spcd_t *pcd;
655 char *compatible;
656 int dimms;
657 int i;
658
659 pcd = bcp->pcd;
660 coreid = bcp->coreid;
661 impl = bcp->impl;
662
663 ASSERT(IS_JAGUAR(impl) || IS_PANTHER(impl));
664
665 /*
666 * Get the External Cache Size from the Common PCD.
667 */
668 pcd_cache_size = pcd->spcd_cache * 0x100000;
669
670 switch (impl) {
671 case JAGUAR_IMPL:
672 compatible = "SUNW,UltraSPARC-IV";
673 l1_icache_size = CH_ICACHE_SIZE;
674 l1_icache_line_size = CH_ICACHE_LSIZE;
675 l2_cache_assoc = CHP_ECACHE_NWAY;
676
677 /*
678 * Jaguar has no logical sharing of L2 cache, so the sharing
679 * bit-map will represent this core only.
680 */
681 l2_cache_share = coreid ? 0x2 : 0x1;
682
683 /*
684 * Jaguar has a split ecache, so the total ecache must be
685 * divided in half to get the ecache for the individual core.
686 */
687 l2_cache_size = pcd_cache_size / 2;
688
689 switch (l2_cache_size) {
690 case JG_ECACHE_4M_SIZE:
691 l2_cache_line_size = 64;
692 break;
693 case JG_ECACHE_8M_SIZE:
694 l2_cache_line_size = 128;
695 break;
696 default:
697 GPTWO_DEBUG1(1, CE_CONT, "set_cpu_us4_props: "
698 "invalid l2_cache-size 0x%x\n", l2_cache_size);
699 return (DDI_WALK_ERROR);
700 }
701 break;
702 case PANTHER_IMPL:
703 ASSERT(pcd_cache_size == PN_L3_SIZE);
704 compatible = "SUNW,UltraSPARC-IV+";
705 l1_icache_size = PN_ICACHE_SIZE;
706 l1_icache_line_size = PN_ICACHE_LSIZE;
707 l2_cache_size = PN_L2_SIZE;
708 l2_cache_line_size = PN_L2_LINESIZE;
709 l2_cache_assoc = PN_ECACHE_NWAY;
710
711 /*
712 * For Panther, the L2 and L3 caches are logically shared by
713 * all enabled cores, so the sharing bit-map will represent
714 * all enabled cores. Panther split-mode is still considered
715 * shared.
716 *
717 * Check the PCD status to determine enabled cores.
718 */
719 ASSERT(pcd->spcd_ptype == SAFPTYPE_CPU);
720 l2_cache_share = 0;
721 for (i = 0; i < AGENTS_PER_PORT; i++) {
722 if (pcd->spcd_agent[i] == SPCD_RSV_PASS) {
723 l2_cache_share |= (1 << i);
724 }
725 }
726
727 break;
728 default:
729 GPTWO_DEBUG1(1, CE_CONT, "set_cpu_us4_props: invalid "
730 "implementation=0x%x\n", impl);
731 return (DDI_WALK_ERROR);
732 }
733
734 if (ndi_prop_update_string(DDI_DEV_T_NONE, new_child,
735 "name", "cpu") != DDI_SUCCESS) {
736 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us4_props: failed "
737 "to create name property\n");
738 return (DDI_WALK_ERROR);
739 }
740
741 if (ndi_prop_update_string(DDI_DEV_T_NONE, new_child,
742 "compatible", compatible) != DDI_SUCCESS) {
743 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us4_props: failed "
744 "to create compatible property\n");
745 return (DDI_WALK_ERROR);
746 }
747
748 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child,
749 "reg", coreid) != DDI_SUCCESS) {
750 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us4_props: failed "
751 "to create reg property\n");
752 return (DDI_WALK_ERROR);
753 }
754
755 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child,
756 "l1-icache-size", l1_icache_size) != DDI_SUCCESS) {
757 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us4_props: failed "
758 "to create l1-icache-size property\n");
759 return (DDI_WALK_ERROR);
760 }
761
762 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child,
763 "l1-icache-line-size", l1_icache_line_size) != DDI_SUCCESS) {
764 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us4_props: failed "
765 "to create icache-line-size property\n");
766 return (DDI_WALK_ERROR);
767 }
768
769 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child,
770 "l1-icache-associativity", CH_ICACHE_NWAY) != DDI_SUCCESS) {
771 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us4_props: failed "
772 "to create l1-icache-associativity property\n");
773 return (DDI_WALK_ERROR);
774 }
775
776 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child,
777 "l1-dcache-size", CH_DCACHE_SIZE) != DDI_SUCCESS) {
778 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us4_props: failed "
779 "to create l1-dcache-size property\n");
780 return (DDI_WALK_ERROR);
781 }
782
783 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child,
784 "l1-dcache-line-size", CH_DCACHE_LSIZE) != DDI_SUCCESS) {
785 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us4_props: failed "
786 "to create dcache-line-size property\n");
787 return (DDI_WALK_ERROR);
788 }
789
790 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child,
791 "l1-dcache-associativity", CH_DCACHE_NWAY) != DDI_SUCCESS) {
792 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us4_props: failed "
793 "to create l1-dcache-associativity property\n");
794 return (DDI_WALK_ERROR);
795 }
796
797 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child,
798 "l2-cache-size", l2_cache_size) != DDI_SUCCESS) {
799 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us4_props: failed "
800 "to create l2-cache-size property\n");
801 return (DDI_WALK_ERROR);
802 }
803
804 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child,
805 "l2-cache-line-size", l2_cache_line_size) != DDI_SUCCESS) {
806 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us4_props: failed "
807 "to create l2_cache-line-size property\n");
808 return (DDI_WALK_ERROR);
809 }
810
811 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child,
812 "l2-cache-associativity", l2_cache_assoc) != DDI_SUCCESS) {
813 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us4_props: failed "
814 "to create l2-cache-associativity property\n");
815 return (DDI_WALK_ERROR);
816 }
817
818 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child,
819 "l2-cache-sharing", l2_cache_share) != DDI_SUCCESS) {
820 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us4_props: failed "
821 "to create l2-cache-sharing property\n");
822 return (DDI_WALK_ERROR);
823 }
824
825 /*
826 * Create the ecache-dimm-label property.
827 */
828 dimms = 0;
829
830 while ((pcd->sprd_ecache_dimm_label[dimms] != NULL) &&
831 (dimms < MAX_DIMMS_PER_PORT))
832 dimms++;
833
834 if (dimms) {
835 (void) ndi_prop_update_string_array(DDI_DEV_T_NONE, new_child,
836 "ecache-dimm-label", (char **)pcd->sprd_ecache_dimm_label,
837 dimms);
838 }
839
840 if (IS_PANTHER(impl)) {
841 int l3_cache_share = l2_cache_share;
842
843 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child,
844 "l3-cache-size", PN_L3_SIZE) != DDI_SUCCESS) {
845 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us4_props: "
846 "failed to create l3-cache-size property\n");
847 return (DDI_WALK_ERROR);
848 }
849
850 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child,
851 "l3-cache-line-size", PN_L3_LINESIZE) != DDI_SUCCESS) {
852 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us4_props: "
853 "failed to create l3-cache-line-size property\n");
854 return (DDI_WALK_ERROR);
855 }
856
857 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child,
858 "l3-cache-associativity", PN_ECACHE_NWAY) != DDI_SUCCESS) {
859 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us4_props: "
860 "failed to create l3-cache-associativity "
861 "property\n");
862 return (DDI_WALK_ERROR);
863 }
864
865 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child,
866 "l3-cache-sharing", l3_cache_share) != DDI_SUCCESS) {
867 GPTWO_DEBUG0(1, CE_CONT, "set_cpu_us4_props: "
868 "failed to create l3-cache-sharing property\n");
869 return (DDI_WALK_ERROR);
870 }
871 }
872
873 return (DDI_WALK_TERMINATE);
874 }
875
876 static dev_info_t *
gptwocfg_create_mc_node(dev_info_t * ap,spcd_t * pcd,uint_t portid)877 gptwocfg_create_mc_node(dev_info_t *ap, spcd_t *pcd, uint_t portid)
878 {
879 struct bca arg;
880 devi_branch_t b = {0};
881
882 arg.pcd = pcd;
883 arg.portid = portid;
884 arg.cpuid = portid;
885 arg.new_child = NULL;
886
887 b.arg = &arg;
888 b.type = DEVI_BRANCH_SID;
889 b.create.sid_branch_create = set_mc_props;
890 b.devi_branch_callback = get_new_child;
891
892 if (e_ddi_branch_create(ap, &b, NULL, 0))
893 return (NULL);
894
895 return (arg.new_child);
896 }
897
898 /*ARGSUSED*/
899 static int
set_mc_props(dev_info_t * new_child,void * arg,uint_t flags)900 set_mc_props(dev_info_t *new_child, void *arg, uint_t flags)
901 {
902 struct bca *bcp = arg;
903 gptwo_regspec_t reg;
904 int banks, dimms;
905 spcd_t *pcd = bcp->pcd;
906 uint_t portid = bcp->portid;
907 uint_t cpuid = bcp->cpuid;
908
909 GPTWO_DEBUG3(1, CE_CONT, "set_mc_props: ap=0x%lx portid=0x%x "
910 "cpuid=0x%x\n", ddi_get_parent(new_child), portid, cpuid);
911
912 if (ndi_prop_update_string(DDI_DEV_T_NONE, new_child,
913 "name", "memory-controller") != DDI_SUCCESS) {
914 GPTWO_DEBUG0(1, CE_CONT, "set_mc_props: failed "
915 "to create name property\n");
916 return (DDI_WALK_ERROR);
917 }
918
919 if (ndi_prop_update_string(DDI_DEV_T_NONE, new_child,
920 "compatible", "SUNW,UltraSPARC-III,mc") != DDI_SUCCESS) {
921 GPTWO_DEBUG0(1, CE_CONT, "set_mc_props: failed "
922 "to create compatible property\n");
923 return (DDI_WALK_ERROR);
924 }
925
926 if (ndi_prop_update_string(DDI_DEV_T_NONE, new_child,
927 "device_type", "memory-controller") != DDI_SUCCESS) {
928 GPTWO_DEBUG0(1, CE_CONT, "set_mc_props: failed "
929 "to create device_type property\n");
930 return (DDI_WALK_ERROR);
931 }
932
933 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child,
934 "portid", portid) != DDI_SUCCESS) {
935 GPTWO_DEBUG0(1, CE_CONT, "set_mc_props: failed "
936 "to create portid property\n");
937 return (DDI_WALK_ERROR);
938 }
939
940 if (ndi_prop_update_int(DDI_DEV_T_NONE, new_child,
941 "cpuid", cpuid) != DDI_SUCCESS) {
942 GPTWO_DEBUG0(1, CE_CONT, "set_mc_props: failed "
943 "to create cpuid property\n");
944 return (DDI_WALK_ERROR);
945 }
946
947 reg.gptwo_phys_hi = 0x400 | (portid >> 9);
948 reg.gptwo_phys_low = (portid << 23) | 0x400000;
949 reg.gptwo_size_hi = 0;
950 reg.gptwo_size_low = 0x48;
951
952 if (ndi_prop_update_int_array(DDI_DEV_T_NONE,
953 new_child, "reg", (int *)®,
954 sizeof (gptwo_regspec_t) / sizeof (int)) != DDI_SUCCESS) {
955 GPTWO_DEBUG0(1, CE_CONT, "set_mc_props: failed "
956 "to create reg property\n");
957 return (DDI_WALK_ERROR);
958 }
959
960 if (pcd->memory_layout) {
961 if (ndi_prop_update_byte_array(DDI_DEV_T_NONE,
962 new_child, "memory-layout", (uchar_t *)pcd->memory_layout,
963 pcd->memory_layout_size) != DDI_SUCCESS) {
964
965 GPTWO_DEBUG0(1, CE_CONT, "set_mc_props: failed "
966 "to create memory-layout property\n");
967
968 return (DDI_WALK_ERROR);
969 }
970 }
971
972 /*
973 * Create the bank-status property.
974 */
975 banks = 0;
976
977 while ((pcd->sprd_bank_rsv[banks] != NULL) &&
978 (banks < MAX_BANKS_PER_PORT))
979 banks++;
980
981 if (banks) {
982 (void) ndi_prop_update_string_array(DDI_DEV_T_NONE, new_child,
983 "bank-status", (char **)pcd->sprd_bank_rsv, banks);
984 }
985
986 /*
987 * Create the dimm-status property.
988 */
989 dimms = 0;
990
991 while ((pcd->sprd_dimm[dimms] != NULL) &&
992 (dimms < MAX_DIMMS_PER_PORT))
993 dimms++;
994
995 if (dimms) {
996 (void) ndi_prop_update_string_array(DDI_DEV_T_NONE, new_child,
997 "dimm-status", (char **)pcd->sprd_dimm, dimms);
998 }
999
1000
1001 return (DDI_WALK_TERMINATE);
1002 }
1003
1004 /*ARGSUSED*/
1005 static void
get_new_child(dev_info_t * rdip,void * arg,uint_t flags)1006 get_new_child(dev_info_t *rdip, void *arg, uint_t flags)
1007 {
1008 struct bca *bcp = arg;
1009
1010 bcp->new_child = rdip;
1011
1012 }
1013
1014 #ifdef DEBUG
1015 static void
debug(char * fmt,uintptr_t a1,uintptr_t a2,uintptr_t a3,uintptr_t a4,uintptr_t a5)1016 debug(char *fmt, uintptr_t a1, uintptr_t a2, uintptr_t a3,
1017 uintptr_t a4, uintptr_t a5)
1018 {
1019 cmn_err(CE_CONT, fmt, a1, a2, a3, a4, a5);
1020 }
1021 #endif
1022