Back to home page

OSCL-LXR

 
 

    


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              * Merge nearby areas, we walk in order
0081              * through the bitmap, so no need to sort.
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     /* Cut unused entries, due to merging. */
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 }