kern: Add cpucounter which returns 64bit monotonic counter.
[dragonfly.git] / sys / sys / systimer.h
blob85c50883deb7f83a0ece181e5baf0c1399c55bc8
1 /*
2 * SYS/SYSTIMER.H
3 *
4 * Copyright (c) 2003,2004 The DragonFly Project. All rights reserved.
5 *
6 * This code is derived from software contributed to The DragonFly Project
7 * by Matthew Dillon <dillon@backplane.com>
8 *
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
13 * 1. Redistributions of source code must retain the above copyright
14 * notice, this list of conditions and the following disclaimer.
15 * 2. Redistributions in binary form must reproduce the above copyright
16 * notice, this list of conditions and the following disclaimer in
17 * the documentation and/or other materials provided with the
18 * distribution.
19 * 3. Neither the name of The DragonFly Project nor the names of its
20 * contributors may be used to endorse or promote products derived
21 * from this software without specific, prior written permission.
23 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
24 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
25 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
26 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
27 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
28 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING,
29 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
30 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED
31 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY,
32 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT
33 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
34 * SUCH DAMAGE.
36 * $DragonFly: src/sys/sys/systimer.h,v 1.13 2007/04/30 06:57:36 dillon Exp $
39 #ifndef _SYS_SYSTIMER_H_
40 #define _SYS_SYSTIMER_H_
42 #if defined(_KERNEL) || defined(_KERNEL_STRUCTURES)
44 #ifndef _SYS_TYPES_H_
45 #include <sys/types.h>
46 #endif
47 #ifndef _SYS_QUEUE_H_
48 #include <sys/queue.h>
49 #endif
51 /* XXX fix sys/kinfo.h */
52 #ifndef __BOOLEAN_T_DEFINED__
53 #define __BOOLEAN_T_DEFINED__
54 typedef __boolean_t boolean_t;
55 #endif
57 struct intrframe;
59 typedef __uint32_t sysclock_t;
60 typedef int32_t ssysclock_t;
61 typedef TAILQ_HEAD(systimerq, systimer) *systimerq_t;
62 typedef void (*systimer_func_t)(struct systimer *, int, struct intrframe *);
64 typedef struct systimer {
65 TAILQ_ENTRY(systimer) node;
66 systimerq_t queue;
67 sysclock_t time; /* absolute time next intr */
68 sysclock_t periodic; /* if non-zero */
69 systimer_func_t func;
70 void *data;
71 int flags;
72 int freq; /* frequency if periodic */
73 struct cputimer *which; /* which timer was used? */
74 struct globaldata *gd; /* cpu owning structure */
75 } *systimer_t;
77 #define SYSTF_ONQUEUE 0x0001
78 #define SYSTF_IPIRUNNING 0x0002
79 #define SYSTF_NONQUEUED 0x0004
81 void systimer_intr_enable(void);
82 void systimer_intr(sysclock_t *, int, struct intrframe *);
83 void systimer_add(systimer_t);
84 void systimer_del(systimer_t);
85 void systimer_init_periodic(systimer_t, systimer_func_t, void *, int);
86 void systimer_init_periodic_nq(systimer_t, systimer_func_t, void *, int);
87 void systimer_adjust_periodic(systimer_t, int);
88 void systimer_init_oneshot(systimer_t, systimer_func_t, void *, int);
91 * The cputimer interface. This provides a free-running (non-interrupt)
92 * and monotonically increasing timebase for the system.
94 * The cputimer structure holds the fixed cputimer frequency, determining
95 * the granularity of sys_cputimer->count().
97 * Note that sys_cputimer->count() always returns a full-width wrapping
98 * counter.
100 * The 64 bit versions of the frequency are used for converting count
101 * values into uS or nS as follows:
103 * usec = (sys_cputimer->freq64_usec * count) >> 32
105 * NOTE: If count > sys_cputimer->freq, above conversion may overflow.
107 * REQUIREMENT FOR CPUTIMER IMPLEMENTATION:
109 * - 'freq' should not be too high, i.e. sysclock_t, which is 32 bits,
110 * must be able to hold several seconds at least.
111 * - The values returned by count() must be MP synchronized.
112 * - The values returned by count() must be stable under all situation,
113 * e.g. when the platform enters power saving mode.
114 * - The values returned by count() must be monotonically increasing.
117 struct cputimer {
118 SLIST_ENTRY(cputimer) next;
119 const char *name;
120 int pri;
121 int type;
122 sysclock_t (*count)(void);
123 sysclock_t (*fromhz)(int freq);
124 sysclock_t (*fromus)(int us);
125 void (*construct)(struct cputimer *, sysclock_t);
126 void (*destruct)(struct cputimer *);
127 sysclock_t base; /* (implementation dependant) */
128 sysclock_t freq; /* in Hz */
129 int64_t freq64_usec; /* in (1e6 << 32) / freq */
130 int64_t freq64_nsec; /* in (1e9 << 32) / freq */
133 extern struct cputimer *sys_cputimer;
135 #define CPUTIMER_DUMMY 0
136 #define CPUTIMER_8254_SEL1 1
137 #define CPUTIMER_8254_SEL2 2
138 #define CPUTIMER_ACPI 3
139 #define CPUTIMER_VKERNEL 4
140 #define CPUTIMER_HPET 5
141 #define CPUTIMER_GEODE 6
142 #define CPUTIMER_CS5536 7
143 #define CPUTIMER_TSC 8
144 #define CPUTIMER_VMM 9
145 #define CPUTIMER_VMM1 10
146 #define CPUTIMER_VMM2 11
148 #define CPUTIMER_PRI_DUMMY -10
149 #define CPUTIMER_PRI_8254 0
150 #define CPUTIMER_PRI_ACPI 10
151 #define CPUTIMER_PRI_HPET 20
152 #define CPUTIMER_PRI_CS5536 30
153 #define CPUTIMER_PRI_GEODE 40
154 #define CPUTIMER_PRI_VKERNEL 200
155 #define CPUTIMER_PRI_TSC 250
156 #define CPUTIMER_PRI_VMM 1000
157 #define CPUTIMER_PRI_VMM_HI 2000
159 void cputimer_select(struct cputimer *, int);
160 void cputimer_register(struct cputimer *);
161 void cputimer_deregister(struct cputimer *);
162 void cputimer_set_frequency(struct cputimer *, sysclock_t);
163 sysclock_t cputimer_default_fromhz(int);
164 sysclock_t cputimer_default_fromus(int);
165 void cputimer_default_construct(struct cputimer *, sysclock_t);
166 void cputimer_default_destruct(struct cputimer *);
169 * Interrupt cputimer interface.
171 * Interrupt cputimers are normally one shot timers which will
172 * generate interrupt upon expiration.
174 * initclock -- Called at SI_BOOT2_CLOCKREG, SI_ORDER_SECOND. The
175 * interrupt timer could deregister itself here, if it
176 * is not the selected system interrupt cputimer. Before
177 * this function is called, 'enable' and 'reload' will
178 * not be called.
179 * enable -- Enable interrupt. It is called by each CPU. It is
180 * only called once during boot. Before this function
181 * is called, 'reload' will not be called.
182 * reload -- Called by each CPU when it wants to to reprogram the
183 * one shot timer expiration time. The reload value is
184 * measured in sys_cputimer->freq.
185 * config -- Setup the interrupt cputimer according to the passed
186 * in non-interrupt cputimer. It will be called when
187 * sys_cputimer's frequency is changed or when sys_cputimer
188 * itself is changed. It is also called when this interrupt
189 * cputimer gets registered.
190 * restart -- Start the possibly stalled interrupt cputimer immediately.
191 * Do fixup if necessary.
192 * pmfixup -- Called after ACPI power management is enabled.
193 * pcpuhand -- Per-cpu handler (could be NULL).
195 struct cputimer_intr {
196 sysclock_t freq;
197 void (*reload)
198 (struct cputimer_intr *, sysclock_t);
199 void (*enable)
200 (struct cputimer_intr *);
201 void (*config)
202 (struct cputimer_intr *, const struct cputimer *);
203 void (*restart)
204 (struct cputimer_intr *);
205 void (*pmfixup)
206 (struct cputimer_intr *);
207 void (*initclock)
208 (struct cputimer_intr *, boolean_t);
209 void (*pcpuhand)
210 (struct cputimer_intr *);
211 SLIST_ENTRY(cputimer_intr) next;
212 const char *name;
213 int type; /* CPUTIMER_INTR_ */
214 int prio; /* CPUTIMER_INTR_PRIO_ */
215 uint32_t caps; /* CPUTIMER_INTR_CAP_ */
216 void *priv; /* private data */
219 #define CPUTIMER_INTR_8254 0
220 #define CPUTIMER_INTR_LAPIC 1
221 #define CPUTIMER_INTR_VKERNEL 2
222 #define CPUTIMER_INTR_VMM 3
224 /* NOTE: Keep the new values less than CPUTIMER_INTR_PRIO_MAX */
225 #define CPUTIMER_INTR_PRIO_8254 0
226 #define CPUTIMER_INTR_PRIO_LAPIC 10
227 #define CPUTIMER_INTR_PRIO_VKERNEL 20
228 #define CPUTIMER_INTR_PRIO_VMM 500
229 #define CPUTIMER_INTR_PRIO_MAX 1000
231 #define CPUTIMER_INTR_CAP_NONE 0
232 #define CPUTIMER_INTR_CAP_PS 0x1 /* works during powersaving */
235 * Interrupt cputimer implementation interfaces
237 * NOTE:
238 * cputimer_intr_deregister() is _not_ allowed to be called
239 * with the currently selected interrupt cputimer.
241 void cputimer_intr_register(struct cputimer_intr *);
242 void cputimer_intr_deregister(struct cputimer_intr *);
243 int cputimer_intr_select(struct cputimer_intr *, int);
246 * Interrupt cputimer implementation helper functions
248 * default_enable -- NOP
249 * default_restart -- reload(0)
250 * default_config -- NOP
251 * default_pmfixup -- NOP
252 * default_initclock -- NOP
254 void cputimer_intr_default_enable(struct cputimer_intr *);
255 void cputimer_intr_default_restart(struct cputimer_intr *);
256 void cputimer_intr_default_config(struct cputimer_intr *,
257 const struct cputimer *);
258 void cputimer_intr_default_pmfixup(struct cputimer_intr *);
259 void cputimer_intr_default_initclock(struct cputimer_intr *, boolean_t);
262 * Interrupt cputimer external interfaces
264 void cputimer_intr_enable(void);
265 void cputimer_intr_pmfixup(void);
266 void cputimer_intr_config(const struct cputimer *);
267 void cputimer_intr_reload(sysclock_t);
268 void cputimer_intr_restart(void);
269 int cputimer_intr_select_caps(uint32_t);
270 int cputimer_intr_powersave_addreq(void);
271 void cputimer_intr_powersave_remreq(void);
274 * The cpucounter interface.
276 * REQUIREMENT FOR CPUCOUNTER IMPLEMENTATION:
278 * - The values returned by count() must be MP synchronized, if
279 * CPUCOUNTER_FLAG_MPSYNC is set on 'flags'.
280 * - The values returned by count() must be stable under all situation,
281 * e.g. when the platform enters power saving mode.
282 * - The values returned by count() must be monotonically increasing.
284 struct cpucounter {
285 uint64_t freq;
286 uint64_t (*count)(void);
287 uint16_t flags; /* CPUCOUNTER_FLAG_ */
288 uint16_t prio; /* CPUCOUNTER_PRIO_ */
289 uint16_t type; /* CPUCOUNTER_ */
290 uint16_t reserved;
291 SLIST_ENTRY(cpucounter) link;
292 } __cachealign;
294 #define CPUCOUNTER_FLAG_MPSYNC 0x0001
296 #define CPUCOUNTER_DUMMY 0
297 #define CPUCOUNTER_TSC 1
298 #define CPUCOUNTER_VMM 2
299 #define CPUCOUNTER_VMM1 3
300 #define CPUCOUNTER_VMM2 4
302 #define CPUCOUNTER_PRIO_DUMMY 0
303 #define CPUCOUNTER_PRIO_TSC 50
304 #define CPUCOUNTER_PRIO_VMM 100
305 #define CPUCOUNTER_PRIO_VMM_HI 150
307 void cpucounter_register(struct cpucounter *);
308 const struct cpucounter *cpucounter_find_pcpu(void);
309 const struct cpucounter *cpucounter_find(void);
311 #endif /* _KERNEL || _KERNEL_STRUCTURES */
313 #endif /* !_SYS_SYSTIMER_H_ */