| Index: src/trusted/validator/x86/nacl_cpuid.c
|
| diff --git a/src/trusted/validator/x86/nacl_cpuid.c b/src/trusted/validator/x86/nacl_cpuid.c
|
| deleted file mode 100644
|
| index bcb83ffc9d2c427121d89e4b083353b761f92779..0000000000000000000000000000000000000000
|
| --- a/src/trusted/validator/x86/nacl_cpuid.c
|
| +++ /dev/null
|
| @@ -1,637 +0,0 @@
|
| -/*
|
| - * Copyright (c) 2012 The Native Client Authors. All rights reserved.
|
| - * Use of this source code is governed by a BSD-style license that can be
|
| - * found in the LICENSE file.
|
| - */
|
| -
|
| -#include "native_client/src/trusted/validator/x86/nacl_cpuid.h"
|
| -
|
| -/*
|
| - * nacl_cpuid.c
|
| - * Retrieve and decode CPU model specific feature mask.
|
| - */
|
| -#if NACL_WINDOWS
|
| -#include <intrin.h> /* __cpuid intrinsic */
|
| -#endif /* NACL_WINDOWS */
|
| -
|
| -#include <stdio.h>
|
| -#include <string.h>
|
| -#include <assert.h>
|
| -#include <stdlib.h>
|
| -
|
| -#include "native_client/src/include/portability_io.h"
|
| -#include "native_client/src/shared/platform/nacl_log.h"
|
| -
|
| -/*
|
| - * TODO(bradchen): consolidate to use one debug print mechanism.
|
| - */
|
| -
|
| -#define CPUID_EDX_x87 0x00000001 /* x87 FPU support */
|
| -#define CPUID_EDX_VME 0x00000002 /* Virtual 8086 Mode Enhancement */
|
| -#define CPUID_EDX_DEB 0x00000004 /* Debugging Extensions */
|
| -#define CPUID_EDX_PSE 0x00000008 /* Page Size Extensions */
|
| -#define CPUID_EDX_TSC 0x00000010 /* Time Stamp Counter */
|
| -#define CPUID_EDX_MSR 0x00000020 /* RDMSR and WRMSR */
|
| -#define CPUID_EDX_PAE 0x00000040 /* Physical Address Extensions */
|
| -#define CPUID_EDX_MCE 0x00000080 /* Machine Check Exception */
|
| -#define CPUID_EDX_CX8 0x00000100 /* CMPXCHG8B Instruction */
|
| -#define CPUID_EDX_APIC 0x00000200 /* APIC on chip */
|
| -/* 0x00000400 reserved */
|
| -#define CPUID_EDX_SEP 0x00000800 /* SYSENTER and SYSEXIT */
|
| -#define CPUID_EDX_MTRR 0x00001000 /* Memory Type Range Registers */
|
| -#define CPUID_EDX_PGE 0x00002000 /* PTE Global Bit */
|
| -#define CPUID_EDX_MCA 0x00004000 /* Machine Check Architecture */
|
| -#define CPUID_EDX_CMOV 0x00008000 /* CMOV instruction */
|
| -#define CPUID_EDX_PAT 0x00010000 /* Page Attribute Table */
|
| -#define CPUID_EDX_PSE36 0x00020000 /* Page Size Extension bis */
|
| -#define CPUID_EDX_PSN 0x00040000 /* Processor Serial Number */
|
| -#define CPUID_EDX_CLFLUSH 0x00080000 /* CLFLUSH instruction */
|
| -/* 0x00100000 reserved */
|
| -#define CPUID_EDX_DS 0x00200000 /* Debug Store */
|
| -#define CPUID_EDX_ACPI 0x00400000 /* Thermal Monitor and Clock Ctrl */
|
| -#define CPUID_EDX_MMX 0x00800000 /* MMX extensions */
|
| -#define CPUID_EDX_FXSR 0x01000000 /* FXSAVE/FXRSTOR instructions */
|
| -#define CPUID_EDX_SSE 0x02000000 /* SSE extensions */
|
| -#define CPUID_EDX_SSE2 0x04000000 /* SSE2 extensions */
|
| -#define CPUID_EDX_SS 0x08000000 /* Self snoop */
|
| -#define CPUID_EDX_HTT 0x10000000 /* Hyper-threading */
|
| -#define CPUID_EDX_TM 0x20000000 /* Thermal monitor */
|
| -/* 0x40000000 reserved */
|
| -#define CPUID_EDX_PBE 0x80000000 /* Pending Break Enable */
|
| -
|
| -#define CPUID_ECX_SSE3 0x00000001 /* SSE3 extensions */
|
| -#define CPUID_ECX_CLMUL 0x00000002 /* PCLMULQDQ instruction */
|
| -#define CPUID_ECX_DTES64 0x00000004 /* 64-bit DS Area */
|
| -#define CPUID_ECX_MON 0x00000008 /* MONITOR/MWAIT instructions */
|
| -#define CPUID_ECX_DSCPL 0x00000010 /* CPL Qualified Debug Store */
|
| -#define CPUID_ECX_VMX 0x00000020 /* Virtual Machine Extensions */
|
| -#define CPUID_ECX_SMX 0x00000040 /* Safer Mode Extensions */
|
| -#define CPUID_ECX_EST 0x00000080 /* Enahcned SpeedStep */
|
| -#define CPUID_ECX_TM2 0x00000100 /* Thermal Monitor 2 */
|
| -#define CPUID_ECX_SSSE3 0x00000200 /* SS_S_E3 extensions */
|
| -#define CPUID_ECX_CXID 0x00000400 /* L1 context ID */
|
| -/* 0x00000800 reserved */
|
| -#define CPUID_ECX_FMA 0x00001000 /* FMA instructions */
|
| -#define CPUID_ECX_CX16 0x00002000 /* CMPXCHG16B instruction */
|
| -#define CPUID_ECX_XTPR 0x00004000 /* xTPR update control */
|
| -#define CPUID_ECX_PDCM 0x00008000 /* Perf/Debug Capability MSR */
|
| -/* 0x00010000 reserved */
|
| -#define CPUID_ECX_PCID 0x00020000 /* Process-context identifiers */
|
| -#define CPUID_ECX_DCA 0x00040000 /* Direct Cache Access */
|
| -#define CPUID_ECX_SSE41 0x00080000 /* SSE4.1 extensions */
|
| -#define CPUID_ECX_SSE42 0x00100000 /* SSE4.2 extensions */
|
| -#define CPUID_ECX_x2APIC 0x00800000 /* x2APIC feature */
|
| -#define CPUID_ECX_MOVBE 0x00400000 /* MOVBE instruction */
|
| -#define CPUID_ECX_POPCNT 0x00800000 /* POPCNT instruction */
|
| -#define CPUID_ECX_TSCDDLN 0xx1000000 /* TSC-Deadline */
|
| -#define CPUID_ECX_AES 0x02000000 /* AES instructions */
|
| -#define CPUID_ECX_XSAVE 0x04000000 /* XSAVE/XRSTOR/XSETBV/XGETBV */
|
| -#define CPUID_ECX_OSXSAVE 0x08000000 /* XSAVE et al enabled by OS */
|
| -#define CPUID_ECX_AVX 0x10000000 /* AVX instructions */
|
| -#define CPUID_ECX_F16C 0x20000000 /* 16bit floating-point instructions */
|
| -#define CPUID_ECX_RDRAND 0x40000000 /* RDRAND instruction */
|
| -/* 0x80000000 reserved */
|
| -
|
| -/* Function 07h main leaf (ecx = 0) */
|
| -#define CPUID_EBX_FSGSBASE 0x00000001 /* RD/WR FS/GS BASE instructions */
|
| -/* 0x00000002 reserved */
|
| -/* 0x00000004 reserved */
|
| -#define CPUID_EBX_BMI1 0x00000008 /* BMI1 instructions */
|
| -#define CPUID_EBX_HLE 0x00000010 /* HLE instructions */
|
| -#define CPUID_EBX_AVX2 0x00000020 /* AVX2 instructions */
|
| -#define CPUID_EBX_SMEP 0x00000040 /* Supervisor Mode Exec-Protection */
|
| -/* 0x00000080 reserved */
|
| -#define CPUID_EBX_BMI2 0x00000100 /* BMI2 instructions */
|
| -#define CPUID_EBX_ERMS 0x00000200 /* Enhanced REP MOVSB/STOSB */
|
| -#define CPUID_EBX_INVPCID 0x00000400 /* Invalidate Processor Context ID */
|
| -#define CPUID_EBX_RTM 0x00000800 /* Restricted Transactional Memory */
|
| -/* 0xFFFFF000 reserved */
|
| -
|
| -/* AMD-specific masks - most are the same as in eax == 1 subfunction */
|
| -/* 0x00000001 duplicates CPUID_EDX_x87 */
|
| -/* 0x00000002 duplicates CPUID_EDX_VME */
|
| -/* 0x00000004 duplicates CPUID_EDX_DEB */
|
| -/* 0x00000008 duplicates CPUID_EDX_PSE */
|
| -/* 0x00000010 duplicates CPUID_EDX_TSC */
|
| -/* 0x00000020 duplicates CPUID_EDX_MSR */
|
| -/* 0x00000040 duplicates CPUID_EDX_PAE */
|
| -/* 0x00000080 duplicates CPUID_EDX_MCE */
|
| -/* 0x00000100 duplicates CPUID_EDX_CX8 */
|
| -/* 0000000200 duplicates CPUID_EDX_APIC */
|
| -/* 0x00000400 reserved */
|
| -#define CPUID_EDX_SYSCALL 0x00000800 /* SYSCALL/SYSRET instructions */
|
| -/* 0x00001000 duplicates CPUID_EDX_MTRR */
|
| -/* 0x00002000 duplicates CPUID_EDX_PGE */
|
| -/* 0x00004000 duplicates CPUID_EDX_MCA */
|
| -/* 0x00008000 duplicates CPUID_EDX_CMOV */
|
| -/* 0x00010000 duplicates CPUID_EDX_PAT */
|
| -/* 0x00020000 duplicates CPUID_EDX_PSE36 */
|
| -/* 0x00040000 reserved */
|
| -/* 0x00080000 reserved */
|
| -#define CPUID_EDX_NX 0x00100000 /* Execute Disable Bit available */
|
| -/* 0x00200000 reserved */
|
| -#define CPUID_EDX_EMMX 0x00400000 /* Extensions to MMX instructions */
|
| -/* 0x00800000 duplicates CPUID_EDX_MMX */
|
| -/* 0x01000000 duplicates CPUID_EDX_FXSR */
|
| -#define CPUID_EDX_FFFXSR 0x02000000 /* FXSAVE/FXRSTOR optimizations */
|
| -#define CPUID_EDX_1GBPAGES 0x04000000 /* 1-GB large page support */
|
| -#define CPUID_EDX_TSCP 0x08000000 /* RDTSCP instruction */
|
| -/* 0x10000000 reserved */
|
| -#define CPUID_EDX_LM 0x20000000 /* Longmode (AKA x86-64 mode) */
|
| -#define CPUID_EDX_E3DN 0x40000000 /* Extensions to 3DNow! instructions */
|
| -#define CPUID_EDX_3DN 0x80000000 /* 3DNow! instructions */
|
| -
|
| -#define CPUID_ECX_LAHF 0x00000001 /* LAHF/SAHF in x86-64 mode */
|
| -#define CPUID_ECX_CMPLEGACY 0x00000002 /* Core Multi-Processing legacy mode */
|
| -#define CPUID_ECX_SVM 0x00000004 /* Secure Virtual Machine */
|
| -#define CPUID_ECX_EXTAPIC 0x00000008 /* Extended APIC space */
|
| -#define CPUID_ECX_ALTMOVCR8 0x00000010 /* LOCK MOV CR0 means MOV CR8 */
|
| -#define CPUID_ECX_ABM 0x00000020 /* LZCNT instruction */
|
| -#define CPUID_ECX_SSE4A 0x00000040 /* SSRE4A instructions */
|
| -#define CPUID_ECX_MISALGNSSE 0x00000080 /* Misalign SSE mode */
|
| -#define CPUID_ECX_PRE 0x00000100 /* 3DNow! prefetch */
|
| -#define CPUID_ECX_OSVW 0x00000200 /* OS visible workaround */
|
| -#define CPUID_ECX_IBS 0x00000400 /* Instruction Based Sampling */
|
| -#define CPUID_ECX_XOP 0x00000800 /* XOP instructions */
|
| -#define CPUID_ECX_SKINIT 0x00001000 /* SKINIT/STGI are always supported */
|
| -#define CPUID_ECX_WDT 0x00002000 /* Watchdog timer support */
|
| -/* 0x00004000 reserved */
|
| -#define CPUID_ECX_LWP 0x00008000 /* Lightweight profiling support */
|
| -#define CPUID_ECX_FMA4 0x00010000 /* FMA4 instructions */
|
| -/* 0x00020000 reserved */
|
| -/* 0x00040000 reserved */
|
| -#define CPUID_ECX_NODEID 0x00080000 /* MSRC001_100C[NodeId, NodesPerCPU] */
|
| -/* 0x00100000 reserved */
|
| -#define CPUID_ECX_TBM 0x00200000 /* Trailing bit manipulations */
|
| -#define CPUID_ECX_TOPOLOGY 0x00400000 /* Topology extensions support */
|
| -/* 0xFF800000 reserved */
|
| -
|
| -
|
| -typedef enum {
|
| - CFReg_EAX_I=0, /* eax == 1 */
|
| - CFReg_EBX_I, /* eax == 1 */
|
| - CFReg_ECX_I, /* eax == 1 */
|
| - CFReg_EDX_I, /* eax == 1 */
|
| - CFReg_EAX_7, /* eax == 7; ecx == 0 */
|
| - CFReg_EBX_7, /* eax == 7; ecx == 0 */
|
| - CFReg_ECX_7, /* eax == 7; ecx == 0 */
|
| - CFReg_EDX_7, /* eax == 7; ecx == 0 */
|
| - CFReg_EAX_A, /* eax == 0x80000001 */
|
| - CFReg_EBX_A, /* eax == 0x80000001 */
|
| - CFReg_ECX_A, /* eax == 0x80000001 */
|
| - CFReg_EDX_A /* eax == 0x80000001 */
|
| -} CPUFeatureReg;
|
| -
|
| -typedef struct cpufeature {
|
| - CPUFeatureReg reg;
|
| - uint32_t mask;
|
| - const char *name;
|
| -} CPUFeature;
|
| -
|
| -static const CPUFeature CPUFeatureDescriptions[(int)NaClCPUFeatureX86_Max] = {
|
| - {0, 0, "CPUID supported"},
|
| - {0, 0, "CPU supported"},
|
| - {CFReg_EDX_A, CPUID_EDX_3DN, "3DNow"},
|
| - {CFReg_ECX_I, CPUID_ECX_AES, "AES"},
|
| - {CFReg_ECX_I, CPUID_ECX_AVX, "AVX"},
|
| - {CFReg_EBX_7, CPUID_EBX_BMI1, "BMI1"},
|
| - {CFReg_EDX_I, CPUID_EDX_CLFLUSH, "CLFLUSH"},
|
| - {CFReg_ECX_I, CPUID_ECX_CLMUL, "CLMUL"},
|
| - {CFReg_EDX_I, CPUID_EDX_CMOV, "CMOV"},
|
| - {CFReg_ECX_I, CPUID_ECX_CX16, "CMPXCHG16B"},
|
| - {CFReg_EDX_I, CPUID_EDX_CX8, "CMPXCHG8B"},
|
| - {CFReg_EDX_A, CPUID_EDX_E3DN, "E3DNow"},
|
| - {CFReg_EDX_A, CPUID_EDX_EMMX, "EMMX"},
|
| - {CFReg_ECX_I, CPUID_ECX_F16C, "F16C"},
|
| - {CFReg_ECX_I, CPUID_ECX_FMA, "FMA"},
|
| - {CFReg_ECX_A, CPUID_ECX_FMA4, "FMA4"},
|
| - {CFReg_EDX_I, CPUID_EDX_FXSR, "FXSAVE/FXRSTOR"},
|
| - {CFReg_EDX_A, CPUID_ECX_LAHF, "LAHF"},
|
| - {CFReg_EDX_A, CPUID_EDX_LM, "LongMode"},
|
| - {CFReg_ECX_A, CPUID_ECX_LWP, "LWP"},
|
| - {CFReg_ECX_A, CPUID_ECX_ABM, "LZCNT"},
|
| - {CFReg_EDX_I, CPUID_EDX_MMX, "MMX"},
|
| - {CFReg_ECX_I, CPUID_ECX_MON, "MONITOR/MWAIT"},
|
| - {CFReg_ECX_I, CPUID_ECX_MOVBE, "MOVBE"},
|
| - {CFReg_ECX_I, CPUID_ECX_OSXSAVE, "OSXSAVE"},
|
| - {CFReg_ECX_I, CPUID_ECX_POPCNT, "POPCNT"},
|
| - {CFReg_ECX_A, CPUID_ECX_PRE, "3DNowPrefetch"},
|
| - {CFReg_EDX_I, CPUID_EDX_SSE, "SSE"},
|
| - {CFReg_EDX_I, CPUID_EDX_SSE2, "SSE2"},
|
| - {CFReg_ECX_I, CPUID_ECX_SSE3, "SSE3"},
|
| - {CFReg_ECX_I, CPUID_ECX_SSE41, "SSE41"},
|
| - {CFReg_ECX_I, CPUID_ECX_SSE42, "SSE42"},
|
| - {CFReg_ECX_A, CPUID_ECX_SSE4A, "SSE4A"},
|
| - {CFReg_ECX_I, CPUID_ECX_SSSE3, "SSSE3"},
|
| - {CFReg_ECX_A, CPUID_ECX_TBM, "TBM"},
|
| - {CFReg_EDX_I, CPUID_EDX_TSC, "RDTSC"},
|
| - {CFReg_EDX_I, CPUID_EDX_x87, "x87"},
|
| - {CFReg_ECX_A, CPUID_ECX_XOP, "XOP"},
|
| -};
|
| -
|
| -#define /* static const int */ kVendorIDLength 13
|
| -static const char Intel_CPUID0[kVendorIDLength] = "GenuineIntel";
|
| -static const char AMD_CPUID0[kVendorIDLength] = "AuthenticAMD";
|
| -#ifdef NOTYET
|
| -static const char UMC_CPUID0[kVendorIDLength] = "UMC UMC UMC ";
|
| -static const char Cyrix_CPUID0[kVendorIDLength] = "CyrixInstead";
|
| -static const char NexGen_CPUID0[kVendorIDLength] = "NexGenDriven";
|
| -static const char Cantaur_CPUID0[kVendorIDLength] = "CentaurHauls";
|
| -static const char Rise_CPUID0[kVendorIDLength] = "RiseRiseRise";
|
| -static const char SiS_CPUID0[kVendorIDLength] = "SiS SiS SiS ";
|
| -static const char TM_CPUID0[kVendorIDLength] = "GenuineTMx86";
|
| -static const char NSC_CPUID0[kVendorIDLength] = "Geode by NSC";
|
| -#endif
|
| -
|
| -static int asm_HasCPUID(void) {
|
| - volatile int before, after, result;
|
| -#if NACL_BUILD_SUBARCH == 64
|
| - /* Note: If we are running in x86-64, then cpuid must be defined,
|
| - * since CPUID dates from DX2 486, and x86-64 was added after this.
|
| - */
|
| - return 1;
|
| -/* TODO(bradchen): split into separate Windows, etc., files */
|
| -#elif defined(__GNUC__)
|
| - __asm__ volatile("pushfl \n\t" /* save EFLAGS to eax */
|
| - "pop %%eax \n\t"
|
| - "movl %%eax, %0 \n\t" /* remember EFLAGS in %0 */
|
| - "xor $0x00200000, %%eax\n\t" /* toggle bit 21 */
|
| - "push %%eax \n\t" /* write eax to EFLAGS */
|
| - "popfl \n\t"
|
| - "pushfl \n\t" /* save EFLAGS to %1 */
|
| - "pop %1 \n\t"
|
| - /*
|
| - * We use "r" constraints here, forcing registers,
|
| - * because a memory reference using the stack
|
| - * pointer wouldn't be safe since we're moving the
|
| - * stack pointer around in between the
|
| - * instructions. We need to inform the compiler
|
| - * that we're clobbering %eax as a scratch register.
|
| - */
|
| - : "=r" (before), "=r" (after) : : "eax");
|
| -#elif NACL_WINDOWS
|
| - __asm {
|
| - pushfd
|
| - pop eax
|
| - mov before, eax
|
| - xor eax, 0x00200000
|
| - push eax
|
| - popfd
|
| - pushfd
|
| - pop after
|
| - }
|
| -#else
|
| -# error Unsupported platform
|
| -#endif
|
| - result = (before ^ after) & 0x0200000;
|
| - return result;
|
| -}
|
| -
|
| -static void asm_CPUID(uint32_t op, volatile uint32_t reg[4]) {
|
| -#if defined(__GNUC__)
|
| -#if NACL_BUILD_SUBARCH == 64
|
| - __asm__ volatile("push %%rbx \n\t" /* save %ebx */
|
| -#else
|
| - __asm__ volatile("pushl %%ebx \n\t"
|
| -#endif
|
| - "cpuid \n\t"
|
| - "movl %%ebx, %1 \n\t"
|
| - /* save what cpuid just put in %ebx */
|
| -#if NACL_BUILD_SUBARCH == 64
|
| - "pop %%rbx \n\t"
|
| -#else
|
| - "popl %%ebx \n\t" /* restore the old %ebx */
|
| -#endif
|
| - : "=a"(reg[0]), "=S"(reg[1]), "=c"(reg[2]), "=d"(reg[3])
|
| - : "a"(op)
|
| - : "cc");
|
| -#elif NACL_WINDOWS
|
| - __cpuid((uint32_t*)reg, op);
|
| -#else
|
| -# error Unsupported platform
|
| -#endif
|
| -}
|
| -
|
| -/*
|
| - * Historically CPUID only used eax to select "CPUID function". Function 07h
|
| - * broke this tradition: it's now required to specify "leaf" in ECX register.
|
| - *
|
| - * We can specify leaf in all cases (older "CPUID functions" will just ignore
|
| - * it), but there is a catch: MSVC 2005 or below don't include __cpuidex
|
| - * intrinsic required to call CPUID with leaf support!
|
| - *
|
| - * Thus we have two functions: asm_CPUID (for "CPUID functions" without leaves)
|
| - * and asm_CPUIDx (for "CPUID functions" with leaves). If code is compiled using
|
| - * MSVC 2005 or MSVC 2008 then features detected using function 07h will not be
|
| - * available.
|
| - *
|
| - * Note: MSVC 2008 is particularly problematic: MSVC 2008 does not support
|
| - * __cpuidex while MSVC 2008 SP1 does. Unfortunatelly there are no easy way
|
| - * to distinguish MSVC 2008 SP1 from MSVC 2008 using ifdef's thus we disable
|
| - * __cpuidex for MSVC 2008 unconditionally.
|
| - */
|
| -static void asm_CPUIDx(uint32_t op, volatile uint32_t reg[4], uint32_t ecx) {
|
| -#if defined(__GNUC__)
|
| -#if NACL_BUILD_SUBARCH == 64
|
| - __asm__ volatile("push %%rbx \n\t" /* save %ebx */
|
| -#else
|
| - __asm__ volatile("pushl %%ebx \n\t"
|
| -#endif
|
| - "cpuid \n\t"
|
| - "movl %%ebx, %1 \n\t"
|
| - /* save what cpuid just put in %ebx */
|
| -#if NACL_BUILD_SUBARCH == 64
|
| - "pop %%rbx \n\t"
|
| -#else
|
| - "popl %%ebx \n\t" /* restore the old %ebx */
|
| -#endif
|
| - : "=a"(reg[0]), "=S"(reg[1]), "=c"(reg[2]), "=d"(reg[3])
|
| - : "a"(op), "c"(ecx)
|
| - : "cc");
|
| -#elif NACL_WINDOWS
|
| -#ifdef _MSC_VER
|
| -#if _MSC_VER < 1600
|
| - reg[0] = 0;
|
| - reg[1] = 0;
|
| - reg[2] = 0;
|
| - reg[3] = 0;
|
| -#else
|
| - __cpuidex((uint32_t*)reg, op, ecx);
|
| -#endif
|
| -#else /* NACL_WINDOWS, but _MSC_VER is not defined */
|
| -/* This is Windows but not MSVC: who knows if __cpuidex is available? */
|
| -# error Unsupported compiler
|
| -#endif
|
| -#else
|
| -# error Unsupported platform
|
| -#endif
|
| -}
|
| -
|
| -static void CacheCPUVersionID(NaClCPUData* data) {
|
| - uint32_t reg[4] = {0, 0, 0, 0 };
|
| - asm_CPUID(0, reg);
|
| - data->_vidwords[0] = reg[1];
|
| - data->_vidwords[1] = reg[3];
|
| - data->_vidwords[2] = reg[2];
|
| - data->_vidwords[3] = 0;
|
| -}
|
| -
|
| -/* Defines the (cached) cpu version id */
|
| -#define CPUVersionID(data) ((char*) (data)->_vidwords)
|
| -
|
| -
|
| -/* Cache feature vector as array of uint32_t [ecx, edx] */
|
| -static void CacheCPUFeatureVector(NaClCPUData* data) {
|
| - int i;
|
| - for (i = 0; i < kMaxCPUFeatureReg; ++i) {
|
| - data->_featurev[i] = 0;
|
| - }
|
| - asm_CPUID(1, data->_featurev);
|
| - /* This is for for model-specific instructions from AMD and Intel after
|
| - AMD's Bulldozer (introduced BMI1 set) and Intel's Haswell (introduced
|
| - AVX2, BMI2, HLE, RTM, and RD/WR FS/GS BASE instructions). */
|
| - asm_CPUIDx(7, &data->_featurev[CFReg_EAX_7], 0);
|
| - /* this is for AMD CPUs */
|
| - asm_CPUID(0x80000001, &data->_featurev[CFReg_EAX_A]);
|
| -#if 0
|
| - /* print feature vector */
|
| - printf("CPUID: %08x %08x %08x %08x\n",
|
| - data->_featurev[0],
|
| - data->_featurev[1],
|
| - data->_featurev[2],
|
| - data->_featurev[3]);
|
| - printf("CPUID: %08x %08x %08x %08x\n",
|
| - data->_featurev[4],
|
| - data->_featurev[5],
|
| - data->_featurev[6],
|
| - data->_featurev[7]);
|
| -#endif
|
| -}
|
| -
|
| -/* CacheGetCPUIDString creates an ASCII string that identfies this CPU's */
|
| -/* vendor ID, family, model, and stepping, as per the CPUID instruction */
|
| -static void CacheGetCPUIDString(NaClCPUData* data) {
|
| - char *cpuversionid = CPUVersionID(data);
|
| - uint32_t *fv = data->_featurev;
|
| - char* wlid = data->_wlid;
|
| - /* Subtract 1 in this assert to avoid counting two null characters. */
|
| - assert(9 + kVendorIDLength - 1 == kCPUIDStringLength);
|
| - memcpy(wlid, cpuversionid, kVendorIDLength-1);
|
| - SNPRINTF(&(wlid[kVendorIDLength-1]), 9, "%08x", (int)fv[CFReg_EAX_I]);
|
| -}
|
| -
|
| -char *GetCPUIDString(NaClCPUData* data) {
|
| - return data->_wlid;
|
| -}
|
| -
|
| -/* Returns true if the given feature is defined by the CPUID. */
|
| -static int CheckCPUFeature(NaClCPUData* data, NaClCPUFeatureX86ID fid) {
|
| - const CPUFeature *f = &CPUFeatureDescriptions[fid];
|
| - uint32_t *fv = data->_featurev;
|
| - if ((fid == NaClCPUFeatureX86_CPUIDSupported) ||
|
| - (fid == NaClCPUFeatureX86_CPUSupported)) {
|
| - /* CPUIDSupported and CPUSupported aren't actually in CPUID,
|
| - CPUFeatureDescriptions therefore doesn't contain actual reg/mask for
|
| - them. */
|
| - return 1;
|
| - }
|
| - if (fv[f->reg] & f->mask) {
|
| - return 1;
|
| - } else {
|
| - return 0;
|
| - }
|
| -}
|
| -
|
| -uint64_t NaClXGETBV(uint32_t);
|
| -
|
| -/* Cache XCR vector */
|
| -static void CacheCPUXCRVector(NaClCPUData* data) {
|
| - if (CheckCPUFeature(data, NaClCPUFeatureX86_OSXSAVE)) {
|
| - int i;
|
| - for (i = 0; i < kMaxCPUXCRReg; ++i) {
|
| - data->_xcrv[i] = NaClXGETBV(i);
|
| - }
|
| - } else {
|
| - int i;
|
| - for (i = 0; i < kMaxCPUXCRReg; ++i) {
|
| - data->_xcrv[i] = 0;
|
| - }
|
| - }
|
| -}
|
| -
|
| -/* Check that we have a supported 386 architecture. NOTE:
|
| - * As as side effect, the given cpu features is cleared before
|
| - * setting the appropriate fields.
|
| - */
|
| -static void CheckNaClArchFeatures(NaClCPUData *data,
|
| - NaClCPUFeaturesX86 *features) {
|
| - const size_t kCPUID0Length = 12;
|
| - char *cpuversionid;
|
| - if (data->_has_CPUID) {
|
| - NaClSetCPUFeatureX86(features, NaClCPUFeatureX86_CPUIDSupported, 1);
|
| - }
|
| - cpuversionid = CPUVersionID(data);
|
| - if (strncmp(cpuversionid, Intel_CPUID0, kCPUID0Length) == 0) {
|
| - NaClSetCPUFeatureX86(features, NaClCPUFeatureX86_CPUSupported, 1);
|
| - } else if (strncmp(cpuversionid, AMD_CPUID0, kCPUID0Length) == 0) {
|
| - NaClSetCPUFeatureX86(features, NaClCPUFeatureX86_CPUSupported, 1);
|
| - }
|
| -}
|
| -
|
| -void NaClSetAllCPUFeaturesX86(NaClCPUFeatures *f) {
|
| - /* TODO(jfb) Use a safe cast in this interface. */
|
| - NaClCPUFeaturesX86 *features = (NaClCPUFeaturesX86 *) f;
|
| - /* Be a little more pedantic than using memset because we don't know exactly
|
| - * how the structure is laid out. If we use memset, fields may be initialized
|
| - * to 0xff instead of 1 ... this isn't the end of the world but it can
|
| - * create a skew if the structure is hashed, etc.
|
| - */
|
| - int id;
|
| - /* Ensure any padding is zeroed. */
|
| - NaClClearCPUFeaturesX86(features);
|
| - for (id = 0; id < NaClCPUFeatureX86_Max; ++id) {
|
| - NaClSetCPUFeatureX86(features, id, 1);
|
| - }
|
| -}
|
| -
|
| -/* WARNING: This routine and subroutines it uses are not threadsafe.
|
| - * However, if races occur, they are short lived, and at worst, will
|
| - * result in defining fewer features than are actually supported by
|
| - * the hardware. Hence, if a race occurs, the validator may reject
|
| - * some features that should not be rejected.
|
| - */
|
| -static void GetCPUFeatures(NaClCPUData* data, NaClCPUFeaturesX86 *cpuf) {
|
| - int id;
|
| - NaClClearCPUFeaturesX86(cpuf);
|
| - CheckNaClArchFeatures(data, cpuf);
|
| - if (!NaClGetCPUFeatureX86(cpuf, NaClCPUFeatureX86_CPUIDSupported)) {
|
| - return;
|
| - }
|
| -
|
| - for (id = 0; id < NaClCPUFeatureX86_Max; ++id) {
|
| - NaClSetCPUFeatureX86(cpuf, id, CheckCPUFeature(data, id));
|
| - }
|
| -
|
| - /*
|
| - * If the operating system doesn't maintain the YMM state,
|
| - * pretend we don't have the instructions available at all.
|
| - */
|
| - if (!(NaClGetCPUFeatureX86(cpuf, NaClCPUFeatureX86_OSXSAVE)
|
| - && (data->_xcrv[0] & 6) == 6)) {
|
| - NaClSetCPUFeatureX86(cpuf, NaClCPUFeatureX86_AVX, 0);
|
| - NaClSetCPUFeatureX86(cpuf, NaClCPUFeatureX86_F16C, 0);
|
| - NaClSetCPUFeatureX86(cpuf, NaClCPUFeatureX86_FMA, 0);
|
| - NaClSetCPUFeatureX86(cpuf, NaClCPUFeatureX86_FMA4, 0);
|
| - }
|
| -}
|
| -
|
| -void NaClCPUDataGet(NaClCPUData* data) {
|
| - data->_has_CPUID = asm_HasCPUID();
|
| - CacheCPUVersionID(data);
|
| - CacheCPUFeatureVector(data);
|
| - CacheCPUXCRVector(data);
|
| - CacheGetCPUIDString(data);
|
| -}
|
| -
|
| -void NaClGetCurrentCPUFeaturesX86(NaClCPUFeatures *f) {
|
| - /* TODO(jfb) Use a safe cast in this interface. */
|
| - NaClCPUFeaturesX86 *features = (NaClCPUFeaturesX86 *) f;
|
| - NaClCPUData cpu_data;
|
| - NaClCPUDataGet(&cpu_data);
|
| - GetCPUFeatures(&cpu_data, features);
|
| -}
|
| -
|
| -/* This array defines the CPU feature model for fixed-feature CPU
|
| - * mode. We currently require the same set of features for both
|
| - * 32- and 64-bit x86 CPUs, intended to be supported by most/all
|
| - * post-Pentium III CPUs. This set may be something we need to
|
| - * revisit in the future.
|
| - */
|
| -const int kFixedFeatureCPUModel[NaClCPUFeatureX86_Max] = {
|
| - 1, /* NaClCPUFeatureX86_CPUIDSupported */
|
| - 1, /* NaClCPUFeatureX86_CPUSupported */
|
| - 0, /* NaClCPUFeatureX86_3DNOW */ /* AMD-specific */
|
| - 0, /* NaClCPUFeatureX86_AES */
|
| - 0, /* NaClCPUFeatureX86_AVX */
|
| - 0, /* NaClCPUFeatureX86_BMI1 */
|
| - 1, /* NaClCPUFeatureX86_CLFLUSH */
|
| - 0, /* NaClCPUFeatureX86_CLMUL */
|
| - 1, /* NaClCPUFeatureX86_CMOV */
|
| - 1, /* NaClCPUFeatureX86_CX16 */
|
| - 1, /* NaClCPUFeatureX86_CX8 */
|
| - 0, /* NaClCPUFeatureX86_E3DNOW */ /* AMD-specific */
|
| - 0, /* NaClCPUFeatureX86_EMMX */ /* AMD-specific */
|
| - 0, /* NaClCPUFeatureX86_F16C */
|
| - 0, /* NaClCPUFeatureX86_FMA */
|
| - 0, /* NaClCPUFeatureX86_FMA4 */ /* AMD-specific */
|
| - 1, /* NaClCPUFeatureX86_FXSR */
|
| - 0, /* NaClCPUFeatureX86_LAHF */
|
| - 0, /* NaClCPUFeatureX86_LM */
|
| - 0, /* NaClCPUFeatureX86_LWP */ /* AMD-specific */
|
| - 0, /* NaClCPUFeatureX86_LZCNT */ /* AMD-specific */
|
| - 0, /* NaClCPUFeatureX86_MMX */
|
| - 0, /* NaClCPUFeatureX86_MON */
|
| - 0, /* NaClCPUFeatureX86_MOVBE */
|
| - 0, /* NaClCPUFeatureX86_OSXSAVE */
|
| - 0, /* NaClCPUFeatureX86_POPCNT */
|
| - 0, /* NaClCPUFeatureX86_PRE */ /* AMD-specific */
|
| - 1, /* NaClCPUFeatureX86_SSE */
|
| - 1, /* NaClCPUFeatureX86_SSE2 */
|
| - 1, /* NaClCPUFeatureX86_SSE3 */
|
| - 0, /* NaClCPUFeatureX86_SSE41 */
|
| - 0, /* NaClCPUFeatureX86_SSE42 */
|
| - 0, /* NaClCPUFeatureX86_SSE4A */ /* AMD-specific */
|
| - 0, /* NaClCPUFeatureX86_SSSE3 */
|
| - 0, /* NaClCPUFeatureX86_TBM */ /* AMD-specific */
|
| - 1, /* NaClCPUFeatureX86_TSC */
|
| - 0, /* NaClCPUFeatureX86_x87 */
|
| - 0 /* NaClCPUFeatureX86_XOP */ /* AMD-specific */
|
| -};
|
| -
|
| -int NaClFixCPUFeaturesX86(NaClCPUFeatures *f) {
|
| - /* TODO(jfb) Use a safe cast in this interface. */
|
| - NaClCPUFeaturesX86 *features = (NaClCPUFeaturesX86 *) f;
|
| - NaClCPUFeatureX86ID fid;
|
| - int rvalue = 1;
|
| -
|
| - for (fid = 0; fid < NaClCPUFeatureX86_Max; fid++) {
|
| - if (kFixedFeatureCPUModel[fid]) {
|
| - if (!NaClGetCPUFeatureX86(features, fid)) {
|
| - /* This CPU is missing a required feature. */
|
| - NaClLog(LOG_ERROR,
|
| - "This CPU is missing a feature required by fixed-mode: %s\n",
|
| - NaClGetCPUFeatureX86Name(fid));
|
| - rvalue = 0; /* set return value to indicate failure */
|
| - }
|
| - } else {
|
| - /* Feature is not in the fixed model.
|
| - * Ensure features does not have it either.
|
| - */
|
| - NaClSetCPUFeatureX86(features, fid, 0);
|
| - }
|
| - }
|
| - return rvalue;
|
| -}
|
| -
|
| -const char* NaClGetCPUFeatureX86Name(NaClCPUFeatureX86ID id) {
|
| - return CPUFeatureDescriptions[id].name;
|
| -}
|
| -
|
| -void NaClSetCPUFeatureX86(NaClCPUFeaturesX86 *f, NaClCPUFeatureX86ID id,
|
| - int state) {
|
| - f->data[id] = (char) state;
|
| -}
|
| -
|
| -void NaClClearCPUFeaturesX86(NaClCPUFeaturesX86 *features) {
|
| - memset(features, 0, sizeof(*features));
|
| -}
|
| -
|
| -void NaClCopyCPUFeaturesX86(NaClCPUFeaturesX86 *target,
|
| - const NaClCPUFeaturesX86 *source) {
|
| - memcpy(target, source, sizeof(*target));
|
| -}
|
| -
|
| -int NaClArchSupportedX86(const NaClCPUFeaturesX86 *f) {
|
| - return (NaClGetCPUFeatureX86(f, NaClCPUFeatureX86_CPUIDSupported) &&
|
| - NaClGetCPUFeatureX86(f, NaClCPUFeatureX86_CPUSupported));
|
| -}
|
|
|