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