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