/* * 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); } }
static void check_cpus_ver(void) { int i; int impl, cpuid = getprocessorid(); int min_supported_rev; ASSERT(cpunodes[cpuid].nodeid != 0); impl = cpunodes[cpuid].implementation; switch (impl) { default: min_supported_rev = 0; break; case SPITFIRE_IMPL: min_supported_rev = SPITFIRE_MINREV_SUPPORTED; break; case CHEETAH_IMPL: min_supported_rev = CHEETAH_MINREV_SUPPORTED; break; } for (i = 0; i < NCPU; i++) { if (cpunodes[i].nodeid == 0) continue; if (IS_SPITFIRE(impl)) { if (cpunodes[i].version < min_supported_rev) { cmn_err(CE_PANIC, "UltraSPARC versions older " "than %d.%d are no longer supported " "(cpu #%d)", SPITFIRE_MAJOR_VERSION(min_supported_rev), SPITFIRE_MINOR_VERSION(min_supported_rev), i); } /* * Min supported rev is 2.1 but we've seen problems * with that so we still want to warn if we see one. */ if (cpunodes[i].version < 0x22) { cmn_err(CE_WARN, "UltraSPARC versions older than " "2.2 are not supported (cpu #%d)", i); #ifdef SF_ERRATA_30 /* call causes fp-disabled */ spitfire_call_bug = 1; #endif /* SF_ERRATA_30 */ } } #ifdef SF_V9_TABLE_28 /* fp over/underflow traps may cause wrong fsr.cexc */ if (IS_SPITFIRE(impl) || IS_BLACKBIRD(impl)) spitfire_bb_fsr_bug = 1; #endif /* SF_V9_TABLE_28 */ if (IS_CHEETAH(impl)) { if (cpunodes[i].version < min_supported_rev) { cmn_err(CE_PANIC, "UltraSPARC-III versions " "older than %d.%d are no longer supported " "(cpu #%d)", CHEETAH_MAJOR_VERSION(min_supported_rev), CHEETAH_MINOR_VERSION(min_supported_rev), i); } } #ifdef JALAPENO_ERRATA_85 if (IS_JALAPENO(impl) && (cpunodes[i].version < 0x24)) { jp_errata_85_allow_slow_scrub = 0; jp_errata_85_enable = 1; } #endif /* JALAPENO_ERRATA_85 */ } }
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++; }
/* * 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++; }
void display_cpus(Board_node *board) { Prom_node *cpu; uint_t freq; int ecache_size; int *l3_shares; int *mid; int *impl; int *mask; int *coreid; char fru_prev = 'X'; /* Valid frus are 'A','B' */ int mid_prev; int ecache_size_prev = 0; char fru_name; /* * 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")) { mid = (int *)get_prop_val(find_prop(cpu, "portid")); if (mid == NULL) mid = (int *)get_prop_val(find_prop(cpu, "cpuid")); freq = HZ_TO_MHZ(get_cpu_freq(cpu)); ecache_size = get_ecache_size(cpu); impl = (int *)get_prop_val(find_prop(cpu, "implementation#")); mask = (int *)get_prop_val(find_prop(cpu, "mask#")); l3_shares = (int *)get_prop_val(find_prop(cpu, "l3-cache-sharing")); /* Do not display a failed CPU node */ if ((impl == NULL) || (freq == 0) || (node_failed(cpu))) continue; fru_name = CHERRYSTONE_GETSLOT_LABEL(*mid); if (CPU_IMPL_IS_CMP(*impl)) { coreid = (int *)get_prop_val(find_prop(cpu, "reg")); if (coreid == NULL) { continue; } if ((fru_prev == 'X') || ((fru_prev != 'X') && (fru_name != fru_prev))) { fru_prev = fru_name; mid_prev = *mid; ecache_size_prev = ecache_size; continue; } else { /* * Some CMP chips have a split E$, * so the size for both cores is added * together to get the total size for * the chip. * * Still, other CMP chips have E$ (L3) * which is logically shared, so the * total size is equal to the core size. */ if ((l3_shares == NULL) || ((l3_shares != NULL) && MULTIPLE_BITS_SET(*l3_shares))) { ecache_size += ecache_size_prev; } ecache_size_prev = 0; fru_prev = 'X'; } } log_printf(" %c", fru_name); /* CPU Module ID */ if (CPU_IMPL_IS_CMP(*impl)) { log_printf("%3d,%3d ", mid_prev, *mid, 0); } else log_printf(" %2d ", *mid); /* Running frequency */ log_printf("%4u", freq); if (ecache_size == 0) log_printf(" N/A "); else log_printf(" %4.1f ", (float)ecache_size / (float)(1<<20)); /* Implementation */ if (impl == NULL) { log_printf(dgettext(TEXT_DOMAIN, " N/A ")); } else { if (IS_CHEETAH(*impl)) log_printf(dgettext(TEXT_DOMAIN, "US-III ")); else if (IS_CHEETAH_PLUS(*impl)) log_printf(dgettext(TEXT_DOMAIN, "US-III+ ")); else if (IS_JAGUAR(*impl)) log_printf(dgettext(TEXT_DOMAIN, "US-IV ")); else if (IS_PANTHER(*impl)) log_printf(dgettext(TEXT_DOMAIN, "US-IV+ ")); else log_printf("%-6x ", *impl); } /* CPU Mask */ if (mask == NULL) { log_printf(dgettext(TEXT_DOMAIN, " N/A\n")); } else { log_printf(dgettext(TEXT_DOMAIN, " %d.%d\n"), (*mask >> 4) & 0xf, *mask & 0xf); } } }