blob: 9b4dabc1ae896b2d0a4e25bdc2b19378550d8287 [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"
37#include "pub_core_mallocfree.h"
njnf536bbb2005-06-13 04:21:38 +000038#include "pub_core_machine.h"
sewardje2d1e672005-11-12 23:10:48 +000039#include "pub_core_cpuid.h"
bart1581e742009-01-13 07:49:14 +000040#include "pub_core_libcsignal.h" // for ppc32 messing with SIGILL and SIGFPE
sewardj3b0cae72009-05-28 17:15:41 +000041#include "pub_core_debuglog.h"
sewardje3826cf2005-11-13 00:30:22 +000042
njnf536bbb2005-06-13 04:21:38 +000043
njnaf839f52005-06-23 03:27:57 +000044#define INSTR_PTR(regs) ((regs).vex.VG_INSTR_PTR)
45#define STACK_PTR(regs) ((regs).vex.VG_STACK_PTR)
46#define FRAME_PTR(regs) ((regs).vex.VG_FRAME_PTR)
njnf536bbb2005-06-13 04:21:38 +000047
sewardj1dbd3372010-08-22 12:21:14 +000048Addr VG_(get_IP) ( ThreadId tid ) {
njnf536bbb2005-06-13 04:21:38 +000049 return INSTR_PTR( VG_(threads)[tid].arch );
50}
sewardj1dbd3372010-08-22 12:21:14 +000051Addr VG_(get_SP) ( ThreadId tid ) {
52 return STACK_PTR( VG_(threads)[tid].arch );
53}
54Addr VG_(get_FP) ( ThreadId tid ) {
njnf536bbb2005-06-13 04:21:38 +000055 return FRAME_PTR( VG_(threads)[tid].arch );
56}
57
sewardj1dbd3372010-08-22 12:21:14 +000058void VG_(set_IP) ( ThreadId tid, Addr ip ) {
njnf536bbb2005-06-13 04:21:38 +000059 INSTR_PTR( VG_(threads)[tid].arch ) = ip;
60}
sewardj1dbd3372010-08-22 12:21:14 +000061void VG_(set_SP) ( ThreadId tid, Addr sp ) {
62 STACK_PTR( VG_(threads)[tid].arch ) = sp;
63}
sewardj59570ff2010-01-01 11:59:33 +000064
65void VG_(get_UnwindStartRegs) ( /*OUT*/UnwindStartRegs* regs,
66 ThreadId tid )
67{
68# if defined(VGA_x86)
69 regs->r_pc = (ULong)VG_(threads)[tid].arch.vex.guest_EIP;
70 regs->r_sp = (ULong)VG_(threads)[tid].arch.vex.guest_ESP;
71 regs->misc.X86.r_ebp
72 = VG_(threads)[tid].arch.vex.guest_EBP;
73# elif defined(VGA_amd64)
74 regs->r_pc = VG_(threads)[tid].arch.vex.guest_RIP;
75 regs->r_sp = VG_(threads)[tid].arch.vex.guest_RSP;
76 regs->misc.AMD64.r_rbp
77 = VG_(threads)[tid].arch.vex.guest_RBP;
78# elif defined(VGA_ppc32)
79 regs->r_pc = (ULong)VG_(threads)[tid].arch.vex.guest_CIA;
sewardjf5f1e122010-01-02 13:24:58 +000080 regs->r_sp = (ULong)VG_(threads)[tid].arch.vex.guest_GPR1;
sewardj59570ff2010-01-01 11:59:33 +000081 regs->misc.PPC32.r_lr
82 = VG_(threads)[tid].arch.vex.guest_LR;
83# elif defined(VGA_ppc64)
84 regs->r_pc = VG_(threads)[tid].arch.vex.guest_CIA;
sewardjf5f1e122010-01-02 13:24:58 +000085 regs->r_sp = VG_(threads)[tid].arch.vex.guest_GPR1;
sewardj59570ff2010-01-01 11:59:33 +000086 regs->misc.PPC64.r_lr
87 = VG_(threads)[tid].arch.vex.guest_LR;
88# elif defined(VGA_arm)
sewardj1dbd3372010-08-22 12:21:14 +000089 regs->r_pc = (ULong)VG_(threads)[tid].arch.vex.guest_R15T;
sewardj59570ff2010-01-01 11:59:33 +000090 regs->r_sp = (ULong)VG_(threads)[tid].arch.vex.guest_R13;
91 regs->misc.ARM.r14
92 = VG_(threads)[tid].arch.vex.guest_R14;
93 regs->misc.ARM.r12
94 = VG_(threads)[tid].arch.vex.guest_R12;
95 regs->misc.ARM.r11
96 = VG_(threads)[tid].arch.vex.guest_R11;
sewardjfa5ce562010-09-23 22:05:59 +000097 regs->misc.ARM.r7
98 = VG_(threads)[tid].arch.vex.guest_R7;
sewardjb5b87402011-03-07 16:05:35 +000099# elif defined(VGA_s390x)
100 regs->r_pc = (ULong)VG_(threads)[tid].arch.vex.guest_IA;
101 regs->r_sp = (ULong)VG_(threads)[tid].arch.vex.guest_SP;
102 regs->misc.S390X.r_fp
103 = VG_(threads)[tid].arch.vex.guest_r11;
104 regs->misc.S390X.r_lr
105 = VG_(threads)[tid].arch.vex.guest_r14;
sewardj5db15402012-06-07 09:13:21 +0000106# elif defined(VGA_mips32)
107 regs->r_pc = VG_(threads)[tid].arch.vex.guest_PC;
108 regs->r_sp = VG_(threads)[tid].arch.vex.guest_r29;
109 regs->misc.MIPS32.r30
110 = VG_(threads)[tid].arch.vex.guest_r30;
111 regs->misc.MIPS32.r31
112 = VG_(threads)[tid].arch.vex.guest_r31;
113 regs->misc.MIPS32.r28
114 = VG_(threads)[tid].arch.vex.guest_r28;
sewardj59570ff2010-01-01 11:59:33 +0000115# else
116# error "Unknown arch"
117# endif
118}
119
120
sewardj9c606bd2008-09-18 18:12:50 +0000121void VG_(set_syscall_return_shadows) ( ThreadId tid,
122 /* shadow vals for the result */
123 UWord s1res, UWord s2res,
124 /* shadow vals for the error val */
125 UWord s1err, UWord s2err )
126{
127# if defined(VGP_x86_linux)
128 VG_(threads)[tid].arch.vex_shadow1.guest_EAX = s1res;
129 VG_(threads)[tid].arch.vex_shadow2.guest_EAX = s2res;
130# elif defined(VGP_amd64_linux)
131 VG_(threads)[tid].arch.vex_shadow1.guest_RAX = s1res;
132 VG_(threads)[tid].arch.vex_shadow2.guest_RAX = s2res;
133# elif defined(VGP_ppc32_linux) || defined(VGP_ppc64_linux)
134 VG_(threads)[tid].arch.vex_shadow1.guest_GPR3 = s1res;
135 VG_(threads)[tid].arch.vex_shadow2.guest_GPR3 = s2res;
sewardj59570ff2010-01-01 11:59:33 +0000136# elif defined(VGP_arm_linux)
137 VG_(threads)[tid].arch.vex_shadow1.guest_R0 = s1res;
138 VG_(threads)[tid].arch.vex_shadow2.guest_R0 = s2res;
njnf76d27a2009-05-28 01:53:07 +0000139# elif defined(VGO_darwin)
140 // GrP fixme darwin syscalls may return more values (2 registers plus error)
sewardjb5b87402011-03-07 16:05:35 +0000141# elif defined(VGP_s390x_linux)
142 VG_(threads)[tid].arch.vex_shadow1.guest_r2 = s1res;
143 VG_(threads)[tid].arch.vex_shadow2.guest_r2 = s2res;
sewardj5db15402012-06-07 09:13:21 +0000144# elif defined(VGP_mips32_linux)
145 VG_(threads)[tid].arch.vex_shadow1.guest_r2 = s1res;
146 VG_(threads)[tid].arch.vex_shadow2.guest_r2 = s2res;
sewardj9c606bd2008-09-18 18:12:50 +0000147# else
148# error "Unknown plat"
149# endif
150}
njnf536bbb2005-06-13 04:21:38 +0000151
sewardj7cf4e6b2008-05-01 20:24:26 +0000152void
153VG_(get_shadow_regs_area) ( ThreadId tid,
154 /*DST*/UChar* dst,
njnc4431bf2009-01-15 21:29:24 +0000155 /*SRC*/Int shadowNo, PtrdiffT offset, SizeT size )
njnf536bbb2005-06-13 04:21:38 +0000156{
sewardj7cf4e6b2008-05-01 20:24:26 +0000157 void* src;
njnf536bbb2005-06-13 04:21:38 +0000158 ThreadState* tst;
sewardj9c606bd2008-09-18 18:12:50 +0000159 vg_assert(shadowNo == 0 || shadowNo == 1 || shadowNo == 2);
njnf536bbb2005-06-13 04:21:38 +0000160 vg_assert(VG_(is_valid_tid)(tid));
njnf536bbb2005-06-13 04:21:38 +0000161 // Bounds check
162 vg_assert(0 <= offset && offset < sizeof(VexGuestArchState));
163 vg_assert(offset + size <= sizeof(VexGuestArchState));
sewardj7cf4e6b2008-05-01 20:24:26 +0000164 // Copy
165 tst = & VG_(threads)[tid];
sewardj9c606bd2008-09-18 18:12:50 +0000166 src = NULL;
167 switch (shadowNo) {
168 case 0: src = (void*)(((Addr)&(tst->arch.vex)) + offset); break;
169 case 1: src = (void*)(((Addr)&(tst->arch.vex_shadow1)) + offset); break;
170 case 2: src = (void*)(((Addr)&(tst->arch.vex_shadow2)) + offset); break;
171 }
172 tl_assert(src != NULL);
sewardj7cf4e6b2008-05-01 20:24:26 +0000173 VG_(memcpy)( dst, src, size);
njnf536bbb2005-06-13 04:21:38 +0000174}
175
sewardj7cf4e6b2008-05-01 20:24:26 +0000176void
177VG_(set_shadow_regs_area) ( ThreadId tid,
njnc4431bf2009-01-15 21:29:24 +0000178 /*DST*/Int shadowNo, PtrdiffT offset, SizeT size,
sewardj7cf4e6b2008-05-01 20:24:26 +0000179 /*SRC*/const UChar* src )
njnf536bbb2005-06-13 04:21:38 +0000180{
sewardj7cf4e6b2008-05-01 20:24:26 +0000181 void* dst;
njnf536bbb2005-06-13 04:21:38 +0000182 ThreadState* tst;
sewardj9c606bd2008-09-18 18:12:50 +0000183 vg_assert(shadowNo == 0 || shadowNo == 1 || shadowNo == 2);
njnf536bbb2005-06-13 04:21:38 +0000184 vg_assert(VG_(is_valid_tid)(tid));
njnf536bbb2005-06-13 04:21:38 +0000185 // Bounds check
186 vg_assert(0 <= offset && offset < sizeof(VexGuestArchState));
187 vg_assert(offset + size <= sizeof(VexGuestArchState));
sewardj7cf4e6b2008-05-01 20:24:26 +0000188 // Copy
189 tst = & VG_(threads)[tid];
sewardj9c606bd2008-09-18 18:12:50 +0000190 dst = NULL;
191 switch (shadowNo) {
192 case 0: dst = (void*)(((Addr)&(tst->arch.vex)) + offset); break;
193 case 1: dst = (void*)(((Addr)&(tst->arch.vex_shadow1)) + offset); break;
194 case 2: dst = (void*)(((Addr)&(tst->arch.vex_shadow2)) + offset); break;
195 }
196 tl_assert(dst != NULL);
sewardj7cf4e6b2008-05-01 20:24:26 +0000197 VG_(memcpy)( dst, src, size);
njnf536bbb2005-06-13 04:21:38 +0000198}
199
200
philippea22f59d2012-01-26 23:13:52 +0000201static void apply_to_GPs_of_tid(ThreadId tid, void (*f)(ThreadId, HChar*, Addr))
njn6ace3ea2005-06-17 03:06:27 +0000202{
philippea22f59d2012-01-26 23:13:52 +0000203 VexGuestArchState* vex = &(VG_(get_ThreadState)(tid)->arch.vex);
njn6ace3ea2005-06-17 03:06:27 +0000204#if defined(VGA_x86)
philippea22f59d2012-01-26 23:13:52 +0000205 (*f)(tid, "EAX", vex->guest_EAX);
206 (*f)(tid, "ECX", vex->guest_ECX);
207 (*f)(tid, "EDX", vex->guest_EDX);
208 (*f)(tid, "EBX", vex->guest_EBX);
209 (*f)(tid, "ESI", vex->guest_ESI);
210 (*f)(tid, "EDI", vex->guest_EDI);
211 (*f)(tid, "ESP", vex->guest_ESP);
212 (*f)(tid, "EBP", vex->guest_EBP);
njn6ace3ea2005-06-17 03:06:27 +0000213#elif defined(VGA_amd64)
philippea22f59d2012-01-26 23:13:52 +0000214 (*f)(tid, "RAX", vex->guest_RAX);
215 (*f)(tid, "RCX", vex->guest_RCX);
216 (*f)(tid, "RDX", vex->guest_RDX);
217 (*f)(tid, "RBX", vex->guest_RBX);
218 (*f)(tid, "RSI", vex->guest_RSI);
219 (*f)(tid, "RDI", vex->guest_RDI);
220 (*f)(tid, "RSP", vex->guest_RSP);
221 (*f)(tid, "RBP", vex->guest_RBP);
222 (*f)(tid, "R8" , vex->guest_R8 );
223 (*f)(tid, "R9" , vex->guest_R9 );
224 (*f)(tid, "R10", vex->guest_R10);
225 (*f)(tid, "R11", vex->guest_R11);
226 (*f)(tid, "R12", vex->guest_R12);
227 (*f)(tid, "R13", vex->guest_R13);
228 (*f)(tid, "R14", vex->guest_R14);
229 (*f)(tid, "R15", vex->guest_R15);
sewardj2c48c7b2005-11-29 13:05:56 +0000230#elif defined(VGA_ppc32) || defined(VGA_ppc64)
philippea22f59d2012-01-26 23:13:52 +0000231 (*f)(tid, "GPR0" , vex->guest_GPR0 );
232 (*f)(tid, "GPR1" , vex->guest_GPR1 );
233 (*f)(tid, "GPR2" , vex->guest_GPR2 );
234 (*f)(tid, "GPR3" , vex->guest_GPR3 );
235 (*f)(tid, "GPR4" , vex->guest_GPR4 );
236 (*f)(tid, "GPR5" , vex->guest_GPR5 );
237 (*f)(tid, "GPR6" , vex->guest_GPR6 );
238 (*f)(tid, "GPR7" , vex->guest_GPR7 );
239 (*f)(tid, "GPR8" , vex->guest_GPR8 );
240 (*f)(tid, "GPR9" , vex->guest_GPR9 );
241 (*f)(tid, "GPR10", vex->guest_GPR10);
242 (*f)(tid, "GPR11", vex->guest_GPR11);
243 (*f)(tid, "GPR12", vex->guest_GPR12);
244 (*f)(tid, "GPR13", vex->guest_GPR13);
245 (*f)(tid, "GPR14", vex->guest_GPR14);
246 (*f)(tid, "GPR15", vex->guest_GPR15);
247 (*f)(tid, "GPR16", vex->guest_GPR16);
248 (*f)(tid, "GPR17", vex->guest_GPR17);
249 (*f)(tid, "GPR18", vex->guest_GPR18);
250 (*f)(tid, "GPR19", vex->guest_GPR19);
251 (*f)(tid, "GPR20", vex->guest_GPR20);
252 (*f)(tid, "GPR21", vex->guest_GPR21);
253 (*f)(tid, "GPR22", vex->guest_GPR22);
254 (*f)(tid, "GPR23", vex->guest_GPR23);
255 (*f)(tid, "GPR24", vex->guest_GPR24);
256 (*f)(tid, "GPR25", vex->guest_GPR25);
257 (*f)(tid, "GPR26", vex->guest_GPR26);
258 (*f)(tid, "GPR27", vex->guest_GPR27);
259 (*f)(tid, "GPR28", vex->guest_GPR28);
260 (*f)(tid, "GPR29", vex->guest_GPR29);
261 (*f)(tid, "GPR30", vex->guest_GPR30);
262 (*f)(tid, "GPR31", vex->guest_GPR31);
263 (*f)(tid, "CTR" , vex->guest_CTR );
264 (*f)(tid, "LR" , vex->guest_LR );
sewardj59570ff2010-01-01 11:59:33 +0000265#elif defined(VGA_arm)
philippea22f59d2012-01-26 23:13:52 +0000266 (*f)(tid, "R0" , vex->guest_R0 );
267 (*f)(tid, "R1" , vex->guest_R1 );
268 (*f)(tid, "R2" , vex->guest_R2 );
269 (*f)(tid, "R3" , vex->guest_R3 );
270 (*f)(tid, "R4" , vex->guest_R4 );
271 (*f)(tid, "R5" , vex->guest_R5 );
272 (*f)(tid, "R6" , vex->guest_R6 );
273 (*f)(tid, "R8" , vex->guest_R8 );
274 (*f)(tid, "R9" , vex->guest_R9 );
275 (*f)(tid, "R10", vex->guest_R10);
276 (*f)(tid, "R11", vex->guest_R11);
277 (*f)(tid, "R12", vex->guest_R12);
278 (*f)(tid, "R13", vex->guest_R13);
279 (*f)(tid, "R14", vex->guest_R14);
sewardjb5b87402011-03-07 16:05:35 +0000280#elif defined(VGA_s390x)
philippea22f59d2012-01-26 23:13:52 +0000281 (*f)(tid, "r0" , vex->guest_r0 );
282 (*f)(tid, "r1" , vex->guest_r1 );
283 (*f)(tid, "r2" , vex->guest_r2 );
284 (*f)(tid, "r3" , vex->guest_r3 );
285 (*f)(tid, "r4" , vex->guest_r4 );
286 (*f)(tid, "r5" , vex->guest_r5 );
287 (*f)(tid, "r6" , vex->guest_r6 );
288 (*f)(tid, "r7" , vex->guest_r7 );
289 (*f)(tid, "r8" , vex->guest_r8 );
290 (*f)(tid, "r9" , vex->guest_r9 );
291 (*f)(tid, "r10", vex->guest_r10);
292 (*f)(tid, "r11", vex->guest_r11);
293 (*f)(tid, "r12", vex->guest_r12);
294 (*f)(tid, "r13", vex->guest_r13);
295 (*f)(tid, "r14", vex->guest_r14);
296 (*f)(tid, "r15", vex->guest_r15);
sewardj5db15402012-06-07 09:13:21 +0000297#elif defined(VGA_mips32)
298 (*f)(tid, "r0" , vex->guest_r0 );
299 (*f)(tid, "r1" , vex->guest_r1 );
300 (*f)(tid, "r2" , vex->guest_r2 );
301 (*f)(tid, "r3" , vex->guest_r3 );
302 (*f)(tid, "r4" , vex->guest_r4 );
303 (*f)(tid, "r5" , vex->guest_r5 );
304 (*f)(tid, "r6" , vex->guest_r6 );
305 (*f)(tid, "r7" , vex->guest_r7 );
306 (*f)(tid, "r8" , vex->guest_r8 );
307 (*f)(tid, "r9" , vex->guest_r9 );
308 (*f)(tid, "r10", vex->guest_r10);
309 (*f)(tid, "r11", vex->guest_r11);
310 (*f)(tid, "r12", vex->guest_r12);
311 (*f)(tid, "r13", vex->guest_r13);
312 (*f)(tid, "r14", vex->guest_r14);
313 (*f)(tid, "r15", vex->guest_r15);
314 (*f)(tid, "r16", vex->guest_r16);
315 (*f)(tid, "r17", vex->guest_r17);
316 (*f)(tid, "r18", vex->guest_r18);
317 (*f)(tid, "r19", vex->guest_r19);
318 (*f)(tid, "r20", vex->guest_r20);
319 (*f)(tid, "r21", vex->guest_r21);
320 (*f)(tid, "r22", vex->guest_r22);
321 (*f)(tid, "r23", vex->guest_r23);
322 (*f)(tid, "r24", vex->guest_r24);
323 (*f)(tid, "r25", vex->guest_r25);
324 (*f)(tid, "r26", vex->guest_r26);
325 (*f)(tid, "r27", vex->guest_r27);
326 (*f)(tid, "r28", vex->guest_r28);
327 (*f)(tid, "r29", vex->guest_r29);
328 (*f)(tid, "r30", vex->guest_r30);
329 (*f)(tid, "r31", vex->guest_r31);
njn6ace3ea2005-06-17 03:06:27 +0000330#else
331# error Unknown arch
332#endif
333}
334
335
philippea22f59d2012-01-26 23:13:52 +0000336void VG_(apply_to_GP_regs)(void (*f)(ThreadId, HChar*, UWord))
njn6ace3ea2005-06-17 03:06:27 +0000337{
338 ThreadId tid;
339
340 for (tid = 1; tid < VG_N_THREADS; tid++) {
341 if (VG_(is_valid_tid)(tid)) {
philippea22f59d2012-01-26 23:13:52 +0000342 apply_to_GPs_of_tid(tid, f);
njn6ace3ea2005-06-17 03:06:27 +0000343 }
344 }
345}
346
sewardjb8b79ad2008-03-03 01:35:41 +0000347void VG_(thread_stack_reset_iter)(/*OUT*/ThreadId* tid)
njnb506bd82005-06-21 04:01:51 +0000348{
sewardjb8b79ad2008-03-03 01:35:41 +0000349 *tid = (ThreadId)(-1);
njnb506bd82005-06-21 04:01:51 +0000350}
njn6ace3ea2005-06-17 03:06:27 +0000351
sewardjb8b79ad2008-03-03 01:35:41 +0000352Bool VG_(thread_stack_next)(/*MOD*/ThreadId* tid,
353 /*OUT*/Addr* stack_min,
354 /*OUT*/Addr* stack_max)
njn1d0cb0d2005-08-15 01:52:02 +0000355{
356 ThreadId i;
sewardjb8b79ad2008-03-03 01:35:41 +0000357 for (i = (*tid)+1; i < VG_N_THREADS; i++) {
358 if (i == VG_INVALID_THREADID)
359 continue;
njn1d0cb0d2005-08-15 01:52:02 +0000360 if (VG_(threads)[i].status != VgTs_Empty) {
361 *tid = i;
362 *stack_min = VG_(get_SP)(i);
363 *stack_max = VG_(threads)[i].client_stack_highest_word;
njn1d0cb0d2005-08-15 01:52:02 +0000364 return True;
365 }
366 }
367 return False;
368}
sewardj7821e2e2005-08-08 00:35:46 +0000369
sewardjbbec7722007-11-25 14:08:53 +0000370Addr VG_(thread_get_stack_max)(ThreadId tid)
371{
372 vg_assert(0 <= tid && tid < VG_N_THREADS && tid != VG_INVALID_THREADID);
373 vg_assert(VG_(threads)[tid].status != VgTs_Empty);
374 return VG_(threads)[tid].client_stack_highest_word;
375}
376
bart0fb03202008-03-29 09:25:53 +0000377SizeT VG_(thread_get_stack_size)(ThreadId tid)
378{
379 vg_assert(0 <= tid && tid < VG_N_THREADS && tid != VG_INVALID_THREADID);
380 vg_assert(VG_(threads)[tid].status != VgTs_Empty);
381 return VG_(threads)[tid].client_stack_szB;
382}
383
bart83c5a922010-09-02 14:38:38 +0000384Addr VG_(thread_get_altstack_min)(ThreadId tid)
385{
386 vg_assert(0 <= tid && tid < VG_N_THREADS && tid != VG_INVALID_THREADID);
387 vg_assert(VG_(threads)[tid].status != VgTs_Empty);
388 return (Addr)VG_(threads)[tid].altstack.ss_sp;
389}
390
391SizeT VG_(thread_get_altstack_size)(ThreadId tid)
392{
393 vg_assert(0 <= tid && tid < VG_N_THREADS && tid != VG_INVALID_THREADID);
394 vg_assert(VG_(threads)[tid].status != VgTs_Empty);
395 return VG_(threads)[tid].altstack.ss_size;
396}
397
sewardje2d1e672005-11-12 23:10:48 +0000398//-------------------------------------------------------------
399/* Details about the capabilities of the underlying (host) CPU. These
400 details are acquired by (1) enquiring with the CPU at startup, or
401 (2) from the AT_SYSINFO entries the kernel gave us (ppc32 cache
402 line size). It's a bit nasty in the sense that there's no obvious
403 way to stop uses of some of this info before it's ready to go.
florian0daa4e32012-04-22 02:48:20 +0000404 See pub_core_machine.h for more information about that.
sewardjb5b87402011-03-07 16:05:35 +0000405
sewardje2d1e672005-11-12 23:10:48 +0000406 VG_(machine_get_hwcaps) may use signals (although it attempts to
407 leave signal state unchanged) and therefore should only be
408 called before m_main sets up the client's signal state.
409*/
410
411/* --------- State --------- */
sewardj59570ff2010-01-01 11:59:33 +0000412static Bool hwcaps_done = False;
sewardje2d1e672005-11-12 23:10:48 +0000413
414/* --- all archs --- */
sewardj98763d52012-06-03 22:40:07 +0000415static VexArch va = VexArch_INVALID;
sewardje2d1e672005-11-12 23:10:48 +0000416static VexArchInfo vai;
sewardja48a4932005-09-29 11:09:56 +0000417
sewardj7821e2e2005-08-08 00:35:46 +0000418#if defined(VGA_x86)
sewardje2d1e672005-11-12 23:10:48 +0000419UInt VG_(machine_x86_have_mxcsr) = 0;
sewardj7821e2e2005-08-08 00:35:46 +0000420#endif
sewardje2d1e672005-11-12 23:10:48 +0000421#if defined(VGA_ppc32)
sewardj2c36d422005-11-13 01:59:22 +0000422UInt VG_(machine_ppc32_has_FP) = 0;
sewardje2d1e672005-11-12 23:10:48 +0000423UInt VG_(machine_ppc32_has_VMX) = 0;
424#endif
sewardj2c48c7b2005-11-29 13:05:56 +0000425#if defined(VGA_ppc64)
426ULong VG_(machine_ppc64_has_VMX) = 0;
427#endif
sewardj1dbd3372010-08-22 12:21:14 +0000428#if defined(VGA_arm)
429Int VG_(machine_arm_archlevel) = 4;
430#endif
sewardje2d1e672005-11-12 23:10:48 +0000431
sewardjb5b87402011-03-07 16:05:35 +0000432/* fixs390: anything for s390x here ? */
sewardje2d1e672005-11-12 23:10:48 +0000433
sewardj2c3f2ea2011-04-13 15:40:10 +0000434/* For hwcaps detection on ppc32/64, s390x, and arm we'll need to do SIGILL
sewardj6c591e12011-04-11 16:17:51 +0000435 testing, so we need a VG_MINIMAL_JMP_BUF. */
436#if defined(VGA_ppc32) || defined(VGA_ppc64) \
petarj2fd883a2012-06-30 02:12:13 +0000437 || defined(VGA_arm) || defined(VGA_s390x)
sewardj6c591e12011-04-11 16:17:51 +0000438#include "pub_tool_libcsetjmp.h"
sewardj97d3ebb2011-04-11 18:36:34 +0000439static VG_MINIMAL_JMP_BUF(env_unsup_insn);
sewardj6c591e12011-04-11 16:17:51 +0000440static void handler_unsup_insn ( Int x ) {
441 VG_MINIMAL_LONGJMP(env_unsup_insn);
442}
sewardj5ae70ce2010-09-08 15:12:33 +0000443#endif
444
sewardjb9c815b2010-09-03 15:51:34 +0000445
446/* Helper function for VG_(machine_get_hwcaps), assumes the SIGILL/etc
447 * handlers are installed. Determines the the sizes affected by dcbz
448 * and dcbzl instructions and updates the given VexArchInfo structure
449 * accordingly.
450 *
451 * Not very defensive: assumes that as long as the dcbz/dcbzl
452 * instructions don't raise a SIGILL, that they will zero an aligned,
453 * contiguous block of memory of a sensible size. */
sewardj5ae70ce2010-09-08 15:12:33 +0000454#if defined(VGA_ppc32) || defined(VGA_ppc64)
sewardjb9c815b2010-09-03 15:51:34 +0000455static void find_ppc_dcbz_sz(VexArchInfo *arch_info)
456{
sewardjdcb3a592010-09-04 00:43:14 +0000457 Int dcbz_szB = 0;
sewardjb9c815b2010-09-03 15:51:34 +0000458 Int dcbzl_szB;
sewardj5ae70ce2010-09-08 15:12:33 +0000459# define MAX_DCBZL_SZB (128) /* largest known effect of dcbzl */
sewardjb9c815b2010-09-03 15:51:34 +0000460 char test_block[4*MAX_DCBZL_SZB];
461 char *aligned = test_block;
462 Int i;
463
464 /* round up to next max block size, assumes MAX_DCBZL_SZB is pof2 */
465 aligned = (char *)(((HWord)aligned + MAX_DCBZL_SZB) & ~(MAX_DCBZL_SZB - 1));
466 vg_assert((aligned + MAX_DCBZL_SZB) <= &test_block[sizeof(test_block)]);
467
468 /* dcbz often clears 32B, although sometimes whatever the native cache
469 * block size is */
470 VG_(memset)(test_block, 0xff, sizeof(test_block));
471 __asm__ __volatile__("dcbz 0,%0"
472 : /*out*/
473 : "r" (aligned) /*in*/
474 : "memory" /*clobber*/);
475 for (dcbz_szB = 0, i = 0; i < sizeof(test_block); ++i) {
476 if (!test_block[i])
477 ++dcbz_szB;
478 }
479 vg_assert(dcbz_szB == 32 || dcbz_szB == 64 || dcbz_szB == 128);
480
481 /* dcbzl clears 128B on G5/PPC970, and usually 32B on other platforms */
sewardj6c591e12011-04-11 16:17:51 +0000482 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardjb9c815b2010-09-03 15:51:34 +0000483 dcbzl_szB = 0; /* indicates unsupported */
484 }
485 else {
486 VG_(memset)(test_block, 0xff, sizeof(test_block));
487 /* some older assemblers won't understand the dcbzl instruction
488 * variant, so we directly emit the instruction ourselves */
489 __asm__ __volatile__("mr 9, %0 ; .long 0x7C204FEC" /*dcbzl 0,9*/
490 : /*out*/
491 : "r" (aligned) /*in*/
492 : "memory", "r9" /*clobber*/);
493 for (dcbzl_szB = 0, i = 0; i < sizeof(test_block); ++i) {
494 if (!test_block[i])
495 ++dcbzl_szB;
496 }
497 vg_assert(dcbzl_szB == 32 || dcbzl_szB == 64 || dcbzl_szB == 128);
498 }
499
500 arch_info->ppc_dcbz_szB = dcbz_szB;
501 arch_info->ppc_dcbzl_szB = dcbzl_szB;
502
503 VG_(debugLog)(1, "machine", "dcbz_szB=%d dcbzl_szB=%d\n",
504 dcbz_szB, dcbzl_szB);
sewardj5ae70ce2010-09-08 15:12:33 +0000505# undef MAX_DCBZL_SZB
sewardjb9c815b2010-09-03 15:51:34 +0000506}
sewardj5ae70ce2010-09-08 15:12:33 +0000507#endif /* defined(VGA_ppc32) || defined(VGA_ppc64) */
508
sewardj2c3f2ea2011-04-13 15:40:10 +0000509#ifdef VGA_s390x
sewardj5ae70ce2010-09-08 15:12:33 +0000510
sewardj2c3f2ea2011-04-13 15:40:10 +0000511/* Read /proc/cpuinfo. Look for lines like these
512
513 processor 0: version = FF, identification = 0117C9, machine = 2064
514
florian4e63b8e2012-04-22 03:50:20 +0000515 and return the machine model. If the machine model could not be determined
516 or it is an unknown model, return VEX_S390X_MODEL_UNKNOWN. */
sewardj2c3f2ea2011-04-13 15:40:10 +0000517
518static UInt VG_(get_machine_model)(void)
519{
520 static struct model_map {
521 HChar name[5];
522 UInt id;
523 } model_map[] = {
524 { "2064", VEX_S390X_MODEL_Z900 },
525 { "2066", VEX_S390X_MODEL_Z800 },
526 { "2084", VEX_S390X_MODEL_Z990 },
527 { "2086", VEX_S390X_MODEL_Z890 },
528 { "2094", VEX_S390X_MODEL_Z9_EC },
529 { "2096", VEX_S390X_MODEL_Z9_BC },
530 { "2097", VEX_S390X_MODEL_Z10_EC },
531 { "2098", VEX_S390X_MODEL_Z10_BC },
532 { "2817", VEX_S390X_MODEL_Z196 },
florian258ede72011-09-02 22:20:41 +0000533 { "2818", VEX_S390X_MODEL_Z114 },
florian87a25cf2012-08-28 13:33:10 +0000534 { "2827", VEX_S390X_MODEL_ZEC12 },
sewardj2c3f2ea2011-04-13 15:40:10 +0000535 };
536
537 Int model, n, fh;
538 SysRes fd;
539 SizeT num_bytes, file_buf_size;
540 HChar *p, *m, *model_name, *file_buf;
541
542 /* Slurp contents of /proc/cpuinfo into FILE_BUF */
543 fd = VG_(open)( "/proc/cpuinfo", 0, VKI_S_IRUSR );
florian4e63b8e2012-04-22 03:50:20 +0000544 if ( sr_isError(fd) ) return VEX_S390X_MODEL_UNKNOWN;
sewardj2c3f2ea2011-04-13 15:40:10 +0000545
546 fh = sr_Res(fd);
547
548 /* Determine the size of /proc/cpuinfo.
549 Work around broken-ness in /proc file system implementation.
550 fstat returns a zero size for /proc/cpuinfo although it is
551 claimed to be a regular file. */
552 num_bytes = 0;
553 file_buf_size = 1000;
554 file_buf = VG_(malloc)("cpuinfo", file_buf_size + 1);
555 while (42) {
556 n = VG_(read)(fh, file_buf, file_buf_size);
557 if (n < 0) break;
558
559 num_bytes += n;
560 if (n < file_buf_size) break; /* reached EOF */
561 }
562
563 if (n < 0) num_bytes = 0; /* read error; ignore contents */
564
565 if (num_bytes > file_buf_size) {
566 VG_(free)( file_buf );
567 VG_(lseek)( fh, 0, VKI_SEEK_SET );
568 file_buf = VG_(malloc)( "cpuinfo", num_bytes + 1 );
569 n = VG_(read)( fh, file_buf, num_bytes );
570 if (n < 0) num_bytes = 0;
571 }
572
573 file_buf[num_bytes] = '\0';
574 VG_(close)(fh);
575
576 /* Parse file */
florian4e63b8e2012-04-22 03:50:20 +0000577 model = VEX_S390X_MODEL_UNKNOWN;
sewardj2c3f2ea2011-04-13 15:40:10 +0000578 for (p = file_buf; *p; ++p) {
579 /* Beginning of line */
580 if (VG_(strncmp)( p, "processor", sizeof "processor" - 1 ) != 0) continue;
581
582 m = VG_(strstr)( p, "machine" );
583 if (m == NULL) continue;
584
585 p = m + sizeof "machine" - 1;
586 while ( VG_(isspace)( *p ) || *p == '=') {
587 if (*p == '\n') goto next_line;
588 ++p;
589 }
590
591 model_name = p;
592 for (n = 0; n < sizeof model_map / sizeof model_map[0]; ++n) {
593 struct model_map *mm = model_map + n;
594 SizeT len = VG_(strlen)( mm->name );
595 if ( VG_(strncmp)( mm->name, model_name, len ) == 0 &&
596 VG_(isspace)( model_name[len] )) {
597 if (mm->id < model) model = mm->id;
598 p = model_name + len;
599 break;
600 }
601 }
602 /* Skip until end-of-line */
603 while (*p != '\n')
604 ++p;
605 next_line: ;
606 }
607
608 VG_(free)( file_buf );
florian00164922011-10-25 21:37:15 +0000609 VG_(debugLog)(1, "machine", "model = %s\n",
florian4e63b8e2012-04-22 03:50:20 +0000610 model == VEX_S390X_MODEL_UNKNOWN ? "UNKNOWN"
florian00164922011-10-25 21:37:15 +0000611 : model_map[model].name);
sewardj2c3f2ea2011-04-13 15:40:10 +0000612 return model;
613}
614
615#endif /* VGA_s390x */
sewardj5ae70ce2010-09-08 15:12:33 +0000616
sewardj5db15402012-06-07 09:13:21 +0000617#ifdef VGA_mips32
618
619/* Read /proc/cpuinfo and return the machine model. */
620static UInt VG_(get_machine_model)(void)
621{
622 char *search_MIPS_str = "MIPS";
623 char *search_Broadcom_str = "Broadcom";
624 Int n, fh;
625 SysRes fd;
626 SizeT num_bytes, file_buf_size;
627 HChar *file_buf;
628
629 /* Slurp contents of /proc/cpuinfo into FILE_BUF */
630 fd = VG_(open)( "/proc/cpuinfo", 0, VKI_S_IRUSR );
631 if ( sr_isError(fd) ) return -1;
632
633 fh = sr_Res(fd);
634
635 /* Determine the size of /proc/cpuinfo.
636 Work around broken-ness in /proc file system implementation.
637 fstat returns a zero size for /proc/cpuinfo although it is
638 claimed to be a regular file. */
639 num_bytes = 0;
640 file_buf_size = 1000;
641 file_buf = VG_(malloc)("cpuinfo", file_buf_size + 1);
642 while (42) {
643 n = VG_(read)(fh, file_buf, file_buf_size);
644 if (n < 0) break;
645
646 num_bytes += n;
647 if (n < file_buf_size) break; /* reached EOF */
648 }
649
650 if (n < 0) num_bytes = 0; /* read error; ignore contents */
651
652 if (num_bytes > file_buf_size) {
653 VG_(free)( file_buf );
654 VG_(lseek)( fh, 0, VKI_SEEK_SET );
655 file_buf = VG_(malloc)( "cpuinfo", num_bytes + 1 );
656 n = VG_(read)( fh, file_buf, num_bytes );
657 if (n < 0) num_bytes = 0;
658 }
659
660 file_buf[num_bytes] = '\0';
661 VG_(close)(fh);
662
663 /* Parse file */
664 if (VG_(strstr) (file_buf, search_Broadcom_str) != NULL)
665 return VEX_PRID_COMP_BROADCOM;
666 if (VG_(strstr) (file_buf, search_MIPS_str) != NULL)
667 return VEX_PRID_COMP_MIPS;
668
669 /* Did not find string in the proc file. */
670 return -1;
671}
672
673#endif
674
sewardj5ae70ce2010-09-08 15:12:33 +0000675/* Determine what insn set and insn set variant the host has, and
676 record it. To be called once at system startup. Returns False if
florian78627012012-10-07 19:47:04 +0000677 this a CPU incapable of running Valgrind.
678 Also determine information about the caches on this host. */
sewardje3826cf2005-11-13 00:30:22 +0000679
sewardje2d1e672005-11-12 23:10:48 +0000680Bool VG_(machine_get_hwcaps)( void )
681{
682 vg_assert(hwcaps_done == False);
683 hwcaps_done = True;
684
685 // Whack default settings into vai, so that we only need to fill in
686 // any interesting bits.
687 LibVEX_default_VexArchInfo(&vai);
688
689#if defined(VGA_x86)
sewardj40d91c72010-07-29 15:40:32 +0000690 { Bool have_sse1, have_sse2, have_cx8, have_lzcnt;
sewardjc7ffc942011-03-28 16:26:42 +0000691 UInt eax, ebx, ecx, edx, max_extended;
sewardj40d91c72010-07-29 15:40:32 +0000692 UChar vstr[13];
693 vstr[0] = 0;
sewardje2d1e672005-11-12 23:10:48 +0000694
695 if (!VG_(has_cpuid)())
696 /* we can't do cpuid at all. Give up. */
697 return False;
698
tomad8a5912011-06-10 15:04:22 +0000699 VG_(cpuid)(0, 0, &eax, &ebx, &ecx, &edx);
sewardje2d1e672005-11-12 23:10:48 +0000700 if (eax < 1)
701 /* we can't ask for cpuid(x) for x > 0. Give up. */
702 return False;
703
sewardj40d91c72010-07-29 15:40:32 +0000704 /* Get processor ID string, and max basic/extended index
705 values. */
sewardj40d91c72010-07-29 15:40:32 +0000706 VG_(memcpy)(&vstr[0], &ebx, 4);
707 VG_(memcpy)(&vstr[4], &edx, 4);
708 VG_(memcpy)(&vstr[8], &ecx, 4);
709 vstr[12] = 0;
710
tomad8a5912011-06-10 15:04:22 +0000711 VG_(cpuid)(0x80000000, 0, &eax, &ebx, &ecx, &edx);
sewardj40d91c72010-07-29 15:40:32 +0000712 max_extended = eax;
713
sewardje2d1e672005-11-12 23:10:48 +0000714 /* get capabilities bits into edx */
tomad8a5912011-06-10 15:04:22 +0000715 VG_(cpuid)(1, 0, &eax, &ebx, &ecx, &edx);
sewardje2d1e672005-11-12 23:10:48 +0000716
717 have_sse1 = (edx & (1<<25)) != 0; /* True => have sse insns */
718 have_sse2 = (edx & (1<<26)) != 0; /* True => have sse2 insns */
719
sewardj1c0ce7a2009-07-01 08:10:49 +0000720 /* cmpxchg8b is a minimum requirement now; if we don't have it we
721 must simply give up. But all CPUs since Pentium-I have it, so
722 that doesn't seem like much of a restriction. */
723 have_cx8 = (edx & (1<<8)) != 0; /* True => have cmpxchg8b */
724 if (!have_cx8)
725 return False;
726
sewardj40d91c72010-07-29 15:40:32 +0000727 /* Figure out if this is an AMD that can do LZCNT. */
728 have_lzcnt = False;
729 if (0 == VG_(strcmp)(vstr, "AuthenticAMD")
730 && max_extended >= 0x80000001) {
tomad8a5912011-06-10 15:04:22 +0000731 VG_(cpuid)(0x80000001, 0, &eax, &ebx, &ecx, &edx);
sewardj40d91c72010-07-29 15:40:32 +0000732 have_lzcnt = (ecx & (1<<5)) != 0; /* True => have LZCNT */
733 }
734
florian78627012012-10-07 19:47:04 +0000735 va = VexArchX86;
sewardje2d1e672005-11-12 23:10:48 +0000736 if (have_sse2 && have_sse1) {
sewardje3121f32006-01-27 21:23:23 +0000737 vai.hwcaps = VEX_HWCAPS_X86_SSE1;
738 vai.hwcaps |= VEX_HWCAPS_X86_SSE2;
sewardj40d91c72010-07-29 15:40:32 +0000739 if (have_lzcnt)
740 vai.hwcaps |= VEX_HWCAPS_X86_LZCNT;
sewardje2d1e672005-11-12 23:10:48 +0000741 VG_(machine_x86_have_mxcsr) = 1;
florian78627012012-10-07 19:47:04 +0000742 } else if (have_sse1) {
sewardje3121f32006-01-27 21:23:23 +0000743 vai.hwcaps = VEX_HWCAPS_X86_SSE1;
sewardje2d1e672005-11-12 23:10:48 +0000744 VG_(machine_x86_have_mxcsr) = 1;
florian78627012012-10-07 19:47:04 +0000745 } else {
746 vai.hwcaps = 0; /*baseline - no sse at all*/
747 VG_(machine_x86_have_mxcsr) = 0;
sewardje2d1e672005-11-12 23:10:48 +0000748 }
749
florian78627012012-10-07 19:47:04 +0000750 VG_(machine_get_cache_info)(&vai);
751
sewardje2d1e672005-11-12 23:10:48 +0000752 return True;
753 }
754
755#elif defined(VGA_amd64)
sewardjc7ffc942011-03-28 16:26:42 +0000756 { Bool have_sse3, have_cx8, have_cx16;
sewardjee1a8972012-04-26 14:17:50 +0000757 Bool have_lzcnt, have_avx /*, have_fma*/;
sewardjc7ffc942011-03-28 16:26:42 +0000758 UInt eax, ebx, ecx, edx, max_extended;
sewardj40d91c72010-07-29 15:40:32 +0000759 UChar vstr[13];
760 vstr[0] = 0;
sewardj1c0ce7a2009-07-01 08:10:49 +0000761
762 if (!VG_(has_cpuid)())
763 /* we can't do cpuid at all. Give up. */
764 return False;
765
tomad8a5912011-06-10 15:04:22 +0000766 VG_(cpuid)(0, 0, &eax, &ebx, &ecx, &edx);
sewardj1c0ce7a2009-07-01 08:10:49 +0000767 if (eax < 1)
768 /* we can't ask for cpuid(x) for x > 0. Give up. */
769 return False;
770
sewardj40d91c72010-07-29 15:40:32 +0000771 /* Get processor ID string, and max basic/extended index
772 values. */
sewardj40d91c72010-07-29 15:40:32 +0000773 VG_(memcpy)(&vstr[0], &ebx, 4);
774 VG_(memcpy)(&vstr[4], &edx, 4);
775 VG_(memcpy)(&vstr[8], &ecx, 4);
776 vstr[12] = 0;
777
tomad8a5912011-06-10 15:04:22 +0000778 VG_(cpuid)(0x80000000, 0, &eax, &ebx, &ecx, &edx);
sewardj40d91c72010-07-29 15:40:32 +0000779 max_extended = eax;
780
sewardj1c0ce7a2009-07-01 08:10:49 +0000781 /* get capabilities bits into edx */
tomad8a5912011-06-10 15:04:22 +0000782 VG_(cpuid)(1, 0, &eax, &ebx, &ecx, &edx);
sewardj1c0ce7a2009-07-01 08:10:49 +0000783
sewardjc7ffc942011-03-28 16:26:42 +0000784 // we assume that SSE1 and SSE2 are available by default
sewardj598971e2009-07-12 13:19:04 +0000785 have_sse3 = (ecx & (1<<0)) != 0; /* True => have sse3 insns */
sewardjee1a8972012-04-26 14:17:50 +0000786 // ssse3 is ecx:9
787 // sse41 is ecx:19
788 // sse42 is ecx:20
789
790 // osxsave is ecx:27
791 // avx is ecx:28
792 // fma is ecx:12
793 have_avx = False;
794 /* have_fma = False; */
795 if ( (ecx & ((1<<27)|(1<<28))) == ((1<<27)|(1<<28)) ) {
796 /* processor supports AVX instructions and XGETBV is enabled
797 by OS */
798 ULong w;
799 __asm__ __volatile__("movq $0,%%rcx ; "
800 ".byte 0x0F,0x01,0xD0 ; " /* xgetbv */
801 "movq %%rax,%0"
802 :/*OUT*/"=r"(w) :/*IN*/
803 :/*TRASH*/"rdx","rcx");
804 if ((w & 6) == 6) {
805 /* OS has enabled both XMM and YMM state support */
806 have_avx = True;
807 /* have_fma = (ecx & (1<<12)) != 0; */
808 /* have_fma: Probably correct, but gcc complains due to
809 unusedness. &*/
810 }
811 }
812
sewardj1c0ce7a2009-07-01 08:10:49 +0000813
814 /* cmpxchg8b is a minimum requirement now; if we don't have it we
815 must simply give up. But all CPUs since Pentium-I have it, so
816 that doesn't seem like much of a restriction. */
817 have_cx8 = (edx & (1<<8)) != 0; /* True => have cmpxchg8b */
818 if (!have_cx8)
819 return False;
820
821 /* on amd64 we tolerate older cpus, which don't have cmpxchg16b */
822 have_cx16 = (ecx & (1<<13)) != 0; /* True => have cmpxchg16b */
823
sewardj40d91c72010-07-29 15:40:32 +0000824 /* Figure out if this is an AMD that can do LZCNT. */
825 have_lzcnt = False;
826 if (0 == VG_(strcmp)(vstr, "AuthenticAMD")
827 && max_extended >= 0x80000001) {
tomad8a5912011-06-10 15:04:22 +0000828 VG_(cpuid)(0x80000001, 0, &eax, &ebx, &ecx, &edx);
sewardj40d91c72010-07-29 15:40:32 +0000829 have_lzcnt = (ecx & (1<<5)) != 0; /* True => have LZCNT */
830 }
831
sewardj1c0ce7a2009-07-01 08:10:49 +0000832 va = VexArchAMD64;
sewardjee1a8972012-04-26 14:17:50 +0000833 vai.hwcaps = (have_sse3 ? VEX_HWCAPS_AMD64_SSE3 : 0)
834 | (have_cx16 ? VEX_HWCAPS_AMD64_CX16 : 0)
835 | (have_lzcnt ? VEX_HWCAPS_AMD64_LZCNT : 0)
836 | (have_avx ? VEX_HWCAPS_AMD64_AVX : 0);
florian78627012012-10-07 19:47:04 +0000837
838 VG_(machine_get_cache_info)(&vai);
839
sewardj1c0ce7a2009-07-01 08:10:49 +0000840 return True;
841 }
sewardje2d1e672005-11-12 23:10:48 +0000842
843#elif defined(VGA_ppc32)
bart1581e742009-01-13 07:49:14 +0000844 {
845 /* Find out which subset of the ppc32 instruction set is supported by
846 verifying whether various ppc32 instructions generate a SIGILL
847 or a SIGFPE. An alternative approach is to check the AT_HWCAP and
848 AT_PLATFORM entries in the ELF auxiliary table -- see also
849 the_iifii.client_auxv in m_main.c.
850 */
njncda2f0f2009-05-18 02:12:08 +0000851 vki_sigset_t saved_set, tmp_set;
852 vki_sigaction_fromK_t saved_sigill_act, saved_sigfpe_act;
853 vki_sigaction_toK_t tmp_sigill_act, tmp_sigfpe_act;
sewardje3826cf2005-11-13 00:30:22 +0000854
sewardj5ba075a2012-04-02 21:25:14 +0000855 volatile Bool have_F, have_V, have_FX, have_GX, have_VX, have_DFP;
sewardj7637e9e2006-02-21 17:11:11 +0000856 Int r;
sewardje3826cf2005-11-13 00:30:22 +0000857
njncda2f0f2009-05-18 02:12:08 +0000858 /* This is a kludge. Really we ought to back-convert saved_act
859 into a toK_t using VG_(convert_sigaction_fromK_to_toK), but
860 since that's a no-op on all ppc32 platforms so far supported,
861 it's not worth the typing effort. At least include most basic
862 sanity check: */
863 vg_assert(sizeof(vki_sigaction_fromK_t) == sizeof(vki_sigaction_toK_t));
864
sewardje3826cf2005-11-13 00:30:22 +0000865 VG_(sigemptyset)(&tmp_set);
866 VG_(sigaddset)(&tmp_set, VKI_SIGILL);
bart1581e742009-01-13 07:49:14 +0000867 VG_(sigaddset)(&tmp_set, VKI_SIGFPE);
sewardje3826cf2005-11-13 00:30:22 +0000868
sewardj7637e9e2006-02-21 17:11:11 +0000869 r = VG_(sigprocmask)(VKI_SIG_UNBLOCK, &tmp_set, &saved_set);
870 vg_assert(r == 0);
sewardje3826cf2005-11-13 00:30:22 +0000871
bart1581e742009-01-13 07:49:14 +0000872 r = VG_(sigaction)(VKI_SIGILL, NULL, &saved_sigill_act);
sewardj7637e9e2006-02-21 17:11:11 +0000873 vg_assert(r == 0);
bart1581e742009-01-13 07:49:14 +0000874 tmp_sigill_act = saved_sigill_act;
875
876 r = VG_(sigaction)(VKI_SIGFPE, NULL, &saved_sigfpe_act);
877 vg_assert(r == 0);
878 tmp_sigfpe_act = saved_sigfpe_act;
sewardje3826cf2005-11-13 00:30:22 +0000879
sewardj7637e9e2006-02-21 17:11:11 +0000880 /* NODEFER: signal handler does not return (from the kernel's point of
881 view), hence if it is to successfully catch a signal more than once,
882 we need the NODEFER flag. */
bart1581e742009-01-13 07:49:14 +0000883 tmp_sigill_act.sa_flags &= ~VKI_SA_RESETHAND;
884 tmp_sigill_act.sa_flags &= ~VKI_SA_SIGINFO;
885 tmp_sigill_act.sa_flags |= VKI_SA_NODEFER;
886 tmp_sigill_act.ksa_handler = handler_unsup_insn;
887 r = VG_(sigaction)(VKI_SIGILL, &tmp_sigill_act, NULL);
888 vg_assert(r == 0);
889
890 tmp_sigfpe_act.sa_flags &= ~VKI_SA_RESETHAND;
891 tmp_sigfpe_act.sa_flags &= ~VKI_SA_SIGINFO;
892 tmp_sigfpe_act.sa_flags |= VKI_SA_NODEFER;
893 tmp_sigfpe_act.ksa_handler = handler_unsup_insn;
894 r = VG_(sigaction)(VKI_SIGFPE, &tmp_sigfpe_act, NULL);
895 vg_assert(r == 0);
sewardje3826cf2005-11-13 00:30:22 +0000896
sewardje3121f32006-01-27 21:23:23 +0000897 /* standard FP insns */
898 have_F = True;
sewardj6c591e12011-04-11 16:17:51 +0000899 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardje3121f32006-01-27 21:23:23 +0000900 have_F = False;
sewardje3826cf2005-11-13 00:30:22 +0000901 } else {
sewardjf1c91e02006-10-17 01:35:58 +0000902 __asm__ __volatile__(".long 0xFC000090"); /*fmr 0,0 */
sewardje3826cf2005-11-13 00:30:22 +0000903 }
904
sewardje3121f32006-01-27 21:23:23 +0000905 /* Altivec insns */
906 have_V = True;
sewardj6c591e12011-04-11 16:17:51 +0000907 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardje3121f32006-01-27 21:23:23 +0000908 have_V = False;
sewardje3826cf2005-11-13 00:30:22 +0000909 } else {
sewardj71592122006-04-04 03:29:48 +0000910 /* Unfortunately some older assemblers don't speak Altivec (or
911 choose not to), so to be safe we directly emit the 32-bit
912 word corresponding to "vor 0,0,0". This fixes a build
913 problem that happens on Debian 3.1 (ppc32), and probably
914 various other places. */
sewardj54d0dc72006-04-04 03:08:49 +0000915 __asm__ __volatile__(".long 0x10000484"); /*vor 0,0,0*/
sewardje3826cf2005-11-13 00:30:22 +0000916 }
917
sewardje3121f32006-01-27 21:23:23 +0000918 /* General-Purpose optional (fsqrt, fsqrts) */
919 have_FX = True;
sewardj6c591e12011-04-11 16:17:51 +0000920 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardje3121f32006-01-27 21:23:23 +0000921 have_FX = False;
922 } else {
sewardjf1c91e02006-10-17 01:35:58 +0000923 __asm__ __volatile__(".long 0xFC00002C"); /*fsqrt 0,0 */
sewardje3121f32006-01-27 21:23:23 +0000924 }
925
926 /* Graphics optional (stfiwx, fres, frsqrte, fsel) */
927 have_GX = True;
sewardj6c591e12011-04-11 16:17:51 +0000928 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardje3121f32006-01-27 21:23:23 +0000929 have_GX = False;
930 } else {
sewardjf1c91e02006-10-17 01:35:58 +0000931 __asm__ __volatile__(".long 0xFC000034"); /* frsqrte 0,0 */
sewardje3121f32006-01-27 21:23:23 +0000932 }
933
sewardjf34eb492011-04-15 11:57:05 +0000934 /* VSX support implies Power ISA 2.06 */
935 have_VX = True;
936 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
937 have_VX = False;
938 } else {
939 __asm__ __volatile__(".long 0xf0000564"); /* xsabsdp XT,XB */
940 }
941
sewardj5ba075a2012-04-02 21:25:14 +0000942 /* Check for Decimal Floating Point (DFP) support. */
943 have_DFP = True;
944 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
945 have_DFP = False;
946 } else {
947 __asm__ __volatile__(".long 0xee4e8005"); /* dadd FRT,FRA, FRB */
948 }
sewardjf34eb492011-04-15 11:57:05 +0000949
sewardjb9c815b2010-09-03 15:51:34 +0000950 /* determine dcbz/dcbzl sizes while we still have the signal
951 * handlers registered */
952 find_ppc_dcbz_sz(&vai);
953
bart1581e742009-01-13 07:49:14 +0000954 r = VG_(sigaction)(VKI_SIGILL, &saved_sigill_act, NULL);
955 vg_assert(r == 0);
956 r = VG_(sigaction)(VKI_SIGFPE, &saved_sigfpe_act, NULL);
sewardj7637e9e2006-02-21 17:11:11 +0000957 vg_assert(r == 0);
958 r = VG_(sigprocmask)(VKI_SIG_SETMASK, &saved_set, NULL);
959 vg_assert(r == 0);
sewardj5ba075a2012-04-02 21:25:14 +0000960 VG_(debugLog)(1, "machine", "F %d V %d FX %d GX %d VX %d DFP %d\n",
sewardjf34eb492011-04-15 11:57:05 +0000961 (Int)have_F, (Int)have_V, (Int)have_FX,
sewardj5ba075a2012-04-02 21:25:14 +0000962 (Int)have_GX, (Int)have_VX, (Int)have_DFP);
sewardje3121f32006-01-27 21:23:23 +0000963 /* Make FP a prerequisite for VMX (bogusly so), and for FX and GX. */
964 if (have_V && !have_F)
965 have_V = False;
966 if (have_FX && !have_F)
967 have_FX = False;
968 if (have_GX && !have_F)
969 have_GX = False;
sewardje3826cf2005-11-13 00:30:22 +0000970
sewardje3121f32006-01-27 21:23:23 +0000971 VG_(machine_ppc32_has_FP) = have_F ? 1 : 0;
972 VG_(machine_ppc32_has_VMX) = have_V ? 1 : 0;
sewardje3826cf2005-11-13 00:30:22 +0000973
974 va = VexArchPPC32;
975
sewardje3121f32006-01-27 21:23:23 +0000976 vai.hwcaps = 0;
977 if (have_F) vai.hwcaps |= VEX_HWCAPS_PPC32_F;
978 if (have_V) vai.hwcaps |= VEX_HWCAPS_PPC32_V;
979 if (have_FX) vai.hwcaps |= VEX_HWCAPS_PPC32_FX;
980 if (have_GX) vai.hwcaps |= VEX_HWCAPS_PPC32_GX;
sewardjf34eb492011-04-15 11:57:05 +0000981 if (have_VX) vai.hwcaps |= VEX_HWCAPS_PPC32_VX;
sewardj5ba075a2012-04-02 21:25:14 +0000982 if (have_DFP) vai.hwcaps |= VEX_HWCAPS_PPC32_DFP;
983
florian78627012012-10-07 19:47:04 +0000984 VG_(machine_get_cache_info)(&vai);
sewardje3826cf2005-11-13 00:30:22 +0000985
986 /* But we're not done yet: VG_(machine_ppc32_set_clszB) must be
987 called before we're ready to go. */
988 return True;
989 }
sewardje2d1e672005-11-12 23:10:48 +0000990
sewardj2c48c7b2005-11-29 13:05:56 +0000991#elif defined(VGA_ppc64)
bart1581e742009-01-13 07:49:14 +0000992 {
993 /* Same instruction set detection algorithm as for ppc32. */
njncda2f0f2009-05-18 02:12:08 +0000994 vki_sigset_t saved_set, tmp_set;
995 vki_sigaction_fromK_t saved_sigill_act, saved_sigfpe_act;
996 vki_sigaction_toK_t tmp_sigill_act, tmp_sigfpe_act;
sewardj2c48c7b2005-11-29 13:05:56 +0000997
sewardj5ba075a2012-04-02 21:25:14 +0000998 volatile Bool have_F, have_V, have_FX, have_GX, have_VX, have_DFP;
njncda2f0f2009-05-18 02:12:08 +0000999 Int r;
1000
1001 /* This is a kludge. Really we ought to back-convert saved_act
1002 into a toK_t using VG_(convert_sigaction_fromK_to_toK), but
1003 since that's a no-op on all ppc64 platforms so far supported,
1004 it's not worth the typing effort. At least include most basic
1005 sanity check: */
1006 vg_assert(sizeof(vki_sigaction_fromK_t) == sizeof(vki_sigaction_toK_t));
sewardj2c48c7b2005-11-29 13:05:56 +00001007
1008 VG_(sigemptyset)(&tmp_set);
1009 VG_(sigaddset)(&tmp_set, VKI_SIGILL);
bart1581e742009-01-13 07:49:14 +00001010 VG_(sigaddset)(&tmp_set, VKI_SIGFPE);
sewardj2c48c7b2005-11-29 13:05:56 +00001011
njncda2f0f2009-05-18 02:12:08 +00001012 r = VG_(sigprocmask)(VKI_SIG_UNBLOCK, &tmp_set, &saved_set);
1013 vg_assert(r == 0);
sewardj2c48c7b2005-11-29 13:05:56 +00001014
njncda2f0f2009-05-18 02:12:08 +00001015 r = VG_(sigaction)(VKI_SIGILL, NULL, &saved_sigill_act);
1016 vg_assert(r == 0);
bart1581e742009-01-13 07:49:14 +00001017 tmp_sigill_act = saved_sigill_act;
1018
1019 VG_(sigaction)(VKI_SIGFPE, NULL, &saved_sigfpe_act);
1020 tmp_sigfpe_act = saved_sigfpe_act;
1021
sewardj7637e9e2006-02-21 17:11:11 +00001022 /* NODEFER: signal handler does not return (from the kernel's point of
1023 view), hence if it is to successfully catch a signal more than once,
1024 we need the NODEFER flag. */
bart1581e742009-01-13 07:49:14 +00001025 tmp_sigill_act.sa_flags &= ~VKI_SA_RESETHAND;
1026 tmp_sigill_act.sa_flags &= ~VKI_SA_SIGINFO;
1027 tmp_sigill_act.sa_flags |= VKI_SA_NODEFER;
1028 tmp_sigill_act.ksa_handler = handler_unsup_insn;
1029 VG_(sigaction)(VKI_SIGILL, &tmp_sigill_act, NULL);
1030
1031 tmp_sigfpe_act.sa_flags &= ~VKI_SA_RESETHAND;
1032 tmp_sigfpe_act.sa_flags &= ~VKI_SA_SIGINFO;
1033 tmp_sigfpe_act.sa_flags |= VKI_SA_NODEFER;
1034 tmp_sigfpe_act.ksa_handler = handler_unsup_insn;
1035 VG_(sigaction)(VKI_SIGFPE, &tmp_sigfpe_act, NULL);
sewardj2c48c7b2005-11-29 13:05:56 +00001036
sewardje3121f32006-01-27 21:23:23 +00001037 /* standard FP insns */
1038 have_F = True;
sewardj6c591e12011-04-11 16:17:51 +00001039 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardje3121f32006-01-27 21:23:23 +00001040 have_F = False;
1041 } else {
1042 __asm__ __volatile__("fmr 0,0");
1043 }
1044
1045 /* Altivec insns */
1046 have_V = True;
sewardj6c591e12011-04-11 16:17:51 +00001047 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardje3121f32006-01-27 21:23:23 +00001048 have_V = False;
sewardj2c48c7b2005-11-29 13:05:56 +00001049 } else {
sewardjf1c91e02006-10-17 01:35:58 +00001050 __asm__ __volatile__(".long 0x10000484"); /*vor 0,0,0*/
sewardj2c48c7b2005-11-29 13:05:56 +00001051 }
1052
sewardje3121f32006-01-27 21:23:23 +00001053 /* General-Purpose optional (fsqrt, fsqrts) */
1054 have_FX = True;
sewardj6c591e12011-04-11 16:17:51 +00001055 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardje3121f32006-01-27 21:23:23 +00001056 have_FX = False;
1057 } else {
sewardjf1c91e02006-10-17 01:35:58 +00001058 __asm__ __volatile__(".long 0xFC00002C"); /*fsqrt 0,0*/
sewardje3121f32006-01-27 21:23:23 +00001059 }
1060
1061 /* Graphics optional (stfiwx, fres, frsqrte, fsel) */
1062 have_GX = True;
sewardj6c591e12011-04-11 16:17:51 +00001063 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardje3121f32006-01-27 21:23:23 +00001064 have_GX = False;
1065 } else {
sewardjf1c91e02006-10-17 01:35:58 +00001066 __asm__ __volatile__(".long 0xFC000034"); /*frsqrte 0,0*/
sewardje3121f32006-01-27 21:23:23 +00001067 }
1068
sewardjf34eb492011-04-15 11:57:05 +00001069 /* VSX support implies Power ISA 2.06 */
1070 have_VX = True;
1071 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
1072 have_VX = False;
1073 } else {
1074 __asm__ __volatile__(".long 0xf0000564"); /* xsabsdp XT,XB */
1075 }
1076
sewardj5ba075a2012-04-02 21:25:14 +00001077 /* Check for Decimal Floating Point (DFP) support. */
1078 have_DFP = True;
1079 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
1080 have_DFP = False;
1081 } else {
1082 __asm__ __volatile__(".long 0xee4e8005"); /* dadd FRT,FRA, FRB */
1083 }
1084
sewardjb9c815b2010-09-03 15:51:34 +00001085 /* determine dcbz/dcbzl sizes while we still have the signal
1086 * handlers registered */
1087 find_ppc_dcbz_sz(&vai);
1088
bart1581e742009-01-13 07:49:14 +00001089 VG_(sigaction)(VKI_SIGILL, &saved_sigill_act, NULL);
1090 VG_(sigaction)(VKI_SIGFPE, &saved_sigfpe_act, NULL);
sewardj2c48c7b2005-11-29 13:05:56 +00001091 VG_(sigprocmask)(VKI_SIG_SETMASK, &saved_set, NULL);
sewardj5ba075a2012-04-02 21:25:14 +00001092 VG_(debugLog)(1, "machine", "F %d V %d FX %d GX %d VX %d DFP %d\n",
sewardjf34eb492011-04-15 11:57:05 +00001093 (Int)have_F, (Int)have_V, (Int)have_FX,
sewardj5ba075a2012-04-02 21:25:14 +00001094 (Int)have_GX, (Int)have_VX, (Int)have_DFP);
sewardje3121f32006-01-27 21:23:23 +00001095 /* on ppc64, if we don't even have FP, just give up. */
1096 if (!have_F)
1097 return False;
1098
1099 VG_(machine_ppc64_has_VMX) = have_V ? 1 : 0;
sewardj2c48c7b2005-11-29 13:05:56 +00001100
1101 va = VexArchPPC64;
sewardje3121f32006-01-27 21:23:23 +00001102
1103 vai.hwcaps = 0;
1104 if (have_V) vai.hwcaps |= VEX_HWCAPS_PPC64_V;
1105 if (have_FX) vai.hwcaps |= VEX_HWCAPS_PPC64_FX;
1106 if (have_GX) vai.hwcaps |= VEX_HWCAPS_PPC64_GX;
sewardjf34eb492011-04-15 11:57:05 +00001107 if (have_VX) vai.hwcaps |= VEX_HWCAPS_PPC64_VX;
sewardj5ba075a2012-04-02 21:25:14 +00001108 if (have_DFP) vai.hwcaps |= VEX_HWCAPS_PPC64_DFP;
sewardj2c48c7b2005-11-29 13:05:56 +00001109
florian78627012012-10-07 19:47:04 +00001110 VG_(machine_get_cache_info)(&vai);
1111
sewardj2c48c7b2005-11-29 13:05:56 +00001112 /* But we're not done yet: VG_(machine_ppc64_set_clszB) must be
1113 called before we're ready to go. */
1114 return True;
1115 }
1116
sewardjb5b87402011-03-07 16:05:35 +00001117#elif defined(VGA_s390x)
1118 {
1119 /* Instruction set detection code borrowed from ppc above. */
1120 vki_sigset_t saved_set, tmp_set;
1121 vki_sigaction_fromK_t saved_sigill_act;
1122 vki_sigaction_toK_t tmp_sigill_act;
1123
sewardj1c6f6ab2011-04-27 12:00:51 +00001124 volatile Bool have_LDISP, have_EIMM, have_GIE, have_DFP, have_FGX;
florian370bc772012-08-30 20:30:32 +00001125 volatile Bool have_STFLE, have_ETF2, have_ETF3, have_STCKF, have_FPEXT;
sewardj2c3f2ea2011-04-13 15:40:10 +00001126 Int r, model;
sewardjb5b87402011-03-07 16:05:35 +00001127
1128 /* Unblock SIGILL and stash away the old action for that signal */
1129 VG_(sigemptyset)(&tmp_set);
1130 VG_(sigaddset)(&tmp_set, VKI_SIGILL);
1131
1132 r = VG_(sigprocmask)(VKI_SIG_UNBLOCK, &tmp_set, &saved_set);
1133 vg_assert(r == 0);
1134
1135 r = VG_(sigaction)(VKI_SIGILL, NULL, &saved_sigill_act);
1136 vg_assert(r == 0);
1137 tmp_sigill_act = saved_sigill_act;
1138
1139 /* NODEFER: signal handler does not return (from the kernel's point of
1140 view), hence if it is to successfully catch a signal more than once,
1141 we need the NODEFER flag. */
1142 tmp_sigill_act.sa_flags &= ~VKI_SA_RESETHAND;
1143 tmp_sigill_act.sa_flags &= ~VKI_SA_SIGINFO;
1144 tmp_sigill_act.sa_flags |= VKI_SA_NODEFER;
1145 tmp_sigill_act.ksa_handler = handler_unsup_insn;
1146 VG_(sigaction)(VKI_SIGILL, &tmp_sigill_act, NULL);
1147
1148 /* Determine hwcaps. Note, we cannot use the stfle insn because it
1149 is not supported on z900. */
1150
1151 have_LDISP = True;
sewardj6c591e12011-04-11 16:17:51 +00001152 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardjb5b87402011-03-07 16:05:35 +00001153 have_LDISP = False;
1154 } else {
1155 /* BASR loads the address of the next insn into r1. Needed to avoid
1156 a segfault in XY. */
1157 __asm__ __volatile__("basr %%r1,%%r0\n\t"
1158 ".long 0xe3001000\n\t" /* XY 0,0(%r1) */
1159 ".short 0x0057" : : : "r0", "r1", "cc", "memory");
1160 }
1161
1162 have_EIMM = True;
sewardj6c591e12011-04-11 16:17:51 +00001163 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardjb5b87402011-03-07 16:05:35 +00001164 have_EIMM = False;
1165 } else {
1166 __asm__ __volatile__(".long 0xc0090000\n\t" /* iilf r0,0 */
1167 ".short 0x0000" : : : "r0", "memory");
1168 }
1169
1170 have_GIE = True;
sewardj6c591e12011-04-11 16:17:51 +00001171 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardjb5b87402011-03-07 16:05:35 +00001172 have_GIE = False;
1173 } else {
1174 __asm__ __volatile__(".long 0xc2010000\n\t" /* msfi r0,0 */
1175 ".short 0x0000" : : : "r0", "memory");
1176 }
1177
1178 have_DFP = True;
sewardj6c591e12011-04-11 16:17:51 +00001179 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardjb5b87402011-03-07 16:05:35 +00001180 have_DFP = False;
1181 } else {
1182 __asm__ __volatile__(".long 0xb3d20000"
1183 : : : "r0", "cc", "memory"); /* adtr r0,r0,r0 */
1184 }
1185
sewardj1c6f6ab2011-04-27 12:00:51 +00001186 have_FGX = True;
1187 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
1188 have_FGX = False;
1189 } else {
1190 __asm__ __volatile__(".long 0xb3cd0000" : : : "r0"); /* lgdr r0,f0 */
1191 }
1192
florian833ffd02012-08-26 04:23:08 +00001193 /* Detect presence of certain facilities using the STFLE insn.
1194 Note, that these facilities were introduced at the same time or later
1195 as STFLE, so the absence of STLFE implies the absence of the facility
1196 we're trying to detect. */
floriand19733c2012-01-15 21:02:44 +00001197 have_STFLE = True;
1198 have_ETF2 = False;
floriane3d028c2012-05-03 01:31:24 +00001199 have_ETF3 = False;
florian833ffd02012-08-26 04:23:08 +00001200 have_STCKF = False;
floriane9685912012-09-01 23:48:09 +00001201 have_FPEXT = False;
floriand19733c2012-01-15 21:02:44 +00001202 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
1203 have_STFLE = False;
1204 } else {
1205 ULong hoststfle[1];
1206 register ULong reg0 asm("0") = 0; /* one double word available */
1207
1208 __asm__ __volatile__(" .insn s,0xb2b00000,%0\n" /* stfle */
1209 : "=m" (hoststfle), "+d"(reg0)
1210 : : "cc", "memory");
1211 if (hoststfle[0] & (1ULL << (63 - 24)))
1212 have_ETF2 = True;
floriane3d028c2012-05-03 01:31:24 +00001213 if (hoststfle[0] & (1ULL << (63 - 30)))
1214 have_ETF3 = True;
florian833ffd02012-08-26 04:23:08 +00001215 if (hoststfle[0] & (1ULL << (63 - 25)))
1216 have_STCKF = True;
florian370bc772012-08-30 20:30:32 +00001217 if (hoststfle[0] & (1ULL << (63 - 37)))
1218 have_FPEXT = True;
floriand19733c2012-01-15 21:02:44 +00001219 }
1220
sewardjb5b87402011-03-07 16:05:35 +00001221 /* Restore signals */
1222 r = VG_(sigaction)(VKI_SIGILL, &saved_sigill_act, NULL);
1223 vg_assert(r == 0);
1224 r = VG_(sigprocmask)(VKI_SIG_SETMASK, &saved_set, NULL);
1225 vg_assert(r == 0);
sewardjb5b87402011-03-07 16:05:35 +00001226 va = VexArchS390X;
1227
sewardj2c3f2ea2011-04-13 15:40:10 +00001228 model = VG_(get_machine_model)();
1229
florian4e63b8e2012-04-22 03:50:20 +00001230 /* If the model is "unknown" don't treat this as an error. Assume
1231 this is a brand-new machine model for which we don't have the
1232 identification yet. Keeping fingers crossed. */
1233
sewardj1c6f6ab2011-04-27 12:00:51 +00001234 VG_(debugLog)(1, "machine", "machine %d LDISP %d EIMM %d GIE %d DFP %d "
florian833ffd02012-08-26 04:23:08 +00001235 "FGX %d STFLE %d ETF2 %d ETF3 %d STCKF %d\n",
1236 model, have_LDISP, have_EIMM, have_GIE, have_DFP, have_FGX,
1237 have_STFLE, have_ETF2, have_ETF3, have_STCKF);
sewardj2c3f2ea2011-04-13 15:40:10 +00001238
sewardj2c3f2ea2011-04-13 15:40:10 +00001239 vai.hwcaps = model;
1240 if (have_LDISP) {
1241 /* Use long displacement only on machines >= z990. For all other machines
1242 it is millicoded and therefore slow. */
1243 if (model >= VEX_S390X_MODEL_Z990)
1244 vai.hwcaps |= VEX_HWCAPS_S390X_LDISP;
1245 }
sewardjb5b87402011-03-07 16:05:35 +00001246 if (have_EIMM) vai.hwcaps |= VEX_HWCAPS_S390X_EIMM;
1247 if (have_GIE) vai.hwcaps |= VEX_HWCAPS_S390X_GIE;
1248 if (have_DFP) vai.hwcaps |= VEX_HWCAPS_S390X_DFP;
sewardj1c6f6ab2011-04-27 12:00:51 +00001249 if (have_FGX) vai.hwcaps |= VEX_HWCAPS_S390X_FGX;
floriand19733c2012-01-15 21:02:44 +00001250 if (have_ETF2) vai.hwcaps |= VEX_HWCAPS_S390X_ETF2;
floriane3d028c2012-05-03 01:31:24 +00001251 if (have_ETF3) vai.hwcaps |= VEX_HWCAPS_S390X_ETF3;
florian68aba522012-04-21 15:43:25 +00001252 if (have_STFLE) vai.hwcaps |= VEX_HWCAPS_S390X_STFLE;
florian833ffd02012-08-26 04:23:08 +00001253 if (have_STCKF) vai.hwcaps |= VEX_HWCAPS_S390X_STCKF;
florian370bc772012-08-30 20:30:32 +00001254 if (have_FPEXT) vai.hwcaps |= VEX_HWCAPS_S390X_FPEXT;
sewardjb5b87402011-03-07 16:05:35 +00001255
sewardj2c3f2ea2011-04-13 15:40:10 +00001256 VG_(debugLog)(1, "machine", "hwcaps = 0x%x\n", vai.hwcaps);
1257
florian78627012012-10-07 19:47:04 +00001258 VG_(machine_get_cache_info)(&vai);
1259
sewardjb5b87402011-03-07 16:05:35 +00001260 return True;
1261 }
1262
sewardj59570ff2010-01-01 11:59:33 +00001263#elif defined(VGA_arm)
1264 {
sewardj1dbd3372010-08-22 12:21:14 +00001265 /* Same instruction set detection algorithm as for ppc32. */
1266 vki_sigset_t saved_set, tmp_set;
1267 vki_sigaction_fromK_t saved_sigill_act, saved_sigfpe_act;
1268 vki_sigaction_toK_t tmp_sigill_act, tmp_sigfpe_act;
1269
1270 volatile Bool have_VFP, have_VFP2, have_VFP3, have_NEON;
1271 volatile Int archlevel;
1272 Int r;
1273
1274 /* This is a kludge. Really we ought to back-convert saved_act
1275 into a toK_t using VG_(convert_sigaction_fromK_to_toK), but
1276 since that's a no-op on all ppc64 platforms so far supported,
1277 it's not worth the typing effort. At least include most basic
1278 sanity check: */
1279 vg_assert(sizeof(vki_sigaction_fromK_t) == sizeof(vki_sigaction_toK_t));
1280
1281 VG_(sigemptyset)(&tmp_set);
1282 VG_(sigaddset)(&tmp_set, VKI_SIGILL);
1283 VG_(sigaddset)(&tmp_set, VKI_SIGFPE);
1284
1285 r = VG_(sigprocmask)(VKI_SIG_UNBLOCK, &tmp_set, &saved_set);
1286 vg_assert(r == 0);
1287
1288 r = VG_(sigaction)(VKI_SIGILL, NULL, &saved_sigill_act);
1289 vg_assert(r == 0);
1290 tmp_sigill_act = saved_sigill_act;
1291
1292 VG_(sigaction)(VKI_SIGFPE, NULL, &saved_sigfpe_act);
1293 tmp_sigfpe_act = saved_sigfpe_act;
1294
1295 /* NODEFER: signal handler does not return (from the kernel's point of
1296 view), hence if it is to successfully catch a signal more than once,
1297 we need the NODEFER flag. */
1298 tmp_sigill_act.sa_flags &= ~VKI_SA_RESETHAND;
1299 tmp_sigill_act.sa_flags &= ~VKI_SA_SIGINFO;
1300 tmp_sigill_act.sa_flags |= VKI_SA_NODEFER;
1301 tmp_sigill_act.ksa_handler = handler_unsup_insn;
1302 VG_(sigaction)(VKI_SIGILL, &tmp_sigill_act, NULL);
1303
1304 tmp_sigfpe_act.sa_flags &= ~VKI_SA_RESETHAND;
1305 tmp_sigfpe_act.sa_flags &= ~VKI_SA_SIGINFO;
1306 tmp_sigfpe_act.sa_flags |= VKI_SA_NODEFER;
1307 tmp_sigfpe_act.ksa_handler = handler_unsup_insn;
1308 VG_(sigaction)(VKI_SIGFPE, &tmp_sigfpe_act, NULL);
1309
1310 /* VFP insns */
1311 have_VFP = True;
sewardj6c591e12011-04-11 16:17:51 +00001312 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardj1dbd3372010-08-22 12:21:14 +00001313 have_VFP = False;
1314 } else {
1315 __asm__ __volatile__(".word 0xEEB02B42"); /* VMOV.F64 d2, d2 */
1316 }
1317 /* There are several generation of VFP extension but they differs very
1318 little so for now we will not distinguish them. */
1319 have_VFP2 = have_VFP;
1320 have_VFP3 = have_VFP;
1321
1322 /* NEON insns */
1323 have_NEON = True;
sewardj6c591e12011-04-11 16:17:51 +00001324 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardj1dbd3372010-08-22 12:21:14 +00001325 have_NEON = False;
1326 } else {
1327 __asm__ __volatile__(".word 0xF2244154"); /* VMOV q2, q2 */
1328 }
1329
1330 /* ARM architecture level */
1331 archlevel = 5; /* v5 will be base level */
1332 if (archlevel < 7) {
1333 archlevel = 7;
sewardj6c591e12011-04-11 16:17:51 +00001334 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardj1dbd3372010-08-22 12:21:14 +00001335 archlevel = 5;
1336 } else {
1337 __asm__ __volatile__(".word 0xF45FF000"); /* PLI [PC,#-0] */
1338 }
1339 }
1340 if (archlevel < 6) {
1341 archlevel = 6;
sewardj6c591e12011-04-11 16:17:51 +00001342 if (VG_MINIMAL_SETJMP(env_unsup_insn)) {
sewardj1dbd3372010-08-22 12:21:14 +00001343 archlevel = 5;
1344 } else {
1345 __asm__ __volatile__(".word 0xE6822012"); /* PKHBT r2, r2, r2 */
1346 }
1347 }
1348
1349 VG_(convert_sigaction_fromK_to_toK)(&saved_sigill_act, &tmp_sigill_act);
1350 VG_(convert_sigaction_fromK_to_toK)(&saved_sigfpe_act, &tmp_sigfpe_act);
1351 VG_(sigaction)(VKI_SIGILL, &tmp_sigill_act, NULL);
1352 VG_(sigaction)(VKI_SIGFPE, &tmp_sigfpe_act, NULL);
1353 VG_(sigprocmask)(VKI_SIG_SETMASK, &saved_set, NULL);
1354
1355 VG_(debugLog)(1, "machine", "ARMv%d VFP %d VFP2 %d VFP3 %d NEON %d\n",
1356 archlevel, (Int)have_VFP, (Int)have_VFP2, (Int)have_VFP3,
1357 (Int)have_NEON);
1358
1359 VG_(machine_arm_archlevel) = archlevel;
1360
sewardj59570ff2010-01-01 11:59:33 +00001361 va = VexArchARM;
sewardj1dbd3372010-08-22 12:21:14 +00001362
1363 vai.hwcaps = VEX_ARM_ARCHLEVEL(archlevel);
1364 if (have_VFP3) vai.hwcaps |= VEX_HWCAPS_ARM_VFP3;
1365 if (have_VFP2) vai.hwcaps |= VEX_HWCAPS_ARM_VFP2;
1366 if (have_VFP) vai.hwcaps |= VEX_HWCAPS_ARM_VFP;
1367 if (have_NEON) vai.hwcaps |= VEX_HWCAPS_ARM_NEON;
1368
florian78627012012-10-07 19:47:04 +00001369 VG_(machine_get_cache_info)(&vai);
1370
sewardj59570ff2010-01-01 11:59:33 +00001371 return True;
1372 }
1373
sewardj5db15402012-06-07 09:13:21 +00001374#elif defined(VGA_mips32)
1375 {
1376 va = VexArchMIPS32;
1377 UInt model = VG_(get_machine_model)();
1378 if (model== -1)
1379 return False;
1380
1381 vai.hwcaps = model;
florian78627012012-10-07 19:47:04 +00001382
1383 VG_(machine_get_cache_info)(&vai);
1384
sewardj5db15402012-06-07 09:13:21 +00001385 return True;
1386 }
1387
sewardje2d1e672005-11-12 23:10:48 +00001388#else
1389# error "Unknown arch"
1390#endif
1391}
1392
sewardj2c48c7b2005-11-29 13:05:56 +00001393/* Notify host cpu cache line size. */
sewardje3826cf2005-11-13 00:30:22 +00001394#if defined(VGA_ppc32)
1395void VG_(machine_ppc32_set_clszB)( Int szB )
1396{
1397 vg_assert(hwcaps_done);
1398
1399 /* Either the value must not have been set yet (zero) or we can
1400 tolerate it being set to the same value multiple times, as the
1401 stack scanning logic in m_main is a bit stupid. */
cerion1f0d8142005-12-23 00:57:03 +00001402 vg_assert(vai.ppc_cache_line_szB == 0
1403 || vai.ppc_cache_line_szB == szB);
sewardje3826cf2005-11-13 00:30:22 +00001404
sewardj89230ca2008-05-29 16:39:57 +00001405 vg_assert(szB == 32 || szB == 64 || szB == 128);
cerion1f0d8142005-12-23 00:57:03 +00001406 vai.ppc_cache_line_szB = szB;
sewardje3826cf2005-11-13 00:30:22 +00001407}
1408#endif
1409
sewardje2d1e672005-11-12 23:10:48 +00001410
sewardj2c48c7b2005-11-29 13:05:56 +00001411/* Notify host cpu cache line size. */
1412#if defined(VGA_ppc64)
1413void VG_(machine_ppc64_set_clszB)( Int szB )
1414{
1415 vg_assert(hwcaps_done);
1416
1417 /* Either the value must not have been set yet (zero) or we can
1418 tolerate it being set to the same value multiple times, as the
1419 stack scanning logic in m_main is a bit stupid. */
cerion1f0d8142005-12-23 00:57:03 +00001420 vg_assert(vai.ppc_cache_line_szB == 0
1421 || vai.ppc_cache_line_szB == szB);
sewardj2c48c7b2005-11-29 13:05:56 +00001422
sewardj89230ca2008-05-29 16:39:57 +00001423 vg_assert(szB == 32 || szB == 64 || szB == 128);
cerion1f0d8142005-12-23 00:57:03 +00001424 vai.ppc_cache_line_szB = szB;
sewardj2c48c7b2005-11-29 13:05:56 +00001425}
1426#endif
1427
1428
sewardja3551be2010-09-09 07:25:58 +00001429/* Notify host's ability to handle NEON instructions. */
1430#if defined(VGA_arm)
1431void VG_(machine_arm_set_has_NEON)( Bool has_neon )
1432{
1433 vg_assert(hwcaps_done);
1434 /* There's nothing else we can sanity check. */
1435
1436 if (has_neon) {
1437 vai.hwcaps |= VEX_HWCAPS_ARM_NEON;
1438 } else {
1439 vai.hwcaps &= ~VEX_HWCAPS_ARM_NEON;
1440 }
1441}
1442#endif
1443
1444
sewardje2d1e672005-11-12 23:10:48 +00001445/* Fetch host cpu info, once established. */
1446void VG_(machine_get_VexArchInfo)( /*OUT*/VexArch* pVa,
1447 /*OUT*/VexArchInfo* pVai )
1448{
1449 vg_assert(hwcaps_done);
sewardje3826cf2005-11-13 00:30:22 +00001450 if (pVa) *pVa = va;
1451 if (pVai) *pVai = vai;
sewardje2d1e672005-11-12 23:10:48 +00001452}
sewardj7821e2e2005-08-08 00:35:46 +00001453
1454
sewardj98763d52012-06-03 22:40:07 +00001455/* Returns the size of the largest guest register that we will
1456 simulate in this run. This depends on both the guest architecture
1457 and on the specific capabilities we are simulating for that guest
1458 (eg, AVX or non-AVX ?, for amd64). Should return either 4, 8, 16
1459 or 32. General rule: if in doubt, return a value larger than
1460 reality.
1461
1462 This information is needed by Cachegrind and Callgrind to decide
1463 what the minimum cache line size they are prepared to simulate is.
1464 Basically require that the minimum cache line size is at least as
1465 large as the largest register that might get transferred to/from
1466 memory, so as to guarantee that any such transaction can straddle
1467 at most 2 cache lines.
1468*/
1469Int VG_(machine_get_size_of_largest_guest_register) ( void )
1470{
1471 vg_assert(hwcaps_done);
1472 /* Once hwcaps_done is True, we can fish around inside va/vai to
1473 find the information we need. */
1474
1475# if defined(VGA_x86)
1476 vg_assert(va == VexArchX86);
1477 /* We don't support AVX, so 32 is out. At the other end, even if
1478 we don't support any SSE, the X87 can generate 10 byte
1479 transfers, so let's say 16 to be on the safe side. Hence the
1480 answer is always 16. */
1481 return 16;
1482
1483# elif defined(VGA_amd64)
1484 /* if AVX then 32 else 16 */
1485 return (vai.hwcaps & VEX_HWCAPS_AMD64_AVX) ? 32 : 16;
1486
1487# elif defined(VGA_ppc32)
1488 /* 8 if boring; 16 if signs of Altivec or other exotic stuff */
1489 if (vai.hwcaps & VEX_HWCAPS_PPC32_V) return 16;
1490 if (vai.hwcaps & VEX_HWCAPS_PPC32_VX) return 16;
1491 if (vai.hwcaps & VEX_HWCAPS_PPC32_DFP) return 16;
1492 return 8;
1493
1494# elif defined(VGA_ppc64)
1495 /* 8 if boring; 16 if signs of Altivec or other exotic stuff */
1496 if (vai.hwcaps & VEX_HWCAPS_PPC64_V) return 16;
1497 if (vai.hwcaps & VEX_HWCAPS_PPC64_VX) return 16;
1498 if (vai.hwcaps & VEX_HWCAPS_PPC64_DFP) return 16;
1499 return 8;
1500
1501# elif defined(VGA_s390x)
1502 return 8;
1503
1504# elif defined(VGA_arm)
1505 /* Really it depends whether or not we have NEON, but let's just
1506 assume we always do. */
1507 return 16;
1508
sewardj5db15402012-06-07 09:13:21 +00001509# elif defined(VGA_mips32)
1510 /* The guest state implies 4, but that can't really be true, can
1511 it? */
1512 return 8;
1513
sewardj98763d52012-06-03 22:40:07 +00001514# else
1515# error "Unknown arch"
1516# endif
1517}
1518
1519
sewardj53ee1fc2005-12-23 02:29:58 +00001520// Given a pointer to a function as obtained by "& functionname" in C,
sewardjf1c91e02006-10-17 01:35:58 +00001521// produce a pointer to the actual entry point for the function.
sewardj53ee1fc2005-12-23 02:29:58 +00001522void* VG_(fnptr_to_fnentry)( void* f )
1523{
sewardj6e9de462011-06-28 07:25:29 +00001524# if defined(VGP_x86_linux) || defined(VGP_amd64_linux) \
1525 || defined(VGP_arm_linux) \
1526 || defined(VGP_ppc32_linux) || defined(VGO_darwin) \
sewardj5db15402012-06-07 09:13:21 +00001527 || defined(VGP_s390x_linux) || defined(VGP_mips32_linux)
sewardj53ee1fc2005-12-23 02:29:58 +00001528 return f;
sewardj6e9de462011-06-28 07:25:29 +00001529# elif defined(VGP_ppc64_linux)
1530 /* ppc64-linux uses the AIX scheme, in which f is a pointer to a
1531 3-word function descriptor, of which the first word is the entry
1532 address. */
sewardjf1c91e02006-10-17 01:35:58 +00001533 UWord* descr = (UWord*)f;
sewardj53ee1fc2005-12-23 02:29:58 +00001534 return (void*)(descr[0]);
sewardj6e9de462011-06-28 07:25:29 +00001535# else
1536# error "Unknown platform"
1537# endif
sewardj53ee1fc2005-12-23 02:29:58 +00001538}
1539
njnf536bbb2005-06-13 04:21:38 +00001540/*--------------------------------------------------------------------*/
1541/*--- end ---*/
1542/*--------------------------------------------------------------------*/