nrelease - fix/improve livecd
[dragonfly.git] / sys / sys / systimer.h
CommitLineData
88c4d2f6
MD
1/*
2 * SYS/SYSTIMER.H
27a6bce6 3 *
8c10bfcf 4 * Copyright (c) 2003,2004 The DragonFly Project. All rights reserved.
27a6bce6 5 *
8c10bfcf
MD
6 * This code is derived from software contributed to The DragonFly Project
7 * by Matthew Dillon <dillon@backplane.com>
27a6bce6 8 *
88c4d2f6
MD
9 * Redistribution and use in source and binary forms, with or without
10 * modification, are permitted provided that the following conditions
11 * are met:
27a6bce6 12 *
88c4d2f6
MD
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
8c10bfcf
MD
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.
27a6bce6 22 *
8c10bfcf
MD
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
88c4d2f6 34 * SUCH DAMAGE.
88c4d2f6
MD
35 */
36
37#ifndef _SYS_SYSTIMER_H_
38#define _SYS_SYSTIMER_H_
39
59ef3aa7
SZ
40#if defined(_KERNEL) || defined(_KERNEL_STRUCTURES)
41
1bd40720
MD
42#ifndef _SYS_TYPES_H_
43#include <sys/types.h>
44#endif
45#ifndef _SYS_QUEUE_H_
46#include <sys/queue.h>
47#endif
48
88c4d2f6
MD
49struct intrframe;
50
8fbc264d
MD
51typedef __uint64_t sysclock_t;
52typedef int64_t ssysclock_t;
88c4d2f6 53typedef TAILQ_HEAD(systimerq, systimer) *systimerq_t;
96d52ac8 54typedef void (*systimer_func_t)(struct systimer *, int, struct intrframe *);
88c4d2f6
MD
55
56typedef struct systimer {
57 TAILQ_ENTRY(systimer) node;
58 systimerq_t queue;
59 sysclock_t time; /* absolute time next intr */
8fbc264d 60 sysclock_t periodic; /* non-zero if periodic */
96d52ac8 61 systimer_func_t func;
88c4d2f6
MD
62 void *data;
63 int flags;
8fbc264d
MD
64 int us; /* non-zero if one-shot */
65 ssysclock_t freq; /* frequency if periodic */
4b52d1af 66 struct cputimer *which; /* which timer was used? */
88c4d2f6
MD
67 struct globaldata *gd; /* cpu owning structure */
68} *systimer_t;
69
70#define SYSTF_ONQUEUE 0x0001
71#define SYSTF_IPIRUNNING 0x0002
0d1dffdf 72#define SYSTF_NONQUEUED 0x0004
c6a766f4
MD
73#define SYSTF_MSSYNC 0x0008 /* 1Khz coincident sync */
74#define SYSTF_100KHZSYNC 0x0010 /* 100Khz coincident sync */
75#define SYSTF_FIRST 0x0020 /* order first if coincident */
880fb308 76#define SYSTF_OFFSET50 0x0040 /* add 1/2 interval offset */
91dc43dd 77#define SYSTF_OFFSETCPU 0x0080 /* add cpu*periodic/ncpus */
88c4d2f6 78
27a6bce6 79#ifdef _KERNEL
8fbc264d 80void systimer_changed(void);
43adde98 81void systimer_intr_enable(void);
b8a98473 82void systimer_intr(sysclock_t *, int, struct intrframe *);
0ded555b
MD
83void systimer_add(systimer_t);
84void systimer_del(systimer_t);
8fbc264d
MD
85void systimer_init_periodic(systimer_t, systimer_func_t, void *, int64_t);
86void systimer_init_periodic_nq(systimer_t, systimer_func_t, void *, int64_t);
87void systimer_init_periodic_nq1khz(systimer_t, systimer_func_t, void *, int64_t);
88void systimer_init_periodic_nq100khz(systimer_t, systimer_func_t, void *, int64_t);
c6a766f4 89void systimer_init_periodic_flags(systimer_t, systimer_func_t, void *,
8fbc264d
MD
90 int64_t, int);
91void systimer_adjust_periodic(systimer_t, int64_t);
92void systimer_init_oneshot(systimer_t, systimer_func_t, void *, int64_t);
88c4d2f6 93
88c4d2f6 94/*
27a6bce6 95 * The cputimer interface. This provides a free-running (non-interrupt)
9800d437 96 * and monotonically increasing timebase for the system.
044ee7c4 97 *
9800d437
SZ
98 * The cputimer structure holds the fixed cputimer frequency, determining
99 * the granularity of sys_cputimer->count().
624051cd 100 *
9800d437
SZ
101 * Note that sys_cputimer->count() always returns a full-width wrapping
102 * counter.
88c4d2f6 103 *
9800d437
SZ
104 * The 64 bit versions of the frequency are used for converting count
105 * values into uS or nS as follows:
88c4d2f6 106 *
9800d437
SZ
107 * usec = (sys_cputimer->freq64_usec * count) >> 32
108 *
109 * NOTE: If count > sys_cputimer->freq, above conversion may overflow.
110 *
111 * REQUIREMENT FOR CPUTIMER IMPLEMENTATION:
112 *
9800d437
SZ
113 * - The values returned by count() must be MP synchronized.
114 * - The values returned by count() must be stable under all situation,
115 * e.g. when the platform enters power saving mode.
116 * - The values returned by count() must be monotonically increasing.
88c4d2f6 117 */
044ee7c4
MD
118
119struct cputimer {
d8fdd978 120 SLIST_ENTRY(cputimer) next;
044ee7c4
MD
121 const char *name;
122 int pri;
123 int type;
124 sysclock_t (*count)(void);
8fbc264d
MD
125 sysclock_t (*fromhz)(int64_t freq);
126 sysclock_t (*fromus)(int64_t us);
624051cd
SZ
127 void (*construct)(struct cputimer *, sysclock_t);
128 void (*destruct)(struct cputimer *);
c6a766f4 129 sysclock_t sync_base; /* periodic synchronization base */
93631e64 130 sysclock_t base; /* (implementation dependant) */
044ee7c4 131 sysclock_t freq; /* in Hz */
9800d437
SZ
132 int64_t freq64_usec; /* in (1e6 << 32) / freq */
133 int64_t freq64_nsec; /* in (1e9 << 32) / freq */
044ee7c4
MD
134};
135
136extern struct cputimer *sys_cputimer;
137
138#define CPUTIMER_DUMMY 0
139#define CPUTIMER_8254_SEL1 1
140#define CPUTIMER_8254_SEL2 2
141#define CPUTIMER_ACPI 3
60297eb4 142#define CPUTIMER_VKERNEL 4
bea6e278 143#define CPUTIMER_HPET 5
a75ee873 144#define CPUTIMER_GEODE 6
96d52ac8 145#define CPUTIMER_CS5536 7
8d23b56c 146#define CPUTIMER_TSC 8
45de427d 147#define CPUTIMER_VMM 9
52df6187
SZ
148#define CPUTIMER_VMM1 10
149#define CPUTIMER_VMM2 11
044ee7c4
MD
150
151#define CPUTIMER_PRI_DUMMY -10
152#define CPUTIMER_PRI_8254 0
153#define CPUTIMER_PRI_ACPI 10
f9ddf8c9
SZ
154#define CPUTIMER_PRI_HPET 20
155#define CPUTIMER_PRI_CS5536 30
156#define CPUTIMER_PRI_GEODE 40
157#define CPUTIMER_PRI_VKERNEL 200
8d23b56c 158#define CPUTIMER_PRI_TSC 250
45de427d 159#define CPUTIMER_PRI_VMM 1000
52df6187 160#define CPUTIMER_PRI_VMM_HI 2000
044ee7c4 161
0ded555b
MD
162void cputimer_select(struct cputimer *, int);
163void cputimer_register(struct cputimer *);
164void cputimer_deregister(struct cputimer *);
e2addb3d 165void cputimer_set_frequency(struct cputimer *, sysclock_t);
8fbc264d
MD
166sysclock_t cputimer_default_fromhz(int64_t);
167sysclock_t cputimer_default_fromus(int64_t);
0ded555b
MD
168void cputimer_default_construct(struct cputimer *, sysclock_t);
169void cputimer_default_destruct(struct cputimer *);
044ee7c4 170
ef612539
SZ
171/*
172 * Interrupt cputimer interface.
173 *
174 * Interrupt cputimers are normally one shot timers which will
175 * generate interrupt upon expiration.
176 *
177 * initclock -- Called at SI_BOOT2_CLOCKREG, SI_ORDER_SECOND. The
178 * interrupt timer could deregister itself here, if it
179 * is not the selected system interrupt cputimer. Before
180 * this function is called, 'enable' and 'reload' will
181 * not be called.
182 * enable -- Enable interrupt. It is called by each CPU. It is
183 * only called once during boot. Before this function
184 * is called, 'reload' will not be called.
185 * reload -- Called by each CPU when it wants to to reprogram the
186 * one shot timer expiration time. The reload value is
187 * measured in sys_cputimer->freq.
188 * config -- Setup the interrupt cputimer according to the passed
189 * in non-interrupt cputimer. It will be called when
190 * sys_cputimer's frequency is changed or when sys_cputimer
191 * itself is changed. It is also called when this interrupt
192 * cputimer gets registered.
193 * restart -- Start the possibly stalled interrupt cputimer immediately.
194 * Do fixup if necessary.
195 * pmfixup -- Called after ACPI power management is enabled.
42098fc3 196 * pcpuhand -- Per-cpu handler (could be NULL).
ef612539
SZ
197 */
198struct cputimer_intr {
199 sysclock_t freq;
200 void (*reload)
201 (struct cputimer_intr *, sysclock_t);
202 void (*enable)
203 (struct cputimer_intr *);
204 void (*config)
205 (struct cputimer_intr *, const struct cputimer *);
206 void (*restart)
207 (struct cputimer_intr *);
208 void (*pmfixup)
209 (struct cputimer_intr *);
210 void (*initclock)
211 (struct cputimer_intr *, boolean_t);
42098fc3
SZ
212 void (*pcpuhand)
213 (struct cputimer_intr *);
ef612539
SZ
214 SLIST_ENTRY(cputimer_intr) next;
215 const char *name;
216 int type; /* CPUTIMER_INTR_ */
217 int prio; /* CPUTIMER_INTR_PRIO_ */
218 uint32_t caps; /* CPUTIMER_INTR_CAP_ */
42098fc3 219 void *priv; /* private data */
ef612539
SZ
220};
221
222#define CPUTIMER_INTR_8254 0
223#define CPUTIMER_INTR_LAPIC 1
224#define CPUTIMER_INTR_VKERNEL 2
e3c41896 225#define CPUTIMER_INTR_VMM 3
ef612539
SZ
226
227/* NOTE: Keep the new values less than CPUTIMER_INTR_PRIO_MAX */
228#define CPUTIMER_INTR_PRIO_8254 0
229#define CPUTIMER_INTR_PRIO_LAPIC 10
230#define CPUTIMER_INTR_PRIO_VKERNEL 20
e3c41896 231#define CPUTIMER_INTR_PRIO_VMM 500
ef612539
SZ
232#define CPUTIMER_INTR_PRIO_MAX 1000
233
234#define CPUTIMER_INTR_CAP_NONE 0
235#define CPUTIMER_INTR_CAP_PS 0x1 /* works during powersaving */
236
237/*
238 * Interrupt cputimer implementation interfaces
239 *
240 * NOTE:
241 * cputimer_intr_deregister() is _not_ allowed to be called
242 * with the currently selected interrupt cputimer.
243 */
244void cputimer_intr_register(struct cputimer_intr *);
245void cputimer_intr_deregister(struct cputimer_intr *);
246int cputimer_intr_select(struct cputimer_intr *, int);
247
248/*
249 * Interrupt cputimer implementation helper functions
250 *
251 * default_enable -- NOP
252 * default_restart -- reload(0)
253 * default_config -- NOP
254 * default_pmfixup -- NOP
255 * default_initclock -- NOP
256 */
257void cputimer_intr_default_enable(struct cputimer_intr *);
258void cputimer_intr_default_restart(struct cputimer_intr *);
259void cputimer_intr_default_config(struct cputimer_intr *,
260 const struct cputimer *);
261void cputimer_intr_default_pmfixup(struct cputimer_intr *);
262void cputimer_intr_default_initclock(struct cputimer_intr *, boolean_t);
263
264/*
265 * Interrupt cputimer external interfaces
266 */
43adde98 267void cputimer_intr_enable(void);
ef612539
SZ
268void cputimer_intr_pmfixup(void);
269void cputimer_intr_config(const struct cputimer *);
270void cputimer_intr_reload(sysclock_t);
271void cputimer_intr_restart(void);
272int cputimer_intr_select_caps(uint32_t);
e80ea409
SZ
273int cputimer_intr_powersave_addreq(void);
274void cputimer_intr_powersave_remreq(void);
88c4d2f6 275
6b91ee43
SZ
276/*
277 * The cpucounter interface.
278 *
279 * REQUIREMENT FOR CPUCOUNTER IMPLEMENTATION:
280 *
281 * - The values returned by count() must be MP synchronized, if
282 * CPUCOUNTER_FLAG_MPSYNC is set on 'flags'.
283 * - The values returned by count() must be stable under all situation,
284 * e.g. when the platform enters power saving mode.
285 * - The values returned by count() must be monotonically increasing.
286 */
287struct cpucounter {
288 uint64_t freq;
289 uint64_t (*count)(void);
290 uint16_t flags; /* CPUCOUNTER_FLAG_ */
291 uint16_t prio; /* CPUCOUNTER_PRIO_ */
292 uint16_t type; /* CPUCOUNTER_ */
293 uint16_t reserved;
294 SLIST_ENTRY(cpucounter) link;
295} __cachealign;
296
297#define CPUCOUNTER_FLAG_MPSYNC 0x0001
298
299#define CPUCOUNTER_DUMMY 0
300#define CPUCOUNTER_TSC 1
301#define CPUCOUNTER_VMM 2
302#define CPUCOUNTER_VMM1 3
303#define CPUCOUNTER_VMM2 4
304
305#define CPUCOUNTER_PRIO_DUMMY 0
306#define CPUCOUNTER_PRIO_TSC 50
307#define CPUCOUNTER_PRIO_VMM 100
308#define CPUCOUNTER_PRIO_VMM_HI 150
309
310void cpucounter_register(struct cpucounter *);
311const struct cpucounter *cpucounter_find_pcpu(void);
312const struct cpucounter *cpucounter_find(void);
27a6bce6 313#endif /* _KERNEL */
6b91ee43 314
59ef3aa7
SZ
315#endif /* _KERNEL || _KERNEL_STRUCTURES */
316
624051cd 317#endif /* !_SYS_SYSTIMER_H_ */