static int acpi_timer_test() { uint32_t last, this; int min, max, n, delta; register_t s; min = 10000000; max = 0; /* Test the timer with interrupts disabled to get accurate results. */ s = intr_disable(); last = acpi_timer_read(); for (n = 0; n < N; n++) { this = acpi_timer_read(); delta = acpi_TimerDelta(this, last); if (delta > max) max = delta; else if (delta < min) min = delta; last = this; } intr_restore(s); if (max - min > 2) n = 0; else if (min < 0 || max == 0) n = 0; else n = 1; if (bootverbose) printf(" %d/%d", n, max-min); return (n); }
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 int acpi_timer_test(void) { uint32_t last, this; int min, max, n, delta; register_t s; min = 10000000; max = 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(); last = acpi_timer_read(); for (n = 0; n < 2000; n++) { this = acpi_timer_read(); delta = acpi_TimerDelta(this, last); if (delta > max) max = delta; else 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 if (max - min > 2) n = 0; else if (min < 0 || max == 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 int acpi_timer_test() { uint32_t last, this; int delta, max, max2, min, n; register_t s; min = INT32_MAX; max = max2 = 0; /* Test the timer with interrupts disabled to get accurate results. */ s = intr_disable(); last = acpi_timer_read(); for (n = 0; n < N; n++) { this = acpi_timer_read(); 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; } intr_restore(s); delta = max2 - min; if ((max - min > 8 || delta > 3) && vm_guest == VM_GUEST_NO) n = 0; else if (min < 0 || max == 0 || max2 == 0) n = 0; else n = 1; if (bootverbose) printf(" %d/%d", n, delta); return (n); }
/* * Idle the CPU in the lowest state possible. This function is called with * interrupts disabled. Note that once it re-enables interrupts, a task * switch can occur so do not access shared data (i.e. the softc) after * interrupts are re-enabled. */ static void acpi_cpu_idle() { struct acpi_cpu_softc *sc; struct acpi_cx *cx_next; uint32_t start_time, end_time; int bm_active, cx_next_idx, i; /* If disabled, return immediately. */ if (cpu_disable_idle) { ACPI_ENABLE_IRQS(); return; } /* * Look up our CPU id to get our softc. If it's NULL, we'll use C1 * since there is no ACPI processor object for this CPU. This occurs * for logical CPUs in the HTT case. */ sc = cpu_softc[PCPU_GET(cpuid)]; if (sc == NULL) { acpi_cpu_c1(); return; } /* Find the lowest state that has small enough latency. */ cx_next_idx = 0; for (i = sc->cpu_cx_lowest; i >= 0; i--) { if (sc->cpu_cx_states[i].trans_lat * 3 <= sc->cpu_prev_sleep) { cx_next_idx = i; break; } } /* * Check for bus master activity. If there was activity, clear * the bit and use the lowest non-C3 state. Note that the USB * driver polling for new devices keeps this bit set all the * time if USB is loaded. */ if ((cpu_quirks & CPU_QUIRK_NO_BM_CTRL) == 0) { AcpiReadBitRegister(ACPI_BITREG_BUS_MASTER_STATUS, &bm_active); if (bm_active != 0) { AcpiWriteBitRegister(ACPI_BITREG_BUS_MASTER_STATUS, 1); cx_next_idx = min(cx_next_idx, sc->cpu_non_c3); } } /* Select the next state and update statistics. */ cx_next = &sc->cpu_cx_states[cx_next_idx]; sc->cpu_cx_stats[cx_next_idx]++; KASSERT(cx_next->type != ACPI_STATE_C0, ("acpi_cpu_idle: C0 sleep")); /* * Execute HLT (or equivalent) and wait for an interrupt. We can't * calculate the time spent in C1 since the place we wake up is an * ISR. Assume we slept half of quantum and return. */ if (cx_next->type == ACPI_STATE_C1) { sc->cpu_prev_sleep = (sc->cpu_prev_sleep * 3 + 500000 / hz) / 4; acpi_cpu_c1(); return; } /* * For C3, disable bus master arbitration and enable bus master wake * if BM control is available, otherwise flush the CPU cache. */ if (cx_next->type == ACPI_STATE_C3) { if ((cpu_quirks & CPU_QUIRK_NO_BM_CTRL) == 0) { AcpiWriteBitRegister(ACPI_BITREG_ARB_DISABLE, 1); AcpiWriteBitRegister(ACPI_BITREG_BUS_MASTER_RLD, 1); } else ACPI_FLUSH_CPU_CACHE(); } /* * Read from P_LVLx to enter C2(+), checking time spent asleep. * Use the ACPI timer for measuring sleep time. Since we need to * get the time very close to the CPU start/stop clock logic, this * is the only reliable time source. */ AcpiRead(&start_time, &AcpiGbl_FADT.XPmTimerBlock); CPU_GET_REG(cx_next->p_lvlx, 1); /* * Read the end time twice. Since it may take an arbitrary time * to enter the idle state, the first read may be executed before * the processor has stopped. Doing it again provides enough * margin that we are certain to have a correct value. */ AcpiRead(&end_time, &AcpiGbl_FADT.XPmTimerBlock); AcpiRead(&end_time, &AcpiGbl_FADT.XPmTimerBlock); /* Enable bus master arbitration and disable bus master wakeup. */ if (cx_next->type == ACPI_STATE_C3 && (cpu_quirks & CPU_QUIRK_NO_BM_CTRL) == 0) { AcpiWriteBitRegister(ACPI_BITREG_ARB_DISABLE, 0); AcpiWriteBitRegister(ACPI_BITREG_BUS_MASTER_RLD, 0); } ACPI_ENABLE_IRQS(); /* Find the actual time asleep in microseconds. */ end_time = acpi_TimerDelta(end_time, start_time); sc->cpu_prev_sleep = (sc->cpu_prev_sleep * 3 + PM_USEC(end_time)) / 4; }