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 + -
显示快捷键?