]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Rearrange CPUID again. Moved most of the helper logic into C, since
authorJeremy Fitzhardinge <jeremy@valgrind.org>
Mon, 26 Jan 2004 21:11:51 +0000 (21:11 +0000)
committerJeremy Fitzhardinge <jeremy@valgrind.org>
Mon, 26 Jan 2004 21:11:51 +0000 (21:11 +0000)
the assember was getting fiddly.  It now masks out only the undefined
or unimplemented parts of the feature set bits, so it now passes through
all the non-ISA-related feature bits to clients.

It also leaves the vendor ID string unmolested, so that clients can
extract vendor-specific information like extended brand strings and
cache/TLB configuration info.

It does, however, implement some Valgrind-specific requests at 0xd8000000,
though at present the only functionality is the ValgrindVCPU signature.

git-svn-id: svn://svn.valgrind.org/valgrind/trunk@2236

coregrind/vg_constants.h
coregrind/vg_helpers.S
coregrind/vg_to_ucode.c

index 74f3023de99731ce3bd2963c594b84fec06de578..781400bea09eca89efdb1f05d77b34b764cf6f9f 100644 (file)
 /* Assembly code stubs make this request */
 #define VG_USERREQ__SIGNAL_RETURNS          0x4001
 
-/* CPU features */
-#define VG_X86_FEAT_FPU                (0*32 + 0)
-#define VG_X86_FEAT_VME                (0*32 + 1)
-#define VG_X86_FEAT_DE         (0*32 + 2)
-#define VG_X86_FEAT_PSE                (0*32 + 3)
-#define VG_X86_FEAT_TSC                (0*32 + 4)
-#define VG_X86_FEAT_MSR                (0*32 + 5)
-#define VG_X86_FEAT_PAE                (0*32 + 6)
-#define VG_X86_FEAT_MCE                (0*32 + 7)
-#define VG_X86_FEAT_CX8                (0*32 + 8)
-#define VG_X86_FEAT_APIC       (0*32 + 9)
-#define VG_X86_FEAT_SEP                (0*32 + 11)
-#define VG_X86_FEAT_MTRR       (0*32 + 12)
-#define VG_X86_FEAT_PGE                (0*32 + 13)
-#define VG_X86_FEAT_MCA                (0*32 + 14)
-#define VG_X86_FEAT_CMOV       (0*32 + 15)
-#define VG_X86_FEAT_PAT                (0*32 + 16)
-#define VG_X86_FEAT_PSE36      (0*32 + 17)
-#define VG_X86_FEAT_CLFSH      (0*32 + 19)
-#define VG_X86_FEAT_DS         (0*32 + 21)
-#define VG_X86_FEAT_ACPI       (0*32 + 22)
-#define VG_X86_FEAT_MMX                (0*32 + 23)
-#define VG_X86_FEAT_FXSR       (0*32 + 24)
-#define VG_X86_FEAT_SSE                (0*32 + 25)
-#define VG_X86_FEAT_SSE2       (0*32 + 26)
-#define VG_X86_FEAT_SS         (0*32 + 27)
-#define VG_X86_FEAT_HT         (0*32 + 28)
-#define VG_X86_FEAT_TM         (0*32 + 29)
-#define VG_X86_FEAT_PBE                (0*32 + 31)
-
-#define VG_X86_FEAT_EST                (1*32 + 7)
-#define VG_X86_FEAT_TM2                (1*32 + 8)
-#define VG_X86_FEAT_CNXTID     (1*32 + 10)
+/* 
+   0 - standard feature flags
+   1 - Intel extended flags
+   2 - Valgrind internal flags
+   3 - AMD-specific flags
+ */
+#define VG_N_FEATURE_WORDS     4
+
+#define VG_X86_FEAT            0
+#define VG_EXT_FEAT            1
+#define VG_INT_FEAT            2
+#define VG_AMD_FEAT            3
+
+/* CPU features (generic) */
+#define VG_X86_FEAT_FPU                (VG_X86_FEAT*32 + 0)
+#define VG_X86_FEAT_VME                (VG_X86_FEAT*32 + 1)
+#define VG_X86_FEAT_DE         (VG_X86_FEAT*32 + 2)
+#define VG_X86_FEAT_PSE                (VG_X86_FEAT*32 + 3)
+#define VG_X86_FEAT_TSC                (VG_X86_FEAT*32 + 4)
+#define VG_X86_FEAT_MSR                (VG_X86_FEAT*32 + 5)
+#define VG_X86_FEAT_PAE                (VG_X86_FEAT*32 + 6)
+#define VG_X86_FEAT_MCE                (VG_X86_FEAT*32 + 7)
+#define VG_X86_FEAT_CX8                (VG_X86_FEAT*32 + 8)
+#define VG_X86_FEAT_APIC       (VG_X86_FEAT*32 + 9)
+#define VG_X86_FEAT_SEP                (VG_X86_FEAT*32 + 11)
+#define VG_X86_FEAT_MTRR       (VG_X86_FEAT*32 + 12)
+#define VG_X86_FEAT_PGE                (VG_X86_FEAT*32 + 13)
+#define VG_X86_FEAT_MCA                (VG_X86_FEAT*32 + 14)
+#define VG_X86_FEAT_CMOV       (VG_X86_FEAT*32 + 15)
+#define VG_X86_FEAT_PAT                (VG_X86_FEAT*32 + 16)
+#define VG_X86_FEAT_PSE36      (VG_X86_FEAT*32 + 17)
+#define VG_X86_FEAT_CLFSH      (VG_X86_FEAT*32 + 19)
+#define VG_X86_FEAT_DS         (VG_X86_FEAT*32 + 21)
+#define VG_X86_FEAT_ACPI       (VG_X86_FEAT*32 + 22)
+#define VG_X86_FEAT_MMX                (VG_X86_FEAT*32 + 23)
+#define VG_X86_FEAT_FXSR       (VG_X86_FEAT*32 + 24)
+#define VG_X86_FEAT_SSE                (VG_X86_FEAT*32 + 25)
+#define VG_X86_FEAT_SSE2       (VG_X86_FEAT*32 + 26)
+#define VG_X86_FEAT_SS         (VG_X86_FEAT*32 + 27)
+#define VG_X86_FEAT_HT         (VG_X86_FEAT*32 + 28)
+#define VG_X86_FEAT_TM         (VG_X86_FEAT*32 + 29)
+#define VG_X86_FEAT_IA64       (VG_X86_FEAT*32 + 30)
+#define VG_X86_FEAT_PBE                (VG_X86_FEAT*32 + 31)
+
+/* Intel extended feature word */
+#define VG_X86_FEAT_SSE3       (VG_EXT_FEAT*32 + 0)
+#define VG_X86_FEAT_MON                (VG_EXT_FEAT*32 + 3)
+#define VG_X86_FEAT_DSCPL      (VG_EXT_FEAT*32 + 4)
+#define VG_X86_FEAT_EST                (VG_EXT_FEAT*32 + 7)
+#define VG_X86_FEAT_TM2                (VG_EXT_FEAT*32 + 8)
+#define VG_X86_FEAT_CNXTID     (VG_EXT_FEAT*32 + 10)
 
 /* Used internally to mark whether CPUID is even implemented */
-#define VG_X86_FEAT_CPUID      (2*32 + 0)
-
-/* The set of features we're willing to support for the client */
-#define VG_SUPPORTED_FEATURES                  \
-       ((1 << VG_X86_FEAT_FPU)  |              \
-        (1 << VG_X86_FEAT_TSC)  |              \
-        (1 << VG_X86_FEAT_CMOV) |              \
-        (1 << VG_X86_FEAT_MMX)  |              \
-        (1 << VG_X86_FEAT_FXSR) |              \
-        (1 << VG_X86_FEAT_SSE)  |              \
-        (1 << VG_X86_FEAT_SSE2))
+#define VG_X86_FEAT_CPUID      (VG_INT_FEAT*32 + 0)
+
+/* AMD special features */
+#define VG_AMD_FEAT_SYSCALL    (VG_AMD_FEAT*32 + 11)
+#define VG_AMD_FEAT_NXP                (VG_AMD_FEAT*32 + 20)
+#define VG_AMD_FEAT_MMXEXT     (VG_AMD_FEAT*32 + 22)
+#define VG_AMD_FEAT_FFXSR      (VG_AMD_FEAT*32 + 25)
+#define VG_AMD_FEAT_LONGMODE   (VG_AMD_FEAT*32 + 29)
+#define VG_AMD_FEAT_3DNOWEXT   (VG_AMD_FEAT*32 + 30)
+#define VG_AMD_FEAT_3DNOW      (VG_AMD_FEAT*32 + 31)
+
 /* Various environment variables we pay attention to */
 
 /* The directory we look for all our auxillary files in */
index 5d2c313ab6a5b6bf26b770dd29fe52ebedb600c1..d5a8e87e8a06763088473799c4a89516d10a7b11 100644 (file)
@@ -190,76 +190,43 @@ out_done:
        dummy, replaced by %EDX value
        RA   <- %esp
 
-   For simulating the cpuid instruction, we will
-   issue a "real" cpuid instruction and then mask out
-   the bits of the features we do not support currently (3dnow mostly).
-   We also claim to not support most CPUID operations.
-       
-   Dirk Mueller <mueller@kde.org>
-
-   http://www.sandpile.org/ia32/cpuid.htm
-
-   references: 
-
-   pre-MMX pentium:
-
-   <werner> cpuid words (0): 0x1 0x756e6547 0x6c65746e 0x49656e69
-   <werner> cpuid words (1): 0x52b 0x0 0x0 0x1bf
+   We save registers and package up the args so we can call a C helper
+   for all this.
 */
 .global VG_(helper_CPUID)
 VG_(helper_CPUID):
+       pushl   %ebp
+       movl    %esp,%ebp
        pushl   %eax
        pushl   %ebx
        pushl   %ecx
        pushl   %edx
-       movl    32(%esp), %eax
-
-       /* eax==0 - max valid request+processor vendor */
-       cmpl    $0, %eax
-       jne     1f
-
-       movl    $1, %eax        /* only support request 1 */
-       movl    valgrind_brand+0, %ebx
-       movl    valgrind_brand+4, %edx
-       movl    valgrind_brand+8, %ecx
-       jmp     99f
-
-       /* eax==1 - CPU features and model ID */
-1:     cmpl    $1, %eax
-       jne     2f
-
-       cpuid   /* get host CPU's capabilities */
-
-       movl    $0111, %eax
-       movl    $0, %ebx                        /* clear APIC id, CLFLUSH size, Brand ID */
-       movl    $0, %ecx                        /* clear extended feature bits */
-       andl    $VG_SUPPORTED_FEATURES, %edx    /* mask off feature bits we don't support */
-       jmp     99f
-
-       /* eax=0x80000000 - extended cpuid functions */
-2:     cmpl    $0x80000000, %eax
-       jne     99f
-
-       /* leave eax==0x80000000 - we don't support any other extended operations */
-       movl    valgrind_brand+0, %ebx  /* AMD load the brand string again - */
-       movl    valgrind_brand+4, %edx  /* Intel leaves them "reserved" */
-       movl    valgrind_brand+8, %ecx
-       
+       pushl   %esi
+       pushl   %edi
+       pushf
        
-99:    movl    %edx, 20(%esp)
-       movl    %ecx, 24(%esp)
-       movl    %ebx, 28(%esp)
-       movl    %eax, 32(%esp)
+       lea     2*4(%ebp),%eax  /* &edx */
+       pushl   %eax
+       addl    $4,%eax         /* &ecx */
+       pushl   %eax
+       addl    $4,%eax         /* &ebx */
+       pushl   %eax
+       addl    $4,%eax         /* &eax */
+       pushl   %eax
+       pushl   (%eax)          /* eax */
+
+       call    VG_(helperc_CPUID)
+       addl    $20,%esp
 
+       popf
+       popl    %edi
+       popl    %esi
        popl    %edx
        popl    %ecx
        popl    %ebx
        popl    %eax
+       popl    %ebp
        ret
-.data
-valgrind_brand:
-       .ascii "ValgrindVCPU"
-.text
 
 /* Fetch the FPU status register.
    On entry:
index 2a6b49405b593545811fdf1b0a332de22eb7fc82..ae06d21e741d8f1439b6cf9abef4a20ea223f25e 100644 (file)
 /*--- for now.                                             ---*/
 /*------------------------------------------------------------*/
 
-#define VG_N_FEATURE_WORDS     3
+#define VG_CPU_VENDOR_GENERIC  0
+#define VG_CPU_VENDOR_INTEL    1
+#define VG_CPU_VENDOR_AMD      2
+
+static Int cpu_vendor = VG_CPU_VENDOR_GENERIC;
+
+static const struct cpu_vendor {
+       const Char *vendorstr;
+       Int         vendorid;
+} cpu_vendors[] = {
+       { "GenuineIntel", VG_CPU_VENDOR_INTEL },
+       { "AuthenticAMD", VG_CPU_VENDOR_AMD },
+};
 
 static Int cpuid_level = -2;   /* -2 -> not initialized */
 static UInt cpu_features[VG_N_FEATURE_WORDS];
@@ -108,17 +120,37 @@ static inline void cpuid(UInt eax,
 
 static void get_cpu_features(void)
 {
+   Char vendorstr[13];
+   Int i;
+
    if (!has_cpuid()) {
       cpuid_level = -1;
       return;
    }
 
-   cpu_features[2] |= (1 << (VG_X86_FEAT_CPUID%32));
+   cpu_features[VG_INT_FEAT] |= (1 << (VG_X86_FEAT_CPUID%32));
 
-   cpuid_level = cpuid_eax(0);
+   cpuid(0, &cpuid_level, (UInt *)&vendorstr[0], (UInt *)&vendorstr[8], (UInt *)&vendorstr[4]);
+   vendorstr[12] = '\0';
+
+   for(i = 0; i < sizeof(cpu_vendors)/sizeof(*cpu_vendors); i++)
+      if (VG_(memcmp)(vendorstr, cpu_vendors[i].vendorstr, 12) == 0) {
+        cpu_vendor = cpu_vendors[i].vendorid;
+        break;
+      }
 
    if (cpuid_level >= 1)
-      cpuid(1, NULL, NULL, &cpu_features[1], &cpu_features[0]);
+      cpuid(1, NULL, NULL, &cpu_features[VG_EXT_FEAT], &cpu_features[VG_X86_FEAT]);
+
+   switch(cpu_vendor) {
+   case VG_CPU_VENDOR_AMD:
+      /* get AMD-specific flags */
+      cpuid(0x80000001, NULL, NULL, NULL, &cpu_features[VG_AMD_FEAT]);
+      break;
+
+   default:
+      break;
+   }
 }
 
 Bool VG_(cpu_has_feature)(UInt feature)
@@ -134,6 +166,149 @@ Bool VG_(cpu_has_feature)(UInt feature)
    return !!(cpu_features[word] & (1 << bit));
 }
 
+/* The set of features we're willing to support for the client
+   
+   This includes supported instruction set extensions, plus any
+   extensions which don't have any user-mode visible effect (but the
+   client may find interesting).
+ */
+#define VG_X86_SUPPORTED_FEATURES              \
+        ((1 << VG_X86_FEAT_FPU)        |       \
+         (1 << VG_X86_FEAT_VME)        |       \
+         (1 << VG_X86_FEAT_DE)         |       \
+         (1 << VG_X86_FEAT_PSE)        |       \
+         (1 << VG_X86_FEAT_TSC)        |       \
+         (0 << VG_X86_FEAT_MSR)        |       \
+         (1 << VG_X86_FEAT_PAE)        |       \
+         (1 << VG_X86_FEAT_MCE)        |       \
+         (1 << VG_X86_FEAT_CX8)        |       \
+         (1 << VG_X86_FEAT_APIC)       |       \
+         (0 << VG_X86_FEAT_SEP)        |       \
+         (1 << VG_X86_FEAT_MTRR)       |       \
+         (1 << VG_X86_FEAT_PGE)        |       \
+         (1 << VG_X86_FEAT_MCA)        |       \
+         (1 << VG_X86_FEAT_CMOV)       |       \
+         (1 << VG_X86_FEAT_PAT)        |       \
+         (1 << VG_X86_FEAT_PSE36)      |       \
+         (0 << VG_X86_FEAT_CLFSH)      |       \
+         (1 << VG_X86_FEAT_DS)         |       \
+         (1 << VG_X86_FEAT_ACPI)       |       \
+         (1 << VG_X86_FEAT_MMX)        |       \
+         (1 << VG_X86_FEAT_FXSR)       |       \
+         (1 << VG_X86_FEAT_SSE)        |       \
+         (1 << VG_X86_FEAT_SSE2)       |       \
+         (1 << VG_X86_FEAT_SS)         |       \
+         (1 << VG_X86_FEAT_HT)         |       \
+         (1 << VG_X86_FEAT_TM)         |       \
+         (0 << VG_X86_FEAT_IA64)       |       \
+         (1 << VG_X86_FEAT_PBE))
+
+#define VG_AMD_SUPPORTED_FEATURES                                      \
+       ((0 << (VG_AMD_FEAT_SYSCALL % 32))      |                       \
+        (0 << (VG_AMD_FEAT_NXP % 32))          |                       \
+        (1 << (VG_AMD_FEAT_MMXEXT % 32))       |                       \
+        (0 << (VG_AMD_FEAT_FFXSR % 32))        |                       \
+        (0 << (VG_AMD_FEAT_LONGMODE % 32))     |                       \
+        (0 << (VG_AMD_FEAT_3DNOWEXT % 32))     |                       \
+        (0 << (VG_AMD_FEAT_3DNOW % 32))        |                       \
+        /* Common bits between standard features and AMD features */   \
+        (1 << VG_X86_FEAT_FPU)         |                               \
+        (1 << VG_X86_FEAT_VME)         |                               \
+        (1 << VG_X86_FEAT_DE)          |                               \
+        (1 << VG_X86_FEAT_PSE)         |                               \
+        (1 << VG_X86_FEAT_TSC)         |                               \
+        (0 << VG_X86_FEAT_MSR)         |                               \
+        (1 << VG_X86_FEAT_PAE)         |                               \
+        (1 << VG_X86_FEAT_MCE)         |                               \
+        (1 << VG_X86_FEAT_CX8)         |                               \
+        (1 << VG_X86_FEAT_APIC)        |                               \
+        (1 << VG_X86_FEAT_MTRR)        |                               \
+        (1 << VG_X86_FEAT_PGE)         |                               \
+        (1 << VG_X86_FEAT_MCA)         |                               \
+        (1 << VG_X86_FEAT_CMOV)        |                               \
+        (1 << VG_X86_FEAT_PAT)         |                               \
+        (1 << VG_X86_FEAT_PSE36)       |                               \
+        (1 << VG_X86_FEAT_MMX)         |                               \
+        (1 << VG_X86_FEAT_FXSR))
+
+
+/*     
+   For simulating the cpuid instruction, we will
+   issue a "real" cpuid instruction and then mask out
+   the bits of the features we do not support currently (3dnow mostly).
+   We also claim to not support most CPUID operations.
+       
+   Dirk Mueller <mueller@kde.org>
+
+   http://www.sandpile.org/ia32/cpuid.htm
+
+   references: 
+
+   pre-MMX pentium:
+
+   <werner> cpuid words (0): 0x1 0x756e6547 0x6c65746e 0x49656e69
+   <werner> cpuid words (1): 0x52b 0x0 0x0 0x1bf
+
+   Updated to be more extensible about future vendor extensions and
+   vendor-specific parts of CPUID.
+*/
+void VG_(helperc_CPUID)(UInt op, UInt *eax_ret, UInt *ebx_ret, UInt *ecx_ret, UInt *edx_ret)
+{
+   UInt eax, ebx, ecx, edx;
+
+   if (cpuid_level == -2)
+      get_cpu_features();      /* for cpu_vendor */
+
+   cpuid(op, &eax, &ebx, &ecx, &edx);
+
+   /* Common mangling */
+   switch(op) {
+   case 1:
+      edx &= VG_X86_SUPPORTED_FEATURES;
+      break;
+
+   case 0xd8000000: {
+      /* Implement some private information at 0xd8000000 */
+      static const Char valgrind_vendor[] = "ValgrindVCPU";
+
+      eax = 0xd8000000;                /* max request */
+      ebx = *(UInt *)&valgrind_vendor[0];
+      ecx = *(UInt *)&valgrind_vendor[8];
+      edx = *(UInt *)&valgrind_vendor[4];
+   }
+      break;
+   }
+
+   /* Vendor-specific mangling of the results */
+   switch(cpu_vendor) {
+   case VG_CPU_VENDOR_INTEL:
+      switch(op) {
+      case 1:
+        ecx = 0;               /* mask out all extended features for now */
+        break;
+
+      case 0x80000001:
+        ebx = ecx = edx = 0;
+        break;
+      }
+      break;
+
+   case VG_CPU_VENDOR_AMD:
+      switch(op) {
+      case 0x80000001:
+        edx &= VG_AMD_SUPPORTED_FEATURES;
+        break;
+      }
+      break;
+   }
+
+   *eax_ret = eax;
+   *ebx_ret = ebx;
+   *ecx_ret = ecx;
+   *edx_ret = edx;
+}
+
+
 /*------------------------------------------------------------*/
 /*--- Here so it can be inlined everywhere.                ---*/
 /*------------------------------------------------------------*/