/* * Callback to the ptree walk function during add_cpus. * As a part of the args receives a cpu di_node, compares * each picl cpu node's cpuid to the device tree node's cpuid. * Sets arg struct's result to 1 on a match. */ static int cpu_exists(picl_nodehdl_t nodeh, void *c_args) { di_node_t di_node; cpu_lookup_t *cpu_arg; int err; int dcpuid, pcpuid; int reg_prop[4]; if (c_args == NULL) return (PICL_INVALIDARG); cpu_arg = c_args; di_node = cpu_arg->di_node; dcpuid = get_cpuid(di_node); err = ptree_get_propval_by_name(nodeh, OBP_REG, reg_prop, sizeof (reg_prop)); if (err != PICL_SUCCESS) return (PICL_WALK_CONTINUE); pcpuid = CFGHDL_TO_CPUID(reg_prop[0]); if (dcpuid == pcpuid) { cpu_arg->result = 1; return (PICL_WALK_TERMINATE); } cpu_arg->result = 0; return (PICL_WALK_CONTINUE); }
/* * Callback to the ptree walk function during remove_cpus. * As a part of the args receives a picl nodeh, searches * the device tree for a cpu whose cpuid matches the picl cpu node. * Sets arg struct's result to 1 if it failed to match and terminates * the walk. */ static int remove_cpu_candidate(picl_nodehdl_t nodeh, void *c_args) { di_node_t di_node; cpu_lookup_t *cpu_arg; int err; int pcpuid; int reg_prop[SUN4V_CPU_REGSIZE]; if (c_args == NULL) return (PICL_INVALIDARG); cpu_arg = c_args; di_node = cpu_arg->di_node; err = ptree_get_propval_by_name(nodeh, OBP_REG, reg_prop, sizeof (reg_prop)); if (err != PICL_SUCCESS) { return (PICL_WALK_CONTINUE); } pcpuid = CFGHDL_TO_CPUID(reg_prop[0]); if (!find_cpu(di_node, pcpuid)) { cpu_arg->result = 1; cpu_arg->nodeh = nodeh; return (PICL_WALK_TERMINATE); } cpu_arg->result = 0; return (PICL_WALK_CONTINUE); }
/* * Given a devinfo cpu node find its cpuid property. */ int get_cpuid(di_node_t di_node) { int len; int *idata; int dcpuid = -1; len = get_reg_prop(di_node, &idata); if (len != SUN4V_CPU_REGSIZE) return (dcpuid); if (len == SUN4V_CPU_REGSIZE) dcpuid = CFGHDL_TO_CPUID(idata[0]); return (dcpuid); }
int add_cpu_prop(picl_nodehdl_t node, void *args) { mde_cookie_t *cpulistp; mde_cookie_t *cachelistp; mde_cookie_t *tlblistp; int x, num_nodes; int ncpus, ncaches, ntlbs; int status; int reg_prop[SUN4V_CPU_REGSIZE], cpuid; uint64_t int_value; status = ptree_get_propval_by_name(node, OBP_REG, reg_prop, sizeof (reg_prop)); if (status != PICL_SUCCESS) { return (PICL_WALK_TERMINATE); } cpuid = CFGHDL_TO_CPUID(reg_prop[0]); /* * Allocate space for our searches. */ num_nodes = md_node_count(mdp); cpulistp = (mde_cookie_t *) alloca(sizeof (mde_cookie_t) *num_nodes); if (cpulistp == NULL) { return (PICL_WALK_TERMINATE); } cachelistp = (mde_cookie_t *) alloca(sizeof (mde_cookie_t) *num_nodes); if (cachelistp == NULL) { return (PICL_WALK_TERMINATE); } tlblistp = (mde_cookie_t *) alloca(sizeof (mde_cookie_t) *num_nodes); if (tlblistp == NULL) { return (PICL_WALK_TERMINATE); } /* * Starting at the root node, scan the "fwd" dag for * all the cpus in this description. */ ncpus = md_scan_dag(mdp, rootnode, md_find_name(mdp, "cpu"), md_find_name(mdp, "fwd"), cpulistp); if (ncpus < 0) { return (PICL_WALK_TERMINATE); } /* * Create PD cpus with a few select properties */ for (x = 0; x < ncpus; x++) { if (md_get_prop_val(mdp, cpulistp[x], "id", &int_value)) { continue; } if (int_value != cpuid) continue; add_md_prop(node, sizeof (int_value), "cpuid", &int_value, PICL_PTYPE_INT); add_md_prop(node, sizeof (int_value), "portid", &int_value, PICL_PTYPE_INT); /* get caches for CPU */ ncaches = md_scan_dag(mdp, cpulistp[x], md_find_name(mdp, "cache"), md_find_name(mdp, "fwd"), cachelistp); add_cache_props(node, cachelistp, ncaches); /* get tlbs for CPU */ ntlbs = md_scan_dag(mdp, cpulistp[x], md_find_name(mdp, "tlb"), md_find_name(mdp, "fwd"), tlblistp); add_tlb_props(node, tlblistp, ntlbs); } return (PICL_WALK_CONTINUE); }