cyclic_machdep.c revision 221990
11573Srgrimes/*- 21573Srgrimes * Copyright 2006-2008 John Birrell <jb@FreeBSD.org> 31573Srgrimes * 41573Srgrimes * Redistribution and use in source and binary forms, with or without 51573Srgrimes * modification, are permitted provided that the following conditions 61573Srgrimes * are met: 71573Srgrimes * 1. Redistributions of source code must retain the above copyright 81573Srgrimes * notice, this list of conditions and the following disclaimer. 91573Srgrimes * 2. Redistributions in binary form must reproduce the above copyright 101573Srgrimes * notice, this list of conditions and the following disclaimer in the 111573Srgrimes * documentation and/or other materials provided with the distribution. 121573Srgrimes * 131573Srgrimes * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 141573Srgrimes * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 151573Srgrimes * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 161573Srgrimes * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 171573Srgrimes * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 181573Srgrimes * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 191573Srgrimes * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 201573Srgrimes * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 211573Srgrimes * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 221573Srgrimes * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 231573Srgrimes * SUCH DAMAGE. 241573Srgrimes * 251573Srgrimes * $FreeBSD: head/sys/cddl/dev/cyclic/i386/cyclic_machdep.c 221990 2011-05-16 15:29:59Z avg $ 261573Srgrimes * 271573Srgrimes */ 281573Srgrimes 291573Srgrimesstatic void enable(cyb_arg_t); 301573Srgrimesstatic void disable(cyb_arg_t); 311573Srgrimesstatic void reprogram(cyb_arg_t, hrtime_t); 321573Srgrimesstatic void xcall(cyb_arg_t, cpu_t *, cyc_func_t, void *); 331573Srgrimesstatic void cyclic_clock(struct trapframe *frame); 341573Srgrimes 351573Srgrimesstatic cyc_backend_t be = { 361573Srgrimes NULL, /* cyb_configure */ 371573Srgrimes NULL, /* cyb_unconfigure */ 381573Srgrimes enable, 391573Srgrimes disable, 401573Srgrimes reprogram, 411573Srgrimes xcall, 421573Srgrimes NULL /* cyb_arg_t cyb_arg */ 431573Srgrimes}; 441573Srgrimes 451573Srgrimesstatic void 461573Srgrimescyclic_ap_start(void *dummy) 471573Srgrimes{ 481573Srgrimes /* Initialise the rest of the CPUs. */ 491573Srgrimes cyclic_clock_func = cyclic_clock; 501573Srgrimes cyclic_mp_init(); 511573Srgrimes} 521573Srgrimes 531573SrgrimesSYSINIT(cyclic_ap_start, SI_SUB_SMP, SI_ORDER_ANY, cyclic_ap_start, NULL); 541573Srgrimes 551573Srgrimes/* 561573Srgrimes * Machine dependent cyclic subsystem initialisation. 571573Srgrimes */ 581573Srgrimesstatic void 591573Srgrimescyclic_machdep_init(void) 601573Srgrimes{ 611573Srgrimes /* Register the cyclic backend. */ 621573Srgrimes cyclic_init(&be); 631573Srgrimes} 641573Srgrimes 651573Srgrimesstatic void 661573Srgrimescyclic_machdep_uninit(void) 671573Srgrimes{ 681573Srgrimes /* De-register the cyclic backend. */ 691573Srgrimes cyclic_uninit(); 701573Srgrimes} 711573Srgrimes 721573Srgrimes/* 731573Srgrimes * This function is the one registered by the machine dependent 741573Srgrimes * initialiser as the callback for high speed timer events. 751573Srgrimes */ 761573Srgrimesstatic void 771573Srgrimescyclic_clock(struct trapframe *frame) 781573Srgrimes{ 791573Srgrimes cpu_t *c = &solaris_cpu[curcpu]; 801573Srgrimes 811573Srgrimes if (c->cpu_cyclic != NULL) { 821573Srgrimes if (TRAPF_USERMODE(frame)) { 831573Srgrimes c->cpu_profile_pc = 0; 841573Srgrimes c->cpu_profile_upc = TRAPF_PC(frame); 851573Srgrimes } else { 861573Srgrimes c->cpu_profile_pc = TRAPF_PC(frame); 871573Srgrimes c->cpu_profile_upc = 0; 881573Srgrimes } 891573Srgrimes 901573Srgrimes c->cpu_intr_actv = 1; 911573Srgrimes 921573Srgrimes /* Fire any timers that are due. */ 931573Srgrimes cyclic_fire(c); 941573Srgrimes 951573Srgrimes c->cpu_intr_actv = 0; 961573Srgrimes } 971573Srgrimes} 981573Srgrimes 991573Srgrimesstatic void 1001573Srgrimesenable(cyb_arg_t arg __unused) 1011573Srgrimes{ 1021573Srgrimes 1031573Srgrimes} 1041573Srgrimes 1051573Srgrimesstatic void 1061573Srgrimesdisable(cyb_arg_t arg __unused) 1071573Srgrimes{ 1081573Srgrimes 1091573Srgrimes} 1101573Srgrimes 1111573Srgrimesstatic void 1121573Srgrimesreprogram(cyb_arg_t arg __unused, hrtime_t exp) 1131573Srgrimes{ 1141573Srgrimes struct bintime bt; 1151573Srgrimes struct timespec ts; 1161573Srgrimes 1171573Srgrimes ts.tv_sec = exp / 1000000000; 1181573Srgrimes ts.tv_nsec = exp % 1000000000; 1191573Srgrimes timespec2bintime(&ts, &bt); 1201573Srgrimes clocksource_cyc_set(&bt); 1211573Srgrimes} 1221573Srgrimes 1231573Srgrimesstatic void xcall(cyb_arg_t arg __unused, cpu_t *c, cyc_func_t func, 1241573Srgrimes void *param) 1251573Srgrimes{ 1261573Srgrimes 1271573Srgrimes smp_rendezvous_cpus((cpumask_t)1 << c->cpuid, 1281573Srgrimes smp_no_rendevous_barrier, func, smp_no_rendevous_barrier, param); 1291573Srgrimes} 1301573Srgrimes