4 #include <linux/bitmap.h>
5 #include <linux/kernel.h>
6 #include <linux/zalloc.h>
12 struct rb_node rb_node
;
18 static void phys_entry__insert(struct phys_entry
*entry
, struct rb_root
*root
)
20 struct rb_node
**p
= &root
->rb_node
;
21 struct rb_node
*parent
= NULL
;
26 e
= rb_entry(parent
, struct phys_entry
, rb_node
);
28 if (entry
->start
< e
->start
)
34 rb_link_node(&entry
->rb_node
, parent
, p
);
35 rb_insert_color(&entry
->rb_node
, root
);
39 phys_entry__init(struct phys_entry
*entry
, u64 start
, u64 bsize
, u64 node
)
42 entry
->end
= start
+ bsize
;
44 RB_CLEAR_NODE(&entry
->rb_node
);
47 int mem2node__init(struct mem2node
*map
, struct perf_env
*env
)
49 struct memory_node
*n
, *nodes
= &env
->memory_nodes
[0];
50 struct phys_entry
*entries
, *tmp_entries
;
51 u64 bsize
= env
->memory_bsize
;
52 int i
, j
= 0, max
= 0;
54 memset(map
, 0x0, sizeof(*map
));
57 for (i
= 0; i
< env
->nr_memory_nodes
; i
++) {
59 max
+= bitmap_weight(n
->set
, n
->size
);
62 entries
= zalloc(sizeof(*entries
) * max
);
66 for (i
= 0; i
< env
->nr_memory_nodes
; i
++) {
71 for (bit
= 0; bit
< n
->size
; bit
++) {
74 if (!test_bit(bit
, n
->set
))
80 * Merge nearby areas, we walk in order
81 * through the bitmap, so no need to sort.
84 struct phys_entry
*prev
= &entries
[j
- 1];
86 if ((prev
->end
== start
) &&
87 (prev
->node
== n
->node
)) {
93 phys_entry__init(&entries
[j
++], start
, bsize
, n
->node
);
97 /* Cut unused entries, due to merging. */
98 tmp_entries
= realloc(entries
, sizeof(*entries
) * j
);
99 if (tmp_entries
|| WARN_ON_ONCE(j
== 0))
100 entries
= tmp_entries
;
102 for (i
= 0; i
< j
; i
++) {
103 pr_debug("mem2node %03" PRIu64
" [0x%016" PRIx64
"-0x%016" PRIx64
"]\n",
104 entries
[i
].node
, entries
[i
].start
, entries
[i
].end
);
106 phys_entry__insert(&entries
[i
], &map
->root
);
109 map
->entries
= entries
;
113 void mem2node__exit(struct mem2node
*map
)
115 zfree(&map
->entries
);
118 int mem2node__node(struct mem2node
*map
, u64 addr
)
120 struct rb_node
**p
, *parent
= NULL
;
121 struct phys_entry
*entry
;
123 p
= &map
->root
.rb_node
;
126 entry
= rb_entry(parent
, struct phys_entry
, rb_node
);
127 if (addr
< entry
->start
)
129 else if (addr
>= entry
->end
)
137 return entry
? (int) entry
->node
: -1;