1 /* mdesc.c: Sun4V machine description handling.
3 * Copyright (C) 2007, 2008 David S. Miller <davem@davemloft.net>
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>
12 #include <linux/miscdevice.h>
13 #include <linux/bootmem.h>
15 #include <asm/cpudata.h>
16 #include <asm/hypervisor.h>
17 #include <asm/mdesc.h>
19 #include <asm/oplib.h>
22 /* Unlike the OBP device tree, the machine description is a full-on
23 * DAG. An arbitrary number of ARCs are possible from one
24 * node to other nodes and thus we can't use the OBP device_node
25 * data structure to represent these nodes inside of the kernel.
27 * Actually, it isn't even a DAG, because there are back pointers
28 * which create cycles in the graph.
30 * mdesc_hdr and mdesc_elem describe the layout of the data structure
31 * we get from the Hypervisor.
34 u32 version
; /* Transport version */
35 u32 node_sz
; /* node block size */
36 u32 name_sz
; /* name block size */
37 u32 data_sz
; /* data block size */
38 } __attribute__((aligned(16)));
42 #define MD_LIST_END 0x00
44 #define MD_NODE_END 0x45
46 #define MD_PROP_ARC 0x61
47 #define MD_PROP_VAL 0x76
48 #define MD_PROP_STR 0x73
49 #define MD_PROP_DATA 0x64
62 struct mdesc_mem_ops
{
63 struct mdesc_handle
*(*alloc
)(unsigned int mdesc_size
);
64 void (*free
)(struct mdesc_handle
*handle
);
68 struct list_head list
;
69 struct mdesc_mem_ops
*mops
;
72 unsigned int handle_size
;
73 struct mdesc_hdr mdesc
;
76 static void mdesc_handle_init(struct mdesc_handle
*hp
,
77 unsigned int handle_size
,
80 BUG_ON(((unsigned long)&hp
->mdesc
) & (16UL - 1));
82 memset(hp
, 0, handle_size
);
83 INIT_LIST_HEAD(&hp
->list
);
85 atomic_set(&hp
->refcnt
, 1);
86 hp
->handle_size
= handle_size
;
89 static struct mdesc_handle
* __init
mdesc_memblock_alloc(unsigned int mdesc_size
)
91 unsigned int handle_size
, alloc_size
;
92 struct mdesc_handle
*hp
;
95 handle_size
= (sizeof(struct mdesc_handle
) -
96 sizeof(struct mdesc_hdr
) +
98 alloc_size
= PAGE_ALIGN(handle_size
);
100 paddr
= memblock_alloc(alloc_size
, PAGE_SIZE
);
105 mdesc_handle_init(hp
, handle_size
, hp
);
110 static void __init
mdesc_memblock_free(struct mdesc_handle
*hp
)
112 unsigned int alloc_size
;
115 BUG_ON(atomic_read(&hp
->refcnt
) != 0);
116 BUG_ON(!list_empty(&hp
->list
));
118 alloc_size
= PAGE_ALIGN(hp
->handle_size
);
120 free_bootmem_late(start
, alloc_size
);
123 static struct mdesc_mem_ops memblock_mdesc_ops
= {
124 .alloc
= mdesc_memblock_alloc
,
125 .free
= mdesc_memblock_free
,
128 static struct mdesc_handle
*mdesc_kmalloc(unsigned int mdesc_size
)
130 unsigned int handle_size
;
133 handle_size
= (sizeof(struct mdesc_handle
) -
134 sizeof(struct mdesc_hdr
) +
137 base
= kmalloc(handle_size
+ 15, GFP_KERNEL
| __GFP_NOFAIL
);
139 struct mdesc_handle
*hp
;
142 addr
= (unsigned long)base
;
143 addr
= (addr
+ 15UL) & ~15UL;
144 hp
= (struct mdesc_handle
*) addr
;
146 mdesc_handle_init(hp
, handle_size
, base
);
153 static void mdesc_kfree(struct mdesc_handle
*hp
)
155 BUG_ON(atomic_read(&hp
->refcnt
) != 0);
156 BUG_ON(!list_empty(&hp
->list
));
158 kfree(hp
->self_base
);
161 static struct mdesc_mem_ops kmalloc_mdesc_memops
= {
162 .alloc
= mdesc_kmalloc
,
166 static struct mdesc_handle
*mdesc_alloc(unsigned int mdesc_size
,
167 struct mdesc_mem_ops
*mops
)
169 struct mdesc_handle
*hp
= mops
->alloc(mdesc_size
);
177 static void mdesc_free(struct mdesc_handle
*hp
)
182 static struct mdesc_handle
*cur_mdesc
;
183 static LIST_HEAD(mdesc_zombie_list
);
184 static DEFINE_SPINLOCK(mdesc_lock
);
186 struct mdesc_handle
*mdesc_grab(void)
188 struct mdesc_handle
*hp
;
191 spin_lock_irqsave(&mdesc_lock
, flags
);
194 atomic_inc(&hp
->refcnt
);
195 spin_unlock_irqrestore(&mdesc_lock
, flags
);
199 EXPORT_SYMBOL(mdesc_grab
);
201 void mdesc_release(struct mdesc_handle
*hp
)
205 spin_lock_irqsave(&mdesc_lock
, flags
);
206 if (atomic_dec_and_test(&hp
->refcnt
)) {
207 list_del_init(&hp
->list
);
210 spin_unlock_irqrestore(&mdesc_lock
, flags
);
212 EXPORT_SYMBOL(mdesc_release
);
214 static DEFINE_MUTEX(mdesc_mutex
);
215 static struct mdesc_notifier_client
*client_list
;
217 void mdesc_register_notifier(struct mdesc_notifier_client
*client
)
221 mutex_lock(&mdesc_mutex
);
222 client
->next
= client_list
;
223 client_list
= client
;
225 mdesc_for_each_node_by_name(cur_mdesc
, node
, client
->node_name
)
226 client
->add(cur_mdesc
, node
);
228 mutex_unlock(&mdesc_mutex
);
231 static const u64
*parent_cfg_handle(struct mdesc_handle
*hp
, u64 node
)
237 mdesc_for_each_arc(a
, hp
, node
, MDESC_ARC_TYPE_BACK
) {
240 target
= mdesc_arc_target(hp
, a
);
241 id
= mdesc_get_property(hp
, target
,
250 /* Run 'func' on nodes which are in A but not in B. */
251 static void invoke_on_missing(const char *name
,
252 struct mdesc_handle
*a
,
253 struct mdesc_handle
*b
,
254 void (*func
)(struct mdesc_handle
*, u64
))
258 mdesc_for_each_node_by_name(a
, node
, name
) {
259 int found
= 0, is_vdc_port
= 0;
260 const char *name_prop
;
264 name_prop
= mdesc_get_property(a
, node
, "name", NULL
);
265 if (name_prop
&& !strcmp(name_prop
, "vdc-port")) {
267 id
= parent_cfg_handle(a
, node
);
269 id
= mdesc_get_property(a
, node
, "id", NULL
);
272 printk(KERN_ERR
"MD: Cannot find ID for %s node.\n",
273 (name_prop
? name_prop
: name
));
277 mdesc_for_each_node_by_name(b
, fnode
, name
) {
281 name_prop
= mdesc_get_property(b
, fnode
,
284 strcmp(name_prop
, "vdc-port"))
286 fid
= parent_cfg_handle(b
, fnode
);
288 printk(KERN_ERR
"MD: Cannot find ID "
289 "for vdc-port node.\n");
293 fid
= mdesc_get_property(b
, fnode
,
306 static void notify_one(struct mdesc_notifier_client
*p
,
307 struct mdesc_handle
*old_hp
,
308 struct mdesc_handle
*new_hp
)
310 invoke_on_missing(p
->node_name
, old_hp
, new_hp
, p
->remove
);
311 invoke_on_missing(p
->node_name
, new_hp
, old_hp
, p
->add
);
314 static void mdesc_notify_clients(struct mdesc_handle
*old_hp
,
315 struct mdesc_handle
*new_hp
)
317 struct mdesc_notifier_client
*p
= client_list
;
320 notify_one(p
, old_hp
, new_hp
);
325 void mdesc_update(void)
327 unsigned long len
, real_len
, status
;
328 struct mdesc_handle
*hp
, *orig_hp
;
331 mutex_lock(&mdesc_mutex
);
333 (void) sun4v_mach_desc(0UL, 0UL, &len
);
335 hp
= mdesc_alloc(len
, &kmalloc_mdesc_memops
);
337 printk(KERN_ERR
"MD: mdesc alloc fails\n");
341 status
= sun4v_mach_desc(__pa(&hp
->mdesc
), len
, &real_len
);
342 if (status
!= HV_EOK
|| real_len
> len
) {
343 printk(KERN_ERR
"MD: mdesc reread fails with %lu\n",
345 atomic_dec(&hp
->refcnt
);
350 spin_lock_irqsave(&mdesc_lock
, flags
);
353 spin_unlock_irqrestore(&mdesc_lock
, flags
);
355 mdesc_notify_clients(orig_hp
, hp
);
357 spin_lock_irqsave(&mdesc_lock
, flags
);
358 if (atomic_dec_and_test(&orig_hp
->refcnt
))
361 list_add(&orig_hp
->list
, &mdesc_zombie_list
);
362 spin_unlock_irqrestore(&mdesc_lock
, flags
);
365 mutex_unlock(&mdesc_mutex
);
368 static struct mdesc_elem
*node_block(struct mdesc_hdr
*mdesc
)
370 return (struct mdesc_elem
*) (mdesc
+ 1);
373 static void *name_block(struct mdesc_hdr
*mdesc
)
375 return ((void *) node_block(mdesc
)) + mdesc
->node_sz
;
378 static void *data_block(struct mdesc_hdr
*mdesc
)
380 return ((void *) name_block(mdesc
)) + mdesc
->name_sz
;
383 u64
mdesc_node_by_name(struct mdesc_handle
*hp
,
384 u64 from_node
, const char *name
)
386 struct mdesc_elem
*ep
= node_block(&hp
->mdesc
);
387 const char *names
= name_block(&hp
->mdesc
);
388 u64 last_node
= hp
->mdesc
.node_sz
/ 16;
391 if (from_node
== MDESC_NODE_NULL
) {
393 } else if (from_node
>= last_node
) {
394 return MDESC_NODE_NULL
;
396 ret
= ep
[from_node
].d
.val
;
399 while (ret
< last_node
) {
400 if (ep
[ret
].tag
!= MD_NODE
)
401 return MDESC_NODE_NULL
;
402 if (!strcmp(names
+ ep
[ret
].name_offset
, name
))
406 if (ret
>= last_node
)
407 ret
= MDESC_NODE_NULL
;
410 EXPORT_SYMBOL(mdesc_node_by_name
);
412 const void *mdesc_get_property(struct mdesc_handle
*hp
, u64 node
,
413 const char *name
, int *lenp
)
415 const char *names
= name_block(&hp
->mdesc
);
416 u64 last_node
= hp
->mdesc
.node_sz
/ 16;
417 void *data
= data_block(&hp
->mdesc
);
418 struct mdesc_elem
*ep
;
420 if (node
== MDESC_NODE_NULL
|| node
>= last_node
)
423 ep
= node_block(&hp
->mdesc
) + node
;
425 for (; ep
->tag
!= MD_NODE_END
; ep
++) {
437 val
= data
+ ep
->d
.data
.data_offset
;
438 len
= ep
->d
.data
.data_len
;
447 if (!strcmp(names
+ ep
->name_offset
, name
)) {
456 EXPORT_SYMBOL(mdesc_get_property
);
458 u64
mdesc_next_arc(struct mdesc_handle
*hp
, u64 from
, const char *arc_type
)
460 struct mdesc_elem
*ep
, *base
= node_block(&hp
->mdesc
);
461 const char *names
= name_block(&hp
->mdesc
);
462 u64 last_node
= hp
->mdesc
.node_sz
/ 16;
464 if (from
== MDESC_NODE_NULL
|| from
>= last_node
)
465 return MDESC_NODE_NULL
;
470 for (; ep
->tag
!= MD_NODE_END
; ep
++) {
471 if (ep
->tag
!= MD_PROP_ARC
)
474 if (strcmp(names
+ ep
->name_offset
, arc_type
))
480 return MDESC_NODE_NULL
;
482 EXPORT_SYMBOL(mdesc_next_arc
);
484 u64
mdesc_arc_target(struct mdesc_handle
*hp
, u64 arc
)
486 struct mdesc_elem
*ep
, *base
= node_block(&hp
->mdesc
);
492 EXPORT_SYMBOL(mdesc_arc_target
);
494 const char *mdesc_node_name(struct mdesc_handle
*hp
, u64 node
)
496 struct mdesc_elem
*ep
, *base
= node_block(&hp
->mdesc
);
497 const char *names
= name_block(&hp
->mdesc
);
498 u64 last_node
= hp
->mdesc
.node_sz
/ 16;
500 if (node
== MDESC_NODE_NULL
|| node
>= last_node
)
504 if (ep
->tag
!= MD_NODE
)
507 return names
+ ep
->name_offset
;
509 EXPORT_SYMBOL(mdesc_node_name
);
511 static void __init
report_platform_properties(void)
513 struct mdesc_handle
*hp
= mdesc_grab();
514 u64 pn
= mdesc_node_by_name(hp
, MDESC_NODE_NULL
, "platform");
518 if (pn
== MDESC_NODE_NULL
) {
519 prom_printf("No platform node in machine-description.\n");
523 s
= mdesc_get_property(hp
, pn
, "banner-name", NULL
);
524 printk("PLATFORM: banner-name [%s]\n", s
);
525 s
= mdesc_get_property(hp
, pn
, "name", NULL
);
526 printk("PLATFORM: name [%s]\n", s
);
528 v
= mdesc_get_property(hp
, pn
, "hostid", NULL
);
530 printk("PLATFORM: hostid [%08llx]\n", *v
);
531 v
= mdesc_get_property(hp
, pn
, "serial#", NULL
);
533 printk("PLATFORM: serial# [%08llx]\n", *v
);
534 v
= mdesc_get_property(hp
, pn
, "stick-frequency", NULL
);
535 printk("PLATFORM: stick-frequency [%08llx]\n", *v
);
536 v
= mdesc_get_property(hp
, pn
, "mac-address", NULL
);
538 printk("PLATFORM: mac-address [%llx]\n", *v
);
539 v
= mdesc_get_property(hp
, pn
, "watchdog-resolution", NULL
);
541 printk("PLATFORM: watchdog-resolution [%llu ms]\n", *v
);
542 v
= mdesc_get_property(hp
, pn
, "watchdog-max-timeout", NULL
);
544 printk("PLATFORM: watchdog-max-timeout [%llu ms]\n", *v
);
545 v
= mdesc_get_property(hp
, pn
, "max-cpus", NULL
);
547 printk("PLATFORM: max-cpus [%llu]\n", *v
);
555 if (max_cpu
> NR_CPUS
)
560 for (i
= 0; i
< max_cpu
; i
++)
561 set_cpu_possible(i
, true);
568 static void __cpuinit
fill_in_one_cache(cpuinfo_sparc
*c
,
569 struct mdesc_handle
*hp
,
572 const u64
*level
= mdesc_get_property(hp
, mp
, "level", NULL
);
573 const u64
*size
= mdesc_get_property(hp
, mp
, "size", NULL
);
574 const u64
*line_size
= mdesc_get_property(hp
, mp
, "line-size", NULL
);
578 type
= mdesc_get_property(hp
, mp
, "type", &type_len
);
582 if (of_find_in_proplist(type
, "instn", type_len
)) {
583 c
->icache_size
= *size
;
584 c
->icache_line_size
= *line_size
;
585 } else if (of_find_in_proplist(type
, "data", type_len
)) {
586 c
->dcache_size
= *size
;
587 c
->dcache_line_size
= *line_size
;
592 c
->ecache_size
= *size
;
593 c
->ecache_line_size
= *line_size
;
603 mdesc_for_each_arc(a
, hp
, mp
, MDESC_ARC_TYPE_FWD
) {
604 u64 target
= mdesc_arc_target(hp
, a
);
605 const char *name
= mdesc_node_name(hp
, target
);
607 if (!strcmp(name
, "cache"))
608 fill_in_one_cache(c
, hp
, target
);
613 static void __cpuinit
mark_core_ids(struct mdesc_handle
*hp
, u64 mp
, int core_id
)
617 mdesc_for_each_arc(a
, hp
, mp
, MDESC_ARC_TYPE_BACK
) {
618 u64 t
= mdesc_arc_target(hp
, a
);
622 name
= mdesc_node_name(hp
, t
);
623 if (!strcmp(name
, "cpu")) {
624 id
= mdesc_get_property(hp
, t
, "id", NULL
);
626 cpu_data(*id
).core_id
= core_id
;
630 mdesc_for_each_arc(j
, hp
, t
, MDESC_ARC_TYPE_BACK
) {
631 u64 n
= mdesc_arc_target(hp
, j
);
634 n_name
= mdesc_node_name(hp
, n
);
635 if (strcmp(n_name
, "cpu"))
638 id
= mdesc_get_property(hp
, n
, "id", NULL
);
640 cpu_data(*id
).core_id
= core_id
;
646 static void __cpuinit
set_core_ids(struct mdesc_handle
*hp
)
652 mdesc_for_each_node_by_name(hp
, mp
, "cache") {
657 level
= mdesc_get_property(hp
, mp
, "level", NULL
);
661 type
= mdesc_get_property(hp
, mp
, "type", &len
);
662 if (!of_find_in_proplist(type
, "instn", len
))
665 mark_core_ids(hp
, mp
, idx
);
671 static void __cpuinit
mark_proc_ids(struct mdesc_handle
*hp
, u64 mp
, int proc_id
)
675 mdesc_for_each_arc(a
, hp
, mp
, MDESC_ARC_TYPE_BACK
) {
676 u64 t
= mdesc_arc_target(hp
, a
);
680 name
= mdesc_node_name(hp
, t
);
681 if (strcmp(name
, "cpu"))
684 id
= mdesc_get_property(hp
, t
, "id", NULL
);
686 cpu_data(*id
).proc_id
= proc_id
;
690 static void __cpuinit
__set_proc_ids(struct mdesc_handle
*hp
, const char *exec_unit_name
)
696 mdesc_for_each_node_by_name(hp
, mp
, exec_unit_name
) {
700 type
= mdesc_get_property(hp
, mp
, "type", &len
);
701 if (!of_find_in_proplist(type
, "int", len
) &&
702 !of_find_in_proplist(type
, "integer", len
))
705 mark_proc_ids(hp
, mp
, idx
);
711 static void __cpuinit
set_proc_ids(struct mdesc_handle
*hp
)
713 __set_proc_ids(hp
, "exec_unit");
714 __set_proc_ids(hp
, "exec-unit");
717 static void __cpuinit
get_one_mondo_bits(const u64
*p
, unsigned int *mask
,
726 if (!val
|| val
>= 64)
729 *mask
= ((1U << val
) * 64U) - 1U;
733 *mask
= ((1U << def
) * 64U) - 1U;
736 static void __cpuinit
get_mondo_data(struct mdesc_handle
*hp
, u64 mp
,
737 struct trap_per_cpu
*tb
)
741 val
= mdesc_get_property(hp
, mp
, "q-cpu-mondo-#bits", NULL
);
742 get_one_mondo_bits(val
, &tb
->cpu_mondo_qmask
, 7);
744 val
= mdesc_get_property(hp
, mp
, "q-dev-mondo-#bits", NULL
);
745 get_one_mondo_bits(val
, &tb
->dev_mondo_qmask
, 7);
747 val
= mdesc_get_property(hp
, mp
, "q-resumable-#bits", NULL
);
748 get_one_mondo_bits(val
, &tb
->resum_qmask
, 6);
750 val
= mdesc_get_property(hp
, mp
, "q-nonresumable-#bits", NULL
);
751 get_one_mondo_bits(val
, &tb
->nonresum_qmask
, 2);
754 static void * __cpuinit
mdesc_iterate_over_cpus(void *(*func
)(struct mdesc_handle
*, u64
, int, void *), void *arg
, cpumask_t
*mask
)
756 struct mdesc_handle
*hp
= mdesc_grab();
760 mdesc_for_each_node_by_name(hp
, mp
, "cpu") {
761 const u64
*id
= mdesc_get_property(hp
, mp
, "id", NULL
);
765 if (cpuid
>= NR_CPUS
) {
766 printk(KERN_WARNING
"Ignoring CPU %d which is "
771 if (!cpumask_test_cpu(cpuid
, mask
))
775 ret
= func(hp
, mp
, cpuid
, arg
);
784 static void * __cpuinit
record_one_cpu(struct mdesc_handle
*hp
, u64 mp
, int cpuid
, void *arg
)
788 set_cpu_present(cpuid
, true);
793 void __cpuinit
mdesc_populate_present_mask(cpumask_t
*mask
)
795 if (tlb_type
!= hypervisor
)
799 mdesc_iterate_over_cpus(record_one_cpu
, NULL
, mask
);
802 static void * __cpuinit
fill_in_one_cpu(struct mdesc_handle
*hp
, u64 mp
, int cpuid
, void *arg
)
804 const u64
*cfreq
= mdesc_get_property(hp
, mp
, "clock-frequency", NULL
);
805 struct trap_per_cpu
*tb
;
810 /* On uniprocessor we only want the values for the
811 * real physical cpu the kernel booted onto, however
812 * cpu_data() only has one entry at index 0.
814 if (cpuid
!= real_hard_smp_processor_id())
819 c
= &cpu_data(cpuid
);
820 c
->clock_tick
= *cfreq
;
822 tb
= &trap_block
[cpuid
];
823 get_mondo_data(hp
, mp
, tb
);
825 mdesc_for_each_arc(a
, hp
, mp
, MDESC_ARC_TYPE_FWD
) {
826 u64 j
, t
= mdesc_arc_target(hp
, a
);
829 t_name
= mdesc_node_name(hp
, t
);
830 if (!strcmp(t_name
, "cache")) {
831 fill_in_one_cache(c
, hp
, t
);
835 mdesc_for_each_arc(j
, hp
, t
, MDESC_ARC_TYPE_FWD
) {
836 u64 n
= mdesc_arc_target(hp
, j
);
839 n_name
= mdesc_node_name(hp
, n
);
840 if (!strcmp(n_name
, "cache"))
841 fill_in_one_cache(c
, hp
, n
);
851 void __cpuinit
mdesc_fill_in_cpu_data(cpumask_t
*mask
)
853 struct mdesc_handle
*hp
;
855 mdesc_iterate_over_cpus(fill_in_one_cpu
, NULL
, mask
);
858 sparc64_multi_core
= 1;
868 smp_fill_in_sib_core_maps();
871 static ssize_t
mdesc_read(struct file
*file
, char __user
*buf
,
872 size_t len
, loff_t
*offp
)
874 struct mdesc_handle
*hp
= mdesc_grab();
880 err
= hp
->handle_size
;
881 if (len
< hp
->handle_size
)
883 else if (copy_to_user(buf
, &hp
->mdesc
, hp
->handle_size
))
890 static const struct file_operations mdesc_fops
= {
892 .owner
= THIS_MODULE
,
893 .llseek
= noop_llseek
,
896 static struct miscdevice mdesc_misc
= {
897 .minor
= MISC_DYNAMIC_MINOR
,
902 static int __init
mdesc_misc_init(void)
904 return misc_register(&mdesc_misc
);
907 __initcall(mdesc_misc_init
);
909 void __init
sun4v_mdesc_init(void)
911 struct mdesc_handle
*hp
;
912 unsigned long len
, real_len
, status
;
914 (void) sun4v_mach_desc(0UL, 0UL, &len
);
916 printk("MDESC: Size is %lu bytes.\n", len
);
918 hp
= mdesc_alloc(len
, &memblock_mdesc_ops
);
920 prom_printf("MDESC: alloc of %lu bytes failed.\n", len
);
924 status
= sun4v_mach_desc(__pa(&hp
->mdesc
), len
, &real_len
);
925 if (status
!= HV_EOK
|| real_len
> len
) {
926 prom_printf("sun4v_mach_desc fails, err(%lu), "
927 "len(%lu), real_len(%lu)\n",
928 status
, len
, real_len
);
935 report_platform_properties();