mdesc.c

来自「linux 内核源代码」· C语言 代码 · 共 913 行 · 第 1/2 页

C
913
字号
	return NULL;}EXPORT_SYMBOL(mdesc_get_property);u64 mdesc_next_arc(struct mdesc_handle *hp, u64 from, const char *arc_type){	struct mdesc_elem *ep, *base = node_block(&hp->mdesc);	const char *names = name_block(&hp->mdesc);	u64 last_node = hp->mdesc.node_sz / 16;	if (from == MDESC_NODE_NULL || from >= last_node)		return MDESC_NODE_NULL;	ep = base + from;	ep++;	for (; ep->tag != MD_NODE_END; ep++) {		if (ep->tag != MD_PROP_ARC)			continue;		if (strcmp(names + ep->name_offset, arc_type))			continue;		return ep - base;	}	return MDESC_NODE_NULL;}EXPORT_SYMBOL(mdesc_next_arc);u64 mdesc_arc_target(struct mdesc_handle *hp, u64 arc){	struct mdesc_elem *ep, *base = node_block(&hp->mdesc);	ep = base + arc;	return ep->d.val;}EXPORT_SYMBOL(mdesc_arc_target);const char *mdesc_node_name(struct mdesc_handle *hp, u64 node){	struct mdesc_elem *ep, *base = node_block(&hp->mdesc);	const char *names = name_block(&hp->mdesc);	u64 last_node = hp->mdesc.node_sz / 16;	if (node == MDESC_NODE_NULL || node >= last_node)		return NULL;	ep = base + node;	if (ep->tag != MD_NODE)		return NULL;	return names + ep->name_offset;}EXPORT_SYMBOL(mdesc_node_name);static void __init report_platform_properties(void){	struct mdesc_handle *hp = mdesc_grab();	u64 pn = mdesc_node_by_name(hp, MDESC_NODE_NULL, "platform");	const char *s;	const u64 *v;	if (pn == MDESC_NODE_NULL) {		prom_printf("No platform node in machine-description.\n");		prom_halt();	}	s = mdesc_get_property(hp, pn, "banner-name", NULL);	printk("PLATFORM: banner-name [%s]\n", s);	s = mdesc_get_property(hp, pn, "name", NULL);	printk("PLATFORM: name [%s]\n", s);	v = mdesc_get_property(hp, pn, "hostid", NULL);	if (v)		printk("PLATFORM: hostid [%08lx]\n", *v);	v = mdesc_get_property(hp, pn, "serial#", NULL);	if (v)		printk("PLATFORM: serial# [%08lx]\n", *v);	v = mdesc_get_property(hp, pn, "stick-frequency", NULL);	printk("PLATFORM: stick-frequency [%08lx]\n", *v);	v = mdesc_get_property(hp, pn, "mac-address", NULL);	if (v)		printk("PLATFORM: mac-address [%lx]\n", *v);	v = mdesc_get_property(hp, pn, "watchdog-resolution", NULL);	if (v)		printk("PLATFORM: watchdog-resolution [%lu ms]\n", *v);	v = mdesc_get_property(hp, pn, "watchdog-max-timeout", NULL);	if (v)		printk("PLATFORM: watchdog-max-timeout [%lu ms]\n", *v);	v = mdesc_get_property(hp, pn, "max-cpus", NULL);	if (v)		printk("PLATFORM: max-cpus [%lu]\n", *v);#ifdef CONFIG_SMP	{		int max_cpu, i;		if (v) {			max_cpu = *v;			if (max_cpu > NR_CPUS)				max_cpu = NR_CPUS;		} else {			max_cpu = NR_CPUS;		}		for (i = 0; i < max_cpu; i++)			cpu_set(i, cpu_possible_map);	}#endif	mdesc_release(hp);}static void __devinit fill_in_one_cache(cpuinfo_sparc *c,					struct mdesc_handle *hp,					u64 mp){	const u64 *level = mdesc_get_property(hp, mp, "level", NULL);	const u64 *size = mdesc_get_property(hp, mp, "size", NULL);	const u64 *line_size = mdesc_get_property(hp, mp, "line-size", NULL);	const char *type;	int type_len;	type = mdesc_get_property(hp, mp, "type", &type_len);	switch (*level) {	case 1:		if (of_find_in_proplist(type, "instn", type_len)) {			c->icache_size = *size;			c->icache_line_size = *line_size;		} else if (of_find_in_proplist(type, "data", type_len)) {			c->dcache_size = *size;			c->dcache_line_size = *line_size;		}		break;	case 2:		c->ecache_size = *size;		c->ecache_line_size = *line_size;		break;	default:		break;	}	if (*level == 1) {		u64 a;		mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_FWD) {			u64 target = mdesc_arc_target(hp, a);			const char *name = mdesc_node_name(hp, target);			if (!strcmp(name, "cache"))				fill_in_one_cache(c, hp, target);		}	}}static void __devinit mark_core_ids(struct mdesc_handle *hp, u64 mp,				    int core_id){	u64 a;	mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_BACK) {		u64 t = mdesc_arc_target(hp, a);		const char *name;		const u64 *id;		name = mdesc_node_name(hp, t);		if (!strcmp(name, "cpu")) {			id = mdesc_get_property(hp, t, "id", NULL);			if (*id < NR_CPUS)				cpu_data(*id).core_id = core_id;		} else {			u64 j;			mdesc_for_each_arc(j, hp, t, MDESC_ARC_TYPE_BACK) {				u64 n = mdesc_arc_target(hp, j);				const char *n_name;				n_name = mdesc_node_name(hp, n);				if (strcmp(n_name, "cpu"))					continue;				id = mdesc_get_property(hp, n, "id", NULL);				if (*id < NR_CPUS)					cpu_data(*id).core_id = core_id;			}		}	}}static void __devinit set_core_ids(struct mdesc_handle *hp){	int idx;	u64 mp;	idx = 1;	mdesc_for_each_node_by_name(hp, mp, "cache") {		const u64 *level;		const char *type;		int len;		level = mdesc_get_property(hp, mp, "level", NULL);		if (*level != 1)			continue;		type = mdesc_get_property(hp, mp, "type", &len);		if (!of_find_in_proplist(type, "instn", len))			continue;		mark_core_ids(hp, mp, idx);		idx++;	}}static void __devinit mark_proc_ids(struct mdesc_handle *hp, u64 mp,				    int proc_id){	u64 a;	mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_BACK) {		u64 t = mdesc_arc_target(hp, a);		const char *name;		const u64 *id;		name = mdesc_node_name(hp, t);		if (strcmp(name, "cpu"))			continue;		id = mdesc_get_property(hp, t, "id", NULL);		if (*id < NR_CPUS)			cpu_data(*id).proc_id = proc_id;	}}static void __devinit __set_proc_ids(struct mdesc_handle *hp,				     const char *exec_unit_name){	int idx;	u64 mp;	idx = 0;	mdesc_for_each_node_by_name(hp, mp, exec_unit_name) {		const char *type;		int len;		type = mdesc_get_property(hp, mp, "type", &len);		if (!of_find_in_proplist(type, "int", len) &&		    !of_find_in_proplist(type, "integer", len))			continue;		mark_proc_ids(hp, mp, idx);		idx++;	}}static void __devinit set_proc_ids(struct mdesc_handle *hp){	__set_proc_ids(hp, "exec_unit");	__set_proc_ids(hp, "exec-unit");}static void __devinit get_one_mondo_bits(const u64 *p, unsigned int *mask,					 unsigned char def){	u64 val;	if (!p)		goto use_default;	val = *p;	if (!val || val >= 64)		goto use_default;	*mask = ((1U << val) * 64U) - 1U;	return;use_default:	*mask = ((1U << def) * 64U) - 1U;}static void __devinit get_mondo_data(struct mdesc_handle *hp, u64 mp,				     struct trap_per_cpu *tb){	const u64 *val;	val = mdesc_get_property(hp, mp, "q-cpu-mondo-#bits", NULL);	get_one_mondo_bits(val, &tb->cpu_mondo_qmask, 7);	val = mdesc_get_property(hp, mp, "q-dev-mondo-#bits", NULL);	get_one_mondo_bits(val, &tb->dev_mondo_qmask, 7);	val = mdesc_get_property(hp, mp, "q-resumable-#bits", NULL);	get_one_mondo_bits(val, &tb->resum_qmask, 6);	val = mdesc_get_property(hp, mp, "q-nonresumable-#bits", NULL);	get_one_mondo_bits(val, &tb->nonresum_qmask, 2);}void __devinit mdesc_fill_in_cpu_data(cpumask_t mask){	struct mdesc_handle *hp = mdesc_grab();	u64 mp;	ncpus_probed = 0;	mdesc_for_each_node_by_name(hp, mp, "cpu") {		const u64 *id = mdesc_get_property(hp, mp, "id", NULL);		const u64 *cfreq = mdesc_get_property(hp, mp, "clock-frequency", NULL);		struct trap_per_cpu *tb;		cpuinfo_sparc *c;		int cpuid;		u64 a;		ncpus_probed++;		cpuid = *id;#ifdef CONFIG_SMP		if (cpuid >= NR_CPUS) {			printk(KERN_WARNING "Ignoring CPU %d which is "			       ">= NR_CPUS (%d)\n",			       cpuid, NR_CPUS);			continue;		}		if (!cpu_isset(cpuid, mask))			continue;#else		/* On uniprocessor we only want the values for the		 * real physical cpu the kernel booted onto, however		 * cpu_data() only has one entry at index 0.		 */		if (cpuid != real_hard_smp_processor_id())			continue;		cpuid = 0;#endif		c = &cpu_data(cpuid);		c->clock_tick = *cfreq;		tb = &trap_block[cpuid];		get_mondo_data(hp, mp, tb);		mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_FWD) {			u64 j, t = mdesc_arc_target(hp, a);			const char *t_name;			t_name = mdesc_node_name(hp, t);			if (!strcmp(t_name, "cache")) {				fill_in_one_cache(c, hp, t);				continue;			}			mdesc_for_each_arc(j, hp, t, MDESC_ARC_TYPE_FWD) {				u64 n = mdesc_arc_target(hp, j);				const char *n_name;				n_name = mdesc_node_name(hp, n);				if (!strcmp(n_name, "cache"))					fill_in_one_cache(c, hp, n);			}		}#ifdef CONFIG_SMP		cpu_set(cpuid, cpu_present_map);#endif		c->core_id = 0;		c->proc_id = -1;	}#ifdef CONFIG_SMP	sparc64_multi_core = 1;#endif	set_core_ids(hp);	set_proc_ids(hp);	smp_fill_in_sib_core_maps();	mdesc_release(hp);}static ssize_t mdesc_read(struct file *file, char __user *buf,			  size_t len, loff_t *offp){	struct mdesc_handle *hp = mdesc_grab();	int err;	if (!hp)		return -ENODEV;	err = hp->handle_size;	if (len < hp->handle_size)		err = -EMSGSIZE;	else if (copy_to_user(buf, &hp->mdesc, hp->handle_size))		err = -EFAULT;	mdesc_release(hp);	return err;}static const struct file_operations mdesc_fops = {	.read	= mdesc_read,	.owner	= THIS_MODULE,};static struct miscdevice mdesc_misc = {	.minor	= MISC_DYNAMIC_MINOR,	.name	= "mdesc",	.fops	= &mdesc_fops,};static int __init mdesc_misc_init(void){	return misc_register(&mdesc_misc);}__initcall(mdesc_misc_init);void __init sun4v_mdesc_init(void){	struct mdesc_handle *hp;	unsigned long len, real_len, status;	cpumask_t mask;	(void) sun4v_mach_desc(0UL, 0UL, &len);	printk("MDESC: Size is %lu bytes.\n", len);	hp = mdesc_alloc(len, &bootmem_mdesc_ops);	if (hp == NULL) {		prom_printf("MDESC: alloc of %lu bytes failed.\n", len);		prom_halt();	}	status = sun4v_mach_desc(__pa(&hp->mdesc), len, &real_len);	if (status != HV_EOK || real_len > len) {		prom_printf("sun4v_mach_desc fails, err(%lu), "			    "len(%lu), real_len(%lu)\n",			    status, len, real_len);		mdesc_free(hp);		prom_halt();	}	cur_mdesc = hp;	report_platform_properties();	cpus_setall(mask);	mdesc_fill_in_cpu_data(mask);}

⌨️ 快捷键说明

复制代码Ctrl + C
搜索代码Ctrl + F
全屏模式F11
增大字号Ctrl + =
减小字号Ctrl + -
显示快捷键?