Exemplo n.º 1
0
/*
 * 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);
		}
	}
Exemplo n.º 2
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 */
    }
}
Exemplo n.º 3
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++;
}
Exemplo n.º 4
0
/*
 * 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++;
}
Exemplo n.º 5
0
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);
		}
	}
}