blob: ba3d52dec27f80e9ac05e7d503fc6e9fbee24ff1 [file] [log] [blame]
njnf536bbb2005-06-13 04:21:38 +00001/*--------------------------------------------------------------------*/
2/*--- Machine-related stuff. m_machine.c ---*/
3/*--------------------------------------------------------------------*/
4
5/*
6 This file is part of Valgrind, a dynamic binary instrumentation
7 framework.
8
sewardj03f8d3f2012-08-05 15:46:46 +00009 Copyright (C) 2000-2012 Julian Seward
njnf536bbb2005-06-13 04:21:38 +000010 jseward@acm.org
11
12 This program is free software; you can redistribute it and/or
13 modify it under the terms of the GNU General Public License as
14 published by the Free Software Foundation; either version 2 of the
15 License, or (at your option) any later version.
16
17 This program is distributed in the hope that it will be useful, but
18 WITHOUT ANY WARRANTY; without even the implied warranty of
19 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
20 General Public License for more details.
21
22 You should have received a copy of the GNU General Public License
23 along with this program; if not, write to the Free Software
24 Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
25 02111-1307, USA.
26
27 The GNU General Public License is contained in the file COPYING.
28*/
29
njnc7561b92005-06-19 01:24:32 +000030#include "pub_core_basics.h"
sewardj4cfea4f2006-10-14 19:26:10 +000031#include "pub_core_vki.h"
sewardj6c591e12011-04-11 16:17:51 +000032#include "pub_core_libcsetjmp.h" // setjmp facilities
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"
sewardj2c3f2ea2011-04-13 15:40:10 +000036#include "pub_core_libcfile.h"
floriandf14eea2012-12-09 17:30:45 +000037#include "pub_core_libcprint.h"
sewardj2c3f2ea2011-04-13 15:40:10 +000038#include "pub_core_mallocfree.h"
njnf536bbb2005-06-13 04:21:38 +000039#include "pub_core_machine.h"
sewardje2d1e672005-11-12 23:10:48 +000040#include "pub_core_cpuid.h"
bart1581e742009-01-13 07:49:14 +000041#include "pub_core_libcsignal.h" // for ppc32 messing with SIGILL and SIGFPE
sewardj3b0cae72009-05-28 17:15:41 +000042#include "pub_core_debuglog.h"
sewardje3826cf2005-11-13 00:30:22 +000043
njnf536bbb2005-06-13 04:21:38 +000044
njnaf839f52005-06-23 03:27:57 +000045#define INSTR_PTR(regs) ((regs).vex.VG_INSTR_PTR)
46#define STACK_PTR(regs) ((regs).vex.VG_STACK_PTR)
47#define FRAME_PTR(regs) ((regs).vex.VG_FRAME_PTR)
njnf536bbb2005-06-13 04:21:38 +000048
sewardj1dbd3372010-08-22 12:21:14 +000049Addr VG_(get_IP) ( ThreadId tid ) {
njnf536bbb2005-06-13 04:21:38 +000050 return INSTR_PTR( VG_(threads)[tid].arch );
51}
sewardj1dbd3372010-08-22 12:21:14 +000052Addr VG_(get_SP) ( ThreadId tid ) {
53 return STACK_PTR( VG_(threads)[tid].arch );
54}
55Addr VG_(get_FP) ( ThreadId tid ) {
njnf536bbb2005-06-13 04:21:38 +000056 return FRAME_PTR( VG_(threads)[tid].arch );
57}
58
sewardj1dbd3372010-08-22 12:21:14 +000059void VG_(set_IP) ( ThreadId tid, Addr ip ) {
njnf536bbb2005-06-13 04:21:38 +000060 INSTR_PTR( VG_(threads)[tid].arch ) = ip;
61}
sewardj1dbd3372010-08-22 12:21:14 +000062void VG_(set_SP) ( ThreadId tid, Addr sp ) {
63 STACK_PTR( VG_(threads)[tid].arch ) = sp;
64}
sewardj59570ff2010-01-01 11:59:33 +000065
66void VG_(get_UnwindStartRegs) ( /*OUT*/UnwindStartRegs* regs,
67 ThreadId tid )
68{
69# if defined(VGA_x86)
70 regs->r_pc = (ULong)VG_(threads)[tid].arch.vex.guest_EIP;
71 regs->r_sp = (ULong)VG_(threads)[tid].arch.vex.guest_ESP;
72 regs->misc.X86.r_ebp
73 = VG_(threads)[tid].arch.vex.guest_EBP;
74# elif defined(VGA_amd64)
75 regs->r_pc = VG_(threads)[tid].arch.vex.guest_RIP;
76 regs->r_sp = VG_(threads)[tid].arch.vex.guest_RSP;
77 regs->misc.AMD64.r_rbp
78 = VG_(threads)[tid].arch.vex.guest_RBP;
79# elif defined(VGA_ppc32)
80 regs->r_pc = (ULong)VG_(threads)[tid].arch.vex.guest_CIA;
sewardjf5f1e122010-01-02 13:24:58 +000081 regs->r_sp = (ULong)VG_(threads)[tid].arch.vex.guest_GPR1;
sewardj59570ff2010-01-01 11:59:33 +000082 regs->misc.PPC32.r_lr
83 = VG_(threads)[tid].arch.vex.guest_LR;
84# elif defined(VGA_ppc64)
85 regs->r_pc = VG_(threads)[tid].arch.vex.guest_CIA;
sewardjf5f1e122010-01-02 13:24:58 +000086 regs->r_sp = VG_(threads)[tid].arch.vex.guest_GPR1;
sewardj59570ff2010-01-01 11:59:33 +000087 regs->misc.PPC64.r_lr
88 = VG_(threads)[tid].arch.vex.guest_LR;
89# elif defined(VGA_arm)
sewardj1dbd3372010-08-22 12:21:14 +000090 regs->r_pc = (ULong)VG_(threads)[tid].arch.vex.guest_R15T;
sewardj59570ff2010-01-01 11:59:33 +000091 regs->r_sp = (ULong)VG_(threads)[tid].arch.vex.guest_R13;
92 regs->misc.ARM.r14
93 = VG_(threads)[tid].arch.vex.guest_R14;
94 regs->misc.ARM.r12
95 = VG_(threads)[tid].arch.vex.guest_R12;
96 regs->misc.ARM.r11
97 = VG_(threads)[tid].arch.vex.guest_R11;
sewardjfa5ce562010-09-23 22:05:59 +000098 regs->misc.ARM.r7
99 = VG_(threads)[tid].arch.vex.guest_R7;
sewardjb5b87402011-03-07 16:05:35 +0000100# elif defined(VGA_s390x)
101 regs->r_pc = (ULong)VG_(threads)[tid].arch.vex.guest_IA;
102 regs->r_sp = (ULong)VG_(threads)[tid].arch.vex.guest_SP;
103 regs->misc.S390X.r_fp
104 = VG_(threads)[tid].arch.vex.guest_r11;
105 regs->misc.S390X.r_lr
106 = VG_(threads)[tid].arch.vex.guest_r14;
sewardj5db15402012-06-07 09:13:21 +0000107# elif defined(VGA_mips32)
108 regs->r_pc = VG_(threads)[tid].arch.vex.guest_PC;
109 regs->r_sp = VG_(threads)[tid].arch.vex.guest_r29;
110 regs->misc.MIPS32.r30
111 = VG_(threads)[tid].arch.vex.guest_r30;
112 regs->misc.MIPS32.r31
113 = VG_(threads)[tid].arch.vex.guest_r31;
114 regs->misc.MIPS32.r28
115 = VG_(threads)[tid].arch.vex.guest_r28;
sewardj59570ff2010-01-01 11:59:33 +0000116# else
117# error "Unknown arch"
118# endif
119}
120
121
sewardj9c606bd2008-09-18 18:12:50 +0000122void VG_(set_syscall_return_shadows) ( ThreadId tid,
123 /* shadow vals for the result */
124 UWord s1res, UWord s2res,
125 /* shadow vals for the error val */
126 UWord s1err, UWord s2err )
127{
128# if defined(VGP_x86_linux)
129 VG_(threads)[tid].arch.vex_shadow1.guest_EAX = s1res;
130 VG_(threads)[tid].arch.vex_shadow2.guest_EAX = s2res;
131# elif defined(VGP_amd64_linux)
132 VG_(threads)[tid].arch.vex_shadow1.guest_RAX = s1res;
133 VG_(threads)[tid].arch.vex_shadow2.guest_RAX = s2res;
134# elif defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
135 VG_(threads)[tid].arch.vex_shadow1.guest_GPR3 = s1res;
136 VG_(threads)[tid].arch.vex_shadow2.guest_GPR3 = s2res;
sewardj59570ff2010-01-01 11:59:33 +0000137# elif defined(VGP_arm_linux)
138 VG_(threads)[tid].arch.vex_shadow1.guest_R0 = s1res;
139 VG_(threads)[tid].arch.vex_shadow2.guest_R0 = s2res;
njnf76d27a2009-05-28 01:53:07 +0000140# elif defined(VGO_darwin)
141 // GrP fixme darwin syscalls may return more values (2 registers plus error)
sewardjb5b87402011-03-07 16:05:35 +0000142# elif defined(VGP_s390x_linux)
143 VG_(threads)[tid].arch.vex_shadow1.guest_r2 = s1res;
144 VG_(threads)[tid].arch.vex_shadow2.guest_r2 = s2res;
sewardj5db15402012-06-07 09:13:21 +0000145# elif defined(VGP_mips32_linux)
146 VG_(threads)[tid].arch.vex_shadow1.guest_r2 = s1res;
147 VG_(threads)[tid].arch.vex_shadow2.guest_r2 = s2res;
sewardj9c606bd2008-09-18 18:12:50 +0000148# else
149# error "Unknown plat"
150# endif
151}
njnf536bbb2005-06-13 04:21:38 +0000152
sewardj7cf4e6b2008-05-01 20:24:26 +0000153void
154VG_(get_shadow_regs_area) ( ThreadId tid,
155 /*DST*/UChar* dst,
njnc4431bf2009-01-15 21:29:24 +0000156 /*SRC*/Int shadowNo, PtrdiffT offset, SizeT size )
njnf536bbb2005-06-13 04:21:38 +0000157{
sewardj7cf4e6b2008-05-01 20:24:26 +0000158 void* src;
njnf536bbb2005-06-13 04:21:38 +0000159 ThreadState* tst;
sewardj9c606bd2008-09-18 18:12:50 +0000160 vg_assert(shadowNo == 0 || shadowNo == 1 || shadowNo == 2);
njnf536bbb2005-06-13 04:21:38 +0000161 vg_assert(VG_(is_valid_tid)(tid));
njnf536bbb2005-06-13 04:21:38 +0000162 // Bounds check
163 vg_assert(0 <= offset && offset < sizeof(VexGuestArchState));
164 vg_assert(offset + size <= sizeof(VexGuestArchState));
sewardj7cf4e6b2008-05-01 20:24:26 +0000165 // Copy
166 tst = & VG_(threads)[tid];
sewardj9c606bd2008-09-18 18:12:50 +0000167 src = NULL;
168 switch (shadowNo) {
169 case 0: src = (void*)(((Addr)&(tst->arch.vex)) + offset); break;
170 case 1: src = (void*)(((Addr)&(tst->arch.vex_shadow1)) + offset); break;
171 case 2: src = (void*)(((Addr)&(tst->arch.vex_shadow2)) + offset); break;
172 }
173 tl_assert(src != NULL);
sewardj7cf4e6b2008-05-01 20:24:26 +0000174 VG_(memcpy)( dst, src, size);
njnf536bbb2005-06-13 04:21:38 +0000175}
176
sewardj7cf4e6b2008-05-01 20:24:26 +0000177void
178VG_(set_shadow_regs_area) ( ThreadId tid,
njnc4431bf2009-01-15 21:29:24 +0000179 /*DST*/Int shadowNo, PtrdiffT offset, SizeT size,
sewardj7cf4e6b2008-05-01 20:24:26 +0000180 /*SRC*/const UChar* src )
njnf536bbb2005-06-13 04:21:38 +0000181{
sewardj7cf4e6b2008-05-01 20:24:26 +0000182 void* dst;
njnf536bbb2005-06-13 04:21:38 +0000183 ThreadState* tst;
sewardj9c606bd2008-09-18 18:12:50 +0000184 vg_assert(shadowNo == 0 || shadowNo == 1 || shadowNo == 2);
njnf536bbb2005-06-13 04:21:38 +0000185 vg_assert(VG_(is_valid_tid)(tid));
njnf536bbb2005-06-13 04:21:38 +0000186 // Bounds check
187 vg_assert(0 <= offset && offset < sizeof(VexGuestArchState));
188 vg_assert(offset + size <= sizeof(VexGuestArchState));
sewardj7cf4e6b2008-05-01 20:24:26 +0000189 // Copy
190 tst = & VG_(threads)[tid];
sewardj9c606bd2008-09-18 18:12:50 +0000191 dst = NULL;
192 switch (shadowNo) {
193 case 0: dst = (void*)(((Addr)&(tst->arch.vex)) + offset); break;
194 case 1: dst = (void*)(((Addr)&(tst->arch.vex_shadow1)) + offset); break;
195 case 2: dst = (void*)(((Addr)&(tst->arch.vex_shadow2)) + offset); break;
196 }
197 tl_assert(dst != NULL);
sewardj7cf4e6b2008-05-01 20:24:26 +0000198 VG_(memcpy)( dst, src, size);
njnf536bbb2005-06-13 04:21:38 +0000199}
200
201
florian6bd9dc12012-11-23 16:17:43 +0000202static void apply_to_GPs_of_tid(ThreadId tid, void (*f)(ThreadId,
203 const HChar*, Addr))
njn6ace3ea2005-06-17 03:06:27 +0000204{
philippea22f59d2012-01-26 23:13:52 +0000205 VexGuestArchState* vex = &(VG_(get_ThreadState)(tid)->arch.vex);
njn6ace3ea2005-06-17 03:06:27 +0000206#if defined(VGA_x86)
philippea22f59d2012-01-26 23:13:52 +0000207 (*f)(tid, "EAX", vex->guest_EAX);
208 (*f)(tid, "ECX", vex->guest_ECX);
209 (*f)(tid, "EDX", vex->guest_EDX);
210 (*f)(tid, "EBX", vex->guest_EBX);
211 (*f)(tid, "ESI", vex->guest_ESI);
212 (*f)(tid, "EDI", vex->guest_EDI);
213 (*f)(tid, "ESP", vex->guest_ESP);
214 (*f)(tid, "EBP", vex->guest_EBP);
njn6ace3ea2005-06-17 03:06:27 +0000215#elif defined(VGA_amd64)
philippea22f59d2012-01-26 23:13:52 +0000216 (*f)(tid, "RAX", vex->guest_RAX);
217 (*f)(tid, "RCX", vex->guest_RCX);
218 (*f)(tid, "RDX", vex->guest_RDX);
219 (*f)(tid, "RBX", vex->guest_RBX);
220 (*f)(tid, "RSI", vex->guest_RSI);
221 (*f)(tid, "RDI", vex->guest_RDI);
222 (*f)(tid, "RSP", vex->guest_RSP);
223 (*f)(tid, "RBP", vex->guest_RBP);
224 (*f)(tid, "R8" , vex->guest_R8 );
225 (*f)(tid, "R9" , vex->guest_R9 );
226 (*f)(tid, "R10", vex->guest_R10);
227 (*f)(tid, "R11", vex->guest_R11);
228 (*f)(tid, "R12", vex->guest_R12);
229 (*f)(tid, "R13", vex->guest_R13);
230 (*f)(tid, "R14", vex->guest_R14);
231 (*f)(tid, "R15", vex->guest_R15);
sewardj2c48c7b2005-11-29 13:05:56 +0000232#elif defined(VGA_ppc32) || defined(VGA_ppc64)
philippea22f59d2012-01-26 23:13:52 +0000233 (*f)(tid, "GPR0" , vex->guest_GPR0 );
234 (*f)(tid, "GPR1" , vex->guest_GPR1 );
235 (*f)(tid, "GPR2" , vex->guest_GPR2 );
236 (*f)(tid, "GPR3" , vex->guest_GPR3 );
237 (*f)(tid, "GPR4" , vex->guest_GPR4 );
238 (*f)(tid, "GPR5" , vex->guest_GPR5 );
239 (*f)(tid, "GPR6" , vex->guest_GPR6 );
240 (*f)(tid, "GPR7" , vex->guest_GPR7 );
241 (*f)(tid, "GPR8" , vex->guest_GPR8 );
242 (*f)(tid, "GPR9" , vex->guest_GPR9 );
243 (*f)(tid, "GPR10", vex->guest_GPR10);
244 (*f)(tid, "GPR11", vex->guest_GPR11);
245 (*f)(tid, "GPR12", vex->guest_GPR12);
246 (*f)(tid, "GPR13", vex->guest_GPR13);
247 (*f)(tid, "GPR14", vex->guest_GPR14);
248 (*f)(tid, "GPR15", vex->guest_GPR15);
249 (*f)(tid, "GPR16", vex->guest_GPR16);
250 (*f)(tid, "GPR17", vex->guest_GPR17);
251 (*f)(tid, "GPR18", vex->guest_GPR18);
252 (*f)(tid, "GPR19", vex->guest_GPR19);
253 (*f)(tid, "GPR20", vex->guest_GPR20);
254 (*f)(tid, "GPR21", vex->guest_GPR21);
255 (*f)(tid, "GPR22", vex->guest_GPR22);
256 (*f)(tid, "GPR23", vex->guest_GPR23);
257 (*f)(tid, "GPR24", vex->guest_GPR24);
258 (*f)(tid, "GPR25", vex->guest_GPR25);
259 (*f)(tid, "GPR26", vex->guest_GPR26);
260 (*f)(tid, "GPR27", vex->guest_GPR27);
261 (*f)(tid, "GPR28", vex->guest_GPR28);
262 (*f)(tid, "GPR29", vex->guest_GPR29);
263 (*f)(tid, "GPR30", vex->guest_GPR30);
264 (*f)(tid, "GPR31", vex->guest_GPR31);
265 (*f)(tid, "CTR" , vex->guest_CTR );
266 (*f)(tid, "LR" , vex->guest_LR );
sewardj59570ff2010-01-01 11:59:33 +0000267#elif defined(VGA_arm)
philippea22f59d2012-01-26 23:13:52 +0000268 (*f)(tid, "R0" , vex->guest_R0 );
269 (*f)(tid, "R1" , vex->guest_R1 );
270 (*f)(tid, "R2" , vex->guest_R2 );
271 (*f)(tid, "R3" , vex->guest_R3 );
272 (*f)(tid, "R4" , vex->guest_R4 );
273 (*f)(tid, "R5" , vex->guest_R5 );
274 (*f)(tid, "R6" , vex->guest_R6 );
275 (*f)(tid, "R8" , vex->guest_R8 );
276 (*f)(tid, "R9" , vex->guest_R9 );
277 (*f)(tid, "R10", vex->guest_R10);
278 (*f)(tid, "R11", vex->guest_R11);
279 (*f)(tid, "R12", vex->guest_R12);
280 (*f)(tid, "R13", vex->guest_R13);
281 (*f)(tid, "R14", vex->guest_R14);
sewardjb5b87402011-03-07 16:05:35 +0000282#elif defined(VGA_s390x)
philippea22f59d2012-01-26 23:13:52 +0000283 (*f)(tid, "r0" , vex->guest_r0 );
284 (*f)(tid, "r1" , vex->guest_r1 );
285 (*f)(tid, "r2" , vex->guest_r2 );
286 (*f)(tid, "r3" , vex->guest_r3 );
287 (*f)(tid, "r4" , vex->guest_r4 );
288 (*f)(tid, "r5" , vex->guest_r5 );
289 (*f)(tid, "r6" , vex->guest_r6 );
290 (*f)(tid, "r7" , vex->guest_r7 );
291 (*f)(tid, "r8" , vex->guest_r8 );
292 (*f)(tid, "r9" , vex->guest_r9 );
293 (*f)(tid, "r10", vex->guest_r10);
294 (*f)(tid, "r11", vex->guest_r11);
295 (*f)(tid, "r12", vex->guest_r12);
296 (*f)(tid, "r13", vex->guest_r13);
297 (*f)(tid, "r14", vex->guest_r14);
298 (*f)(tid, "r15", vex->guest_r15);
sewardj5db15402012-06-07 09:13:21 +0000299#elif defined(VGA_mips32)
300 (*f)(tid, "r0" , vex->guest_r0 );
301 (*f)(tid, "r1" , vex->guest_r1 );
302 (*f)(tid, "r2" , vex->guest_r2 );
303 (*f)(tid, "r3" , vex->guest_r3 );
304 (*f)(tid, "r4" , vex->guest_r4 );
305 (*f)(tid, "r5" , vex->guest_r5 );
306 (*f)(tid, "r6" , vex->guest_r6 );
307 (*f)(tid, "r7" , vex->guest_r7 );
308 (*f)(tid, "r8" , vex->guest_r8 );
309 (*f)(tid, "r9" , vex->guest_r9 );
310 (*f)(tid, "r10", vex->guest_r10);
311 (*f)(tid, "r11", vex->guest_r11);
312 (*f)(tid, "r12", vex->guest_r12);
313 (*f)(tid, "r13", vex->guest_r13);
314 (*f)(tid, "r14", vex->guest_r14);
315 (*f)(tid, "r15", vex->guest_r15);
316 (*f)(tid, "r16", vex->guest_r16);
317 (*f)(tid, "r17", vex->guest_r17);
318 (*f)(tid, "r18", vex->guest_r18);
319 (*f)(tid, "r19", vex->guest_r19);
320 (*f)(tid, "r20", vex->guest_r20);
321 (*f)(tid, "r21", vex->guest_r21);
322 (*f)(tid, "r22", vex->guest_r22);
323 (*f)(tid, "r23", vex->guest_r23);
324 (*f)(tid, "r24", vex->guest_r24);
325 (*f)(tid, "r25", vex->guest_r25);
326 (*f)(tid, "r26", vex->guest_r26);
327 (*f)(tid, "r27", vex->guest_r27);
328 (*f)(tid, "r28", vex->guest_r28);
329 (*f)(tid, "r29", vex->guest_r29);
330 (*f)(tid, "r30", vex->guest_r30);
331 (*f)(tid, "r31", vex->guest_r31);
njn6ace3ea2005-06-17 03:06:27 +0000332#else
333# error Unknown arch
334#endif
335}
336
337
florian6bd9dc12012-11-23 16:17:43 +0000338void VG_(apply_to_GP_regs)(void (*f)(ThreadId, const HChar*, UWord))
njn6ace3ea2005-06-17 03:06:27 +0000339{
340 ThreadId tid;
341
342 for (tid = 1; tid < VG_N_THREADS; tid++) {
343 if (VG_(is_valid_tid)(tid)) {
philippea22f59d2012-01-26 23:13:52 +0000344 apply_to_GPs_of_tid(tid, f);
njn6ace3ea2005-06-17 03:06:27 +0000345 }
346 }
347}
348
sewardjb8b79ad2008-03-03 01:35:41 +0000349void VG_(thread_stack_reset_iter)(/*OUT*/ThreadId* tid)
njnb506bd82005-06-21 04:01:51 +0000350{
sewardjb8b79ad2008-03-03 01:35:41 +0000351 *tid = (ThreadId)(-1);
njnb506bd82005-06-21 04:01:51 +0000352}
njn6ace3ea2005-06-17 03:06:27 +0000353
sewardjb8b79ad2008-03-03 01:35:41 +0000354Bool VG_(thread_stack_next)(/*MOD*/ThreadId* tid,
355 /*OUT*/Addr* stack_min,
356 /*OUT*/Addr* stack_max)
njn1d0cb0d2005-08-15 01:52:02 +0000357{
358 ThreadId i;
sewardjb8b79ad2008-03-03 01:35:41 +0000359 for (i = (*tid)+1; i < VG_N_THREADS; i++) {
360 if (i == VG_INVALID_THREADID)
361 continue;
njn1d0cb0d2005-08-15 01:52:02 +0000362 if (VG_(threads)[i].status != VgTs_Empty) {
363 *tid = i;
364 *stack_min = VG_(get_SP)(i);
365 *stack_max = VG_(threads)[i].client_stack_highest_word;
njn1d0cb0d2005-08-15 01:52:02 +0000366 return True;
367 }
368 }
369 return False;
370}
sewardj7821e2e2005-08-08 00:35:46 +0000371
sewardjbbec7722007-11-25 14:08:53 +0000372Addr VG_(thread_get_stack_max)(ThreadId tid)
373{
374 vg_assert(0 <= tid && tid < VG_N_THREADS && tid != VG_INVALID_THREADID);
375 vg_assert(VG_(threads)[tid].status != VgTs_Empty);
376 return VG_(threads)[tid].client_stack_highest_word;
377}
378
bart0fb03202008-03-29 09:25:53 +0000379SizeT VG_(thread_get_stack_size)(ThreadId tid)
380{
381 vg_assert(0 <= tid && tid < VG_N_THREADS && tid != VG_INVALID_THREADID);
382 vg_assert(VG_(threads)[tid].status != VgTs_Empty);
383 return VG_(threads)[tid].client_stack_szB;
384}
385
bart83c5a922010-09-02 14:38:38 +0000386Addr VG_(thread_get_altstack_min)(ThreadId tid)
387{
388 vg_assert(0 <= tid && tid < VG_N_THREADS && tid != VG_INVALID_THREADID);
389 vg_assert(VG_(threads)[tid].status != VgTs_Empty);
390 return (Addr)VG_(threads)[tid].altstack.ss_sp;
391}
392
393SizeT VG_(thread_get_altstack_size)(ThreadId tid)
394{
395 vg_assert(0 <= tid && tid < VG_N_THREADS && tid != VG_INVALID_THREADID);
396 vg_assert(VG_(threads)[tid].status != VgTs_Empty);
397 return VG_(threads)[tid].altstack.ss_size;
398}
399
sewardje2d1e672005-11-12 23:10:48 +0000400//-------------------------------------------------------------
401/* Details about the capabilities of the underlying (host) CPU. These
402 details are acquired by (1) enquiring with the CPU at startup, or
403 (2) from the AT_SYSINFO entries the kernel gave us (ppc32 cache
404 line size). It's a bit nasty in the sense that there's no obvious
405 way to stop uses of some of this info before it's ready to go.
florian0daa4e32012-04-22 02:48:20 +0000406 See pub_core_machine.h for more information about that.
sewardjb5b87402011-03-07 16:05:35 +0000407
sewardje2d1e672005-11-12 23:10:48 +0000408 VG_(machine_get_hwcaps) may use signals (although it attempts to
409 leave signal state unchanged) and therefore should only be
410 called before m_main sets up the client's signal state.
411*/
412
413/* --------- State --------- */
sewardj59570ff2010-01-01 11:59:33 +0000414static Bool hwcaps_done = False;
sewardje2d1e672005-11-12 23:10:48 +0000415
416/* --- all archs --- */
sewardj98763d52012-06-03 22:40:07 +0000417static VexArch va = VexArch_INVALID;
sewardje2d1e672005-11-12 23:10:48 +0000418static VexArchInfo vai;
sewardja48a4932005-09-29 11:09:56 +0000419
sewardj7821e2e2005-08-08 00:35:46 +0000420#if defined(VGA_x86)
sewardje2d1e672005-11-12 23:10:48 +0000421UInt VG_(machine_x86_have_mxcsr) = 0;
sewardj7821e2e2005-08-08 00:35:46 +0000422#endif
sewardje2d1e672005-11-12 23:10:48 +0000423#if defined(VGA_ppc32)
sewardj2c36d422005-11-13 01:59:22 +0000424UInt VG_(machine_ppc32_has_FP) = 0;
sewardje2d1e672005-11-12 23:10:48 +0000425UInt VG_(machine_ppc32_has_VMX) = 0;
426#endif
sewardj2c48c7b2005-11-29 13:05:56 +0000427#if defined(VGA_ppc64)
428ULong VG_(machine_ppc64_has_VMX) = 0;
429#endif
sewardj1dbd3372010-08-22 12:21:14 +0000430#if defined(VGA_arm)
431Int VG_(machine_arm_archlevel) = 4;
432#endif
sewardje2d1e672005-11-12 23:10:48 +0000433
sewardjb5b87402011-03-07 16:05:35 +0000434/* fixs390: anything for s390x here ? */
sewardje2d1e672005-11-12 23:10:48 +0000435
sewardj2c3f2ea2011-04-13 15:40:10 +0000436/* For hwcaps detection on ppc32/64, s390x, and arm we'll need to do SIGILL
sewardj6c591e12011-04-11 16:17:51 +0000437 testing, so we need a VG_MINIMAL_JMP_BUF. */
438#if defined(VGA_ppc32) || defined(VGA_ppc64) \
petarj2fd883a2012-06-30 02:12:13 +0000439 || defined(VGA_arm) || defined(VGA_s390x)
sewardj6c591e12011-04-11 16:17:51 +0000440#include "pub_tool_libcsetjmp.h"
sewardj97d3ebb2011-04-11 18:36:34 +0000441static VG_MINIMAL_JMP_BUF(env_unsup_insn);
sewardj6c591e12011-04-11 16:17:51 +0000442static void handler_unsup_insn ( Int x ) {
443 VG_MINIMAL_LONGJMP(env_unsup_insn);
444}
sewardj5ae70ce2010-09-08 15:12:33 +0000445#endif
446
sewardjb9c815b2010-09-03 15:51:34 +0000447
448/* Helper function for VG_(machine_get_hwcaps), assumes the SIGILL/etc
449 * handlers are installed. Determines the the sizes affected by dcbz
450 * and dcbzl instructions and updates the given VexArchInfo structure
451 * accordingly.
452 *
453 * Not very defensive: assumes that as long as the dcbz/dcbzl
454 * instructions don't raise a SIGILL, that they will zero an aligned,
455 * contiguous block of memory of a sensible size. */
sewardj5ae70ce2010-09-08 15:12:33 +0000456#if defined(VGA_ppc32) || defined(VGA_ppc64)
sewardjb9c815b2010-09-03 15:51:34 +0000457static void find_ppc_dcbz_sz(VexArchInfo *arch_info)
458{
sewardjdcb3a592010-09-04 00:43:14 +0000459 Int dcbz_szB = 0;
sewardjb9c815b2010-09-03 15:51:34 +0000460 Int dcbzl_szB;
sewardj5ae70ce2010-09-08 15:12:33 +0000461# define MAX_DCBZL_SZB (128) /* largest known effect of dcbzl */
sewardjb9c815b2010-09-03 15:51:34 +0000462 char test_block[4*MAX_DCBZL_SZB];
463 char *aligned = test_block;
464 Int i;
465
466 /* round up to next max block size, assumes MAX_DCBZL_SZB is pof2 */
467 aligned = (char *)(((HWord)aligned + MAX_DCBZL_SZB) & ~(MAX_DCBZL_SZB - 1));
468 vg_assert((aligned + MAX_DCBZL_SZB) <= &test_block[sizeof(test_block)]);
469
470 /* dcbz often clears 32B, although sometimes whatever the native cache
471 * block size is */
472 VG_(memset)(test_block, 0xff, sizeof(test_block));
473 __asm__ __volatile__("dcbz 0,%0"
474 : /*out*/
475 : "r" (aligned) /*in*/
476 : "memory" /*clobber*/);
477 for (dcbz_szB = 0, i = 0; i < sizeof(test_block); ++i) {
478 if (!test_block[i])
479 ++dcbz_szB;
480 }
481 vg_assert(dcbz_szB == 32 || dcbz_szB == 64 || dcbz_szB == 128);
482
483 /* dcbzl clears 128B on G5/PPC970, and usually 32B on other platforms */
sewardj6c591e12011-04-11 16:17:51 +0000484 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardjb9c815b2010-09-03 15:51:34 +0000485 dcbzl_szB = 0; /* indicates unsupported */
486 }
487 else {
488 VG_(memset)(test_block, 0xff, sizeof(test_block));
489 /* some older assemblers won't understand the dcbzl instruction
490 * variant, so we directly emit the instruction ourselves */
491 __asm__ __volatile__("mr 9, %0 ; .long 0x7C204FEC" /*dcbzl 0,9*/
492 : /*out*/
493 : "r" (aligned) /*in*/
494 : "memory", "r9" /*clobber*/);
495 for (dcbzl_szB = 0, i = 0; i < sizeof(test_block); ++i) {
496 if (!test_block[i])
497 ++dcbzl_szB;
498 }
499 vg_assert(dcbzl_szB == 32 || dcbzl_szB == 64 || dcbzl_szB == 128);
500 }
501
502 arch_info->ppc_dcbz_szB = dcbz_szB;
503 arch_info->ppc_dcbzl_szB = dcbzl_szB;
504
505 VG_(debugLog)(1, "machine", "dcbz_szB=%d dcbzl_szB=%d\n",
506 dcbz_szB, dcbzl_szB);
sewardj5ae70ce2010-09-08 15:12:33 +0000507# undef MAX_DCBZL_SZB
sewardjb9c815b2010-09-03 15:51:34 +0000508}
sewardj5ae70ce2010-09-08 15:12:33 +0000509#endif /* defined(VGA_ppc32) || defined(VGA_ppc64) */
510
sewardj2c3f2ea2011-04-13 15:40:10 +0000511#ifdef VGA_s390x
sewardj5ae70ce2010-09-08 15:12:33 +0000512
sewardj2c3f2ea2011-04-13 15:40:10 +0000513/* Read /proc/cpuinfo. Look for lines like these
514
515 processor 0: version = FF, identification = 0117C9, machine = 2064
516
florian4e63b8e2012-04-22 03:50:20 +0000517 and return the machine model. If the machine model could not be determined
518 or it is an unknown model, return VEX_S390X_MODEL_UNKNOWN. */
sewardj2c3f2ea2011-04-13 15:40:10 +0000519
520static UInt VG_(get_machine_model)(void)
521{
522 static struct model_map {
523 HChar name[5];
524 UInt id;
525 } model_map[] = {
526 { "2064", VEX_S390X_MODEL_Z900 },
527 { "2066", VEX_S390X_MODEL_Z800 },
528 { "2084", VEX_S390X_MODEL_Z990 },
529 { "2086", VEX_S390X_MODEL_Z890 },
530 { "2094", VEX_S390X_MODEL_Z9_EC },
531 { "2096", VEX_S390X_MODEL_Z9_BC },
532 { "2097", VEX_S390X_MODEL_Z10_EC },
533 { "2098", VEX_S390X_MODEL_Z10_BC },
534 { "2817", VEX_S390X_MODEL_Z196 },
florian258ede72011-09-02 22:20:41 +0000535 { "2818", VEX_S390X_MODEL_Z114 },
florian87a25cf2012-08-28 13:33:10 +0000536 { "2827", VEX_S390X_MODEL_ZEC12 },
sewardj2c3f2ea2011-04-13 15:40:10 +0000537 };
538
539 Int model, n, fh;
540 SysRes fd;
541 SizeT num_bytes, file_buf_size;
542 HChar *p, *m, *model_name, *file_buf;
543
544 /* Slurp contents of /proc/cpuinfo into FILE_BUF */
545 fd = VG_(open)( "/proc/cpuinfo", 0, VKI_S_IRUSR );
florian4e63b8e2012-04-22 03:50:20 +0000546 if ( sr_isError(fd) ) return VEX_S390X_MODEL_UNKNOWN;
sewardj2c3f2ea2011-04-13 15:40:10 +0000547
548 fh = sr_Res(fd);
549
550 /* Determine the size of /proc/cpuinfo.
551 Work around broken-ness in /proc file system implementation.
552 fstat returns a zero size for /proc/cpuinfo although it is
553 claimed to be a regular file. */
554 num_bytes = 0;
555 file_buf_size = 1000;
556 file_buf = VG_(malloc)("cpuinfo", file_buf_size + 1);
557 while (42) {
558 n = VG_(read)(fh, file_buf, file_buf_size);
559 if (n < 0) break;
560
561 num_bytes += n;
562 if (n < file_buf_size) break; /* reached EOF */
563 }
564
565 if (n < 0) num_bytes = 0; /* read error; ignore contents */
566
567 if (num_bytes > file_buf_size) {
568 VG_(free)( file_buf );
569 VG_(lseek)( fh, 0, VKI_SEEK_SET );
570 file_buf = VG_(malloc)( "cpuinfo", num_bytes + 1 );
571 n = VG_(read)( fh, file_buf, num_bytes );
572 if (n < 0) num_bytes = 0;
573 }
574
575 file_buf[num_bytes] = '\0';
576 VG_(close)(fh);
577
578 /* Parse file */
florian4e63b8e2012-04-22 03:50:20 +0000579 model = VEX_S390X_MODEL_UNKNOWN;
sewardj2c3f2ea2011-04-13 15:40:10 +0000580 for (p = file_buf; *p; ++p) {
581 /* Beginning of line */
582 if (VG_(strncmp)( p, "processor", sizeof "processor" - 1 ) != 0) continue;
583
584 m = VG_(strstr)( p, "machine" );
585 if (m == NULL) continue;
586
587 p = m + sizeof "machine" - 1;
588 while ( VG_(isspace)( *p ) || *p == '=') {
589 if (*p == '\n') goto next_line;
590 ++p;
591 }
592
593 model_name = p;
594 for (n = 0; n < sizeof model_map / sizeof model_map[0]; ++n) {
595 struct model_map *mm = model_map + n;
596 SizeT len = VG_(strlen)( mm->name );
597 if ( VG_(strncmp)( mm->name, model_name, len ) == 0 &&
598 VG_(isspace)( model_name[len] )) {
599 if (mm->id < model) model = mm->id;
600 p = model_name + len;
601 break;
602 }
603 }
604 /* Skip until end-of-line */
605 while (*p != '\n')
606 ++p;
607 next_line: ;
608 }
609
610 VG_(free)( file_buf );
florian00164922011-10-25 21:37:15 +0000611 VG_(debugLog)(1, "machine", "model = %s\n",
florian4e63b8e2012-04-22 03:50:20 +0000612 model == VEX_S390X_MODEL_UNKNOWN ? "UNKNOWN"
florian00164922011-10-25 21:37:15 +0000613 : model_map[model].name);
sewardj2c3f2ea2011-04-13 15:40:10 +0000614 return model;
615}
616
617#endif /* VGA_s390x */
sewardj5ae70ce2010-09-08 15:12:33 +0000618
sewardj5db15402012-06-07 09:13:21 +0000619#ifdef VGA_mips32
620
621/* Read /proc/cpuinfo and return the machine model. */
622static UInt VG_(get_machine_model)(void)
623{
624 char *search_MIPS_str = "MIPS";
625 char *search_Broadcom_str = "Broadcom";
626 Int n, fh;
627 SysRes fd;
628 SizeT num_bytes, file_buf_size;
629 HChar *file_buf;
630
631 /* Slurp contents of /proc/cpuinfo into FILE_BUF */
632 fd = VG_(open)( "/proc/cpuinfo", 0, VKI_S_IRUSR );
633 if ( sr_isError(fd) ) return -1;
634
635 fh = sr_Res(fd);
636
637 /* Determine the size of /proc/cpuinfo.
638 Work around broken-ness in /proc file system implementation.
639 fstat returns a zero size for /proc/cpuinfo although it is
640 claimed to be a regular file. */
641 num_bytes = 0;
642 file_buf_size = 1000;
643 file_buf = VG_(malloc)("cpuinfo", file_buf_size + 1);
644 while (42) {
645 n = VG_(read)(fh, file_buf, file_buf_size);
646 if (n < 0) break;
647
648 num_bytes += n;
649 if (n < file_buf_size) break; /* reached EOF */
650 }
651
652 if (n < 0) num_bytes = 0; /* read error; ignore contents */
653
654 if (num_bytes > file_buf_size) {
655 VG_(free)( file_buf );
656 VG_(lseek)( fh, 0, VKI_SEEK_SET );
657 file_buf = VG_(malloc)( "cpuinfo", num_bytes + 1 );
658 n = VG_(read)( fh, file_buf, num_bytes );
659 if (n < 0) num_bytes = 0;
660 }
661
662 file_buf[num_bytes] = '\0';
663 VG_(close)(fh);
664
665 /* Parse file */
666 if (VG_(strstr) (file_buf, search_Broadcom_str) != NULL)
667 return VEX_PRID_COMP_BROADCOM;
668 if (VG_(strstr) (file_buf, search_MIPS_str) != NULL)
669 return VEX_PRID_COMP_MIPS;
670
671 /* Did not find string in the proc file. */
672 return -1;
673}
674
675#endif
676
sewardj5ae70ce2010-09-08 15:12:33 +0000677/* Determine what insn set and insn set variant the host has, and
678 record it. To be called once at system startup. Returns False if
florian78627012012-10-07 19:47:04 +0000679 this a CPU incapable of running Valgrind.
680 Also determine information about the caches on this host. */
sewardje3826cf2005-11-13 00:30:22 +0000681
sewardje2d1e672005-11-12 23:10:48 +0000682Bool VG_(machine_get_hwcaps)( void )
683{
684 vg_assert(hwcaps_done == False);
685 hwcaps_done = True;
686
687 // Whack default settings into vai, so that we only need to fill in
688 // any interesting bits.
689 LibVEX_default_VexArchInfo(&vai);
690
691#if defined(VGA_x86)
sewardj40d91c72010-07-29 15:40:32 +0000692 { Bool have_sse1, have_sse2, have_cx8, have_lzcnt;
sewardjc7ffc942011-03-28 16:26:42 +0000693 UInt eax, ebx, ecx, edx, max_extended;
sewardj66826ec2012-11-19 14:55:15 +0000694 HChar vstr[13];
sewardj40d91c72010-07-29 15:40:32 +0000695 vstr[0] = 0;
sewardje2d1e672005-11-12 23:10:48 +0000696
697 if (!VG_(has_cpuid)())
698 /* we can't do cpuid at all. Give up. */
699 return False;
700
tomad8a5912011-06-10 15:04:22 +0000701 VG_(cpuid)(0, 0, &eax, &ebx, &ecx, &edx);
sewardje2d1e672005-11-12 23:10:48 +0000702 if (eax < 1)
703 /* we can't ask for cpuid(x) for x > 0. Give up. */
704 return False;
705
sewardj40d91c72010-07-29 15:40:32 +0000706 /* Get processor ID string, and max basic/extended index
707 values. */
sewardj40d91c72010-07-29 15:40:32 +0000708 VG_(memcpy)(&vstr[0], &ebx, 4);
709 VG_(memcpy)(&vstr[4], &edx, 4);
710 VG_(memcpy)(&vstr[8], &ecx, 4);
711 vstr[12] = 0;
712
tomad8a5912011-06-10 15:04:22 +0000713 VG_(cpuid)(0x80000000, 0, &eax, &ebx, &ecx, &edx);
sewardj40d91c72010-07-29 15:40:32 +0000714 max_extended = eax;
715
sewardje2d1e672005-11-12 23:10:48 +0000716 /* get capabilities bits into edx */
tomad8a5912011-06-10 15:04:22 +0000717 VG_(cpuid)(1, 0, &eax, &ebx, &ecx, &edx);
sewardje2d1e672005-11-12 23:10:48 +0000718
719 have_sse1 = (edx & (1<<25)) != 0; /* True => have sse insns */
720 have_sse2 = (edx & (1<<26)) != 0; /* True => have sse2 insns */
721
sewardj1c0ce7a2009-07-01 08:10:49 +0000722 /* cmpxchg8b is a minimum requirement now; if we don't have it we
723 must simply give up. But all CPUs since Pentium-I have it, so
724 that doesn't seem like much of a restriction. */
725 have_cx8 = (edx & (1<<8)) != 0; /* True => have cmpxchg8b */
726 if (!have_cx8)
727 return False;
728
sewardj40d91c72010-07-29 15:40:32 +0000729 /* Figure out if this is an AMD that can do LZCNT. */
730 have_lzcnt = False;
731 if (0 == VG_(strcmp)(vstr, "AuthenticAMD")
732 && max_extended >= 0x80000001) {
tomad8a5912011-06-10 15:04:22 +0000733 VG_(cpuid)(0x80000001, 0, &eax, &ebx, &ecx, &edx);
sewardj40d91c72010-07-29 15:40:32 +0000734 have_lzcnt = (ecx & (1<<5)) != 0; /* True => have LZCNT */
735 }
736
florian78627012012-10-07 19:47:04 +0000737 va = VexArchX86;
sewardje2d1e672005-11-12 23:10:48 +0000738 if (have_sse2 && have_sse1) {
sewardje3121f32006-01-27 21:23:23 +0000739 vai.hwcaps = VEX_HWCAPS_X86_SSE1;
740 vai.hwcaps |= VEX_HWCAPS_X86_SSE2;
sewardj40d91c72010-07-29 15:40:32 +0000741 if (have_lzcnt)
742 vai.hwcaps |= VEX_HWCAPS_X86_LZCNT;
sewardje2d1e672005-11-12 23:10:48 +0000743 VG_(machine_x86_have_mxcsr) = 1;
florian78627012012-10-07 19:47:04 +0000744 } else if (have_sse1) {
sewardje3121f32006-01-27 21:23:23 +0000745 vai.hwcaps = VEX_HWCAPS_X86_SSE1;
sewardje2d1e672005-11-12 23:10:48 +0000746 VG_(machine_x86_have_mxcsr) = 1;
florian78627012012-10-07 19:47:04 +0000747 } else {
748 vai.hwcaps = 0; /*baseline - no sse at all*/
749 VG_(machine_x86_have_mxcsr) = 0;
sewardje2d1e672005-11-12 23:10:48 +0000750 }
751
florian78627012012-10-07 19:47:04 +0000752 VG_(machine_get_cache_info)(&vai);
753
sewardje2d1e672005-11-12 23:10:48 +0000754 return True;
755 }
756
757#elif defined(VGA_amd64)
sewardjc7ffc942011-03-28 16:26:42 +0000758 { Bool have_sse3, have_cx8, have_cx16;
sewardjee1a8972012-04-26 14:17:50 +0000759 Bool have_lzcnt, have_avx /*, have_fma*/;
sewardjc7ffc942011-03-28 16:26:42 +0000760 UInt eax, ebx, ecx, edx, max_extended;
florian19f91bb2012-11-10 22:29:54 +0000761 HChar vstr[13];
sewardj40d91c72010-07-29 15:40:32 +0000762 vstr[0] = 0;
sewardj1c0ce7a2009-07-01 08:10:49 +0000763
764 if (!VG_(has_cpuid)())
765 /* we can't do cpuid at all. Give up. */
766 return False;
767
tomad8a5912011-06-10 15:04:22 +0000768 VG_(cpuid)(0, 0, &eax, &ebx, &ecx, &edx);
sewardj1c0ce7a2009-07-01 08:10:49 +0000769 if (eax < 1)
770 /* we can't ask for cpuid(x) for x > 0. Give up. */
771 return False;
772
sewardj40d91c72010-07-29 15:40:32 +0000773 /* Get processor ID string, and max basic/extended index
774 values. */
sewardj40d91c72010-07-29 15:40:32 +0000775 VG_(memcpy)(&vstr[0], &ebx, 4);
776 VG_(memcpy)(&vstr[4], &edx, 4);
777 VG_(memcpy)(&vstr[8], &ecx, 4);
778 vstr[12] = 0;
779
tomad8a5912011-06-10 15:04:22 +0000780 VG_(cpuid)(0x80000000, 0, &eax, &ebx, &ecx, &edx);
sewardj40d91c72010-07-29 15:40:32 +0000781 max_extended = eax;
782
sewardj1c0ce7a2009-07-01 08:10:49 +0000783 /* get capabilities bits into edx */
tomad8a5912011-06-10 15:04:22 +0000784 VG_(cpuid)(1, 0, &eax, &ebx, &ecx, &edx);
sewardj1c0ce7a2009-07-01 08:10:49 +0000785
sewardjc7ffc942011-03-28 16:26:42 +0000786 // we assume that SSE1 and SSE2 are available by default
sewardj598971e2009-07-12 13:19:04 +0000787 have_sse3 = (ecx & (1<<0)) != 0; /* True => have sse3 insns */
sewardjee1a8972012-04-26 14:17:50 +0000788 // ssse3 is ecx:9
789 // sse41 is ecx:19
790 // sse42 is ecx:20
791
792 // osxsave is ecx:27
793 // avx is ecx:28
794 // fma is ecx:12
795 have_avx = False;
796 /* have_fma = False; */
797 if ( (ecx & ((1<<27)|(1<<28))) == ((1<<27)|(1<<28)) ) {
798 /* processor supports AVX instructions and XGETBV is enabled
799 by OS */
800 ULong w;
801 __asm__ __volatile__("movq $0,%%rcx ; "
802 ".byte 0x0F,0x01,0xD0 ; " /* xgetbv */
803 "movq %%rax,%0"
804 :/*OUT*/"=r"(w) :/*IN*/
805 :/*TRASH*/"rdx","rcx");
806 if ((w & 6) == 6) {
807 /* OS has enabled both XMM and YMM state support */
808 have_avx = True;
809 /* have_fma = (ecx & (1<<12)) != 0; */
810 /* have_fma: Probably correct, but gcc complains due to
811 unusedness. &*/
812 }
813 }
814
sewardj1c0ce7a2009-07-01 08:10:49 +0000815
816 /* cmpxchg8b is a minimum requirement now; if we don't have it we
817 must simply give up. But all CPUs since Pentium-I have it, so
818 that doesn't seem like much of a restriction. */
819 have_cx8 = (edx & (1<<8)) != 0; /* True => have cmpxchg8b */
820 if (!have_cx8)
821 return False;
822
823 /* on amd64 we tolerate older cpus, which don't have cmpxchg16b */
824 have_cx16 = (ecx & (1<<13)) != 0; /* True => have cmpxchg16b */
825
sewardj40d91c72010-07-29 15:40:32 +0000826 /* Figure out if this is an AMD that can do LZCNT. */
827 have_lzcnt = False;
828 if (0 == VG_(strcmp)(vstr, "AuthenticAMD")
829 && max_extended >= 0x80000001) {
tomad8a5912011-06-10 15:04:22 +0000830 VG_(cpuid)(0x80000001, 0, &eax, &ebx, &ecx, &edx);
sewardj40d91c72010-07-29 15:40:32 +0000831 have_lzcnt = (ecx & (1<<5)) != 0; /* True => have LZCNT */
832 }
833
sewardj1c0ce7a2009-07-01 08:10:49 +0000834 va = VexArchAMD64;
sewardjee1a8972012-04-26 14:17:50 +0000835 vai.hwcaps = (have_sse3 ? VEX_HWCAPS_AMD64_SSE3 : 0)
836 | (have_cx16 ? VEX_HWCAPS_AMD64_CX16 : 0)
837 | (have_lzcnt ? VEX_HWCAPS_AMD64_LZCNT : 0)
838 | (have_avx ? VEX_HWCAPS_AMD64_AVX : 0);
florian78627012012-10-07 19:47:04 +0000839
840 VG_(machine_get_cache_info)(&vai);
841
sewardj1c0ce7a2009-07-01 08:10:49 +0000842 return True;
843 }
sewardje2d1e672005-11-12 23:10:48 +0000844
845#elif defined(VGA_ppc32)
bart1581e742009-01-13 07:49:14 +0000846 {
847 /* Find out which subset of the ppc32 instruction set is supported by
848 verifying whether various ppc32 instructions generate a SIGILL
849 or a SIGFPE. An alternative approach is to check the AT_HWCAP and
850 AT_PLATFORM entries in the ELF auxiliary table -- see also
851 the_iifii.client_auxv in m_main.c.
852 */
njncda2f0f2009-05-18 02:12:08 +0000853 vki_sigset_t saved_set, tmp_set;
854 vki_sigaction_fromK_t saved_sigill_act, saved_sigfpe_act;
855 vki_sigaction_toK_t tmp_sigill_act, tmp_sigfpe_act;
sewardje3826cf2005-11-13 00:30:22 +0000856
sewardj5ba075a2012-04-02 21:25:14 +0000857 volatile Bool have_F, have_V, have_FX, have_GX, have_VX, have_DFP;
sewardj7637e9e2006-02-21 17:11:11 +0000858 Int r;
sewardje3826cf2005-11-13 00:30:22 +0000859
njncda2f0f2009-05-18 02:12:08 +0000860 /* This is a kludge. Really we ought to back-convert saved_act
861 into a toK_t using VG_(convert_sigaction_fromK_to_toK), but
862 since that's a no-op on all ppc32 platforms so far supported,
863 it's not worth the typing effort. At least include most basic
864 sanity check: */
865 vg_assert(sizeof(vki_sigaction_fromK_t) == sizeof(vki_sigaction_toK_t));
866
sewardje3826cf2005-11-13 00:30:22 +0000867 VG_(sigemptyset)(&tmp_set);
868 VG_(sigaddset)(&tmp_set, VKI_SIGILL);
bart1581e742009-01-13 07:49:14 +0000869 VG_(sigaddset)(&tmp_set, VKI_SIGFPE);
sewardje3826cf2005-11-13 00:30:22 +0000870
sewardj7637e9e2006-02-21 17:11:11 +0000871 r = VG_(sigprocmask)(VKI_SIG_UNBLOCK, &tmp_set, &saved_set);
872 vg_assert(r == 0);
sewardje3826cf2005-11-13 00:30:22 +0000873
bart1581e742009-01-13 07:49:14 +0000874 r = VG_(sigaction)(VKI_SIGILL, NULL, &saved_sigill_act);
sewardj7637e9e2006-02-21 17:11:11 +0000875 vg_assert(r == 0);
bart1581e742009-01-13 07:49:14 +0000876 tmp_sigill_act = saved_sigill_act;
877
878 r = VG_(sigaction)(VKI_SIGFPE, NULL, &saved_sigfpe_act);
879 vg_assert(r == 0);
880 tmp_sigfpe_act = saved_sigfpe_act;
sewardje3826cf2005-11-13 00:30:22 +0000881
sewardj7637e9e2006-02-21 17:11:11 +0000882 /* NODEFER: signal handler does not return (from the kernel's point of
883 view), hence if it is to successfully catch a signal more than once,
884 we need the NODEFER flag. */
bart1581e742009-01-13 07:49:14 +0000885 tmp_sigill_act.sa_flags &= ~VKI_SA_RESETHAND;
886 tmp_sigill_act.sa_flags &= ~VKI_SA_SIGINFO;
887 tmp_sigill_act.sa_flags |= VKI_SA_NODEFER;
888 tmp_sigill_act.ksa_handler = handler_unsup_insn;
889 r = VG_(sigaction)(VKI_SIGILL, &tmp_sigill_act, NULL);
890 vg_assert(r == 0);
891
892 tmp_sigfpe_act.sa_flags &= ~VKI_SA_RESETHAND;
893 tmp_sigfpe_act.sa_flags &= ~VKI_SA_SIGINFO;
894 tmp_sigfpe_act.sa_flags |= VKI_SA_NODEFER;
895 tmp_sigfpe_act.ksa_handler = handler_unsup_insn;
896 r = VG_(sigaction)(VKI_SIGFPE, &tmp_sigfpe_act, NULL);
897 vg_assert(r == 0);
sewardje3826cf2005-11-13 00:30:22 +0000898
sewardje3121f32006-01-27 21:23:23 +0000899 /* standard FP insns */
900 have_F = True;
sewardj6c591e12011-04-11 16:17:51 +0000901 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardje3121f32006-01-27 21:23:23 +0000902 have_F = False;
sewardje3826cf2005-11-13 00:30:22 +0000903 } else {
sewardjf1c91e02006-10-17 01:35:58 +0000904 __asm__ __volatile__(".long 0xFC000090"); /*fmr 0,0 */
sewardje3826cf2005-11-13 00:30:22 +0000905 }
906
sewardje3121f32006-01-27 21:23:23 +0000907 /* Altivec insns */
908 have_V = True;
sewardj6c591e12011-04-11 16:17:51 +0000909 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardje3121f32006-01-27 21:23:23 +0000910 have_V = False;
sewardje3826cf2005-11-13 00:30:22 +0000911 } else {
sewardj71592122006-04-04 03:29:48 +0000912 /* Unfortunately some older assemblers don't speak Altivec (or
913 choose not to), so to be safe we directly emit the 32-bit
914 word corresponding to "vor 0,0,0". This fixes a build
915 problem that happens on Debian 3.1 (ppc32), and probably
916 various other places. */
sewardj54d0dc72006-04-04 03:08:49 +0000917 __asm__ __volatile__(".long 0x10000484"); /*vor 0,0,0*/
sewardje3826cf2005-11-13 00:30:22 +0000918 }
919
sewardje3121f32006-01-27 21:23:23 +0000920 /* General-Purpose optional (fsqrt, fsqrts) */
921 have_FX = True;
sewardj6c591e12011-04-11 16:17:51 +0000922 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardje3121f32006-01-27 21:23:23 +0000923 have_FX = False;
924 } else {
sewardjf1c91e02006-10-17 01:35:58 +0000925 __asm__ __volatile__(".long 0xFC00002C"); /*fsqrt 0,0 */
sewardje3121f32006-01-27 21:23:23 +0000926 }
927
928 /* Graphics optional (stfiwx, fres, frsqrte, fsel) */
929 have_GX = True;
sewardj6c591e12011-04-11 16:17:51 +0000930 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardje3121f32006-01-27 21:23:23 +0000931 have_GX = False;
932 } else {
sewardjf1c91e02006-10-17 01:35:58 +0000933 __asm__ __volatile__(".long 0xFC000034"); /* frsqrte 0,0 */
sewardje3121f32006-01-27 21:23:23 +0000934 }
935
sewardjf34eb492011-04-15 11:57:05 +0000936 /* VSX support implies Power ISA 2.06 */
937 have_VX = True;
938 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
939 have_VX = False;
940 } else {
941 __asm__ __volatile__(".long 0xf0000564"); /* xsabsdp XT,XB */
942 }
943
sewardj5ba075a2012-04-02 21:25:14 +0000944 /* Check for Decimal Floating Point (DFP) support. */
945 have_DFP = True;
946 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
947 have_DFP = False;
948 } else {
949 __asm__ __volatile__(".long 0xee4e8005"); /* dadd FRT,FRA, FRB */
950 }
sewardjf34eb492011-04-15 11:57:05 +0000951
sewardjb9c815b2010-09-03 15:51:34 +0000952 /* determine dcbz/dcbzl sizes while we still have the signal
953 * handlers registered */
954 find_ppc_dcbz_sz(&vai);
955
bart1581e742009-01-13 07:49:14 +0000956 r = VG_(sigaction)(VKI_SIGILL, &saved_sigill_act, NULL);
957 vg_assert(r == 0);
958 r = VG_(sigaction)(VKI_SIGFPE, &saved_sigfpe_act, NULL);
sewardj7637e9e2006-02-21 17:11:11 +0000959 vg_assert(r == 0);
960 r = VG_(sigprocmask)(VKI_SIG_SETMASK, &saved_set, NULL);
961 vg_assert(r == 0);
sewardj5ba075a2012-04-02 21:25:14 +0000962 VG_(debugLog)(1, "machine", "F %d V %d FX %d GX %d VX %d DFP %d\n",
sewardjf34eb492011-04-15 11:57:05 +0000963 (Int)have_F, (Int)have_V, (Int)have_FX,
sewardj5ba075a2012-04-02 21:25:14 +0000964 (Int)have_GX, (Int)have_VX, (Int)have_DFP);
sewardje3121f32006-01-27 21:23:23 +0000965 /* Make FP a prerequisite for VMX (bogusly so), and for FX and GX. */
966 if (have_V && !have_F)
967 have_V = False;
968 if (have_FX && !have_F)
969 have_FX = False;
970 if (have_GX && !have_F)
971 have_GX = False;
sewardje3826cf2005-11-13 00:30:22 +0000972
sewardje3121f32006-01-27 21:23:23 +0000973 VG_(machine_ppc32_has_FP) = have_F ? 1 : 0;
974 VG_(machine_ppc32_has_VMX) = have_V ? 1 : 0;
sewardje3826cf2005-11-13 00:30:22 +0000975
976 va = VexArchPPC32;
977
sewardje3121f32006-01-27 21:23:23 +0000978 vai.hwcaps = 0;
979 if (have_F) vai.hwcaps |= VEX_HWCAPS_PPC32_F;
980 if (have_V) vai.hwcaps |= VEX_HWCAPS_PPC32_V;
981 if (have_FX) vai.hwcaps |= VEX_HWCAPS_PPC32_FX;
982 if (have_GX) vai.hwcaps |= VEX_HWCAPS_PPC32_GX;
sewardjf34eb492011-04-15 11:57:05 +0000983 if (have_VX) vai.hwcaps |= VEX_HWCAPS_PPC32_VX;
sewardj5ba075a2012-04-02 21:25:14 +0000984 if (have_DFP) vai.hwcaps |= VEX_HWCAPS_PPC32_DFP;
985
florian78627012012-10-07 19:47:04 +0000986 VG_(machine_get_cache_info)(&vai);
sewardje3826cf2005-11-13 00:30:22 +0000987
988 /* But we're not done yet: VG_(machine_ppc32_set_clszB) must be
989 called before we're ready to go. */
990 return True;
991 }
sewardje2d1e672005-11-12 23:10:48 +0000992
sewardj2c48c7b2005-11-29 13:05:56 +0000993#elif defined(VGA_ppc64)
bart1581e742009-01-13 07:49:14 +0000994 {
995 /* Same instruction set detection algorithm as for ppc32. */
njncda2f0f2009-05-18 02:12:08 +0000996 vki_sigset_t saved_set, tmp_set;
997 vki_sigaction_fromK_t saved_sigill_act, saved_sigfpe_act;
998 vki_sigaction_toK_t tmp_sigill_act, tmp_sigfpe_act;
sewardj2c48c7b2005-11-29 13:05:56 +0000999
sewardj5ba075a2012-04-02 21:25:14 +00001000 volatile Bool have_F, have_V, have_FX, have_GX, have_VX, have_DFP;
njncda2f0f2009-05-18 02:12:08 +00001001 Int r;
1002
1003 /* This is a kludge. Really we ought to back-convert saved_act
1004 into a toK_t using VG_(convert_sigaction_fromK_to_toK), but
1005 since that's a no-op on all ppc64 platforms so far supported,
1006 it's not worth the typing effort. At least include most basic
1007 sanity check: */
1008 vg_assert(sizeof(vki_sigaction_fromK_t) == sizeof(vki_sigaction_toK_t));
sewardj2c48c7b2005-11-29 13:05:56 +00001009
1010 VG_(sigemptyset)(&tmp_set);
1011 VG_(sigaddset)(&tmp_set, VKI_SIGILL);
bart1581e742009-01-13 07:49:14 +00001012 VG_(sigaddset)(&tmp_set, VKI_SIGFPE);
sewardj2c48c7b2005-11-29 13:05:56 +00001013
njncda2f0f2009-05-18 02:12:08 +00001014 r = VG_(sigprocmask)(VKI_SIG_UNBLOCK, &tmp_set, &saved_set);
1015 vg_assert(r == 0);
sewardj2c48c7b2005-11-29 13:05:56 +00001016
njncda2f0f2009-05-18 02:12:08 +00001017 r = VG_(sigaction)(VKI_SIGILL, NULL, &saved_sigill_act);
1018 vg_assert(r == 0);
bart1581e742009-01-13 07:49:14 +00001019 tmp_sigill_act = saved_sigill_act;
1020
1021 VG_(sigaction)(VKI_SIGFPE, NULL, &saved_sigfpe_act);
1022 tmp_sigfpe_act = saved_sigfpe_act;
1023
sewardj7637e9e2006-02-21 17:11:11 +00001024 /* NODEFER: signal handler does not return (from the kernel's point of
1025 view), hence if it is to successfully catch a signal more than once,
1026 we need the NODEFER flag. */
bart1581e742009-01-13 07:49:14 +00001027 tmp_sigill_act.sa_flags &= ~VKI_SA_RESETHAND;
1028 tmp_sigill_act.sa_flags &= ~VKI_SA_SIGINFO;
1029 tmp_sigill_act.sa_flags |= VKI_SA_NODEFER;
1030 tmp_sigill_act.ksa_handler = handler_unsup_insn;
1031 VG_(sigaction)(VKI_SIGILL, &tmp_sigill_act, NULL);
1032
1033 tmp_sigfpe_act.sa_flags &= ~VKI_SA_RESETHAND;
1034 tmp_sigfpe_act.sa_flags &= ~VKI_SA_SIGINFO;
1035 tmp_sigfpe_act.sa_flags |= VKI_SA_NODEFER;
1036 tmp_sigfpe_act.ksa_handler = handler_unsup_insn;
1037 VG_(sigaction)(VKI_SIGFPE, &tmp_sigfpe_act, NULL);
sewardj2c48c7b2005-11-29 13:05:56 +00001038
sewardje3121f32006-01-27 21:23:23 +00001039 /* standard FP insns */
1040 have_F = True;
sewardj6c591e12011-04-11 16:17:51 +00001041 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardje3121f32006-01-27 21:23:23 +00001042 have_F = False;
1043 } else {
1044 __asm__ __volatile__("fmr 0,0");
1045 }
1046
1047 /* Altivec insns */
1048 have_V = True;
sewardj6c591e12011-04-11 16:17:51 +00001049 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardje3121f32006-01-27 21:23:23 +00001050 have_V = False;
sewardj2c48c7b2005-11-29 13:05:56 +00001051 } else {
sewardjf1c91e02006-10-17 01:35:58 +00001052 __asm__ __volatile__(".long 0x10000484"); /*vor 0,0,0*/
sewardj2c48c7b2005-11-29 13:05:56 +00001053 }
1054
sewardje3121f32006-01-27 21:23:23 +00001055 /* General-Purpose optional (fsqrt, fsqrts) */
1056 have_FX = True;
sewardj6c591e12011-04-11 16:17:51 +00001057 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardje3121f32006-01-27 21:23:23 +00001058 have_FX = False;
1059 } else {
sewardjf1c91e02006-10-17 01:35:58 +00001060 __asm__ __volatile__(".long 0xFC00002C"); /*fsqrt 0,0*/
sewardje3121f32006-01-27 21:23:23 +00001061 }
1062
1063 /* Graphics optional (stfiwx, fres, frsqrte, fsel) */
1064 have_GX = True;
sewardj6c591e12011-04-11 16:17:51 +00001065 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardje3121f32006-01-27 21:23:23 +00001066 have_GX = False;
1067 } else {
sewardjf1c91e02006-10-17 01:35:58 +00001068 __asm__ __volatile__(".long 0xFC000034"); /*frsqrte 0,0*/
sewardje3121f32006-01-27 21:23:23 +00001069 }
1070
sewardjf34eb492011-04-15 11:57:05 +00001071 /* VSX support implies Power ISA 2.06 */
1072 have_VX = True;
1073 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
1074 have_VX = False;
1075 } else {
1076 __asm__ __volatile__(".long 0xf0000564"); /* xsabsdp XT,XB */
1077 }
1078
sewardj5ba075a2012-04-02 21:25:14 +00001079 /* Check for Decimal Floating Point (DFP) support. */
1080 have_DFP = True;
1081 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
1082 have_DFP = False;
1083 } else {
1084 __asm__ __volatile__(".long 0xee4e8005"); /* dadd FRT,FRA, FRB */
1085 }
1086
sewardjb9c815b2010-09-03 15:51:34 +00001087 /* determine dcbz/dcbzl sizes while we still have the signal
1088 * handlers registered */
1089 find_ppc_dcbz_sz(&vai);
1090
bart1581e742009-01-13 07:49:14 +00001091 VG_(sigaction)(VKI_SIGILL, &saved_sigill_act, NULL);
1092 VG_(sigaction)(VKI_SIGFPE, &saved_sigfpe_act, NULL);
sewardj2c48c7b2005-11-29 13:05:56 +00001093 VG_(sigprocmask)(VKI_SIG_SETMASK, &saved_set, NULL);
sewardj5ba075a2012-04-02 21:25:14 +00001094 VG_(debugLog)(1, "machine", "F %d V %d FX %d GX %d VX %d DFP %d\n",
sewardjf34eb492011-04-15 11:57:05 +00001095 (Int)have_F, (Int)have_V, (Int)have_FX,
sewardj5ba075a2012-04-02 21:25:14 +00001096 (Int)have_GX, (Int)have_VX, (Int)have_DFP);
sewardje3121f32006-01-27 21:23:23 +00001097 /* on ppc64, if we don't even have FP, just give up. */
1098 if (!have_F)
1099 return False;
1100
1101 VG_(machine_ppc64_has_VMX) = have_V ? 1 : 0;
sewardj2c48c7b2005-11-29 13:05:56 +00001102
1103 va = VexArchPPC64;
sewardje3121f32006-01-27 21:23:23 +00001104
1105 vai.hwcaps = 0;
1106 if (have_V) vai.hwcaps |= VEX_HWCAPS_PPC64_V;
1107 if (have_FX) vai.hwcaps |= VEX_HWCAPS_PPC64_FX;
1108 if (have_GX) vai.hwcaps |= VEX_HWCAPS_PPC64_GX;
sewardjf34eb492011-04-15 11:57:05 +00001109 if (have_VX) vai.hwcaps |= VEX_HWCAPS_PPC64_VX;
sewardj5ba075a2012-04-02 21:25:14 +00001110 if (have_DFP) vai.hwcaps |= VEX_HWCAPS_PPC64_DFP;
sewardj2c48c7b2005-11-29 13:05:56 +00001111
florian78627012012-10-07 19:47:04 +00001112 VG_(machine_get_cache_info)(&vai);
1113
sewardj2c48c7b2005-11-29 13:05:56 +00001114 /* But we're not done yet: VG_(machine_ppc64_set_clszB) must be
1115 called before we're ready to go. */
1116 return True;
1117 }
1118
sewardjb5b87402011-03-07 16:05:35 +00001119#elif defined(VGA_s390x)
floriandf14eea2012-12-09 17:30:45 +00001120
1121#include "libvex_s390x_common.h"
1122
sewardjb5b87402011-03-07 16:05:35 +00001123 {
1124 /* Instruction set detection code borrowed from ppc above. */
1125 vki_sigset_t saved_set, tmp_set;
1126 vki_sigaction_fromK_t saved_sigill_act;
1127 vki_sigaction_toK_t tmp_sigill_act;
1128
floriandf14eea2012-12-09 17:30:45 +00001129 volatile Bool have_LDISP, have_STFLE;
1130 Int i, r, model;
1131
1132 /* If the model is "unknown" don't treat this as an error. Assume
1133 this is a brand-new machine model for which we don't have the
1134 identification yet. Keeping fingers crossed. */
1135 model = VG_(get_machine_model)();
sewardjb5b87402011-03-07 16:05:35 +00001136
1137 /* Unblock SIGILL and stash away the old action for that signal */
1138 VG_(sigemptyset)(&tmp_set);
1139 VG_(sigaddset)(&tmp_set, VKI_SIGILL);
1140
1141 r = VG_(sigprocmask)(VKI_SIG_UNBLOCK, &tmp_set, &saved_set);
1142 vg_assert(r == 0);
1143
1144 r = VG_(sigaction)(VKI_SIGILL, NULL, &saved_sigill_act);
1145 vg_assert(r == 0);
1146 tmp_sigill_act = saved_sigill_act;
1147
1148 /* NODEFER: signal handler does not return (from the kernel's point of
1149 view), hence if it is to successfully catch a signal more than once,
1150 we need the NODEFER flag. */
1151 tmp_sigill_act.sa_flags &= ~VKI_SA_RESETHAND;
1152 tmp_sigill_act.sa_flags &= ~VKI_SA_SIGINFO;
1153 tmp_sigill_act.sa_flags |= VKI_SA_NODEFER;
1154 tmp_sigill_act.ksa_handler = handler_unsup_insn;
1155 VG_(sigaction)(VKI_SIGILL, &tmp_sigill_act, NULL);
1156
1157 /* Determine hwcaps. Note, we cannot use the stfle insn because it
1158 is not supported on z900. */
1159
1160 have_LDISP = True;
sewardj6c591e12011-04-11 16:17:51 +00001161 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardjb5b87402011-03-07 16:05:35 +00001162 have_LDISP = False;
1163 } else {
1164 /* BASR loads the address of the next insn into r1. Needed to avoid
1165 a segfault in XY. */
1166 __asm__ __volatile__("basr %%r1,%%r0\n\t"
1167 ".long 0xe3001000\n\t" /* XY 0,0(%r1) */
1168 ".short 0x0057" : : : "r0", "r1", "cc", "memory");
1169 }
1170
floriandf14eea2012-12-09 17:30:45 +00001171 /* Check availability og STFLE. If available store facility bits
1172 in hoststfle. */
1173 ULong hoststfle[S390_NUM_FACILITY_DW];
sewardjb5b87402011-03-07 16:05:35 +00001174
floriandf14eea2012-12-09 17:30:45 +00001175 for (i = 0; i < S390_NUM_FACILITY_DW; ++i)
1176 hoststfle[i] = 0;
sewardjb5b87402011-03-07 16:05:35 +00001177
floriand19733c2012-01-15 21:02:44 +00001178 have_STFLE = True;
floriand19733c2012-01-15 21:02:44 +00001179 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
1180 have_STFLE = False;
1181 } else {
floriandf14eea2012-12-09 17:30:45 +00001182 register ULong reg0 asm("0") = S390_NUM_FACILITY_DW - 1;
floriand19733c2012-01-15 21:02:44 +00001183
1184 __asm__ __volatile__(" .insn s,0xb2b00000,%0\n" /* stfle */
1185 : "=m" (hoststfle), "+d"(reg0)
1186 : : "cc", "memory");
floriand19733c2012-01-15 21:02:44 +00001187 }
1188
sewardjb5b87402011-03-07 16:05:35 +00001189 /* Restore signals */
1190 r = VG_(sigaction)(VKI_SIGILL, &saved_sigill_act, NULL);
1191 vg_assert(r == 0);
1192 r = VG_(sigprocmask)(VKI_SIG_SETMASK, &saved_set, NULL);
1193 vg_assert(r == 0);
sewardjb5b87402011-03-07 16:05:35 +00001194 va = VexArchS390X;
1195
sewardj2c3f2ea2011-04-13 15:40:10 +00001196 vai.hwcaps = model;
floriandf14eea2012-12-09 17:30:45 +00001197 if (have_STFLE) vai.hwcaps |= VEX_HWCAPS_S390X_STFLE;
sewardj2c3f2ea2011-04-13 15:40:10 +00001198 if (have_LDISP) {
floriandf14eea2012-12-09 17:30:45 +00001199 /* Use long displacement only on machines >= z990. For all other
1200 machines it is millicoded and therefore slow. */
sewardj2c3f2ea2011-04-13 15:40:10 +00001201 if (model >= VEX_S390X_MODEL_Z990)
1202 vai.hwcaps |= VEX_HWCAPS_S390X_LDISP;
1203 }
sewardjb5b87402011-03-07 16:05:35 +00001204
floriandf14eea2012-12-09 17:30:45 +00001205 /* Detect presence of certain facilities using the STFLE insn.
1206 Note, that these facilities were introduced at the same time or later
1207 as STFLE, so the absence of STLFE implies the absence of the facility
1208 we're trying to detect. */
1209 struct fac_hwcaps_map {
1210 UInt installed;
1211 UInt facility_bit;
1212 UInt hwcaps_bit;
1213 const HChar name[6]; // may need adjustment for new facility names
1214 } fac_hwcaps[] = {
1215 { False, S390_FAC_EIMM, VEX_HWCAPS_S390X_EIMM, "EIMM" },
1216 { False, S390_FAC_GIE, VEX_HWCAPS_S390X_GIE, "GIE" },
1217 { False, S390_FAC_DFP, VEX_HWCAPS_S390X_DFP, "DFP" },
1218 { False, S390_FAC_FPSE, VEX_HWCAPS_S390X_FGX, "FGX" },
1219 { False, S390_FAC_ETF2, VEX_HWCAPS_S390X_ETF2, "ETF2" },
1220 { False, S390_FAC_ETF3, VEX_HWCAPS_S390X_ETF3, "ETF3" },
1221 { False, S390_FAC_STCKF, VEX_HWCAPS_S390X_STCKF, "STCKF" },
1222 { False, S390_FAC_FPEXT, VEX_HWCAPS_S390X_FPEXT, "FPEXT" },
1223 { False, S390_FAC_LSC, VEX_HWCAPS_S390X_LSC, "LSC" },
1224 };
1225
1226 /* Set hwcaps according to the detected facilities */
1227 for (i=0; i < sizeof fac_hwcaps / sizeof fac_hwcaps[0]; ++i) {
1228 vg_assert(fac_hwcaps[i].facility_bit <= 63); // for now
1229 if (hoststfle[0] & (1ULL << (63 - fac_hwcaps[i].facility_bit))) {
1230 fac_hwcaps[i].installed = True;
1231 vai.hwcaps |= fac_hwcaps[i].hwcaps_bit;
1232 }
1233 }
1234
1235 /* Build up a string showing the probed-for facilities */
1236 HChar fac_str[(sizeof fac_hwcaps / sizeof fac_hwcaps[0]) *
1237 (sizeof fac_hwcaps[0].name + 3) + // %s %d
1238 7 + 1 + 4 + 2 // machine %4d
1239 + 1]; // \0
1240 HChar *p = fac_str;
1241 p += VG_(sprintf)(p, "machine %4d ", model);
1242 for (i=0; i < sizeof fac_hwcaps / sizeof fac_hwcaps[0]; ++i) {
1243 p += VG_(sprintf)(p, " %s %1d", fac_hwcaps[i].name,
1244 fac_hwcaps[i].installed);
1245 }
1246 *p++ = '\0';
1247
1248 VG_(debugLog)(1, "machine", "%s\n", fac_str);
sewardj2c3f2ea2011-04-13 15:40:10 +00001249 VG_(debugLog)(1, "machine", "hwcaps = 0x%x\n", vai.hwcaps);
1250
florian78627012012-10-07 19:47:04 +00001251 VG_(machine_get_cache_info)(&vai);
1252
sewardjb5b87402011-03-07 16:05:35 +00001253 return True;
1254 }
1255
sewardj59570ff2010-01-01 11:59:33 +00001256#elif defined(VGA_arm)
1257 {
sewardj1dbd3372010-08-22 12:21:14 +00001258 /* Same instruction set detection algorithm as for ppc32. */
1259 vki_sigset_t saved_set, tmp_set;
1260 vki_sigaction_fromK_t saved_sigill_act, saved_sigfpe_act;
1261 vki_sigaction_toK_t tmp_sigill_act, tmp_sigfpe_act;
1262
1263 volatile Bool have_VFP, have_VFP2, have_VFP3, have_NEON;
1264 volatile Int archlevel;
1265 Int r;
1266
1267 /* This is a kludge. Really we ought to back-convert saved_act
1268 into a toK_t using VG_(convert_sigaction_fromK_to_toK), but
1269 since that's a no-op on all ppc64 platforms so far supported,
1270 it's not worth the typing effort. At least include most basic
1271 sanity check: */
1272 vg_assert(sizeof(vki_sigaction_fromK_t) == sizeof(vki_sigaction_toK_t));
1273
1274 VG_(sigemptyset)(&tmp_set);
1275 VG_(sigaddset)(&tmp_set, VKI_SIGILL);
1276 VG_(sigaddset)(&tmp_set, VKI_SIGFPE);
1277
1278 r = VG_(sigprocmask)(VKI_SIG_UNBLOCK, &tmp_set, &saved_set);
1279 vg_assert(r == 0);
1280
1281 r = VG_(sigaction)(VKI_SIGILL, NULL, &saved_sigill_act);
1282 vg_assert(r == 0);
1283 tmp_sigill_act = saved_sigill_act;
1284
1285 VG_(sigaction)(VKI_SIGFPE, NULL, &saved_sigfpe_act);
1286 tmp_sigfpe_act = saved_sigfpe_act;
1287
1288 /* NODEFER: signal handler does not return (from the kernel's point of
1289 view), hence if it is to successfully catch a signal more than once,
1290 we need the NODEFER flag. */
1291 tmp_sigill_act.sa_flags &= ~VKI_SA_RESETHAND;
1292 tmp_sigill_act.sa_flags &= ~VKI_SA_SIGINFO;
1293 tmp_sigill_act.sa_flags |= VKI_SA_NODEFER;
1294 tmp_sigill_act.ksa_handler = handler_unsup_insn;
1295 VG_(sigaction)(VKI_SIGILL, &tmp_sigill_act, NULL);
1296
1297 tmp_sigfpe_act.sa_flags &= ~VKI_SA_RESETHAND;
1298 tmp_sigfpe_act.sa_flags &= ~VKI_SA_SIGINFO;
1299 tmp_sigfpe_act.sa_flags |= VKI_SA_NODEFER;
1300 tmp_sigfpe_act.ksa_handler = handler_unsup_insn;
1301 VG_(sigaction)(VKI_SIGFPE, &tmp_sigfpe_act, NULL);
1302
1303 /* VFP insns */
1304 have_VFP = True;
sewardj6c591e12011-04-11 16:17:51 +00001305 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardj1dbd3372010-08-22 12:21:14 +00001306 have_VFP = False;
1307 } else {
1308 __asm__ __volatile__(".word 0xEEB02B42"); /* VMOV.F64 d2, d2 */
1309 }
1310 /* There are several generation of VFP extension but they differs very
1311 little so for now we will not distinguish them. */
1312 have_VFP2 = have_VFP;
1313 have_VFP3 = have_VFP;
1314
1315 /* NEON insns */
1316 have_NEON = True;
sewardj6c591e12011-04-11 16:17:51 +00001317 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardj1dbd3372010-08-22 12:21:14 +00001318 have_NEON = False;
1319 } else {
1320 __asm__ __volatile__(".word 0xF2244154"); /* VMOV q2, q2 */
1321 }
1322
1323 /* ARM architecture level */
1324 archlevel = 5; /* v5 will be base level */
1325 if (archlevel < 7) {
1326 archlevel = 7;
sewardj6c591e12011-04-11 16:17:51 +00001327 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardj1dbd3372010-08-22 12:21:14 +00001328 archlevel = 5;
1329 } else {
1330 __asm__ __volatile__(".word 0xF45FF000"); /* PLI [PC,#-0] */
1331 }
1332 }
1333 if (archlevel < 6) {
1334 archlevel = 6;
sewardj6c591e12011-04-11 16:17:51 +00001335 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardj1dbd3372010-08-22 12:21:14 +00001336 archlevel = 5;
1337 } else {
1338 __asm__ __volatile__(".word 0xE6822012"); /* PKHBT r2, r2, r2 */
1339 }
1340 }
1341
1342 VG_(convert_sigaction_fromK_to_toK)(&saved_sigill_act, &tmp_sigill_act);
1343 VG_(convert_sigaction_fromK_to_toK)(&saved_sigfpe_act, &tmp_sigfpe_act);
1344 VG_(sigaction)(VKI_SIGILL, &tmp_sigill_act, NULL);
1345 VG_(sigaction)(VKI_SIGFPE, &tmp_sigfpe_act, NULL);
1346 VG_(sigprocmask)(VKI_SIG_SETMASK, &saved_set, NULL);
1347
1348 VG_(debugLog)(1, "machine", "ARMv%d VFP %d VFP2 %d VFP3 %d NEON %d\n",
1349 archlevel, (Int)have_VFP, (Int)have_VFP2, (Int)have_VFP3,
1350 (Int)have_NEON);
1351
1352 VG_(machine_arm_archlevel) = archlevel;
1353
sewardj59570ff2010-01-01 11:59:33 +00001354 va = VexArchARM;
sewardj1dbd3372010-08-22 12:21:14 +00001355
1356 vai.hwcaps = VEX_ARM_ARCHLEVEL(archlevel);
1357 if (have_VFP3) vai.hwcaps |= VEX_HWCAPS_ARM_VFP3;
1358 if (have_VFP2) vai.hwcaps |= VEX_HWCAPS_ARM_VFP2;
1359 if (have_VFP) vai.hwcaps |= VEX_HWCAPS_ARM_VFP;
1360 if (have_NEON) vai.hwcaps |= VEX_HWCAPS_ARM_NEON;
1361
florian78627012012-10-07 19:47:04 +00001362 VG_(machine_get_cache_info)(&vai);
1363
sewardj59570ff2010-01-01 11:59:33 +00001364 return True;
1365 }
1366
sewardj5db15402012-06-07 09:13:21 +00001367#elif defined(VGA_mips32)
1368 {
1369 va = VexArchMIPS32;
1370 UInt model = VG_(get_machine_model)();
1371 if (model== -1)
1372 return False;
1373
1374 vai.hwcaps = model;
florian78627012012-10-07 19:47:04 +00001375
1376 VG_(machine_get_cache_info)(&vai);
1377
sewardj5db15402012-06-07 09:13:21 +00001378 return True;
1379 }
1380
sewardje2d1e672005-11-12 23:10:48 +00001381#else
1382# error "Unknown arch"
1383#endif
1384}
1385
sewardj2c48c7b2005-11-29 13:05:56 +00001386/* Notify host cpu cache line size. */
sewardje3826cf2005-11-13 00:30:22 +00001387#if defined(VGA_ppc32)
1388void VG_(machine_ppc32_set_clszB)( Int szB )
1389{
1390 vg_assert(hwcaps_done);
1391
1392 /* Either the value must not have been set yet (zero) or we can
1393 tolerate it being set to the same value multiple times, as the
1394 stack scanning logic in m_main is a bit stupid. */
cerion1f0d8142005-12-23 00:57:03 +00001395 vg_assert(vai.ppc_cache_line_szB == 0
1396 || vai.ppc_cache_line_szB == szB);
sewardje3826cf2005-11-13 00:30:22 +00001397
sewardj89230ca2008-05-29 16:39:57 +00001398 vg_assert(szB == 32 || szB == 64 || szB == 128);
cerion1f0d8142005-12-23 00:57:03 +00001399 vai.ppc_cache_line_szB = szB;
sewardje3826cf2005-11-13 00:30:22 +00001400}
1401#endif
1402
sewardje2d1e672005-11-12 23:10:48 +00001403
sewardj2c48c7b2005-11-29 13:05:56 +00001404/* Notify host cpu cache line size. */
1405#if defined(VGA_ppc64)
1406void VG_(machine_ppc64_set_clszB)( Int szB )
1407{
1408 vg_assert(hwcaps_done);
1409
1410 /* Either the value must not have been set yet (zero) or we can
1411 tolerate it being set to the same value multiple times, as the
1412 stack scanning logic in m_main is a bit stupid. */
cerion1f0d8142005-12-23 00:57:03 +00001413 vg_assert(vai.ppc_cache_line_szB == 0
1414 || vai.ppc_cache_line_szB == szB);
sewardj2c48c7b2005-11-29 13:05:56 +00001415
sewardj89230ca2008-05-29 16:39:57 +00001416 vg_assert(szB == 32 || szB == 64 || szB == 128);
cerion1f0d8142005-12-23 00:57:03 +00001417 vai.ppc_cache_line_szB = szB;
sewardj2c48c7b2005-11-29 13:05:56 +00001418}
1419#endif
1420
1421
sewardja3551be2010-09-09 07:25:58 +00001422/* Notify host's ability to handle NEON instructions. */
1423#if defined(VGA_arm)
1424void VG_(machine_arm_set_has_NEON)( Bool has_neon )
1425{
1426 vg_assert(hwcaps_done);
1427 /* There's nothing else we can sanity check. */
1428
1429 if (has_neon) {
1430 vai.hwcaps |= VEX_HWCAPS_ARM_NEON;
1431 } else {
1432 vai.hwcaps &= ~VEX_HWCAPS_ARM_NEON;
1433 }
1434}
1435#endif
1436
1437
sewardje2d1e672005-11-12 23:10:48 +00001438/* Fetch host cpu info, once established. */
1439void VG_(machine_get_VexArchInfo)( /*OUT*/VexArch* pVa,
1440 /*OUT*/VexArchInfo* pVai )
1441{
1442 vg_assert(hwcaps_done);
sewardje3826cf2005-11-13 00:30:22 +00001443 if (pVa) *pVa = va;
1444 if (pVai) *pVai = vai;
sewardje2d1e672005-11-12 23:10:48 +00001445}
sewardj7821e2e2005-08-08 00:35:46 +00001446
1447
sewardj98763d52012-06-03 22:40:07 +00001448/* Returns the size of the largest guest register that we will
1449 simulate in this run. This depends on both the guest architecture
1450 and on the specific capabilities we are simulating for that guest
1451 (eg, AVX or non-AVX ?, for amd64). Should return either 4, 8, 16
1452 or 32. General rule: if in doubt, return a value larger than
1453 reality.
1454
1455 This information is needed by Cachegrind and Callgrind to decide
1456 what the minimum cache line size they are prepared to simulate is.
1457 Basically require that the minimum cache line size is at least as
1458 large as the largest register that might get transferred to/from
1459 memory, so as to guarantee that any such transaction can straddle
1460 at most 2 cache lines.
1461*/
1462Int VG_(machine_get_size_of_largest_guest_register) ( void )
1463{
1464 vg_assert(hwcaps_done);
1465 /* Once hwcaps_done is True, we can fish around inside va/vai to
1466 find the information we need. */
1467
1468# if defined(VGA_x86)
1469 vg_assert(va == VexArchX86);
1470 /* We don't support AVX, so 32 is out. At the other end, even if
1471 we don't support any SSE, the X87 can generate 10 byte
1472 transfers, so let's say 16 to be on the safe side. Hence the
1473 answer is always 16. */
1474 return 16;
1475
1476# elif defined(VGA_amd64)
1477 /* if AVX then 32 else 16 */
1478 return (vai.hwcaps & VEX_HWCAPS_AMD64_AVX) ? 32 : 16;
1479
1480# elif defined(VGA_ppc32)
1481 /* 8 if boring; 16 if signs of Altivec or other exotic stuff */
1482 if (vai.hwcaps & VEX_HWCAPS_PPC32_V) return 16;
1483 if (vai.hwcaps & VEX_HWCAPS_PPC32_VX) return 16;
1484 if (vai.hwcaps & VEX_HWCAPS_PPC32_DFP) return 16;
1485 return 8;
1486
1487# elif defined(VGA_ppc64)
1488 /* 8 if boring; 16 if signs of Altivec or other exotic stuff */
1489 if (vai.hwcaps & VEX_HWCAPS_PPC64_V) return 16;
1490 if (vai.hwcaps & VEX_HWCAPS_PPC64_VX) return 16;
1491 if (vai.hwcaps & VEX_HWCAPS_PPC64_DFP) return 16;
1492 return 8;
1493
1494# elif defined(VGA_s390x)
1495 return 8;
1496
1497# elif defined(VGA_arm)
1498 /* Really it depends whether or not we have NEON, but let's just
1499 assume we always do. */
1500 return 16;
1501
sewardj5db15402012-06-07 09:13:21 +00001502# elif defined(VGA_mips32)
1503 /* The guest state implies 4, but that can't really be true, can
1504 it? */
1505 return 8;
1506
sewardj98763d52012-06-03 22:40:07 +00001507# else
1508# error "Unknown arch"
1509# endif
1510}
1511
1512
sewardj53ee1fc2005-12-23 02:29:58 +00001513// Given a pointer to a function as obtained by "& functionname" in C,
sewardjf1c91e02006-10-17 01:35:58 +00001514// produce a pointer to the actual entry point for the function.
sewardj53ee1fc2005-12-23 02:29:58 +00001515void* VG_(fnptr_to_fnentry)( void* f )
1516{
sewardj6e9de462011-06-28 07:25:29 +00001517# if defined(VGP_x86_linux) || defined(VGP_amd64_linux) \
1518 || defined(VGP_arm_linux) \
1519 || defined(VGP_ppc32_linux) || defined(VGO_darwin) \
sewardj5db15402012-06-07 09:13:21 +00001520 || defined(VGP_s390x_linux) || defined(VGP_mips32_linux)
sewardj53ee1fc2005-12-23 02:29:58 +00001521 return f;
sewardj6e9de462011-06-28 07:25:29 +00001522# elif defined(VGP_ppc64_linux)
1523 /* ppc64-linux uses the AIX scheme, in which f is a pointer to a
1524 3-word function descriptor, of which the first word is the entry
1525 address. */
sewardjf1c91e02006-10-17 01:35:58 +00001526 UWord* descr = (UWord*)f;
sewardj53ee1fc2005-12-23 02:29:58 +00001527 return (void*)(descr[0]);
sewardj6e9de462011-06-28 07:25:29 +00001528# else
1529# error "Unknown platform"
1530# endif
sewardj53ee1fc2005-12-23 02:29:58 +00001531}
1532
njnf536bbb2005-06-13 04:21:38 +00001533/*--------------------------------------------------------------------*/
1534/*--- end ---*/
1535/*--------------------------------------------------------------------*/