2 * drivers/misc/tegra-profiler/quadd_proc.c
4 * Copyright (c) 2014, NVIDIA CORPORATION. All rights reserved.
6 * This program is free software; you can redistribute it and/or modify it
7 * under the terms and conditions of the GNU General Public License,
8 * version 2, as published by the Free Software Foundation.
10 * This program is distributed in the hope it will be useful, but WITHOUT
11 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
12 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
19 #include <linux/proc_fs.h>
20 #include <linux/seq_file.h>
22 #include <linux/tegra_profiler.h>
26 #include "quadd_proc.h"
28 #define YES_NO(x) ((x) ? "yes" : "no")
30 static struct quadd_ctx *ctx;
32 #define QUADD_PROC_DEV QUADD_DEVICE_NAME
34 static int show_version(struct seq_file *f, void *offset)
36 seq_printf(f, "version: %s\n", QUADD_MODULE_VERSION);
37 seq_printf(f, "branch: %s\n", QUADD_MODULE_BRANCH);
38 seq_printf(f, "samples version: %d\n", QUADD_SAMPLES_VERSION);
39 seq_printf(f, "io version: %d\n", QUADD_IO_VERSION);
44 static int show_version_proc_open(struct inode *inode, struct file *file)
46 return single_open(file, show_version, NULL);
49 static const struct file_operations version_proc_fops = {
50 .open = show_version_proc_open,
53 .release = single_release,
56 static int show_capabilities(struct seq_file *f, void *offset)
58 struct quadd_comm_cap *cap = &ctx->cap;
59 struct quadd_events_cap *event = &cap->events_cap;
60 unsigned int extra = cap->reserved[QUADD_COMM_CAP_IDX_EXTRA];
62 seq_printf(f, "pmu: %s\n",
64 seq_printf(f, "tegra 3 LP cluster: %s\n",
65 YES_NO(cap->tegra_lp_cluster));
66 seq_printf(f, "power rate samples: %s\n",
67 YES_NO(cap->power_rate));
69 seq_printf(f, "l2 cache: %s\n",
70 YES_NO(cap->l2_cache));
72 seq_printf(f, "multiple l2 events: %s\n",
73 YES_NO(cap->l2_multiple_events));
76 seq_printf(f, "support polling mode: %s\n",
77 YES_NO(cap->blocked_read));
78 seq_printf(f, "backtrace from the kernel ctx: %s\n",
79 YES_NO(extra & QUADD_COMM_CAP_EXTRA_BT_KERNEL_CTX));
80 seq_printf(f, "send mmap regions at the start: %s\n",
81 YES_NO(extra & QUADD_COMM_CAP_EXTRA_GET_MMAP));
82 seq_printf(f, "group samples: %s\n",
83 YES_NO(extra & QUADD_COMM_CAP_EXTRA_GROUP_SAMPLES));
84 seq_printf(f, "unwinding based on ex-handling tables: %s\n",
85 YES_NO(extra & QUADD_COMM_CAP_EXTRA_BT_UNWIND_TABLES));
86 seq_printf(f, "support AArch64 architecture: %s\n",
87 YES_NO(extra & QUADD_COMM_CAP_EXTRA_SUPPORT_AARCH64));
88 seq_printf(f, "support special architecture mappings: %s\n",
89 YES_NO(extra & QUADD_COMM_CAP_EXTRA_SPECIAL_ARCH_MMAP));
90 seq_printf(f, "support mixed unwinding mode: %s\n",
91 YES_NO(extra & QUADD_COMM_CAP_EXTRA_UNWIND_MIXED));
92 seq_printf(f, "information about unwind entry: %s\n",
93 YES_NO(extra & QUADD_COMM_CAP_EXTRA_UNW_ENTRY_TYPE));
96 seq_puts(f, "Supported events:\n");
97 seq_printf(f, "cpu_cycles: %s\n",
98 YES_NO(event->cpu_cycles));
99 seq_printf(f, "instructions: %s\n",
100 YES_NO(event->instructions));
101 seq_printf(f, "branch_instructions: %s\n",
102 YES_NO(event->branch_instructions));
103 seq_printf(f, "branch_misses: %s\n",
104 YES_NO(event->branch_misses));
105 seq_printf(f, "bus_cycles: %s\n",
106 YES_NO(event->bus_cycles));
107 seq_printf(f, "l1_dcache_read_misses: %s\n",
108 YES_NO(event->l1_dcache_read_misses));
109 seq_printf(f, "l1_dcache_write_misses: %s\n",
110 YES_NO(event->l1_dcache_write_misses));
111 seq_printf(f, "l1_icache_misses: %s\n",
112 YES_NO(event->l1_icache_misses));
113 seq_printf(f, "l2_dcache_read_misses: %s\n",
114 YES_NO(event->l2_dcache_read_misses));
115 seq_printf(f, "l2_dcache_write_misses: %s\n",
116 YES_NO(event->l2_dcache_write_misses));
117 seq_printf(f, "l2_icache_misses: %s\n",
118 YES_NO(event->l2_icache_misses));
123 static int show_capabilities_proc_open(struct inode *inode, struct file *file)
125 return single_open(file, show_capabilities, NULL);
128 static const struct file_operations capabilities_proc_fops = {
129 .open = show_capabilities_proc_open,
132 .release = single_release,
135 static int show_status(struct seq_file *f, void *offset)
138 unsigned int is_auth_open, active;
139 struct quadd_module_state s;
142 status = s.reserved[QUADD_MOD_STATE_IDX_STATUS];
144 active = status & QUADD_MOD_STATE_STATUS_IS_ACTIVE;
145 is_auth_open = status & QUADD_MOD_STATE_STATUS_IS_AUTH_OPEN;
147 seq_printf(f, "status: %s\n", active ? "active" : "waiting");
148 seq_printf(f, "auth: %s\n", YES_NO(is_auth_open));
149 seq_printf(f, "all samples: %llu\n", s.nr_all_samples);
150 seq_printf(f, "skipped samples: %llu\n", s.nr_skipped_samples);
155 static int show_status_proc_open(struct inode *inode, struct file *file)
157 return single_open(file, show_status, NULL);
160 static const struct file_operations status_proc_fops = {
161 .open = show_status_proc_open,
164 .release = single_release,
167 void quadd_proc_init(struct quadd_ctx *context)
171 proc_mkdir(QUADD_PROC_DEV, NULL);
173 proc_create(QUADD_PROC_DEV "/version", 0, NULL, &version_proc_fops);
174 proc_create(QUADD_PROC_DEV "/capabilities", 0, NULL,
175 &capabilities_proc_fops);
176 proc_create(QUADD_PROC_DEV "/status", 0, NULL, &status_proc_fops);
179 void quadd_proc_deinit(void)
181 remove_proc_entry(QUADD_PROC_DEV "/version", NULL);
182 remove_proc_entry(QUADD_PROC_DEV "/capabilities", NULL);
183 remove_proc_entry(QUADD_PROC_DEV "/status", NULL);
184 remove_proc_entry(QUADD_PROC_DEV, NULL);
187 #endif /* CONFIG_PROC_FS */