1 /*
2  *  Licensed under the terms of the GNU GPL License version 2.
3  *
4  *  FreeBSD Routines for retrieving cpuid registers.
5  *  Originally submitted by Stanislav Sedov <stas@FreeBSD.org>
6  */
7 
8 #if defined(__FreeBSD__) || defined(__DragonFly__)
9 #include <sys/types.h>
10 #include <sys/param.h>
11 #include <sys/fcntl.h>
12 #include <sys/ioctl.h>
13 #include <sys/cpuctl.h>
14 #ifdef __DragonFly__
15 #include <sched.h>
16 #include <string.h>
17 #else
18 #include <sys/cpuset.h>
19 #endif
20 #include <stdio.h>
21 #include <stdlib.h>
22 #include <unistd.h>
23 
24 #include <x86info.h>
25 
26 #ifdef __DragonFly__
bind_cpu(unsigned int cpunr)27 void bind_cpu(unsigned int cpunr)
28 {
29 	int ret;
30 	cpu_set_t set;
31 	cpu_set_t tmp_set;
32 
33 	ret = sched_getaffinity(getpid(), sizeof(set), &set);
34 	if (ret)
35 		return;
36 
37 	memcpy(&tmp_set, &set, sizeof(cpu_set_t));
38 	CPU_ZERO(&set);
39 	CPU_SET(cpunr, &set);
40 	sched_setaffinity(getpid(), sizeof(set), &set);
41 	return;
42 }
43 #else
bind_cpu(unsigned int cpunr)44 void bind_cpu(unsigned int cpunr)
45 {
46 	cpuset_t mask;
47 
48 	CPU_ZERO(&mask);
49 	CPU_SET(cpunr, &mask);
50 	(void) cpuset_setaffinity(CPU_LEVEL_WHICH, CPU_WHICH_PID, -1,
51 	    sizeof(mask), &mask);
52 }
53 #endif
54 
55 static const char *NATIVE_CPUID_FAILED_MSG = "WARNING: Native cpuid failed\n";
56 
cpuid(unsigned int CPU_number,unsigned long long idx,unsigned int * eax,unsigned int * ebx,unsigned int * ecx,unsigned int * edx)57 void cpuid(unsigned int CPU_number, unsigned long long idx,
58 	unsigned int *eax,
59 	unsigned int *ebx,
60 	unsigned int *ecx,
61 	unsigned int *edx)
62 {
63 	static int nodriver=0;
64 	char cpuname[20];
65 	int fh;
66 	cpuctl_cpuid_count_args_t args;
67 
68 	if (nodriver == 1) {
69 		if (native_cpuid(CPU_number, idx, eax,ebx,ecx,edx))
70 			printf("%s", NATIVE_CPUID_FAILED_MSG);
71 		return;
72 	}
73 
74 	args.level = idx;
75 	args.level_type = idx >> 32;
76 	/* Ok, use the /dev/CPU interface in preference to the _up code. */
77 	(void)snprintf(cpuname, sizeof(cpuname), "/dev/cpuctl%u", CPU_number);
78 	fh = open(cpuname, O_RDONLY);
79 	if (fh != -1) {
80 		if (ioctl(fh, CPUCTL_CPUID_COUNT, &args) != 0) {
81 			perror(cpuname);
82 			exit(EXIT_FAILURE);
83 		}
84 		if (eax!=0)	*eax = args.data[0];
85 		if (ebx!=0)	*ebx = args.data[1];
86 		if (ecx!=0)	*ecx = args.data[2];
87 		if (edx!=0)	*edx = args.data[3];
88 #ifdef __DragonFly__
89 		close(fh);
90 #else
91 		if (close(fh) == -1) {
92 			perror("close");
93 			exit(EXIT_FAILURE);
94 		}
95 #endif
96 	} else {
97 		/* Something went wrong, just do UP and hope for the best. */
98 		nodriver = 1;
99 		if (nrCPUs != 1)
100 			perror(cpuname);
101 		if (native_cpuid(CPU_number, idx, eax,ebx,ecx,edx))
102 			printf("%s", NATIVE_CPUID_FAILED_MSG);
103 
104 		return;
105 	}
106 }
107 
108 #endif /* __FreeBSD__ */
109