static ssize_t node_read_distance(struct device *dev, struct device_attribute *attr, char * buf) { int nid = dev->id; int len = 0; int i; /* * buf is currently PAGE_SIZE in length and each node needs 4 chars * at the most (distance + space or newline). */ BUILD_BUG_ON(MAX_NUMNODES * 4 > PAGE_SIZE); for_each_online_node(i) len += sprintf(buf + len, "%s%d", i ? " " : "", node_distance(nid, i)); len += sprintf(buf + len, "\n"); return len; }
/** * acpi_map_pxm_to_online_node - Map proximity ID to online node * @pxm: ACPI proximity ID * * This is similar to acpi_map_pxm_to_node(), but always returns an online * node. When the mapped node from a given proximity ID is offline, it * looks up the node distance table and returns the nearest online node. * * ACPI device drivers, which are called after the NUMA initialization has * completed in the kernel, can call this interface to obtain their device * NUMA topology from ACPI tables. Such drivers do not have to deal with * offline nodes. A node may be offline when a device proximity ID is * unique, SRAT memory entry does not exist, or NUMA is disabled, ex. * "numa=off" on x86. */ int acpi_map_pxm_to_online_node(int pxm) { int node, n, dist, min_dist; node = acpi_map_pxm_to_node(pxm); if (node == NUMA_NO_NODE) node = 0; if (!node_online(node)) { min_dist = INT_MAX; for_each_online_node(n) { dist = node_distance(node, n); if (dist < min_dist) { min_dist = dist; node = n; } } }
void quick_core(vector<node> s, node a, node b, vector<node>& con) {//位于a->b的左边区域的点集s,返回该区域中的凸包顶点,存储于数组con中 //递归终止条件 if(s.empty()) return; //找出区域s中距离向量a->b所在直线距离最远的点far_pos vector<node>::iterator far_pos; double dist(0); for(vector<node>::iterator it = s.begin(); it != s.end(); ++ it){ //点it到向量a->b所在直线的距离为a->b和a->it的叉积除以a->b的长度 double d = cross(vec(a, b), vec(a, *it)) / node_distance(a, b); if(dist < d){ //若点it到a->b所在直线的距离d比dist大则更新dist //并用far_pos记下当前点i是距离最远的点 far_pos = it; dist = d; } } //将far_pos点加入凸包 con.push_back(*far_pos); //在s中删去far_pos,但需要保留一个备份far node far(*far_pos); s.erase(far_pos); vector<node> lt, rt; for(vector<node>::iterator it = s.begin(); it != s.end(); ++ it){ //遍历区域s中每个点i //计算a->far和a->it的叉积,若为正,则点it在向量a->far的左边 if(cross(vec(a, far), vec(a, *it)) > 0) lt.push_back(*it); //计算far->b和far->i的叉积,若为正,则点it在far->b的左边 if(cross(vec(far, b), vec(far, *it)) > 0) rt.push_back(*it); } //继续递归 //求向量a->far左边的区域中的凸包顶点 quick_core(lt, a, far, con); //求向量far->b左边的区域中的凸包顶点 quick_core(rt, far, b, con); }
static int __init pcpu_cpu_distance(unsigned int from, unsigned int to) { return node_distance(early_cpu_to_node(from), early_cpu_to_node(to)); }
void __init acpi_numa_arch_fixup(void) { int i, j, node_from, node_to; /* If there's no SRAT, fix the phys_id and mark node 0 online */ if (srat_num_cpus == 0) { node_set_online(0); node_cpuid[0].phys_id = hard_smp_processor_id(); return; } /* * MCD - This can probably be dropped now. No need for pxm ID to node ID * mapping with sparse node numbering iff MAX_PXM_DOMAINS <= MAX_NUMNODES. */ nodes_clear(node_online_map); for (i = 0; i < MAX_PXM_DOMAINS; i++) { if (pxm_bit_test(i)) { int nid = acpi_map_pxm_to_node(i); node_set_online(nid); } } /* set logical node id in memory chunk structure */ for (i = 0; i < num_node_memblks; i++) node_memblk[i].nid = pxm_to_node(node_memblk[i].nid); /* assign memory bank numbers for each chunk on each node */ for_each_online_node(i) { int bank; bank = 0; for (j = 0; j < num_node_memblks; j++) if (node_memblk[j].nid == i) node_memblk[j].bank = bank++; } /* set logical node id in cpu structure */ for_each_possible_early_cpu(i) node_cpuid[i].nid = pxm_to_node(node_cpuid[i].nid); printk(KERN_INFO "Number of logical nodes in system = %d\n", num_online_nodes()); printk(KERN_INFO "Number of memory chunks in system = %d\n", num_node_memblks); if (!slit_table) return; memset(numa_slit, -1, sizeof(numa_slit)); for (i = 0; i < slit_table->locality_count; i++) { if (!pxm_bit_test(i)) continue; node_from = pxm_to_node(i); for (j = 0; j < slit_table->locality_count; j++) { if (!pxm_bit_test(j)) continue; node_to = pxm_to_node(j); node_distance(node_from, node_to) = slit_table->entry[i * slit_table->locality_count + j]; } } #ifdef SLIT_DEBUG printk("ACPI 2.0 SLIT locality table:\n"); for_each_online_node(i) { for_each_online_node(j) printk("%03d ", node_distance(i, j)); printk("\n"); } #endif }
void __init acpi_numa_arch_fixup (void) { int i, j, node_from, node_to; /* If there's no SRAT, fix the phys_id and mark node 0 online */ if (srat_num_cpus == 0) { node_set_online(0); node_cpuid[0].phys_id = hard_smp_processor_id(); return; } /* calculate total number of nodes in system from PXM bitmap */ numnodes = 0; /* init total nodes in system */ memset(pxm_to_nid_map, -1, sizeof(pxm_to_nid_map)); memset(nid_to_pxm_map, -1, sizeof(nid_to_pxm_map)); for (i = 0; i < MAX_PXM_DOMAINS; i++) { if (pxm_bit_test(i)) { pxm_to_nid_map[i] = numnodes; node_set_online(numnodes); nid_to_pxm_map[numnodes++] = i; } } /* set logical node id in memory chunk structure */ for (i = 0; i < num_node_memblks; i++) node_memblk[i].nid = pxm_to_nid_map[node_memblk[i].nid]; /* assign memory bank numbers for each chunk on each node */ for (i = 0; i < numnodes; i++) { int bank; bank = 0; for (j = 0; j < num_node_memblks; j++) if (node_memblk[j].nid == i) node_memblk[j].bank = bank++; } /* set logical node id in cpu structure */ for (i = 0; i < srat_num_cpus; i++) node_cpuid[i].nid = pxm_to_nid_map[node_cpuid[i].nid]; printk(KERN_INFO "Number of logical nodes in system = %d\n", numnodes); printk(KERN_INFO "Number of memory chunks in system = %d\n", num_node_memblks); if (!slit_table) return; memset(numa_slit, -1, sizeof(numa_slit)); for (i=0; i<slit_table->localities; i++) { if (!pxm_bit_test(i)) continue; node_from = pxm_to_nid_map[i]; for (j=0; j<slit_table->localities; j++) { if (!pxm_bit_test(j)) continue; node_to = pxm_to_nid_map[j]; node_distance(node_from, node_to) = slit_table->entry[i*slit_table->localities + j]; } } #ifdef SLIT_DEBUG printk("ACPI 2.0 SLIT locality table:\n"); for (i = 0; i < numnodes; i++) { for (j = 0; j < numnodes; j++) printk("%03d ", node_distance(i,j)); printk("\n"); } #endif }
static int sn_topology_show(struct seq_file *s, void *d) { int sz; int pt; int e = 0; int i; int j; const char *slabname; int ordinal; cpumask_t cpumask; char slice; struct cpuinfo_ia64 *c; struct sn_hwperf_port_info *ptdata; struct sn_hwperf_object_info *p; struct sn_hwperf_object_info *obj = d; /* this object */ struct sn_hwperf_object_info *objs = s->private; /* all objects */ int rack, bay, slot, slab; u8 shubtype; u8 system_size; u8 sharing_size; u8 partid; u8 coher; u8 nasid_shift; u8 region_size; u16 nasid_mask; int nasid_msb; int pci_bus_ordinal = 0; if (obj == objs) { seq_printf(s, "# sn_topology version 2\n"); seq_printf(s, "# objtype ordinal location partition" " [attribute value [, ...]]\n"); if (ia64_sn_get_sn_info(0, &shubtype, &nasid_mask, &nasid_shift, &system_size, &sharing_size, &partid, &coher, ®ion_size)) BUG(); for (nasid_msb=63; nasid_msb > 0; nasid_msb--) { if (((u64)nasid_mask << nasid_shift) & (1ULL << nasid_msb)) break; } seq_printf(s, "partition %u %s local " "shubtype %s, " "nasid_mask 0x%016lx, " "nasid_bits %d:%d, " "system_size %d, " "sharing_size %d, " "coherency_domain %d, " "region_size %d\n", partid, system_utsname.nodename, shubtype ? "shub2" : "shub1", (u64)nasid_mask << nasid_shift, nasid_msb, nasid_shift, system_size, sharing_size, coher, region_size); } if (SN_HWPERF_FOREIGN(obj)) { /* private in another partition: not interesting */ return 0; } for (i = 0; i < SN_HWPERF_MAXSTRING && obj->name[i]; i++) { if (obj->name[i] == ' ') obj->name[i] = '_'; } slabname = sn_hwperf_get_slabname(obj, objs, &ordinal); seq_printf(s, "%s %d %s %s asic %s", slabname, ordinal, obj->location, obj->sn_hwp_this_part ? "local" : "shared", obj->name); if (!SN_HWPERF_IS_NODE(obj) && !SN_HWPERF_IS_IONODE(obj)) seq_putc(s, '\n'); else { seq_printf(s, ", nasid 0x%x", cnodeid_to_nasid(ordinal)); for (i=0; i < numionodes; i++) { seq_printf(s, i ? ":%d" : ", dist %d", node_distance(ordinal, i)); } seq_putc(s, '\n'); /* * CPUs on this node, if any */ cpumask = node_to_cpumask(ordinal); for_each_online_cpu(i) { if (cpu_isset(i, cpumask)) { slice = 'a' + cpuid_to_slice(i); c = cpu_data(i); seq_printf(s, "cpu %d %s%c local" " freq %luMHz, arch ia64", i, obj->location, slice, c->proc_freq / 1000000); for_each_online_cpu(j) { seq_printf(s, j ? ":%d" : ", dist %d", node_distance( cpuid_to_cnodeid(i), cpuid_to_cnodeid(j))); } seq_putc(s, '\n'); } } /* * PCI busses attached to this node, if any */ if (sn_hwperf_location_to_bpos(obj->location, &rack, &bay, &slot, &slab)) { /* export pci bus info */ print_pci_topology(s, obj, &pci_bus_ordinal, rack, bay, slot, slab); } } if (obj->ports) { /* * numalink ports */ sz = obj->ports * sizeof(struct sn_hwperf_port_info); if ((ptdata = vmalloc(sz)) == NULL) return -ENOMEM; e = ia64_sn_hwperf_op(sn_hwperf_master_nasid, SN_HWPERF_ENUM_PORTS, obj->id, sz, (u64) ptdata, 0, 0, NULL); if (e != SN_HWPERF_OP_OK) return -EINVAL; for (ordinal=0, p=objs; p != obj; p++) { if (!SN_HWPERF_FOREIGN(p)) ordinal += p->ports; } for (pt = 0; pt < obj->ports; pt++) { for (p = objs, i = 0; i < sn_hwperf_obj_cnt; i++, p++) { if (ptdata[pt].conn_id == p->id) { break; } } seq_printf(s, "numalink %d %s-%d", ordinal+pt, obj->location, ptdata[pt].port); if (i >= sn_hwperf_obj_cnt) { /* no connection */ seq_puts(s, " local endpoint disconnected" ", protocol unknown\n"); continue; } if (obj->sn_hwp_this_part && p->sn_hwp_this_part) /* both ends local to this partition */ seq_puts(s, " local"); else if (!obj->sn_hwp_this_part && !p->sn_hwp_this_part) /* both ends of the link in foreign partiton */ seq_puts(s, " foreign"); else /* link straddles a partition */ seq_puts(s, " shared"); /* * Unlikely, but strictly should query the LLP config * registers because an NL4R can be configured to run * NL3 protocol, even when not talking to an NL3 router. * Ditto for node-node. */ seq_printf(s, " endpoint %s-%d, protocol %s\n", p->location, ptdata[pt].conn_port, (SN_HWPERF_IS_NL3ROUTER(obj) || SN_HWPERF_IS_NL3ROUTER(p)) ? "LLP3" : "LLP4"); } vfree(ptdata); } return 0; }
void __init acpi_numa_arch_fixup(void) { int i, j, node_from, node_to; if (srat_num_cpus == 0) { node_set_online(0); node_cpuid[0].phys_id = hard_smp_processor_id(); return; } nodes_clear(node_online_map); for (i = 0; i < MAX_PXM_DOMAINS; i++) { if (pxm_bit_test(i)) { int nid = acpi_map_pxm_to_node(i); node_set_online(nid); } } for (i = 0; i < num_node_memblks; i++) node_memblk[i].nid = pxm_to_node(node_memblk[i].nid); for_each_online_node(i) { int bank; bank = 0; for (j = 0; j < num_node_memblks; j++) if (node_memblk[j].nid == i) node_memblk[j].bank = bank++; } for_each_possible_early_cpu(i) node_cpuid[i].nid = pxm_to_node(node_cpuid[i].nid); printk(KERN_INFO "Number of logical nodes in system = %d\n", num_online_nodes()); printk(KERN_INFO "Number of memory chunks in system = %d\n", num_node_memblks); if (!slit_table) { for (i = 0; i < MAX_NUMNODES; i++) for (j = 0; j < MAX_NUMNODES; j++) node_distance(i, j) = i == j ? LOCAL_DISTANCE : REMOTE_DISTANCE; return; } memset(numa_slit, -1, sizeof(numa_slit)); for (i = 0; i < slit_table->locality_count; i++) { if (!pxm_bit_test(i)) continue; node_from = pxm_to_node(i); for (j = 0; j < slit_table->locality_count; j++) { if (!pxm_bit_test(j)) continue; node_to = pxm_to_node(j); node_distance(node_from, node_to) = slit_table->entry[i * slit_table->locality_count + j]; } } #ifdef SLIT_DEBUG printk("ACPI 2.0 SLIT locality table:\n"); for_each_online_node(i) { for_each_online_node(j) printk("%03d ", node_distance(i, j)); printk("\n"); } #endif }