From: Julian Seward Date: Sun, 13 Nov 2005 00:30:22 +0000 (+0000) Subject: Hook the ppc32 stuff up to the revised CPU detection machinery, and X-Git-Tag: svn/VALGRIND_3_1_0~124 X-Git-Url: http://git.ipfire.org/?a=commitdiff_plain;h=77a40e255614af11a3e7988f461a95a7d3a59c3c;p=thirdparty%2Fvalgrind.git Hook the ppc32 stuff up to the revised CPU detection machinery, and add a bunch of code to detect what the cpu can do at startup by catching SIGILLs. Shame PPC doesn't offer any sane mechanism for finding out what instruction subsets the CPU is capable of (a la x86/amd64 cpuid). git-svn-id: svn://svn.valgrind.org/valgrind/trunk@5108 --- diff --git a/coregrind/m_dispatch/dispatch-ppc32-linux.S b/coregrind/m_dispatch/dispatch-ppc32-linux.S index 6a34f0b5a8..e956a37759 100644 --- a/coregrind/m_dispatch/dispatch-ppc32-linux.S +++ b/coregrind/m_dispatch/dispatch-ppc32-linux.S @@ -178,8 +178,8 @@ VG_(run_innerloop): /* set host AltiVec control word to the default mode expected by VEX-generated code. */ - lis 3,VG_(have_altivec_ppc32)@ha - lwz 3,VG_(have_altivec_ppc32)@l(3) + lis 3,VG_(machine_ppc32_has_VMX)@ha + lwz 3,VG_(machine_ppc32_has_VMX)@l(3) cmplwi 3,0 beq L1 /* generate vector {0x0,0x0,0x0,0x00010000} */ diff --git a/coregrind/m_machine.c b/coregrind/m_machine.c index c0342533f4..be3e0d2838 100644 --- a/coregrind/m_machine.c +++ b/coregrind/m_machine.c @@ -34,6 +34,8 @@ #include "pub_core_libcbase.h" #include "pub_core_machine.h" #include "pub_core_cpuid.h" +#include "pub_core_libcsignal.h" // for ppc32 messing with SIGILL + #define INSTR_PTR(regs) ((regs).vex.VG_INSTR_PTR) #define STACK_PTR(regs) ((regs).vex.VG_STACK_PTR) @@ -262,6 +264,12 @@ UInt VG_(machine_ppc32_has_VMX) = 0; record it. To be called once at system startup. Returns False if this a CPU incapable of running Valgrind. */ +#if defined(VGA_ppc32) +#include // For jmp_buf +static jmp_buf env_sigill; +static void handler_sigill ( Int x ) { __builtin_longjmp(env_sigill,1); } +#endif + Bool VG_(machine_get_hwcaps)( void ) { vg_assert(hwcaps_done == False); @@ -317,25 +325,108 @@ Bool VG_(machine_get_hwcaps)( void ) 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; + { /* ppc32 doesn't seem to have a sane way to find out what insn + sets the CPU supports. So we have to arse around with + SIGILLs. Yuck. */ + vki_sigset_t saved_set, tmp_set; + struct vki_sigaction saved_act, tmp_act; + + Bool have_fp, have_vmx; + + VG_(sigemptyset)(&tmp_set); + VG_(sigaddset)(&tmp_set, VKI_SIGILL); + + VG_(sigprocmask)(VKI_SIG_UNBLOCK, &tmp_set, &saved_set); + + VG_(sigaction)(VKI_SIGILL, NULL, &saved_act); + tmp_act = saved_act; + + tmp_act.sa_flags &= ~VKI_SA_RESETHAND; + tmp_act.sa_flags &= ~VKI_SA_SIGINFO; + + tmp_act.ksa_handler = handler_sigill; + VG_(sigaction)(VKI_SIGILL, &tmp_act, NULL); + + have_fp = True; + if (__builtin_setjmp(env_sigill)) { + have_fp = False; + } else { + __asm__ __volatile__("fmr 0,0"); + } + + tmp_act.ksa_handler = handler_sigill; + VG_(sigaction)(VKI_SIGILL, &tmp_act, NULL); + + have_vmx = True; + if (__builtin_setjmp(env_sigill)) { + have_vmx = False; + } else { + __asm__ __volatile__("vor 0,0,0"); + } + + VG_(sigaction)(VKI_SIGILL, &saved_act, NULL); + VG_(sigprocmask)(VKI_SIG_SETMASK, &saved_set, NULL); + + /* VG_(printf)("FP %d VMX %d\n", (Int)have_fp, (Int)have_vmx); */ + + /* We can only support 3 cases, not 4 (vmx but no fp). So make + fp a prerequisite for vmx. */ + if (have_vmx && !have_fp) + have_vmx = False; + + VG_(machine_ppc32_has_FPU) = have_fp ? 1 : 0; + VG_(machine_ppc32_has_VMX) = have_vmx ? 1 : 0; + + va = VexArchPPC32; + + if (have_fp == False && have_vmx == False) { + vai.subarch = VexSubArchPPC32_noAV; // _I + } + else if (have_fp == True && have_vmx == False) { + vai.subarch = VexSubArchPPC32_noAV; // _FI + } + else if (have_fp == True && have_vmx == True) { + vai.subarch = VexSubArchPPC32_AV; // _VFI + } else { + /* this can't happen. */ + vg_assert2(0, "VG_(machine_get_hwcaps)(ppc32)"); + } + + /* 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 } +/* Notify host cpu cache line size, as per above comment. */ +#if defined(VGA_ppc32) +void VG_(machine_ppc32_set_clszB)( Int szB ) +{ + vg_assert(hwcaps_done); + + /* Either the value must not have been set yet (zero) or we can + tolerate it being set to the same value multiple times, as the + stack scanning logic in m_main is a bit stupid. */ + vg_assert(vai.ppc32_cache_line_szB == 0 + || vai.ppc32_cache_line_szB == szB); + + vg_assert(szB == 32 || szB == 128); + vai.ppc32_cache_line_szB = szB; +} +#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; + if (pVa) *pVa = va; + if (pVai) *pVai = vai; } diff --git a/coregrind/m_main.c b/coregrind/m_main.c index 5423ce2561..795fd0be0c 100644 --- a/coregrind/m_main.c +++ b/coregrind/m_main.c @@ -545,15 +545,6 @@ Addr setup_client_stack( void* init_sp, break; case AT_HWCAP: -# if defined(VGP_ppc32_linux) - /* Acquire altivecness info */ - VG_(debugLog)(2, "main", "PPC32 hwcaps: 0x%x\n", - (UInt)auxv->u.a_val); - if (auxv->u.a_val & 0x10000000) - VG_(have_altivec_ppc32) = 1; - VG_(debugLog)(2, "main", "PPC32 AltiVec support: %u\n", - VG_(have_altivec_ppc32)); -# endif break; case AT_DCACHEBSIZE: @@ -562,7 +553,7 @@ Addr setup_client_stack( void* init_sp, # if defined(VGP_ppc32_linux) /* acquire cache info */ if (auxv->u.a_val > 0) { - VG_(cache_line_size_ppc32) = auxv->u.a_val; + VG_(machine_ppc32_set_clszB)( auxv->u.a_val ); VG_(debugLog)(2, "main", "PPC32 cache line size %u (type %u)\n", (UInt)auxv->u.a_val, (UInt)auxv->a_type ); diff --git a/coregrind/m_transtab.c b/coregrind/m_transtab.c index 9e99da3b53..bf57d09f66 100644 --- a/coregrind/m_transtab.c +++ b/coregrind/m_transtab.c @@ -737,8 +737,12 @@ static void invalidate_icache ( void *ptr, Int nbytes ) # if defined(VGA_ppc32) Addr startaddr = (Addr) ptr; Addr endaddr = startaddr + nbytes; - Addr cls = VG_(cache_line_size_ppc32); + Addr cls; Addr addr; + VexArchInfo vai; + + VG_(machine_get_VexArchInfo)( NULL, &vai ); + cls = vai.ppc32_cache_line_szB; /* Stay sane .. */ vg_assert(cls == 32 || cls == 128);