static int acpi_timer_test(void) { uint32_t last, this; int min, max, max2, n, delta; register_t s; min = INT32_MAX; max = max2 = 0; /* Test the timer with interrupts disabled to get accurate results. */ #if defined(__i386__) s = read_eflags(); #elif defined(__x86_64__) s = read_rflags(); #else #error "no read_eflags" #endif cpu_disable_intr(); AcpiGetTimer(&last); for (n = 0; n < 2000; n++) { AcpiGetTimer(&this); delta = acpi_TimerDelta(this, last); if (delta > max) { max2 = max; max = delta; } else if (delta > max2) { max2 = delta; } if (delta < min) min = delta; last = this; } #if defined(__i386__) write_eflags(s); #elif defined(__x86_64__) write_rflags(s); #else #error "no read_eflags" #endif delta = max2 - min; if ((max - min > 8 || delta > 3) && vmm_guest == VMM_GUEST_NONE) n = 0; else if (min < 0 || max == 0 || max2 == 0) n = 0; else n = 1; if (bootverbose) { kprintf("ACPI timer looks %s min = %d, max = %d, width = %d\n", n ? "GOOD" : "BAD ", min, max, max - min); } return (n); }
static sysclock_t acpi_timer_get_timecount(void) { sysclock_t counter; AcpiGetTimer(&counter); return (counter + acpi_cputimer.base); }
u_int acpitimer_read_fast(struct timecounter *tc) { uint32_t t; (void)AcpiGetTimer(&t); return t; }
/* * Some chipsets (PIIX4 variants) do not latch correctly; * there is a chance that a transition is hit. */ u_int acpitimer_read_safe(struct timecounter *tc) { uint32_t t1, t2, t3; (void)AcpiGetTimer(&t2); (void)AcpiGetTimer(&t3); do { t1 = t2; t2 = t3; (void)AcpiGetTimer(&t3); } while ((t1 > t2) || (t2 > t3)); return t2; }
static int acpitimer_test(void) { uint32_t last, this, delta; int minl, maxl, n; minl = 10000000; maxl = 0; acpi_md_OsDisableInterrupt(); (void)AcpiGetTimer(&last); for (n = 0; n < N; n++) { (void)AcpiGetTimer(&this); delta = acpitimer_delta(this, last); if (delta > maxl) maxl = delta; else if (delta < minl) minl = delta; last = this; } acpi_md_OsEnableInterrupt(); if (maxl - minl > 2 ) n = 0; else if (minl < 0 || maxl == 0) n = 0; else n = 1; return n; }
/* * Fetch current time value from reliable hardware. * * The cputimer interface requires a 32 bit return value. If the ACPI timer * is only 24 bits then we have to keep track of the upper 8 bits on our * own. * * XXX we could probably get away with using a per-cpu field for this and * just use interrupt disablement instead of clock_lock. */ static sysclock_t acpi_timer_get_timecount24(void) { sysclock_t counter; clock_lock(); AcpiGetTimer(&counter); if (counter < acpi_last_counter) acpi_cputimer.base += 0x01000000; acpi_last_counter = counter; counter += acpi_cputimer.base; clock_unlock(); return (counter); }
/* * Fetch current time value from hardware that may not correctly * latch the counter. We need to read until we have three monotonic * samples and then use the middle one, otherwise we are not protected * against the fact that the bits can be wrong in two directions. If * we only cared about monosity, two reads would be enough. */ static sysclock_t acpi_timer_get_timecount_safe(void) { u_int u1, u2, u3; if (acpi_timer_resolution != 32) clock_lock(); AcpiGetTimer(&u2); AcpiGetTimer(&u3); do { u1 = u2; u2 = u3; AcpiGetTimer(&u3); } while (u1 > u2 || u2 > u3); if (acpi_timer_resolution != 32) { if (u2 < acpi_last_counter) acpi_cputimer.base += 0x01000000; acpi_last_counter = u2; clock_unlock(); } return (u2 + acpi_cputimer.base); }