^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 1) #include <errno.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 2) #include <inttypes.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 3) #include <asm/bug.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 4) #include <linux/bitmap.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 5) #include <linux/kernel.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 6) #include <linux/zalloc.h>
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 7) #include "debug.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 8) #include "env.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 9) #include "mem2node.h"
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 10)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 11) struct phys_entry {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 12) struct rb_node rb_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 13) u64 start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 14) u64 end;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 15) u64 node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 16) };
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 17)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 18) static void phys_entry__insert(struct phys_entry *entry, struct rb_root *root)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 19) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 20) struct rb_node **p = &root->rb_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 21) struct rb_node *parent = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 22) struct phys_entry *e;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 23)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 24) while (*p != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 25) parent = *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 26) e = rb_entry(parent, struct phys_entry, rb_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 27)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 28) if (entry->start < e->start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 29) p = &(*p)->rb_left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 30) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 31) p = &(*p)->rb_right;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 32) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 33)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 34) rb_link_node(&entry->rb_node, parent, p);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 35) rb_insert_color(&entry->rb_node, root);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 36) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 37)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 38) static void
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 39) phys_entry__init(struct phys_entry *entry, u64 start, u64 bsize, u64 node)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 40) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 41) entry->start = start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 42) entry->end = start + bsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 43) entry->node = node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 44) RB_CLEAR_NODE(&entry->rb_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 45) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 46)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 47) int mem2node__init(struct mem2node *map, struct perf_env *env)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 48) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 49) struct memory_node *n, *nodes = &env->memory_nodes[0];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 50) struct phys_entry *entries, *tmp_entries;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 51) u64 bsize = env->memory_bsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 52) int i, j = 0, max = 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 53)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 54) memset(map, 0x0, sizeof(*map));
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 55) map->root = RB_ROOT;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 56)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 57) for (i = 0; i < env->nr_memory_nodes; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 58) n = &nodes[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 59) max += bitmap_weight(n->set, n->size);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 60) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 61)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 62) entries = zalloc(sizeof(*entries) * max);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 63) if (!entries)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 64) return -ENOMEM;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 65)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 66) for (i = 0; i < env->nr_memory_nodes; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 67) u64 bit;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 68)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 69) n = &nodes[i];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 70)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 71) for (bit = 0; bit < n->size; bit++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 72) u64 start;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 73)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 74) if (!test_bit(bit, n->set))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 75) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 76)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 77) start = bit * bsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 78)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 79) /*
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 80) * Merge nearby areas, we walk in order
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 81) * through the bitmap, so no need to sort.
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 82) */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 83) if (j > 0) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 84) struct phys_entry *prev = &entries[j - 1];
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 85)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 86) if ((prev->end == start) &&
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 87) (prev->node == n->node)) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 88) prev->end += bsize;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 89) continue;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 90) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 91) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 92)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 93) phys_entry__init(&entries[j++], start, bsize, n->node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 94) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 95) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 96)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 97) /* Cut unused entries, due to merging. */
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 98) tmp_entries = realloc(entries, sizeof(*entries) * j);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 99) if (tmp_entries || WARN_ON_ONCE(j == 0))
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 100) entries = tmp_entries;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 101)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 102) for (i = 0; i < j; i++) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 103) pr_debug("mem2node %03" PRIu64 " [0x%016" PRIx64 "-0x%016" PRIx64 "]\n",
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 104) entries[i].node, entries[i].start, entries[i].end);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 105)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 106) phys_entry__insert(&entries[i], &map->root);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 107) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 108)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 109) map->entries = entries;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 110) return 0;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 111) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 112)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 113) void mem2node__exit(struct mem2node *map)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 114) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 115) zfree(&map->entries);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 116) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 117)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 118) int mem2node__node(struct mem2node *map, u64 addr)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 119) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 120) struct rb_node **p, *parent = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 121) struct phys_entry *entry;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 122)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 123) p = &map->root.rb_node;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 124) while (*p != NULL) {
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 125) parent = *p;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 126) entry = rb_entry(parent, struct phys_entry, rb_node);
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 127) if (addr < entry->start)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 128) p = &(*p)->rb_left;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 129) else if (addr >= entry->end)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 130) p = &(*p)->rb_right;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 131) else
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 132) goto out;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 133) }
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 134)
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 135) entry = NULL;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 136) out:
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 137) return entry ? (int) entry->node : -1;
^8f3ce5b39 (kx 2023-10-28 12:00:06 +0300 138) }