blob: 1061112592c2a7f1479f1c854e26f0e3765f2fe8 [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
njn9f207462009-03-10 22:02:09 +000010 Copyright (C) 2000-2009 Julian Seward
njnf536bbb2005-06-13 04:21:38 +000011 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"
sewardj4cfea4f2006-10-14 19:26:10 +000032#include "pub_core_vki.h"
njnc7561b92005-06-19 01:24:32 +000033#include "pub_core_threadstate.h"
njnf536bbb2005-06-13 04:21:38 +000034#include "pub_core_libcassert.h"
35#include "pub_core_libcbase.h"
36#include "pub_core_machine.h"
sewardje2d1e672005-11-12 23:10:48 +000037#include "pub_core_cpuid.h"
bart1581e742009-01-13 07:49:14 +000038#include "pub_core_libcsignal.h" // for ppc32 messing with SIGILL and SIGFPE
sewardj3b0cae72009-05-28 17:15:41 +000039#include "pub_core_debuglog.h"
sewardje3826cf2005-11-13 00:30:22 +000040
njnf536bbb2005-06-13 04:21:38 +000041
njnaf839f52005-06-23 03:27:57 +000042#define INSTR_PTR(regs) ((regs).vex.VG_INSTR_PTR)
43#define STACK_PTR(regs) ((regs).vex.VG_STACK_PTR)
44#define FRAME_PTR(regs) ((regs).vex.VG_FRAME_PTR)
njnf536bbb2005-06-13 04:21:38 +000045
46Addr VG_(get_SP) ( ThreadId tid )
47{
48 return STACK_PTR( VG_(threads)[tid].arch );
49}
50
51Addr VG_(get_IP) ( ThreadId tid )
52{
53 return INSTR_PTR( VG_(threads)[tid].arch );
54}
55
56Addr VG_(get_FP) ( ThreadId tid )
57{
58 return FRAME_PTR( VG_(threads)[tid].arch );
59}
60
sewardjacaec5f2005-08-19 16:02:59 +000061Addr VG_(get_LR) ( ThreadId tid )
62{
sewardj2c48c7b2005-11-29 13:05:56 +000063# if defined(VGA_ppc32) || defined(VGA_ppc64)
sewardjacaec5f2005-08-19 16:02:59 +000064 return VG_(threads)[tid].arch.vex.guest_LR;
65# elif defined(VGA_x86) || defined(VGA_amd64)
66 return 0;
67# else
68# error "Unknown arch"
69# endif
70}
71
njnf536bbb2005-06-13 04:21:38 +000072void VG_(set_SP) ( ThreadId tid, Addr sp )
73{
74 STACK_PTR( VG_(threads)[tid].arch ) = sp;
75}
76
77void VG_(set_IP) ( ThreadId tid, Addr ip )
78{
79 INSTR_PTR( VG_(threads)[tid].arch ) = ip;
80}
81
sewardj9c606bd2008-09-18 18:12:50 +000082void VG_(set_syscall_return_shadows) ( ThreadId tid,
83 /* shadow vals for the result */
84 UWord s1res, UWord s2res,
85 /* shadow vals for the error val */
86 UWord s1err, UWord s2err )
87{
88# if defined(VGP_x86_linux)
89 VG_(threads)[tid].arch.vex_shadow1.guest_EAX = s1res;
90 VG_(threads)[tid].arch.vex_shadow2.guest_EAX = s2res;
91# elif defined(VGP_amd64_linux)
92 VG_(threads)[tid].arch.vex_shadow1.guest_RAX = s1res;
93 VG_(threads)[tid].arch.vex_shadow2.guest_RAX = s2res;
94# elif defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
95 VG_(threads)[tid].arch.vex_shadow1.guest_GPR3 = s1res;
96 VG_(threads)[tid].arch.vex_shadow2.guest_GPR3 = s2res;
97# elif defined(VGP_ppc32_aix5) || defined(VGP_ppc64_aix5)
98 VG_(threads)[tid].arch.vex_shadow1.guest_GPR3 = s1res;
99 VG_(threads)[tid].arch.vex_shadow2.guest_GPR3 = s2res;
100 VG_(threads)[tid].arch.vex_shadow1.guest_GPR4 = s1err;
101 VG_(threads)[tid].arch.vex_shadow2.guest_GPR4 = s2err;
njnf76d27a2009-05-28 01:53:07 +0000102# elif defined(VGO_darwin)
103 // GrP fixme darwin syscalls may return more values (2 registers plus error)
sewardj9c606bd2008-09-18 18:12:50 +0000104# else
105# error "Unknown plat"
106# endif
107}
njnf536bbb2005-06-13 04:21:38 +0000108
sewardj7cf4e6b2008-05-01 20:24:26 +0000109void
110VG_(get_shadow_regs_area) ( ThreadId tid,
111 /*DST*/UChar* dst,
njnc4431bf2009-01-15 21:29:24 +0000112 /*SRC*/Int shadowNo, PtrdiffT offset, SizeT size )
njnf536bbb2005-06-13 04:21:38 +0000113{
sewardj7cf4e6b2008-05-01 20:24:26 +0000114 void* src;
njnf536bbb2005-06-13 04:21:38 +0000115 ThreadState* tst;
sewardj9c606bd2008-09-18 18:12:50 +0000116 vg_assert(shadowNo == 0 || shadowNo == 1 || shadowNo == 2);
njnf536bbb2005-06-13 04:21:38 +0000117 vg_assert(VG_(is_valid_tid)(tid));
njnf536bbb2005-06-13 04:21:38 +0000118 // Bounds check
119 vg_assert(0 <= offset && offset < sizeof(VexGuestArchState));
120 vg_assert(offset + size <= sizeof(VexGuestArchState));
sewardj7cf4e6b2008-05-01 20:24:26 +0000121 // Copy
122 tst = & VG_(threads)[tid];
sewardj9c606bd2008-09-18 18:12:50 +0000123 src = NULL;
124 switch (shadowNo) {
125 case 0: src = (void*)(((Addr)&(tst->arch.vex)) + offset); break;
126 case 1: src = (void*)(((Addr)&(tst->arch.vex_shadow1)) + offset); break;
127 case 2: src = (void*)(((Addr)&(tst->arch.vex_shadow2)) + offset); break;
128 }
129 tl_assert(src != NULL);
sewardj7cf4e6b2008-05-01 20:24:26 +0000130 VG_(memcpy)( dst, src, size);
njnf536bbb2005-06-13 04:21:38 +0000131}
132
sewardj7cf4e6b2008-05-01 20:24:26 +0000133void
134VG_(set_shadow_regs_area) ( ThreadId tid,
njnc4431bf2009-01-15 21:29:24 +0000135 /*DST*/Int shadowNo, PtrdiffT offset, SizeT size,
sewardj7cf4e6b2008-05-01 20:24:26 +0000136 /*SRC*/const UChar* src )
njnf536bbb2005-06-13 04:21:38 +0000137{
sewardj7cf4e6b2008-05-01 20:24:26 +0000138 void* dst;
njnf536bbb2005-06-13 04:21:38 +0000139 ThreadState* tst;
sewardj9c606bd2008-09-18 18:12:50 +0000140 vg_assert(shadowNo == 0 || shadowNo == 1 || shadowNo == 2);
njnf536bbb2005-06-13 04:21:38 +0000141 vg_assert(VG_(is_valid_tid)(tid));
njnf536bbb2005-06-13 04:21:38 +0000142 // Bounds check
143 vg_assert(0 <= offset && offset < sizeof(VexGuestArchState));
144 vg_assert(offset + size <= sizeof(VexGuestArchState));
sewardj7cf4e6b2008-05-01 20:24:26 +0000145 // Copy
146 tst = & VG_(threads)[tid];
sewardj9c606bd2008-09-18 18:12:50 +0000147 dst = NULL;
148 switch (shadowNo) {
149 case 0: dst = (void*)(((Addr)&(tst->arch.vex)) + offset); break;
150 case 1: dst = (void*)(((Addr)&(tst->arch.vex_shadow1)) + offset); break;
151 case 2: dst = (void*)(((Addr)&(tst->arch.vex_shadow2)) + offset); break;
152 }
153 tl_assert(dst != NULL);
sewardj7cf4e6b2008-05-01 20:24:26 +0000154 VG_(memcpy)( dst, src, size);
njnf536bbb2005-06-13 04:21:38 +0000155}
156
157
njn6ace3ea2005-06-17 03:06:27 +0000158static void apply_to_GPs_of_tid(VexGuestArchState* vex, void (*f)(Addr))
159{
160#if defined(VGA_x86)
161 (*f)(vex->guest_EAX);
162 (*f)(vex->guest_ECX);
163 (*f)(vex->guest_EDX);
164 (*f)(vex->guest_EBX);
165 (*f)(vex->guest_ESI);
166 (*f)(vex->guest_EDI);
167 (*f)(vex->guest_ESP);
168 (*f)(vex->guest_EBP);
169#elif defined(VGA_amd64)
170 (*f)(vex->guest_RAX);
171 (*f)(vex->guest_RCX);
172 (*f)(vex->guest_RDX);
173 (*f)(vex->guest_RBX);
174 (*f)(vex->guest_RSI);
175 (*f)(vex->guest_RDI);
176 (*f)(vex->guest_RSP);
177 (*f)(vex->guest_RBP);
178 (*f)(vex->guest_R8);
179 (*f)(vex->guest_R9);
180 (*f)(vex->guest_R10);
181 (*f)(vex->guest_R11);
182 (*f)(vex->guest_R12);
183 (*f)(vex->guest_R13);
184 (*f)(vex->guest_R14);
185 (*f)(vex->guest_R15);
sewardj2c48c7b2005-11-29 13:05:56 +0000186#elif defined(VGA_ppc32) || defined(VGA_ppc64)
cerion85665ca2005-06-20 15:51:07 +0000187 /* XXX ask tool about validity? */
188 (*f)(vex->guest_GPR0);
189 (*f)(vex->guest_GPR1);
190 (*f)(vex->guest_GPR2);
191 (*f)(vex->guest_GPR3);
192 (*f)(vex->guest_GPR4);
193 (*f)(vex->guest_GPR5);
194 (*f)(vex->guest_GPR6);
195 (*f)(vex->guest_GPR7);
196 (*f)(vex->guest_GPR8);
197 (*f)(vex->guest_GPR9);
198 (*f)(vex->guest_GPR10);
199 (*f)(vex->guest_GPR11);
200 (*f)(vex->guest_GPR12);
201 (*f)(vex->guest_GPR13);
202 (*f)(vex->guest_GPR14);
203 (*f)(vex->guest_GPR15);
204 (*f)(vex->guest_GPR16);
205 (*f)(vex->guest_GPR17);
206 (*f)(vex->guest_GPR18);
207 (*f)(vex->guest_GPR19);
208 (*f)(vex->guest_GPR20);
209 (*f)(vex->guest_GPR21);
210 (*f)(vex->guest_GPR22);
211 (*f)(vex->guest_GPR23);
212 (*f)(vex->guest_GPR24);
213 (*f)(vex->guest_GPR25);
214 (*f)(vex->guest_GPR26);
215 (*f)(vex->guest_GPR27);
216 (*f)(vex->guest_GPR28);
217 (*f)(vex->guest_GPR29);
218 (*f)(vex->guest_GPR30);
219 (*f)(vex->guest_GPR31);
220 (*f)(vex->guest_CTR);
221 (*f)(vex->guest_LR);
222
njn6ace3ea2005-06-17 03:06:27 +0000223#else
224# error Unknown arch
225#endif
226}
227
228
229void VG_(apply_to_GP_regs)(void (*f)(UWord))
230{
231 ThreadId tid;
232
233 for (tid = 1; tid < VG_N_THREADS; tid++) {
234 if (VG_(is_valid_tid)(tid)) {
235 ThreadState* tst = VG_(get_ThreadState)(tid);
236 apply_to_GPs_of_tid(&(tst->arch.vex), f);
237 }
238 }
239}
240
sewardjb8b79ad2008-03-03 01:35:41 +0000241void VG_(thread_stack_reset_iter)(/*OUT*/ThreadId* tid)
njnb506bd82005-06-21 04:01:51 +0000242{
sewardjb8b79ad2008-03-03 01:35:41 +0000243 *tid = (ThreadId)(-1);
njnb506bd82005-06-21 04:01:51 +0000244}
njn6ace3ea2005-06-17 03:06:27 +0000245
sewardjb8b79ad2008-03-03 01:35:41 +0000246Bool VG_(thread_stack_next)(/*MOD*/ThreadId* tid,
247 /*OUT*/Addr* stack_min,
248 /*OUT*/Addr* stack_max)
njn1d0cb0d2005-08-15 01:52:02 +0000249{
250 ThreadId i;
sewardjb8b79ad2008-03-03 01:35:41 +0000251 for (i = (*tid)+1; i < VG_N_THREADS; i++) {
252 if (i == VG_INVALID_THREADID)
253 continue;
njn1d0cb0d2005-08-15 01:52:02 +0000254 if (VG_(threads)[i].status != VgTs_Empty) {
255 *tid = i;
256 *stack_min = VG_(get_SP)(i);
257 *stack_max = VG_(threads)[i].client_stack_highest_word;
njn1d0cb0d2005-08-15 01:52:02 +0000258 return True;
259 }
260 }
261 return False;
262}
sewardj7821e2e2005-08-08 00:35:46 +0000263
sewardjbbec7722007-11-25 14:08:53 +0000264Addr VG_(thread_get_stack_max)(ThreadId tid)
265{
266 vg_assert(0 <= tid && tid < VG_N_THREADS && tid != VG_INVALID_THREADID);
267 vg_assert(VG_(threads)[tid].status != VgTs_Empty);
268 return VG_(threads)[tid].client_stack_highest_word;
269}
270
bart0fb03202008-03-29 09:25:53 +0000271SizeT VG_(thread_get_stack_size)(ThreadId tid)
272{
273 vg_assert(0 <= tid && tid < VG_N_THREADS && tid != VG_INVALID_THREADID);
274 vg_assert(VG_(threads)[tid].status != VgTs_Empty);
275 return VG_(threads)[tid].client_stack_szB;
276}
277
sewardje2d1e672005-11-12 23:10:48 +0000278//-------------------------------------------------------------
279/* Details about the capabilities of the underlying (host) CPU. These
280 details are acquired by (1) enquiring with the CPU at startup, or
281 (2) from the AT_SYSINFO entries the kernel gave us (ppc32 cache
282 line size). It's a bit nasty in the sense that there's no obvious
283 way to stop uses of some of this info before it's ready to go.
sewardj10f08cf2005-06-29 10:16:14 +0000284
sewardje2d1e672005-11-12 23:10:48 +0000285 Current dependencies are:
sewardja48a4932005-09-29 11:09:56 +0000286
sewardje2d1e672005-11-12 23:10:48 +0000287 x86: initially: call VG_(machine_get_hwcaps)
sewardj10f08cf2005-06-29 10:16:14 +0000288
sewardje2d1e672005-11-12 23:10:48 +0000289 then safe to use VG_(machine_get_VexArchInfo)
290 and VG_(machine_x86_have_mxcsr)
291 -------------
292 amd64: initially: call VG_(machine_get_hwcaps)
293
294 then safe to use VG_(machine_get_VexArchInfo)
295 -------------
296 ppc32: initially: call VG_(machine_get_hwcaps)
297 call VG_(machine_ppc32_set_clszB)
298
299 then safe to use VG_(machine_get_VexArchInfo)
sewardj2c36d422005-11-13 01:59:22 +0000300 and VG_(machine_ppc32_has_FP)
sewardje2d1e672005-11-12 23:10:48 +0000301 and VG_(machine_ppc32_has_VMX)
cerion1f0d8142005-12-23 00:57:03 +0000302 -------------
303 ppc64: initially: call VG_(machine_get_hwcaps)
304 call VG_(machine_ppc64_set_clszB)
305
306 then safe to use VG_(machine_get_VexArchInfo)
307 and VG_(machine_ppc64_has_VMX)
sewardje2d1e672005-11-12 23:10:48 +0000308
309 VG_(machine_get_hwcaps) may use signals (although it attempts to
310 leave signal state unchanged) and therefore should only be
311 called before m_main sets up the client's signal state.
312*/
313
314/* --------- State --------- */
315static Bool hwcaps_done = False;
316
317/* --- all archs --- */
318static VexArch va;
319static VexArchInfo vai;
sewardja48a4932005-09-29 11:09:56 +0000320
sewardj7821e2e2005-08-08 00:35:46 +0000321#if defined(VGA_x86)
sewardje2d1e672005-11-12 23:10:48 +0000322UInt VG_(machine_x86_have_mxcsr) = 0;
sewardj7821e2e2005-08-08 00:35:46 +0000323#endif
sewardje2d1e672005-11-12 23:10:48 +0000324#if defined(VGA_ppc32)
sewardj2c36d422005-11-13 01:59:22 +0000325UInt VG_(machine_ppc32_has_FP) = 0;
sewardje2d1e672005-11-12 23:10:48 +0000326UInt VG_(machine_ppc32_has_VMX) = 0;
327#endif
sewardj2c48c7b2005-11-29 13:05:56 +0000328#if defined(VGA_ppc64)
329ULong VG_(machine_ppc64_has_VMX) = 0;
330#endif
sewardje2d1e672005-11-12 23:10:48 +0000331
332
333/* Determine what insn set and insn set variant the host has, and
334 record it. To be called once at system startup. Returns False if
335 this a CPU incapable of running Valgrind. */
336
sewardj2c48c7b2005-11-29 13:05:56 +0000337#if defined(VGA_ppc32) || defined(VGA_ppc64)
sewardje3826cf2005-11-13 00:30:22 +0000338#include <setjmp.h> // For jmp_buf
bart1581e742009-01-13 07:49:14 +0000339static jmp_buf env_unsup_insn;
340static void handler_unsup_insn ( Int x ) { __builtin_longjmp(env_unsup_insn,1); }
sewardje3826cf2005-11-13 00:30:22 +0000341#endif
342
sewardje2d1e672005-11-12 23:10:48 +0000343Bool VG_(machine_get_hwcaps)( void )
344{
345 vg_assert(hwcaps_done == False);
346 hwcaps_done = True;
347
348 // Whack default settings into vai, so that we only need to fill in
349 // any interesting bits.
350 LibVEX_default_VexArchInfo(&vai);
351
352#if defined(VGA_x86)
sewardj1c0ce7a2009-07-01 08:10:49 +0000353 { Bool have_sse1, have_sse2, have_cx8;
sewardje2d1e672005-11-12 23:10:48 +0000354 UInt eax, ebx, ecx, edx;
355
356 if (!VG_(has_cpuid)())
357 /* we can't do cpuid at all. Give up. */
358 return False;
359
360 VG_(cpuid)(0, &eax, &ebx, &ecx, &edx);
361 if (eax < 1)
362 /* we can't ask for cpuid(x) for x > 0. Give up. */
363 return False;
364
365 /* get capabilities bits into edx */
366 VG_(cpuid)(1, &eax, &ebx, &ecx, &edx);
367
368 have_sse1 = (edx & (1<<25)) != 0; /* True => have sse insns */
369 have_sse2 = (edx & (1<<26)) != 0; /* True => have sse2 insns */
370
sewardj1c0ce7a2009-07-01 08:10:49 +0000371 /* cmpxchg8b is a minimum requirement now; if we don't have it we
372 must simply give up. But all CPUs since Pentium-I have it, so
373 that doesn't seem like much of a restriction. */
374 have_cx8 = (edx & (1<<8)) != 0; /* True => have cmpxchg8b */
375 if (!have_cx8)
376 return False;
377
sewardje2d1e672005-11-12 23:10:48 +0000378 if (have_sse2 && have_sse1) {
379 va = VexArchX86;
sewardje3121f32006-01-27 21:23:23 +0000380 vai.hwcaps = VEX_HWCAPS_X86_SSE1;
381 vai.hwcaps |= VEX_HWCAPS_X86_SSE2;
sewardje2d1e672005-11-12 23:10:48 +0000382 VG_(machine_x86_have_mxcsr) = 1;
383 return True;
384 }
385
386 if (have_sse1) {
387 va = VexArchX86;
sewardje3121f32006-01-27 21:23:23 +0000388 vai.hwcaps = VEX_HWCAPS_X86_SSE1;
sewardje2d1e672005-11-12 23:10:48 +0000389 VG_(machine_x86_have_mxcsr) = 1;
390 return True;
391 }
392
sewardje3121f32006-01-27 21:23:23 +0000393 va = VexArchX86;
394 vai.hwcaps = 0; /*baseline - no sse at all*/
sewardje2d1e672005-11-12 23:10:48 +0000395 VG_(machine_x86_have_mxcsr) = 0;
396 return True;
397 }
398
399#elif defined(VGA_amd64)
sewardj1c0ce7a2009-07-01 08:10:49 +0000400 { Bool have_sse1, have_sse2, have_sse3, have_cx8, have_cx16;
401 UInt eax, ebx, ecx, edx;
402
403 if (!VG_(has_cpuid)())
404 /* we can't do cpuid at all. Give up. */
405 return False;
406
407 VG_(cpuid)(0, &eax, &ebx, &ecx, &edx);
408 if (eax < 1)
409 /* we can't ask for cpuid(x) for x > 0. Give up. */
410 return False;
411
412 /* get capabilities bits into edx */
413 VG_(cpuid)(1, &eax, &ebx, &ecx, &edx);
414
415 have_sse1 = (edx & (1<<25)) != 0; /* True => have sse insns */
416 have_sse2 = (edx & (1<<26)) != 0; /* True => have sse2 insns */
sewardj598971e2009-07-12 13:19:04 +0000417 have_sse3 = (ecx & (1<<0)) != 0; /* True => have sse3 insns */
sewardj1c0ce7a2009-07-01 08:10:49 +0000418
419 /* cmpxchg8b is a minimum requirement now; if we don't have it we
420 must simply give up. But all CPUs since Pentium-I have it, so
421 that doesn't seem like much of a restriction. */
422 have_cx8 = (edx & (1<<8)) != 0; /* True => have cmpxchg8b */
423 if (!have_cx8)
424 return False;
425
426 /* on amd64 we tolerate older cpus, which don't have cmpxchg16b */
427 have_cx16 = (ecx & (1<<13)) != 0; /* True => have cmpxchg16b */
428
429 va = VexArchAMD64;
430 vai.hwcaps = (have_sse3 ? VEX_HWCAPS_AMD64_SSE3 : 0)
431 | (have_cx16 ? VEX_HWCAPS_AMD64_CX16 : 0);
432 return True;
433 }
sewardje2d1e672005-11-12 23:10:48 +0000434
435#elif defined(VGA_ppc32)
bart1581e742009-01-13 07:49:14 +0000436 {
437 /* Find out which subset of the ppc32 instruction set is supported by
438 verifying whether various ppc32 instructions generate a SIGILL
439 or a SIGFPE. An alternative approach is to check the AT_HWCAP and
440 AT_PLATFORM entries in the ELF auxiliary table -- see also
441 the_iifii.client_auxv in m_main.c.
442 */
njncda2f0f2009-05-18 02:12:08 +0000443 vki_sigset_t saved_set, tmp_set;
444 vki_sigaction_fromK_t saved_sigill_act, saved_sigfpe_act;
445 vki_sigaction_toK_t tmp_sigill_act, tmp_sigfpe_act;
sewardje3826cf2005-11-13 00:30:22 +0000446
sewardjb32bc732006-01-27 21:52:39 +0000447 volatile Bool have_F, have_V, have_FX, have_GX;
sewardj7637e9e2006-02-21 17:11:11 +0000448 Int r;
sewardje3826cf2005-11-13 00:30:22 +0000449
njncda2f0f2009-05-18 02:12:08 +0000450 /* This is a kludge. Really we ought to back-convert saved_act
451 into a toK_t using VG_(convert_sigaction_fromK_to_toK), but
452 since that's a no-op on all ppc32 platforms so far supported,
453 it's not worth the typing effort. At least include most basic
454 sanity check: */
455 vg_assert(sizeof(vki_sigaction_fromK_t) == sizeof(vki_sigaction_toK_t));
456
sewardje3826cf2005-11-13 00:30:22 +0000457 VG_(sigemptyset)(&tmp_set);
458 VG_(sigaddset)(&tmp_set, VKI_SIGILL);
bart1581e742009-01-13 07:49:14 +0000459 VG_(sigaddset)(&tmp_set, VKI_SIGFPE);
sewardje3826cf2005-11-13 00:30:22 +0000460
sewardj7637e9e2006-02-21 17:11:11 +0000461 r = VG_(sigprocmask)(VKI_SIG_UNBLOCK, &tmp_set, &saved_set);
462 vg_assert(r == 0);
sewardje3826cf2005-11-13 00:30:22 +0000463
bart1581e742009-01-13 07:49:14 +0000464 r = VG_(sigaction)(VKI_SIGILL, NULL, &saved_sigill_act);
sewardj7637e9e2006-02-21 17:11:11 +0000465 vg_assert(r == 0);
bart1581e742009-01-13 07:49:14 +0000466 tmp_sigill_act = saved_sigill_act;
467
468 r = VG_(sigaction)(VKI_SIGFPE, NULL, &saved_sigfpe_act);
469 vg_assert(r == 0);
470 tmp_sigfpe_act = saved_sigfpe_act;
sewardje3826cf2005-11-13 00:30:22 +0000471
sewardj7637e9e2006-02-21 17:11:11 +0000472 /* NODEFER: signal handler does not return (from the kernel's point of
473 view), hence if it is to successfully catch a signal more than once,
474 we need the NODEFER flag. */
bart1581e742009-01-13 07:49:14 +0000475 tmp_sigill_act.sa_flags &= ~VKI_SA_RESETHAND;
476 tmp_sigill_act.sa_flags &= ~VKI_SA_SIGINFO;
477 tmp_sigill_act.sa_flags |= VKI_SA_NODEFER;
478 tmp_sigill_act.ksa_handler = handler_unsup_insn;
479 r = VG_(sigaction)(VKI_SIGILL, &tmp_sigill_act, NULL);
480 vg_assert(r == 0);
481
482 tmp_sigfpe_act.sa_flags &= ~VKI_SA_RESETHAND;
483 tmp_sigfpe_act.sa_flags &= ~VKI_SA_SIGINFO;
484 tmp_sigfpe_act.sa_flags |= VKI_SA_NODEFER;
485 tmp_sigfpe_act.ksa_handler = handler_unsup_insn;
486 r = VG_(sigaction)(VKI_SIGFPE, &tmp_sigfpe_act, NULL);
487 vg_assert(r == 0);
sewardje3826cf2005-11-13 00:30:22 +0000488
sewardje3121f32006-01-27 21:23:23 +0000489 /* standard FP insns */
490 have_F = True;
bart1581e742009-01-13 07:49:14 +0000491 if (__builtin_setjmp(env_unsup_insn)) {
sewardje3121f32006-01-27 21:23:23 +0000492 have_F = False;
sewardje3826cf2005-11-13 00:30:22 +0000493 } else {
sewardjf1c91e02006-10-17 01:35:58 +0000494 __asm__ __volatile__(".long 0xFC000090"); /*fmr 0,0 */
sewardje3826cf2005-11-13 00:30:22 +0000495 }
496
sewardje3121f32006-01-27 21:23:23 +0000497 /* Altivec insns */
498 have_V = True;
bart1581e742009-01-13 07:49:14 +0000499 if (__builtin_setjmp(env_unsup_insn)) {
sewardje3121f32006-01-27 21:23:23 +0000500 have_V = False;
sewardje3826cf2005-11-13 00:30:22 +0000501 } else {
sewardj71592122006-04-04 03:29:48 +0000502 /* Unfortunately some older assemblers don't speak Altivec (or
503 choose not to), so to be safe we directly emit the 32-bit
504 word corresponding to "vor 0,0,0". This fixes a build
505 problem that happens on Debian 3.1 (ppc32), and probably
506 various other places. */
sewardj54d0dc72006-04-04 03:08:49 +0000507 __asm__ __volatile__(".long 0x10000484"); /*vor 0,0,0*/
sewardje3826cf2005-11-13 00:30:22 +0000508 }
509
sewardje3121f32006-01-27 21:23:23 +0000510 /* General-Purpose optional (fsqrt, fsqrts) */
511 have_FX = True;
bart1581e742009-01-13 07:49:14 +0000512 if (__builtin_setjmp(env_unsup_insn)) {
sewardje3121f32006-01-27 21:23:23 +0000513 have_FX = False;
514 } else {
sewardjf1c91e02006-10-17 01:35:58 +0000515 __asm__ __volatile__(".long 0xFC00002C"); /*fsqrt 0,0 */
sewardje3121f32006-01-27 21:23:23 +0000516 }
517
518 /* Graphics optional (stfiwx, fres, frsqrte, fsel) */
519 have_GX = True;
bart1581e742009-01-13 07:49:14 +0000520 if (__builtin_setjmp(env_unsup_insn)) {
sewardje3121f32006-01-27 21:23:23 +0000521 have_GX = False;
522 } else {
sewardjf1c91e02006-10-17 01:35:58 +0000523 __asm__ __volatile__(".long 0xFC000034"); /* frsqrte 0,0 */
sewardje3121f32006-01-27 21:23:23 +0000524 }
525
bart1581e742009-01-13 07:49:14 +0000526 r = VG_(sigaction)(VKI_SIGILL, &saved_sigill_act, NULL);
527 vg_assert(r == 0);
528 r = VG_(sigaction)(VKI_SIGFPE, &saved_sigfpe_act, NULL);
sewardj7637e9e2006-02-21 17:11:11 +0000529 vg_assert(r == 0);
530 r = VG_(sigprocmask)(VKI_SIG_SETMASK, &saved_set, NULL);
531 vg_assert(r == 0);
bart1581e742009-01-13 07:49:14 +0000532 VG_(debugLog)(1, "machine", "F %d V %d FX %d GX %d\n",
sewardje3121f32006-01-27 21:23:23 +0000533 (Int)have_F, (Int)have_V, (Int)have_FX, (Int)have_GX);
sewardje3121f32006-01-27 21:23:23 +0000534 /* Make FP a prerequisite for VMX (bogusly so), and for FX and GX. */
535 if (have_V && !have_F)
536 have_V = False;
537 if (have_FX && !have_F)
538 have_FX = False;
539 if (have_GX && !have_F)
540 have_GX = False;
sewardje3826cf2005-11-13 00:30:22 +0000541
sewardje3121f32006-01-27 21:23:23 +0000542 VG_(machine_ppc32_has_FP) = have_F ? 1 : 0;
543 VG_(machine_ppc32_has_VMX) = have_V ? 1 : 0;
sewardje3826cf2005-11-13 00:30:22 +0000544
545 va = VexArchPPC32;
546
sewardje3121f32006-01-27 21:23:23 +0000547 vai.hwcaps = 0;
548 if (have_F) vai.hwcaps |= VEX_HWCAPS_PPC32_F;
549 if (have_V) vai.hwcaps |= VEX_HWCAPS_PPC32_V;
550 if (have_FX) vai.hwcaps |= VEX_HWCAPS_PPC32_FX;
551 if (have_GX) vai.hwcaps |= VEX_HWCAPS_PPC32_GX;
sewardje3826cf2005-11-13 00:30:22 +0000552
553 /* But we're not done yet: VG_(machine_ppc32_set_clszB) must be
554 called before we're ready to go. */
555 return True;
556 }
sewardje2d1e672005-11-12 23:10:48 +0000557
sewardj2c48c7b2005-11-29 13:05:56 +0000558#elif defined(VGA_ppc64)
bart1581e742009-01-13 07:49:14 +0000559 {
560 /* Same instruction set detection algorithm as for ppc32. */
njncda2f0f2009-05-18 02:12:08 +0000561 vki_sigset_t saved_set, tmp_set;
562 vki_sigaction_fromK_t saved_sigill_act, saved_sigfpe_act;
563 vki_sigaction_toK_t tmp_sigill_act, tmp_sigfpe_act;
sewardj2c48c7b2005-11-29 13:05:56 +0000564
sewardjb32bc732006-01-27 21:52:39 +0000565 volatile Bool have_F, have_V, have_FX, have_GX;
njncda2f0f2009-05-18 02:12:08 +0000566 Int r;
567
568 /* This is a kludge. Really we ought to back-convert saved_act
569 into a toK_t using VG_(convert_sigaction_fromK_to_toK), but
570 since that's a no-op on all ppc64 platforms so far supported,
571 it's not worth the typing effort. At least include most basic
572 sanity check: */
573 vg_assert(sizeof(vki_sigaction_fromK_t) == sizeof(vki_sigaction_toK_t));
sewardj2c48c7b2005-11-29 13:05:56 +0000574
575 VG_(sigemptyset)(&tmp_set);
576 VG_(sigaddset)(&tmp_set, VKI_SIGILL);
bart1581e742009-01-13 07:49:14 +0000577 VG_(sigaddset)(&tmp_set, VKI_SIGFPE);
sewardj2c48c7b2005-11-29 13:05:56 +0000578
njncda2f0f2009-05-18 02:12:08 +0000579 r = VG_(sigprocmask)(VKI_SIG_UNBLOCK, &tmp_set, &saved_set);
580 vg_assert(r == 0);
sewardj2c48c7b2005-11-29 13:05:56 +0000581
njncda2f0f2009-05-18 02:12:08 +0000582 r = VG_(sigaction)(VKI_SIGILL, NULL, &saved_sigill_act);
583 vg_assert(r == 0);
bart1581e742009-01-13 07:49:14 +0000584 tmp_sigill_act = saved_sigill_act;
585
586 VG_(sigaction)(VKI_SIGFPE, NULL, &saved_sigfpe_act);
587 tmp_sigfpe_act = saved_sigfpe_act;
588
sewardj7637e9e2006-02-21 17:11:11 +0000589 /* NODEFER: signal handler does not return (from the kernel's point of
590 view), hence if it is to successfully catch a signal more than once,
591 we need the NODEFER flag. */
bart1581e742009-01-13 07:49:14 +0000592 tmp_sigill_act.sa_flags &= ~VKI_SA_RESETHAND;
593 tmp_sigill_act.sa_flags &= ~VKI_SA_SIGINFO;
594 tmp_sigill_act.sa_flags |= VKI_SA_NODEFER;
595 tmp_sigill_act.ksa_handler = handler_unsup_insn;
596 VG_(sigaction)(VKI_SIGILL, &tmp_sigill_act, NULL);
597
598 tmp_sigfpe_act.sa_flags &= ~VKI_SA_RESETHAND;
599 tmp_sigfpe_act.sa_flags &= ~VKI_SA_SIGINFO;
600 tmp_sigfpe_act.sa_flags |= VKI_SA_NODEFER;
601 tmp_sigfpe_act.ksa_handler = handler_unsup_insn;
602 VG_(sigaction)(VKI_SIGFPE, &tmp_sigfpe_act, NULL);
sewardj2c48c7b2005-11-29 13:05:56 +0000603
sewardje3121f32006-01-27 21:23:23 +0000604 /* standard FP insns */
605 have_F = True;
bart1581e742009-01-13 07:49:14 +0000606 if (__builtin_setjmp(env_unsup_insn)) {
sewardje3121f32006-01-27 21:23:23 +0000607 have_F = False;
608 } else {
609 __asm__ __volatile__("fmr 0,0");
610 }
611
612 /* Altivec insns */
613 have_V = True;
bart1581e742009-01-13 07:49:14 +0000614 if (__builtin_setjmp(env_unsup_insn)) {
sewardje3121f32006-01-27 21:23:23 +0000615 have_V = False;
sewardj2c48c7b2005-11-29 13:05:56 +0000616 } else {
sewardjf1c91e02006-10-17 01:35:58 +0000617 __asm__ __volatile__(".long 0x10000484"); /*vor 0,0,0*/
sewardj2c48c7b2005-11-29 13:05:56 +0000618 }
619
sewardje3121f32006-01-27 21:23:23 +0000620 /* General-Purpose optional (fsqrt, fsqrts) */
621 have_FX = True;
bart1581e742009-01-13 07:49:14 +0000622 if (__builtin_setjmp(env_unsup_insn)) {
sewardje3121f32006-01-27 21:23:23 +0000623 have_FX = False;
624 } else {
sewardjf1c91e02006-10-17 01:35:58 +0000625 __asm__ __volatile__(".long 0xFC00002C"); /*fsqrt 0,0*/
sewardje3121f32006-01-27 21:23:23 +0000626 }
627
628 /* Graphics optional (stfiwx, fres, frsqrte, fsel) */
629 have_GX = True;
bart1581e742009-01-13 07:49:14 +0000630 if (__builtin_setjmp(env_unsup_insn)) {
sewardje3121f32006-01-27 21:23:23 +0000631 have_GX = False;
632 } else {
sewardjf1c91e02006-10-17 01:35:58 +0000633 __asm__ __volatile__(".long 0xFC000034"); /*frsqrte 0,0*/
sewardje3121f32006-01-27 21:23:23 +0000634 }
635
bart1581e742009-01-13 07:49:14 +0000636 VG_(sigaction)(VKI_SIGILL, &saved_sigill_act, NULL);
637 VG_(sigaction)(VKI_SIGFPE, &saved_sigfpe_act, NULL);
sewardj2c48c7b2005-11-29 13:05:56 +0000638 VG_(sigprocmask)(VKI_SIG_SETMASK, &saved_set, NULL);
bart1581e742009-01-13 07:49:14 +0000639 VG_(debugLog)(1, "machine", "F %d V %d FX %d GX %d\n",
sewardje3121f32006-01-27 21:23:23 +0000640 (Int)have_F, (Int)have_V, (Int)have_FX, (Int)have_GX);
sewardje3121f32006-01-27 21:23:23 +0000641 /* on ppc64, if we don't even have FP, just give up. */
642 if (!have_F)
643 return False;
644
645 VG_(machine_ppc64_has_VMX) = have_V ? 1 : 0;
sewardj2c48c7b2005-11-29 13:05:56 +0000646
647 va = VexArchPPC64;
sewardje3121f32006-01-27 21:23:23 +0000648
649 vai.hwcaps = 0;
650 if (have_V) vai.hwcaps |= VEX_HWCAPS_PPC64_V;
651 if (have_FX) vai.hwcaps |= VEX_HWCAPS_PPC64_FX;
652 if (have_GX) vai.hwcaps |= VEX_HWCAPS_PPC64_GX;
sewardj2c48c7b2005-11-29 13:05:56 +0000653
654 /* But we're not done yet: VG_(machine_ppc64_set_clszB) must be
655 called before we're ready to go. */
656 return True;
657 }
658
sewardje2d1e672005-11-12 23:10:48 +0000659#else
660# error "Unknown arch"
661#endif
662}
663
sewardj2c48c7b2005-11-29 13:05:56 +0000664/* Notify host cpu cache line size. */
sewardje3826cf2005-11-13 00:30:22 +0000665#if defined(VGA_ppc32)
666void VG_(machine_ppc32_set_clszB)( Int szB )
667{
668 vg_assert(hwcaps_done);
669
670 /* Either the value must not have been set yet (zero) or we can
671 tolerate it being set to the same value multiple times, as the
672 stack scanning logic in m_main is a bit stupid. */
cerion1f0d8142005-12-23 00:57:03 +0000673 vg_assert(vai.ppc_cache_line_szB == 0
674 || vai.ppc_cache_line_szB == szB);
sewardje3826cf2005-11-13 00:30:22 +0000675
sewardj89230ca2008-05-29 16:39:57 +0000676 vg_assert(szB == 32 || szB == 64 || szB == 128);
cerion1f0d8142005-12-23 00:57:03 +0000677 vai.ppc_cache_line_szB = szB;
sewardje3826cf2005-11-13 00:30:22 +0000678}
679#endif
680
sewardje2d1e672005-11-12 23:10:48 +0000681
sewardj2c48c7b2005-11-29 13:05:56 +0000682/* Notify host cpu cache line size. */
683#if defined(VGA_ppc64)
684void VG_(machine_ppc64_set_clszB)( Int szB )
685{
686 vg_assert(hwcaps_done);
687
688 /* Either the value must not have been set yet (zero) or we can
689 tolerate it being set to the same value multiple times, as the
690 stack scanning logic in m_main is a bit stupid. */
cerion1f0d8142005-12-23 00:57:03 +0000691 vg_assert(vai.ppc_cache_line_szB == 0
692 || vai.ppc_cache_line_szB == szB);
sewardj2c48c7b2005-11-29 13:05:56 +0000693
sewardj89230ca2008-05-29 16:39:57 +0000694 vg_assert(szB == 32 || szB == 64 || szB == 128);
cerion1f0d8142005-12-23 00:57:03 +0000695 vai.ppc_cache_line_szB = szB;
sewardj2c48c7b2005-11-29 13:05:56 +0000696}
697#endif
698
699
sewardje2d1e672005-11-12 23:10:48 +0000700/* Fetch host cpu info, once established. */
701void VG_(machine_get_VexArchInfo)( /*OUT*/VexArch* pVa,
702 /*OUT*/VexArchInfo* pVai )
703{
704 vg_assert(hwcaps_done);
sewardje3826cf2005-11-13 00:30:22 +0000705 if (pVa) *pVa = va;
706 if (pVai) *pVai = vai;
sewardje2d1e672005-11-12 23:10:48 +0000707}
sewardj7821e2e2005-08-08 00:35:46 +0000708
709
sewardj53ee1fc2005-12-23 02:29:58 +0000710// Given a pointer to a function as obtained by "& functionname" in C,
sewardjf1c91e02006-10-17 01:35:58 +0000711// produce a pointer to the actual entry point for the function.
sewardj53ee1fc2005-12-23 02:29:58 +0000712void* VG_(fnptr_to_fnentry)( void* f )
713{
njnf76d27a2009-05-28 01:53:07 +0000714#if defined(VGP_x86_linux) || defined(VGP_amd64_linux) || \
715 defined(VGP_ppc32_linux) || defined(VGO_darwin)
sewardj53ee1fc2005-12-23 02:29:58 +0000716 return f;
sewardjf1c91e02006-10-17 01:35:58 +0000717#elif defined(VGP_ppc64_linux) || defined(VGP_ppc32_aix5) \
718 || defined(VGP_ppc64_aix5)
719 /* All other ppc variants use the AIX scheme, in which f is a
720 pointer to a 3-word function descriptor, of which the first word
721 is the entry address. */
722 UWord* descr = (UWord*)f;
sewardj53ee1fc2005-12-23 02:29:58 +0000723 return (void*)(descr[0]);
724#else
725# error "Unknown platform"
726#endif
727}
728
njnf536bbb2005-06-13 04:21:38 +0000729/*--------------------------------------------------------------------*/
730/*--- end ---*/
731/*--------------------------------------------------------------------*/