aboutsummaryrefslogtreecommitdiffstats
path: root/kernel
diff options
context:
space:
mode:
Diffstat (limited to 'kernel')
-rw-r--r--kernel/perf_counter.c145
1 files changed, 145 insertions, 0 deletions
diff --git a/kernel/perf_counter.c b/kernel/perf_counter.c
index c95e92329b97..f35e89e3d6a4 100644
--- a/kernel/perf_counter.c
+++ b/kernel/perf_counter.c
@@ -25,6 +25,7 @@
25#include <linux/anon_inodes.h> 25#include <linux/anon_inodes.h>
26#include <linux/kernel_stat.h> 26#include <linux/kernel_stat.h>
27#include <linux/perf_counter.h> 27#include <linux/perf_counter.h>
28#include <linux/dcache.h>
28 29
29#include <asm/irq_regs.h> 30#include <asm/irq_regs.h>
30 31
@@ -1844,6 +1845,150 @@ void perf_counter_output(struct perf_counter *counter,
1844} 1845}
1845 1846
1846/* 1847/*
1848 * mmap tracking
1849 */
1850
1851struct perf_mmap_event {
1852 struct file *file;
1853 char *file_name;
1854 int file_size;
1855
1856 struct {
1857 struct perf_event_header header;
1858
1859 u32 pid;
1860 u32 tid;
1861 u64 start;
1862 u64 len;
1863 u64 pgoff;
1864 } event;
1865};
1866
1867static void perf_counter_mmap_output(struct perf_counter *counter,
1868 struct perf_mmap_event *mmap_event)
1869{
1870 struct perf_output_handle handle;
1871 int size = mmap_event->event.header.size;
1872 int ret = perf_output_begin(&handle, counter, size);
1873
1874 if (ret)
1875 return;
1876
1877 perf_output_put(&handle, mmap_event->event);
1878 perf_output_copy(&handle, mmap_event->file_name,
1879 mmap_event->file_size);
1880 perf_output_end(&handle, 0);
1881}
1882
1883static int perf_counter_mmap_match(struct perf_counter *counter,
1884 struct perf_mmap_event *mmap_event)
1885{
1886 if (counter->hw_event.mmap &&
1887 mmap_event->event.header.type == PERF_EVENT_MMAP)
1888 return 1;
1889
1890 if (counter->hw_event.munmap &&
1891 mmap_event->event.header.type == PERF_EVENT_MUNMAP)
1892 return 1;
1893
1894 return 0;
1895}
1896
1897static void perf_counter_mmap_ctx(struct perf_counter_context *ctx,
1898 struct perf_mmap_event *mmap_event)
1899{
1900 struct perf_counter *counter;
1901
1902 if (system_state != SYSTEM_RUNNING || list_empty(&ctx->event_list))
1903 return;
1904
1905 rcu_read_lock();
1906 list_for_each_entry_rcu(counter, &ctx->event_list, event_entry) {
1907 if (perf_counter_mmap_match(counter, mmap_event))
1908 perf_counter_mmap_output(counter, mmap_event);
1909 }
1910 rcu_read_unlock();
1911}
1912
1913static void perf_counter_mmap_event(struct perf_mmap_event *mmap_event)
1914{
1915 struct perf_cpu_context *cpuctx;
1916 struct file *file = mmap_event->file;
1917 unsigned int size;
1918 char tmp[16];
1919 char *buf = NULL;
1920 char *name;
1921
1922 if (file) {
1923 buf = kzalloc(PATH_MAX, GFP_KERNEL);
1924 if (!buf) {
1925 name = strncpy(tmp, "//enomem", sizeof(tmp));
1926 goto got_name;
1927 }
1928 name = dentry_path(file->f_dentry, buf, PATH_MAX);
1929 if (IS_ERR(name)) {
1930 name = strncpy(tmp, "//toolong", sizeof(tmp));
1931 goto got_name;
1932 }
1933 } else {
1934 name = strncpy(tmp, "//anon", sizeof(tmp));
1935 goto got_name;
1936 }
1937
1938got_name:
1939 size = ALIGN(strlen(name), sizeof(u64));
1940
1941 mmap_event->file_name = name;
1942 mmap_event->file_size = size;
1943
1944 mmap_event->event.header.size = sizeof(mmap_event->event) + size;
1945
1946 cpuctx = &get_cpu_var(perf_cpu_context);
1947 perf_counter_mmap_ctx(&cpuctx->ctx, mmap_event);
1948 put_cpu_var(perf_cpu_context);
1949
1950 perf_counter_mmap_ctx(&current->perf_counter_ctx, mmap_event);
1951
1952 kfree(buf);
1953}
1954
1955void perf_counter_mmap(unsigned long addr, unsigned long len,
1956 unsigned long pgoff, struct file *file)
1957{
1958 struct perf_mmap_event mmap_event = {
1959 .file = file,
1960 .event = {
1961 .header = { .type = PERF_EVENT_MMAP, },
1962 .pid = current->group_leader->pid,
1963 .tid = current->pid,
1964 .start = addr,
1965 .len = len,
1966 .pgoff = pgoff,
1967 },
1968 };
1969
1970 perf_counter_mmap_event(&mmap_event);
1971}
1972
1973void perf_counter_munmap(unsigned long addr, unsigned long len,
1974 unsigned long pgoff, struct file *file)
1975{
1976 struct perf_mmap_event mmap_event = {
1977 .file = file,
1978 .event = {
1979 .header = { .type = PERF_EVENT_MUNMAP, },
1980 .pid = current->group_leader->pid,
1981 .tid = current->pid,
1982 .start = addr,
1983 .len = len,
1984 .pgoff = pgoff,
1985 },
1986 };
1987
1988 perf_counter_mmap_event(&mmap_event);
1989}
1990
1991/*
1847 * Generic software counter infrastructure 1992 * Generic software counter infrastructure
1848 */ 1993 */
1849 1994