GNU Binutils with patches for OS216
Revision | 3626824cea3dd1dc27f0d121c283dde67d8ef56c (tree) |
---|---|
Zeit | 2017-03-17 01:01:49 |
Autor | Philipp Rudo <prudo@linu...> |
Commiter | Andreas Arnez |
Add S390 support for linux-kernel target
After implementing the new linux-kernel target and preparing s390-tdep.
It is now time to get everything to work. Thus implement the hooks
required by the linux-kernel target and enable s390's privileged
registers.
gdb/ChangeLog:
* s390-lk-tdep.h: New file.
* s390-lk-tdep.c: New file.
* Makefile.in (ALL_TARGET_OBS): Add s390-lk-tdep.o.
(HFILES_NO_SRCDIR): Add s390-lk-tdep.h.
(ALLDEPFILES): Add s390-lk-tdep.c.
* configure.tgt (s390*-*-linux*): Add s390-lk-tdep.o.
* s390-tdep.h: Define macros for address translation.
* s390-tdep.c (s390-lk-tdep.h): New include.
(s390_iterate_over_regset_sections): Enable privileged registers.
(s390_core_read_description): Enable privileged registers.
(s390_gdbarch_init): : Enable privileged registers and adjust.
@@ -863,6 +863,7 @@ ALL_TARGET_OBS = \ | ||
863 | 863 | rs6000-tdep.o \ |
864 | 864 | rx-tdep.o \ |
865 | 865 | s390-linux-tdep.o \ |
866 | + s390-lk-tdep.o \ | |
866 | 867 | s390-tdep.o \ |
867 | 868 | score-tdep.o \ |
868 | 869 | sh-linux-tdep.o \ |
@@ -1421,6 +1422,7 @@ HFILES_NO_SRCDIR = \ | ||
1421 | 1422 | rs6000-aix-tdep.h \ |
1422 | 1423 | rs6000-tdep.h \ |
1423 | 1424 | s390-linux-tdep.h \ |
1425 | + s390-lk-tdep.h \ | |
1424 | 1426 | s390-tdep.h \ |
1425 | 1427 | score-tdep.h \ |
1426 | 1428 | selftest-arch.h \ |
@@ -2620,6 +2622,7 @@ ALLDEPFILES = \ | ||
2620 | 2622 | rx-tdep.c \ |
2621 | 2623 | s390-linux-nat.c \ |
2622 | 2624 | s390-linux-tdep.c \ |
2625 | + s390-lk-tdep.c \ | |
2623 | 2626 | s390-tdep.c \ |
2624 | 2627 | score-tdep.c \ |
2625 | 2628 | ser-go32.c \ |
@@ -482,8 +482,9 @@ powerpc*-*-*) | ||
482 | 482 | |
483 | 483 | s390*-*-linux*) |
484 | 484 | # Target: S390 running Linux |
485 | - gdb_target_obs="s390-tdep.o s390-linux-tdep.o solib-svr4.o \ | |
486 | - linux-tdep.o linux-record.o ${lk_target_obs}" | |
485 | + gdb_target_obs="s390-tdep.o s390-linux-tdep.o s390-lk-tdep.o \ | |
486 | + solib-svr4.o linux-tdep.o linux-record.o \ | |
487 | + ${lk_target_obs}" | |
487 | 488 | build_gdbserver=yes |
488 | 489 | ;; |
489 | 490 |
@@ -0,0 +1,390 @@ | ||
1 | +/* Target-dependent code for linux-kernel target on S390. | |
2 | + Copyright (C) 2017 Free Software Foundation, Inc. | |
3 | + | |
4 | + This file is part of GDB. | |
5 | + | |
6 | + This program is free software; you can redistribute it and/or modify | |
7 | + it under the terms of the GNU General Public License as published by | |
8 | + the Free Software Foundation; either version 3 of the License, or | |
9 | + (at your option) any later version. | |
10 | + | |
11 | + This program is distributed in the hope that it will be useful, | |
12 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | + GNU General Public License for more details. | |
15 | + | |
16 | + You should have received a copy of the GNU General Public License | |
17 | + along with this program. If not, see <http://www.gnu.org/licenses/>. */ | |
18 | + | |
19 | +#include "defs.h" | |
20 | + | |
21 | +#include "gdbarch.h" | |
22 | +#include "gdbcore.h" | |
23 | +#include "gdbthread.h" | |
24 | +#include "lk-low.h" | |
25 | +#include "osabi.h" | |
26 | +#include "regcache.h" | |
27 | +#include "regset.h" | |
28 | +#include "s390-tdep.h" | |
29 | +#include "s390-lk-tdep.h" | |
30 | + | |
31 | +#include "features/s390x-cr-linux64.c" | |
32 | +#include "features/s390x-vxcr-linux64.c" | |
33 | + | |
34 | +/* Register maps and sets. */ | |
35 | + | |
36 | +static const struct regcache_map_entry s390x_gregmap_lk[] = | |
37 | + { | |
38 | + { 10, S390_R6_REGNUM }, /* r0-r5 volatile */ | |
39 | + { -2, REGCACHE_MAP_SKIP, 8 }, | |
40 | + { 1, S390_PSWA_REGNUM }, /* Use r14 for PSWA. */ | |
41 | + { 0 } | |
42 | + }; | |
43 | + | |
44 | +static const struct regcache_map_entry s390x_regmap_cr [] = | |
45 | + { | |
46 | + { 16, S390_CR0_REGNUM, 8 }, | |
47 | + { 0 } | |
48 | + }; | |
49 | + | |
50 | +static const struct regcache_map_entry s390x_regmap_timer [] = | |
51 | + { | |
52 | + { 1, S390_TIMER_REGNUM, 8 }, | |
53 | + { 0 } | |
54 | + }; | |
55 | + | |
56 | +static const struct regcache_map_entry s390x_regmap_todcmp [] = | |
57 | + { | |
58 | + { 1, S390_TODCMP_REGNUM, 8 }, | |
59 | + { 0 } | |
60 | + }; | |
61 | + | |
62 | +static const struct regcache_map_entry s390x_regmap_todpreg [] = | |
63 | + { | |
64 | + { 1, S390_TODPREG_REGNUM, 4 }, | |
65 | + { 0 } | |
66 | + }; | |
67 | + | |
68 | +static const struct regcache_map_entry s390x_regmap_prefix [] = | |
69 | + { | |
70 | + { 1, S390_PREFIX_REGNUM, 4 }, | |
71 | + { 0 } | |
72 | + }; | |
73 | + | |
74 | +const struct regset s390x_gregset_lk = { | |
75 | + s390x_gregmap_lk, | |
76 | + regcache_supply_regset, | |
77 | + regcache_collect_regset | |
78 | +}; | |
79 | + | |
80 | +const struct regset s390x_cr_regset = { | |
81 | + s390x_regmap_cr, | |
82 | + regcache_supply_regset, | |
83 | + regcache_collect_regset | |
84 | +}; | |
85 | + | |
86 | +const struct regset s390x_timer_regset = { | |
87 | + s390x_regmap_timer, | |
88 | + regcache_supply_regset, | |
89 | + regcache_collect_regset | |
90 | +}; | |
91 | + | |
92 | +const struct regset s390x_todcmp_regset = { | |
93 | + s390x_regmap_todcmp, | |
94 | + regcache_supply_regset, | |
95 | + regcache_collect_regset | |
96 | +}; | |
97 | + | |
98 | +const struct regset s390x_todpreg_regset = { | |
99 | + s390x_regmap_todpreg, | |
100 | + regcache_supply_regset, | |
101 | + regcache_collect_regset | |
102 | +}; | |
103 | + | |
104 | +const struct regset s390x_prefix_regset = { | |
105 | + s390x_regmap_prefix, | |
106 | + regcache_supply_regset, | |
107 | + regcache_collect_regset | |
108 | +}; | |
109 | + | |
110 | +/* Function for Linux kernel target get_registers hook. Supplies gprs for | |
111 | + task TASK to REGCACHE. Uses r14 (back jump address) as current pswa. */ | |
112 | + | |
113 | +void | |
114 | +s390_lk_get_registers (CORE_ADDR task, struct target_ops *target, | |
115 | + struct regcache *regcache, int regnum) | |
116 | +{ | |
117 | + const struct regset *regset; | |
118 | + CORE_ADDR ksp, gprs, pswa; | |
119 | + gdb_byte buf[80]; /* 80 = 10 (#registers saved) * 8 (64 bit width) */ | |
120 | + size_t size; | |
121 | + | |
122 | + regset = &s390x_gregset_lk; | |
123 | + | |
124 | + ksp = lk_read_addr (task + LK_OFFSET (task_struct, thread) | |
125 | + + LK_OFFSET (thread_struct, ksp)); | |
126 | + gprs = ksp + LK_OFFSET (stack_frame, gprs); | |
127 | + size = FIELD_SIZE (LK_FIELD (stack_frame, gprs)); | |
128 | + gdb_assert (size <= sizeof (buf)); | |
129 | + | |
130 | + read_memory (gprs, buf, size); | |
131 | + regset->supply_regset (regset, regcache, -1, buf, size); | |
132 | +} | |
133 | + | |
134 | +/* Function for Linux kernel target get_percpu_offset hook. Returns the | |
135 | + percpu_offset from lowcore for cpu CPU. */ | |
136 | + | |
137 | +CORE_ADDR | |
138 | +s390_lk_get_percpu_offset (unsigned int cpu) | |
139 | +{ | |
140 | + CORE_ADDR lowcore_ptr, lowcore; | |
141 | + size_t ptr_len = lk_builtin_type_size (unsigned_long); | |
142 | + | |
143 | + lowcore_ptr = LK_ADDR (lowcore_ptr) + (ptr_len * cpu); | |
144 | + lowcore = lk_read_addr (lowcore_ptr); | |
145 | + | |
146 | + return lk_read_addr (lowcore + LK_OFFSET (lowcore, percpu_offset)); | |
147 | +} | |
148 | + | |
149 | +/* Function for Linux kernel target map_running_task_to_cpu hook. */ | |
150 | + | |
151 | +unsigned int | |
152 | +s390_lk_map_running_task_to_cpu (struct thread_info *ti) | |
153 | +{ | |
154 | + struct regcache *regcache; | |
155 | + enum register_status reg_status; | |
156 | + CORE_ADDR lowcore; | |
157 | + unsigned int cpu; | |
158 | + | |
159 | + regcache = get_thread_regcache (ti->ptid); | |
160 | + reg_status = regcache_raw_read_unsigned (regcache, S390_PREFIX_REGNUM, | |
161 | + (ULONGEST *) &lowcore); | |
162 | + if (reg_status != REG_VALID) | |
163 | + error (_("Could not find prefix register for thread with pid %d, lwp %li."), | |
164 | + ti->ptid.pid, ti->ptid.lwp); | |
165 | + | |
166 | + cpu = lk_read_uint (lowcore + LK_OFFSET (lowcore, cpu_nr)); | |
167 | + | |
168 | + return cpu; | |
169 | +} | |
170 | + | |
171 | +/* Function for Linux kernel target is_kvaddr hook. */ | |
172 | + | |
173 | +int | |
174 | +s390_lk_is_kvaddr (CORE_ADDR addr) | |
175 | +{ | |
176 | + return addr >= LK_ADDR (high_memory); | |
177 | +} | |
178 | + | |
179 | +/* Read table entry from TABLE at offset OFFSET. Helper for s390_lk_vtop. */ | |
180 | + | |
181 | +static inline ULONGEST | |
182 | +s390_lk_read_table_entry (CORE_ADDR table, ULONGEST offset) | |
183 | +{ | |
184 | + return lk_read_ulong (table + offset * lk_builtin_type_size (unsigned_long)); | |
185 | +} | |
186 | + | |
187 | +/* Function for Linux kernel target vtop hook. Assume 64 bit addresses. */ | |
188 | + | |
189 | +CORE_ADDR | |
190 | +s390_lk_vtop (CORE_ADDR table, CORE_ADDR vaddr) | |
191 | +{ | |
192 | + ULONGEST entry, offset; | |
193 | + CORE_ADDR paddr; | |
194 | + unsigned int table_type; | |
195 | + size_t addr_size = lk_builtin_type_size (unsigned_long); | |
196 | + | |
197 | + /* Read first entry in table to get its type. As the Table-Type bits are | |
198 | + the same in every table assume Region1-Table. */ | |
199 | + entry = s390_lk_read_table_entry (table, 0); | |
200 | + table_type = (entry & S390_LK_RFTE_TT) >> 2; | |
201 | + | |
202 | + switch (table_type) | |
203 | + { | |
204 | + case S390_LK_DAT_TT_REGION1: | |
205 | + { | |
206 | + offset = (vaddr & S390_LK_VADDR_RFX) >> 53; | |
207 | + entry = s390_lk_read_table_entry (table, offset); | |
208 | + | |
209 | + /* Do sanity checks. */ | |
210 | + if (!entry) | |
211 | + warning (_("Trying to translate address 0x%s with empty "\ | |
212 | + "region-first-table entry."), | |
213 | + phex (vaddr, addr_size)); | |
214 | + else if ((entry & S390_LK_RFTE_TT) >> 2 != S390_LK_DAT_TT_REGION1) | |
215 | + warning (_("Trying to translate address 0x%s with corrupt "\ | |
216 | + "table type in region-first-table entry."), | |
217 | + phex (vaddr, addr_size)); | |
218 | + else if (entry & S390_LK_RFTE_I) | |
219 | + warning (_("Translating address 0x%s with invalid bit set at "\ | |
220 | + "region-first-table entry."), | |
221 | + phex (vaddr, addr_size)); | |
222 | + | |
223 | + table = entry & S390_LK_RFTE_O; | |
224 | + } | |
225 | + /* fall through */ | |
226 | + case S390_LK_DAT_TT_REGION2: | |
227 | + { | |
228 | + offset = (vaddr & S390_LK_VADDR_RSX) >> 42; | |
229 | + entry = s390_lk_read_table_entry (table, offset); | |
230 | + | |
231 | + /* Do sanity checks. */ | |
232 | + if (!entry) | |
233 | + warning (_("Trying to translate address 0x%s with empty "\ | |
234 | + "region-second-table entry."), | |
235 | + phex (vaddr, addr_size)); | |
236 | + else if ((entry & S390_LK_RSTE_TT) >> 2 != S390_LK_DAT_TT_REGION2) | |
237 | + warning (_("Trying to translate address 0x%s with corrupt "\ | |
238 | + "table type in region-second-table entry."), | |
239 | + phex (vaddr, addr_size)); | |
240 | + else if (entry & S390_LK_RSTE_I) | |
241 | + warning (_("Translating address 0x%s with invalid bit set at "\ | |
242 | + "region-second-table entry."), | |
243 | + phex (vaddr, addr_size)); | |
244 | + | |
245 | + table = entry & S390_LK_RSTE_O; | |
246 | + } | |
247 | + /* fall through */ | |
248 | + case S390_LK_DAT_TT_REGION3: | |
249 | + { | |
250 | + offset = (vaddr & S390_LK_VADDR_RTX) >> 31; | |
251 | + entry = s390_lk_read_table_entry (table, offset); | |
252 | + | |
253 | + /* Do sanity checks. */ | |
254 | + if (!entry) | |
255 | + warning (_("Trying to translate address 0x%s with empty "\ | |
256 | + "region-third-table entry."), | |
257 | + phex (vaddr, addr_size)); | |
258 | + else if ((entry & S390_LK_RTTE_TT) >> 2 != S390_LK_DAT_TT_REGION3) | |
259 | + warning (_("Trying to translate address 0x%s with corrupt "\ | |
260 | + "table type in region-third-table entry."), | |
261 | + phex (vaddr, addr_size)); | |
262 | + else if (entry & S390_LK_RTTE_I) | |
263 | + warning (_("Translating address 0x%s with invalid bit set at "\ | |
264 | + "region-third-table entry."), | |
265 | + phex (vaddr, addr_size)); | |
266 | + | |
267 | + /* Check for huge page. */ | |
268 | + if (entry & S390_LK_RTTE_FC) | |
269 | + { | |
270 | + paddr = ((entry & S390_LK_RTTE_RFAA) | |
271 | + + (vaddr & ~S390_LK_RTTE_RFAA)); | |
272 | + return paddr; | |
273 | + } | |
274 | + | |
275 | + table = entry & S390_LK_RTTE_O; | |
276 | + } | |
277 | + /* fall through */ | |
278 | + case S390_LK_DAT_TT_SEGMENT: | |
279 | + { | |
280 | + offset = (vaddr & S390_LK_VADDR_SX) >> 20; | |
281 | + entry = s390_lk_read_table_entry (table, offset); | |
282 | + | |
283 | + /* Do sanity checks. */ | |
284 | + if (!entry) | |
285 | + warning (_("Trying to translate address 0x%s with empty "\ | |
286 | + "segment-table entry."), | |
287 | + phex (vaddr, addr_size)); | |
288 | + else if ((entry & S390_LK_STE_TT) >> 2 != S390_LK_DAT_TT_SEGMENT) | |
289 | + warning (_("Trying to translate address 0x%s with corrupt "\ | |
290 | + "table type in segment-table entry."), | |
291 | + phex (vaddr, addr_size)); | |
292 | + else if (entry & S390_LK_STE_I) | |
293 | + warning (_("Translating address 0x%s with invalid bit set at "\ | |
294 | + "segment-table entry."), | |
295 | + phex (vaddr, addr_size)); | |
296 | + | |
297 | + /* Check for large page. */ | |
298 | + if (entry & S390_LK_STE_FC) | |
299 | + { | |
300 | + paddr = ((entry & S390_LK_STE_SFAA) | |
301 | + + (vaddr & ~S390_LK_STE_SFAA)); | |
302 | + return paddr; | |
303 | + } | |
304 | + | |
305 | + table = entry & S390_LK_STE_O; | |
306 | + break; | |
307 | + } | |
308 | + } /* switch (table_type) */ | |
309 | + | |
310 | + offset = (vaddr & S390_LK_VADDR_PX) >> 12; | |
311 | + entry = s390_lk_read_table_entry (table, offset); | |
312 | + | |
313 | + /* Do sanity checks. */ | |
314 | + if (!entry) | |
315 | + warning (_("Trying to translate address 0x%s with empty page-table "\ | |
316 | + "entry."), | |
317 | + phex (vaddr, addr_size)); | |
318 | + else if (entry & S390_LK_PTE_I) | |
319 | + warning (_("Translating address 0x%s with invalid bit set at page-table "\ | |
320 | + "entry."), | |
321 | + phex (vaddr, addr_size)); | |
322 | + | |
323 | + paddr = ((entry & S390_LK_PTE_PFAA) + (vaddr & ~S390_LK_PTE_PFAA)); | |
324 | + | |
325 | + return paddr; | |
326 | +} | |
327 | + | |
328 | +/* Function for Linux kernel target get_module_text_offset hook. */ | |
329 | + | |
330 | +CORE_ADDR | |
331 | +s390_lk_get_module_text_offset (CORE_ADDR mod) | |
332 | +{ | |
333 | + CORE_ADDR offset, mod_arch; | |
334 | + | |
335 | + mod_arch = mod + LK_OFFSET (module, arch); | |
336 | + offset = lk_read_ulong (mod_arch + LK_OFFSET (mod_arch_specific, got_size)); | |
337 | + offset += lk_read_ulong (mod_arch + LK_OFFSET (mod_arch_specific, plt_size)); | |
338 | + | |
339 | + return offset; | |
340 | +} | |
341 | + | |
342 | +/* Initialize s390 dependent private data for linux kernel target. */ | |
343 | + | |
344 | +static void | |
345 | +s390_lk_init_private (struct gdbarch *gdbarch) | |
346 | +{ | |
347 | + LK_DECLARE_FIELD (stack_frame, gprs); | |
348 | + | |
349 | + LK_DECLARE_FIELD (thread_struct, ksp); | |
350 | + | |
351 | + LK_DECLARE_STRUCT_ALIAS (_lowcore, lowcore); /* linux -4.4 */ | |
352 | + LK_DECLARE_STRUCT_ALIAS (lowcore, lowcore); /* linux 4.5+ */ | |
353 | + if (LK_STRUCT (lowcore) == NULL) | |
354 | + error (_("Could not find struct lowcore. Aborting.")); | |
355 | + LK_DECLARE_FIELD (lowcore, percpu_offset); | |
356 | + LK_DECLARE_FIELD (lowcore, current_pid); | |
357 | + LK_DECLARE_FIELD (lowcore, cpu_nr); | |
358 | + | |
359 | + LK_DECLARE_FIELD (mod_arch_specific, got_size); | |
360 | + LK_DECLARE_FIELD (mod_arch_specific, plt_size); | |
361 | + | |
362 | + LK_DECLARE_ADDR (lowcore_ptr); | |
363 | + LK_DECLARE_ADDR (high_memory); | |
364 | + | |
365 | + LK_HOOK->get_registers = s390_lk_get_registers; | |
366 | + LK_HOOK->is_kvaddr = s390_lk_is_kvaddr; | |
367 | + LK_HOOK->vtop = s390_lk_vtop; | |
368 | + LK_HOOK->get_percpu_offset = s390_lk_get_percpu_offset; | |
369 | + LK_HOOK->map_running_task_to_cpu = s390_lk_map_running_task_to_cpu; | |
370 | + LK_HOOK->get_module_text_offset = s390_lk_get_module_text_offset; | |
371 | +} | |
372 | + | |
373 | +/* Initialize Linux kernel specific gdbarch hooks. */ | |
374 | + | |
375 | +void | |
376 | +s390_gdbarch_lk_init (struct gdbarch_info info, struct gdbarch *gdbarch) | |
377 | +{ | |
378 | + /* Support linux kernel debugging. */ | |
379 | + set_gdbarch_lk_init_private (gdbarch, s390_lk_init_private); | |
380 | +} | |
381 | + | |
382 | +extern initialize_file_ftype _initialize_s390_lk_tdep; /* -Wmissing-prototypes */ | |
383 | + | |
384 | +void | |
385 | +_initialize_s390_lk_tdep (void) | |
386 | +{ | |
387 | + /* Initialize the Linux kernel target descriptions. */ | |
388 | + initialize_tdesc_s390x_cr_linux64 (); | |
389 | + initialize_tdesc_s390x_vxcr_linux64 (); | |
390 | +} |
@@ -0,0 +1,36 @@ | ||
1 | +/* Target-dependent code for linux-kernel target on S390. | |
2 | + Copyright (C) 2017 Free Software Foundation, Inc. | |
3 | + | |
4 | + This file is part of GDB. | |
5 | + | |
6 | + This program is free software; you can redistribute it and/or modify | |
7 | + it under the terms of the GNU General Public License as published by | |
8 | + the Free Software Foundation; either version 3 of the License, or | |
9 | + (at your option) any later version. | |
10 | + | |
11 | + This program is distributed in the hope that it will be useful, | |
12 | + but WITHOUT ANY WARRANTY; without even the implied warranty of | |
13 | + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
14 | + GNU General Public License for more details. | |
15 | + | |
16 | + You should have received a copy of the GNU General Public License | |
17 | + along with this program. If not, see <http://www.gnu.org/licenses/>. */ | |
18 | + | |
19 | +#ifndef S390_LK_TDEP_H | |
20 | +#define S390_LK_TDEP_H | |
21 | + | |
22 | +extern void s390_gdbarch_lk_init (struct gdbarch_info info, | |
23 | + struct gdbarch *gdbarch); | |
24 | + | |
25 | +/* Core file privileged register sets, defined in s390-lk-tdep.c. */ | |
26 | +extern const struct regset s390x_gregset_lk; | |
27 | +extern const struct regset s390x_cr_regset; | |
28 | +extern const struct regset s390x_timer_regset; | |
29 | +extern const struct regset s390x_todcmp_regset; | |
30 | +extern const struct regset s390x_todpreg_regset; | |
31 | +extern const struct regset s390x_prefix_regset; | |
32 | + | |
33 | +extern struct target_desc *tdesc_s390x_cr_linux64; | |
34 | +extern struct target_desc *tdesc_s390x_vxcr_linux64; | |
35 | + | |
36 | +#endif /* S390_LK_TDEP_H */ |
@@ -40,6 +40,7 @@ | ||
40 | 40 | #include "reggroups.h" |
41 | 41 | #include "regset.h" |
42 | 42 | #include "s390-linux-tdep.h" |
43 | +#include "s390-lk-tdep.h" | |
43 | 44 | #include "s390-tdep.h" |
44 | 45 | #include "target-descriptions.h" |
45 | 46 | #include "trad-frame.h" |
@@ -1032,7 +1033,7 @@ s390_core_read_description (struct gdbarch *gdbarch, | ||
1032 | 1033 | { |
1033 | 1034 | asection *section = bfd_get_section_by_name (abfd, ".reg"); |
1034 | 1035 | CORE_ADDR hwcap = 0; |
1035 | - int high_gprs, v1, v2, te, vx; | |
1036 | + int high_gprs, v1, v2, te, vx, cr; | |
1036 | 1037 | |
1037 | 1038 | target_auxv_search (target, AT_HWCAP, &hwcap); |
1038 | 1039 | if (!section) |
@@ -1044,6 +1045,7 @@ s390_core_read_description (struct gdbarch *gdbarch, | ||
1044 | 1045 | v2 = (bfd_get_section_by_name (abfd, ".reg-s390-system-call") != NULL); |
1045 | 1046 | vx = (hwcap & HWCAP_S390_VX); |
1046 | 1047 | te = (hwcap & HWCAP_S390_TE); |
1048 | + cr = (bfd_get_section_by_name (abfd, ".reg-s390-ctrs") != NULL); | |
1047 | 1049 | |
1048 | 1050 | switch (bfd_section_size (abfd, section)) |
1049 | 1051 | { |
@@ -1060,6 +1062,8 @@ s390_core_read_description (struct gdbarch *gdbarch, | ||
1060 | 1062 | |
1061 | 1063 | case s390x_sizeof_gregset: |
1062 | 1064 | return (te && vx ? tdesc_s390x_tevx_linux64 : |
1065 | + vx && cr ? tdesc_s390x_vxcr_linux64 : | |
1066 | + cr ? tdesc_s390x_cr_linux64 : | |
1063 | 1067 | vx ? tdesc_s390x_vx_linux64 : |
1064 | 1068 | te ? tdesc_s390x_te_linux64 : |
1065 | 1069 | v2 ? tdesc_s390x_linux64v2 : |
@@ -1116,6 +1120,22 @@ s390_iterate_over_regset_sections (struct gdbarch *gdbarch, | ||
1116 | 1120 | cb (".reg-s390-vxrs-high", 16 * 16, &s390_vxrs_high_regset, |
1117 | 1121 | "s390 vector registers 16-31", cb_data); |
1118 | 1122 | } |
1123 | + | |
1124 | + /* Privileged registers for kernel debugging. */ | |
1125 | + if (bfd_get_section_by_name (core_bfd, ".reg-s390-timer")) | |
1126 | + cb (".reg-s390-timer", 8, &s390x_timer_regset, "s390 timer", cb_data); | |
1127 | + if (bfd_get_section_by_name (core_bfd, ".reg-s390-todcmp")) | |
1128 | + cb (".reg-s390-todcmp", 8, &s390x_todcmp_regset, | |
1129 | + "s390 clock comperator", cb_data); | |
1130 | + if (bfd_get_section_by_name (core_bfd, ".reg-s390-todpreg")) | |
1131 | + cb (".reg-s390-todpreg", 4, &s390x_todpreg_regset, | |
1132 | + "s390 TOD programable register", cb_data); | |
1133 | + if (bfd_get_section_by_name (core_bfd, ".reg-s390-ctrs")) | |
1134 | + cb (".reg-s390-ctrs", 16 * 8, &s390x_cr_regset, | |
1135 | + "s390 control registers", cb_data); | |
1136 | + if (bfd_get_section_by_name (core_bfd, ".reg-s390-prefix")) | |
1137 | + cb (".reg-s390-prefix", 4, &s390x_prefix_regset, | |
1138 | + "s390 prefix area", cb_data); | |
1119 | 1139 | } |
1120 | 1140 | |
1121 | 1141 |
@@ -2986,6 +3006,7 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) | ||
2986 | 3006 | int have_linux_v2 = 0; |
2987 | 3007 | int have_tdb = 0; |
2988 | 3008 | int have_vx = 0; |
3009 | + int have_privileged = 0; | |
2989 | 3010 | int first_pseudo_reg, last_pseudo_reg; |
2990 | 3011 | static const char *const stap_register_prefixes[] = { "%", NULL }; |
2991 | 3012 | static const char *const stap_register_indirection_prefixes[] = { "(", |
@@ -3160,6 +3181,30 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) | ||
3160 | 3181 | have_vx = 1; |
3161 | 3182 | } |
3162 | 3183 | |
3184 | + /* Control registers. */ | |
3185 | + feature = tdesc_find_feature (tdesc, "org.gnu.gdb.s390.cr"); | |
3186 | + if (feature) | |
3187 | + { | |
3188 | + for (i = 0; i < 16; i++) | |
3189 | + valid_p &= tdesc_numbered_register (feature, tdesc_data, | |
3190 | + S390_CR0_REGNUM + i, cr[i]); | |
3191 | + } | |
3192 | + | |
3193 | + /* Privileged registers. */ | |
3194 | + feature = tdesc_find_feature (tdesc, "org.gnu.gdb.s390.privileged"); | |
3195 | + if (feature) | |
3196 | + { | |
3197 | + valid_p &= tdesc_numbered_register (feature, tdesc_data, | |
3198 | + S390_TIMER_REGNUM, "timer"); | |
3199 | + valid_p &= tdesc_numbered_register (feature, tdesc_data, | |
3200 | + S390_TODCMP_REGNUM, "todcmp"); | |
3201 | + valid_p &= tdesc_numbered_register (feature, tdesc_data, | |
3202 | + S390_TODPREG_REGNUM, "todpreg"); | |
3203 | + valid_p &= tdesc_numbered_register (feature, tdesc_data, | |
3204 | + S390_PREFIX_REGNUM, "prefix"); | |
3205 | + have_privileged = 1; | |
3206 | + } | |
3207 | + | |
3163 | 3208 | if (!valid_p) |
3164 | 3209 | { |
3165 | 3210 | tdesc_data_cleanup (tdesc_data); |
@@ -3340,8 +3385,14 @@ s390_gdbarch_init (struct gdbarch_info info, struct gdbarch_list *arches) | ||
3340 | 3385 | set_gdbarch_valid_disassembler_options (gdbarch, |
3341 | 3386 | disassembler_options_s390 ()); |
3342 | 3387 | |
3343 | - /* Note that GNU/Linux is the only OS supported on this platform. */ | |
3344 | - s390_gdbarch_linux_init (info, gdbarch); | |
3388 | + /* Note that GNU/Linux is the only OS supported on this platform. | |
3389 | + Nevertheless we need to distinguish between a kernel- and user-space | |
3390 | + gdbarch. GDBs osabi support is not sufficient for our case as for both | |
3391 | + cases the ELF bits are for Linux. Thus fallback to this method. */ | |
3392 | + if (have_privileged) | |
3393 | + s390_gdbarch_lk_init (info, gdbarch); | |
3394 | + else | |
3395 | + s390_gdbarch_linux_init (info, gdbarch); | |
3345 | 3396 | |
3346 | 3397 | return gdbarch; |
3347 | 3398 | } |
@@ -319,4 +319,66 @@ enum | ||
319 | 319 | #define S390_IS_TDBREGSET_REGNUM(i) \ |
320 | 320 | ((i) >= S390_TDB_DWORD0_REGNUM && (i) <= S390_TDB_R15_REGNUM) |
321 | 321 | |
322 | +/* Definitions for address translation. */ | |
323 | +/* DAT Table types. */ | |
324 | +#define S390_LK_DAT_TT_REGION1 3 | |
325 | +#define S390_LK_DAT_TT_REGION2 2 | |
326 | +#define S390_LK_DAT_TT_REGION3 1 | |
327 | +#define S390_LK_DAT_TT_SEGMENT 0 | |
328 | + | |
329 | +/* Region-First-Table */ | |
330 | +#define S390_LK_RFTE_TL 0x3ULL /* Table-Length */ | |
331 | +#define S390_LK_RFTE_TT 0xcULL /* Table-Type */ | |
332 | +#define S390_LK_RFTE_I 0x20ULL /* Region-Invalid Bit */ | |
333 | +#define S390_LK_RFTE_TF 0xc0ULL /* Table Offset */ | |
334 | +#define S390_LK_RFTE_P 0x200ULL /* DAT-Protection Bit */ | |
335 | +#define S390_LK_RFTE_O ~0xfffULL /* Region-Second-Table Origin */ | |
336 | + | |
337 | +/* Region-Second-Table flags. */ | |
338 | +#define S390_LK_RSTE_TL 0x3ULL /* Table-Length */ | |
339 | +#define S390_LK_RSTE_TT 0xcULL /* Table-Type */ | |
340 | +#define S390_LK_RSTE_I 0x20ULL /* Region-Invalid Bit */ | |
341 | +#define S390_LK_RSTE_TF 0xc0ULL /* Table Offset */ | |
342 | +#define S390_LK_RSTE_P 0x200ULL /* DAT-Protection Bit */ | |
343 | +#define S390_LK_RSTE_O ~0xfffULL /* Region-Third-Table Origin */ | |
344 | + | |
345 | +/* Region-Third-Table flags. */ | |
346 | +#define S390_LK_RTTE_TL 0x3ULL /* Table-Length */ | |
347 | +#define S390_LK_RTTE_TT 0xcULL /* Table-Type */ | |
348 | +#define S390_LK_RTTE_CR 0x10ULL /* Common-Region Bit */ | |
349 | +#define S390_LK_RTTE_I 0x20ULL /* Region-Invalid Bit */ | |
350 | +#define S390_LK_RTTE_TF 0xc0ULL /* Table Offset */ | |
351 | +#define S390_LK_RTTE_P 0x200ULL /* DAT-Protection Bit */ | |
352 | +#define S390_LK_RTTE_FC 0x400ULL /* Format-Control Bit */ | |
353 | +#define S390_LK_RTTE_F 0x800ULL /* Fetch-Protection Bit */ | |
354 | +#define S390_LK_RTTE_ACC 0xf000ULL /* Access-Control Bits */ | |
355 | +#define S390_LK_RTTE_AV 0x10000ULL /* ACCF-Validity Control */ | |
356 | +#define S390_LK_RTTE_O ~0xfffULL /* Segment-Table Origin */ | |
357 | +#define S390_LK_RTTE_RFAA ~0x7fffffffULL /* Region-Frame Absolute Address */ | |
358 | + | |
359 | +/* Segment-Table flags. */ | |
360 | +#define S390_LK_STE_TT 0xcULL /* Table-Type */ | |
361 | +#define S390_LK_STE_I 0x20ULL /* Segment-Invalid Bit */ | |
362 | +#define S390_LK_STE_TF 0xc0ULL /* Table Offset */ | |
363 | +#define S390_LK_STE_P 0x200ULL /* DAT-Protection Bit */ | |
364 | +#define S390_LK_STE_FC 0x400ULL /* Format-Control Bit */ | |
365 | +#define S390_LK_STE_F 0x800ULL /* Fetch-Protection Bit */ | |
366 | +#define S390_LK_STE_ACC 0xf000ULL /* Access-Control Bits */ | |
367 | +#define S390_LK_STE_AV 0x10000ULL /* ACCF-Validity Control */ | |
368 | +#define S390_LK_STE_O ~0x7ffULL /* Page-Table Origin */ | |
369 | +#define S390_LK_STE_SFAA ~0xfffffULL /* Segment-Frame Absolute Address */ | |
370 | + | |
371 | +/* Page-Table flags. */ | |
372 | +#define S390_LK_PTE_P 0x200ULL /* DAT-Protection Bit */ | |
373 | +#define S390_LK_PTE_I 0x400ULL /* Page-Invalid Bit */ | |
374 | +#define S390_LK_PTE_PFAA ~0xfffULL /* Page-Frame Absolute Address */ | |
375 | + | |
376 | +/* Virtual Address Fields. */ | |
377 | +#define S390_LK_VADDR_RFX 0xffe0000000000000ULL | |
378 | +#define S390_LK_VADDR_RSX 0x001ffc0000000000ULL | |
379 | +#define S390_LK_VADDR_RTX 0x000003ff80000000ULL | |
380 | +#define S390_LK_VADDR_SX 0x000000007ff00000ULL | |
381 | +#define S390_LK_VADDR_PX 0x00000000000ff000ULL | |
382 | +#define S390_LK_VADDR_BX 0x0000000000000fffULL | |
383 | + | |
322 | 384 | #endif /* S390_TDEP_H */ |