|
From: <sv...@va...> - 2005-11-12 23:10:51
|
Author: sewardj
Date: 2005-11-12 23:10:48 +0000 (Sat, 12 Nov 2005)
New Revision: 5104
Log:
Tidy up the machinery for detecting the CPU type and capabilities.
Move it from m_translate to m_machine, which is a more appropriate
place for it.
Modified:
trunk/coregrind/m_dispatch/dispatch-x86-linux.S
trunk/coregrind/m_machine.c
trunk/coregrind/m_main.c
trunk/coregrind/m_translate.c
trunk/coregrind/pub_core_machine.h
Modified: trunk/coregrind/m_dispatch/dispatch-x86-linux.S
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/m_dispatch/dispatch-x86-linux.S 2005-11-12 21:57:09 U=
TC (rev 5103)
+++ trunk/coregrind/m_dispatch/dispatch-x86-linux.S 2005-11-12 23:10:48 U=
TC (rev 5104)
@@ -71,7 +71,7 @@
=09
/* set host SSE control word to the default mode expected=20
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 @@
%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)
+#endif
+ cmpl $0, VG_(machine_x86_have_mxcsr)
jz L2
-#endif
pushl $0
stmxcsr (%esp)
andl $0xFFFFFFC0, (%esp) /* mask out status flags */
Modified: trunk/coregrind/m_machine.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/m_machine.c 2005-11-12 21:57:09 UTC (rev 5103)
+++ trunk/coregrind/m_machine.c 2005-11-12 23:10:48 UTC (rev 5104)
@@ -33,6 +33,7 @@
#include "pub_core_libcassert.h"
#include "pub_core_libcbase.h"
#include "pub_core_machine.h"
+#include "pub_core_cpuid.h"
=20
#define INSTR_PTR(regs) ((regs).vex.VG_INSTR_PTR)
#define STACK_PTR(regs) ((regs).vex.VG_STACK_PTR)
@@ -211,38 +212,133 @@
return False;
}
=20
-//////////////////////////////////////////////////////////////////
-// 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.
=20
-#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) =3D 0;
+ Current dependencies are:
=20
-/* Altivec enabled? Harvested on startup from the AT_HWCAP entry. */
-Int VG_(have_altivec_ppc32) =3D 0;
+ x86: initially: call VG_(machine_get_hwcaps)
+
+ then safe to use VG_(machine_get_VexArchInfo)=20
+ and VG_(machine_x86_have_mxcsr)
+ -------------
+ amd64: initially: call VG_(machine_get_hwcaps)
+
+ then safe to use VG_(machine_get_VexArchInfo)=20
+ -------------
+ ppc32: initially: call VG_(machine_get_hwcaps)
+ call VG_(machine_ppc32_set_clszB)
+
+ then safe to use VG_(machine_get_VexArchInfo)=20
+ 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.
+*/
+
+/* --------- State --------- */
+static Bool hwcaps_done =3D False;
+
+/* --- all archs --- */
+static VexArch va;
+static VexArchInfo vai;
+
+#if defined(VGA_x86)
+UInt VG_(machine_x86_have_mxcsr) =3D 0;
#endif
+#if defined(VGA_ppc32)
+UInt VG_(machine_ppc32_has_FPU) =3D 0;
+UInt VG_(machine_ppc32_has_VMX) =3D 0;
+#endif
=20
=20
+/* 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 =3D=3D False);
+ hwcaps_done =3D 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.
+ { Bool have_sse1, have_sse2;
+ UInt eax, ebx, ecx, edx;
=20
- 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) =3D 0;
+ 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 =3D (edx & (1<<25)) !=3D 0; /* True =3D> have sse insns *=
/
+ have_sse2 =3D (edx & (1<<26)) !=3D 0; /* True =3D> have sse2 insns =
*/
+
+ if (have_sse2 && have_sse1) {
+ va =3D VexArchX86;
+ vai.subarch =3D VexSubArchX86_sse2;
+ VG_(machine_x86_have_mxcsr) =3D 1;
+ return True;
+ }
+
+ if (have_sse1) {
+ va =3D VexArchX86;
+ vai.subarch =3D VexSubArchX86_sse1;
+ VG_(machine_x86_have_mxcsr) =3D 1;
+ return True;
+ }
+
+ va =3D VexArchX86;
+ vai.subarch =3D VexSubArchX86_sse0;
+ VG_(machine_x86_have_mxcsr) =3D 0;
+ return True;
+ }
+
+#elif defined(VGA_amd64)
+ vg_assert(VG_(has_cpuid)());
+ va =3D VexArchAMD64;
+ vai.subarch =3D VexSubArch_NONE;
+ return True;
+
+#elif defined(VGA_ppc32)
+ va =3D VexArchPPC32;
+ vai.subarch =3D 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
+}
=20
=20
+/* Fetch host cpu info, once established. */
+void VG_(machine_get_VexArchInfo)( /*OUT*/VexArch* pVa,
+ /*OUT*/VexArchInfo* pVai )
+{
+ vg_assert(hwcaps_done);
+ *pVa =3D va;
+ *pVai =3D vai;
+}
+
+
/*--------------------------------------------------------------------*/
/*--- end ---*/
/*--------------------------------------------------------------------*/
Modified: trunk/coregrind/m_main.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/m_main.c 2005-11-12 21:57:09 UTC (rev 5103)
+++ trunk/coregrind/m_main.c 2005-11-12 23:10:48 UTC (rev 5104)
@@ -2033,6 +2033,30 @@
// Get the current process stack rlimit.
VG_(getrlimit)(VKI_RLIMIT_STACK, &VG_(client_rlimit_stack));
=20
+ //--------------------------------------------------------------
+ // Figure out what sort of CPU we're on, and whether it is=20
+ // able to run V.
+ VG_(debugLog)(1, "main", "Get hardware capabilities ...\n");
+ { VexArch vex_arch;
+ VexArchInfo vex_archinfo;
+ Bool ok =3D 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 =3D %s, subarch =3D %s\n",
+ LibVEX_ppVexArch ( vex_arch ),
+ LibVEX_ppVexSubArch( vex_archinfo.subarch ) );
+ }
+
//=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
// Command line argument handling order:
// * If --help/--help-debug are present, show usage message=20
Modified: trunk/coregrind/m_translate.c
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/m_translate.c 2005-11-12 21:57:09 UTC (rev 5103)
+++ trunk/coregrind/m_translate.c 2005-11-12 23:10:48 UTC (rev 5104)
@@ -31,11 +31,9 @@
=20
#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"
@@ -53,81 +51,6 @@
=20
=20
/*------------------------------------------------------------*/
-/*--- 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,=20
- /*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 =3D (edx & (1<<25)) !=3D 0; /* True =3D> have sse insns *=
/
- have_sse2 =3D (edx & (1<<26)) !=3D 0; /* True =3D> have sse2 insns =
*/
-
- VG_(have_mxcsr_x86) =3D 1;
-
- if (have_sse2 && have_sse1) {
- *vex_arch =3D VexArchX86;
- vai->subarch =3D VexSubArchX86_sse2;
- return True;
- }
-
- if (have_sse1) {
- *vex_arch =3D VexArchX86;
- vai->subarch =3D VexSubArchX86_sse1;
- return True;
- }
-
- {
- *vex_arch =3D VexArchX86;
- vai->subarch =3D VexSubArchX86_sse0;
- VG_(have_mxcsr_x86) =3D 0;
- return True;
- }
- }
-
-#elif defined(VGA_amd64)
- vg_assert(VG_(has_cpuid)());
- *vex_arch =3D VexArchAMD64;
- vai->subarch =3D VexSubArch_NONE;
- return True;
-
-#elif defined(VGA_ppc32)
- *vex_arch =3D VexArchPPC32;
- vai->subarch =3D VG_(have_altivec_ppc32) ? VexSubArchPPC32_AV
- : VexSubArchPPC32_noAV;
- vai->ppc32_cache_line_szB =3D VG_(cache_line_size_ppc32);
- return True;
-
-#else
-# error Unknown architecture
-#endif
-}
-
-
-/*------------------------------------------------------------*/
/*--- %SP-update pass ---*/
/*------------------------------------------------------------*/
=20
@@ -524,42 +447,21 @@
Int debugging_verbosity,
ULong bbs_done )
{
- Addr64 redir, orig_addr_noredir =3D orig_addr;
- Int tmpbuf_used, verbosity, i;
- Bool notrace_until_done, do_self_check;
- UInt notrace_until_limit =3D 0;
- NSegment* seg;
- VexGuestExtents vge;
+ Addr64 redir, orig_addr_noredir =3D orig_addr;
+ Int tmpbuf_used, verbosity, i;
+ Bool notrace_until_done, do_self_check;
+ UInt notrace_until_limit =3D 0;
+ NSegment* seg;
+ VexArch vex_arch;
+ VexArchInfo vex_archinfo;
+ VexGuestExtents vge;
+ VexTranslateResult tres;
=20
- /* Indicates what arch we are running on, and other important info
- (subarch variant, cache line size). */
- static VexArchInfo vex_archinfo;
- static VexArch vex_arch =3D VexArch_INVALID;
-
/* Make sure Vex is initialised right. */
- VexTranslateResult tres;
+
static Bool vex_init_done =3D False;
=20
if (!vex_init_done) {
- Bool ok =3D 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,=20
- "Host CPU: arch =3D %s, subarch =3D %s",
- LibVEX_ppVexArch ( vex_arch ),
- LibVEX_ppVexSubArch( vex_archinfo.subarch ) );
- }
-
LibVEX_Init ( &failure_exit, &log_bytes,=20
1, /* debug_paranoia */=20
False, /* valgrind support */
@@ -664,10 +566,13 @@
=20
VGP_PUSHCC(VgpVexTime);
=20
- /* Actually do the translation. */
+ /* ------ Actually do the translation. ------ */
tl_assert2(VG_(tdict).tool_instrument,
"you forgot to set VgToolInterface function 'tool_instrume=
nt'");
=20
+ /* 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 =3D tid;
=20
Modified: trunk/coregrind/pub_core_machine.h
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=
=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D=3D
--- trunk/coregrind/pub_core_machine.h 2005-11-12 21:57:09 UTC (rev 5103)
+++ trunk/coregrind/pub_core_machine.h 2005-11-12 23:10:48 UTC (rev 5104)
@@ -76,24 +76,71 @@
#define VG_O_STACK_PTR (offsetof(VexGuestArchState, VG_STACK_PTR)=
)
=20
=20
-// 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.
=20
+ Current dependencies are:
+
+ x86: initially: call VG_(machine_get_hwcaps)
+
+ then safe to use VG_(machine_get_VexArchInfo)=20
+ and VG_(machine_x86_have_mxcsr)
+ -------------
+ amd64: initially: call VG_(machine_get_hwcaps)
+
+ then safe to use VG_(machine_get_VexArchInfo)=20
+ -------------
+ ppc32: initially: call VG_(machine_get_hwcaps)
+ call VG_(machine_ppc32_set_clszB)
+
+ then safe to use VG_(machine_get_VexArchInfo)=20
+ 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
=20
-// X86: set to 1 if the host is able to do {ld,st}mxcsr (load/store
-// the SSE control/status register.=20
+/* 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
=20
+/* 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
=20
+/* 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
=20
/*--------------------------------------------------------------------*/
|