cyclic_machdep.c revision 179260
1179260Sjb/*-
2179260Sjb * Copyright 2006-2008 John Birrell <jb@FreeBSD.org>
3179260Sjb *
4179260Sjb * Redistribution and use in source and binary forms, with or without
5179260Sjb * modification, are permitted provided that the following conditions
6179260Sjb * are met:
7179260Sjb * 1. Redistributions of source code must retain the above copyright
8179260Sjb *    notice, this list of conditions and the following disclaimer.
9179260Sjb * 2. Redistributions in binary form must reproduce the above copyright
10179260Sjb *    notice, this list of conditions and the following disclaimer in the
11179260Sjb *    documentation and/or other materials provided with the distribution.
12179260Sjb *
13179260Sjb * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND
14179260Sjb * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
15179260Sjb * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
16179260Sjb * ARE DISCLAIMED.  IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE
17179260Sjb * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
18179260Sjb * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
19179260Sjb * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
20179260Sjb * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
21179260Sjb * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
22179260Sjb * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
23179260Sjb * SUCH DAMAGE.
24179260Sjb *
25179260Sjb * $FreeBSD: head/sys/cddl/dev/cyclic/i386/cyclic_machdep.c 179260 2008-05-23 22:21:58Z jb $
26179260Sjb *
27179260Sjb */
28179260Sjb
29179260Sjbstatic void enable(cyb_arg_t);
30179260Sjbstatic void disable(cyb_arg_t);
31179260Sjbstatic void reprogram(cyb_arg_t, hrtime_t);
32179260Sjbstatic void xcall(cyb_arg_t, cpu_t *, cyc_func_t, void *);
33179260Sjb
34179260Sjbstatic cyc_backend_t	be	= {
35179260Sjb	NULL,		/* cyb_configure */
36179260Sjb	NULL,		/* cyb_unconfigure */
37179260Sjb	enable,
38179260Sjb	disable,
39179260Sjb	reprogram,
40179260Sjb	xcall,
41179260Sjb	NULL		/* cyb_arg_t cyb_arg */
42179260Sjb};
43179260Sjb
44179260Sjbstatic void
45179260Sjbcyclic_ap_start(void *dummy)
46179260Sjb{
47179260Sjb	/* Initialise the rest of the CPUs. */
48179260Sjb	cyclic_mp_init();
49179260Sjb}
50179260Sjb
51179260SjbSYSINIT(cyclic_ap_start, SI_SUB_SMP, SI_ORDER_ANY, cyclic_ap_start, NULL);
52179260Sjb
53179260Sjb/*
54179260Sjb *  Machine dependent cyclic subsystem initialisation.
55179260Sjb */
56179260Sjbstatic void
57179260Sjbcyclic_machdep_init(void)
58179260Sjb{
59179260Sjb	/* Register the cyclic backend. */
60179260Sjb	cyclic_init(&be);
61179260Sjb}
62179260Sjb
63179260Sjbstatic void
64179260Sjbcyclic_machdep_uninit(void)
65179260Sjb{
66179260Sjb	int i;
67179260Sjb
68179260Sjb	for (i = 0; i <= mp_maxid; i++)
69179260Sjb		/* Reset the cyclic clock callback hook. */
70179260Sjb		lapic_cyclic_clock_func[i] = NULL;
71179260Sjb
72179260Sjb	/* De-register the cyclic backend. */
73179260Sjb	cyclic_uninit();
74179260Sjb}
75179260Sjb
76179260Sjbstatic hrtime_t exp_due[MAXCPU];
77179260Sjb
78179260Sjb/*
79179260Sjb * This function is the one registered by the machine dependent
80179260Sjb * initialiser as the callback for high speed timer events.
81179260Sjb */
82179260Sjbstatic void
83179260Sjbcyclic_clock(struct trapframe *frame)
84179260Sjb{
85179260Sjb	cpu_t *c = &solaris_cpu[curcpu];
86179260Sjb
87179260Sjb	if (c->cpu_cyclic != NULL && gethrtime() >= exp_due[curcpu]) {
88179260Sjb		if (TRAPF_USERMODE(frame)) {
89179260Sjb			c->cpu_profile_pc = 0;
90179260Sjb			c->cpu_profile_upc = TRAPF_PC(frame);
91179260Sjb		} else {
92179260Sjb			c->cpu_profile_pc = TRAPF_PC(frame);
93179260Sjb			c->cpu_profile_upc = 0;
94179260Sjb		}
95179260Sjb
96179260Sjb		c->cpu_intr_actv = 1;
97179260Sjb
98179260Sjb		/* Fire any timers that are due. */
99179260Sjb		cyclic_fire(c);
100179260Sjb
101179260Sjb		c->cpu_intr_actv = 0;
102179260Sjb	}
103179260Sjb}
104179260Sjb
105179260Sjbstatic void enable(cyb_arg_t arg)
106179260Sjb{
107179260Sjb	/* Register the cyclic clock callback function. */
108179260Sjb	lapic_cyclic_clock_func[curcpu] = cyclic_clock;
109179260Sjb}
110179260Sjb
111179260Sjbstatic void disable(cyb_arg_t arg)
112179260Sjb{
113179260Sjb	/* Reset the cyclic clock callback function. */
114179260Sjb	lapic_cyclic_clock_func[curcpu] = NULL;
115179260Sjb}
116179260Sjb
117179260Sjbstatic void reprogram(cyb_arg_t arg, hrtime_t exp)
118179260Sjb{
119179260Sjb	exp_due[curcpu] = exp;
120179260Sjb}
121179260Sjb
122179260Sjbstatic void xcall(cyb_arg_t arg, cpu_t *c, cyc_func_t func, void *param)
123179260Sjb{
124179260Sjb	/*
125179260Sjb	 * If the target CPU is the current one, just call the
126179260Sjb	 * function. This covers the non-SMP case.
127179260Sjb	 */
128179260Sjb	if (c == &solaris_cpu[curcpu])
129179260Sjb		(*func)(param);
130179260Sjb	else
131179260Sjb		smp_rendezvous_cpus((cpumask_t) (1 << c->cpuid), NULL,
132179260Sjb		    func, smp_no_rendevous_barrier, param);
133179260Sjb}
134