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$
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 *);
33221990Savgstatic void cyclic_clock(struct trapframe *frame);
34179260Sjb
35179260Sjbstatic cyc_backend_t	be	= {
36179260Sjb	NULL,		/* cyb_configure */
37179260Sjb	NULL,		/* cyb_unconfigure */
38179260Sjb	enable,
39179260Sjb	disable,
40179260Sjb	reprogram,
41179260Sjb	xcall,
42179260Sjb	NULL		/* cyb_arg_t cyb_arg */
43179260Sjb};
44179260Sjb
45179260Sjbstatic void
46179260Sjbcyclic_ap_start(void *dummy)
47179260Sjb{
48179260Sjb	/* Initialise the rest of the CPUs. */
49221990Savg	cyclic_clock_func = cyclic_clock;
50179260Sjb	cyclic_mp_init();
51179260Sjb}
52179260Sjb
53179260SjbSYSINIT(cyclic_ap_start, SI_SUB_SMP, SI_ORDER_ANY, cyclic_ap_start, NULL);
54179260Sjb
55179260Sjb/*
56179260Sjb *  Machine dependent cyclic subsystem initialisation.
57179260Sjb */
58179260Sjbstatic void
59179260Sjbcyclic_machdep_init(void)
60179260Sjb{
61179260Sjb	/* Register the cyclic backend. */
62179260Sjb	cyclic_init(&be);
63179260Sjb}
64179260Sjb
65179260Sjbstatic void
66179260Sjbcyclic_machdep_uninit(void)
67179260Sjb{
68179260Sjb	/* De-register the cyclic backend. */
69179260Sjb	cyclic_uninit();
70179260Sjb}
71179260Sjb
72179260Sjb/*
73179260Sjb * This function is the one registered by the machine dependent
74179260Sjb * initialiser as the callback for high speed timer events.
75179260Sjb */
76179260Sjbstatic void
77179260Sjbcyclic_clock(struct trapframe *frame)
78179260Sjb{
79179260Sjb	cpu_t *c = &solaris_cpu[curcpu];
80179260Sjb
81221990Savg	if (c->cpu_cyclic != NULL) {
82179260Sjb		if (TRAPF_USERMODE(frame)) {
83179260Sjb			c->cpu_profile_pc = 0;
84179260Sjb			c->cpu_profile_upc = TRAPF_PC(frame);
85179260Sjb		} else {
86179260Sjb			c->cpu_profile_pc = TRAPF_PC(frame);
87179260Sjb			c->cpu_profile_upc = 0;
88179260Sjb		}
89179260Sjb
90179260Sjb		c->cpu_intr_actv = 1;
91179260Sjb
92179260Sjb		/* Fire any timers that are due. */
93179260Sjb		cyclic_fire(c);
94179260Sjb
95179260Sjb		c->cpu_intr_actv = 0;
96179260Sjb	}
97179260Sjb}
98179260Sjb
99221990Savgstatic void
100221990Savgenable(cyb_arg_t arg __unused)
101179260Sjb{
102221990Savg
103179260Sjb}
104179260Sjb
105221990Savgstatic void
106221990Savgdisable(cyb_arg_t arg __unused)
107179260Sjb{
108221990Savg
109179260Sjb}
110179260Sjb
111221990Savgstatic void
112221990Savgreprogram(cyb_arg_t arg __unused, hrtime_t exp)
113179260Sjb{
114221990Savg	struct bintime bt;
115221990Savg	struct timespec ts;
116221990Savg
117221990Savg	ts.tv_sec = exp / 1000000000;
118221990Savg	ts.tv_nsec = exp % 1000000000;
119221990Savg	timespec2bintime(&ts, &bt);
120221990Savg	clocksource_cyc_set(&bt);
121179260Sjb}
122179260Sjb
123221990Savgstatic void xcall(cyb_arg_t arg __unused, cpu_t *c, cyc_func_t func,
124221990Savg    void *param)
125179260Sjb{
126222813Sattilio	cpuset_t cpus;
127216252Savg
128222813Sattilio	CPU_SETOF(c->cpuid, &cpus);
129222813Sattilio	smp_rendezvous_cpus(cpus,
130216505Savg	    smp_no_rendevous_barrier, func, smp_no_rendevous_barrier, param);
131179260Sjb}
132