Beispiel #1
0
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;
	}
}