Added perfmon interrupt handling to allow overflow based profiling
[akaros.git] / kern / arch / x86 / perfmon.h
1 /* Copyright (c) 2015 Google Inc
2  * Davide Libenzi <dlibenzi@google.com>
3  * See LICENSE for details.
4  */
5
6 #pragma once
7
8 #include <sys/types.h>
9 #include <ros/common.h>
10 #include <ros/arch/perfmon.h>
11 #include <arch/x86.h>
12 #include <atomic.h>
13 #include <core_set.h>
14 #include <kref.h>
15 #include <stdint.h>
16
17 #define MAX_VAR_COUNTERS 32
18 #define MAX_FIX_COUNTERS 16
19 #define MAX_PERFMON_COUNTERS (MAX_VAR_COUNTERS + MAX_FIX_COUNTERS)
20 #define INVALID_COUNTER INT32_MIN
21
22 struct hw_trapframe;
23
24 typedef int32_t counter_t;
25
26 struct perfmon_cpu_caps {
27         uint32_t perfmon_version;
28         uint32_t proc_arch_events;
29         uint32_t bits_x_counter;
30         uint32_t counters_x_proc;
31         uint32_t bits_x_fix_counter;
32         uint32_t fix_counters_x_proc;
33 };
34
35 struct perfmon_alloc {
36         struct kref ref;
37         struct perfmon_event ev;
38         counter_t cores_counters[0];
39 };
40
41 struct perfmon_session {
42         struct kref ref;
43         spinlock_t lock;
44         struct perfmon_alloc *allocs[MAX_PERFMON_COUNTERS];
45 };
46
47 struct perfmon_status {
48         struct perfmon_event ev;
49         uint64_t cores_values[0];
50 };
51
52 void perfmon_init(void);
53 void perfmon_interrupt(struct hw_trapframe *hw_tf, void *data);
54 void perfmon_get_cpu_caps(struct perfmon_cpu_caps *pcc);
55 int perfmon_open_event(const struct core_set *cset, struct perfmon_session *ps,
56                                            const struct perfmon_event *pev);
57 void perfmon_close_event(struct perfmon_session *ps, int ped);
58 struct perfmon_status *perfmon_get_event_status(struct perfmon_session *ps,
59                                                                                                 int ped);
60 void perfmon_free_event_status(struct perfmon_status *pef);
61 struct perfmon_session *perfmon_create_session(void);
62 void perfmon_get_session(struct perfmon_session *ps);
63 void perfmon_close_session(struct perfmon_session *ps);
64
65 static inline uint64_t read_pmc(uint32_t index)
66 {
67         uint32_t edx, eax;
68
69         asm volatile("rdpmc" : "=d"(edx), "=a"(eax) : "c"(index));
70         return ((uint64_t) edx << 32) | eax;
71 }