]> git.ipfire.org Git - thirdparty/valgrind.git/commitdiff
Tidy up the machinery for detecting the CPU type and capabilities.
authorJulian Seward <jseward@acm.org>
Sat, 12 Nov 2005 23:10:48 +0000 (23:10 +0000)
committerJulian Seward <jseward@acm.org>
Sat, 12 Nov 2005 23:10:48 +0000 (23:10 +0000)
Move it from m_translate to m_machine, which is a more appropriate
place for it.

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

coregrind/m_dispatch/dispatch-x86-linux.S
coregrind/m_machine.c
coregrind/m_main.c
coregrind/m_translate.c
coregrind/pub_core_machine.h

index e743a8c1329791c7375b28c969bd62db8cf8a980..f357ad71743cb3386bab1fa5155f5e65aa725d0b 100644 (file)
@@ -71,7 +71,7 @@ VG_(run_innerloop):
        
        /* set host SSE control word to the default mode expected 
           by VEX-generated code. */
-       cmpl    $0, VG_(have_mxcsr_x86)
+       cmpl    $0, VG_(machine_x86_have_mxcsr)
        jz      L1
        pushl   $0x1F80
        ldmxcsr (%esp)
@@ -134,15 +134,15 @@ run_innerloop_exit:
            %mxcsr or %fpucw.  We can't mess with %eax here as it
           holds the tentative return value, but any other is OK. */
 /* This fails for self-hosting, so skip in that case */
-#ifndef ENABLE_INNER
+#if !defined(ENABLE_INNER)
        pushl   $0
        fstcw   (%esp)
        cmpl    $0x027F, (%esp)
        popl    %esi /* get rid of the word without trashing %eflags */
        jnz     invariant_violation
-       cmpl    $0, VG_(have_mxcsr_x86)
-       jz      L2
 #endif
+       cmpl    $0, VG_(machine_x86_have_mxcsr)
+       jz      L2
        pushl   $0
        stmxcsr (%esp)
        andl    $0xFFFFFFC0, (%esp)  /* mask out status flags */
index f143f00c507372872a62e7166871df4c6ff2e31b..c0342533f4080584354855c90e189444b5f8ae06 100644 (file)
@@ -33,6 +33,7 @@
 #include "pub_core_libcassert.h"
 #include "pub_core_libcbase.h"
 #include "pub_core_machine.h"
+#include "pub_core_cpuid.h"
 
 #define INSTR_PTR(regs)    ((regs).vex.VG_INSTR_PTR)
 #define STACK_PTR(regs)    ((regs).vex.VG_STACK_PTR)
@@ -211,36 +212,131 @@ Bool VG_(thread_stack_next)(ThreadId* tid, Addr* stack_min, Addr* stack_max)
    return False;
 }
 
-//////////////////////////////////////////////////////////////////
-// Architecture specifics
+//-------------------------------------------------------------
+/* Details about the capabilities of the underlying (host) CPU.  These
+   details are acquired by (1) enquiring with the CPU at startup, or
+   (2) from the AT_SYSINFO entries the kernel gave us (ppc32 cache
+   line size).  It's a bit nasty in the sense that there's no obvious
+   way to stop uses of some of this info before it's ready to go.
 
-#if defined(VGA_ppc32)
-/* PPC: what is the cache line size (for dcbz etc) ?  This info is
-   harvested on Linux at startup from the AT_SYSINFO entries.  0 means
-   not-yet-set. */
-Int VG_(cache_line_size_ppc32) = 0;
+   Current dependencies are:
+
+   x86:   initially:  call VG_(machine_get_hwcaps)
+
+          then safe to use VG_(machine_get_VexArchInfo) 
+                       and VG_(machine_x86_have_mxcsr)
+   -------------
+   amd64: initially:  call VG_(machine_get_hwcaps)
+
+          then safe to use VG_(machine_get_VexArchInfo) 
+   -------------
+   ppc32: initially:  call VG_(machine_get_hwcaps)
+                      call VG_(machine_ppc32_set_clszB)
+
+          then safe to use VG_(machine_get_VexArchInfo) 
+                       and VG_(machine_ppc32_has_FPU)
+                       and VG_(machine_ppc32_has_VMX)
+
+   VG_(machine_get_hwcaps) may use signals (although it attempts to
+   leave signal state unchanged) and therefore should only be
+   called before m_main sets up the client's signal state.
+*/
 
-/* Altivec enabled?  Harvested on startup from the AT_HWCAP entry. */
-Int VG_(have_altivec_ppc32) = 0;
+/* --------- State --------- */
+static Bool        hwcaps_done = False;
+
+/* --- all archs --- */
+static VexArch     va;
+static VexArchInfo vai;
+
+#if defined(VGA_x86)
+UInt VG_(machine_x86_have_mxcsr) = 0;
 #endif
+#if defined(VGA_ppc32)
+UInt VG_(machine_ppc32_has_FPU) = 0;
+UInt VG_(machine_ppc32_has_VMX) = 0;
+#endif
+
+
+/* Determine what insn set and insn set variant the host has, and
+   record it.  To be called once at system startup.  Returns False if
+   this a CPU incapable of running Valgrind. */
 
+Bool VG_(machine_get_hwcaps)( void )
+{
+   vg_assert(hwcaps_done == False);
+   hwcaps_done = True;
+
+   // Whack default settings into vai, so that we only need to fill in
+   // any interesting bits.
+   LibVEX_default_VexArchInfo(&vai);
 
 #if defined(VGA_x86)
-/* X86: set to 1 if the host is able to do {ld,st}mxcsr (load/store
-   the SSE control/status register.  For most modern CPUs this will be
-   1.  It is set to 1, if possible, by m_translate.getArchAndArchInfo.
-   The value is read by m_dispatch.dispatch-x86.S, which is why it is
-   an Int rather than a Bool.
-
-   Ugly hack: this has to start as 0 and be set to 1 in the normal
-   case, rather than the other way round, because the dispatch loop
-   needs it, and it runs before the first translation is made.  Yet it
-   is the act of making that first translation which causes
-   getArchAndArchInfo to set this value to its final value.  So it is
-   necessary to start this value off at 0 as only that guarantees that
-   the dispatch loop will not SIGILL on its first attempt. */
-Int VG_(have_mxcsr_x86) = 0;
+   { Bool have_sse1, have_sse2;
+     UInt eax, ebx, ecx, edx;
+
+     if (!VG_(has_cpuid)())
+        /* we can't do cpuid at all.  Give up. */
+        return False;
+
+     VG_(cpuid)(0, &eax, &ebx, &ecx, &edx);
+     if (eax < 1)
+        /* we can't ask for cpuid(x) for x > 0.  Give up. */
+        return False;
+
+     /* get capabilities bits into edx */
+     VG_(cpuid)(1, &eax, &ebx, &ecx, &edx);
+
+     have_sse1 = (edx & (1<<25)) != 0; /* True => have sse insns */
+     have_sse2 = (edx & (1<<26)) != 0; /* True => have sse2 insns */
+
+     if (have_sse2 && have_sse1) {
+        va          = VexArchX86;
+        vai.subarch = VexSubArchX86_sse2;
+        VG_(machine_x86_have_mxcsr) = 1;
+        return True;
+     }
+
+     if (have_sse1) {
+        va          = VexArchX86;
+        vai.subarch = VexSubArchX86_sse1;
+        VG_(machine_x86_have_mxcsr) = 1;
+        return True;
+     }
+
+     va          = VexArchX86;
+     vai.subarch = VexSubArchX86_sse0;
+     VG_(machine_x86_have_mxcsr) = 0;
+     return True;
+   }
+
+#elif defined(VGA_amd64)
+   vg_assert(VG_(has_cpuid)());
+   va          = VexArchAMD64;
+   vai.subarch = VexSubArch_NONE;
+   return True;
+
+#elif defined(VGA_ppc32)
+   va          = VexArchPPC32;
+   vai.subarch = VexSubArchPPC32_AV;
+   /* But we're not done yet: VG_(machine_ppc32_set_clszB) must be
+      called before we're ready to go. */
+   return True;
+
+#else
+#  error "Unknown arch"
 #endif
+}
+
+
+/* Fetch host cpu info, once established. */
+void VG_(machine_get_VexArchInfo)( /*OUT*/VexArch* pVa,
+                                   /*OUT*/VexArchInfo* pVai )
+{
+   vg_assert(hwcaps_done);
+   *pVa = va;
+   *pVai = vai;
+}
 
 
 /*--------------------------------------------------------------------*/
index 05503f2430f9dcea254034dc5b772d7feadd28c7..5423ce25619ec3cca7724048b27dded77f20c57b 100644 (file)
@@ -2033,6 +2033,30 @@ Int main(Int argc, HChar **argv, HChar **envp)
    // Get the current process stack rlimit.
    VG_(getrlimit)(VKI_RLIMIT_STACK, &VG_(client_rlimit_stack));
 
+   //--------------------------------------------------------------
+   // Figure out what sort of CPU we're on, and whether it is 
+   // able to run V.
+   VG_(debugLog)(1, "main", "Get hardware capabilities ...\n");
+   { VexArch     vex_arch;
+     VexArchInfo vex_archinfo;
+     Bool ok = VG_(machine_get_hwcaps)();
+     if (!ok) {
+        VG_(printf)("\n");
+        VG_(printf)("valgrind: fatal error: unsupported CPU.\n");
+        VG_(printf)("   Supported CPUs are:\n");
+        VG_(printf)("   * x86 (practically any; Pentium-I or above), "
+                    "AMD Athlon or above)\n");
+        VG_(printf)("   * AMD Athlon64/Opteron\n");
+        VG_(printf)("   * PowerPC (most; ppc405 and above)\n");
+        VG_(printf)("\n");
+        VG_(exit)(1);
+     }
+     VG_(machine_get_VexArchInfo)( &vex_arch, &vex_archinfo );
+     VG_(debugLog)(1, "main", "... arch = %s, subarch = %s\n",
+                   LibVEX_ppVexArch   ( vex_arch ),
+                   LibVEX_ppVexSubArch( vex_archinfo.subarch ) );
+   }
+
    //============================================================
    // Command line argument handling order:
    // * If --help/--help-debug are present, show usage message 
index ad109f5b5c2f796c2641d8e6defb6d89b357cb08..f6558a7a8639f0aef224e4268ee81a66f5e4e46c 100644 (file)
 
 #include "pub_core_basics.h"
 #include "pub_core_aspacemgr.h"
-#include "pub_core_cpuid.h"
-#include "pub_core_machine.h"       // For VG_(cache_line_size_ppc32)
-                                    // and VG_(have_altivec_ppc)
+
+#include "pub_core_machine.h"       // For VG_(machine_get_VexArchInfo)
                                     // and VG_(get_SP)
-                                    // and VG_(have_mxcsr_x86)
 #include "pub_core_libcbase.h"
 #include "pub_core_libcassert.h"
 #include "pub_core_libcprint.h"
 #include "pub_core_transtab.h"
 
 
-/*------------------------------------------------------------*/
-/*--- Determining arch/subarch.                            ---*/
-/*------------------------------------------------------------*/
-
-// Returns the architecture and auxiliary information, or indicates
-// that this subarchitecture is unable to run Valgrind.  Returns False
-// to indicate we cannot proceed further.
-
-static Bool getArchAndArchInfo( /*OUT*/VexArch*     vex_arch, 
-                                /*OUT*/VexArchInfo* vai )
-{
-   // Whack default settings into vai, so that we only need to fill in
-   // any interesting bits.
-   LibVEX_default_VexArchInfo(vai);
-
-#if defined(VGA_x86)
-   { Bool have_sse1, have_sse2;
-     UInt eax, ebx, ecx, edx;
-
-     if (!VG_(has_cpuid)())
-        /* we can't do cpuid at all.  Give up. */
-        return False;
-
-     VG_(cpuid)(0, &eax, &ebx, &ecx, &edx);
-     if (eax < 1)
-        /* we can't ask for cpuid(x) for x > 0.  Give up. */
-        return False;
-
-     /* get capabilities bits into edx */
-     VG_(cpuid)(1, &eax, &ebx, &ecx, &edx);
-
-     have_sse1 = (edx & (1<<25)) != 0; /* True => have sse insns */
-     have_sse2 = (edx & (1<<26)) != 0; /* True => have sse2 insns */
-
-     VG_(have_mxcsr_x86) = 1;
-
-     if (have_sse2 && have_sse1) {
-        *vex_arch    = VexArchX86;
-        vai->subarch = VexSubArchX86_sse2;
-        return True;
-     }
-
-     if (have_sse1) {
-        *vex_arch    = VexArchX86;
-        vai->subarch = VexSubArchX86_sse1;
-        return True;
-     }
-
-     {
-        *vex_arch    = VexArchX86;
-        vai->subarch = VexSubArchX86_sse0;
-        VG_(have_mxcsr_x86) = 0;
-        return True;
-     }
-   }
-
-#elif defined(VGA_amd64)
-   vg_assert(VG_(has_cpuid)());
-   *vex_arch    = VexArchAMD64;
-   vai->subarch = VexSubArch_NONE;
-   return True;
-
-#elif defined(VGA_ppc32)
-   *vex_arch    = VexArchPPC32;
-   vai->subarch = VG_(have_altivec_ppc32) ? VexSubArchPPC32_AV
-                                          : VexSubArchPPC32_noAV;
-   vai->ppc32_cache_line_szB = VG_(cache_line_size_ppc32);
-   return True;
-
-#else
-#  error Unknown architecture
-#endif
-}
-
-
 /*------------------------------------------------------------*/
 /*--- %SP-update pass                                      ---*/
 /*------------------------------------------------------------*/
@@ -524,42 +447,21 @@ Bool VG_(translate) ( ThreadId tid,
                       Int      debugging_verbosity,
                       ULong    bbs_done )
 {
-   Addr64    redir, orig_addr_noredir = orig_addr;
-   Int       tmpbuf_used, verbosity, i;
-   Bool      notrace_until_done, do_self_check;
-   UInt      notrace_until_limit = 0;
-   NSegment* seg;
-   VexGuestExtents vge;
-
-   /* Indicates what arch we are running on, and other important info
-      (subarch variant, cache line size). */
-   static VexArchInfo vex_archinfo;
-   static VexArch     vex_arch    = VexArch_INVALID;
+   Addr64             redir, orig_addr_noredir = orig_addr;
+   Int                tmpbuf_used, verbosity, i;
+   Bool               notrace_until_done, do_self_check;
+   UInt               notrace_until_limit = 0;
+   NSegment*          seg;
+   VexArch            vex_arch;
+   VexArchInfo        vex_archinfo;
+   VexGuestExtents    vge;
+   VexTranslateResult tres;
 
    /* Make sure Vex is initialised right. */
-   VexTranslateResult tres;
+
    static Bool vex_init_done = False;
 
    if (!vex_init_done) {
-      Bool ok = getArchAndArchInfo( &vex_arch, &vex_archinfo );
-      if (!ok) {
-         VG_(printf)("\n");
-         VG_(printf)("valgrind: fatal error: unsupported CPU.\n");
-         VG_(printf)("   Supported CPUs are:\n");
-         VG_(printf)("   * x86 (practically any; Pentium-I or above), "
-                     "AMD Athlon or above)\n");
-         VG_(printf)("   * AMD Athlon64/Opteron\n");
-         VG_(printf)("   * PowerPC with Altivec\n");
-         VG_(printf)("\n");
-         VG_(exit)(1);
-      }
-      if (VG_(clo_verbosity) > 2) {
-         VG_(message)(Vg_DebugMsg, 
-                      "Host CPU: arch = %s, subarch = %s",
-                      LibVEX_ppVexArch   ( vex_arch ),
-                      LibVEX_ppVexSubArch( vex_archinfo.subarch ) );
-      }
-
       LibVEX_Init ( &failure_exit, &log_bytes, 
                     1,     /* debug_paranoia */ 
                     False, /* valgrind support */
@@ -664,10 +566,13 @@ Bool VG_(translate) ( ThreadId tid,
 
    VGP_PUSHCC(VgpVexTime);
    
-   /* Actually do the translation. */
+   /* ------ Actually do the translation. ------ */
    tl_assert2(VG_(tdict).tool_instrument,
               "you forgot to set VgToolInterface function 'tool_instrument'");
 
+   /* Get the CPU info established at startup. */
+   VG_(machine_get_VexArchInfo)( &vex_arch, &vex_archinfo );
+
    /* Set up closure arg for "chase_into_ok" */
    chase_into_ok__CLOSURE_tid = tid;
 
index 2046fe67689ded96df15531b2d8826ed481ae52d..f22bfcc080bd3a187dcd9c75b1e699d868145762 100644 (file)
 #define VG_O_STACK_PTR        (offsetof(VexGuestArchState, VG_STACK_PTR))
 
 
-// Architecture specifics
+//-------------------------------------------------------------
+/* Details about the capabilities of the underlying (host) CPU.  These
+   details are acquired by (1) enquiring with the CPU at startup, or
+   (2) from the AT_SYSINFO entries the kernel gave us (ppc32 cache
+   line size).  It's a bit nasty in the sense that there's no obvious
+   way to stop uses of some of this info before it's ready to go.
+
+   Current dependencies are:
+
+   x86:   initially:  call VG_(machine_get_hwcaps)
+
+          then safe to use VG_(machine_get_VexArchInfo) 
+                       and VG_(machine_x86_have_mxcsr)
+   -------------
+   amd64: initially:  call VG_(machine_get_hwcaps)
+
+          then safe to use VG_(machine_get_VexArchInfo) 
+   -------------
+   ppc32: initially:  call VG_(machine_get_hwcaps)
+                      call VG_(machine_ppc32_set_clszB)
+
+          then safe to use VG_(machine_get_VexArchInfo) 
+                       and VG_(machine_ppc32_has_FPU)
+                       and VG_(machine_ppc32_has_VMX)
+
+   VG_(machine_get_hwcaps) may use signals (although it attempts to
+   leave signal state unchanged) and therefore should only be
+   called before m_main sets up the client's signal state.
+*/
+
+/* Determine what insn set and insn set variant the host has, and
+   record it.  To be called once at system startup.  Returns False if
+   this a CPU incapable of running Valgrind. */
+extern Bool VG_(machine_get_hwcaps)( void );
 
+/* Fetch host cpu info, as per above comment. */
+extern void VG_(machine_get_VexArchInfo)( /*OUT*/VexArch*,
+                                          /*OUT*/VexArchInfo* );
+
+/* Notify host cpu cache line size, as per above comment. */
 #if defined(VGA_ppc32)
-// PPC: what is the cache line size (for dcbz etc) ?
-// This info is harvested on Linux at startup from the AT_SYSINFO
-// entries.
-extern Int VG_(cache_line_size_ppc32);
-// Altivec enabled?  Harvested on startup from the AT_HWCAP entry
-extern Int VG_(have_altivec_ppc32);
+extern void VG_(machine_ppc32_set_clszB)( Int );
 #endif
 
-// X86: set to 1 if the host is able to do {ld,st}mxcsr (load/store
-// the SSE control/status register. 
+/* X86: set to 1 if the host is able to do {ld,st}mxcsr (load/store
+   the SSE control/status register), else zero.  Is referenced from
+   assembly code, so do not change from a 32-bit int. */
 #if defined(VGA_x86)
-extern Int VG_(have_mxcsr_x86);
+extern UInt VG_(machine_x86_have_mxcsr);
+#endif
+
+/* PPC32: set to 1 if FP instructions are supported in user-space,
+   else 0.  Is referenced from assembly code, so do not change from a
+   32-bit int. */
+#if defined(VGA_ppc32)
+extern UInt VG_(machine_ppc32_has_FPU);
 #endif
 
+/* PPC32: set to 1 if Altivec instructions are supported in
+   user-space, else 0.  Is referenced from assembly code, so do not
+   change from a 32-bit int. */
+#if defined(VGA_ppc32)
+extern UInt VG_(machine_ppc32_has_VMX);
+#endif
 
 #endif   // __PUB_CORE_MACHINE_H