delay.c revision 263008
1263008Sroyger/*- 2263008Sroyger * Copyright (c) 1990 The Regents of the University of California. 3263008Sroyger * Copyright (c) 2010 Alexander Motin <mav@FreeBSD.org> 4263008Sroyger * All rights reserved. 5263008Sroyger * 6263008Sroyger * This code is derived from software contributed to Berkeley by 7263008Sroyger * William Jolitz and Don Ahn. 8263008Sroyger * 9263008Sroyger * Redistribution and use in source and binary forms, with or without 10263008Sroyger * modification, are permitted provided that the following conditions 11263008Sroyger * are met: 12263008Sroyger * 1. Redistributions of source code must retain the above copyright 13263008Sroyger * notice, this list of conditions and the following disclaimer. 14263008Sroyger * 2. Redistributions in binary form must reproduce the above copyright 15263008Sroyger * notice, this list of conditions and the following disclaimer in the 16263008Sroyger * documentation and/or other materials provided with the distribution. 17263008Sroyger * 4. Neither the name of the University nor the names of its contributors 18263008Sroyger * may be used to endorse or promote products derived from this software 19263008Sroyger * without specific prior written permission. 20263008Sroyger * 21263008Sroyger * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 22263008Sroyger * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 23263008Sroyger * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 24263008Sroyger * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 25263008Sroyger * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 26263008Sroyger * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 27263008Sroyger * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 28263008Sroyger * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 29263008Sroyger * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 30263008Sroyger * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 31263008Sroyger * SUCH DAMAGE. 32263008Sroyger * 33263008Sroyger * from: @(#)clock.c 7.2 (Berkeley) 5/12/91 34263008Sroyger */ 35263008Sroyger 36263008Sroyger#include <sys/cdefs.h> 37263008Sroyger__FBSDID("$FreeBSD: head/sys/x86/x86/delay.c 263008 2014-03-11 10:20:42Z royger $"); 38263008Sroyger 39263008Sroyger/* Generic x86 routines to handle delay */ 40263008Sroyger 41263008Sroyger#include <sys/param.h> 42263008Sroyger#include <sys/systm.h> 43263008Sroyger#include <sys/timetc.h> 44263008Sroyger#include <sys/proc.h> 45263008Sroyger#include <sys/kernel.h> 46263008Sroyger#include <sys/sched.h> 47263008Sroyger 48263008Sroyger#include <machine/clock.h> 49263008Sroyger#include <machine/cpu.h> 50263008Sroyger#include <x86/init.h> 51263008Sroyger 52263008Sroygerstatic u_int 53263008Sroygerget_tsc(__unused struct timecounter *tc) 54263008Sroyger{ 55263008Sroyger 56263008Sroyger return (rdtsc32()); 57263008Sroyger} 58263008Sroyger 59263008Sroygerstatic int 60263008Sroygerdelay_tc(int n) 61263008Sroyger{ 62263008Sroyger struct timecounter *tc; 63263008Sroyger timecounter_get_t *func; 64263008Sroyger uint64_t end, freq, now; 65263008Sroyger u_int last, mask, u; 66263008Sroyger 67263008Sroyger tc = timecounter; 68263008Sroyger freq = atomic_load_acq_64(&tsc_freq); 69263008Sroyger if (tsc_is_invariant && freq != 0) { 70263008Sroyger func = get_tsc; 71263008Sroyger mask = ~0u; 72263008Sroyger } else { 73263008Sroyger if (tc->tc_quality <= 0) 74263008Sroyger return (0); 75263008Sroyger func = tc->tc_get_timecount; 76263008Sroyger mask = tc->tc_counter_mask; 77263008Sroyger freq = tc->tc_frequency; 78263008Sroyger } 79263008Sroyger now = 0; 80263008Sroyger end = freq * n / 1000000; 81263008Sroyger if (func == get_tsc) 82263008Sroyger sched_pin(); 83263008Sroyger last = func(tc) & mask; 84263008Sroyger do { 85263008Sroyger cpu_spinwait(); 86263008Sroyger u = func(tc) & mask; 87263008Sroyger if (u < last) 88263008Sroyger now += mask - last + u + 1; 89263008Sroyger else 90263008Sroyger now += u - last; 91263008Sroyger last = u; 92263008Sroyger } while (now < end); 93263008Sroyger if (func == get_tsc) 94263008Sroyger sched_unpin(); 95263008Sroyger return (1); 96263008Sroyger} 97263008Sroyger 98263008Sroygervoid 99263008SroygerDELAY(int n) 100263008Sroyger{ 101263008Sroyger 102263008Sroyger if (delay_tc(n)) 103263008Sroyger return; 104263008Sroyger 105263008Sroyger init_ops.early_delay(n); 106263008Sroyger} 107