gdb/
[deliverable/binutils-gdb.git] / gdb / gdbserver / linux-s390-low.c
CommitLineData
265f716b
DJ
1/* GNU/Linux S/390 specific low level interface, for the remote server
2 for GDB.
7b6bb8da 3 Copyright (C) 2001, 2002, 2005, 2006, 2007, 2008, 2009, 2010, 2011
9b254dd1 4 Free Software Foundation, Inc.
265f716b
DJ
5
6 This file is part of GDB.
7
8 This program is free software; you can redistribute it and/or modify
9 it under the terms of the GNU General Public License as published by
a9762ec7 10 the Free Software Foundation; either version 3 of the License, or
265f716b
DJ
11 (at your option) any later version.
12
13 This program is distributed in the hope that it will be useful,
14 but WITHOUT ANY WARRANTY; without even the implied warranty of
15 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
16 GNU General Public License for more details.
17
18 You should have received a copy of the GNU General Public License
a9762ec7 19 along with this program. If not, see <http://www.gnu.org/licenses/>. */
265f716b
DJ
20
21/* This file is used for both 31-bit and 64-bit S/390 systems. */
22
23#include "server.h"
24#include "linux-low.h"
c642a434 25#include "elf/common.h"
265f716b
DJ
26
27#include <asm/ptrace.h>
c642a434
UW
28#include <sys/ptrace.h>
29#include <sys/uio.h>
7803799a 30#include <elf.h>
265f716b 31
7803799a
UW
32#ifndef HWCAP_S390_HIGH_GPRS
33#define HWCAP_S390_HIGH_GPRS 512
34#endif
d05b4ac3 35
c642a434
UW
36#ifndef PTRACE_GETREGSET
37#define PTRACE_GETREGSET 0x4204
38#endif
39
40#ifndef PTRACE_SETREGSET
41#define PTRACE_SETREGSET 0x4205
42#endif
43
7803799a
UW
44/* Defined in auto-generated file s390-linux32.c. */
45void init_registers_s390_linux32 (void);
c642a434
UW
46/* Defined in auto-generated file s390-linux32v1.c. */
47void init_registers_s390_linux32v1 (void);
48/* Defined in auto-generated file s390-linux32v2.c. */
49void init_registers_s390_linux32v2 (void);
7803799a
UW
50/* Defined in auto-generated file s390-linux64.c. */
51void init_registers_s390_linux64 (void);
c642a434
UW
52/* Defined in auto-generated file s390-linux64v1.c. */
53void init_registers_s390_linux64v1 (void);
54/* Defined in auto-generated file s390-linux64v2.c. */
55void init_registers_s390_linux64v2 (void);
7803799a
UW
56/* Defined in auto-generated file s390x-linux64.c. */
57void init_registers_s390x_linux64 (void);
c642a434
UW
58/* Defined in auto-generated file s390x-linux64v1.c. */
59void init_registers_s390x_linux64v1 (void);
60/* Defined in auto-generated file s390x-linux64v2.c. */
61void init_registers_s390x_linux64v2 (void);
d05b4ac3 62
c642a434 63#define s390_num_regs 52
265f716b 64
2ec06d2e 65static int s390_regmap[] = {
265f716b
DJ
66 PT_PSWMASK, PT_PSWADDR,
67
68 PT_GPR0, PT_GPR1, PT_GPR2, PT_GPR3,
69 PT_GPR4, PT_GPR5, PT_GPR6, PT_GPR7,
70 PT_GPR8, PT_GPR9, PT_GPR10, PT_GPR11,
71 PT_GPR12, PT_GPR13, PT_GPR14, PT_GPR15,
72
73 PT_ACR0, PT_ACR1, PT_ACR2, PT_ACR3,
74 PT_ACR4, PT_ACR5, PT_ACR6, PT_ACR7,
75 PT_ACR8, PT_ACR9, PT_ACR10, PT_ACR11,
76 PT_ACR12, PT_ACR13, PT_ACR14, PT_ACR15,
77
265f716b
DJ
78 PT_FPC,
79
d0f54f9d 80#ifndef __s390x__
265f716b
DJ
81 PT_FPR0_HI, PT_FPR1_HI, PT_FPR2_HI, PT_FPR3_HI,
82 PT_FPR4_HI, PT_FPR5_HI, PT_FPR6_HI, PT_FPR7_HI,
83 PT_FPR8_HI, PT_FPR9_HI, PT_FPR10_HI, PT_FPR11_HI,
84 PT_FPR12_HI, PT_FPR13_HI, PT_FPR14_HI, PT_FPR15_HI,
85#else
86 PT_FPR0, PT_FPR1, PT_FPR2, PT_FPR3,
87 PT_FPR4, PT_FPR5, PT_FPR6, PT_FPR7,
88 PT_FPR8, PT_FPR9, PT_FPR10, PT_FPR11,
89 PT_FPR12, PT_FPR13, PT_FPR14, PT_FPR15,
90#endif
c642a434
UW
91
92 PT_ORIGGPR2,
265f716b
DJ
93};
94
7803799a 95#ifdef __s390x__
c642a434 96#define s390_num_regs_3264 68
7803799a
UW
97
98static int s390_regmap_3264[] = {
99 PT_PSWMASK, PT_PSWADDR,
100
493e2a69
MS
101 PT_GPR0, PT_GPR0, PT_GPR1, PT_GPR1,
102 PT_GPR2, PT_GPR2, PT_GPR3, PT_GPR3,
103 PT_GPR4, PT_GPR4, PT_GPR5, PT_GPR5,
104 PT_GPR6, PT_GPR6, PT_GPR7, PT_GPR7,
105 PT_GPR8, PT_GPR8, PT_GPR9, PT_GPR9,
106 PT_GPR10, PT_GPR10, PT_GPR11, PT_GPR11,
107 PT_GPR12, PT_GPR12, PT_GPR13, PT_GPR13,
108 PT_GPR14, PT_GPR14, PT_GPR15, PT_GPR15,
7803799a
UW
109
110 PT_ACR0, PT_ACR1, PT_ACR2, PT_ACR3,
111 PT_ACR4, PT_ACR5, PT_ACR6, PT_ACR7,
112 PT_ACR8, PT_ACR9, PT_ACR10, PT_ACR11,
113 PT_ACR12, PT_ACR13, PT_ACR14, PT_ACR15,
114
115 PT_FPC,
116
117 PT_FPR0, PT_FPR1, PT_FPR2, PT_FPR3,
118 PT_FPR4, PT_FPR5, PT_FPR6, PT_FPR7,
119 PT_FPR8, PT_FPR9, PT_FPR10, PT_FPR11,
120 PT_FPR12, PT_FPR13, PT_FPR14, PT_FPR15,
c642a434
UW
121
122 PT_ORIGGPR2,
7803799a
UW
123};
124#endif
125
126
2ec06d2e
DJ
127static int
128s390_cannot_fetch_register (int regno)
265f716b 129{
265f716b
DJ
130 return 0;
131}
132
2ec06d2e
DJ
133static int
134s390_cannot_store_register (int regno)
265f716b 135{
265f716b
DJ
136 return 0;
137}
2ec06d2e 138
ee1a7ae4 139static void
442ea881 140s390_collect_ptrace_register (struct regcache *regcache, int regno, char *buf)
ee1a7ae4
UW
141{
142 int size = register_size (regno);
143 if (size < sizeof (long))
144 {
7803799a
UW
145 int regaddr = the_low_target.regmap[regno];
146
ee1a7ae4
UW
147 memset (buf, 0, sizeof (long));
148
7803799a
UW
149 if ((regno ^ 1) < the_low_target.num_regs
150 && the_low_target.regmap[regno ^ 1] == regaddr)
151 {
18f5de3b
JK
152 collect_register (regcache, regno & ~1, buf);
153 collect_register (regcache, (regno & ~1) + 1,
154 buf + sizeof (long) - size);
7803799a 155 }
d6db1fab
UW
156 else if (regaddr == PT_PSWMASK)
157 {
158 /* Convert 4-byte PSW mask to 8 bytes by clearing bit 12 and copying
159 the basic addressing mode bit from the PSW address. */
160 char *addr = alloca (register_size (regno ^ 1));
161 collect_register (regcache, regno, buf);
162 collect_register (regcache, regno ^ 1, addr);
163 buf[1] &= ~0x8;
164 buf[size] |= (addr[0] & 0x80);
165 }
166 else if (regaddr == PT_PSWADDR)
167 {
168 /* Convert 4-byte PSW address to 8 bytes by clearing the addressing
169 mode bit (which gets copied to the PSW mask instead). */
170 collect_register (regcache, regno, buf + sizeof (long) - size);
171 buf[sizeof (long) - size] &= ~0x80;
172 }
c642a434
UW
173 else if ((regaddr >= PT_GPR0 && regaddr <= PT_GPR15)
174 || regaddr == PT_ORIGGPR2)
442ea881 175 collect_register (regcache, regno, buf + sizeof (long) - size);
ee1a7ae4 176 else
442ea881 177 collect_register (regcache, regno, buf);
ee1a7ae4
UW
178 }
179 else
18f5de3b 180 collect_register (regcache, regno, buf);
ee1a7ae4
UW
181}
182
183static void
493e2a69
MS
184s390_supply_ptrace_register (struct regcache *regcache,
185 int regno, const char *buf)
ee1a7ae4
UW
186{
187 int size = register_size (regno);
188 if (size < sizeof (long))
189 {
7803799a
UW
190 int regaddr = the_low_target.regmap[regno];
191
192 if ((regno ^ 1) < the_low_target.num_regs
193 && the_low_target.regmap[regno ^ 1] == regaddr)
194 {
18f5de3b
JK
195 supply_register (regcache, regno & ~1, buf);
196 supply_register (regcache, (regno & ~1) + 1,
197 buf + sizeof (long) - size);
7803799a 198 }
d6db1fab
UW
199 else if (regaddr == PT_PSWMASK)
200 {
201 /* Convert 8-byte PSW mask to 4 bytes by setting bit 12 and copying
202 the basic addressing mode into the PSW address. */
203 char *mask = alloca (size);
204 char *addr = alloca (register_size (regno ^ 1));
205 memcpy (mask, buf, size);
206 mask[1] |= 0x8;
207 supply_register (regcache, regno, mask);
208
209 collect_register (regcache, regno ^ 1, addr);
210 addr[0] &= ~0x80;
211 addr[0] |= (buf[size] & 0x80);
212 supply_register (regcache, regno ^ 1, addr);
213 }
214 else if (regaddr == PT_PSWADDR)
215 {
216 /* Convert 8-byte PSW address to 4 bytes by truncating, but
217 keeping the addressing mode bit (which was set from the mask). */
218 char *addr = alloca (size);
219 char amode;
220 collect_register (regcache, regno, addr);
221 amode = addr[0] & 0x80;
222 memcpy (addr, buf + sizeof (long) - size, size);
223 addr[0] &= ~0x80;
224 addr[0] |= amode;
225 supply_register (regcache, regno, addr);
226 }
c642a434
UW
227 else if ((regaddr >= PT_GPR0 && regaddr <= PT_GPR15)
228 || regaddr == PT_ORIGGPR2)
442ea881 229 supply_register (regcache, regno, buf + sizeof (long) - size);
ee1a7ae4 230 else
442ea881 231 supply_register (regcache, regno, buf);
ee1a7ae4
UW
232 }
233 else
442ea881 234 supply_register (regcache, regno, buf);
ee1a7ae4
UW
235}
236
b7149293
UW
237/* Provide only a fill function for the general register set. ps_lgetregs
238 will use this for NPTL support. */
239
442ea881 240static void s390_fill_gregset (struct regcache *regcache, void *buf)
b7149293
UW
241{
242 int i;
243
7803799a
UW
244 for (i = 0; i < the_low_target.num_regs; i++)
245 {
246 if (the_low_target.regmap[i] < PT_PSWMASK
247 || the_low_target.regmap[i] > PT_ACR15)
248 continue;
249
442ea881 250 s390_collect_ptrace_register (regcache, i, (char *) buf
7803799a
UW
251 + the_low_target.regmap[i]);
252 }
b7149293
UW
253}
254
c642a434
UW
255/* Fill and store functions for extended register sets. */
256
257static void
258s390_fill_last_break (struct regcache *regcache, void *buf)
259{
260 /* Last break address is read-only. */
261}
262
263static void
264s390_store_last_break (struct regcache *regcache, const void *buf)
265{
266 supply_register_by_name (regcache, "last_break",
267 (const char *)buf + 8 - register_size (0));
268}
269
270static void
271s390_fill_system_call (struct regcache *regcache, void *buf)
272{
273 collect_register_by_name (regcache, "system_call", buf);
274}
275
276static void
277s390_store_system_call (struct regcache *regcache, const void *buf)
278{
279 supply_register_by_name (regcache, "system_call", buf);
280}
281
b7149293 282struct regset_info target_regsets[] = {
1570b33e 283 { 0, 0, 0, 0, GENERAL_REGS, s390_fill_gregset, NULL },
c642a434
UW
284 /* Last break address is read-only; do not attempt PTRACE_SETREGSET. */
285 { PTRACE_GETREGSET, PTRACE_GETREGSET, NT_S390_LAST_BREAK, 0,
286 EXTENDED_REGS, s390_fill_last_break, s390_store_last_break },
287 { PTRACE_GETREGSET, PTRACE_SETREGSET, NT_S390_SYSTEM_CALL, 0,
288 EXTENDED_REGS, s390_fill_system_call, s390_store_system_call },
1570b33e 289 { 0, 0, 0, -1, -1, NULL, NULL }
b7149293
UW
290};
291
b0ded00b 292
f450004a 293static const unsigned char s390_breakpoint[] = { 0, 1 };
b0ded00b
UW
294#define s390_breakpoint_len 2
295
296static CORE_ADDR
442ea881 297s390_get_pc (struct regcache *regcache)
b0ded00b 298{
d61ddec4
UW
299 if (register_size (0) == 4)
300 {
d6db1fab
UW
301 unsigned int pswa;
302 collect_register_by_name (regcache, "pswa", &pswa);
303 return pswa & 0x7fffffff;
d61ddec4
UW
304 }
305 else
306 {
307 unsigned long pc;
442ea881 308 collect_register_by_name (regcache, "pswa", &pc);
d61ddec4
UW
309 return pc;
310 }
b0ded00b
UW
311}
312
313static void
442ea881 314s390_set_pc (struct regcache *regcache, CORE_ADDR newpc)
b0ded00b 315{
d61ddec4
UW
316 if (register_size (0) == 4)
317 {
d6db1fab
UW
318 unsigned int pswa;
319 collect_register_by_name (regcache, "pswa", &pswa);
320 pswa = (pswa & 0x80000000) | (newpc & 0x7fffffff);
321 supply_register_by_name (regcache, "pswa", &pswa);
d61ddec4
UW
322 }
323 else
324 {
325 unsigned long pc = newpc;
442ea881 326 supply_register_by_name (regcache, "pswa", &pc);
d61ddec4 327 }
b0ded00b
UW
328}
329
7803799a
UW
330#ifdef __s390x__
331static unsigned long
332s390_get_hwcap (void)
333{
334 int wordsize = register_size (0);
335 unsigned char *data = alloca (2 * wordsize);
336 int offset = 0;
337
338 while ((*the_target->read_auxv) (offset, data, 2 * wordsize) == 2 * wordsize)
339 {
340 if (wordsize == 4)
341 {
342 unsigned int *data_p = (unsigned int *)data;
343 if (data_p[0] == AT_HWCAP)
344 return data_p[1];
345 }
346 else
347 {
348 unsigned long *data_p = (unsigned long *)data;
349 if (data_p[0] == AT_HWCAP)
350 return data_p[1];
351 }
352
353 offset += 2 * wordsize;
354 }
355
356 return 0;
357}
358#endif
d61ddec4 359
c642a434
UW
360static int
361s390_check_regset (int pid, int regset, int regsize)
362{
363 gdb_byte *buf = alloca (regsize);
364 struct iovec iov;
365
366 iov.iov_base = buf;
367 iov.iov_len = regsize;
368
369 if (ptrace (PTRACE_GETREGSET, pid, (long) regset, (long) &iov) < 0)
370 return 0;
371 else
372 return 1;
373}
374
d61ddec4
UW
375static void
376s390_arch_setup (void)
377{
c642a434
UW
378 struct regset_info *regset;
379
380 /* Check whether the kernel supports extra register sets. */
381 int pid = pid_of (get_thread_lwp (current_inferior));
382 int have_regset_last_break
383 = s390_check_regset (pid, NT_S390_LAST_BREAK, 8);
384 int have_regset_system_call
385 = s390_check_regset (pid, NT_S390_SYSTEM_CALL, 4);
386
387 /* Update target_regsets according to available register sets. */
388 for (regset = target_regsets; regset->fill_function != NULL; regset++)
389 if (regset->get_request == PTRACE_GETREGSET)
390 switch (regset->nt_type)
391 {
392 case NT_S390_LAST_BREAK:
393 regset->size = have_regset_last_break? 8 : 0;
394 break;
395 case NT_S390_SYSTEM_CALL:
396 regset->size = have_regset_system_call? 4 : 0;
397 break;
398 default:
399 break;
400 }
401
d61ddec4 402 /* Assume 31-bit inferior process. */
c642a434
UW
403 if (have_regset_system_call)
404 init_registers_s390_linux32v2 ();
405 else if (have_regset_last_break)
406 init_registers_s390_linux32v1 ();
407 else
408 init_registers_s390_linux32 ();
409
7803799a
UW
410 the_low_target.num_regs = s390_num_regs;
411 the_low_target.regmap = s390_regmap;
d61ddec4
UW
412
413 /* On a 64-bit host, check the low bit of the (31-bit) PSWM
414 -- if this is one, we actually have a 64-bit inferior. */
415#ifdef __s390x__
416 {
417 unsigned int pswm;
92b72907
UW
418 struct regcache *regcache = new_register_cache ();
419 fetch_inferior_registers (regcache, find_regno ("pswm"));
442ea881 420 collect_register_by_name (regcache, "pswm", &pswm);
92b72907
UW
421 free_register_cache (regcache);
422
d61ddec4 423 if (pswm & 1)
c642a434
UW
424 {
425 if (have_regset_system_call)
426 init_registers_s390x_linux64v2 ();
427 else if (have_regset_last_break)
428 init_registers_s390x_linux64v1 ();
429 else
430 init_registers_s390x_linux64 ();
431 }
7803799a
UW
432
433 /* For a 31-bit inferior, check whether the kernel supports
434 using the full 64-bit GPRs. */
435 else if (s390_get_hwcap () & HWCAP_S390_HIGH_GPRS)
436 {
c642a434
UW
437 if (have_regset_system_call)
438 init_registers_s390_linux64v2 ();
439 else if (have_regset_last_break)
440 init_registers_s390_linux64v1 ();
441 else
442 init_registers_s390_linux64 ();
443
7803799a
UW
444 the_low_target.num_regs = s390_num_regs_3264;
445 the_low_target.regmap = s390_regmap_3264;
446 }
d61ddec4
UW
447 }
448#endif
449}
450
451
b0ded00b
UW
452static int
453s390_breakpoint_at (CORE_ADDR pc)
454{
455 unsigned char c[s390_breakpoint_len];
456 read_inferior_memory (pc, c, s390_breakpoint_len);
457 return memcmp (c, s390_breakpoint, s390_breakpoint_len) == 0;
458}
459
460
2ec06d2e 461struct linux_target_ops the_low_target = {
d61ddec4 462 s390_arch_setup,
2ec06d2e
DJ
463 s390_num_regs,
464 s390_regmap,
465 s390_cannot_fetch_register,
466 s390_cannot_store_register,
b0ded00b
UW
467 s390_get_pc,
468 s390_set_pc,
469 s390_breakpoint,
470 s390_breakpoint_len,
471 NULL,
472 s390_breakpoint_len,
473 s390_breakpoint_at,
ee1a7ae4
UW
474 NULL,
475 NULL,
476 NULL,
477 NULL,
478 s390_collect_ptrace_register,
479 s390_supply_ptrace_register,
2ec06d2e 480};
This page took 0.704742 seconds and 4 git commands to generate.