1 /* 2 * Copyright (c) 2006 The DragonFly Project. All rights reserved. 3 * 4 * This code is derived from software contributed to The DragonFly Project 5 * by Matthew Dillon <dillon@backplane.com> 6 * 7 * Redistribution and use in source and binary forms, with or without 8 * modification, are permitted provided that the following conditions 9 * are met: 10 * 11 * 1. Redistributions of source code must retain the above copyright 12 * notice, this list of conditions and the following disclaimer. 13 * 2. Redistributions in binary form must reproduce the above copyright 14 * notice, this list of conditions and the following disclaimer in 15 * the documentation and/or other materials provided with the 16 * distribution. 17 * 3. Neither the name of The DragonFly Project nor the names of its 18 * contributors may be used to endorse or promote products derived 19 * from this software without specific, prior written permission. 20 * 21 * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS 22 * ``AS IS'' AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT 23 * LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS 24 * FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE 25 * COPYRIGHT HOLDERS OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, 26 * INCIDENTAL, SPECIAL, EXEMPLARY OR CONSEQUENTIAL DAMAGES (INCLUDING, 27 * BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; 28 * LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED 29 * AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, 30 * OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT 31 * OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 32 * SUCH DAMAGE. 33 * 34 * $DragonFly: src/sys/platform/vkernel/platform/systimer.c,v 1.17 2008/06/06 13:19:25 swildner Exp $ 35 */ 36 37 #include <sys/types.h> 38 #include <sys/systm.h> 39 #include <sys/kernel.h> 40 #include <sys/systimer.h> 41 #include <sys/sysctl.h> 42 #include <sys/signal.h> 43 #include <sys/interrupt.h> 44 #include <sys/bus.h> 45 #include <sys/time.h> 46 #include <machine/cpu.h> 47 #include <machine/clock.h> 48 #include <machine/globaldata.h> 49 #include <machine/md_var.h> 50 51 #include <sys/thread2.h> 52 53 #include <unistd.h> 54 #include <signal.h> 55 56 #define VKTIMER_FREQ 1000000 /* 1us granularity */ 57 58 static void vktimer_intr(void *dummy, struct intrframe *frame); 59 60 int disable_rtc_set; 61 SYSCTL_INT(_machdep, CPU_DISRTCSET, disable_rtc_set, 62 CTLFLAG_RW, &disable_rtc_set, 0, ""); 63 SYSCTL_INT(_hw, OID_AUTO, tsc_present, CTLFLAG_RD, 64 &tsc_present, 0, "TSC Available"); 65 SYSCTL_QUAD(_hw, OID_AUTO, tsc_frequency, CTLFLAG_RD, 66 &tsc_frequency, 0, "TSC Frequency"); 67 68 int adjkerntz; 69 int wall_cmos_clock = 0; 70 static struct kqueue_info *kqueue_timer_info; 71 72 static int cputimer_mib[16]; 73 static int cputimer_miblen; 74 75 /* 76 * SYSTIMER IMPLEMENTATION 77 */ 78 static sysclock_t vkernel_timer_get_timecount(void); 79 static void vkernel_timer_construct(struct cputimer *timer, sysclock_t oclock); 80 81 static struct cputimer vkernel_cputimer = { 82 SLIST_ENTRY_INITIALIZER, 83 "VKERNEL", 84 CPUTIMER_PRI_VKERNEL, 85 CPUTIMER_VKERNEL, 86 vkernel_timer_get_timecount, 87 cputimer_default_fromhz, 88 cputimer_default_fromus, 89 vkernel_timer_construct, 90 cputimer_default_destruct, 91 VKTIMER_FREQ, 92 0, 0, 0 93 }; 94 95 static void vktimer_intr_reload(struct cputimer_intr *, sysclock_t); 96 static void vktimer_intr_initclock(struct cputimer_intr *, boolean_t); 97 98 static struct cputimer_intr vkernel_cputimer_intr = { 99 .freq = VKTIMER_FREQ, 100 .reload = vktimer_intr_reload, 101 .enable = cputimer_intr_default_enable, 102 .config = cputimer_intr_default_config, 103 .restart = cputimer_intr_default_restart, 104 .pmfixup = cputimer_intr_default_pmfixup, 105 .initclock = vktimer_intr_initclock, 106 .next = SLIST_ENTRY_INITIALIZER, 107 .name = "vkernel", 108 .type = CPUTIMER_INTR_VKERNEL, 109 .prio = CPUTIMER_INTR_PRIO_VKERNEL, 110 .caps = CPUTIMER_INTR_CAP_NONE 111 }; 112 113 /* 114 * Initialize the systimer subsystem, called from MI code in early boot. 115 */ 116 static void 117 cpu_initclocks(void *arg __unused) 118 { 119 size_t len; 120 121 kprintf("initclocks\n"); 122 len = sizeof(vkernel_cputimer.freq); 123 if (sysctlbyname("kern.cputimer.freq", &vkernel_cputimer.freq, &len, 124 NULL, 0) < 0) { 125 panic("cpu_initclocks: can't get kern.cputimer.freq!"); 126 } 127 len = sizeof(cputimer_mib)/sizeof(cputimer_mib[0]); 128 if (sysctlnametomib("kern.cputimer.clock", cputimer_mib, &len) < 0) 129 panic("cpu_initclocks: can't get kern.cputimer.clock!"); 130 cputimer_miblen = len; 131 132 cputimer_intr_register(&vkernel_cputimer_intr); 133 cputimer_intr_select(&vkernel_cputimer_intr, 0); 134 135 cputimer_register(&vkernel_cputimer); 136 cputimer_select(&vkernel_cputimer, 0); 137 } 138 SYSINIT(clocksvk, SI_BOOT2_CLOCKREG, SI_ORDER_FIRST, cpu_initclocks, NULL) 139 140 /* 141 * Constructor to initialize timer->base and get an initial count. 142 */ 143 static void 144 vkernel_timer_construct(struct cputimer *timer, sysclock_t oclock) 145 { 146 timer->base = 0; 147 timer->base = oclock - vkernel_timer_get_timecount(); 148 } 149 150 /* 151 * Get the current counter, with 2's complement rollover. 152 * 153 * NOTE! MPSAFE, possibly no critical section 154 */ 155 static sysclock_t 156 vkernel_timer_get_timecount(void) 157 { 158 sysclock_t counter; 159 size_t len; 160 161 len = sizeof(counter); 162 if (sysctl(cputimer_mib, cputimer_miblen, &counter, &len, 163 NULL, 0) < 0) { 164 panic("vkernel_timer_get_timecount: sysctl failed!"); 165 } 166 return(counter); 167 } 168 169 /* 170 * Initialize the interrupt for our core systimer. Use the kqueue timer 171 * support functions. 172 */ 173 static void 174 vktimer_intr_initclock(struct cputimer_intr *cti __unused, 175 boolean_t selected __unused) 176 { 177 KKASSERT(kqueue_timer_info == NULL); 178 kqueue_timer_info = kqueue_add_timer(vktimer_intr, NULL); 179 } 180 181 /* 182 * Reload the interrupt for our core systimer. Because the caller's 183 * reload calculation can be negatively indexed, we need a minimal 184 * check to ensure that a reasonable reload value is selected. 185 */ 186 static void 187 vktimer_intr_reload(struct cputimer_intr *cti __unused, sysclock_t reload) 188 { 189 if (kqueue_timer_info) { 190 if ((int)reload < 1) 191 reload = 1; 192 kqueue_reload_timer(kqueue_timer_info, (reload + 999) / 1000); 193 } 194 } 195 196 /* 197 * clock interrupt. 198 * 199 * NOTE: frame is a struct intrframe pointer. 200 */ 201 static void 202 vktimer_intr(void *dummy, struct intrframe *frame) 203 { 204 static sysclock_t sysclock_count; 205 struct globaldata *gd = mycpu; 206 #ifdef SMP 207 struct globaldata *gscan; 208 int n; 209 #endif 210 211 sysclock_count = sys_cputimer->count(); 212 #ifdef SMP 213 for (n = 0; n < ncpus; ++n) { 214 gscan = globaldata_find(n); 215 if (TAILQ_FIRST(&gscan->gd_systimerq) == NULL) 216 continue; 217 if (gscan != gd) { 218 lwkt_send_ipiq3(gscan, (ipifunc3_t)systimer_intr, 219 &sysclock_count, 0); 220 } else { 221 systimer_intr(&sysclock_count, 0, frame); 222 } 223 } 224 #else 225 if (TAILQ_FIRST(&gd->gd_systimerq) != NULL) 226 systimer_intr(&sysclock_count, 0, frame); 227 #endif 228 } 229 230 /* 231 * Initialize the time of day register, based on the time base which is, e.g. 232 * from a filesystem. 233 */ 234 void 235 inittodr(time_t base) 236 { 237 struct timespec ts; 238 struct timeval tv; 239 240 gettimeofday(&tv, NULL); 241 ts.tv_sec = tv.tv_sec; 242 ts.tv_nsec = tv.tv_usec * 1000; 243 set_timeofday(&ts); 244 } 245 246 /* 247 * Write system time back to the RTC 248 */ 249 void 250 resettodr(void) 251 { 252 } 253 254 /* 255 * We need to enter a critical section to prevent signals from recursing 256 * into pthreads. 257 */ 258 void 259 DELAY(int usec) 260 { 261 crit_enter(); 262 usleep(usec); 263 crit_exit(); 264 } 265 266 void 267 DRIVERSLEEP(int usec) 268 { 269 if (mycpu->gd_intr_nesting_level) 270 DELAY(usec); 271 else if (1000000 / usec >= hz) 272 tsleep(DRIVERSLEEP, 0, "DELAY", 1000000 / usec / hz + 1); 273 else 274 DELAY(usec); 275 } 276