PRIVATE void estimate_cpu_freq(void) { u64_t tsc_delta; u64_t cpu_freq; irq_hook_t calib_cpu; /* set the probe, we use the legacy timer, IRQ 0 */ put_irq_handler(&calib_cpu, CLOCK_IRQ, calib_cpu_handler); /* just in case we are in an SMP single cpu fallback mode */ BKL_UNLOCK(); /* set the PIC timer to get some time */ intr_enable(); /* loop for some time to get a sample */ while(probe_ticks < PROBE_TICKS) { intr_enable(); } intr_disable(); /* just in case we are in an SMP single cpu fallback mode */ BKL_LOCK(); /* remove the probe */ rm_irq_handler(&calib_cpu); tsc_delta = sub64(tsc1, tsc0); cpu_freq = mul64(div64u64(tsc_delta, PROBE_TICKS - 1), make64(system_hz, 0)); cpu_set_freq(cpuid, cpu_freq); cpu_info[cpuid].freq = div64u(cpu_freq, 1000000); BOOT_VERBOSE(cpu_print_freq(cpuid)); }
static void testdiv0(void) { int funcidx; assert(cmp64u(j, 0) == 0); /* loop through the 5 different division functions */ for (funcidx = 0; funcidx < 5; funcidx++) { expect_SIGFPE = 1; if (setjmp(jmpbuf_SIGFPE) == 0) { /* divide by zero using various functions */ switch (funcidx) { case 0: div64(i, j); ERR; break; case 1: div64u64(i, ex64lo(j)); ERR; break; case 2: div64u(i, ex64lo(j)); ERR; break; case 3: rem64(i, j); ERR; break; case 4: rem64u(i, ex64lo(j)); ERR; break; default: assert(0); ERR; break; } /* if we reach this point there was no signal and an * error has been recorded */ expect_SIGFPE = 0; } else { /* a signal has been received and expect_SIGFPE has * been reset; all is ok now */ assert(!expect_SIGFPE); } } }
static void testdiv(void) { u64_t q, r; #if TIMED struct timeval tvstart, tvend; printf("i=0x%.8x%.8x; j=0x%.8x%.8x\n", ex64hi(i), ex64lo(i), ex64hi(j), ex64lo(j)); fflush(stdout); if (gettimeofday(&tvstart, NULL) < 0) ERR; #endif /* division by zero has a separate test */ if (cmp64u(j, 0) == 0) { testdiv0(); return; } /* perform division, store q in k to make ERR more informative */ q = div64(i, j); r = rem64(i, j); k = q; #if TIMED if (gettimeofday(&tvend, NULL) < 0) ERR; tvend.tv_sec -= tvstart.tv_sec; tvend.tv_usec -= tvstart.tv_usec; if (tvend.tv_usec < 0) { tvend.tv_sec -= 1; tvend.tv_usec += 1000000; } printf("q=0x%.8x%.8x; r=0x%.8x%.8x; time=%d.%.6d\n", ex64hi(q), ex64lo(q), ex64hi(r), ex64lo(r), tvend.tv_sec, tvend.tv_usec); fflush(stdout); #endif /* compare to 64/32-bit division if possible */ if (!ex64hi(j)) { if (cmp64(q, div64u64(i, ex64lo(j))) != 0) ERR; if (!ex64hi(q)) { if (cmp64u(q, div64u(i, ex64lo(j))) != 0) ERR; } if (cmp64u(r, rem64u(i, ex64lo(j))) != 0) ERR; /* compare to 32-bit division if possible */ if (!ex64hi(i)) { if (cmp64u(q, ex64lo(i) / ex64lo(j)) != 0) ERR; if (cmp64u(r, ex64lo(i) % ex64lo(j)) != 0) ERR; } } /* check results using i = q j + r and r < j */ if (cmp64(i, add64(mul64(q, j), r)) != 0) ERR; if (cmp64(r, j) >= 0) ERR; }