예제 #1
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++;
}
예제 #2
0
파일: cpu.c 프로젝트: andreiw/polaris
/*
 * 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);
		}
	}
예제 #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++;
}