xref: /freebsd/lib/libsys/x86/sched_getcpu_x86.c (revision 31a46e2cc84d7ebfc25ce5a33e54681057e9ed9a)
1*31a46e2cSBrooks Davis /*-
2*31a46e2cSBrooks Davis  * Copyright (c) 2021 The FreeBSD Foundation
3*31a46e2cSBrooks Davis  *
4*31a46e2cSBrooks Davis  * This software were developed by Konstantin Belousov <kib@FreeBSD.org>
5*31a46e2cSBrooks Davis  * under sponsorship from the FreeBSD Foundation.
6*31a46e2cSBrooks Davis  *
7*31a46e2cSBrooks Davis  * Redistribution and use in source and binary forms, with or without
8*31a46e2cSBrooks Davis  * modification, are permitted provided that the following conditions
9*31a46e2cSBrooks Davis  * are met:
10*31a46e2cSBrooks Davis  * 1. Redistributions of source code must retain the above copyright
11*31a46e2cSBrooks Davis  *    notice, this list of conditions and the following disclaimer.
12*31a46e2cSBrooks Davis  * 2. Redistributions in binary form must reproduce the above copyright
13*31a46e2cSBrooks Davis  *    notice, this list of conditions and the following disclaimer in the
14*31a46e2cSBrooks Davis  *    documentation and/or other materials provided with the distribution.
15*31a46e2cSBrooks Davis  *
16*31a46e2cSBrooks Davis  * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
17*31a46e2cSBrooks Davis  * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
18*31a46e2cSBrooks Davis  * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
19*31a46e2cSBrooks Davis  * ARE DISCLAIMED.  IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
20*31a46e2cSBrooks Davis  * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
21*31a46e2cSBrooks Davis  * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
22*31a46e2cSBrooks Davis  * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
23*31a46e2cSBrooks Davis  * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
24*31a46e2cSBrooks Davis  * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
25*31a46e2cSBrooks Davis  * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
26*31a46e2cSBrooks Davis  * SUCH DAMAGE.
27*31a46e2cSBrooks Davis  */
28*31a46e2cSBrooks Davis 
29*31a46e2cSBrooks Davis #include <sys/param.h>
30*31a46e2cSBrooks Davis #include <machine/cpufunc.h>
31*31a46e2cSBrooks Davis #include <machine/specialreg.h>
32*31a46e2cSBrooks Davis #include <machine/sysarch.h>
33*31a46e2cSBrooks Davis #include <x86/ifunc.h>
34*31a46e2cSBrooks Davis #include <errno.h>
35*31a46e2cSBrooks Davis #include <sched.h>
36*31a46e2cSBrooks Davis #include "libc_private.h"
37*31a46e2cSBrooks Davis 
38*31a46e2cSBrooks Davis static int
sched_getcpu_sys(void)39*31a46e2cSBrooks Davis sched_getcpu_sys(void)
40*31a46e2cSBrooks Davis {
41*31a46e2cSBrooks Davis 	return (__sys_sched_getcpu());
42*31a46e2cSBrooks Davis }
43*31a46e2cSBrooks Davis 
44*31a46e2cSBrooks Davis static int
sched_getcpu_rdpid(void)45*31a46e2cSBrooks Davis sched_getcpu_rdpid(void)
46*31a46e2cSBrooks Davis {
47*31a46e2cSBrooks Davis 	register_t res;
48*31a46e2cSBrooks Davis 
49*31a46e2cSBrooks Davis 	__asm("rdpid	%0" : "=r" (res));
50*31a46e2cSBrooks Davis 	return ((int)res);
51*31a46e2cSBrooks Davis }
52*31a46e2cSBrooks Davis 
53*31a46e2cSBrooks Davis static int
sched_getcpu_rdtscp(void)54*31a46e2cSBrooks Davis sched_getcpu_rdtscp(void)
55*31a46e2cSBrooks Davis {
56*31a46e2cSBrooks Davis 	int res;
57*31a46e2cSBrooks Davis 
58*31a46e2cSBrooks Davis 	__asm("rdtscp" : "=c" (res) : : "eax", "edx");
59*31a46e2cSBrooks Davis 	return (res);
60*31a46e2cSBrooks Davis }
61*31a46e2cSBrooks Davis 
62*31a46e2cSBrooks Davis DEFINE_UIFUNC(, int, sched_getcpu, (void))
63*31a46e2cSBrooks Davis {
64*31a46e2cSBrooks Davis 	u_int amd_feature, cpu_exthigh, p[4];
65*31a46e2cSBrooks Davis 
66*31a46e2cSBrooks Davis 	if ((cpu_stdext_feature2 & CPUID_STDEXT2_RDPID) != 0)
67*31a46e2cSBrooks Davis 		return (sched_getcpu_rdpid);
68*31a46e2cSBrooks Davis 
69*31a46e2cSBrooks Davis 	amd_feature = 0;
70*31a46e2cSBrooks Davis 	if (cpu_feature != 0) {
71*31a46e2cSBrooks Davis 		do_cpuid(0x80000000, p);
72*31a46e2cSBrooks Davis 		cpu_exthigh = p[0];
73*31a46e2cSBrooks Davis 		if (cpu_exthigh >= 0x80000001) {
74*31a46e2cSBrooks Davis 			do_cpuid(0x80000001, p);
75*31a46e2cSBrooks Davis 			amd_feature = p[3];
76*31a46e2cSBrooks Davis 		}
77*31a46e2cSBrooks Davis 	}
78*31a46e2cSBrooks Davis 
79*31a46e2cSBrooks Davis 	return ((amd_feature & AMDID_RDTSCP) == 0 ?
80*31a46e2cSBrooks Davis 	    sched_getcpu_sys : sched_getcpu_rdtscp);
81*31a46e2cSBrooks Davis }
82