4 * Copyright (c) 2003,2004 The DragonFly Project. All rights reserved.
6 * This code is derived from software contributed to The DragonFly Project
7 * by Matthew Dillon <dillon@backplane.com>
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
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
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
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)
45 #include <sys/types.h>
48 #include <sys/queue.h>
51 /* XXX fix sys/kinfo.h */
52 #ifndef __BOOLEAN_T_DEFINED__
53 #define __BOOLEAN_T_DEFINED__
54 typedef __boolean_t boolean_t;
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;
67 sysclock_t time; /* absolute time next intr */
68 sysclock_t periodic; /* if non-zero */
72 int freq; /* frequency if periodic */
73 struct cputimer *which; /* which timer was used? */
74 struct globaldata *gd; /* cpu owning structure */
77 #define SYSTF_ONQUEUE 0x0001
78 #define SYSTF_IPIRUNNING 0x0002
79 #define SYSTF_NONQUEUED 0x0004
80 #define SYSTF_MSSYNC 0x0008 /* 1Khz coincident sync */
81 #define SYSTF_100KHZSYNC 0x0010 /* 100Khz coincident sync */
82 #define SYSTF_FIRST 0x0020 /* order first if coincident */
84 void systimer_intr_enable(void);
85 void systimer_intr(sysclock_t *, int, struct intrframe *);
86 void systimer_add(systimer_t);
87 void systimer_del(systimer_t);
88 void systimer_init_periodic(systimer_t, systimer_func_t, void *, int);
89 void systimer_init_periodic_nq(systimer_t, systimer_func_t, void *, int);
90 void systimer_init_periodic_nq1khz(systimer_t, systimer_func_t, void *, int);
91 void systimer_init_periodic_nq100khz(systimer_t, systimer_func_t, void *, int);
92 void systimer_init_periodic_flags(systimer_t, systimer_func_t, void *,
94 void systimer_adjust_periodic(systimer_t, int);
95 void systimer_init_oneshot(systimer_t, systimer_func_t, void *, int);
98 * The cputimer interface. This provides a free-running (non-interrupt)
99 * and monotonically increasing timebase for the system.
101 * The cputimer structure holds the fixed cputimer frequency, determining
102 * the granularity of sys_cputimer->count().
104 * Note that sys_cputimer->count() always returns a full-width wrapping
107 * The 64 bit versions of the frequency are used for converting count
108 * values into uS or nS as follows:
110 * usec = (sys_cputimer->freq64_usec * count) >> 32
112 * NOTE: If count > sys_cputimer->freq, above conversion may overflow.
114 * REQUIREMENT FOR CPUTIMER IMPLEMENTATION:
116 * - 'freq' should not be too high, i.e. sysclock_t, which is 32 bits,
117 * must be able to hold several seconds at least.
118 * - The values returned by count() must be MP synchronized.
119 * - The values returned by count() must be stable under all situation,
120 * e.g. when the platform enters power saving mode.
121 * - The values returned by count() must be monotonically increasing.
125 SLIST_ENTRY(cputimer) next;
129 sysclock_t (*count)(void);
130 sysclock_t (*fromhz)(int freq);
131 sysclock_t (*fromus)(int us);
132 void (*construct)(struct cputimer *, sysclock_t);
133 void (*destruct)(struct cputimer *);
134 sysclock_t sync_base; /* periodic synchronization base */
135 sysclock_t base; /* (implementation dependant) */
136 sysclock_t freq; /* in Hz */
137 int64_t freq64_usec; /* in (1e6 << 32) / freq */
138 int64_t freq64_nsec; /* in (1e9 << 32) / freq */
141 extern struct cputimer *sys_cputimer;
143 #define CPUTIMER_DUMMY 0
144 #define CPUTIMER_8254_SEL1 1
145 #define CPUTIMER_8254_SEL2 2
146 #define CPUTIMER_ACPI 3
147 #define CPUTIMER_VKERNEL 4
148 #define CPUTIMER_HPET 5
149 #define CPUTIMER_GEODE 6
150 #define CPUTIMER_CS5536 7
151 #define CPUTIMER_TSC 8
152 #define CPUTIMER_VMM 9
153 #define CPUTIMER_VMM1 10
154 #define CPUTIMER_VMM2 11
156 #define CPUTIMER_PRI_DUMMY -10
157 #define CPUTIMER_PRI_8254 0
158 #define CPUTIMER_PRI_ACPI 10
159 #define CPUTIMER_PRI_HPET 20
160 #define CPUTIMER_PRI_CS5536 30
161 #define CPUTIMER_PRI_GEODE 40
162 #define CPUTIMER_PRI_VKERNEL 200
163 #define CPUTIMER_PRI_TSC 250
164 #define CPUTIMER_PRI_VMM 1000
165 #define CPUTIMER_PRI_VMM_HI 2000
167 void cputimer_select(struct cputimer *, int);
168 void cputimer_register(struct cputimer *);
169 void cputimer_deregister(struct cputimer *);
170 void cputimer_set_frequency(struct cputimer *, sysclock_t);
171 sysclock_t cputimer_default_fromhz(int);
172 sysclock_t cputimer_default_fromus(int);
173 void cputimer_default_construct(struct cputimer *, sysclock_t);
174 void cputimer_default_destruct(struct cputimer *);
177 * Interrupt cputimer interface.
179 * Interrupt cputimers are normally one shot timers which will
180 * generate interrupt upon expiration.
182 * initclock -- Called at SI_BOOT2_CLOCKREG, SI_ORDER_SECOND. The
183 * interrupt timer could deregister itself here, if it
184 * is not the selected system interrupt cputimer. Before
185 * this function is called, 'enable' and 'reload' will
187 * enable -- Enable interrupt. It is called by each CPU. It is
188 * only called once during boot. Before this function
189 * is called, 'reload' will not be called.
190 * reload -- Called by each CPU when it wants to to reprogram the
191 * one shot timer expiration time. The reload value is
192 * measured in sys_cputimer->freq.
193 * config -- Setup the interrupt cputimer according to the passed
194 * in non-interrupt cputimer. It will be called when
195 * sys_cputimer's frequency is changed or when sys_cputimer
196 * itself is changed. It is also called when this interrupt
197 * cputimer gets registered.
198 * restart -- Start the possibly stalled interrupt cputimer immediately.
199 * Do fixup if necessary.
200 * pmfixup -- Called after ACPI power management is enabled.
201 * pcpuhand -- Per-cpu handler (could be NULL).
203 struct cputimer_intr {
206 (struct cputimer_intr *, sysclock_t);
208 (struct cputimer_intr *);
210 (struct cputimer_intr *, const struct cputimer *);
212 (struct cputimer_intr *);
214 (struct cputimer_intr *);
216 (struct cputimer_intr *, boolean_t);
218 (struct cputimer_intr *);
219 SLIST_ENTRY(cputimer_intr) next;
221 int type; /* CPUTIMER_INTR_ */
222 int prio; /* CPUTIMER_INTR_PRIO_ */
223 uint32_t caps; /* CPUTIMER_INTR_CAP_ */
224 void *priv; /* private data */
227 #define CPUTIMER_INTR_8254 0
228 #define CPUTIMER_INTR_LAPIC 1
229 #define CPUTIMER_INTR_VKERNEL 2
230 #define CPUTIMER_INTR_VMM 3
232 /* NOTE: Keep the new values less than CPUTIMER_INTR_PRIO_MAX */
233 #define CPUTIMER_INTR_PRIO_8254 0
234 #define CPUTIMER_INTR_PRIO_LAPIC 10
235 #define CPUTIMER_INTR_PRIO_VKERNEL 20
236 #define CPUTIMER_INTR_PRIO_VMM 500
237 #define CPUTIMER_INTR_PRIO_MAX 1000
239 #define CPUTIMER_INTR_CAP_NONE 0
240 #define CPUTIMER_INTR_CAP_PS 0x1 /* works during powersaving */
243 * Interrupt cputimer implementation interfaces
246 * cputimer_intr_deregister() is _not_ allowed to be called
247 * with the currently selected interrupt cputimer.
249 void cputimer_intr_register(struct cputimer_intr *);
250 void cputimer_intr_deregister(struct cputimer_intr *);
251 int cputimer_intr_select(struct cputimer_intr *, int);
254 * Interrupt cputimer implementation helper functions
256 * default_enable -- NOP
257 * default_restart -- reload(0)
258 * default_config -- NOP
259 * default_pmfixup -- NOP
260 * default_initclock -- NOP
262 void cputimer_intr_default_enable(struct cputimer_intr *);
263 void cputimer_intr_default_restart(struct cputimer_intr *);
264 void cputimer_intr_default_config(struct cputimer_intr *,
265 const struct cputimer *);
266 void cputimer_intr_default_pmfixup(struct cputimer_intr *);
267 void cputimer_intr_default_initclock(struct cputimer_intr *, boolean_t);
270 * Interrupt cputimer external interfaces
272 void cputimer_intr_enable(void);
273 void cputimer_intr_pmfixup(void);
274 void cputimer_intr_config(const struct cputimer *);
275 void cputimer_intr_reload(sysclock_t);
276 void cputimer_intr_restart(void);
277 int cputimer_intr_select_caps(uint32_t);
278 int cputimer_intr_powersave_addreq(void);
279 void cputimer_intr_powersave_remreq(void);
282 * The cpucounter interface.
284 * REQUIREMENT FOR CPUCOUNTER IMPLEMENTATION:
286 * - The values returned by count() must be MP synchronized, if
287 * CPUCOUNTER_FLAG_MPSYNC is set on 'flags'.
288 * - The values returned by count() must be stable under all situation,
289 * e.g. when the platform enters power saving mode.
290 * - The values returned by count() must be monotonically increasing.
294 uint64_t (*count)(void);
295 uint16_t flags; /* CPUCOUNTER_FLAG_ */
296 uint16_t prio; /* CPUCOUNTER_PRIO_ */
297 uint16_t type; /* CPUCOUNTER_ */
299 SLIST_ENTRY(cpucounter) link;
302 #define CPUCOUNTER_FLAG_MPSYNC 0x0001
304 #define CPUCOUNTER_DUMMY 0
305 #define CPUCOUNTER_TSC 1
306 #define CPUCOUNTER_VMM 2
307 #define CPUCOUNTER_VMM1 3
308 #define CPUCOUNTER_VMM2 4
310 #define CPUCOUNTER_PRIO_DUMMY 0
311 #define CPUCOUNTER_PRIO_TSC 50
312 #define CPUCOUNTER_PRIO_VMM 100
313 #define CPUCOUNTER_PRIO_VMM_HI 150
315 void cpucounter_register(struct cpucounter *);
316 const struct cpucounter *cpucounter_find_pcpu(void);
317 const struct cpucounter *cpucounter_find(void);
319 #endif /* _KERNEL || _KERNEL_STRUCTURES */
321 #endif /* !_SYS_SYSTIMER_H_ */