m_machine.c revision 2c36d4285afacafc10232e2f70978e0519216138
1 2/*--------------------------------------------------------------------*/ 3/*--- Machine-related stuff. m_machine.c ---*/ 4/*--------------------------------------------------------------------*/ 5 6/* 7 This file is part of Valgrind, a dynamic binary instrumentation 8 framework. 9 10 Copyright (C) 2000-2005 Julian Seward 11 jseward@acm.org 12 13 This program is free software; you can redistribute it and/or 14 modify it under the terms of the GNU General Public License as 15 published by the Free Software Foundation; either version 2 of the 16 License, or (at your option) any later version. 17 18 This program is distributed in the hope that it will be useful, but 19 WITHOUT ANY WARRANTY; without even the implied warranty of 20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 21 General Public License for more details. 22 23 You should have received a copy of the GNU General Public License 24 along with this program; if not, write to the Free Software 25 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 26 02111-1307, USA. 27 28 The GNU General Public License is contained in the file COPYING. 29*/ 30 31#include "pub_core_basics.h" 32#include "pub_core_threadstate.h" 33#include "pub_core_libcassert.h" 34#include "pub_core_libcbase.h" 35#include "pub_core_machine.h" 36#include "pub_core_cpuid.h" 37#include "pub_core_libcsignal.h" // for ppc32 messing with SIGILL 38 39 40#define INSTR_PTR(regs) ((regs).vex.VG_INSTR_PTR) 41#define STACK_PTR(regs) ((regs).vex.VG_STACK_PTR) 42#define FRAME_PTR(regs) ((regs).vex.VG_FRAME_PTR) 43 44Addr VG_(get_SP) ( ThreadId tid ) 45{ 46 return STACK_PTR( VG_(threads)[tid].arch ); 47} 48 49Addr VG_(get_IP) ( ThreadId tid ) 50{ 51 return INSTR_PTR( VG_(threads)[tid].arch ); 52} 53 54Addr VG_(get_FP) ( ThreadId tid ) 55{ 56 return FRAME_PTR( VG_(threads)[tid].arch ); 57} 58 59Addr VG_(get_LR) ( ThreadId tid ) 60{ 61# if defined(VGA_ppc32) 62 return VG_(threads)[tid].arch.vex.guest_LR; 63# elif defined(VGA_x86) || defined(VGA_amd64) 64 return 0; 65# else 66# error "Unknown arch" 67# endif 68} 69 70void VG_(set_SP) ( ThreadId tid, Addr sp ) 71{ 72 STACK_PTR( VG_(threads)[tid].arch ) = sp; 73} 74 75void VG_(set_IP) ( ThreadId tid, Addr ip ) 76{ 77 INSTR_PTR( VG_(threads)[tid].arch ) = ip; 78} 79 80 81void VG_(get_shadow_regs_area) ( ThreadId tid, OffT offset, SizeT size, 82 UChar* area ) 83{ 84 ThreadState* tst; 85 86 vg_assert(VG_(is_valid_tid)(tid)); 87 tst = & VG_(threads)[tid]; 88 89 // Bounds check 90 vg_assert(0 <= offset && offset < sizeof(VexGuestArchState)); 91 vg_assert(offset + size <= sizeof(VexGuestArchState)); 92 93 VG_(memcpy)( area, (void*)(((Addr)&(tst->arch.vex_shadow)) + offset), size); 94} 95 96void VG_(set_shadow_regs_area) ( ThreadId tid, OffT offset, SizeT size, 97 const UChar* area ) 98{ 99 ThreadState* tst; 100 101 vg_assert(VG_(is_valid_tid)(tid)); 102 tst = & VG_(threads)[tid]; 103 104 // Bounds check 105 vg_assert(0 <= offset && offset < sizeof(VexGuestArchState)); 106 vg_assert(offset + size <= sizeof(VexGuestArchState)); 107 108 VG_(memcpy)( (void*)(((Addr)(&tst->arch.vex_shadow)) + offset), area, size); 109} 110 111 112static void apply_to_GPs_of_tid(VexGuestArchState* vex, void (*f)(Addr)) 113{ 114#if defined(VGA_x86) 115 (*f)(vex->guest_EAX); 116 (*f)(vex->guest_ECX); 117 (*f)(vex->guest_EDX); 118 (*f)(vex->guest_EBX); 119 (*f)(vex->guest_ESI); 120 (*f)(vex->guest_EDI); 121 (*f)(vex->guest_ESP); 122 (*f)(vex->guest_EBP); 123#elif defined(VGA_amd64) 124 (*f)(vex->guest_RAX); 125 (*f)(vex->guest_RCX); 126 (*f)(vex->guest_RDX); 127 (*f)(vex->guest_RBX); 128 (*f)(vex->guest_RSI); 129 (*f)(vex->guest_RDI); 130 (*f)(vex->guest_RSP); 131 (*f)(vex->guest_RBP); 132 (*f)(vex->guest_R8); 133 (*f)(vex->guest_R9); 134 (*f)(vex->guest_R10); 135 (*f)(vex->guest_R11); 136 (*f)(vex->guest_R12); 137 (*f)(vex->guest_R13); 138 (*f)(vex->guest_R14); 139 (*f)(vex->guest_R15); 140#elif defined(VGA_ppc32) 141 /* XXX ask tool about validity? */ 142 (*f)(vex->guest_GPR0); 143 (*f)(vex->guest_GPR1); 144 (*f)(vex->guest_GPR2); 145 (*f)(vex->guest_GPR3); 146 (*f)(vex->guest_GPR4); 147 (*f)(vex->guest_GPR5); 148 (*f)(vex->guest_GPR6); 149 (*f)(vex->guest_GPR7); 150 (*f)(vex->guest_GPR8); 151 (*f)(vex->guest_GPR9); 152 (*f)(vex->guest_GPR10); 153 (*f)(vex->guest_GPR11); 154 (*f)(vex->guest_GPR12); 155 (*f)(vex->guest_GPR13); 156 (*f)(vex->guest_GPR14); 157 (*f)(vex->guest_GPR15); 158 (*f)(vex->guest_GPR16); 159 (*f)(vex->guest_GPR17); 160 (*f)(vex->guest_GPR18); 161 (*f)(vex->guest_GPR19); 162 (*f)(vex->guest_GPR20); 163 (*f)(vex->guest_GPR21); 164 (*f)(vex->guest_GPR22); 165 (*f)(vex->guest_GPR23); 166 (*f)(vex->guest_GPR24); 167 (*f)(vex->guest_GPR25); 168 (*f)(vex->guest_GPR26); 169 (*f)(vex->guest_GPR27); 170 (*f)(vex->guest_GPR28); 171 (*f)(vex->guest_GPR29); 172 (*f)(vex->guest_GPR30); 173 (*f)(vex->guest_GPR31); 174 (*f)(vex->guest_CTR); 175 (*f)(vex->guest_LR); 176 177#else 178# error Unknown arch 179#endif 180} 181 182 183void VG_(apply_to_GP_regs)(void (*f)(UWord)) 184{ 185 ThreadId tid; 186 187 for (tid = 1; tid < VG_N_THREADS; tid++) { 188 if (VG_(is_valid_tid)(tid)) { 189 ThreadState* tst = VG_(get_ThreadState)(tid); 190 apply_to_GPs_of_tid(&(tst->arch.vex), f); 191 } 192 } 193} 194 195static ThreadId thread_stack_iter = VG_INVALID_THREADID; 196 197void VG_(thread_stack_reset_iter)(void) 198{ 199 thread_stack_iter = 1; 200} 201 202Bool VG_(thread_stack_next)(ThreadId* tid, Addr* stack_min, Addr* stack_max) 203{ 204 ThreadId i; 205 for (i = thread_stack_iter; i < VG_N_THREADS; i++) { 206 if (VG_(threads)[i].status != VgTs_Empty) { 207 *tid = i; 208 *stack_min = VG_(get_SP)(i); 209 *stack_max = VG_(threads)[i].client_stack_highest_word; 210 thread_stack_iter = i + 1; 211 return True; 212 } 213 } 214 return False; 215} 216 217//------------------------------------------------------------- 218/* Details about the capabilities of the underlying (host) CPU. These 219 details are acquired by (1) enquiring with the CPU at startup, or 220 (2) from the AT_SYSINFO entries the kernel gave us (ppc32 cache 221 line size). It's a bit nasty in the sense that there's no obvious 222 way to stop uses of some of this info before it's ready to go. 223 224 Current dependencies are: 225 226 x86: initially: call VG_(machine_get_hwcaps) 227 228 then safe to use VG_(machine_get_VexArchInfo) 229 and VG_(machine_x86_have_mxcsr) 230 ------------- 231 amd64: initially: call VG_(machine_get_hwcaps) 232 233 then safe to use VG_(machine_get_VexArchInfo) 234 ------------- 235 ppc32: initially: call VG_(machine_get_hwcaps) 236 call VG_(machine_ppc32_set_clszB) 237 238 then safe to use VG_(machine_get_VexArchInfo) 239 and VG_(machine_ppc32_has_FP) 240 and VG_(machine_ppc32_has_VMX) 241 242 VG_(machine_get_hwcaps) may use signals (although it attempts to 243 leave signal state unchanged) and therefore should only be 244 called before m_main sets up the client's signal state. 245*/ 246 247/* --------- State --------- */ 248static Bool hwcaps_done = False; 249 250/* --- all archs --- */ 251static VexArch va; 252static VexArchInfo vai; 253 254#if defined(VGA_x86) 255UInt VG_(machine_x86_have_mxcsr) = 0; 256#endif 257#if defined(VGA_ppc32) 258UInt VG_(machine_ppc32_has_FP) = 0; 259UInt VG_(machine_ppc32_has_VMX) = 0; 260#endif 261 262 263/* Determine what insn set and insn set variant the host has, and 264 record it. To be called once at system startup. Returns False if 265 this a CPU incapable of running Valgrind. */ 266 267#if defined(VGA_ppc32) 268#include <setjmp.h> // For jmp_buf 269static jmp_buf env_sigill; 270static void handler_sigill ( Int x ) { __builtin_longjmp(env_sigill,1); } 271#endif 272 273Bool VG_(machine_get_hwcaps)( void ) 274{ 275 vg_assert(hwcaps_done == False); 276 hwcaps_done = True; 277 278 // Whack default settings into vai, so that we only need to fill in 279 // any interesting bits. 280 LibVEX_default_VexArchInfo(&vai); 281 282#if defined(VGA_x86) 283 { Bool have_sse1, have_sse2; 284 UInt eax, ebx, ecx, edx; 285 286 if (!VG_(has_cpuid)()) 287 /* we can't do cpuid at all. Give up. */ 288 return False; 289 290 VG_(cpuid)(0, &eax, &ebx, &ecx, &edx); 291 if (eax < 1) 292 /* we can't ask for cpuid(x) for x > 0. Give up. */ 293 return False; 294 295 /* get capabilities bits into edx */ 296 VG_(cpuid)(1, &eax, &ebx, &ecx, &edx); 297 298 have_sse1 = (edx & (1<<25)) != 0; /* True => have sse insns */ 299 have_sse2 = (edx & (1<<26)) != 0; /* True => have sse2 insns */ 300 301 if (have_sse2 && have_sse1) { 302 va = VexArchX86; 303 vai.subarch = VexSubArchX86_sse2; 304 VG_(machine_x86_have_mxcsr) = 1; 305 return True; 306 } 307 308 if (have_sse1) { 309 va = VexArchX86; 310 vai.subarch = VexSubArchX86_sse1; 311 VG_(machine_x86_have_mxcsr) = 1; 312 return True; 313 } 314 315 va = VexArchX86; 316 vai.subarch = VexSubArchX86_sse0; 317 VG_(machine_x86_have_mxcsr) = 0; 318 return True; 319 } 320 321#elif defined(VGA_amd64) 322 vg_assert(VG_(has_cpuid)()); 323 va = VexArchAMD64; 324 vai.subarch = VexSubArch_NONE; 325 return True; 326 327#elif defined(VGA_ppc32) 328 { /* ppc32 doesn't seem to have a sane way to find out what insn 329 sets the CPU supports. So we have to arse around with 330 SIGILLs. Yuck. */ 331 vki_sigset_t saved_set, tmp_set; 332 struct vki_sigaction saved_act, tmp_act; 333 334 volatile Bool have_fp, have_vmx; 335 336 VG_(sigemptyset)(&tmp_set); 337 VG_(sigaddset)(&tmp_set, VKI_SIGILL); 338 339 VG_(sigprocmask)(VKI_SIG_UNBLOCK, &tmp_set, &saved_set); 340 341 VG_(sigaction)(VKI_SIGILL, NULL, &saved_act); 342 tmp_act = saved_act; 343 344 tmp_act.sa_flags &= ~VKI_SA_RESETHAND; 345 tmp_act.sa_flags &= ~VKI_SA_SIGINFO; 346 347 tmp_act.ksa_handler = handler_sigill; 348 VG_(sigaction)(VKI_SIGILL, &tmp_act, NULL); 349 350 have_fp = True; 351 if (__builtin_setjmp(env_sigill)) { 352 have_fp = False; 353 } else { 354 __asm__ __volatile__("fmr 0,0"); 355 } 356 357 tmp_act.ksa_handler = handler_sigill; 358 VG_(sigaction)(VKI_SIGILL, &tmp_act, NULL); 359 360 have_vmx = True; 361 if (__builtin_setjmp(env_sigill)) { 362 have_vmx = False; 363 } else { 364 __asm__ __volatile__("vor 0,0,0"); 365 } 366 367 VG_(sigaction)(VKI_SIGILL, &saved_act, NULL); 368 VG_(sigprocmask)(VKI_SIG_SETMASK, &saved_set, NULL); 369 370 /* VG_(printf)("FP %d VMX %d\n", (Int)have_fp, (Int)have_vmx); */ 371 372 /* We can only support 3 cases, not 4 (vmx but no fp). So make 373 fp a prerequisite for vmx. */ 374 if (have_vmx && !have_fp) 375 have_vmx = False; 376 377 VG_(machine_ppc32_has_FP) = have_fp ? 1 : 0; 378 VG_(machine_ppc32_has_VMX) = have_vmx ? 1 : 0; 379 380 va = VexArchPPC32; 381 382 if (have_fp == False && have_vmx == False) { 383 vai.subarch = VexSubArchPPC32_I; 384 } 385 else if (have_fp == True && have_vmx == False) { 386 vai.subarch = VexSubArchPPC32_FI; 387 } 388 else if (have_fp == True && have_vmx == True) { 389 vai.subarch = VexSubArchPPC32_VFI; 390 } else { 391 /* this can't happen. */ 392 vg_assert2(0, "VG_(machine_get_hwcaps)(ppc32)"); 393 } 394 395 /* But we're not done yet: VG_(machine_ppc32_set_clszB) must be 396 called before we're ready to go. */ 397 return True; 398 } 399 400#else 401# error "Unknown arch" 402#endif 403} 404 405/* Notify host cpu cache line size, as per above comment. */ 406#if defined(VGA_ppc32) 407void VG_(machine_ppc32_set_clszB)( Int szB ) 408{ 409 vg_assert(hwcaps_done); 410 411 /* Either the value must not have been set yet (zero) or we can 412 tolerate it being set to the same value multiple times, as the 413 stack scanning logic in m_main is a bit stupid. */ 414 vg_assert(vai.ppc32_cache_line_szB == 0 415 || vai.ppc32_cache_line_szB == szB); 416 417 vg_assert(szB == 32 || szB == 128); 418 vai.ppc32_cache_line_szB = szB; 419} 420#endif 421 422 423/* Fetch host cpu info, once established. */ 424void VG_(machine_get_VexArchInfo)( /*OUT*/VexArch* pVa, 425 /*OUT*/VexArchInfo* pVai ) 426{ 427 vg_assert(hwcaps_done); 428 if (pVa) *pVa = va; 429 if (pVai) *pVai = vai; 430} 431 432 433/*--------------------------------------------------------------------*/ 434/*--- end ---*/ 435/*--------------------------------------------------------------------*/ 436