1 /* $NetBSD: cyclic_machdep.c,v 1.4 2012/12/02 01:05:16 chs Exp $ */ 2 3 /*- 4 * Copyright 2006-2008 John Birrell <jb@FreeBSD.org> 5 * 6 * Redistribution and use in source and binary forms, with or without 7 * modification, are permitted provided that the following conditions 8 * are met: 9 * 1. Redistributions of source code must retain the above copyright 10 * notice, this list of conditions and the following disclaimer. 11 * 2. Redistributions in binary form must reproduce the above copyright 12 * notice, this list of conditions and the following disclaimer in the 13 * documentation and/or other materials provided with the distribution. 14 * 15 * THIS SOFTWARE IS PROVIDED BY AUTHOR AND CONTRIBUTORS ``AS IS'' AND 16 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 17 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 18 * ARE DISCLAIMED. IN NO EVENT SHALL AUTHOR OR CONTRIBUTORS BE LIABLE 19 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 20 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 21 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 22 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 23 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 24 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 25 * SUCH DAMAGE. 26 * 27 * $FreeBSD$ 28 * 29 */ 30 31 static void enable(cyb_arg_t); 32 static void disable(cyb_arg_t); 33 static void reprogram(cyb_arg_t, hrtime_t); 34 static void xcall(cyb_arg_t, cpu_t *, cyc_func_t, void *); 35 36 static cyc_backend_t be = { 37 NULL, /* cyb_configure */ 38 NULL, /* cyb_unconfigure */ 39 enable, 40 disable, 41 reprogram, 42 xcall, 43 NULL /* cyb_arg_t cyb_arg */ 44 }; 45 46 static void 47 cyclic_ap_start(void *dummy) 48 { 49 /* Initialise the rest of the CPUs. */ 50 cyclic_mp_init(); 51 } 52 53 SYSINIT(cyclic_ap_start, SI_SUB_SMP, SI_ORDER_ANY, cyclic_ap_start, NULL); 54 55 /* 56 * Machine dependent cyclic subsystem initialisation. 57 */ 58 static void 59 cyclic_machdep_init(void) 60 { 61 /* Register the cyclic backend. */ 62 cyclic_init(&be); 63 #ifdef __NetBSD__ 64 cyclic_ap_start(NULL); 65 #endif 66 } 67 68 static void 69 cyclic_machdep_uninit(void) 70 { 71 int i; 72 73 for (i = 0; i <= mp_maxid; i++) 74 /* Reset the cyclic clock callback hook. */ 75 cyclic_clock_func[i] = NULL; 76 77 /* De-register the cyclic backend. */ 78 cyclic_uninit(); 79 } 80 81 static hrtime_t exp_due[MAXCPU]; 82 83 /* 84 * This function is the one registered by the machine dependent 85 * initialiser as the callback for high speed timer events. 86 */ 87 static void 88 cyclic_clock(struct clockframe *frame) 89 { 90 cpu_t *c = &solaris_cpu[cpu_number()]; 91 92 if (c->cpu_cyclic != NULL && gethrtime() >= exp_due[cpu_number()]) { 93 if (TRAPF_USERMODE(frame)) { 94 c->cpu_profile_pc = 0; 95 c->cpu_profile_upc = TRAPF_PC(frame); 96 } else { 97 c->cpu_profile_pc = TRAPF_PC(frame); 98 c->cpu_profile_upc = 0; 99 } 100 101 c->cpu_intr_actv = 1; 102 103 /* Fire any timers that are due. */ 104 cyclic_fire(c); 105 106 c->cpu_intr_actv = 0; 107 } 108 } 109 110 static void enable(cyb_arg_t arg) 111 { 112 /* Register the cyclic clock callback function. */ 113 cyclic_clock_func[cpu_number()] = cyclic_clock; 114 } 115 116 static void disable(cyb_arg_t arg) 117 { 118 /* Reset the cyclic clock callback function. */ 119 cyclic_clock_func[cpu_number()] = NULL; 120 } 121 122 static void reprogram(cyb_arg_t arg, hrtime_t exp) 123 { 124 exp_due[cpu_number()] = exp; 125 } 126 127 #ifdef __NetBSD__ 128 static void xcall_func(void *arg0, void *arg1) 129 { 130 cyc_func_t func; 131 132 func = arg0; 133 (*func)(arg1); 134 } 135 #endif 136 137 static void xcall(cyb_arg_t arg, cpu_t *c, cyc_func_t func, void *param) 138 { 139 #ifdef __NetBSD__ 140 uint64_t xc; 141 142 xc = xc_unicast(XC_HIGHPRI, xcall_func, func, param, cpu_lookup(c->cpuid)); 143 xc_wait(xc); 144 #else 145 smp_rendezvous_cpus((cpumask_t) (1 << c->cpuid), 146 smp_no_rendevous_barrier, func, smp_no_rendevous_barrier, param); 147 #endif 148 } 149