0001 #include <errno.h>
0002 #include <inttypes.h>
0003 #include <asm/bug.h>
0004 #include <linux/bitmap.h>
0005 #include <linux/kernel.h>
0006 #include <linux/zalloc.h>
0007 #include "debug.h"
0008 #include "env.h"
0009 #include "mem2node.h"
0010
0011 struct phys_entry {
0012 struct rb_node rb_node;
0013 u64 start;
0014 u64 end;
0015 u64 node;
0016 };
0017
0018 static void phys_entry__insert(struct phys_entry *entry, struct rb_root *root)
0019 {
0020 struct rb_node **p = &root->rb_node;
0021 struct rb_node *parent = NULL;
0022 struct phys_entry *e;
0023
0024 while (*p != NULL) {
0025 parent = *p;
0026 e = rb_entry(parent, struct phys_entry, rb_node);
0027
0028 if (entry->start < e->start)
0029 p = &(*p)->rb_left;
0030 else
0031 p = &(*p)->rb_right;
0032 }
0033
0034 rb_link_node(&entry->rb_node, parent, p);
0035 rb_insert_color(&entry->rb_node, root);
0036 }
0037
0038 static void
0039 phys_entry__init(struct phys_entry *entry, u64 start, u64 bsize, u64 node)
0040 {
0041 entry->start = start;
0042 entry->end = start + bsize;
0043 entry->node = node;
0044 RB_CLEAR_NODE(&entry->rb_node);
0045 }
0046
0047 int mem2node__init(struct mem2node *map, struct perf_env *env)
0048 {
0049 struct memory_node *n, *nodes = &env->memory_nodes[0];
0050 struct phys_entry *entries, *tmp_entries;
0051 u64 bsize = env->memory_bsize;
0052 int i, j = 0, max = 0;
0053
0054 memset(map, 0x0, sizeof(*map));
0055 map->root = RB_ROOT;
0056
0057 for (i = 0; i < env->nr_memory_nodes; i++) {
0058 n = &nodes[i];
0059 max += bitmap_weight(n->set, n->size);
0060 }
0061
0062 entries = zalloc(sizeof(*entries) * max);
0063 if (!entries)
0064 return -ENOMEM;
0065
0066 for (i = 0; i < env->nr_memory_nodes; i++) {
0067 u64 bit;
0068
0069 n = &nodes[i];
0070
0071 for (bit = 0; bit < n->size; bit++) {
0072 u64 start;
0073
0074 if (!test_bit(bit, n->set))
0075 continue;
0076
0077 start = bit * bsize;
0078
0079
0080
0081
0082
0083 if (j > 0) {
0084 struct phys_entry *prev = &entries[j - 1];
0085
0086 if ((prev->end == start) &&
0087 (prev->node == n->node)) {
0088 prev->end += bsize;
0089 continue;
0090 }
0091 }
0092
0093 phys_entry__init(&entries[j++], start, bsize, n->node);
0094 }
0095 }
0096
0097
0098 tmp_entries = realloc(entries, sizeof(*entries) * j);
0099 if (tmp_entries ||
0100 WARN_ONCE(j == 0, "No memory nodes, is CONFIG_MEMORY_HOTPLUG enabled?\n"))
0101 entries = tmp_entries;
0102
0103 for (i = 0; i < j; i++) {
0104 pr_debug("mem2node %03" PRIu64 " [0x%016" PRIx64 "-0x%016" PRIx64 "]\n",
0105 entries[i].node, entries[i].start, entries[i].end);
0106
0107 phys_entry__insert(&entries[i], &map->root);
0108 }
0109
0110 map->entries = entries;
0111 return 0;
0112 }
0113
0114 void mem2node__exit(struct mem2node *map)
0115 {
0116 zfree(&map->entries);
0117 }
0118
0119 int mem2node__node(struct mem2node *map, u64 addr)
0120 {
0121 struct rb_node **p, *parent = NULL;
0122 struct phys_entry *entry;
0123
0124 p = &map->root.rb_node;
0125 while (*p != NULL) {
0126 parent = *p;
0127 entry = rb_entry(parent, struct phys_entry, rb_node);
0128 if (addr < entry->start)
0129 p = &(*p)->rb_left;
0130 else if (addr >= entry->end)
0131 p = &(*p)->rb_right;
0132 else
0133 goto out;
0134 }
0135
0136 entry = NULL;
0137 out:
0138 return entry ? (int) entry->node : -1;
0139 }