]>
Commit | Line | Data |
---|---|---|
20b477a7 LM |
1 | /* This testcase is part of GDB, the GNU debugger. |
2 | ||
1d506c26 | 3 | Copyright 2017-2024 Free Software Foundation, Inc. |
20b477a7 LM |
4 | |
5 | This program is free software; you can redistribute it and/or modify | |
6 | it under the terms of the GNU General Public License as published by | |
7 | the Free Software Foundation; either version 3 of the License, or | |
8 | (at your option) any later version. | |
9 | ||
10 | This program is distributed in the hope that it will be useful, | |
11 | but WITHOUT ANY WARRANTY; without even the implied warranty of | |
12 | MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
13 | GNU General Public License for more details. | |
14 | ||
15 | You should have received a copy of the GNU General Public License | |
16 | along with this program. If not, see <http://www.gnu.org/licenses/>. */ | |
17 | ||
18 | #include <cpuid.h> | |
19 | #include <stdint.h> | |
20 | ||
17cd4947 | 21 | /* 0 if the CPU supports rdrand and non-zero otherwise. */ |
20b477a7 LM |
22 | static unsigned int supports_rdrand; |
23 | ||
17cd4947 LM |
24 | /* 0 if the CPU supports rdseed and non-zero otherwise. */ |
25 | static unsigned int supports_rdseed; | |
20b477a7 | 26 | |
17cd4947 LM |
27 | /* Check supported features and set globals accordingly. The globals |
28 | can be used to prevent unsupported tests from running. */ | |
29 | ||
30 | static void | |
31 | check_supported_features (void) | |
20b477a7 LM |
32 | { |
33 | unsigned int rdrand_mask = (1 << 30); | |
17cd4947 | 34 | unsigned int rdseed_mask = (1 << 18); |
20b477a7 | 35 | unsigned int eax, ebx, ecx, edx; |
17cd4947 LM |
36 | unsigned int vendor; |
37 | unsigned int max_level; | |
38 | ||
39 | max_level = __get_cpuid_max (0, &vendor); | |
40 | ||
41 | if (max_level < 1) | |
42 | return; | |
43 | ||
44 | __cpuid (1, eax, ebx, ecx, edx); | |
20b477a7 | 45 | |
17cd4947 LM |
46 | supports_rdrand = ((ecx & rdrand_mask) == rdrand_mask); |
47 | ||
48 | if (max_level >= 7) | |
49 | { | |
50 | __cpuid_count (7, 0, eax, ebx, ecx, edx); | |
51 | supports_rdseed = ((ebx & rdseed_mask) == rdseed_mask); | |
52 | } | |
20b477a7 LM |
53 | } |
54 | ||
55 | /* Test rdrand support for various output registers. */ | |
56 | ||
57 | void | |
58 | rdrand (void) | |
59 | { | |
60 | /* Get a random number from the rdrand assembly instruction. */ | |
61 | register uint64_t number; | |
62 | ||
63 | if (!supports_rdrand) | |
64 | return; | |
65 | ||
66 | /* 16-bit random numbers. */ | |
476dd29d GL |
67 | __asm__ volatile ("rdrand %%ax;": : : "%ax"); |
68 | __asm__ volatile ("rdrand %%bx;": : : "%bx"); | |
69 | __asm__ volatile ("rdrand %%cx;": : : "%cx"); | |
70 | __asm__ volatile ("rdrand %%dx;": : : "%dx"); | |
20b477a7 | 71 | |
476dd29d GL |
72 | __asm__ volatile ("mov %%di, %%ax;\n\ |
73 | rdrand %%di;\n\ | |
74 | mov %%ax, %%di;" : : : "%ax"); | |
20b477a7 | 75 | |
476dd29d GL |
76 | __asm__ volatile ("mov %%si, %%ax;\n\ |
77 | rdrand %%si;\n\ | |
78 | mov %%ax, %%si;" : : : "%ax"); | |
20b477a7 | 79 | |
476dd29d GL |
80 | __asm__ volatile ("mov %%bp, %%ax;\n\ |
81 | rdrand %%bp;\n\ | |
82 | mov %%ax, %%bp;" : : : "%ax"); | |
20b477a7 | 83 | |
476dd29d GL |
84 | __asm__ volatile ("mov %%sp, %%ax;\n\ |
85 | rdrand %%sp;\n\ | |
86 | mov %%ax, %%sp;" : : : "%ax"); | |
20b477a7 | 87 | |
a1499830 | 88 | #ifdef __x86_64__ |
476dd29d GL |
89 | __asm__ volatile ("rdrand %%r8w;": : : "%r8"); |
90 | __asm__ volatile ("rdrand %%r9w;": : : "%r9"); | |
91 | __asm__ volatile ("rdrand %%r10w;": : : "%r10"); | |
92 | __asm__ volatile ("rdrand %%r11w;": : : "%r11"); | |
93 | __asm__ volatile ("rdrand %%r12w;": : : "%r12"); | |
94 | __asm__ volatile ("rdrand %%r13w;": : : "%r13"); | |
95 | __asm__ volatile ("rdrand %%r14w;": : : "%r14"); | |
96 | __asm__ volatile ("rdrand %%r15w;": : : "%r15"); | |
a1499830 | 97 | #endif |
20b477a7 LM |
98 | |
99 | /* 32-bit random numbers. */ | |
476dd29d GL |
100 | __asm__ volatile ("rdrand %%eax;": : : "%eax"); |
101 | __asm__ volatile ("rdrand %%ebx;": : : "%ebx"); | |
102 | __asm__ volatile ("rdrand %%ecx;": : : "%ecx"); | |
103 | __asm__ volatile ("rdrand %%edx;": : : "%edx"); | |
20b477a7 | 104 | |
a1499830 | 105 | #ifdef __x86_64__ |
476dd29d GL |
106 | __asm__ volatile ("mov %%rdi, %%rax;\n\ |
107 | rdrand %%edi;\n\ | |
108 | mov %%rax, %%rdi;" : : : "%rax"); | |
109 | ||
110 | __asm__ volatile ("mov %%rsi, %%rax;\n\ | |
111 | rdrand %%esi;\n\ | |
112 | mov %%rax, %%rsi;" : : : "%rax"); | |
113 | ||
114 | __asm__ volatile ("mov %%rbp, %%rax;\n\ | |
115 | rdrand %%ebp;\n\ | |
116 | mov %%rax, %%rbp;" : : : "%rax"); | |
117 | ||
118 | __asm__ volatile ("mov %%rsp, %%rax;\n\ | |
119 | rdrand %%esp;\n\ | |
120 | mov %%rax, %%rsp;" : : : "%rax"); | |
121 | ||
122 | __asm__ volatile ("rdrand %%r8d;": : : "%r8"); | |
123 | __asm__ volatile ("rdrand %%r9d;": : : "%r9"); | |
124 | __asm__ volatile ("rdrand %%r10d;": : : "%r10"); | |
125 | __asm__ volatile ("rdrand %%r11d;": : : "%r11"); | |
126 | __asm__ volatile ("rdrand %%r12d;": : : "%r12"); | |
127 | __asm__ volatile ("rdrand %%r13d;": : : "%r13"); | |
128 | __asm__ volatile ("rdrand %%r14d;": : : "%r14"); | |
129 | __asm__ volatile ("rdrand %%r15d;": : : "%r15"); | |
20b477a7 LM |
130 | |
131 | /* 64-bit random numbers. */ | |
476dd29d GL |
132 | __asm__ volatile ("rdrand %%rax;": : : "%rax"); |
133 | __asm__ volatile ("rdrand %%rbx;": : : "%rbx"); | |
134 | __asm__ volatile ("rdrand %%rcx;": : : "%rcx"); | |
135 | __asm__ volatile ("rdrand %%rdx;": : : "%rdx"); | |
136 | ||
137 | __asm__ volatile ("mov %%rdi, %%rax;\n\ | |
138 | rdrand %%rdi;\n\ | |
139 | mov %%rax, %%rdi;" : : : "%rax"); | |
140 | ||
141 | __asm__ volatile ("mov %%rsi, %%rax;\n\ | |
142 | rdrand %%rsi;\n\ | |
143 | mov %%rax, %%rsi;" : : : "%rax"); | |
144 | ||
145 | __asm__ volatile ("mov %%rbp, %%rax;\n\ | |
146 | rdrand %%rbp;\n\ | |
147 | mov %%rax, %%rbp;" : : : "%rax"); | |
148 | ||
149 | __asm__ volatile ("mov %%rsp, %%rax;\n\ | |
150 | rdrand %%rsp;\n\ | |
151 | mov %%rax, %%rsp;" : : : "%rax"); | |
152 | ||
153 | __asm__ volatile ("rdrand %%r8;": : : "%r8"); | |
154 | __asm__ volatile ("rdrand %%r9;": : : "%r9"); | |
155 | __asm__ volatile ("rdrand %%r10;": : : "%r10"); | |
156 | __asm__ volatile ("rdrand %%r11;": : : "%r11"); | |
157 | __asm__ volatile ("rdrand %%r12;": : : "%r12"); | |
158 | __asm__ volatile ("rdrand %%r13;": : : "%r13"); | |
159 | __asm__ volatile ("rdrand %%r14;": : : "%r14"); | |
160 | __asm__ volatile ("rdrand %%r15;": : : "%r15"); | |
a1499830 | 161 | #endif |
20b477a7 LM |
162 | } |
163 | ||
164 | /* Test rdseed support for various output registers. */ | |
165 | ||
166 | void | |
167 | rdseed (void) | |
168 | { | |
169 | /* Get a random seed from the rdseed assembly instruction. */ | |
170 | register long seed; | |
171 | ||
17cd4947 | 172 | if (!supports_rdseed) |
20b477a7 LM |
173 | return; |
174 | ||
175 | /* 16-bit random seeds. */ | |
476dd29d GL |
176 | __asm__ volatile ("rdseed %%ax;": : : "%ax"); |
177 | __asm__ volatile ("rdseed %%bx;": : : "%bx"); | |
178 | __asm__ volatile ("rdseed %%cx;": : : "%cx"); | |
179 | __asm__ volatile ("rdseed %%dx;": : : "%dx"); | |
20b477a7 | 180 | |
476dd29d GL |
181 | __asm__ volatile ("mov %%di, %%ax;\n\ |
182 | rdseed %%di;\n\ | |
183 | mov %%ax, %%di;" : : : "%ax"); | |
20b477a7 | 184 | |
476dd29d GL |
185 | __asm__ volatile ("mov %%si, %%ax;\n\ |
186 | rdseed %%si;\n\ | |
187 | mov %%ax, %%si;" : : : "%ax"); | |
20b477a7 | 188 | |
476dd29d GL |
189 | __asm__ volatile ("mov %%bp, %%ax;\n\ |
190 | rdseed %%bp;\n\ | |
191 | mov %%ax, %%bp;" : : : "%ax"); | |
20b477a7 | 192 | |
476dd29d GL |
193 | __asm__ volatile ("mov %%sp, %%ax;\n\ |
194 | rdseed %%sp;\n\ | |
195 | mov %%ax, %%sp;" : : : "%ax"); | |
20b477a7 | 196 | |
a1499830 | 197 | #ifdef __x86_64__ |
476dd29d GL |
198 | __asm__ volatile ("rdseed %%r8w;": : : "%r8"); |
199 | __asm__ volatile ("rdseed %%r9w;": : : "%r9"); | |
200 | __asm__ volatile ("rdseed %%r10w;": : : "%r10"); | |
201 | __asm__ volatile ("rdseed %%r11w;": : : "%r11"); | |
202 | __asm__ volatile ("rdseed %%r12w;": : : "%r12"); | |
203 | __asm__ volatile ("rdseed %%r13w;": : : "%r13"); | |
204 | __asm__ volatile ("rdseed %%r14w;": : : "%r14"); | |
205 | __asm__ volatile ("rdseed %%r15w;": : : "%r15"); | |
a1499830 | 206 | #endif |
20b477a7 LM |
207 | |
208 | /* 32-bit random seeds. */ | |
476dd29d GL |
209 | __asm__ volatile ("rdseed %%eax;": : : "%eax"); |
210 | __asm__ volatile ("rdseed %%ebx;": : : "%ebx"); | |
211 | __asm__ volatile ("rdseed %%ecx;": : : "%ecx"); | |
212 | __asm__ volatile ("rdseed %%edx;": : : "%edx"); | |
20b477a7 | 213 | |
a1499830 | 214 | #ifdef __x86_64__ |
476dd29d GL |
215 | __asm__ volatile ("mov %%rdi, %%rax;\n\ |
216 | rdseed %%edi;\n\ | |
217 | mov %%rax, %%rdi;" : : : "%rax"); | |
218 | ||
219 | __asm__ volatile ("mov %%rsi, %%rax;\n\ | |
220 | rdseed %%esi;\n\ | |
221 | mov %%rax, %%rsi;" : : : "%rax"); | |
222 | ||
223 | __asm__ volatile ("mov %%rbp, %%rax;\n\ | |
224 | rdseed %%ebp;\n\ | |
225 | mov %%rax, %%rbp;" : : : "%rax"); | |
226 | ||
227 | __asm__ volatile ("mov %%rsp, %%rax;\n\ | |
228 | rdseed %%esp;\n\ | |
229 | mov %%rax, %%rsp;" : : : "%rax"); | |
230 | ||
231 | __asm__ volatile ("rdseed %%r8d;": : : "%r8"); | |
232 | __asm__ volatile ("rdseed %%r9d;": : : "%r9"); | |
233 | __asm__ volatile ("rdseed %%r10d;": : : "%r10"); | |
234 | __asm__ volatile ("rdseed %%r11d;": : : "%r11"); | |
235 | __asm__ volatile ("rdseed %%r12d;": : : "%r12"); | |
236 | __asm__ volatile ("rdseed %%r13d;": : : "%r13"); | |
237 | __asm__ volatile ("rdseed %%r14d;": : : "%r14"); | |
238 | __asm__ volatile ("rdseed %%r15d;": : : "%r15"); | |
20b477a7 LM |
239 | |
240 | /* 64-bit random seeds. */ | |
476dd29d GL |
241 | __asm__ volatile ("rdseed %%rax;": : : "%rax"); |
242 | __asm__ volatile ("rdseed %%rbx;": : : "%rbx"); | |
243 | __asm__ volatile ("rdseed %%rcx;": : : "%rcx"); | |
244 | __asm__ volatile ("rdseed %%rdx;": : : "%rdx"); | |
245 | ||
246 | __asm__ volatile ("mov %%rdi, %%rax;\n\ | |
247 | rdseed %%rdi;\n\ | |
248 | mov %%rax, %%rdi;" : : : "%rax"); | |
249 | ||
250 | __asm__ volatile ("mov %%rsi, %%rax;\n\ | |
251 | rdseed %%rsi;\n\ | |
252 | mov %%rax, %%rsi;" : : : "%rax"); | |
253 | ||
254 | __asm__ volatile ("mov %%rbp, %%rax;\n\ | |
255 | rdseed %%rbp;\n\ | |
256 | mov %%rax, %%rbp;" : : : "%rax"); | |
257 | ||
258 | __asm__ volatile ("mov %%rsp, %%rax;\n\ | |
259 | rdseed %%rsp;\n\ | |
260 | mov %%rax, %%rsp;" : : : "%rax"); | |
261 | ||
262 | __asm__ volatile ("rdseed %%r8;": : : "%r8"); | |
263 | __asm__ volatile ("rdseed %%r9;": : : "%r9"); | |
264 | __asm__ volatile ("rdseed %%r10;": : : "%r10"); | |
265 | __asm__ volatile ("rdseed %%r11;": : : "%r11"); | |
266 | __asm__ volatile ("rdseed %%r12;": : : "%r12"); | |
267 | __asm__ volatile ("rdseed %%r13;": : : "%r13"); | |
268 | __asm__ volatile ("rdseed %%r14;": : : "%r14"); | |
269 | __asm__ volatile ("rdseed %%r15;": : : "%r15"); | |
a1499830 | 270 | #endif |
20b477a7 LM |
271 | } |
272 | ||
d2ee8bb6 CM |
273 | /* Test rdtscp support. */ |
274 | ||
275 | void | |
276 | rdtscp (void) | |
277 | { | |
278 | #ifdef __x86_64__ | |
279 | __asm__ volatile ("rdtscp"); | |
280 | #endif | |
281 | } | |
282 | ||
20b477a7 LM |
283 | /* Initialize arch-specific bits. */ |
284 | ||
285 | static void | |
286 | initialize (void) | |
287 | { | |
288 | /* Initialize supported features. */ | |
17cd4947 | 289 | check_supported_features (); |
20b477a7 LM |
290 | } |
291 | ||
292 | /* Functions testing instruction decodings. GDB will test all of these. */ | |
293 | static testcase_ftype testcases[] = | |
294 | { | |
295 | rdrand, | |
d2ee8bb6 CM |
296 | rdseed, |
297 | rdtscp | |
20b477a7 | 298 | }; |