blob: 0f0963ced0449c95be2424148904af1de56be805 [file] [log] [blame]
Chris Wilson545fe0f2016-07-11 12:39:01 +01001/*
2 * Copyright (c) 2013 Intel Corporation
3 *
4 * Permission is hereby granted, free of charge, to any person obtaining a
5 * copy of this software and associated documentation files (the "Software"),
6 * to deal in the Software without restriction, including without limitation
7 * the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 * and/or sell copies of the Software, and to permit persons to whom the
9 * Software is furnished to do so, subject to the following conditions:
10 *
11 * The above copyright notice and this permission notice (including the next
12 * paragraph) shall be included in all copies or substantial portions of the
13 * Software.
14 *
15 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16 * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17 * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL
18 * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19 * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20 * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21 * SOFTWARE.
22 *
23 * Authors:
24 * Chris Wilson <chris@chris-wilson.co.uk>
25 *
26 */
27
Chris Wilson545fe0f2016-07-11 12:39:01 +010028#include "config.h"
Chris Wilson545fe0f2016-07-11 12:39:01 +010029
30#ifdef HAVE_CPUID_H
31#include <cpuid.h>
32#else
33#define __get_cpuid_max(x, y) 0
34#define __cpuid(level, a, b, c, d) a = b = c = d = 0
35#define __cpuid_count(level, count, a, b, c, d) a = b = c = d = 0
36#endif
37
38#include "igt_x86.h"
39#include <stdio.h>
40
Paul Kocialkowski76bce772017-07-20 17:11:52 +030041/**
42 * SECTION:igt_x86
43 * @short_description: x86 helper library
44 * @title: x86
45 * @include: igt_x86.h
46 */
47
Chris Wilson545fe0f2016-07-11 12:39:01 +010048#define BASIC_CPUID 0x0
49#define EXTENDED_CPUID 0x80000000
50
51#ifndef bit_MMX
52#define bit_MMX (1 << 23)
53#endif
54
55#ifndef bit_SSE
56#define bit_SSE (1 << 25)
57#endif
58
59#ifndef bit_SSE2
60#define bit_SSE2 (1 << 26)
61#endif
62
63#ifndef bit_SSE3
64#define bit_SSE3 (1 << 0)
65#endif
66
67#ifndef bit_SSSE3
68#define bit_SSSE3 (1 << 9)
69#endif
70
71#ifndef bit_SSE4_1
72#define bit_SSE4_1 (1 << 19)
73#endif
74
75#ifndef bit_SSE4_2
76#define bit_SSE4_2 (1 << 20)
77#endif
78
79#ifndef bit_OSXSAVE
80#define bit_OSXSAVE (1 << 27)
81#endif
82
83#ifndef bit_AVX
84#define bit_AVX (1 << 28)
85#endif
86
87#ifndef bit_AVX2
88#define bit_AVX2 (1<<5)
89#endif
90
91#define xgetbv(index,eax,edx) \
92 __asm__ ("xgetbv" : "=a"(eax), "=d"(edx) : "c" (index))
93
94#define has_YMM 0x1
95
96unsigned igt_x86_features(void)
97{
98 unsigned max = __get_cpuid_max(BASIC_CPUID, 0);
99 unsigned eax, ebx, ecx, edx;
100 unsigned features = 0;
101 unsigned extra = 0;
102
103 if (max >= 1) {
104 __cpuid(1, eax, ebx, ecx, edx);
105
106 if (ecx & bit_SSE3)
107 features |= SSE3;
108
109 if (ecx & bit_SSSE3)
110 features |= SSSE3;
111
112 if (ecx & bit_SSE4_1)
113 features |= SSE4_1;
114
115 if (ecx & bit_SSE4_2)
116 features |= SSE4_2;
117
118 if (ecx & bit_OSXSAVE) {
119 unsigned int bv_eax, bv_ecx;
120 xgetbv(0, bv_eax, bv_ecx);
121 if ((bv_eax & 6) == 6)
122 extra |= has_YMM;
123 }
124
125 if ((extra & has_YMM) && (ecx & bit_AVX))
126 features |= AVX;
127
128 if (edx & bit_MMX)
129 features |= MMX;
130
131 if (edx & bit_SSE)
132 features |= SSE;
133
134 if (edx & bit_SSE2)
135 features |= SSE2;
136 }
137
138 if (max >= 7) {
139 __cpuid_count(7, 0, eax, ebx, ecx, edx);
140
141 if ((extra & has_YMM) && (ebx & bit_AVX2))
142 features |= AVX2;
143 }
144
145 return features;
146}
147
148char *igt_x86_features_to_string(unsigned features, char *line)
149{
150 char *ret = line;
151
152#ifdef __x86_64__
153 line += sprintf(line, "x86-64");
154#else
155 line += sprintf(line, "x86");
156#endif
157
158 if (features & SSE2)
159 line += sprintf(line, ", sse2");
160 if (features & SSE3)
161 line += sprintf(line, ", sse3");
162 if (features & SSSE3)
163 line += sprintf(line, ", ssse3");
164 if (features & SSE4_1)
165 line += sprintf(line, ", sse4.1");
166 if (features & SSE4_2)
167 line += sprintf(line, ", sse4.2");
168 if (features & AVX)
169 line += sprintf(line, ", avx");
170 if (features & AVX2)
171 line += sprintf(line, ", avx2");
172
173 return ret;
174}