/* * A hotplug version of fill_cpu(). (Doesn't assume that there's a node * in the PROM device tree for this CPU.) We still need the PROM version * since it is called very early in the boot cycle before (before * setup_ddi()). Sigh...someday this will all be cleaned up. */ void fill_cpu_ddi(dev_info_t *dip) { extern int cpu_get_cpu_unum(int, char *, int, int *); struct cpu_node *cpunode; processorid_t cpuid; int portid; int len = OBP_MAXPROPNAME; int tlbsize; dev_info_t *cmpnode; char namebuf[OBP_MAXPROPNAME], unum[UNUM_NAMLEN]; char *namebufp; char dev_type[OBP_MAXPROPNAME]; if ((portid = get_portid_ddi(dip, &cmpnode)) == -1) { cmn_err(CE_PANIC, "portid not found"); } if ((cpuid = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "cpuid", -1)) == -1) { cpuid = portid; } if (cpuid < 0 || cpuid >= NCPU) { cmn_err(CE_PANIC, "cpu dip %p: cpuid %d out of range", (void *)dip, cpuid); return; } cpunode = &cpunodes[cpuid]; cpunode->portid = portid; cpunode->nodeid = ddi_get_nodeid(dip); if (cmpnode != NULL) { /* * For the CMT case, the parent "core" node contains * properties needed below, use it instead of the * cpu node. */ if ((ddi_prop_op(DDI_DEV_T_ANY, cmpnode, PROP_LEN_AND_VAL_BUF, DDI_PROP_DONTPASS, "device_type", (caddr_t)dev_type, &len) == DDI_PROP_SUCCESS) && (strcmp(dev_type, "core") == 0)) dip = cmpnode; } if (cpu_get_cpu_unum(cpuid, unum, UNUM_NAMLEN, &len) != 0) { cpunode->fru_fmri[0] = '\0'; } else { (void) snprintf(cpunode->fru_fmri, sizeof (cpunode->fru_fmri), "%s%s", CPU_FRU_FMRI, unum); } len = sizeof (namebuf); (void) ddi_prop_op(DDI_DEV_T_ANY, dip, PROP_LEN_AND_VAL_BUF, DDI_PROP_DONTPASS, (cmpnode ? "compatible" : "name"), (caddr_t)namebuf, &len); namebufp = namebuf; if (strncmp(namebufp, "SUNW,", 5) == 0) namebufp += 5; else if (strncmp(namebufp, "FJSV,", 5) == 0) namebufp += 5; (void) strcpy(cpunode->name, namebufp); cpunode->implementation = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "implementation#", 0); cpunode->version = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "mask#", 0); if (IS_CHEETAH(cpunode->implementation)) { /* remap mask reg */ cpunode->version = REMAP_CHEETAH_MASK(cpunode->version); } cpunode->clock_freq = (uint32_t)ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "clock-frequency", 0); ASSERT(cpunode->clock_freq != 0); /* * Compute scaling factor based on rate of %tick. This is used * to convert from ticks derived from %tick to nanoseconds. See * comment in sun4u/sys/clock.h for details. */ cpunode->tick_nsec_scale = (uint_t)(((uint64_t)NANOSEC << (32 - TICK_NSEC_SHIFT)) / cpunode->clock_freq); tlbsize = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "#itlb-entries", 0); ASSERT(tlbsize < USHRT_MAX); /* since we cast it */ cpunode->itlb_size = (ushort_t)tlbsize; tlbsize = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "#dtlb-entries", 0); ASSERT(tlbsize < USHRT_MAX); /* since we cast it */ cpunode->dtlb_size = (ushort_t)tlbsize; if (cmpnode != NULL) { /* * If the CPU has a level 3 cache, then that is it's * external cache. Otherwise the external cache must * be the level 2 cache. */ cpunode->ecache_size = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "l3-cache-size", 0); if (cpunode->ecache_size == 0) cpunode->ecache_size = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "l2-cache-size", 0); ASSERT(cpunode->ecache_size != 0); cpunode->ecache_linesize = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "l3-cache-line-size", 0); if (cpunode->ecache_linesize == 0) cpunode->ecache_linesize = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "l2-cache-line-size", 0); ASSERT(cpunode->ecache_linesize != 0); cpunode->ecache_associativity = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "l2-cache-associativity", 0); ASSERT(cpunode->ecache_associativity != 0); cmp_add_cpu(portid, cpuid); } else { cpunode->ecache_size = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "ecache-size", 0); ASSERT(cpunode->ecache_size != 0); cpunode->ecache_linesize = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "ecache-line-size", 0); ASSERT(cpunode->ecache_linesize != 0); cpunode->ecache_associativity = ddi_prop_get_int(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "ecache-associativity", 0); ASSERT(cpunode->ecache_associativity != 0); } /* by default set msram to non-mirrored one */ cpunode->msram = ECACHE_CPU_NON_MIRROR; if (ddi_prop_exists(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "msram")) { cpunode->msram = ECACHE_CPU_MIRROR; } else if (ddi_prop_exists(DDI_DEV_T_ANY, dip, DDI_PROP_DONTPASS, "msram-observed")) { cpunode->msram = ECACHE_CPU_MIRROR; } ASSERT(ncpunode > 0); /* fiximp not req'd */ cpunode->ecache_setsize = cpunode->ecache_size / cpunode->ecache_associativity; adj_ecache_setsize(cpunode->ecache_setsize); ncpunode++; }
/* * Display the CPUs present on this board. */ void display_cpus(Board_node *board) { Prom_node *cpu; /* * display the CPUs' operating frequency, cache size, impl. field * and mask revision. */ for (cpu = dev_find_type(board->nodes, "cpu"); cpu != NULL; cpu = dev_next_type(cpu, "cpu")) { int freq; /* CPU clock frequency */ int ecache_size; /* External cache size */ int *mid; int *impl; int *mask, decoded_mask; mid = (int *)get_prop_val(find_prop(cpu, "upa-portid")); if (mid == NULL) { mid = (int *)get_prop_val(find_prop(cpu, "portid")); } freq = (get_cpu_freq(cpu) + 500000) / 1000000; ecache_size = get_ecache_size(cpu); impl = (int *)get_prop_val(find_prop(cpu, "implementation#")); mask = (int *)get_prop_val(find_prop(cpu, "mask#")); /* Do not display a failed CPU node */ if ((freq != 0) && (node_failed(cpu) == 0)) { /* Board number */ display_boardnum(board->board_num); /* CPU MID */ log_printf(" %2d ", *mid, 0); /* Module number */ display_mid(*mid); /* Running frequency */ log_printf(" %3d ", freq, 0); /* Ecache size */ if (ecache_size == 0) log_printf(" %3s ", "N/A", 0); else log_printf(" %4.1f ", (float)ecache_size / (float)(1<<20), 0); /* Implementation */ if (impl == NULL) { log_printf("%6s ", "N/A", 0); } else { switch (*impl) { case SPITFIRE_IMPL: log_printf("%-6s ", "US-I", 0); break; case BLACKBIRD_IMPL: log_printf("%-6s ", "US-II", 0); break; case CHEETAH_IMPL: log_printf("%-6s ", "US-III", 0); break; case CHEETAH_PLUS_IMPL: log_printf("%-7s ", "US-III+", 0); break; case JAGUAR_IMPL: log_printf("%-6s ", "US-IV", 0); break; default: log_printf("%-6x ", *impl, 0); break; } } /* CPU Mask */ if (mask == NULL) { log_printf(" %3s", "N/A", 0); } else { if ((impl) && IS_CHEETAH(*impl)) decoded_mask = REMAP_CHEETAH_MASK(*mask); else decoded_mask = *mask; log_printf(" %d.%d", (decoded_mask >> 4) & 0xf, decoded_mask & 0xf, 0); } log_printf("\n", 0); } }
void fill_cpu(pnode_t node) { extern int cpu_get_cpu_unum(int, char *, int, int *); struct cpu_node *cpunode; processorid_t cpuid; int portid; int tlbsize; int size; uint_t clk_freq; pnode_t cmpnode; char namebuf[OBP_MAXPROPNAME], unum[UNUM_NAMLEN]; char *namebufp; int proplen; if ((portid = get_portid(node, &cmpnode)) == -1) { cmn_err(CE_PANIC, "portid not found"); } if (GETPROP(node, "cpuid", (caddr_t)&cpuid) == -1) { cpuid = portid; } if (cpuid < 0 || cpuid >= NCPU) { cmn_err(CE_PANIC, "cpu node %x: cpuid %d out of range", node, cpuid); return; } cpunode = &cpunodes[cpuid]; cpunode->portid = portid; cpunode->nodeid = node; if (cpu_get_cpu_unum(cpuid, unum, UNUM_NAMLEN, &size) != 0) { cpunode->fru_fmri[0] = '\0'; } else { (void) snprintf(cpunode->fru_fmri, sizeof (cpunode->fru_fmri), "%s%s", CPU_FRU_FMRI, unum); } if (cmpnode) { /* * For the CMT case, the parent "core" node contains * properties needed below, use it instead of the * cpu node. */ if ((GETPROP(cmpnode, "device_type", namebuf) > 0) && (strcmp(namebuf, "core") == 0)) { node = cmpnode; } } (void) GETPROP(node, (cmpnode ? "compatible" : "name"), namebuf); /* Make sure CPU name is within boundary and NULL terminated */ proplen = GETPROPLEN(node, (cmpnode ? "compatible" : "name")); ASSERT(proplen > 0 && proplen <= OBP_MAXPROPNAME); if (proplen >= OBP_MAXPROPNAME) proplen = OBP_MAXPROPNAME - 1; namebuf[proplen] = '\0'; namebufp = namebuf; if (strncmp(namebufp, "SUNW,", 5) == 0) namebufp += 5; else if (strncmp(namebufp, "FJSV,", 5) == 0) namebufp += 5; (void) strcpy(cpunode->name, namebufp); (void) GETPROP(node, "implementation#", (caddr_t)&cpunode->implementation); (void) GETPROP(node, "mask#", (caddr_t)&cpunode->version); if (IS_CHEETAH(cpunode->implementation)) { /* remap mask reg */ cpunode->version = REMAP_CHEETAH_MASK(cpunode->version); } if (GETPROP(node, "clock-frequency", (caddr_t)&clk_freq) == -1) { /* * If we didn't find it in the CPU node, look in the root node. */ pnode_t root = prom_nextnode((pnode_t)0); if (GETPROP(root, "clock-frequency", (caddr_t)&clk_freq) == -1) clk_freq = 0; } cpunode->clock_freq = clk_freq; ASSERT(cpunode->clock_freq != 0); /* * Compute scaling factor based on rate of %tick. This is used * to convert from ticks derived from %tick to nanoseconds. See * comment in sun4u/sys/clock.h for details. */ cpunode->tick_nsec_scale = (uint_t)(((uint64_t)NANOSEC << (32 - TICK_NSEC_SHIFT)) / cpunode->clock_freq); (void) GETPROP(node, "#itlb-entries", (caddr_t)&tlbsize); ASSERT(tlbsize < USHRT_MAX); /* since we cast it */ cpunode->itlb_size = (ushort_t)tlbsize; (void) GETPROP(node, "#dtlb-entries", (caddr_t)&tlbsize); ASSERT(tlbsize < USHRT_MAX); /* since we cast it */ cpunode->dtlb_size = (ushort_t)tlbsize; if (cmpnode != OBP_NONODE) { /* * If the CPU has a level 3 cache, then it will be the * external cache. Otherwise the level 2 cache is the * external cache. */ size = 0; (void) GETPROP(node, "l3-cache-size", (caddr_t)&size); if (size <= 0) (void) GETPROP(node, "l2-cache-size", (caddr_t)&size); ASSERT(size != 0); cpunode->ecache_size = size; size = 0; (void) GETPROP(node, "l3-cache-line-size", (caddr_t)&size); if (size <= 0) (void) GETPROP(node, "l2-cache-line-size", (caddr_t)&size); ASSERT(size != 0); cpunode->ecache_linesize = size; size = 0; (void) GETPROP(node, "l2-cache-associativity", (caddr_t)&size); ASSERT(size != 0); cpunode->ecache_associativity = size; cmp_add_cpu(portid, cpuid); } else { size = 0; (void) GETPROP(node, "ecache-size", (caddr_t)&size); ASSERT(size != 0); cpunode->ecache_size = size; size = 0; (void) GETPROP(node, "ecache-line-size", (caddr_t)&size); ASSERT(size != 0); cpunode->ecache_linesize = size; size = 0; (void) GETPROP(node, "ecache-associativity", (caddr_t)&size); ASSERT(size != 0); cpunode->ecache_associativity = size; } /* by default set msram to non-mirrored one */ cpunode->msram = ECACHE_CPU_NON_MIRROR; if (GETPROPLEN(node, "msram") != -1) { cpunode->msram = ECACHE_CPU_MIRROR; } if (GETPROPLEN(node, "msram-observed") != -1) { cpunode->msram = ECACHE_CPU_MIRROR; } if (ncpunode == 0) { cpu_fiximp(node); } cpunode->ecache_setsize = cpunode->ecache_size / cpunode->ecache_associativity; adj_ecache_setsize(cpunode->ecache_setsize); ncpunode++; }