blob: 482a1f3354d61cd5b73cc290988fc9432ef5e64e [file] [log] [blame]
njnf536bbb2005-06-13 04:21:38 +00001
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
njnc7561b92005-06-19 01:24:32 +000031#include "pub_core_basics.h"
32#include "pub_core_threadstate.h"
njnf536bbb2005-06-13 04:21:38 +000033#include "pub_core_libcassert.h"
34#include "pub_core_libcbase.h"
35#include "pub_core_machine.h"
sewardje2d1e672005-11-12 23:10:48 +000036#include "pub_core_cpuid.h"
sewardje3826cf2005-11-13 00:30:22 +000037#include "pub_core_libcsignal.h" // for ppc32 messing with SIGILL
38
njnf536bbb2005-06-13 04:21:38 +000039
njnaf839f52005-06-23 03:27:57 +000040#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)
njnf536bbb2005-06-13 04:21:38 +000043
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
sewardjacaec5f2005-08-19 16:02:59 +000059Addr VG_(get_LR) ( ThreadId tid )
60{
sewardj2c48c7b2005-11-29 13:05:56 +000061# if defined(VGA_ppc32) || defined(VGA_ppc64)
sewardjacaec5f2005-08-19 16:02:59 +000062 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
njnf536bbb2005-06-13 04:21:38 +000070void 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
njn6ace3ea2005-06-17 03:06:27 +0000112static 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);
sewardj2c48c7b2005-11-29 13:05:56 +0000140#elif defined(VGA_ppc32) || defined(VGA_ppc64)
cerion85665ca2005-06-20 15:51:07 +0000141 /* 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
njn6ace3ea2005-06-17 03:06:27 +0000177#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
njn1d0cb0d2005-08-15 01:52:02 +0000195static ThreadId thread_stack_iter = VG_INVALID_THREADID;
196
197void VG_(thread_stack_reset_iter)(void)
njnb506bd82005-06-21 04:01:51 +0000198{
njn1d0cb0d2005-08-15 01:52:02 +0000199 thread_stack_iter = 1;
njnb506bd82005-06-21 04:01:51 +0000200}
njn6ace3ea2005-06-17 03:06:27 +0000201
njn1d0cb0d2005-08-15 01:52:02 +0000202Bool 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}
sewardj7821e2e2005-08-08 00:35:46 +0000216
sewardje2d1e672005-11-12 23:10:48 +0000217//-------------------------------------------------------------
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.
sewardj10f08cf2005-06-29 10:16:14 +0000223
sewardje2d1e672005-11-12 23:10:48 +0000224 Current dependencies are:
sewardja48a4932005-09-29 11:09:56 +0000225
sewardje2d1e672005-11-12 23:10:48 +0000226 x86: initially: call VG_(machine_get_hwcaps)
sewardj10f08cf2005-06-29 10:16:14 +0000227
sewardje2d1e672005-11-12 23:10:48 +0000228 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)
sewardj2c36d422005-11-13 01:59:22 +0000239 and VG_(machine_ppc32_has_FP)
sewardje2d1e672005-11-12 23:10:48 +0000240 and VG_(machine_ppc32_has_VMX)
cerion1f0d8142005-12-23 00:57:03 +0000241 -------------
242 ppc64: initially: call VG_(machine_get_hwcaps)
243 call VG_(machine_ppc64_set_clszB)
244
245 then safe to use VG_(machine_get_VexArchInfo)
246 and VG_(machine_ppc64_has_VMX)
sewardje2d1e672005-11-12 23:10:48 +0000247
248 VG_(machine_get_hwcaps) may use signals (although it attempts to
249 leave signal state unchanged) and therefore should only be
250 called before m_main sets up the client's signal state.
251*/
252
253/* --------- State --------- */
254static Bool hwcaps_done = False;
255
256/* --- all archs --- */
257static VexArch va;
258static VexArchInfo vai;
sewardja48a4932005-09-29 11:09:56 +0000259
sewardj7821e2e2005-08-08 00:35:46 +0000260#if defined(VGA_x86)
sewardje2d1e672005-11-12 23:10:48 +0000261UInt VG_(machine_x86_have_mxcsr) = 0;
sewardj7821e2e2005-08-08 00:35:46 +0000262#endif
sewardje2d1e672005-11-12 23:10:48 +0000263#if defined(VGA_ppc32)
sewardj2c36d422005-11-13 01:59:22 +0000264UInt VG_(machine_ppc32_has_FP) = 0;
sewardje2d1e672005-11-12 23:10:48 +0000265UInt VG_(machine_ppc32_has_VMX) = 0;
266#endif
sewardj2c48c7b2005-11-29 13:05:56 +0000267#if defined(VGA_ppc64)
268ULong VG_(machine_ppc64_has_VMX) = 0;
269#endif
sewardje2d1e672005-11-12 23:10:48 +0000270
271
272/* Determine what insn set and insn set variant the host has, and
273 record it. To be called once at system startup. Returns False if
274 this a CPU incapable of running Valgrind. */
275
sewardj2c48c7b2005-11-29 13:05:56 +0000276#if defined(VGA_ppc32) || defined(VGA_ppc64)
sewardje3826cf2005-11-13 00:30:22 +0000277#include <setjmp.h> // For jmp_buf
278static jmp_buf env_sigill;
279static void handler_sigill ( Int x ) { __builtin_longjmp(env_sigill,1); }
280#endif
281
sewardje2d1e672005-11-12 23:10:48 +0000282Bool VG_(machine_get_hwcaps)( void )
283{
284 vg_assert(hwcaps_done == False);
285 hwcaps_done = True;
286
287 // Whack default settings into vai, so that we only need to fill in
288 // any interesting bits.
289 LibVEX_default_VexArchInfo(&vai);
290
291#if defined(VGA_x86)
292 { Bool have_sse1, have_sse2;
293 UInt eax, ebx, ecx, edx;
294
295 if (!VG_(has_cpuid)())
296 /* we can't do cpuid at all. Give up. */
297 return False;
298
299 VG_(cpuid)(0, &eax, &ebx, &ecx, &edx);
300 if (eax < 1)
301 /* we can't ask for cpuid(x) for x > 0. Give up. */
302 return False;
303
304 /* get capabilities bits into edx */
305 VG_(cpuid)(1, &eax, &ebx, &ecx, &edx);
306
307 have_sse1 = (edx & (1<<25)) != 0; /* True => have sse insns */
308 have_sse2 = (edx & (1<<26)) != 0; /* True => have sse2 insns */
309
310 if (have_sse2 && have_sse1) {
311 va = VexArchX86;
312 vai.subarch = VexSubArchX86_sse2;
313 VG_(machine_x86_have_mxcsr) = 1;
314 return True;
315 }
316
317 if (have_sse1) {
318 va = VexArchX86;
319 vai.subarch = VexSubArchX86_sse1;
320 VG_(machine_x86_have_mxcsr) = 1;
321 return True;
322 }
323
324 va = VexArchX86;
325 vai.subarch = VexSubArchX86_sse0;
326 VG_(machine_x86_have_mxcsr) = 0;
327 return True;
328 }
329
330#elif defined(VGA_amd64)
331 vg_assert(VG_(has_cpuid)());
332 va = VexArchAMD64;
333 vai.subarch = VexSubArch_NONE;
334 return True;
335
336#elif defined(VGA_ppc32)
sewardje3826cf2005-11-13 00:30:22 +0000337 { /* ppc32 doesn't seem to have a sane way to find out what insn
338 sets the CPU supports. So we have to arse around with
339 SIGILLs. Yuck. */
340 vki_sigset_t saved_set, tmp_set;
341 struct vki_sigaction saved_act, tmp_act;
342
sewardj2c36d422005-11-13 01:59:22 +0000343 volatile Bool have_fp, have_vmx;
sewardje3826cf2005-11-13 00:30:22 +0000344
345 VG_(sigemptyset)(&tmp_set);
346 VG_(sigaddset)(&tmp_set, VKI_SIGILL);
347
348 VG_(sigprocmask)(VKI_SIG_UNBLOCK, &tmp_set, &saved_set);
349
350 VG_(sigaction)(VKI_SIGILL, NULL, &saved_act);
351 tmp_act = saved_act;
352
353 tmp_act.sa_flags &= ~VKI_SA_RESETHAND;
354 tmp_act.sa_flags &= ~VKI_SA_SIGINFO;
355
356 tmp_act.ksa_handler = handler_sigill;
357 VG_(sigaction)(VKI_SIGILL, &tmp_act, NULL);
358
359 have_fp = True;
360 if (__builtin_setjmp(env_sigill)) {
361 have_fp = False;
362 } else {
363 __asm__ __volatile__("fmr 0,0");
364 }
365
366 tmp_act.ksa_handler = handler_sigill;
367 VG_(sigaction)(VKI_SIGILL, &tmp_act, NULL);
368
369 have_vmx = True;
370 if (__builtin_setjmp(env_sigill)) {
371 have_vmx = False;
372 } else {
373 __asm__ __volatile__("vor 0,0,0");
374 }
375
376 VG_(sigaction)(VKI_SIGILL, &saved_act, NULL);
377 VG_(sigprocmask)(VKI_SIG_SETMASK, &saved_set, NULL);
378
379 /* VG_(printf)("FP %d VMX %d\n", (Int)have_fp, (Int)have_vmx); */
380
381 /* We can only support 3 cases, not 4 (vmx but no fp). So make
cerion297c88f2005-12-22 15:53:12 +0000382 fp a prerequisite for vmx. */
sewardje3826cf2005-11-13 00:30:22 +0000383 if (have_vmx && !have_fp)
384 have_vmx = False;
385
sewardj2c36d422005-11-13 01:59:22 +0000386 VG_(machine_ppc32_has_FP) = have_fp ? 1 : 0;
sewardje3826cf2005-11-13 00:30:22 +0000387 VG_(machine_ppc32_has_VMX) = have_vmx ? 1 : 0;
388
389 va = VexArchPPC32;
390
391 if (have_fp == False && have_vmx == False) {
sewardj22a787b2005-11-13 00:53:33 +0000392 vai.subarch = VexSubArchPPC32_I;
sewardje3826cf2005-11-13 00:30:22 +0000393 }
394 else if (have_fp == True && have_vmx == False) {
sewardj22a787b2005-11-13 00:53:33 +0000395 vai.subarch = VexSubArchPPC32_FI;
sewardje3826cf2005-11-13 00:30:22 +0000396 }
397 else if (have_fp == True && have_vmx == True) {
sewardj22a787b2005-11-13 00:53:33 +0000398 vai.subarch = VexSubArchPPC32_VFI;
sewardje3826cf2005-11-13 00:30:22 +0000399 } else {
400 /* this can't happen. */
401 vg_assert2(0, "VG_(machine_get_hwcaps)(ppc32)");
402 }
403
404 /* But we're not done yet: VG_(machine_ppc32_set_clszB) must be
405 called before we're ready to go. */
406 return True;
407 }
sewardje2d1e672005-11-12 23:10:48 +0000408
sewardj2c48c7b2005-11-29 13:05:56 +0000409#elif defined(VGA_ppc64)
410 { vki_sigset_t saved_set, tmp_set;
411 struct vki_sigaction saved_act, tmp_act;
412
413 volatile Bool have_vmx;
414
415 VG_(sigemptyset)(&tmp_set);
416 VG_(sigaddset)(&tmp_set, VKI_SIGILL);
417
418 VG_(sigprocmask)(VKI_SIG_UNBLOCK, &tmp_set, &saved_set);
419
420 VG_(sigaction)(VKI_SIGILL, NULL, &saved_act);
421 tmp_act = saved_act;
422
423 tmp_act.sa_flags &= ~VKI_SA_RESETHAND;
424 tmp_act.sa_flags &= ~VKI_SA_SIGINFO;
425
426 tmp_act.ksa_handler = handler_sigill;
427 VG_(sigaction)(VKI_SIGILL, &tmp_act, NULL);
428
429 have_vmx = True;
430 if (__builtin_setjmp(env_sigill)) {
431 have_vmx = False;
432 } else {
433 __asm__ __volatile__("vor 0,0,0");
434 }
435
436 VG_(sigaction)(VKI_SIGILL, &saved_act, NULL);
437 VG_(sigprocmask)(VKI_SIG_SETMASK, &saved_set, NULL);
438
439 /* VG_(printf)("VMX %d\n", (Int)have_vmx); */
440
441 VG_(machine_ppc64_has_VMX) = have_vmx ? 1 : 0;
442
443 va = VexArchPPC64;
444 vai.subarch = have_vmx ? VexSubArchPPC64_VFI : VexSubArchPPC64_FI;
445
446 /* But we're not done yet: VG_(machine_ppc64_set_clszB) must be
447 called before we're ready to go. */
448 return True;
449 }
450
sewardje2d1e672005-11-12 23:10:48 +0000451#else
452# error "Unknown arch"
453#endif
454}
455
sewardj2c48c7b2005-11-29 13:05:56 +0000456/* Notify host cpu cache line size. */
sewardje3826cf2005-11-13 00:30:22 +0000457#if defined(VGA_ppc32)
458void VG_(machine_ppc32_set_clszB)( Int szB )
459{
460 vg_assert(hwcaps_done);
461
462 /* Either the value must not have been set yet (zero) or we can
463 tolerate it being set to the same value multiple times, as the
464 stack scanning logic in m_main is a bit stupid. */
cerion1f0d8142005-12-23 00:57:03 +0000465 vg_assert(vai.ppc_cache_line_szB == 0
466 || vai.ppc_cache_line_szB == szB);
sewardje3826cf2005-11-13 00:30:22 +0000467
468 vg_assert(szB == 32 || szB == 128);
cerion1f0d8142005-12-23 00:57:03 +0000469 vai.ppc_cache_line_szB = szB;
sewardje3826cf2005-11-13 00:30:22 +0000470}
471#endif
472
sewardje2d1e672005-11-12 23:10:48 +0000473
sewardj2c48c7b2005-11-29 13:05:56 +0000474/* Notify host cpu cache line size. */
475#if defined(VGA_ppc64)
476void VG_(machine_ppc64_set_clszB)( Int szB )
477{
478 vg_assert(hwcaps_done);
479
480 /* Either the value must not have been set yet (zero) or we can
481 tolerate it being set to the same value multiple times, as the
482 stack scanning logic in m_main is a bit stupid. */
cerion1f0d8142005-12-23 00:57:03 +0000483 vg_assert(vai.ppc_cache_line_szB == 0
484 || vai.ppc_cache_line_szB == szB);
sewardj2c48c7b2005-11-29 13:05:56 +0000485
486 vg_assert(szB == 32 || szB == 128);
cerion1f0d8142005-12-23 00:57:03 +0000487 vai.ppc_cache_line_szB = szB;
sewardj2c48c7b2005-11-29 13:05:56 +0000488}
489#endif
490
491
sewardje2d1e672005-11-12 23:10:48 +0000492/* Fetch host cpu info, once established. */
493void VG_(machine_get_VexArchInfo)( /*OUT*/VexArch* pVa,
494 /*OUT*/VexArchInfo* pVai )
495{
496 vg_assert(hwcaps_done);
sewardje3826cf2005-11-13 00:30:22 +0000497 if (pVa) *pVa = va;
498 if (pVai) *pVai = vai;
sewardje2d1e672005-11-12 23:10:48 +0000499}
sewardj7821e2e2005-08-08 00:35:46 +0000500
501
njnf536bbb2005-06-13 04:21:38 +0000502/*--------------------------------------------------------------------*/
503/*--- end ---*/
504/*--------------------------------------------------------------------*/