1#ifndef SYS_MONOTONIC_H
2#define SYS_MONOTONIC_H
3
4#include <stdbool.h>
5#include <stdint.h>
6#include <sys/cdefs.h>
7#include <sys/ioccom.h>
8
9__BEGIN_DECLS
10
11/*
12 * XXX These declarations are subject to change at any time.
13 */
14
15#define MT_IOC(x) _IO('m', (x))
16
17#define MT_IOC_RESET MT_IOC(0)
18
19#define MT_IOC_ADD MT_IOC(1)
20
21struct monotonic_config {
22 uint64_t event;
23 uint64_t allowed_ctr_mask;
24 uint64_t cpu_mask;
25};
26
27union monotonic_ctl_add {
28 struct {
29 struct monotonic_config config;
30 } in;
31
32 struct {
33 uint32_t ctr;
34 } out;
35};
36
37/*
38 * - Consider a separate IOC for disable -- to avoid the copyin to determine
39 * which way to set it.
40 */
41#define MT_IOC_ENABLE MT_IOC(2)
42
43union monotonic_ctl_enable {
44 struct {
45 bool enable;
46 } in;
47};
48
49#define MT_IOC_COUNTS MT_IOC(3)
50
51union monotonic_ctl_counts {
52 struct {
53 uint64_t ctr_mask;
54 } in;
55
56 struct {
57 uint64_t counts[1];
58 } out;
59};
60
61#define MT_IOC_GET_INFO MT_IOC(4)
62
63union monotonic_ctl_info {
64 struct {
65 unsigned int nmonitors;
66 unsigned int ncounters;
67 } out;
68};
69
70#if XNU_KERNEL_PRIVATE
71
72#include <kern/monotonic.h>
73#include <machine/monotonic.h>
74#include <sys/kdebug.h>
75#include <kern/locks.h>
76
77#ifdef MT_CORE_INSTRS
78#define COUNTS_INSTRS __counts[MT_CORE_INSTRS]
79#else /* defined(MT_CORE_INSTRS) */
80#define COUNTS_INSTRS 0
81#endif /* !defined(MT_CORE_INSTRS) */
82
83/*
84 * MT_KDBG_TMP* macros are meant for temporary (i.e. not checked-in)
85 * performance investigations.
86 */
87
88/*
89 * Record the current CPU counters.
90 *
91 * Preemption must be disabled.
92 */
93#define MT_KDBG_TMPCPU_EVT(CODE) \
94 KDBG_EVENTID(DBG_MONOTONIC, DBG_MT_TMPCPU, CODE)
95
96#define MT_KDBG_TMPCPU_(CODE, FUNC) \
97 do { \
98 if (kdebug_enable && \
99 kdebug_debugid_enabled(MT_KDBG_TMPCPU_EVT(CODE))) { \
100 uint64_t __counts[MT_CORE_NFIXED]; \
101 mt_fixed_counts(__counts); \
102 KDBG(MT_KDBG_TMPCPU_EVT(CODE) | (FUNC), COUNTS_INSTRS, \
103 __counts[MT_CORE_CYCLES]); \
104 } \
105 } while (0)
106
107#define MT_KDBG_TMPCPU(CODE) MT_KDBG_TMPCPU_(CODE, DBG_FUNC_NONE)
108#define MT_KDBG_TMPCPU_START(CODE) MT_KDBG_TMPCPU_(CODE, DBG_FUNC_START)
109#define MT_KDBG_TMPCPU_END(CODE) MT_KDBG_TMPCPU_(CODE, DBG_FUNC_END)
110
111/*
112 * Record the current thread counters.
113 *
114 * Interrupts must be disabled.
115 */
116#define MT_KDBG_TMPTH_EVT(CODE) \
117 KDBG_EVENTID(DBG_MONOTONIC, DBG_MT_TMPTH, CODE)
118
119#define MT_KDBG_TMPTH_(CODE, FUNC) \
120 do { \
121 if (kdebug_enable && \
122 kdebug_debugid_enabled(MT_KDBG_TMPTH_EVT(CODE))) { \
123 uint64_t __counts[MT_CORE_NFIXED]; \
124 mt_cur_thread_fixed_counts(__counts); \
125 KDBG(MT_KDBG_TMPTH_EVT(CODE) | (FUNC), COUNTS_INSTRS, \
126 __counts[MT_CORE_CYCLES]); \
127 } \
128 } while (0)
129
130#define MT_KDBG_TMPTH(CODE) MT_KDBG_TMPTH_(CODE, DBG_FUNC_NONE)
131#define MT_KDBG_TMPTH_START(CODE) MT_KDBG_TMPTH_(CODE, DBG_FUNC_START)
132#define MT_KDBG_TMPTH_END(CODE) MT_KDBG_TMPTH_(CODE, DBG_FUNC_END)
133
134struct mt_device {
135 const char *mtd_name;
136 int (* const mtd_init)(struct mt_device *dev);
137 int (* const mtd_add)(struct monotonic_config *config, uint32_t *ctr_out);
138 void (* const mtd_reset)(void);
139 void (* const mtd_enable)(bool enable);
140 int (* const mtd_read)(uint64_t ctr_mask, uint64_t *counts_out);
141 decl_lck_mtx_data(, mtd_lock);
142
143 uint8_t mtd_nmonitors;
144 uint8_t mtd_ncounters;
145 bool mtd_inuse;
146};
147typedef struct mt_device *mt_device_t;
148
149extern struct mt_device mt_devices[];
150
151extern lck_grp_t *mt_lock_grp;
152
153int mt_dev_init(void);
154
155#endif /* XNU_KERNEL_PRIVATE */
156
157__END_DECLS
158
159#endif /* !defined(SYS_MONOTONIC_H) */
160