• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* mdesc.c: Sun4V machine description handling.
2  *
3  * Copyright (C) 2007, 2008 David S. Miller <davem@davemloft.net>
4  */
5 #include <linux/kernel.h>
6 #include <linux/types.h>
7 #include <linux/memblock.h>
8 #include <linux/log2.h>
9 #include <linux/list.h>
10 #include <linux/slab.h>
11 #include <linux/mm.h>
12 #include <linux/miscdevice.h>
13 #include <linux/bootmem.h>
14 #include <linux/export.h>
15 
16 #include <asm/cpudata.h>
17 #include <asm/hypervisor.h>
18 #include <asm/mdesc.h>
19 #include <asm/prom.h>
20 #include <asm/uaccess.h>
21 #include <asm/oplib.h>
22 #include <asm/smp.h>
23 
24 /* Unlike the OBP device tree, the machine description is a full-on
25  * DAG.  An arbitrary number of ARCs are possible from one
26  * node to other nodes and thus we can't use the OBP device_node
27  * data structure to represent these nodes inside of the kernel.
28  *
29  * Actually, it isn't even a DAG, because there are back pointers
30  * which create cycles in the graph.
31  *
32  * mdesc_hdr and mdesc_elem describe the layout of the data structure
33  * we get from the Hypervisor.
34  */
35 struct mdesc_hdr {
36 	u32	version; /* Transport version */
37 	u32	node_sz; /* node block size */
38 	u32	name_sz; /* name block size */
39 	u32	data_sz; /* data block size */
40 	char	data[];
41 } __attribute__((aligned(16)));
42 
43 struct mdesc_elem {
44 	u8	tag;
45 #define MD_LIST_END	0x00
46 #define MD_NODE		0x4e
47 #define MD_NODE_END	0x45
48 #define MD_NOOP		0x20
49 #define MD_PROP_ARC	0x61
50 #define MD_PROP_VAL	0x76
51 #define MD_PROP_STR	0x73
52 #define MD_PROP_DATA	0x64
53 	u8	name_len;
54 	u16	resv;
55 	u32	name_offset;
56 	union {
57 		struct {
58 			u32	data_len;
59 			u32	data_offset;
60 		} data;
61 		u64	val;
62 	} d;
63 };
64 
65 struct mdesc_mem_ops {
66 	struct mdesc_handle *(*alloc)(unsigned int mdesc_size);
67 	void (*free)(struct mdesc_handle *handle);
68 };
69 
70 struct mdesc_handle {
71 	struct list_head	list;
72 	struct mdesc_mem_ops	*mops;
73 	void			*self_base;
74 	atomic_t		refcnt;
75 	unsigned int		handle_size;
76 	struct mdesc_hdr	mdesc;
77 };
78 
mdesc_handle_init(struct mdesc_handle * hp,unsigned int handle_size,void * base)79 static void mdesc_handle_init(struct mdesc_handle *hp,
80 			      unsigned int handle_size,
81 			      void *base)
82 {
83 	BUG_ON(((unsigned long)&hp->mdesc) & (16UL - 1));
84 
85 	memset(hp, 0, handle_size);
86 	INIT_LIST_HEAD(&hp->list);
87 	hp->self_base = base;
88 	atomic_set(&hp->refcnt, 1);
89 	hp->handle_size = handle_size;
90 }
91 
mdesc_memblock_alloc(unsigned int mdesc_size)92 static struct mdesc_handle * __init mdesc_memblock_alloc(unsigned int mdesc_size)
93 {
94 	unsigned int handle_size, alloc_size;
95 	struct mdesc_handle *hp;
96 	unsigned long paddr;
97 
98 	handle_size = (sizeof(struct mdesc_handle) -
99 		       sizeof(struct mdesc_hdr) +
100 		       mdesc_size);
101 	alloc_size = PAGE_ALIGN(handle_size);
102 
103 	paddr = memblock_alloc(alloc_size, PAGE_SIZE);
104 
105 	hp = NULL;
106 	if (paddr) {
107 		hp = __va(paddr);
108 		mdesc_handle_init(hp, handle_size, hp);
109 	}
110 	return hp;
111 }
112 
mdesc_memblock_free(struct mdesc_handle * hp)113 static void __init mdesc_memblock_free(struct mdesc_handle *hp)
114 {
115 	unsigned int alloc_size;
116 	unsigned long start;
117 
118 	BUG_ON(atomic_read(&hp->refcnt) != 0);
119 	BUG_ON(!list_empty(&hp->list));
120 
121 	alloc_size = PAGE_ALIGN(hp->handle_size);
122 	start = __pa(hp);
123 	free_bootmem_late(start, alloc_size);
124 }
125 
126 static struct mdesc_mem_ops memblock_mdesc_ops = {
127 	.alloc = mdesc_memblock_alloc,
128 	.free  = mdesc_memblock_free,
129 };
130 
mdesc_kmalloc(unsigned int mdesc_size)131 static struct mdesc_handle *mdesc_kmalloc(unsigned int mdesc_size)
132 {
133 	unsigned int handle_size;
134 	struct mdesc_handle *hp;
135 	unsigned long addr;
136 	void *base;
137 
138 	handle_size = (sizeof(struct mdesc_handle) -
139 		       sizeof(struct mdesc_hdr) +
140 		       mdesc_size);
141 
142 	/*
143 	 * Allocation has to succeed because mdesc update would be missed
144 	 * and such events are not retransmitted.
145 	 */
146 	base = kmalloc(handle_size + 15, GFP_KERNEL | __GFP_NOFAIL);
147 	addr = (unsigned long)base;
148 	addr = (addr + 15UL) & ~15UL;
149 	hp = (struct mdesc_handle *) addr;
150 
151 	mdesc_handle_init(hp, handle_size, base);
152 
153 	return hp;
154 }
155 
mdesc_kfree(struct mdesc_handle * hp)156 static void mdesc_kfree(struct mdesc_handle *hp)
157 {
158 	BUG_ON(atomic_read(&hp->refcnt) != 0);
159 	BUG_ON(!list_empty(&hp->list));
160 
161 	kfree(hp->self_base);
162 }
163 
164 static struct mdesc_mem_ops kmalloc_mdesc_memops = {
165 	.alloc = mdesc_kmalloc,
166 	.free  = mdesc_kfree,
167 };
168 
mdesc_alloc(unsigned int mdesc_size,struct mdesc_mem_ops * mops)169 static struct mdesc_handle *mdesc_alloc(unsigned int mdesc_size,
170 					struct mdesc_mem_ops *mops)
171 {
172 	struct mdesc_handle *hp = mops->alloc(mdesc_size);
173 
174 	if (hp)
175 		hp->mops = mops;
176 
177 	return hp;
178 }
179 
mdesc_free(struct mdesc_handle * hp)180 static void mdesc_free(struct mdesc_handle *hp)
181 {
182 	hp->mops->free(hp);
183 }
184 
185 static struct mdesc_handle *cur_mdesc;
186 static LIST_HEAD(mdesc_zombie_list);
187 static DEFINE_SPINLOCK(mdesc_lock);
188 
mdesc_grab(void)189 struct mdesc_handle *mdesc_grab(void)
190 {
191 	struct mdesc_handle *hp;
192 	unsigned long flags;
193 
194 	spin_lock_irqsave(&mdesc_lock, flags);
195 	hp = cur_mdesc;
196 	if (hp)
197 		atomic_inc(&hp->refcnt);
198 	spin_unlock_irqrestore(&mdesc_lock, flags);
199 
200 	return hp;
201 }
202 EXPORT_SYMBOL(mdesc_grab);
203 
mdesc_release(struct mdesc_handle * hp)204 void mdesc_release(struct mdesc_handle *hp)
205 {
206 	unsigned long flags;
207 
208 	spin_lock_irqsave(&mdesc_lock, flags);
209 	if (atomic_dec_and_test(&hp->refcnt)) {
210 		list_del_init(&hp->list);
211 		hp->mops->free(hp);
212 	}
213 	spin_unlock_irqrestore(&mdesc_lock, flags);
214 }
215 EXPORT_SYMBOL(mdesc_release);
216 
217 static DEFINE_MUTEX(mdesc_mutex);
218 static struct mdesc_notifier_client *client_list;
219 
mdesc_register_notifier(struct mdesc_notifier_client * client)220 void mdesc_register_notifier(struct mdesc_notifier_client *client)
221 {
222 	u64 node;
223 
224 	mutex_lock(&mdesc_mutex);
225 	client->next = client_list;
226 	client_list = client;
227 
228 	mdesc_for_each_node_by_name(cur_mdesc, node, client->node_name)
229 		client->add(cur_mdesc, node);
230 
231 	mutex_unlock(&mdesc_mutex);
232 }
233 
parent_cfg_handle(struct mdesc_handle * hp,u64 node)234 static const u64 *parent_cfg_handle(struct mdesc_handle *hp, u64 node)
235 {
236 	const u64 *id;
237 	u64 a;
238 
239 	id = NULL;
240 	mdesc_for_each_arc(a, hp, node, MDESC_ARC_TYPE_BACK) {
241 		u64 target;
242 
243 		target = mdesc_arc_target(hp, a);
244 		id = mdesc_get_property(hp, target,
245 					"cfg-handle", NULL);
246 		if (id)
247 			break;
248 	}
249 
250 	return id;
251 }
252 
253 /* Run 'func' on nodes which are in A but not in B.  */
invoke_on_missing(const char * name,struct mdesc_handle * a,struct mdesc_handle * b,void (* func)(struct mdesc_handle *,u64))254 static void invoke_on_missing(const char *name,
255 			      struct mdesc_handle *a,
256 			      struct mdesc_handle *b,
257 			      void (*func)(struct mdesc_handle *, u64))
258 {
259 	u64 node;
260 
261 	mdesc_for_each_node_by_name(a, node, name) {
262 		int found = 0, is_vdc_port = 0;
263 		const char *name_prop;
264 		const u64 *id;
265 		u64 fnode;
266 
267 		name_prop = mdesc_get_property(a, node, "name", NULL);
268 		if (name_prop && !strcmp(name_prop, "vdc-port")) {
269 			is_vdc_port = 1;
270 			id = parent_cfg_handle(a, node);
271 		} else
272 			id = mdesc_get_property(a, node, "id", NULL);
273 
274 		if (!id) {
275 			printk(KERN_ERR "MD: Cannot find ID for %s node.\n",
276 			       (name_prop ? name_prop : name));
277 			continue;
278 		}
279 
280 		mdesc_for_each_node_by_name(b, fnode, name) {
281 			const u64 *fid;
282 
283 			if (is_vdc_port) {
284 				name_prop = mdesc_get_property(b, fnode,
285 							       "name", NULL);
286 				if (!name_prop ||
287 				    strcmp(name_prop, "vdc-port"))
288 					continue;
289 				fid = parent_cfg_handle(b, fnode);
290 				if (!fid) {
291 					printk(KERN_ERR "MD: Cannot find ID "
292 					       "for vdc-port node.\n");
293 					continue;
294 				}
295 			} else
296 				fid = mdesc_get_property(b, fnode,
297 							 "id", NULL);
298 
299 			if (*id == *fid) {
300 				found = 1;
301 				break;
302 			}
303 		}
304 		if (!found)
305 			func(a, node);
306 	}
307 }
308 
notify_one(struct mdesc_notifier_client * p,struct mdesc_handle * old_hp,struct mdesc_handle * new_hp)309 static void notify_one(struct mdesc_notifier_client *p,
310 		       struct mdesc_handle *old_hp,
311 		       struct mdesc_handle *new_hp)
312 {
313 	invoke_on_missing(p->node_name, old_hp, new_hp, p->remove);
314 	invoke_on_missing(p->node_name, new_hp, old_hp, p->add);
315 }
316 
mdesc_notify_clients(struct mdesc_handle * old_hp,struct mdesc_handle * new_hp)317 static void mdesc_notify_clients(struct mdesc_handle *old_hp,
318 				 struct mdesc_handle *new_hp)
319 {
320 	struct mdesc_notifier_client *p = client_list;
321 
322 	while (p) {
323 		notify_one(p, old_hp, new_hp);
324 		p = p->next;
325 	}
326 }
327 
mdesc_update(void)328 void mdesc_update(void)
329 {
330 	unsigned long len, real_len, status;
331 	struct mdesc_handle *hp, *orig_hp;
332 	unsigned long flags;
333 
334 	mutex_lock(&mdesc_mutex);
335 
336 	(void) sun4v_mach_desc(0UL, 0UL, &len);
337 
338 	hp = mdesc_alloc(len, &kmalloc_mdesc_memops);
339 	if (!hp) {
340 		printk(KERN_ERR "MD: mdesc alloc fails\n");
341 		goto out;
342 	}
343 
344 	status = sun4v_mach_desc(__pa(&hp->mdesc), len, &real_len);
345 	if (status != HV_EOK || real_len > len) {
346 		printk(KERN_ERR "MD: mdesc reread fails with %lu\n",
347 		       status);
348 		atomic_dec(&hp->refcnt);
349 		mdesc_free(hp);
350 		goto out;
351 	}
352 
353 	spin_lock_irqsave(&mdesc_lock, flags);
354 	orig_hp = cur_mdesc;
355 	cur_mdesc = hp;
356 	spin_unlock_irqrestore(&mdesc_lock, flags);
357 
358 	mdesc_notify_clients(orig_hp, hp);
359 
360 	spin_lock_irqsave(&mdesc_lock, flags);
361 	if (atomic_dec_and_test(&orig_hp->refcnt))
362 		mdesc_free(orig_hp);
363 	else
364 		list_add(&orig_hp->list, &mdesc_zombie_list);
365 	spin_unlock_irqrestore(&mdesc_lock, flags);
366 
367 out:
368 	mutex_unlock(&mdesc_mutex);
369 }
370 
node_block(struct mdesc_hdr * mdesc)371 static struct mdesc_elem *node_block(struct mdesc_hdr *mdesc)
372 {
373 	return (struct mdesc_elem *) mdesc->data;
374 }
375 
name_block(struct mdesc_hdr * mdesc)376 static void *name_block(struct mdesc_hdr *mdesc)
377 {
378 	return ((void *) node_block(mdesc)) + mdesc->node_sz;
379 }
380 
data_block(struct mdesc_hdr * mdesc)381 static void *data_block(struct mdesc_hdr *mdesc)
382 {
383 	return ((void *) name_block(mdesc)) + mdesc->name_sz;
384 }
385 
mdesc_node_by_name(struct mdesc_handle * hp,u64 from_node,const char * name)386 u64 mdesc_node_by_name(struct mdesc_handle *hp,
387 		       u64 from_node, const char *name)
388 {
389 	struct mdesc_elem *ep = node_block(&hp->mdesc);
390 	const char *names = name_block(&hp->mdesc);
391 	u64 last_node = hp->mdesc.node_sz / 16;
392 	u64 ret;
393 
394 	if (from_node == MDESC_NODE_NULL) {
395 		ret = from_node = 0;
396 	} else if (from_node >= last_node) {
397 		return MDESC_NODE_NULL;
398 	} else {
399 		ret = ep[from_node].d.val;
400 	}
401 
402 	while (ret < last_node) {
403 		if (ep[ret].tag != MD_NODE)
404 			return MDESC_NODE_NULL;
405 		if (!strcmp(names + ep[ret].name_offset, name))
406 			break;
407 		ret = ep[ret].d.val;
408 	}
409 	if (ret >= last_node)
410 		ret = MDESC_NODE_NULL;
411 	return ret;
412 }
413 EXPORT_SYMBOL(mdesc_node_by_name);
414 
mdesc_get_property(struct mdesc_handle * hp,u64 node,const char * name,int * lenp)415 const void *mdesc_get_property(struct mdesc_handle *hp, u64 node,
416 			       const char *name, int *lenp)
417 {
418 	const char *names = name_block(&hp->mdesc);
419 	u64 last_node = hp->mdesc.node_sz / 16;
420 	void *data = data_block(&hp->mdesc);
421 	struct mdesc_elem *ep;
422 
423 	if (node == MDESC_NODE_NULL || node >= last_node)
424 		return NULL;
425 
426 	ep = node_block(&hp->mdesc) + node;
427 	ep++;
428 	for (; ep->tag != MD_NODE_END; ep++) {
429 		void *val = NULL;
430 		int len = 0;
431 
432 		switch (ep->tag) {
433 		case MD_PROP_VAL:
434 			val = &ep->d.val;
435 			len = 8;
436 			break;
437 
438 		case MD_PROP_STR:
439 		case MD_PROP_DATA:
440 			val = data + ep->d.data.data_offset;
441 			len = ep->d.data.data_len;
442 			break;
443 
444 		default:
445 			break;
446 		}
447 		if (!val)
448 			continue;
449 
450 		if (!strcmp(names + ep->name_offset, name)) {
451 			if (lenp)
452 				*lenp = len;
453 			return val;
454 		}
455 	}
456 
457 	return NULL;
458 }
459 EXPORT_SYMBOL(mdesc_get_property);
460 
mdesc_next_arc(struct mdesc_handle * hp,u64 from,const char * arc_type)461 u64 mdesc_next_arc(struct mdesc_handle *hp, u64 from, const char *arc_type)
462 {
463 	struct mdesc_elem *ep, *base = node_block(&hp->mdesc);
464 	const char *names = name_block(&hp->mdesc);
465 	u64 last_node = hp->mdesc.node_sz / 16;
466 
467 	if (from == MDESC_NODE_NULL || from >= last_node)
468 		return MDESC_NODE_NULL;
469 
470 	ep = base + from;
471 
472 	ep++;
473 	for (; ep->tag != MD_NODE_END; ep++) {
474 		if (ep->tag != MD_PROP_ARC)
475 			continue;
476 
477 		if (strcmp(names + ep->name_offset, arc_type))
478 			continue;
479 
480 		return ep - base;
481 	}
482 
483 	return MDESC_NODE_NULL;
484 }
485 EXPORT_SYMBOL(mdesc_next_arc);
486 
mdesc_arc_target(struct mdesc_handle * hp,u64 arc)487 u64 mdesc_arc_target(struct mdesc_handle *hp, u64 arc)
488 {
489 	struct mdesc_elem *ep, *base = node_block(&hp->mdesc);
490 
491 	ep = base + arc;
492 
493 	return ep->d.val;
494 }
495 EXPORT_SYMBOL(mdesc_arc_target);
496 
mdesc_node_name(struct mdesc_handle * hp,u64 node)497 const char *mdesc_node_name(struct mdesc_handle *hp, u64 node)
498 {
499 	struct mdesc_elem *ep, *base = node_block(&hp->mdesc);
500 	const char *names = name_block(&hp->mdesc);
501 	u64 last_node = hp->mdesc.node_sz / 16;
502 
503 	if (node == MDESC_NODE_NULL || node >= last_node)
504 		return NULL;
505 
506 	ep = base + node;
507 	if (ep->tag != MD_NODE)
508 		return NULL;
509 
510 	return names + ep->name_offset;
511 }
512 EXPORT_SYMBOL(mdesc_node_name);
513 
514 static u64 max_cpus = 64;
515 
report_platform_properties(void)516 static void __init report_platform_properties(void)
517 {
518 	struct mdesc_handle *hp = mdesc_grab();
519 	u64 pn = mdesc_node_by_name(hp, MDESC_NODE_NULL, "platform");
520 	const char *s;
521 	const u64 *v;
522 
523 	if (pn == MDESC_NODE_NULL) {
524 		prom_printf("No platform node in machine-description.\n");
525 		prom_halt();
526 	}
527 
528 	s = mdesc_get_property(hp, pn, "banner-name", NULL);
529 	printk("PLATFORM: banner-name [%s]\n", s);
530 	s = mdesc_get_property(hp, pn, "name", NULL);
531 	printk("PLATFORM: name [%s]\n", s);
532 
533 	v = mdesc_get_property(hp, pn, "hostid", NULL);
534 	if (v)
535 		printk("PLATFORM: hostid [%08llx]\n", *v);
536 	v = mdesc_get_property(hp, pn, "serial#", NULL);
537 	if (v)
538 		printk("PLATFORM: serial# [%08llx]\n", *v);
539 	v = mdesc_get_property(hp, pn, "stick-frequency", NULL);
540 	printk("PLATFORM: stick-frequency [%08llx]\n", *v);
541 	v = mdesc_get_property(hp, pn, "mac-address", NULL);
542 	if (v)
543 		printk("PLATFORM: mac-address [%llx]\n", *v);
544 	v = mdesc_get_property(hp, pn, "watchdog-resolution", NULL);
545 	if (v)
546 		printk("PLATFORM: watchdog-resolution [%llu ms]\n", *v);
547 	v = mdesc_get_property(hp, pn, "watchdog-max-timeout", NULL);
548 	if (v)
549 		printk("PLATFORM: watchdog-max-timeout [%llu ms]\n", *v);
550 	v = mdesc_get_property(hp, pn, "max-cpus", NULL);
551 	if (v) {
552 		max_cpus = *v;
553 		printk("PLATFORM: max-cpus [%llu]\n", max_cpus);
554 	}
555 
556 #ifdef CONFIG_SMP
557 	{
558 		int max_cpu, i;
559 
560 		if (v) {
561 			max_cpu = *v;
562 			if (max_cpu > NR_CPUS)
563 				max_cpu = NR_CPUS;
564 		} else {
565 			max_cpu = NR_CPUS;
566 		}
567 		for (i = 0; i < max_cpu; i++)
568 			set_cpu_possible(i, true);
569 	}
570 #endif
571 
572 	mdesc_release(hp);
573 }
574 
fill_in_one_cache(cpuinfo_sparc * c,struct mdesc_handle * hp,u64 mp)575 static void fill_in_one_cache(cpuinfo_sparc *c, struct mdesc_handle *hp, u64 mp)
576 {
577 	const u64 *level = mdesc_get_property(hp, mp, "level", NULL);
578 	const u64 *size = mdesc_get_property(hp, mp, "size", NULL);
579 	const u64 *line_size = mdesc_get_property(hp, mp, "line-size", NULL);
580 	const char *type;
581 	int type_len;
582 
583 	type = mdesc_get_property(hp, mp, "type", &type_len);
584 
585 	switch (*level) {
586 	case 1:
587 		if (of_find_in_proplist(type, "instn", type_len)) {
588 			c->icache_size = *size;
589 			c->icache_line_size = *line_size;
590 		} else if (of_find_in_proplist(type, "data", type_len)) {
591 			c->dcache_size = *size;
592 			c->dcache_line_size = *line_size;
593 		}
594 		break;
595 
596 	case 2:
597 		c->ecache_size = *size;
598 		c->ecache_line_size = *line_size;
599 		break;
600 
601 	default:
602 		break;
603 	}
604 
605 	if (*level == 1) {
606 		u64 a;
607 
608 		mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_FWD) {
609 			u64 target = mdesc_arc_target(hp, a);
610 			const char *name = mdesc_node_name(hp, target);
611 
612 			if (!strcmp(name, "cache"))
613 				fill_in_one_cache(c, hp, target);
614 		}
615 	}
616 }
617 
find_back_node_value(struct mdesc_handle * hp,u64 node,char * srch_val,void (* func)(struct mdesc_handle *,u64,int),u64 val,int depth)618 static void find_back_node_value(struct mdesc_handle *hp, u64 node,
619 				 char *srch_val,
620 				 void (*func)(struct mdesc_handle *, u64, int),
621 				 u64 val, int depth)
622 {
623 	u64 arc;
624 
625 	/* Since we have an estimate of recursion depth, do a sanity check. */
626 	if (depth == 0)
627 		return;
628 
629 	mdesc_for_each_arc(arc, hp, node, MDESC_ARC_TYPE_BACK) {
630 		u64 n = mdesc_arc_target(hp, arc);
631 		const char *name = mdesc_node_name(hp, n);
632 
633 		if (!strcmp(srch_val, name))
634 			(*func)(hp, n, val);
635 
636 		find_back_node_value(hp, n, srch_val, func, val, depth-1);
637 	}
638 }
639 
__mark_core_id(struct mdesc_handle * hp,u64 node,int core_id)640 static void __mark_core_id(struct mdesc_handle *hp, u64 node,
641 			   int core_id)
642 {
643 	const u64 *id = mdesc_get_property(hp, node, "id", NULL);
644 
645 	if (*id < num_possible_cpus())
646 		cpu_data(*id).core_id = core_id;
647 }
648 
__mark_sock_id(struct mdesc_handle * hp,u64 node,int sock_id)649 static void __mark_sock_id(struct mdesc_handle *hp, u64 node,
650 			   int sock_id)
651 {
652 	const u64 *id = mdesc_get_property(hp, node, "id", NULL);
653 
654 	if (*id < num_possible_cpus())
655 		cpu_data(*id).sock_id = sock_id;
656 }
657 
mark_core_ids(struct mdesc_handle * hp,u64 mp,int core_id)658 static void mark_core_ids(struct mdesc_handle *hp, u64 mp,
659 			  int core_id)
660 {
661 	find_back_node_value(hp, mp, "cpu", __mark_core_id, core_id, 10);
662 }
663 
mark_sock_ids(struct mdesc_handle * hp,u64 mp,int sock_id)664 static void mark_sock_ids(struct mdesc_handle *hp, u64 mp,
665 			  int sock_id)
666 {
667 	find_back_node_value(hp, mp, "cpu", __mark_sock_id, sock_id, 10);
668 }
669 
set_core_ids(struct mdesc_handle * hp)670 static void set_core_ids(struct mdesc_handle *hp)
671 {
672 	int idx;
673 	u64 mp;
674 
675 	idx = 1;
676 
677 	/* Identify unique cores by looking for cpus backpointed to by
678 	 * level 1 instruction caches.
679 	 */
680 	mdesc_for_each_node_by_name(hp, mp, "cache") {
681 		const u64 *level;
682 		const char *type;
683 		int len;
684 
685 		level = mdesc_get_property(hp, mp, "level", NULL);
686 		if (*level != 1)
687 			continue;
688 
689 		type = mdesc_get_property(hp, mp, "type", &len);
690 		if (!of_find_in_proplist(type, "instn", len))
691 			continue;
692 
693 		mark_core_ids(hp, mp, idx);
694 		idx++;
695 	}
696 }
697 
set_sock_ids_by_cache(struct mdesc_handle * hp,int level)698 static int set_sock_ids_by_cache(struct mdesc_handle *hp, int level)
699 {
700 	u64 mp;
701 	int idx = 1;
702 	int fnd = 0;
703 
704 	/* Identify unique sockets by looking for cpus backpointed to by
705 	 * shared level n caches.
706 	 */
707 	mdesc_for_each_node_by_name(hp, mp, "cache") {
708 		const u64 *cur_lvl;
709 
710 		cur_lvl = mdesc_get_property(hp, mp, "level", NULL);
711 		if (*cur_lvl != level)
712 			continue;
713 
714 		mark_sock_ids(hp, mp, idx);
715 		idx++;
716 		fnd = 1;
717 	}
718 	return fnd;
719 }
720 
set_sock_ids_by_socket(struct mdesc_handle * hp,u64 mp)721 static void set_sock_ids_by_socket(struct mdesc_handle *hp, u64 mp)
722 {
723 	int idx = 1;
724 
725 	mdesc_for_each_node_by_name(hp, mp, "socket") {
726 		u64 a;
727 
728 		mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_FWD) {
729 			u64 t = mdesc_arc_target(hp, a);
730 			const char *name;
731 			const u64 *id;
732 
733 			name = mdesc_node_name(hp, t);
734 			if (strcmp(name, "cpu"))
735 				continue;
736 
737 			id = mdesc_get_property(hp, t, "id", NULL);
738 			if (*id < num_possible_cpus())
739 				cpu_data(*id).sock_id = idx;
740 		}
741 		idx++;
742 	}
743 }
744 
set_sock_ids(struct mdesc_handle * hp)745 static void set_sock_ids(struct mdesc_handle *hp)
746 {
747 	u64 mp;
748 
749 	/* If machine description exposes sockets data use it.
750 	 * Otherwise fallback to use shared L3 or L2 caches.
751 	 */
752 	mp = mdesc_node_by_name(hp, MDESC_NODE_NULL, "sockets");
753 	if (mp != MDESC_NODE_NULL)
754 		return set_sock_ids_by_socket(hp, mp);
755 
756 	if (!set_sock_ids_by_cache(hp, 3))
757 		set_sock_ids_by_cache(hp, 2);
758 }
759 
mark_proc_ids(struct mdesc_handle * hp,u64 mp,int proc_id)760 static void mark_proc_ids(struct mdesc_handle *hp, u64 mp, int proc_id)
761 {
762 	u64 a;
763 
764 	mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_BACK) {
765 		u64 t = mdesc_arc_target(hp, a);
766 		const char *name;
767 		const u64 *id;
768 
769 		name = mdesc_node_name(hp, t);
770 		if (strcmp(name, "cpu"))
771 			continue;
772 
773 		id = mdesc_get_property(hp, t, "id", NULL);
774 		if (*id < NR_CPUS)
775 			cpu_data(*id).proc_id = proc_id;
776 	}
777 }
778 
__set_proc_ids(struct mdesc_handle * hp,const char * exec_unit_name)779 static void __set_proc_ids(struct mdesc_handle *hp, const char *exec_unit_name)
780 {
781 	int idx;
782 	u64 mp;
783 
784 	idx = 0;
785 	mdesc_for_each_node_by_name(hp, mp, exec_unit_name) {
786 		const char *type;
787 		int len;
788 
789 		type = mdesc_get_property(hp, mp, "type", &len);
790 		if (!of_find_in_proplist(type, "int", len) &&
791 		    !of_find_in_proplist(type, "integer", len))
792 			continue;
793 
794 		mark_proc_ids(hp, mp, idx);
795 		idx++;
796 	}
797 }
798 
set_proc_ids(struct mdesc_handle * hp)799 static void set_proc_ids(struct mdesc_handle *hp)
800 {
801 	__set_proc_ids(hp, "exec_unit");
802 	__set_proc_ids(hp, "exec-unit");
803 }
804 
get_one_mondo_bits(const u64 * p,unsigned int * mask,unsigned long def,unsigned long max)805 static void get_one_mondo_bits(const u64 *p, unsigned int *mask,
806 			       unsigned long def, unsigned long max)
807 {
808 	u64 val;
809 
810 	if (!p)
811 		goto use_default;
812 	val = *p;
813 
814 	if (!val || val >= 64)
815 		goto use_default;
816 
817 	if (val > max)
818 		val = max;
819 
820 	*mask = ((1U << val) * 64U) - 1U;
821 	return;
822 
823 use_default:
824 	*mask = ((1U << def) * 64U) - 1U;
825 }
826 
get_mondo_data(struct mdesc_handle * hp,u64 mp,struct trap_per_cpu * tb)827 static void get_mondo_data(struct mdesc_handle *hp, u64 mp,
828 			   struct trap_per_cpu *tb)
829 {
830 	static int printed;
831 	const u64 *val;
832 
833 	val = mdesc_get_property(hp, mp, "q-cpu-mondo-#bits", NULL);
834 	get_one_mondo_bits(val, &tb->cpu_mondo_qmask, 7, ilog2(max_cpus * 2));
835 
836 	val = mdesc_get_property(hp, mp, "q-dev-mondo-#bits", NULL);
837 	get_one_mondo_bits(val, &tb->dev_mondo_qmask, 7, 8);
838 
839 	val = mdesc_get_property(hp, mp, "q-resumable-#bits", NULL);
840 	get_one_mondo_bits(val, &tb->resum_qmask, 6, 7);
841 
842 	val = mdesc_get_property(hp, mp, "q-nonresumable-#bits", NULL);
843 	get_one_mondo_bits(val, &tb->nonresum_qmask, 2, 2);
844 	if (!printed++) {
845 		pr_info("SUN4V: Mondo queue sizes "
846 			"[cpu(%u) dev(%u) r(%u) nr(%u)]\n",
847 			tb->cpu_mondo_qmask + 1,
848 			tb->dev_mondo_qmask + 1,
849 			tb->resum_qmask + 1,
850 			tb->nonresum_qmask + 1);
851 	}
852 }
853 
mdesc_iterate_over_cpus(void * (* func)(struct mdesc_handle *,u64,int,void *),void * arg,cpumask_t * mask)854 static void *mdesc_iterate_over_cpus(void *(*func)(struct mdesc_handle *, u64, int, void *), void *arg, cpumask_t *mask)
855 {
856 	struct mdesc_handle *hp = mdesc_grab();
857 	void *ret = NULL;
858 	u64 mp;
859 
860 	mdesc_for_each_node_by_name(hp, mp, "cpu") {
861 		const u64 *id = mdesc_get_property(hp, mp, "id", NULL);
862 		int cpuid = *id;
863 
864 #ifdef CONFIG_SMP
865 		if (cpuid >= NR_CPUS) {
866 			printk(KERN_WARNING "Ignoring CPU %d which is "
867 			       ">= NR_CPUS (%d)\n",
868 			       cpuid, NR_CPUS);
869 			continue;
870 		}
871 		if (!cpumask_test_cpu(cpuid, mask))
872 			continue;
873 #endif
874 
875 		ret = func(hp, mp, cpuid, arg);
876 		if (ret)
877 			goto out;
878 	}
879 out:
880 	mdesc_release(hp);
881 	return ret;
882 }
883 
record_one_cpu(struct mdesc_handle * hp,u64 mp,int cpuid,void * arg)884 static void *record_one_cpu(struct mdesc_handle *hp, u64 mp, int cpuid,
885 			    void *arg)
886 {
887 	ncpus_probed++;
888 #ifdef CONFIG_SMP
889 	set_cpu_present(cpuid, true);
890 #endif
891 	return NULL;
892 }
893 
mdesc_populate_present_mask(cpumask_t * mask)894 void mdesc_populate_present_mask(cpumask_t *mask)
895 {
896 	if (tlb_type != hypervisor)
897 		return;
898 
899 	ncpus_probed = 0;
900 	mdesc_iterate_over_cpus(record_one_cpu, NULL, mask);
901 }
902 
check_one_pgsz(struct mdesc_handle * hp,u64 mp,int cpuid,void * arg)903 static void * __init check_one_pgsz(struct mdesc_handle *hp, u64 mp, int cpuid, void *arg)
904 {
905 	const u64 *pgsz_prop = mdesc_get_property(hp, mp, "mmu-page-size-list", NULL);
906 	unsigned long *pgsz_mask = arg;
907 	u64 val;
908 
909 	val = (HV_PGSZ_MASK_8K | HV_PGSZ_MASK_64K |
910 	       HV_PGSZ_MASK_512K | HV_PGSZ_MASK_4MB);
911 	if (pgsz_prop)
912 		val = *pgsz_prop;
913 
914 	if (!*pgsz_mask)
915 		*pgsz_mask = val;
916 	else
917 		*pgsz_mask &= val;
918 	return NULL;
919 }
920 
mdesc_get_page_sizes(cpumask_t * mask,unsigned long * pgsz_mask)921 void __init mdesc_get_page_sizes(cpumask_t *mask, unsigned long *pgsz_mask)
922 {
923 	*pgsz_mask = 0;
924 	mdesc_iterate_over_cpus(check_one_pgsz, pgsz_mask, mask);
925 }
926 
fill_in_one_cpu(struct mdesc_handle * hp,u64 mp,int cpuid,void * arg)927 static void *fill_in_one_cpu(struct mdesc_handle *hp, u64 mp, int cpuid,
928 			     void *arg)
929 {
930 	const u64 *cfreq = mdesc_get_property(hp, mp, "clock-frequency", NULL);
931 	struct trap_per_cpu *tb;
932 	cpuinfo_sparc *c;
933 	u64 a;
934 
935 #ifndef CONFIG_SMP
936 	/* On uniprocessor we only want the values for the
937 	 * real physical cpu the kernel booted onto, however
938 	 * cpu_data() only has one entry at index 0.
939 	 */
940 	if (cpuid != real_hard_smp_processor_id())
941 		return NULL;
942 	cpuid = 0;
943 #endif
944 
945 	c = &cpu_data(cpuid);
946 	c->clock_tick = *cfreq;
947 
948 	tb = &trap_block[cpuid];
949 	get_mondo_data(hp, mp, tb);
950 
951 	mdesc_for_each_arc(a, hp, mp, MDESC_ARC_TYPE_FWD) {
952 		u64 j, t = mdesc_arc_target(hp, a);
953 		const char *t_name;
954 
955 		t_name = mdesc_node_name(hp, t);
956 		if (!strcmp(t_name, "cache")) {
957 			fill_in_one_cache(c, hp, t);
958 			continue;
959 		}
960 
961 		mdesc_for_each_arc(j, hp, t, MDESC_ARC_TYPE_FWD) {
962 			u64 n = mdesc_arc_target(hp, j);
963 			const char *n_name;
964 
965 			n_name = mdesc_node_name(hp, n);
966 			if (!strcmp(n_name, "cache"))
967 				fill_in_one_cache(c, hp, n);
968 		}
969 	}
970 
971 	c->core_id = 0;
972 	c->proc_id = -1;
973 
974 	return NULL;
975 }
976 
mdesc_fill_in_cpu_data(cpumask_t * mask)977 void mdesc_fill_in_cpu_data(cpumask_t *mask)
978 {
979 	struct mdesc_handle *hp;
980 
981 	mdesc_iterate_over_cpus(fill_in_one_cpu, NULL, mask);
982 
983 	hp = mdesc_grab();
984 
985 	set_core_ids(hp);
986 	set_proc_ids(hp);
987 	set_sock_ids(hp);
988 
989 	mdesc_release(hp);
990 
991 	smp_fill_in_sib_core_maps();
992 }
993 
994 /* mdesc_open() - Grab a reference to mdesc_handle when /dev/mdesc is
995  * opened. Hold this reference until /dev/mdesc is closed to ensure
996  * mdesc data structure is not released underneath us. Store the
997  * pointer to mdesc structure in private_data for read and seek to use
998  */
mdesc_open(struct inode * inode,struct file * file)999 static int mdesc_open(struct inode *inode, struct file *file)
1000 {
1001 	struct mdesc_handle *hp = mdesc_grab();
1002 
1003 	if (!hp)
1004 		return -ENODEV;
1005 
1006 	file->private_data = hp;
1007 
1008 	return 0;
1009 }
1010 
mdesc_read(struct file * file,char __user * buf,size_t len,loff_t * offp)1011 static ssize_t mdesc_read(struct file *file, char __user *buf,
1012 			  size_t len, loff_t *offp)
1013 {
1014 	struct mdesc_handle *hp = file->private_data;
1015 	unsigned char *mdesc;
1016 	int bytes_left, count = len;
1017 
1018 	if (*offp >= hp->handle_size)
1019 		return 0;
1020 
1021 	bytes_left = hp->handle_size - *offp;
1022 	if (count > bytes_left)
1023 		count = bytes_left;
1024 
1025 	mdesc = (unsigned char *)&hp->mdesc;
1026 	mdesc += *offp;
1027 	if (!copy_to_user(buf, mdesc, count)) {
1028 		*offp += count;
1029 		return count;
1030 	} else {
1031 		return -EFAULT;
1032 	}
1033 }
1034 
mdesc_llseek(struct file * file,loff_t offset,int whence)1035 static loff_t mdesc_llseek(struct file *file, loff_t offset, int whence)
1036 {
1037 	struct mdesc_handle *hp;
1038 
1039 	switch (whence) {
1040 	case SEEK_CUR:
1041 		offset += file->f_pos;
1042 		break;
1043 	case SEEK_SET:
1044 		break;
1045 	default:
1046 		return -EINVAL;
1047 	}
1048 
1049 	hp = file->private_data;
1050 	if (offset > hp->handle_size)
1051 		return -EINVAL;
1052 	else
1053 		file->f_pos = offset;
1054 
1055 	return offset;
1056 }
1057 
1058 /* mdesc_close() - /dev/mdesc is being closed, release the reference to
1059  * mdesc structure.
1060  */
mdesc_close(struct inode * inode,struct file * file)1061 static int mdesc_close(struct inode *inode, struct file *file)
1062 {
1063 	mdesc_release(file->private_data);
1064 	return 0;
1065 }
1066 
1067 static const struct file_operations mdesc_fops = {
1068 	.open    = mdesc_open,
1069 	.read	 = mdesc_read,
1070 	.llseek  = mdesc_llseek,
1071 	.release = mdesc_close,
1072 	.owner	 = THIS_MODULE,
1073 };
1074 
1075 static struct miscdevice mdesc_misc = {
1076 	.minor	= MISC_DYNAMIC_MINOR,
1077 	.name	= "mdesc",
1078 	.fops	= &mdesc_fops,
1079 };
1080 
mdesc_misc_init(void)1081 static int __init mdesc_misc_init(void)
1082 {
1083 	return misc_register(&mdesc_misc);
1084 }
1085 
1086 __initcall(mdesc_misc_init);
1087 
sun4v_mdesc_init(void)1088 void __init sun4v_mdesc_init(void)
1089 {
1090 	struct mdesc_handle *hp;
1091 	unsigned long len, real_len, status;
1092 
1093 	(void) sun4v_mach_desc(0UL, 0UL, &len);
1094 
1095 	printk("MDESC: Size is %lu bytes.\n", len);
1096 
1097 	hp = mdesc_alloc(len, &memblock_mdesc_ops);
1098 	if (hp == NULL) {
1099 		prom_printf("MDESC: alloc of %lu bytes failed.\n", len);
1100 		prom_halt();
1101 	}
1102 
1103 	status = sun4v_mach_desc(__pa(&hp->mdesc), len, &real_len);
1104 	if (status != HV_EOK || real_len > len) {
1105 		prom_printf("sun4v_mach_desc fails, err(%lu), "
1106 			    "len(%lu), real_len(%lu)\n",
1107 			    status, len, real_len);
1108 		mdesc_free(hp);
1109 		prom_halt();
1110 	}
1111 
1112 	cur_mdesc = hp;
1113 
1114 	report_platform_properties();
1115 }
1116