4 unsigned long pmnc_counters;
5 /* Human readable name */
6 char core_name[MAXSIZE_CORE_NAME];
7 /* gatorfs event and Perf PMU name */
8 char pmnc_name[MAXSIZE_CORE_NAME];
9 /* compatible from Documentation/devicetree/bindings/arm/cpus.txt */
10 char dt_name[MAXSIZE_CORE_NAME];
14 struct list_head list;
15 unsigned long pmnc_counters;
16 unsigned long has_cycles_counter;
18 char pmnc_name[MAXSIZE_CORE_NAME];
19 /* gatorfs event name */
20 char core_name[MAXSIZE_CORE_NAME];
23 static LIST_HEAD(uncore_pmus);
24 static LIST_HEAD(gator_cpus);
25 static DEFINE_MUTEX(pmu_mutex);
27 static struct super_block *gator_sb;
28 static struct dentry *gator_events_dir;
30 static const struct gator_cpu *gator_find_cpu_by_cpuid(const u32 cpuid)
32 const struct gator_cpu *gator_cpu;
34 list_for_each_entry(gator_cpu, &gator_cpus, list) {
35 if (gator_cpu->cpuid == cpuid)
42 static const char OLD_PMU_PREFIX[] = "ARMv7 Cortex-";
43 static const char NEW_PMU_PREFIX[] = "ARMv7_Cortex_";
46 static const struct gator_cpu *gator_find_cpu_by_pmu_name(const char *const name)
48 const struct gator_cpu *gator_cpu;
50 list_for_each_entry(gator_cpu, &gator_cpus, list) {
51 if (gator_cpu->pmnc_name != NULL &&
52 /* Do the names match exactly? */
53 (strcasecmp(gator_cpu->pmnc_name, name) == 0 ||
54 /* Do these names match but have the old vs new prefix? */
55 ((strncasecmp(name, OLD_PMU_PREFIX, sizeof(OLD_PMU_PREFIX) - 1) == 0 &&
56 strncasecmp(gator_cpu->pmnc_name, NEW_PMU_PREFIX, sizeof(NEW_PMU_PREFIX) - 1) == 0 &&
57 strcasecmp(name + sizeof(OLD_PMU_PREFIX) - 1, gator_cpu->pmnc_name + sizeof(NEW_PMU_PREFIX) - 1) == 0))))
65 static const struct uncore_pmu *gator_find_uncore_pmu(const char *const name)
67 const struct uncore_pmu *uncore_pmu;
69 list_for_each_entry(uncore_pmu, &uncore_pmus, list) {
70 if (uncore_pmu->pmnc_name != NULL && strcasecmp(uncore_pmu->pmnc_name, name) == 0)
77 static bool gator_pmu_initialized;
79 static ssize_t gator_pmu_init_write(struct file *file, char const __user *buf, size_t count, loff_t *offset)
81 if (gator_pmu_initialized)
83 gator_pmu_initialized = true;
84 if (gator_events_perf_pmu_reread() != 0 ||
85 gator_events_perf_pmu_create_files(gator_sb, gator_events_dir) != 0)
90 static const struct file_operations gator_pmu_init_fops = {
91 .write = gator_pmu_init_write,
94 static ssize_t gator_pmu_str_read_file(struct file *file, char __user *buf, size_t count, loff_t *offset)
96 char *const val = file->private_data;
98 return simple_read_from_buffer(buf, count, offset, val, strlen(val));
101 static ssize_t gator_pmu_str_write_file(struct file *file, char const __user *buf, size_t count, loff_t *offset)
103 char *value = file->private_data;
108 if (count >= MAXSIZE_CORE_NAME)
110 if (copy_from_user(value, buf, count))
113 value = strstrip(value);
118 static const struct file_operations gator_pmu_str_fops = {
119 .read = gator_pmu_str_read_file,
120 .write = gator_pmu_str_write_file,
121 .open = default_open,
124 static int gator_pmu_create_str(struct super_block *sb, struct dentry *root, char const *name, char *const val)
126 struct dentry *d = __gatorfs_create_file(sb, root, name, &gator_pmu_str_fops, 0644);
130 d->d_inode->i_private = val;
134 static ssize_t gator_pmu_export_write(struct file *file, char const __user *ubuf, size_t count, loff_t *offset)
137 struct dentry *parent;
138 char buf[MAXSIZE_CORE_NAME];
144 if (count >= sizeof(buf))
146 if (copy_from_user(&buf, ubuf, count))
151 parent = file->f_path.dentry->d_parent;
152 dir = gatorfs_mkdir(gator_sb, parent, buf);
156 if (strcmp("pmu", parent->d_name.name) == 0) {
157 struct gator_cpu *gator_cpu;
159 gator_cpu = kmalloc(sizeof(*gator_cpu), GFP_KERNEL);
160 if (gator_cpu == NULL)
162 memset(gator_cpu, 0, sizeof(*gator_cpu));
164 gatorfs_create_ulong(gator_sb, dir, "cpuid", &gator_cpu->cpuid);
165 gator_pmu_create_str(gator_sb, dir, "core_name", gator_cpu->core_name);
166 strcpy(gator_cpu->pmnc_name, str);
167 gator_pmu_create_str(gator_sb, dir, "dt_name", gator_cpu->dt_name);
168 gatorfs_create_ulong(gator_sb, dir, "pmnc_counters", &gator_cpu->pmnc_counters);
170 mutex_lock(&pmu_mutex);
171 list_add_tail(&gator_cpu->list, &gator_cpus); /* mutex */
172 mutex_unlock(&pmu_mutex);
174 struct uncore_pmu *uncore_pmu;
176 uncore_pmu = kmalloc(sizeof(*uncore_pmu), GFP_KERNEL);
177 if (uncore_pmu == NULL)
179 memset(uncore_pmu, 0, sizeof(*uncore_pmu));
181 strcpy(uncore_pmu->pmnc_name, str);
182 gator_pmu_create_str(gator_sb, dir, "core_name", uncore_pmu->core_name);
183 gatorfs_create_ulong(gator_sb, dir, "pmnc_counters", &uncore_pmu->pmnc_counters);
184 gatorfs_create_ulong(gator_sb, dir, "has_cycles_counter", &uncore_pmu->has_cycles_counter);
186 mutex_lock(&pmu_mutex);
187 list_add_tail(&uncore_pmu->list, &uncore_pmus); /* mutex */
188 mutex_unlock(&pmu_mutex);
194 static const struct file_operations export_fops = {
195 .write = gator_pmu_export_write,
198 static int gator_pmu_create_files(struct super_block *sb, struct dentry *root, struct dentry *events)
203 gator_events_dir = events;
205 gatorfs_create_file(sb, root, "pmu_init", &gator_pmu_init_fops);
207 dir = gatorfs_mkdir(sb, root, "pmu");
211 gatorfs_create_file(sb, dir, "export", &export_fops);
213 dir = gatorfs_mkdir(sb, root, "uncore_pmu");
217 gatorfs_create_file(sb, dir, "export", &export_fops);
222 static void gator_pmu_exit(void)
224 mutex_lock(&pmu_mutex);
226 struct gator_cpu *gator_cpu;
227 struct gator_cpu *next;
229 list_for_each_entry_safe(gator_cpu, next, &gator_cpus, list) {
234 struct uncore_pmu *uncore_pmu;
235 struct uncore_pmu *next;
237 list_for_each_entry_safe(uncore_pmu, next, &uncore_pmus, list) {
241 mutex_unlock(&pmu_mutex);