1 /*- 2 * SPDX-License-Identifier: BSD-3-Clause 3 * 4 * Copyright (c) 1990 The Regents of the University of California. 5 * Copyright (c) 2010 Alexander Motin <mav@FreeBSD.org> 6 * All rights reserved. 7 * 8 * This code is derived from software contributed to Berkeley by 9 * William Jolitz and Don Ahn. 10 * 11 * Redistribution and use in source and binary forms, with or without 12 * modification, are permitted provided that the following conditions 13 * are met: 14 * 1. Redistributions of source code must retain the above copyright 15 * notice, this list of conditions and the following disclaimer. 16 * 2. Redistributions in binary form must reproduce the above copyright 17 * notice, this list of conditions and the following disclaimer in the 18 * documentation and/or other materials provided with the distribution. 19 * 3. Neither the name of the University nor the names of its contributors 20 * may be used to endorse or promote products derived from this software 21 * without specific prior written permission. 22 * 23 * THIS SOFTWARE IS PROVIDED BY THE REGENTS AND CONTRIBUTORS ``AS IS'' AND 24 * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 25 * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 26 * ARE DISCLAIMED. IN NO EVENT SHALL THE REGENTS OR CONTRIBUTORS BE LIABLE 27 * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL 28 * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS 29 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 30 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 31 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 32 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 33 * SUCH DAMAGE. 34 * 35 * from: @(#)clock.c 7.2 (Berkeley) 5/12/91 36 */ 37 38 #include <sys/cdefs.h> 39 __FBSDID("$FreeBSD$"); 40 41 /* Generic x86 routines to handle delay */ 42 43 #include <sys/param.h> 44 #include <sys/systm.h> 45 #include <sys/timetc.h> 46 #include <sys/proc.h> 47 #include <sys/kernel.h> 48 #include <sys/sched.h> 49 50 #include <machine/clock.h> 51 #include <machine/cpu.h> 52 #include <x86/init.h> 53 54 static u_int 55 get_tsc(__unused struct timecounter *tc) 56 { 57 58 return (rdtsc32()); 59 } 60 61 static int 62 delay_tc(int n) 63 { 64 struct timecounter *tc; 65 timecounter_get_t *func; 66 uint64_t end, freq, now; 67 u_int last, mask, u; 68 69 tc = timecounter; 70 freq = atomic_load_acq_64(&tsc_freq); 71 if (tsc_is_invariant && freq != 0) { 72 func = get_tsc; 73 mask = ~0u; 74 } else { 75 if (tc->tc_quality <= 0) 76 return (0); 77 func = tc->tc_get_timecount; 78 mask = tc->tc_counter_mask; 79 freq = tc->tc_frequency; 80 } 81 now = 0; 82 end = freq * n / 1000000; 83 if (func == get_tsc) 84 sched_pin(); 85 last = func(tc) & mask; 86 do { 87 cpu_spinwait(); 88 u = func(tc) & mask; 89 if (u < last) 90 now += mask - last + u + 1; 91 else 92 now += u - last; 93 last = u; 94 } while (now < end); 95 if (func == get_tsc) 96 sched_unpin(); 97 return (1); 98 } 99 100 void 101 DELAY(int n) 102 { 103 104 if (delay_tc(n)) 105 return; 106 107 init_ops.early_delay(n); 108 } 109