1/* $NetBSD: cyclic_machdep.c,v 1.5 2018/05/28 21:05:02 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: head/sys/cddl/dev/cyclic/i386/cyclic_machdep.c 222813 2011-06-07 08:46:13Z attilio $ 28 * 29 */ 30 31static void enable(cyb_arg_t); 32static void disable(cyb_arg_t); 33static void reprogram(cyb_arg_t, hrtime_t); 34static void xcall(cyb_arg_t, cpu_t *, cyc_func_t, void *); 35 36static 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 46static void 47cyclic_ap_start(void *dummy) 48{ 49 /* Initialise the rest of the CPUs. */ 50 cyclic_mp_init(); 51} 52 53SYSINIT(cyclic_ap_start, SI_SUB_SMP, SI_ORDER_ANY, cyclic_ap_start, NULL); 54 55/* 56 * Machine dependent cyclic subsystem initialisation. 57 */ 58static void 59cyclic_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 68static void 69cyclic_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 81static 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 */ 87static void 88cyclic_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 110static void enable(cyb_arg_t arg) 111{ 112 /* Register the cyclic clock callback function. */ 113 cyclic_clock_func[cpu_number()] = cyclic_clock; 114} 115 116static void disable(cyb_arg_t arg) 117{ 118 /* Reset the cyclic clock callback function. */ 119 cyclic_clock_func[cpu_number()] = NULL; 120} 121 122static void reprogram(cyb_arg_t arg, hrtime_t exp) 123{ 124 exp_due[cpu_number()] = exp; 125} 126 127#ifdef __NetBSD__ 128static void xcall_func(void *arg0, void *arg1) 129{ 130 cyc_func_t func; 131 132 func = arg0; 133 (*func)(arg1); 134} 135#endif 136 137static 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