xref: /xnu-8020.140.41/bsd/sys/monotonic.h (revision 27b03b360a988dfd3dfdf34262bb0042026747cc)
1 /*
2  * Copyright (c) 2017-2019 Apple Inc. All rights reserved.
3  *
4  * @APPLE_OSREFERENCE_LICENSE_HEADER_START@
5  *
6  * This file contains Original Code and/or Modifications of Original Code
7  * as defined in and that are subject to the Apple Public Source License
8  * Version 2.0 (the 'License'). You may not use this file except in
9  * compliance with the License. The rights granted to you under the License
10  * may not be used to create, or enable the creation or redistribution of,
11  * unlawful or unlicensed copies of an Apple operating system, or to
12  * circumvent, violate, or enable the circumvention or violation of, any
13  * terms of an Apple operating system software license agreement.
14  *
15  * Please obtain a copy of the License at
16  * http://www.opensource.apple.com/apsl/ and read it before using this file.
17  *
18  * The Original Code and all software distributed under the License are
19  * distributed on an 'AS IS' basis, WITHOUT WARRANTY OF ANY KIND, EITHER
20  * EXPRESS OR IMPLIED, AND APPLE HEREBY DISCLAIMS ALL SUCH WARRANTIES,
21  * INCLUDING WITHOUT LIMITATION, ANY WARRANTIES OF MERCHANTABILITY,
22  * FITNESS FOR A PARTICULAR PURPOSE, QUIET ENJOYMENT OR NON-INFRINGEMENT.
23  * Please see the License for the specific language governing rights and
24  * limitations under the License.
25  *
26  * @APPLE_OSREFERENCE_LICENSE_HEADER_END@
27  */
28 
29 #ifndef SYS_MONOTONIC_H
30 #define SYS_MONOTONIC_H
31 
32 #include <stdbool.h>
33 #include <stdint.h>
34 #include <sys/cdefs.h>
35 
36 #if !MACH_KERNEL_PRIVATE
37 
38 #include <sys/ioccom.h>
39 
40 __BEGIN_DECLS
41 
42 /*
43  * XXX These declarations are subject to change at any time.
44  */
45 
46 #define MT_IOC(x) _IO('m', (x))
47 #define MT_IOC_RESET MT_IOC(0)
48 #define MT_IOC_ADD MT_IOC(1)
49 #define MT_IOC_ENABLE MT_IOC(2)
50 #define MT_IOC_COUNTS MT_IOC(3)
51 #define MT_IOC_GET_INFO MT_IOC(4)
52 
53 __END_DECLS
54 
55 #endif /* !MACH_KERNEL_PRIVATE */
56 
57 __BEGIN_DECLS
58 
59 struct monotonic_config {
60 	uint64_t event;
61 	uint64_t allowed_ctr_mask;
62 	uint64_t cpu_mask;
63 };
64 
65 union monotonic_ctl_add {
66 	struct {
67 		struct monotonic_config config;
68 	} in;
69 
70 	struct {
71 		uint32_t ctr;
72 	} out;
73 };
74 
75 union monotonic_ctl_enable {
76 	struct {
77 		bool enable;
78 	} in;
79 };
80 
81 
82 union monotonic_ctl_counts {
83 	struct {
84 		uint64_t ctr_mask;
85 	} in;
86 
87 	struct {
88 		uint64_t counts[1];
89 	} out;
90 };
91 
92 
93 union monotonic_ctl_info {
94 	struct {
95 		unsigned int nmonitors;
96 		unsigned int ncounters;
97 	} out;
98 };
99 
100 __END_DECLS
101 
102 #if XNU_KERNEL_PRIVATE
103 
104 #if MONOTONIC
105 
106 #include <kern/monotonic.h>
107 #include <machine/monotonic.h>
108 #include <sys/kdebug.h>
109 #include <kern/locks.h>
110 
111 __BEGIN_DECLS
112 
113 #ifdef MT_CORE_INSTRS
114 #define COUNTS_INSTRS __counts[MT_CORE_INSTRS]
115 #else /* defined(MT_CORE_INSTRS) */
116 #define COUNTS_INSTRS 0
117 #endif /* !defined(MT_CORE_INSTRS) */
118 
119 /*
120  * MT_KDBG_TMP* macros are meant for temporary (i.e. not checked-in)
121  * performance investigations.
122  */
123 
124 /*
125  * Record the current CPU counters.
126  *
127  * Preemption must be disabled.
128  */
129 #define MT_KDBG_TMPCPU_EVT(CODE) \
130 	KDBG_EVENTID(DBG_MONOTONIC, DBG_MT_TMPCPU, CODE)
131 
132 #define MT_KDBG_TMPCPU_(CODE, FUNC) \
133 	do { \
134 	        if (kdebug_enable && \
135 	                        kdebug_debugid_enabled(MT_KDBG_TMPCPU_EVT(CODE))) { \
136 	                uint64_t __counts[MT_CORE_NFIXED]; \
137 	                mt_fixed_counts(__counts); \
138 	                KDBG(MT_KDBG_TMPCPU_EVT(CODE) | (FUNC), COUNTS_INSTRS, \
139 	                                __counts[MT_CORE_CYCLES]); \
140 	        } \
141 	} while (0)
142 
143 #define MT_KDBG_TMPCPU(CODE) MT_KDBG_TMPCPU_(CODE, DBG_FUNC_NONE)
144 #define MT_KDBG_TMPCPU_START(CODE) MT_KDBG_TMPCPU_(CODE, DBG_FUNC_START)
145 #define MT_KDBG_TMPCPU_END(CODE) MT_KDBG_TMPCPU_(CODE, DBG_FUNC_END)
146 
147 /*
148  * Record the current thread counters.
149  *
150  * Interrupts must be disabled.
151  */
152 #define MT_KDBG_TMPTH_EVT(CODE) \
153 	KDBG_EVENTID(DBG_MONOTONIC, DBG_MT_TMPTH, CODE)
154 
155 #define MT_KDBG_TMPTH_(CODE, FUNC) \
156 	do { \
157 	        if (kdebug_enable && \
158 	                        kdebug_debugid_enabled(MT_KDBG_TMPTH_EVT(CODE))) { \
159 	                uint64_t __counts[MT_CORE_NFIXED]; \
160 	                mt_cur_thread_fixed_counts(__counts); \
161 	                KDBG(MT_KDBG_TMPTH_EVT(CODE) | (FUNC), COUNTS_INSTRS, \
162 	                                __counts[MT_CORE_CYCLES]); \
163 	        } \
164 	} while (0)
165 
166 #define MT_KDBG_TMPTH(CODE) MT_KDBG_TMPTH_(CODE, DBG_FUNC_NONE)
167 #define MT_KDBG_TMPTH_START(CODE) MT_KDBG_TMPTH_(CODE, DBG_FUNC_START)
168 #define MT_KDBG_TMPTH_END(CODE) MT_KDBG_TMPTH_(CODE, DBG_FUNC_END)
169 
170 extern lck_grp_t mt_lock_grp;
171 
172 int mt_dev_init(void);
173 
174 struct mt_device {
175 	const char *mtd_name;
176 	int(*const mtd_init)(struct mt_device *dev);
177 	int(*const mtd_add)(struct monotonic_config *config, uint32_t *ctr_out);
178 	void(*const mtd_reset)(void);
179 	void(*const mtd_enable)(bool enable);
180 	int(*const mtd_read)(uint64_t ctr_mask, uint64_t *counts_out);
181 	decl_lck_mtx_data(, mtd_lock);
182 
183 	uint8_t mtd_nmonitors;
184 	uint8_t mtd_ncounters;
185 	bool mtd_inuse;
186 };
187 typedef struct mt_device *mt_device_t;
188 
189 extern struct mt_device mt_devices[];
190 
191 __END_DECLS
192 
193 #endif /* MONOTONIC */
194 
195 #endif /* XNU_KERNEL_PRIVATE */
196 
197 #endif /* !defined(SYS_MONOTONIC_H) */
198