1 /* $OpenBSD: clock.c,v 1.74 2022/12/29 22:44:23 cheloha Exp $ */ 2 /* $NetBSD: clock.c,v 1.41 2001/07/24 19:29:25 eeh Exp $ */ 3 4 /* 5 * Copyright (c) 1992, 1993 6 * The Regents of the University of California. All rights reserved. 7 * Copyright (c) 1994 Gordon W. Ross 8 * Copyright (c) 1993 Adam Glass 9 * Copyright (c) 1996 Paul Kranenburg 10 * Copyright (c) 1996 11 * The President and Fellows of Harvard College. All rights reserved. 12 * 13 * This software was developed by the Computer Systems Engineering group 14 * at Lawrence Berkeley Laboratory under DARPA contract BG 91-66 and 15 * contributed to Berkeley. 16 * 17 * All advertising materials mentioning features or use of this software 18 * must display the following acknowledgement: 19 * This product includes software developed by Harvard University. 20 * This product includes software developed by the University of 21 * California, Lawrence Berkeley Laboratory. 22 * 23 * Redistribution and use in source and binary forms, with or without 24 * modification, are permitted provided that the following conditions 25 * are met: 26 * 27 * 1. Redistributions of source code must retain the above copyright 28 * notice, this list of conditions and the following disclaimer. 29 * 2. Redistributions in binary form must reproduce the above copyright 30 * notice, this list of conditions and the following disclaimer in the 31 * documentation and/or other materials provided with the distribution. 32 * 3. All advertising materials mentioning features or use of this software 33 * must display the following acknowledgement: 34 * This product includes software developed by the University of 35 * California, Berkeley and its contributors. 36 * This product includes software developed by Paul Kranenburg. 37 * This product includes software developed by Harvard University. 38 * 4. Neither the name of the University nor the names of its contributors 39 * may be used to endorse or promote products derived from this software 40 * without specific prior written permission. 41 * 42 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 43 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 44 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 45 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 46 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 47 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 48 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 49 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 50 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 51 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 52 * SUCH DAMAGE. 53 * 54 * @(#)clock.c 8.1 (Berkeley) 6/11/93 55 * 56 */ 57 58 /* 59 * Clock driver. This is the id prom and eeprom driver as well 60 * and includes the timer register functions too. 61 */ 62 63 /* Define this for a 1/4s clock to ease debugging */ 64 /* #define INTR_DEBUG */ 65 66 #include <sys/param.h> 67 #include <sys/kernel.h> 68 #include <sys/device.h> 69 #include <sys/proc.h> 70 #include <sys/resourcevar.h> 71 #include <sys/malloc.h> 72 #include <sys/systm.h> 73 #ifdef GPROF 74 #include <sys/gmon.h> 75 #endif 76 #include <sys/sched.h> 77 #include <sys/timetc.h> 78 #include <sys/atomic.h> 79 80 #include <machine/bus.h> 81 #include <machine/autoconf.h> 82 #include <machine/cpu.h> 83 #include <machine/idprom.h> 84 85 #include <dev/clock_subr.h> 86 #include <dev/ic/mk48txxreg.h> 87 88 #include <sparc64/sparc64/intreg.h> 89 #include <sparc64/sparc64/timerreg.h> 90 #include <sparc64/dev/iommureg.h> 91 #include <sparc64/dev/sbusreg.h> 92 #include <dev/sbus/sbusvar.h> 93 #include <sparc64/dev/ebusreg.h> 94 #include <sparc64/dev/ebusvar.h> 95 #include <sparc64/dev/fhcvar.h> 96 97 extern u_int64_t cpu_clockrate; 98 99 struct clock_wenable_info { 100 bus_space_tag_t cwi_bt; 101 bus_space_handle_t cwi_bh; 102 bus_size_t cwi_size; 103 }; 104 105 struct cfdriver clock_cd = { 106 NULL, "clock", DV_DULL 107 }; 108 109 u_int tick_get_timecount(struct timecounter *); 110 111 struct timecounter tick_timecounter = { 112 .tc_get_timecount = tick_get_timecount, 113 .tc_poll_pps = NULL, 114 .tc_counter_mask = ~0u, 115 .tc_frequency = 0, 116 .tc_name = "tick", 117 .tc_quality = 0, 118 .tc_priv = NULL, 119 .tc_user = TC_TICK, 120 }; 121 122 u_int sys_tick_get_timecount(struct timecounter *); 123 124 struct timecounter sys_tick_timecounter = { 125 .tc_get_timecount = sys_tick_get_timecount, 126 .tc_poll_pps = NULL, 127 .tc_counter_mask = ~0u, 128 .tc_frequency = 0, 129 .tc_name = "sys_tick", 130 .tc_quality = 1000, 131 .tc_priv = NULL, 132 .tc_user = TC_SYS_TICK, 133 }; 134 135 /* 136 * Statistics clock interval and variance, in usec. Variance must be a 137 * power of two. Since this gives us an even number, not an odd number, 138 * we discard one case and compensate. That is, a variance of 1024 would 139 * give us offsets in [0..1023]. Instead, we take offsets in [1..1023]. 140 * This is symmetric about the point 512, or statvar/2, and thus averages 141 * to that value (assuming uniform random numbers). 142 */ 143 /* XXX fix comment to match value */ 144 int statvar = 8192; 145 int statmin; /* statclock interval - 1/2*variance */ 146 147 static long tick_increment; 148 149 void tick_start(void); 150 void sys_tick_start(void); 151 void stick_start(void); 152 153 void tick_rearm(uint64_t); 154 void sys_tick_rearm(uint64_t); 155 void stick_rearm(uint64_t); 156 157 int tickintr(void *); 158 int sys_tickintr(void *); 159 int stickintr(void *); 160 int schedintr(void *); 161 162 static struct intrhand level10 = { clockintr }; 163 static struct intrhand level0 = { tickintr }; 164 static struct intrhand level14 = { statintr }; 165 static struct intrhand schedint = { schedintr }; 166 167 /* 168 * clock (eeprom) attaches at the sbus or the ebus (PCI) 169 */ 170 static int clockmatch_sbus(struct device *, void *, void *); 171 static void clockattach_sbus(struct device *, struct device *, void *); 172 static int clockmatch_ebus(struct device *, void *, void *); 173 static void clockattach_ebus(struct device *, struct device *, void *); 174 static int clockmatch_fhc(struct device *, void *, void *); 175 static void clockattach_fhc(struct device *, struct device *, void *); 176 static void clockattach(int, bus_space_tag_t, bus_space_handle_t); 177 178 const struct cfattach clock_sbus_ca = { 179 sizeof(struct device), clockmatch_sbus, clockattach_sbus 180 }; 181 182 const struct cfattach clock_ebus_ca = { 183 sizeof(struct device), clockmatch_ebus, clockattach_ebus 184 }; 185 186 const struct cfattach clock_fhc_ca = { 187 sizeof(struct device), clockmatch_fhc, clockattach_fhc 188 }; 189 190 /* Global TOD clock handle & idprom pointer */ 191 extern todr_chip_handle_t todr_handle; 192 static struct idprom *idprom; 193 194 static int timermatch(struct device *, void *, void *); 195 static void timerattach(struct device *, struct device *, void *); 196 197 struct timerreg_4u timerreg_4u; /* XXX - need more cleanup */ 198 199 const struct cfattach timer_ca = { 200 sizeof(struct device), timermatch, timerattach 201 }; 202 203 struct cfdriver timer_cd = { 204 NULL, "timer", DV_DULL 205 }; 206 207 int clock_bus_wenable(struct todr_chip_handle *, int); 208 struct chiptime; 209 void myetheraddr(u_char *); 210 struct idprom *getidprom(void); 211 int chiptotime(int, int, int, int, int, int); 212 void timetochip(struct chiptime *); 213 void stopcounter(struct timer_4u *); 214 215 int timerblurb = 10; /* Guess a value; used before clock is attached */ 216 217 /* 218 * The OPENPROM calls the clock the "eeprom", so we have to have our 219 * own special match function to call it the "clock". 220 */ 221 static int 222 clockmatch_sbus(struct device *parent, void *cf, void *aux) 223 { 224 struct sbus_attach_args *sa = aux; 225 226 return (strcmp("eeprom", sa->sa_name) == 0); 227 } 228 229 static int 230 clockmatch_ebus(struct device *parent, void *cf, void *aux) 231 { 232 struct ebus_attach_args *ea = aux; 233 234 return (strcmp("eeprom", ea->ea_name) == 0); 235 } 236 237 static int 238 clockmatch_fhc(struct device *parent, void *cf, void *aux) 239 { 240 struct fhc_attach_args *fa = aux; 241 242 return (strcmp("eeprom", fa->fa_name) == 0); 243 } 244 245 /* 246 * Attach a clock (really `eeprom') to the sbus or ebus. 247 * 248 * We ignore any existing virtual address as we need to map 249 * this read-only and make it read-write only temporarily, 250 * whenever we read or write the clock chip. The clock also 251 * contains the ID ``PROM'', and I have already had the pleasure 252 * of reloading the cpu type, Ethernet address, etc, by hand from 253 * the console FORTH interpreter. I intend not to enjoy it again. 254 * 255 * the MK48T02 is 2K. the MK48T08 is 8K, and the MK48T59 is 256 * supposed to be identical to it. 257 * 258 * This is *UGLY*! We probably have multiple mappings. But I do 259 * know that this all fits inside an 8K page, so I'll just map in 260 * once. 261 * 262 * What we really need is some way to record the bus attach args 263 * so we can call *_bus_map() later with BUS_SPACE_MAP_READONLY 264 * or not to write enable/disable the device registers. This is 265 * a non-trivial operation. 266 */ 267 268 static void 269 clockattach_sbus(struct device *parent, struct device *self, void *aux) 270 { 271 struct sbus_attach_args *sa = aux; 272 bus_space_tag_t bt = sa->sa_bustag; 273 int sz; 274 static struct clock_wenable_info cwi; 275 276 /* use sa->sa_regs[0].size? */ 277 sz = 8192; 278 279 if (sbus_bus_map(bt, 280 sa->sa_slot, 281 (sa->sa_offset & ~NBPG), 282 sz, 283 BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_READONLY, 284 0, &cwi.cwi_bh) != 0) { 285 printf("%s: can't map register\n", self->dv_xname); 286 return; 287 } 288 clockattach(sa->sa_node, bt, cwi.cwi_bh); 289 290 /* Save info for the clock wenable call. */ 291 cwi.cwi_bt = bt; 292 cwi.cwi_size = sz; 293 todr_handle->bus_cookie = &cwi; 294 todr_handle->todr_setwen = clock_bus_wenable; 295 } 296 297 /* 298 * Write en/dis-able clock registers. We coordinate so that several 299 * writers can run simultaneously. 300 * XXX There is still a race here. The page change and the "writers" 301 * change are not atomic. 302 */ 303 int 304 clock_bus_wenable(struct todr_chip_handle *handle, int onoff) 305 { 306 int s, err = 0; 307 int prot; /* nonzero => change prot */ 308 volatile static int writers; 309 struct clock_wenable_info *cwi = handle->bus_cookie; 310 311 s = splhigh(); 312 if (onoff) 313 prot = writers++ == 0 ? 1 : 0; 314 else 315 prot = --writers == 0 ? 1 : 0; 316 splx(s); 317 318 if (prot) { 319 err = bus_space_protect(cwi->cwi_bt, cwi->cwi_bh, cwi->cwi_size, 320 onoff ? 0 : BUS_SPACE_MAP_READONLY); 321 if (err) 322 printf("clock_wenable_info: WARNING -- cannot %s " 323 "page protection\n", onoff ? "disable" : "enable"); 324 } 325 return (err); 326 } 327 328 static void 329 clockattach_ebus(struct device *parent, struct device *self, void *aux) 330 { 331 struct ebus_attach_args *ea = aux; 332 bus_space_tag_t bt; 333 int sz; 334 static struct clock_wenable_info cwi; 335 336 /* hard code to 8K? */ 337 sz = ea->ea_regs[0].size; 338 339 if (ea->ea_nvaddrs) { 340 if (bus_space_map(ea->ea_memtag, ea->ea_vaddrs[0], 0, 341 BUS_SPACE_MAP_PROMADDRESS, &cwi.cwi_bh) != 0) { 342 printf("%s: can't map register\n", self->dv_xname); 343 return; 344 } 345 bt = ea->ea_memtag; 346 } else if (ebus_bus_map(ea->ea_iotag, 0, 347 EBUS_PADDR_FROM_REG(&ea->ea_regs[0]), sz, 0, 0, &cwi.cwi_bh) == 0) { 348 bt = ea->ea_iotag; 349 } else if (ebus_bus_map(ea->ea_memtag, 0, 350 EBUS_PADDR_FROM_REG(&ea->ea_regs[0]), sz, 351 BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_READONLY, 352 0, &cwi.cwi_bh) == 0) { 353 bt = ea->ea_memtag; 354 } else { 355 printf("%s: can't map register\n", self->dv_xname); 356 return; 357 } 358 359 clockattach(ea->ea_node, bt, cwi.cwi_bh); 360 361 /* Save info for the clock wenable call. */ 362 cwi.cwi_bt = bt; 363 cwi.cwi_size = sz; 364 todr_handle->bus_cookie = &cwi; 365 todr_handle->todr_setwen = (ea->ea_memtag == bt) ? 366 clock_bus_wenable : NULL; 367 } 368 369 static void 370 clockattach_fhc(struct device *parent, struct device *self, void *aux) 371 { 372 struct fhc_attach_args *fa = aux; 373 bus_space_tag_t bt = fa->fa_bustag; 374 int sz; 375 static struct clock_wenable_info cwi; 376 377 /* use sa->sa_regs[0].size? */ 378 sz = 8192; 379 380 if (fhc_bus_map(bt, fa->fa_reg[0].fbr_slot, 381 (fa->fa_reg[0].fbr_offset & ~NBPG), fa->fa_reg[0].fbr_size, 382 BUS_SPACE_MAP_LINEAR | BUS_SPACE_MAP_READONLY, &cwi.cwi_bh) != 0) { 383 printf("%s: can't map register\n", self->dv_xname); 384 return; 385 } 386 387 clockattach(fa->fa_node, bt, cwi.cwi_bh); 388 389 /* Save info for the clock wenable call. */ 390 cwi.cwi_bt = bt; 391 cwi.cwi_size = sz; 392 todr_handle->bus_cookie = &cwi; 393 todr_handle->todr_setwen = clock_bus_wenable; 394 } 395 396 static void 397 clockattach(int node, bus_space_tag_t bt, bus_space_handle_t bh) 398 { 399 char *model; 400 struct idprom *idp; 401 int h; 402 403 model = getpropstring(node, "model"); 404 405 #ifdef DIAGNOSTIC 406 if (model == NULL) 407 panic("clockattach: no model property"); 408 #endif 409 410 /* Our TOD clock year 0 is 1968 */ 411 if ((todr_handle = mk48txx_attach(bt, bh, model, 1968)) == NULL) 412 panic("Can't attach %s tod clock", model); 413 414 #define IDPROM_OFFSET (8*1024 - 40) /* XXX - get nvram sz from driver */ 415 if (idprom == NULL) { 416 idp = getidprom(); 417 if (idp == NULL) 418 idp = (struct idprom *)(bus_space_vaddr(bt, bh) + 419 IDPROM_OFFSET); 420 idprom = idp; 421 } else 422 idp = idprom; 423 h = idp->id_machine << 24; 424 h |= idp->id_hostid[0] << 16; 425 h |= idp->id_hostid[1] << 8; 426 h |= idp->id_hostid[2]; 427 hostid = h; 428 printf("\n"); 429 } 430 431 struct idprom * 432 getidprom(void) 433 { 434 struct idprom *idp = NULL; 435 int node, n; 436 437 node = findroot(); 438 if (getprop(node, "idprom", sizeof(*idp), &n, (void **)&idp) != 0) 439 return (NULL); 440 if (n != 1) { 441 free(idp, M_DEVBUF, 0); 442 return (NULL); 443 } 444 return (idp); 445 } 446 447 /* 448 * The sun4u OPENPROMs call the timer the "counter-timer", except for 449 * the lame UltraSPARC IIi PCI machines that don't have them. 450 */ 451 static int 452 timermatch(struct device *parent, void *cf, void *aux) 453 { 454 #ifndef MULTIPROCESSOR 455 struct mainbus_attach_args *ma = aux; 456 457 if (!timerreg_4u.t_timer || !timerreg_4u.t_clrintr) 458 return (strcmp("counter-timer", ma->ma_name) == 0); 459 else 460 #endif 461 return (0); 462 } 463 464 static void 465 timerattach(struct device *parent, struct device *self, void *aux) 466 { 467 struct mainbus_attach_args *ma = aux; 468 u_int *va = ma->ma_address; 469 470 /* 471 * What we should have are 3 sets of registers that reside on 472 * different parts of SYSIO or PSYCHO. We'll use the prom 473 * mappings cause we can't get rid of them and set up appropriate 474 * pointers on the timerreg_4u structure. 475 */ 476 timerreg_4u.t_timer = (struct timer_4u *)(u_long)va[0]; 477 timerreg_4u.t_clrintr = (int64_t *)(u_long)va[1]; 478 timerreg_4u.t_mapintr = (int64_t *)(u_long)va[2]; 479 480 /* Install the appropriate interrupt vector here */ 481 level10.ih_number = INTVEC(ma->ma_interrupts[0]); 482 level10.ih_clr = (void *)&timerreg_4u.t_clrintr[0]; 483 level10.ih_map = (void *)&timerreg_4u.t_mapintr[0]; 484 strlcpy(level10.ih_name, "clock", sizeof(level10.ih_name)); 485 intr_establish(10, &level10); 486 487 level14.ih_number = INTVEC(ma->ma_interrupts[1]); 488 level14.ih_clr = (void *)&timerreg_4u.t_clrintr[1]; 489 level14.ih_map = (void *)&timerreg_4u.t_mapintr[1]; 490 strlcpy(level14.ih_name, "prof", sizeof(level14.ih_name)); 491 intr_establish(14, &level14); 492 493 printf(" ivec 0x%llx, 0x%llx\n", INTVEC(level10.ih_number), 494 INTVEC(level14.ih_number)); 495 } 496 497 void 498 stopcounter(struct timer_4u *creg) 499 { 500 /* Stop the clock */ 501 volatile int discard; 502 discard = creg->t_limit; 503 creg->t_limit = 0; 504 } 505 506 /* 507 * XXX this belongs elsewhere 508 */ 509 void 510 myetheraddr(u_char *cp) 511 { 512 struct idprom *idp; 513 514 if ((idp = idprom) == NULL) { 515 int node, n; 516 517 node = findroot(); 518 if (getprop(node, "idprom", sizeof *idp, &n, (void **)&idp) || 519 n != 1) { 520 printf("\nmyetheraddr: clock not setup yet, " 521 "and no idprom property in /\n"); 522 return; 523 } 524 } 525 526 cp[0] = idp->id_ether[0]; 527 cp[1] = idp->id_ether[1]; 528 cp[2] = idp->id_ether[2]; 529 cp[3] = idp->id_ether[3]; 530 cp[4] = idp->id_ether[4]; 531 cp[5] = idp->id_ether[5]; 532 if (idprom == NULL) 533 free(idp, M_DEVBUF, 0); 534 } 535 536 /* 537 * Set up the real-time and statistics clocks. Leave stathz 0 only if 538 * no alternative timer is available. 539 * 540 * The frequencies of these clocks must be an even number of microseconds. 541 */ 542 void 543 cpu_initclocks(void) 544 { 545 int statint, minint; 546 #ifdef DEBUG 547 extern int intrdebug; 548 #endif 549 u_int sys_tick_rate; 550 int impl = 0; 551 552 #ifdef DEBUG 553 /* Set a 1s clock */ 554 if (intrdebug) { 555 hz = 1; 556 tick = 1000000 / hz; 557 tick_nsec = 1000000000 / hz; 558 printf("intrdebug set: 1Hz clock\n"); 559 } 560 #endif 561 562 if (1000000 % hz) { 563 printf("cannot get %d Hz clock; using 100 Hz\n", hz); 564 hz = 100; 565 tick = 1000000 / hz; 566 tick_nsec = 1000000000 / hz; 567 } 568 569 /* Make sure we have a sane cpu_clockrate -- we'll need it */ 570 if (!cpu_clockrate) 571 /* Default to 200MHz clock XXXXX */ 572 cpu_clockrate = 200000000; 573 574 tick_timecounter.tc_frequency = cpu_clockrate; 575 tc_init(&tick_timecounter); 576 577 /* 578 * UltraSPARC IIe processors do have a STICK register, but it 579 * lives on the PCI host bridge and isn't accessible through 580 * ASR24. 581 */ 582 if (CPU_ISSUN4U || CPU_ISSUN4US) 583 impl = (getver() & VER_IMPL) >> VER_IMPL_SHIFT; 584 585 sys_tick_rate = getpropint(findroot(), "stick-frequency", 0); 586 if (sys_tick_rate > 0 && impl != IMPL_HUMMINGBIRD) { 587 sys_tick_timecounter.tc_frequency = sys_tick_rate; 588 tc_init(&sys_tick_timecounter); 589 } 590 591 /* 592 * Now handle machines w/o counter-timers. 593 */ 594 595 if (!timerreg_4u.t_timer || !timerreg_4u.t_clrintr) { 596 struct cpu_info *ci; 597 598 /* We don't have a counter-timer -- use %tick */ 599 level0.ih_clr = 0; 600 601 /* 602 * Establish a level 10 interrupt handler 603 * 604 * We will have a conflict with the softint handler, 605 * so we set the ih_number to 1. 606 */ 607 level0.ih_number = 1; 608 strlcpy(level0.ih_name, "clock", sizeof(level0.ih_name)); 609 intr_establish(10, &level0); 610 evcount_percpu(&level0.ih_count); 611 612 /* We only have one timer so we have no statclock */ 613 stathz = 0; 614 615 if (sys_tick_rate > 0) { 616 tick_increment = sys_tick_rate / hz; 617 if (impl == IMPL_HUMMINGBIRD) { 618 level0.ih_fun = stickintr; 619 cpu_start_clock = stick_start; 620 } else { 621 level0.ih_fun = sys_tickintr; 622 cpu_start_clock = sys_tick_start; 623 } 624 } else { 625 /* set the next interrupt time */ 626 tick_increment = cpu_clockrate / hz; 627 level0.ih_fun = tickintr; 628 cpu_start_clock = tick_start; 629 } 630 631 for (ci = cpus; ci != NULL; ci = ci->ci_next) 632 memcpy(&ci->ci_tickintr, &level0, sizeof(level0)); 633 634 cpu_start_clock(); 635 636 return; 637 } 638 639 if (stathz == 0) 640 stathz = hz; 641 if (1000000 % stathz) { 642 printf("cannot get %d Hz statclock; using 100 Hz\n", stathz); 643 stathz = 100; 644 } 645 646 profhz = stathz; /* always */ 647 648 statint = 1000000 / stathz; 649 minint = statint / 2 + 100; 650 while (statvar > minint) 651 statvar >>= 1; 652 653 /* 654 * Establish scheduler softint. 655 */ 656 schedint.ih_pil = PIL_SCHED; 657 schedint.ih_clr = NULL; 658 schedint.ih_arg = 0; 659 schedint.ih_pending = 0; 660 schedhz = stathz/4; 661 662 /* 663 * Enable timers 664 * 665 * Also need to map the interrupts cause we're not a child of the sbus. 666 * N.B. By default timer[0] is disabled and timer[1] is enabled. 667 */ 668 stxa((vaddr_t)&timerreg_4u.t_timer[0].t_limit, ASI_NUCLEUS, 669 tmr_ustolim(tick)|TMR_LIM_IEN|TMR_LIM_PERIODIC|TMR_LIM_RELOAD); 670 stxa((vaddr_t)&timerreg_4u.t_mapintr[0], ASI_NUCLEUS, 671 timerreg_4u.t_mapintr[0]|INTMAP_V); 672 673 #ifdef DEBUG 674 if (intrdebug) 675 /* Neglect to enable timer */ 676 stxa((vaddr_t)&timerreg_4u.t_timer[1].t_limit, ASI_NUCLEUS, 677 tmr_ustolim(statint)|TMR_LIM_RELOAD); 678 else 679 #endif 680 stxa((vaddr_t)&timerreg_4u.t_timer[1].t_limit, ASI_NUCLEUS, 681 tmr_ustolim(statint)|TMR_LIM_IEN|TMR_LIM_RELOAD); 682 stxa((vaddr_t)&timerreg_4u.t_mapintr[1], ASI_NUCLEUS, 683 timerreg_4u.t_mapintr[1]|INTMAP_V); 684 685 statmin = statint - (statvar >> 1); 686 687 tick_enable(); 688 } 689 690 /* 691 * Dummy setstatclockrate(), since we know profhz==hz. 692 */ 693 void 694 setstatclockrate(int newhz) 695 { 696 /* nothing */ 697 } 698 699 /* 700 * Level 10 (clock) interrupts. If we are using the FORTH PROM for 701 * console input, we need to check for that here as well, and generate 702 * a software interrupt to read it. 703 */ 704 #ifdef DEBUG 705 static int clockcheck = 0; 706 #endif 707 int 708 clockintr(void *cap) 709 { 710 #ifdef DEBUG 711 static int64_t tick_base = 0; 712 struct timeval ctime; 713 int64_t t; 714 715 t = tick() & TICK_TICKS; 716 717 microtime(&ctime); 718 if (!tick_base) { 719 tick_base = (ctime.tv_sec * 1000000LL + ctime.tv_usec) 720 * 1000000LL / cpu_clockrate; 721 tick_base -= t; 722 } else if (clockcheck) { 723 int64_t tk = t; 724 int64_t clk = (ctime.tv_sec * 1000000LL + ctime.tv_usec); 725 t -= tick_base; 726 t = t * 1000000LL / cpu_clockrate; 727 if (t - clk > hz) { 728 printf("Clock lost an interrupt!\n"); 729 printf("Actual: %llx Expected: %llx tick %llx " 730 "tick_base %llx\n", (long long)t, (long long)clk, 731 (long long)tk, (long long)tick_base); 732 #ifdef DDB 733 db_enter(); 734 #endif 735 tick_base = 0; 736 } 737 } 738 #endif 739 /* Let locore.s clear the interrupt for us. */ 740 hardclock((struct clockframe *)cap); 741 742 return (1); 743 } 744 745 /* 746 * Level 10 (clock) interrupts. If we are using the FORTH PROM for 747 * console input, we need to check for that here as well, and generate 748 * a software interrupt to read it. 749 * 750 * %tick is really a level-14 interrupt. We need to remap this in 751 * locore.s to a level 10. 752 */ 753 int 754 tickintr(void *cap) 755 { 756 struct cpu_info *ci = curcpu(); 757 u_int64_t s; 758 759 /* 760 * No need to worry about overflow; %tick is architecturally 761 * defined not to do that for at least 10 years. 762 */ 763 while (ci->ci_tick < tick()) { 764 ci->ci_tick += tick_increment; 765 hardclock((struct clockframe *)cap); 766 evcount_inc(&level0.ih_count); 767 } 768 769 /* Reset the interrupt. */ 770 s = intr_disable(); 771 tick_rearm(ci->ci_tick); 772 intr_restore(s); 773 774 return (1); 775 } 776 777 int 778 sys_tickintr(void *cap) 779 { 780 struct cpu_info *ci = curcpu(); 781 u_int64_t s; 782 783 /* 784 * Do we need to worry about overflow here? 785 */ 786 while (ci->ci_tick < sys_tick()) { 787 ci->ci_tick += tick_increment; 788 hardclock((struct clockframe *)cap); 789 evcount_inc(&level0.ih_count); 790 } 791 792 /* Reset the interrupt. */ 793 s = intr_disable(); 794 sys_tick_rearm(ci->ci_tick); 795 intr_restore(s); 796 797 return (1); 798 } 799 800 int 801 stickintr(void *cap) 802 { 803 struct cpu_info *ci = curcpu(); 804 u_int64_t s; 805 806 /* 807 * Do we need to worry about overflow here? 808 */ 809 while (ci->ci_tick < stick()) { 810 ci->ci_tick += tick_increment; 811 hardclock((struct clockframe *)cap); 812 evcount_inc(&level0.ih_count); 813 } 814 815 /* Reset the interrupt. */ 816 s = intr_disable(); 817 stick_rearm(ci->ci_tick); 818 intr_restore(s); 819 820 return (1); 821 } 822 823 /* 824 * Level 14 (stat clock) interrupt handler. 825 */ 826 int 827 statintr(void *cap) 828 { 829 u_long newint, r, var; 830 struct cpu_info *ci = curcpu(); 831 832 #ifdef NOT_DEBUG 833 printf("statclock: count %x:%x, limit %x:%x\n", 834 timerreg_4u.t_timer[1].t_count, timerreg_4u.t_timer[1].t_limit); 835 #endif 836 #ifdef NOT_DEBUG 837 prom_printf("!"); 838 #endif 839 statclock((struct clockframe *)cap); 840 #ifdef NOTDEF_DEBUG 841 /* Don't re-schedule the IRQ */ 842 return 1; 843 #endif 844 /* 845 * Compute new randomized interval. The intervals are uniformly 846 * distributed on [statint - statvar / 2, statint + statvar / 2], 847 * and therefore have mean statint, giving a stathz frequency clock. 848 */ 849 var = statvar; 850 do { 851 r = random() & (var - 1); 852 } while (r == 0); 853 newint = statmin + r; 854 855 if (schedhz) 856 if ((++ci->ci_schedstate.spc_schedticks & 3) == 0) 857 send_softint(-1, PIL_SCHED, &schedint); 858 stxa((vaddr_t)&timerreg_4u.t_timer[1].t_limit, ASI_NUCLEUS, 859 tmr_ustolim(newint)|TMR_LIM_IEN|TMR_LIM_RELOAD); 860 861 return (1); 862 } 863 864 int 865 schedintr(void *arg) 866 { 867 if (curproc) 868 schedclock(curproc); 869 return (1); 870 } 871 872 void 873 tick_start(void) 874 { 875 struct cpu_info *ci = curcpu(); 876 u_int64_t s; 877 878 tick_enable(); 879 880 s = intr_disable(); 881 ci->ci_tick = tick(); 882 tick_rearm(ci->ci_tick); 883 intr_restore(s); 884 } 885 886 void 887 tick_rearm(uint64_t cmp) 888 { 889 uint64_t now, off = 8; 890 891 tickcmpr_set(cmp); 892 now = tick(); 893 while (cmp <= now) { 894 cmp += off; 895 tickcmpr_set(cmp); 896 now = tick(); 897 off *= 2; 898 } 899 } 900 901 void 902 sys_tick_start(void) 903 { 904 struct cpu_info *ci = curcpu(); 905 u_int64_t s; 906 907 if (CPU_ISSUN4U || CPU_ISSUN4US) { 908 tick_enable(); 909 sys_tick_enable(); 910 } 911 912 s = intr_disable(); 913 ci->ci_tick = sys_tick(); 914 sys_tick_rearm(ci->ci_tick); 915 intr_restore(s); 916 } 917 918 void 919 sys_tick_rearm(uint64_t cmp) 920 { 921 uint64_t now, off = 8; 922 923 sys_tickcmpr_set(cmp); 924 now = sys_tick(); 925 while (cmp <= now) { 926 cmp += off; 927 sys_tickcmpr_set(cmp); 928 now = sys_tick(); 929 off *= 2; 930 } 931 } 932 933 void 934 stick_start(void) 935 { 936 struct cpu_info *ci = curcpu(); 937 u_int64_t s; 938 939 tick_enable(); 940 941 s = intr_disable(); 942 ci->ci_tick = stick(); 943 stick_rearm(ci->ci_tick); 944 intr_restore(s); 945 } 946 947 void 948 stick_rearm(uint64_t cmp) 949 { 950 uint64_t now, off = 8; 951 952 stickcmpr_set(cmp); 953 now = stick(); 954 while (cmp <= now) { 955 cmp += off; 956 stickcmpr_set(cmp); 957 now = stick(); 958 off *= 2; 959 } 960 } 961 962 u_int 963 tick_get_timecount(struct timecounter *tc) 964 { 965 u_int64_t tick; 966 967 __asm volatile("rd %%tick, %0" : "=r" (tick)); 968 969 return (tick & ~0u); 970 } 971 972 u_int 973 sys_tick_get_timecount(struct timecounter *tc) 974 { 975 u_int64_t tick; 976 977 __asm volatile("rd %%sys_tick, %0" : "=r" (tick)); 978 979 return (tick & ~0u); 980 } 981