static void dovmstat(unsigned int interval, int reps) { struct vmtotal total; time_t uptime, halfuptime; struct devinfo *tmp_dinfo; size_t size; int ncpus, maxid; u_long cpumask; int rate_adj; uptime = getuptime() / 1000000000LL; halfuptime = uptime / 2; rate_adj = 1; ncpus = 1; maxid = 0; /* * If the user stops the program (control-Z) and then resumes it, * print out the header again. */ (void)signal(SIGCONT, needhdr); /* * If our standard output is a tty, then install a SIGWINCH handler * and set wresized so that our first iteration through the main * vmstat loop will peek at the terminal's current rows to find out * how many lines can fit in a screenful of output. */ if (isatty(fileno(stdout)) != 0) { wresized = 1; (void)signal(SIGWINCH, needresize); } else { wresized = 0; winlines = VMSTAT_DEFAULT_LINES; } if (kd != NULL) { if (namelist[X_STATHZ].n_type != 0 && namelist[X_STATHZ].n_value != 0) kread(X_STATHZ, &hz, sizeof(hz)); if (!hz) kread(X_HZ, &hz, sizeof(hz)); } else { struct clockinfo clockrate; size = sizeof(clockrate); mysysctl("kern.clockrate", &clockrate, &size, NULL, 0); if (size != sizeof(clockrate)) errx(1, "clockrate size mismatch"); hz = clockrate.hz; } if (Pflag) { ncpus = getcpuinfo(&cpumask, &maxid); size_cp_times = sizeof(long) * (maxid + 1) * CPUSTATES; cur_cp_times = calloc(1, size_cp_times); last_cp_times = calloc(1, size_cp_times); } for (hdrcnt = 1;;) { if (!--hdrcnt) printhdr(maxid, cpumask); if (kd != NULL) { if (kvm_getcptime(kd, cur.cp_time) < 0) errx(1, "kvm_getcptime: %s", kvm_geterr(kd)); } else { size = sizeof(cur.cp_time); mysysctl("kern.cp_time", &cur.cp_time, &size, NULL, 0); if (size != sizeof(cur.cp_time)) errx(1, "cp_time size mismatch"); } if (Pflag) { size = size_cp_times; mysysctl("kern.cp_times", cur_cp_times, &size, NULL, 0); if (size != size_cp_times) errx(1, "cp_times mismatch"); } tmp_dinfo = last.dinfo; last.dinfo = cur.dinfo; cur.dinfo = tmp_dinfo; last.snap_time = cur.snap_time; /* * Here what we want to do is refresh our device stats. * getdevs() returns 1 when the device list has changed. * If the device list has changed, we want to go through * the selection process again, in case a device that we * were previously displaying has gone away. */ switch (devstat_getdevs(NULL, &cur)) { case -1: errx(1, "%s", devstat_errbuf); break; case 1: { int retval; num_devices = cur.dinfo->numdevs; generation = cur.dinfo->generation; retval = devstat_selectdevs(&dev_select, &num_selected, &num_selections, &select_generation, generation, cur.dinfo->devices, num_devices, matches, num_matches, specified_devices, num_devices_specified, select_mode, maxshowdevs, 0); switch (retval) { case -1: errx(1, "%s", devstat_errbuf); break; case 1: printhdr(maxid, cpumask); break; default: break; } } default: break; } fill_vmmeter(&sum); fill_vmtotal(&total); (void)printf("%1d %1d %1d", total.t_rq - 1, total.t_dw + total.t_pw, total.t_sw); #define vmstat_pgtok(a) ((a) * (sum.v_page_size >> 10)) #define rate(x) (((x) * rate_adj + halfuptime) / uptime) /* round */ if (hflag) { printf(""); prthuman(total.t_avm * (u_int64_t)sum.v_page_size, 5); printf(" "); prthuman(total.t_free * (u_int64_t)sum.v_page_size, 5); printf(" "); (void)printf("%5lu ", (unsigned long)rate(sum.v_vm_faults - osum.v_vm_faults)); } else { printf(" %7d", vmstat_pgtok(total.t_avm)); printf(" %7d ", vmstat_pgtok(total.t_free)); (void)printf("%4lu ", (unsigned long)rate(sum.v_vm_faults - osum.v_vm_faults)); } (void)printf("%3lu ", (unsigned long)rate(sum.v_reactivated - osum.v_reactivated)); (void)printf("%3lu ", (unsigned long)rate(sum.v_swapin + sum.v_vnodein - (osum.v_swapin + osum.v_vnodein))); (void)printf("%3lu ", (unsigned long)rate(sum.v_swapout + sum.v_vnodeout - (osum.v_swapout + osum.v_vnodeout))); (void)printf("%5lu ", (unsigned long)rate(sum.v_tfree - osum.v_tfree)); (void)printf("%4lu ", (unsigned long)rate(sum.v_pdpages - osum.v_pdpages)); devstats(); (void)printf("%4lu %5lu %5lu", (unsigned long)rate(sum.v_intr - osum.v_intr), (unsigned long)rate(sum.v_syscall - osum.v_syscall), (unsigned long)rate(sum.v_swtch - osum.v_swtch)); if (Pflag) pcpustats(ncpus, cpumask, maxid); else cpustats(); (void)printf("\n"); (void)fflush(stdout); if (reps >= 0 && --reps <= 0) break; osum = sum; uptime = interval; rate_adj = 1000; /* * We round upward to avoid losing low-frequency events * (i.e., >= 1 per interval but < 1 per millisecond). */ if (interval != 1) halfuptime = (uptime + 1) / 2; else halfuptime = 0; (void)usleep(interval * 1000); } }
/* * locore.s code calls bootstrap() just before calling main(), after double * mapping the kernel to high memory and setting up the trap base register. * We must finish mapping the kernel properly and glean any bootstrap info. */ void bootstrap(void) { extern uint8_t u0[]; extern struct consdev consdev_prom; #if NKSYMS || defined(DDB) || defined(MODULAR) struct btinfo_symtab *bi_sym; #else extern int end[]; #endif struct btinfo_boothowto *bi_howto; cn_tab = &consdev_prom; prom_init(); /* Find the number of CPUs as early as possible */ sparc_ncpus = find_cpus(); uvm_lwp_setuarea(&lwp0, (vaddr_t)u0); cpuinfo.master = 1; getcpuinfo(&cpuinfo, 0); curlwp = &lwp0; #if defined(SUN4M) || defined(SUN4D) /* Switch to sparc v8 multiply/divide functions on v8 machines */ if (cpu_arch == 8) { extern void sparc_v8_muldiv(void); sparc_v8_muldiv(); } #endif /* SUN4M || SUN4D */ #if !NKSYMS && !defined(DDB) && !defined(MODULAR) /* * We want to reuse the memory where the symbols were stored * by the loader. Relocate the bootinfo array which is loaded * above the symbols (we assume) to the start of BSS. Then * adjust kernel_top accordingly. */ bootinfo_relocate((void *)ALIGN((u_int)end)); #endif pmap_bootstrap(cpuinfo.mmu_ncontext, cpuinfo.mmu_nregion, cpuinfo.mmu_nsegment); #if !defined(MSGBUFSIZE) || MSGBUFSIZE == 8192 /* * Now that the kernel map has been set up, we can enable * the message buffer at the first physical page in the * memory bank where we were loaded. There are 8192 * bytes available for the buffer at this location (see the * comment in locore.s at the top of the .text segment). */ initmsgbuf((void *)KERNBASE, 8192); #endif #if defined(SUN4M) /* * sun4m bootstrap is complex and is totally different for "normal" 4m * and for microSPARC-IIep - so it's split into separate functions. */ if (CPU_ISSUN4M) { #if !defined(MSIIEP) bootstrap4m(); #else bootstrapIIep(); #endif } #endif /* SUN4M */ #if defined(SUN4) || defined(SUN4C) if (CPU_ISSUN4 || CPU_ISSUN4C) { /* Map Interrupt Enable Register */ pmap_kenter_pa(INTRREG_VA, INT_ENABLE_REG_PHYSADR | PMAP_NC | PMAP_OBIO, VM_PROT_READ | VM_PROT_WRITE, 0); pmap_update(pmap_kernel()); /* Disable all interrupts */ *((unsigned char *)INTRREG_VA) = 0; } #endif /* SUN4 || SUN4C */ #if NKSYMS || defined(DDB) || defined(MODULAR) if ((bi_sym = lookup_bootinfo(BTINFO_SYMTAB)) != NULL) { if (bi_sym->ssym < KERNBASE) { /* Assume low-loading boot loader */ bi_sym->ssym += KERNBASE; bi_sym->esym += KERNBASE; } ksyms_addsyms_elf(bi_sym->nsym, (void*)bi_sym->ssym, (void*)bi_sym->esym); } #endif if ((bi_howto = lookup_bootinfo(BTINFO_BOOTHOWTO)) != NULL) { boothowto = bi_howto->boothowto; } }