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