1 /* $NetBSD: machdep.c,v 1.61 2002/03/05 16:13:57 simonb Exp $ */ 2 3 /* 4 * Copyright (c) 1988 University of Utah. 5 * Copyright (c) 1992, 1993 6 * The Regents of the University of California. All rights reserved. 7 * 8 * This code is derived from software contributed to Berkeley by 9 * the Systems Programming Group of the University of Utah Computer 10 * Science Department, The Mach Operating System project at 11 * Carnegie-Mellon University and Ralph Campbell. 12 * 13 * Redistribution and use in source and binary forms, with or without 14 * modification, are permitted provided that the following conditions 15 * are met: 16 * 1. Redistributions of source code must retain the above copyright 17 * notice, this list of conditions and the following disclaimer. 18 * 2. Redistributions in binary form must reproduce the above copyright 19 * notice, this list of conditions and the following disclaimer in the 20 * documentation and/or other materials provided with the distribution. 21 * 3. All advertising materials mentioning features or use of this software 22 * must display the following acknowledgement: 23 * This product includes software developed by the University of 24 * California, Berkeley and its contributors. 25 * 4. Neither the name of the University nor the names of its contributors 26 * may be used to endorse or promote products derived from this software 27 * without specific prior written permission. 28 * 29 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 30 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 31 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 32 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 33 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 34 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 35 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 36 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 37 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 38 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 39 * SUCH DAMAGE. 40 * 41 * @(#)machdep.c 8.3 (Berkeley) 1/12/94 42 */ 43 44 #include <sys/cdefs.h> /* RCS ID & Copyright macro defns */ 45 46 __KERNEL_RCSID(0, "$NetBSD: machdep.c,v 1.61 2002/03/05 16:13:57 simonb Exp $"); 47 48 /* from: Utah Hdr: machdep.c 1.63 91/04/24 */ 49 50 #include "fs_mfs.h" 51 #include "opt_ddb.h" 52 #include "opt_execfmt.h" 53 54 #include <sys/param.h> 55 #include <sys/systm.h> 56 #include <sys/signalvar.h> 57 #include <sys/kernel.h> 58 #include <sys/map.h> 59 #include <sys/proc.h> 60 #include <sys/buf.h> 61 #include <sys/reboot.h> 62 #include <sys/conf.h> 63 #include <sys/file.h> 64 #include <sys/malloc.h> 65 #include <sys/mbuf.h> 66 #include <sys/msgbuf.h> 67 #include <sys/ioctl.h> 68 #include <sys/device.h> 69 #include <sys/user.h> 70 #include <sys/exec.h> 71 #include <sys/mount.h> 72 #include <sys/syscallargs.h> 73 #include <sys/kcore.h> 74 75 #include <uvm/uvm_extern.h> 76 #include <sys/sysctl.h> 77 78 #include <ufs/mfs/mfs_extern.h> /* mfs_initminiroot() */ 79 80 #include <machine/cpu.h> 81 #include <machine/reg.h> 82 #include <machine/psl.h> 83 #include <machine/pte.h> 84 #include <machine/autoconf.h> 85 #include <machine/bootinfo.h> 86 #include <machine/apbus.h> 87 #include <machine/apcall.h> 88 89 #include <mips/cache.h> 90 #include <mips/locore.h> 91 92 #define _NEWSMIPS_BUS_DMA_PRIVATE 93 #include <machine/bus.h> 94 95 #ifdef DDB 96 #include <machine/db_machdep.h> 97 #include <ddb/db_access.h> 98 #include <ddb/db_extern.h> 99 #include <ddb/db_sym.h> 100 #endif 101 102 #include <machine/adrsmap.h> 103 #include <machine/machConst.h> 104 #include <machine/intr.h> 105 #include <newsmips/newsmips/clockreg.h> 106 #include <newsmips/newsmips/machid.h> 107 #include <dev/cons.h> 108 109 /* the following is used externally (sysctl_hw) */ 110 char machine[] = MACHINE; /* from <machine/param.h> */ 111 char machine_arch[] = MACHINE_ARCH; 112 char cpu_model[30]; 113 114 /* Our exported CPU info; we can have only one. */ 115 struct cpu_info cpu_info_store; 116 117 /* maps for VM objects */ 118 119 struct vm_map *exec_map = NULL; 120 struct vm_map *mb_map = NULL; 121 struct vm_map *phys_map = NULL; 122 123 char *bootinfo = NULL; /* pointer to bootinfo structure */ 124 int physmem; /* max supported memory, changes to actual */ 125 int systype; /* what type of NEWS we are */ 126 struct apbus_sysinfo *_sip = NULL; 127 128 phys_ram_seg_t mem_clusters[VM_PHYSSEG_MAX]; 129 int mem_cluster_cnt; 130 131 struct idrom idrom; 132 void (*enable_intr) __P((void)); 133 void (*disable_intr) __P((void)); 134 void (*readmicrotime) __P((struct timeval *tvp)); 135 136 /* System type dependent initializations. */ 137 extern void news3400_init __P((void)); 138 extern void news5000_init __P((void)); 139 140 static void (*hardware_intr) __P((u_int, u_int, u_int, u_int)); 141 u_int ssir; 142 143 /* 144 * Local functions. 145 */ 146 147 /* initialize bss, etc. from kernel start, before main() is called. */ 148 void mach_init __P((int, int, int, int)); 149 150 void prom_halt __P((int)) __attribute__((__noreturn__)); 151 void to_monitor __P((int)) __attribute__((__noreturn__)); 152 153 #ifdef DEBUG 154 /* stacktrace code violates prototypes to get callee's registers */ 155 extern void stacktrace __P((void)); /*XXX*/ 156 #endif 157 158 /* 159 * safepri is a safe priority for sleep to set for a spin-wait 160 * during autoconfiguration or after a panic. Used as an argument to splx(). 161 * XXX disables interrupt 5 to disable mips3 on-chip clock, which also 162 * disables mips1 FPU interrupts. 163 */ 164 int safepri = MIPS3_PSL_LOWIPL; /* XXX */ 165 166 extern struct user *proc0paddr; 167 extern u_long bootdev; 168 extern char edata[], end[]; 169 170 /* 171 * Do all the stuff that locore normally does before calling main(). 172 * Process arguments passed to us by the prom monitor. 173 * Return the first page address following the system. 174 */ 175 void 176 mach_init(x_boothowto, x_bootdev, x_bootname, x_maxmem) 177 int x_boothowto; 178 int x_bootdev; 179 int x_bootname; 180 int x_maxmem; 181 { 182 u_long first, last; 183 caddr_t kernend, v; 184 vsize_t size; 185 struct btinfo_magic *bi_magic; 186 struct btinfo_bootarg *bi_arg; 187 struct btinfo_systype *bi_systype; 188 #ifdef DDB 189 struct btinfo_symtab *bi_sym; 190 int nsym = 0; 191 char *ssym, *esym; 192 #endif 193 194 /* clear the BSS segment */ 195 bzero(edata, end - edata); 196 197 systype = NEWS3400; /* XXX compatibility */ 198 199 bootinfo = (void *)BOOTINFO_ADDR; /* XXX */ 200 bi_magic = lookup_bootinfo(BTINFO_MAGIC); 201 if (bi_magic && bi_magic->magic == BOOTINFO_MAGIC) { 202 bi_arg = lookup_bootinfo(BTINFO_BOOTARG); 203 if (bi_arg) { 204 x_boothowto = bi_arg->howto; 205 x_bootdev = bi_arg->bootdev; 206 x_maxmem = bi_arg->maxmem; 207 } 208 #ifdef DDB 209 bi_sym = lookup_bootinfo(BTINFO_SYMTAB); 210 if (bi_sym) { 211 nsym = bi_sym->nsym; 212 ssym = (void *)bi_sym->ssym; 213 esym = (void *)bi_sym->esym; 214 } 215 #endif 216 217 bi_systype = lookup_bootinfo(BTINFO_SYSTYPE); 218 if (bi_systype) 219 systype = bi_systype->type; 220 } 221 222 #ifdef news5000 223 if (systype == NEWS5000) { 224 int i; 225 char *bootspec = (char *)x_bootdev; 226 227 _sip = (void *)bi_arg->sip; 228 x_maxmem = _sip->apbsi_memsize; 229 x_maxmem -= 0x00100000; /* reserve 1MB for ROM monitor */ 230 if (strncmp(bootspec, "scsi", 4) == 0) { 231 x_bootdev = (5 << 28) | 0; /* magic, sd */ 232 bootspec += 4; 233 if (*bootspec != '(' /*)*/) 234 goto bootspec_end; 235 i = strtoul(bootspec + 1, &bootspec, 10); 236 x_bootdev |= (i << 24); /* bus */ 237 if (*bootspec != ',') 238 goto bootspec_end; 239 i = strtoul(bootspec + 1, &bootspec, 10); 240 x_bootdev |= (i / 10) << 20; /* controller */ 241 x_bootdev |= (i % 10) << 16; /* unit */ 242 if (*bootspec != ',') 243 goto bootspec_end; 244 i = strtoul(bootspec + 1, &bootspec, 10); 245 x_bootdev |= (i << 8); /* partition */ 246 } 247 bootspec_end: 248 consinit(); 249 } 250 #endif 251 252 /* 253 * Save parameters into kernel work area. 254 */ 255 *(int *)(MIPS_PHYS_TO_KSEG1(MACH_MAXMEMSIZE_ADDR)) = x_maxmem; 256 *(int *)(MIPS_PHYS_TO_KSEG1(MACH_BOOTDEV_ADDR)) = x_bootdev; 257 *(int *)(MIPS_PHYS_TO_KSEG1(MACH_BOOTSW_ADDR)) = x_boothowto; 258 259 kernend = (caddr_t)mips_round_page(end); 260 #ifdef DDB 261 if (nsym) 262 kernend = (caddr_t)mips_round_page(esym); 263 #endif 264 265 /* 266 * Set the VM page size. 267 */ 268 uvm_setpagesize(); 269 270 boothowto = x_boothowto; 271 bootdev = x_bootdev; 272 physmem = btoc(x_maxmem); 273 274 /* 275 * Now that we know how much memory we have, initialize the 276 * mem cluster array. 277 */ 278 mem_clusters[0].start = 0; /* XXX is this correct? */ 279 mem_clusters[0].size = ctob(physmem); 280 mem_cluster_cnt = 1; 281 282 /* 283 * Copy exception-dispatch code down to exception vector. 284 * Initialize locore-function vector. 285 * Clear out the I and D caches. 286 */ 287 mips_vector_init(); 288 289 /* 290 * We know the CPU type now. Initialize our DMA tags (might 291 * need this early). 292 */ 293 newsmips_bus_dma_init(); 294 295 #if 0 296 if (systype == NEWS5000) { 297 mips_L2CacheSize = 1024 * 1024; /* XXX to be safe */ 298 mips3_FlushCache(); 299 } 300 #endif 301 302 #ifdef DDB 303 if (nsym) 304 ddb_init(esym - ssym, ssym, esym); 305 #endif 306 307 #ifdef KADB 308 boothowto |= RB_KDB; 309 #endif 310 311 #ifdef MFS 312 /* 313 * Check to see if a mini-root was loaded into memory. It resides 314 * at the start of the next page just after the end of BSS. 315 */ 316 if (boothowto & RB_MINIROOT) 317 kernend += round_page(mfs_initminiroot(kernend)); 318 #endif 319 320 /* 321 * Load the rest of the available pages into the VM system. 322 */ 323 first = round_page(MIPS_KSEG0_TO_PHYS(kernend)); 324 last = mem_clusters[0].start + mem_clusters[0].size; 325 uvm_page_physload(atop(first), atop(last), atop(first), atop(last), 326 VM_FREELIST_DEFAULT); 327 328 /* 329 * Initialize error message buffer (at end of core). 330 */ 331 mips_init_msgbuf(); 332 333 /* 334 * Compute the size of system data structures. pmap_bootstrap() 335 * needs some of this information. 336 */ 337 size = (vsize_t)allocsys(NULL, NULL); 338 339 /* 340 * Initialize the virtual memory system. 341 */ 342 pmap_bootstrap(); 343 344 /* 345 * Allocate space for proc0's USPACE. 346 */ 347 v = (caddr_t)uvm_pageboot_alloc(USPACE); 348 proc0.p_addr = proc0paddr = (struct user *)v; 349 proc0.p_md.md_regs = (struct frame *)(v + USPACE) - 1; 350 curpcb = &proc0.p_addr->u_pcb; 351 curpcb->pcb_context[11] = MIPS_INT_MASK | MIPS_SR_INT_IE; /* SR */ 352 353 /* 354 * Allocate space for system data structures. These data structures 355 * are allocated here instead of cpu_startup() because physical 356 * memory is directly addressable. We don't have to map these into 357 * virtual address space. 358 */ 359 v = (caddr_t)uvm_pageboot_alloc(size); 360 if ((allocsys(v, NULL) - v) != size) 361 panic("mach_init: table size inconsistency"); 362 363 /* 364 * Determine what model of computer we are running on. 365 */ 366 switch (systype) { 367 #ifdef news3400 368 case NEWS3400: 369 news3400_init(); 370 strcpy(cpu_model, idrom.id_machine); 371 if (strcmp(cpu_model, "news3400") == 0 || 372 strcmp(cpu_model, "news3200") == 0 || 373 strcmp(cpu_model, "news3700") == 0) { 374 /* 375 * Set up interrupt handling and I/O addresses. 376 */ 377 hardware_intr = news3400_intr; 378 cpuspeed = 10; 379 } else { 380 printf("kernel not configured for machine %s\n", 381 cpu_model); 382 } 383 break; 384 #endif 385 386 #ifdef news5000 387 case NEWS5000: 388 news5000_init(); 389 strcpy(cpu_model, idrom.id_machine); 390 if (strcmp(cpu_model, "news5000") == 0 || 391 strcmp(cpu_model, "news5900") == 0) { 392 /* 393 * Set up interrupt handling and I/O addresses. 394 */ 395 hardware_intr = news5000_intr; 396 cpuspeed = 50; /* ??? XXX */ 397 } else { 398 printf("kernel not configured for machine %s\n", 399 cpu_model); 400 } 401 break; 402 #endif 403 404 default: 405 printf("kernel not configured for systype %d\n", systype); 406 break; 407 } 408 } 409 410 void 411 mips_machdep_cache_config(void) 412 { 413 /* All r4k news boxen have a 1MB L2 cache. */ 414 if (CPUISMIPS3) 415 mips_sdcache_size = 1024 * 1024; 416 } 417 418 /* 419 * cpu_startup: allocate memory for variable-sized tables, 420 * initialize cpu, and do autoconfiguration. 421 */ 422 void 423 cpu_startup() 424 { 425 register unsigned i; 426 int base, residual; 427 vaddr_t minaddr, maxaddr; 428 vsize_t size; 429 char pbuf[9]; 430 #ifdef DEBUG 431 extern int pmapdebug; 432 int opmapdebug = pmapdebug; 433 434 pmapdebug = 0; 435 #endif 436 437 /* 438 * Good {morning,afternoon,evening,night}. 439 */ 440 printf(version); 441 format_bytes(pbuf, sizeof(pbuf), ctob(physmem)); 442 printf("total memory = %s\n", pbuf); 443 444 /* 445 * Allocate virtual address space for file I/O buffers. 446 * Note they are different than the array of headers, 'buf', 447 * and usually occupy more virtual memory than physical. 448 */ 449 size = MAXBSIZE * nbuf; 450 if (uvm_map(kernel_map, (vaddr_t *)&buffers, round_page(size), 451 NULL, UVM_UNKNOWN_OFFSET, 0, 452 UVM_MAPFLAG(UVM_PROT_NONE, UVM_PROT_NONE, UVM_INH_NONE, 453 UVM_ADV_NORMAL, 0)) != 0) 454 panic("startup: cannot allocate VM for buffers"); 455 minaddr = (vaddr_t)buffers; 456 base = bufpages / nbuf; 457 residual = bufpages % nbuf; 458 for (i = 0; i < nbuf; i++) { 459 vsize_t curbufsize; 460 vaddr_t curbuf; 461 struct vm_page *pg; 462 463 /* 464 * Each buffer has MAXBSIZE bytes of VM space allocated. Of 465 * that MAXBSIZE space, we allocate and map (base+1) pages 466 * for the first "residual" buffers, and then we allocate 467 * "base" pages for the rest. 468 */ 469 curbuf = (vaddr_t) buffers + (i * MAXBSIZE); 470 curbufsize = NBPG * ((i < residual) ? (base+1) : base); 471 472 while (curbufsize) { 473 pg = uvm_pagealloc(NULL, 0, NULL, 0); 474 if (pg == NULL) 475 panic("cpu_startup: not enough memory for " 476 "buffer cache"); 477 pmap_kenter_pa(curbuf, VM_PAGE_TO_PHYS(pg), 478 VM_PROT_READ|VM_PROT_WRITE); 479 curbuf += PAGE_SIZE; 480 curbufsize -= PAGE_SIZE; 481 } 482 } 483 pmap_update(pmap_kernel()); 484 485 /* 486 * Allocate a submap for exec arguments. This map effectively 487 * limits the number of processes exec'ing at any time. 488 */ 489 exec_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 490 16 * NCARGS, VM_MAP_PAGEABLE, FALSE, NULL); 491 /* 492 * Allocate a submap for physio 493 */ 494 phys_map = uvm_km_suballoc(kernel_map, &minaddr, &maxaddr, 495 VM_PHYS_SIZE, 0, FALSE, NULL); 496 497 /* 498 * No need to allocate an mbuf cluster submap. Mbuf clusters 499 * are allocated via the pool allocator, and we use KSEG to 500 * map those pages. 501 */ 502 503 #ifdef DEBUG 504 pmapdebug = opmapdebug; 505 #endif 506 format_bytes(pbuf, sizeof(pbuf), ptoa(uvmexp.free)); 507 printf("avail memory = %s\n", pbuf); 508 format_bytes(pbuf, sizeof(pbuf), bufpages * NBPG); 509 printf("using %d buffers containing %s of memory\n", nbuf, pbuf); 510 511 /* 512 * Set up buffers, so they can be used to read disk labels. 513 */ 514 bufinit(); 515 } 516 517 518 /* 519 * machine dependent system variables. 520 */ 521 int 522 cpu_sysctl(name, namelen, oldp, oldlenp, newp, newlen, p) 523 int *name; 524 u_int namelen; 525 void *oldp; 526 size_t *oldlenp; 527 void *newp; 528 size_t newlen; 529 struct proc *p; 530 { 531 /* all sysctl names at this level are terminal */ 532 if (namelen != 1) 533 return (ENOTDIR); /* overloaded */ 534 535 switch (name[0]) { 536 537 default: 538 return (EOPNOTSUPP); 539 } 540 /* NOTREACHED */ 541 } 542 543 /* 544 * lookup_bootinfo: 545 * Look up information in bootinfo of boot loader. 546 */ 547 void * 548 lookup_bootinfo(type) 549 int type; 550 { 551 struct btinfo_common *bt; 552 char *help = bootinfo; 553 554 /* Check for a bootinfo record first. */ 555 if (help == NULL) 556 return (NULL); 557 558 do { 559 bt = (struct btinfo_common *)help; 560 if (bt->type == type) 561 return ((void *)help); 562 help += bt->next; 563 } while (bt->next != 0 && 564 (size_t)help < (size_t)bootinfo + BOOTINFO_SIZE); 565 566 return (NULL); 567 } 568 569 /* 570 * call PROM to halt or reboot. 571 */ 572 void 573 prom_halt(howto) 574 int howto; 575 576 { 577 #ifdef news5000 578 if (systype == NEWS5000) 579 apcall_exit(howto); 580 #endif 581 #ifdef news3400 582 if (systype == NEWS3400) 583 to_monitor(howto); 584 #endif 585 for (;;); 586 } 587 588 int waittime = -1; 589 590 void 591 cpu_reboot(howto, bootstr) 592 volatile int howto; 593 char *bootstr; 594 { 595 596 /* take a snap shot before clobbering any registers */ 597 if (curproc) 598 savectx((struct user *)curpcb); 599 600 #ifdef DEBUG 601 if (panicstr) 602 stacktrace(); 603 #endif 604 605 /* If system is cold, just halt. */ 606 if (cold) { 607 howto |= RB_HALT; 608 goto haltsys; 609 } 610 611 /* If "always halt" was specified as a boot flag, obey. */ 612 if ((boothowto & RB_HALT) != 0) 613 howto |= RB_HALT; 614 615 boothowto = howto; 616 if ((howto & RB_NOSYNC) == 0 && waittime < 0) { 617 /* 618 * Synchronize the disks.... 619 */ 620 waittime = 0; 621 vfs_shutdown(); 622 623 /* 624 * If we've been adjusting the clock, the todr 625 * will be out of synch; adjust it now. 626 */ 627 resettodr(); 628 } 629 630 /* Disable interrupts. */ 631 disable_intr(); 632 633 splhigh(); 634 635 /* If rebooting and a dump is requested do it. */ 636 #if 0 637 if ((howto & (RB_DUMP | RB_HALT)) == RB_DUMP) 638 #else 639 if (howto & RB_DUMP) 640 #endif 641 dumpsys(); 642 643 haltsys: 644 645 /* run any shutdown hooks */ 646 doshutdownhooks(); 647 648 if ((howto & RB_POWERDOWN) == RB_POWERDOWN) 649 prom_halt(0x80); /* rom monitor RB_PWOFF */ 650 651 /* Finally, halt/reboot the system. */ 652 printf("%s\n\n", howto & RB_HALT ? "halted." : "rebooting..."); 653 prom_halt(howto & RB_HALT); 654 /*NOTREACHED*/ 655 } 656 657 /* 658 * Return the best possible estimate of the time in the timeval 659 * to which tvp points. Unfortunately, we can't read the hardware registers. 660 * We guarantee that the time will be greater than the value obtained by a 661 * previous call. 662 */ 663 void 664 microtime(tvp) 665 register struct timeval *tvp; 666 { 667 int s = splclock(); 668 static struct timeval lasttime; 669 670 if (readmicrotime) 671 readmicrotime(tvp); 672 else 673 *tvp = time; 674 675 if (tvp->tv_sec == lasttime.tv_sec && 676 tvp->tv_usec <= lasttime.tv_usec && 677 (tvp->tv_usec = lasttime.tv_usec + 1) >= 1000000) { 678 tvp->tv_sec++; 679 tvp->tv_usec -= 1000000; 680 } 681 lasttime = *tvp; 682 splx(s); 683 } 684 685 void 686 delay(n) 687 int n; 688 { 689 DELAY(n); 690 } 691 692 #include "zsc.h" 693 694 int zssoft __P((void)); 695 696 void 697 cpu_intr(status, cause, pc, ipending) 698 u_int32_t status; 699 u_int32_t cause; 700 u_int32_t pc; 701 u_int32_t ipending; 702 { 703 uvmexp.intrs++; 704 705 /* device interrupts */ 706 (*hardware_intr)(status, cause, pc, ipending); 707 708 /* software simulated interrupt */ 709 if ((ipending & MIPS_SOFT_INT_MASK_1) || 710 (ssir && (status & MIPS_SOFT_INT_MASK_1))) { 711 712 #define DO_SIR(bit, fn) \ 713 do { \ 714 if (n & (bit)) { \ 715 uvmexp.softs++; \ 716 fn; \ 717 } \ 718 } while (0) 719 720 unsigned n; 721 n = ssir; ssir = 0; 722 _clrsoftintr(MIPS_SOFT_INT_MASK_1); 723 724 #if NZSC > 0 725 DO_SIR(SIR_SERIAL, zssoft()); 726 #endif 727 DO_SIR(SIR_NET, netintr()); 728 #undef DO_SIR 729 } 730 731 /* 'softclock' interrupt */ 732 if (ipending & MIPS_SOFT_INT_MASK_0) { 733 _clrsoftintr(MIPS_SOFT_INT_MASK_0); 734 uvmexp.softs++; 735 intrcnt[SOFTCLOCK_INTR]++; 736 softclock(NULL); 737 } 738 } 739