Beispiel #1
0
/**
 * Detects the local APIC reference bus clock. The only sure-fire way to do
 * this is to depend on some other absolute timing source. This function uses
 * the CPU's cycle counter and the previously detected CPU clock frequency.
 *
 * NOTE: This assumes that the CPU's clock frequency has already been detected.
 *       (i.e., cpu_info[cpu_id()].arch.tsc_khz has been initialized.
 */
unsigned int __init
lapic_calibrate_timer(void)
{
	const unsigned int tick_count = 100000000;
	cycles_t tsc_start, tsc_now;
	uint32_t apic_start, apic_now;
	unsigned int apic_Hz;

	/* Start the APIC counter running for calibration */
	lapic_set_timer_count(4000000000);

	apic_start = apic_read(APIC_TMCCT);
	tsc_start  = get_cycles_sync();

	/* Spin until enough ticks for a meaningful result have elapsed */
	do {
		apic_now = apic_read(APIC_TMCCT);
		tsc_now  = get_cycles_sync();
	} while ( ((tsc_now    - tsc_start) < tick_count) &&
	          ((apic_start - apic_now)  < tick_count) );

	apic_Hz = (apic_start - apic_now) * 1000L *
	          cpu_info[this_cpu].arch.tsc_khz / (tsc_now - tsc_start);

	lapic_stop_timer();

	return (apic_Hz / 1000);
}
Beispiel #2
0
PUBLIC int init_local_timer(unsigned freq)
{
#ifdef USE_APIC
	/* if we know the address, lapic is enabled and we should use it */
	if (lapic_addr) {
		unsigned cpu = cpuid;
		tsc_per_ms[cpu] = div64u(cpu_get_freq(cpu), 1000);
		lapic_set_timer_one_shot(1000000/system_hz);
	} else
	{
		BOOT_VERBOSE(printf("Initiating legacy i8253 timer\n"));
#else
	{
#endif
		init_8253A_timer(freq);
		estimate_cpu_freq();
		/* always only 1 cpu in the system */
		tsc_per_ms[0] = div64u(cpu_get_freq(0), 1000);
	}

	return 0;
}

PUBLIC void stop_local_timer(void)
{
#ifdef USE_APIC
	if (lapic_addr) {
		lapic_stop_timer();
		apic_eoi();
	} else
#endif
	{
		stop_8253A_timer();
	}
}

PUBLIC void restart_local_timer(void)
{
#ifdef USE_APIC
	if (lapic_addr) {
		lapic_restart_timer();
	}
#endif
}

PUBLIC int register_local_timer_handler(const irq_handler_t handler)
{
#ifdef USE_APIC
	if (lapic_addr) {
		/* Using APIC, it is configured in apic_idt_init() */
		BOOT_VERBOSE(printf("Using LAPIC timer as tick source\n"));
	} else
#endif
	{
		/* Using PIC, Initialize the CLOCK's interrupt hook. */
		pic_timer_hook.proc_nr_e = NONE;
		pic_timer_hook.irq = CLOCK_IRQ;

		put_irq_handler(&pic_timer_hook, CLOCK_IRQ, handler);
	}

	return 0;
}

PUBLIC void cycles_accounting_init(void)
{
#ifdef CONFIG_SMP
	unsigned cpu = cpuid;
#endif

	read_tsc_64(get_cpu_var_ptr(cpu, tsc_ctr_switch));

	make_zero64(get_cpu_var(cpu, cpu_last_tsc));
	make_zero64(get_cpu_var(cpu, cpu_last_idle));
}