OLD | NEW |
1 /* | 1 /* |
2 * Copyright (c) 2012 The Native Client Authors. All rights reserved. | 2 * Copyright (c) 2012 The Native Client Authors. All rights reserved. |
3 * Use of this source code is governed by a BSD-style license that can be | 3 * Use of this source code is governed by a BSD-style license that can be |
4 * found in the LICENSE file. | 4 * found in the LICENSE file. |
5 */ | 5 */ |
6 | 6 |
7 #include "native_client/src/trusted/validator/x86/nacl_cpuid.h" | 7 #include "native_client/src/trusted/cpu_features/arch/x86/cpu_x86.h" |
8 | 8 |
9 /* | 9 /* |
10 * nacl_cpuid.c | 10 * cpu_x86.c |
11 * Retrieve and decode CPU model specific feature mask. | 11 * Retrieve and decode CPU model specific feature mask. |
12 */ | 12 */ |
13 #if NACL_WINDOWS | 13 #if NACL_WINDOWS |
14 #include <intrin.h> /* __cpuid intrinsic */ | 14 #include <intrin.h> /* __cpuid intrinsic */ |
15 #endif /* NACL_WINDOWS */ | 15 #endif /* NACL_WINDOWS */ |
16 | 16 |
17 #include <stdio.h> | 17 #include <stdio.h> |
18 #include <string.h> | 18 #include <string.h> |
19 #include <assert.h> | 19 #include <assert.h> |
20 #include <stdlib.h> | 20 #include <stdlib.h> |
(...skipping 216 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
237 static const char Cyrix_CPUID0[kVendorIDLength] = "CyrixInstead"; | 237 static const char Cyrix_CPUID0[kVendorIDLength] = "CyrixInstead"; |
238 static const char NexGen_CPUID0[kVendorIDLength] = "NexGenDriven"; | 238 static const char NexGen_CPUID0[kVendorIDLength] = "NexGenDriven"; |
239 static const char Cantaur_CPUID0[kVendorIDLength] = "CentaurHauls"; | 239 static const char Cantaur_CPUID0[kVendorIDLength] = "CentaurHauls"; |
240 static const char Rise_CPUID0[kVendorIDLength] = "RiseRiseRise"; | 240 static const char Rise_CPUID0[kVendorIDLength] = "RiseRiseRise"; |
241 static const char SiS_CPUID0[kVendorIDLength] = "SiS SiS SiS "; | 241 static const char SiS_CPUID0[kVendorIDLength] = "SiS SiS SiS "; |
242 static const char TM_CPUID0[kVendorIDLength] = "GenuineTMx86"; | 242 static const char TM_CPUID0[kVendorIDLength] = "GenuineTMx86"; |
243 static const char NSC_CPUID0[kVendorIDLength] = "Geode by NSC"; | 243 static const char NSC_CPUID0[kVendorIDLength] = "Geode by NSC"; |
244 #endif | 244 #endif |
245 | 245 |
246 static int asm_HasCPUID(void) { | 246 static int asm_HasCPUID(void) { |
| 247 #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 |
247 volatile int before, after, result; | 248 volatile int before, after, result; |
248 #if NACL_BUILD_SUBARCH == 64 | 249 #if NACL_BUILD_SUBARCH == 64 |
249 /* Note: If we are running in x86-64, then cpuid must be defined, | 250 /* Note: If we are running in x86-64, then cpuid must be defined, |
250 * since CPUID dates from DX2 486, and x86-64 was added after this. | 251 * since CPUID dates from DX2 486, and x86-64 was added after this. |
251 */ | 252 */ |
252 return 1; | 253 return 1; |
253 /* TODO(bradchen): split into separate Windows, etc., files */ | 254 /* TODO(bradchen): split into separate Windows, etc., files */ |
254 #elif defined(__GNUC__) | 255 #elif defined(__GNUC__) |
255 __asm__ volatile("pushfl \n\t" /* save EFLAGS to eax */ | 256 __asm__ volatile("pushfl \n\t" /* save EFLAGS to eax */ |
256 "pop %%eax \n\t" | 257 "pop %%eax \n\t" |
(...skipping 21 matching lines...) Expand all Loading... |
278 push eax | 279 push eax |
279 popfd | 280 popfd |
280 pushfd | 281 pushfd |
281 pop after | 282 pop after |
282 } | 283 } |
283 #else | 284 #else |
284 # error Unsupported platform | 285 # error Unsupported platform |
285 #endif | 286 #endif |
286 result = (before ^ after) & 0x0200000; | 287 result = (before ^ after) & 0x0200000; |
287 return result; | 288 return result; |
| 289 #else /* NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 */ |
| 290 return 0; |
| 291 #endif |
288 } | 292 } |
289 | 293 |
290 static void asm_CPUID(uint32_t op, volatile uint32_t reg[4]) { | 294 static void asm_CPUID(uint32_t op, volatile uint32_t reg[4]) { |
| 295 #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 |
291 #if defined(__GNUC__) | 296 #if defined(__GNUC__) |
292 #if NACL_BUILD_SUBARCH == 64 | 297 #if NACL_BUILD_SUBARCH == 64 |
293 __asm__ volatile("push %%rbx \n\t" /* save %ebx */ | 298 __asm__ volatile("push %%rbx \n\t" /* save %ebx */ |
294 #else | 299 #else |
295 __asm__ volatile("pushl %%ebx \n\t" | 300 __asm__ volatile("pushl %%ebx \n\t" |
296 #endif | 301 #endif |
297 "cpuid \n\t" | 302 "cpuid \n\t" |
298 "movl %%ebx, %1 \n\t" | 303 "movl %%ebx, %1 \n\t" |
299 /* save what cpuid just put in %ebx */ | 304 /* save what cpuid just put in %ebx */ |
300 #if NACL_BUILD_SUBARCH == 64 | 305 #if NACL_BUILD_SUBARCH == 64 |
301 "pop %%rbx \n\t" | 306 "pop %%rbx \n\t" |
302 #else | 307 #else |
303 "popl %%ebx \n\t" /* restore the old %ebx */ | 308 "popl %%ebx \n\t" /* restore the old %ebx */ |
304 #endif | 309 #endif |
305 : "=a"(reg[0]), "=S"(reg[1]), "=c"(reg[2]), "=d"(reg[3]) | 310 : "=a"(reg[0]), "=S"(reg[1]), "=c"(reg[2]), "=d"(reg[3]) |
306 : "a"(op) | 311 : "a"(op) |
307 : "cc"); | 312 : "cc"); |
308 #elif NACL_WINDOWS | 313 #elif NACL_WINDOWS |
309 __cpuid((uint32_t*)reg, op); | 314 __cpuid((uint32_t*)reg, op); |
310 #else | 315 #else |
311 # error Unsupported platform | 316 # error Unsupported platform |
312 #endif | 317 #endif |
| 318 #else /* NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 */ |
| 319 UNREFERENCED_PARAMETER(op); |
| 320 reg[0] = 0; |
| 321 reg[1] = 0; |
| 322 reg[2] = 0; |
| 323 reg[3] = 0; |
| 324 return; |
| 325 #endif |
313 } | 326 } |
314 | 327 |
315 /* | 328 /* |
316 * Historically CPUID only used eax to select "CPUID function". Function 07h | 329 * Historically CPUID only used eax to select "CPUID function". Function 07h |
317 * broke this tradition: it's now required to specify "leaf" in ECX register. | 330 * broke this tradition: it's now required to specify "leaf" in ECX register. |
318 * | 331 * |
319 * We can specify leaf in all cases (older "CPUID functions" will just ignore | 332 * We can specify leaf in all cases (older "CPUID functions" will just ignore |
320 * it), but there is a catch: MSVC 2005 or below don't include __cpuidex | 333 * it), but there is a catch: MSVC 2005 or below don't include __cpuidex |
321 * intrinsic required to call CPUID with leaf support! | 334 * intrinsic required to call CPUID with leaf support! |
322 * | 335 * |
323 * Thus we have two functions: asm_CPUID (for "CPUID functions" without leaves) | 336 * Thus we have two functions: asm_CPUID (for "CPUID functions" without leaves) |
324 * and asm_CPUIDx (for "CPUID functions" with leaves). If code is compiled using | 337 * and asm_CPUIDx (for "CPUID functions" with leaves). If code is compiled using |
325 * MSVC 2005 or MSVC 2008 then features detected using function 07h will not be | 338 * MSVC 2005 or MSVC 2008 then features detected using function 07h will not be |
326 * available. | 339 * available. |
327 * | 340 * |
328 * Note: MSVC 2008 is particularly problematic: MSVC 2008 does not support | 341 * Note: MSVC 2008 is particularly problematic: MSVC 2008 does not support |
329 * __cpuidex while MSVC 2008 SP1 does. Unfortunatelly there are no easy way | 342 * __cpuidex while MSVC 2008 SP1 does. Unfortunatelly there are no easy way |
330 * to distinguish MSVC 2008 SP1 from MSVC 2008 using ifdef's thus we disable | 343 * to distinguish MSVC 2008 SP1 from MSVC 2008 using ifdef's thus we disable |
331 * __cpuidex for MSVC 2008 unconditionally. | 344 * __cpuidex for MSVC 2008 unconditionally. |
332 */ | 345 */ |
333 static void asm_CPUIDx(uint32_t op, volatile uint32_t reg[4], uint32_t ecx) { | 346 static void asm_CPUIDx(uint32_t op, volatile uint32_t reg[4], uint32_t ecx) { |
| 347 #if NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 |
334 #if defined(__GNUC__) | 348 #if defined(__GNUC__) |
335 #if NACL_BUILD_SUBARCH == 64 | 349 #if NACL_BUILD_SUBARCH == 64 |
336 __asm__ volatile("push %%rbx \n\t" /* save %ebx */ | 350 __asm__ volatile("push %%rbx \n\t" /* save %ebx */ |
337 #else | 351 #else |
338 __asm__ volatile("pushl %%ebx \n\t" | 352 __asm__ volatile("pushl %%ebx \n\t" |
339 #endif | 353 #endif |
340 "cpuid \n\t" | 354 "cpuid \n\t" |
341 "movl %%ebx, %1 \n\t" | 355 "movl %%ebx, %1 \n\t" |
342 /* save what cpuid just put in %ebx */ | 356 /* save what cpuid just put in %ebx */ |
343 #if NACL_BUILD_SUBARCH == 64 | 357 #if NACL_BUILD_SUBARCH == 64 |
(...skipping 14 matching lines...) Expand all Loading... |
358 #else | 372 #else |
359 __cpuidex((uint32_t*)reg, op, ecx); | 373 __cpuidex((uint32_t*)reg, op, ecx); |
360 #endif | 374 #endif |
361 #else /* NACL_WINDOWS, but _MSC_VER is not defined */ | 375 #else /* NACL_WINDOWS, but _MSC_VER is not defined */ |
362 /* This is Windows but not MSVC: who knows if __cpuidex is available? */ | 376 /* This is Windows but not MSVC: who knows if __cpuidex is available? */ |
363 # error Unsupported compiler | 377 # error Unsupported compiler |
364 #endif | 378 #endif |
365 #else | 379 #else |
366 # error Unsupported platform | 380 # error Unsupported platform |
367 #endif | 381 #endif |
| 382 #else /* NACL_ARCH(NACL_BUILD_ARCH) == NACL_x86 */ |
| 383 UNREFERENCED_PARAMETER(op); |
| 384 UNREFERENCED_PARAMETER(ecx); |
| 385 reg[0] = 0; |
| 386 reg[1] = 0; |
| 387 reg[2] = 0; |
| 388 reg[3] = 0; |
| 389 return; |
| 390 #endif |
368 } | 391 } |
369 | 392 |
370 static void CacheCPUVersionID(NaClCPUData* data) { | 393 static void CacheCPUVersionID(NaClCPUData* data) { |
371 uint32_t reg[4] = {0, 0, 0, 0 }; | 394 uint32_t reg[4] = {0, 0, 0, 0 }; |
372 asm_CPUID(0, reg); | 395 asm_CPUID(0, reg); |
373 data->_vidwords[0] = reg[1]; | 396 data->_vidwords[0] = reg[1]; |
374 data->_vidwords[1] = reg[3]; | 397 data->_vidwords[1] = reg[3]; |
375 data->_vidwords[2] = reg[2]; | 398 data->_vidwords[2] = reg[2]; |
376 data->_vidwords[3] = 0; | 399 data->_vidwords[3] = 0; |
377 } | 400 } |
(...skipping 250 matching lines...) Expand 10 before | Expand all | Expand 10 after Loading... |
628 | 651 |
629 void NaClCopyCPUFeaturesX86(NaClCPUFeaturesX86 *target, | 652 void NaClCopyCPUFeaturesX86(NaClCPUFeaturesX86 *target, |
630 const NaClCPUFeaturesX86 *source) { | 653 const NaClCPUFeaturesX86 *source) { |
631 memcpy(target, source, sizeof(*target)); | 654 memcpy(target, source, sizeof(*target)); |
632 } | 655 } |
633 | 656 |
634 int NaClArchSupportedX86(const NaClCPUFeaturesX86 *f) { | 657 int NaClArchSupportedX86(const NaClCPUFeaturesX86 *f) { |
635 return (NaClGetCPUFeatureX86(f, NaClCPUFeatureX86_CPUIDSupported) && | 658 return (NaClGetCPUFeatureX86(f, NaClCPUFeatureX86_CPUIDSupported) && |
636 NaClGetCPUFeatureX86(f, NaClCPUFeatureX86_CPUSupported)); | 659 NaClGetCPUFeatureX86(f, NaClCPUFeatureX86_CPUSupported)); |
637 } | 660 } |
OLD | NEW |