__vdso_gettc.c (311376) | __vdso_gettc.c (311927) |
---|---|
1/*- 2 * Copyright (c) 2012 Konstantin Belousov <kib@FreeBSD.org> | 1/*- 2 * Copyright (c) 2012 Konstantin Belousov <kib@FreeBSD.org> |
3 * Copyright (c) 2016 The FreeBSD Foundation | 3 * Copyright (c) 2016, 2017 The FreeBSD Foundation |
4 * All rights reserved. 5 * 6 * Portions of this software were developed by Konstantin Belousov 7 * under sponsorship from the FreeBSD Foundation. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: --- 12 unchanged lines hidden (view full) --- 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30 31#include <sys/cdefs.h> | 4 * All rights reserved. 5 * 6 * Portions of this software were developed by Konstantin Belousov 7 * under sponsorship from the FreeBSD Foundation. 8 * 9 * Redistribution and use in source and binary forms, with or without 10 * modification, are permitted provided that the following conditions 11 * are met: --- 12 unchanged lines hidden (view full) --- 24 * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) 25 * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT 26 * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY 27 * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF 28 * SUCH DAMAGE. 29 */ 30 31#include <sys/cdefs.h> |
32__FBSDID("$FreeBSD: stable/11/lib/libc/x86/sys/__vdso_gettc.c 311376 2017-01-05 07:42:08Z sephe $"); | 32__FBSDID("$FreeBSD: stable/11/lib/libc/x86/sys/__vdso_gettc.c 311927 2017-01-11 11:25:18Z kib $"); |
33 34#include <sys/param.h> 35#include "namespace.h" 36#include <sys/elf.h> 37#include <sys/fcntl.h> 38#include <sys/mman.h> 39#include <sys/time.h> 40#include <sys/vdso.h> 41#include <errno.h> 42#include <string.h> 43#include <unistd.h> 44#include "un-namespace.h" | 33 34#include <sys/param.h> 35#include "namespace.h" 36#include <sys/elf.h> 37#include <sys/fcntl.h> 38#include <sys/mman.h> 39#include <sys/time.h> 40#include <sys/vdso.h> 41#include <errno.h> 42#include <string.h> 43#include <unistd.h> 44#include "un-namespace.h" |
45#include <machine/atomic.h> |
|
45#include <machine/cpufunc.h> 46#include <machine/specialreg.h> 47#include <dev/acpica/acpi_hpet.h> 48#ifdef __amd64__ | 46#include <machine/cpufunc.h> 47#include <machine/specialreg.h> 48#include <dev/acpica/acpi_hpet.h> 49#ifdef __amd64__ |
49#include <machine/atomic.h> | |
50#include <dev/hyperv/hyperv.h> 51#endif 52#include "libc_private.h" 53 54static void 55lfence_mb(void) 56{ 57#if defined(__i386__) --- 52 unchanged lines hidden (view full) --- 110static u_int 111__vdso_rdtsc32(void) 112{ 113 114 lfence_mb(); 115 return (rdtsc32()); 116} 117 | 50#include <dev/hyperv/hyperv.h> 51#endif 52#include "libc_private.h" 53 54static void 55lfence_mb(void) 56{ 57#if defined(__i386__) --- 52 unchanged lines hidden (view full) --- 110static u_int 111__vdso_rdtsc32(void) 112{ 113 114 lfence_mb(); 115 return (rdtsc32()); 116} 117 |
118static char *hpet_dev_map = NULL; 119static uint32_t hpet_idx = 0xffffffff; | 118#define HPET_DEV_MAP_MAX 10 119static volatile char *hpet_dev_map[HPET_DEV_MAP_MAX]; |
120 121static void 122__vdso_init_hpet(uint32_t u) 123{ 124 static const char devprefix[] = "/dev/hpet"; 125 char devname[64], *c, *c1, t; | 120 121static void 122__vdso_init_hpet(uint32_t u) 123{ 124 static const char devprefix[] = "/dev/hpet"; 125 char devname[64], *c, *c1, t; |
126 volatile char *new_map, *old_map; 127 uint32_t u1; |
|
126 int fd; 127 128 c1 = c = stpcpy(devname, devprefix); | 128 int fd; 129 130 c1 = c = stpcpy(devname, devprefix); |
129 u = hpet_idx; | 131 u1 = u; |
130 do { | 132 do { |
131 *c++ = u % 10 + '0'; 132 u /= 10; 133 } while (u != 0); | 133 *c++ = u1 % 10 + '0'; 134 u1 /= 10; 135 } while (u1 != 0); |
134 *c = '\0'; 135 for (c--; c1 != c; c1++, c--) { 136 t = *c1; 137 *c1 = *c; 138 *c = t; 139 } | 136 *c = '\0'; 137 for (c--; c1 != c; c1++, c--) { 138 t = *c1; 139 *c1 = *c; 140 *c = t; 141 } |
142 143 old_map = hpet_dev_map[u]; 144 if (old_map != NULL) 145 return; 146 |
|
140 fd = _open(devname, O_RDONLY); 141 if (fd == -1) { | 147 fd = _open(devname, O_RDONLY); 148 if (fd == -1) { |
142 hpet_dev_map = MAP_FAILED; | 149 atomic_cmpset_rel_ptr((volatile uintptr_t *)&hpet_dev_map[u], 150 (uintptr_t)old_map, (uintptr_t)MAP_FAILED); |
143 return; 144 } | 151 return; 152 } |
145 if (hpet_dev_map != NULL && hpet_dev_map != MAP_FAILED) 146 munmap(hpet_dev_map, PAGE_SIZE); 147 hpet_dev_map = mmap(NULL, PAGE_SIZE, PROT_READ, MAP_SHARED, fd, 0); | 153 new_map = mmap(NULL, PAGE_SIZE, PROT_READ, MAP_SHARED, fd, 0); |
148 _close(fd); | 154 _close(fd); |
155 if (atomic_cmpset_rel_ptr((volatile uintptr_t *)&hpet_dev_map[u], 156 (uintptr_t)old_map, (uintptr_t)new_map) == 0 && 157 new_map != MAP_FAILED) 158 munmap((void *)new_map, PAGE_SIZE); |
|
149} 150 151#ifdef __amd64__ 152 153#define HYPERV_REFTSC_DEVPATH "/dev/" HYPERV_REFTSC_DEVNAME 154 155/* 156 * NOTE: --- 51 unchanged lines hidden (view full) --- 208} 209 210#endif /* __amd64__ */ 211 212#pragma weak __vdso_gettc 213int 214__vdso_gettc(const struct vdso_timehands *th, u_int *tc) 215{ | 159} 160 161#ifdef __amd64__ 162 163#define HYPERV_REFTSC_DEVPATH "/dev/" HYPERV_REFTSC_DEVNAME 164 165/* 166 * NOTE: --- 51 unchanged lines hidden (view full) --- 218} 219 220#endif /* __amd64__ */ 221 222#pragma weak __vdso_gettc 223int 224__vdso_gettc(const struct vdso_timehands *th, u_int *tc) 225{ |
216 uint32_t tmp; | 226 volatile char *map; 227 uint32_t idx; |
217 218 switch (th->th_algo) { 219 case VDSO_TH_ALGO_X86_TSC: 220 *tc = th->th_x86_shift > 0 ? __vdso_gettc_rdtsc_low(th) : 221 __vdso_rdtsc32(); 222 return (0); 223 case VDSO_TH_ALGO_X86_HPET: | 228 229 switch (th->th_algo) { 230 case VDSO_TH_ALGO_X86_TSC: 231 *tc = th->th_x86_shift > 0 ? __vdso_gettc_rdtsc_low(th) : 232 __vdso_rdtsc32(); 233 return (0); 234 case VDSO_TH_ALGO_X86_HPET: |
224 tmp = th->th_x86_hpet_idx; 225 if (hpet_dev_map == NULL || tmp != hpet_idx) { 226 hpet_idx = tmp; 227 __vdso_init_hpet(hpet_idx); | 235 idx = th->th_x86_hpet_idx; 236 if (idx >= HPET_DEV_MAP_MAX) 237 return (ENOSYS); 238 map = (volatile char *)atomic_load_acq_ptr( 239 (volatile uintptr_t *)&hpet_dev_map[idx]); 240 if (map == NULL) { 241 __vdso_init_hpet(idx); 242 map = (volatile char *)atomic_load_acq_ptr( 243 (volatile uintptr_t *)&hpet_dev_map[idx]); |
228 } | 244 } |
229 if (hpet_dev_map == MAP_FAILED) | 245 if (map == MAP_FAILED) |
230 return (ENOSYS); | 246 return (ENOSYS); |
231 *tc = *(volatile uint32_t *)(hpet_dev_map + HPET_MAIN_COUNTER); | 247 *tc = *(volatile uint32_t *)(map + HPET_MAIN_COUNTER); |
232 return (0); 233#ifdef __amd64__ 234 case VDSO_TH_ALGO_X86_HVTSC: 235 if (hyperv_ref_tsc == NULL) 236 __vdso_init_hyperv_tsc(); 237 if (hyperv_ref_tsc == MAP_FAILED) 238 return (ENOSYS); 239 return (__vdso_hyperv_tsc(hyperv_ref_tsc, tc)); --- 13 unchanged lines hidden --- | 248 return (0); 249#ifdef __amd64__ 250 case VDSO_TH_ALGO_X86_HVTSC: 251 if (hyperv_ref_tsc == NULL) 252 __vdso_init_hyperv_tsc(); 253 if (hyperv_ref_tsc == MAP_FAILED) 254 return (ENOSYS); 255 return (__vdso_hyperv_tsc(hyperv_ref_tsc, tc)); --- 13 unchanged lines hidden --- |