master
c 524 lines 13.3 KB
Raw
1 /*
2 * PowerPC gdb server stub
3 *
4 * Copyright (c) 2003-2005 Fabrice Bellard
5 * Copyright (c) 2013 SUSE LINUX Products GmbH
6 *
7 * This library is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU Lesser General Public
9 * License as published by the Free Software Foundation; either
10 * version 2.1 of the License, or (at your option) any later version.
11 *
12 * This library 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 GNU
15 * Lesser General Public License for more details.
16 *
17 * You should have received a copy of the GNU Lesser General Public
18 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19 */
20 #include "qemu/osdep.h"
21 #include "cpu.h"
22 #include "exec/gdbstub.h"
23 #include "gdbstub/helpers.h"
24 #include "internal.h"
25
26 static unsigned ppc_gdb_register_len(int n)
27 {
28 switch (n) {
29 case 0 ... 31:
30 /* gprs */
31 return target_long_bits() / 8;
32 case 66:
33 /* cr */
34 case 69:
35 /* xer */
36 return 4;
37 case 64:
38 /* nip */
39 case 65:
40 /* msr */
41 case 67:
42 /* lr */
43 case 68:
44 /* ctr */
45 return target_long_bits() / 8;
46 default:
47 return 0;
48 }
49 }
50
51 /*
52 * We need to present the registers to gdb in the "current" memory
53 * ordering. For user-only mode we get this for free;
54 * TARGET_BIG_ENDIAN is set to the proper ordering for the
55 * binary, and cannot be changed. For system mode,
56 * TARGET_BIG_ENDIAN is always set, and we must check the current
57 * mode of the chip to see if we're running in little-endian.
58 */
59 void ppc_maybe_bswap_register(CPUPPCState *env, uint8_t *mem_buf, int len)
60 {
61 #ifndef CONFIG_USER_ONLY
62 if (!ppc_env_is_little_endian(env)) {
63 /* do nothing */
64 } else if (len == 4) {
65 bswap32s((uint32_t *)mem_buf);
66 } else if (len == 8) {
67 bswap64s((uint64_t *)mem_buf);
68 } else if (len == 16) {
69 bswap128s((Int128 *)mem_buf);
70 } else {
71 g_assert_not_reached();
72 }
73 #endif
74 }
75
76 /*
77 * Old gdb always expects FP registers. Newer (xml-aware) gdb only
78 * expects whatever the target description contains. Due to a
79 * historical mishap the FP registers appear in between core integer
80 * regs and PC, MSR, CR, and so forth. We hack round this by giving
81 * the FP regs zero size when talking to a newer gdb.
82 */
83
84 int ppc_cpu_gdb_read_register(CPUState *cs, GByteArray *buf, int n)
85 {
86 CPUPPCState *env = cpu_env(cs);
87 uint8_t *mem_buf;
88 unsigned r = ppc_gdb_register_len(n);
89
90 if (!r) {
91 return r;
92 }
93
94 if (n < 32) {
95 /* gprs */
96 gdb_get_regl(buf, env->gpr[n]);
97 } else {
98 switch (n) {
99 case 64:
100 gdb_get_regl(buf, env->nip);
101 break;
102 case 65:
103 gdb_get_regl(buf, env->msr);
104 break;
105 case 66:
106 {
107 uint32_t cr = ppc_get_cr(env);
108 gdb_get_reg32(buf, cr);
109 break;
110 }
111 case 67:
112 gdb_get_regl(buf, env->lr);
113 break;
114 case 68:
115 gdb_get_regl(buf, env->ctr);
116 break;
117 case 69:
118 gdb_get_reg32(buf, cpu_read_xer(env));
119 break;
120 }
121 }
122 mem_buf = buf->data + buf->len - r;
123 ppc_maybe_bswap_register(env, mem_buf, r);
124 return r;
125 }
126
127 int ppc_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
128 {
129 CPUPPCState *env = cpu_env(cs);
130 unsigned r = ppc_gdb_register_len(n);
131
132 if (!r) {
133 return r;
134 }
135 ppc_maybe_bswap_register(env, mem_buf, r);
136 if (n < 32) {
137 /* gprs */
138 env->gpr[n] = ldn_p(mem_buf, r);
139 } else if (n < 64) {
140 /* fprs */
141 *cpu_fpr_ptr(env, n - 32) = ldq_p(mem_buf);
142 } else {
143 switch (n) {
144 case 64:
145 env->nip = ldn_p(mem_buf, r);
146 break;
147 case 65:
148 ppc_store_msr(env, ldn_p(mem_buf, r));
149 break;
150 case 66:
151 {
152 uint32_t cr = ldl_p(mem_buf);
153 ppc_set_cr(env, cr);
154 break;
155 }
156 case 67:
157 env->lr = ldn_p(mem_buf, r);
158 break;
159 case 68:
160 env->ctr = ldn_p(mem_buf, r);
161 break;
162 case 69:
163 cpu_write_xer(env, ldl_p(mem_buf));
164 break;
165 case 70:
166 /* fpscr */
167 ppc_store_fpscr(env, ldn_p(mem_buf, r));
168 break;
169 }
170 }
171 return r;
172 }
173
174 #ifndef CONFIG_USER_ONLY
175 static void gdb_gen_spr_feature(CPUState *cs)
176 {
177 PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs);
178 PowerPCCPU *cpu = POWERPC_CPU(cs);
179 CPUPPCState *env = &cpu->env;
180 GDBFeatureBuilder builder;
181 unsigned int num_regs = 0;
182 int i;
183
184 for (i = 0; i < ARRAY_SIZE(env->spr_cb); i++) {
185 ppc_spr_t *spr = &env->spr_cb[i];
186
187 if (!spr->name) {
188 continue;
189 }
190
191 /*
192 * GDB identifies registers based on the order they are
193 * presented in the XML. These ids will not match QEMU's
194 * representation (which follows the PowerISA).
195 *
196 * Store the position of the current register description so
197 * we can make the correspondence later.
198 */
199 spr->gdb_id = num_regs;
200 num_regs++;
201 }
202
203 if (pcc->gdb_spr.xml) {
204 return;
205 }
206
207 gdb_feature_builder_init(&builder, &pcc->gdb_spr,
208 "org.qemu.power.spr", "power-spr.xml",
209 cs->gdb_num_regs);
210
211 for (i = 0; i < ARRAY_SIZE(env->spr_cb); i++) {
212 ppc_spr_t *spr = &env->spr_cb[i];
213
214 if (!spr->name) {
215 continue;
216 }
217
218 gdb_feature_builder_append_reg(&builder, g_ascii_strdown(spr->name, -1),
219 TARGET_LONG_BITS, spr->gdb_id,
220 "int", "spr");
221 }
222
223 gdb_feature_builder_end(&builder);
224 }
225 #endif
226
227 #if !defined(CONFIG_USER_ONLY)
228 static int gdb_find_spr_idx(CPUPPCState *env, int n)
229 {
230 int i;
231
232 for (i = 0; i < ARRAY_SIZE(env->spr_cb); i++) {
233 ppc_spr_t *spr = &env->spr_cb[i];
234
235 if (spr->name && spr->gdb_id == n) {
236 return i;
237 }
238 }
239 return -1;
240 }
241
242 static int gdb_get_spr_reg(CPUState *cs, GByteArray *buf, int n)
243 {
244 PowerPCCPU *cpu = POWERPC_CPU(cs);
245 CPUPPCState *env = &cpu->env;
246 int reg;
247 int len;
248
249 reg = gdb_find_spr_idx(env, n);
250 if (reg < 0) {
251 return 0;
252 }
253
254 len = TARGET_LONG_SIZE;
255
256 /* Handle those SPRs that are not part of the env->spr[] array */
257 target_ulong val;
258 switch (reg) {
259 #if defined(TARGET_PPC64)
260 case SPR_CFAR:
261 val = env->cfar;
262 break;
263 #endif
264 case SPR_HDEC:
265 val = cpu_ppc_load_hdecr(env);
266 break;
267 case SPR_TBL:
268 val = cpu_ppc_load_tbl(env);
269 break;
270 case SPR_TBU:
271 val = cpu_ppc_load_tbu(env);
272 break;
273 case SPR_DECR:
274 val = cpu_ppc_load_decr(env);
275 break;
276 default:
277 val = env->spr[reg];
278 }
279 gdb_get_regl(buf, val);
280
281 ppc_maybe_bswap_register(env, gdb_get_reg_ptr(buf, len), len);
282 return len;
283 }
284
285 static int gdb_set_spr_reg(CPUState *cs, uint8_t *mem_buf, int n)
286 {
287 PowerPCCPU *cpu = POWERPC_CPU(cs);
288 CPUPPCState *env = &cpu->env;
289 int reg;
290 int len;
291
292 reg = gdb_find_spr_idx(env, n);
293 if (reg < 0) {
294 return 0;
295 }
296
297 len = TARGET_LONG_SIZE;
298 ppc_maybe_bswap_register(env, mem_buf, len);
299
300 /* Handle those SPRs that are not part of the env->spr[] array */
301 target_ulong val = ldn_p(mem_buf, len);
302 switch (reg) {
303 #if defined(TARGET_PPC64)
304 case SPR_CFAR:
305 env->cfar = val;
306 break;
307 #endif
308 default:
309 env->spr[reg] = val;
310 }
311
312 return len;
313 }
314 #endif
315
316 static int gdb_get_float_reg(CPUState *cs, GByteArray *buf, int n)
317 {
318 PowerPCCPU *cpu = POWERPC_CPU(cs);
319 CPUPPCState *env = &cpu->env;
320 uint8_t *mem_buf;
321 if (n < 32) {
322 gdb_get_reg64(buf, *cpu_fpr_ptr(env, n));
323 mem_buf = gdb_get_reg_ptr(buf, 8);
324 ppc_maybe_bswap_register(env, mem_buf, 8);
325 return 8;
326 }
327 if (n == 32) {
328 gdb_get_reg32(buf, env->fpscr);
329 mem_buf = gdb_get_reg_ptr(buf, 4);
330 ppc_maybe_bswap_register(env, mem_buf, 4);
331 return 4;
332 }
333 return 0;
334 }
335
336 static int gdb_set_float_reg(CPUState *cs, uint8_t *mem_buf, int n)
337 {
338 PowerPCCPU *cpu = POWERPC_CPU(cs);
339 CPUPPCState *env = &cpu->env;
340
341 if (n < 32) {
342 ppc_maybe_bswap_register(env, mem_buf, 8);
343 *cpu_fpr_ptr(env, n) = ldq_p(mem_buf);
344 return 8;
345 }
346 if (n == 32) {
347 ppc_maybe_bswap_register(env, mem_buf, 4);
348 ppc_store_fpscr(env, ldl_p(mem_buf));
349 return 4;
350 }
351 return 0;
352 }
353
354 static int gdb_get_avr_reg(CPUState *cs, GByteArray *buf, int n)
355 {
356 PowerPCCPU *cpu = POWERPC_CPU(cs);
357 CPUPPCState *env = &cpu->env;
358 uint8_t *mem_buf;
359
360 if (n < 32) {
361 ppc_avr_t *avr = cpu_avr_ptr(env, n);
362 gdb_get_reg128(buf, avr->VsrD(0), avr->VsrD(1));
363 mem_buf = gdb_get_reg_ptr(buf, 16);
364 ppc_maybe_bswap_register(env, mem_buf, 16);
365 return 16;
366 }
367 if (n == 32) {
368 gdb_get_reg32(buf, ppc_get_vscr(env));
369 mem_buf = gdb_get_reg_ptr(buf, 4);
370 ppc_maybe_bswap_register(env, mem_buf, 4);
371 return 4;
372 }
373 if (n == 33) {
374 gdb_get_reg32(buf, (uint32_t)env->spr[SPR_VRSAVE]);
375 mem_buf = gdb_get_reg_ptr(buf, 4);
376 ppc_maybe_bswap_register(env, mem_buf, 4);
377 return 4;
378 }
379 return 0;
380 }
381
382 static int gdb_set_avr_reg(CPUState *cs, uint8_t *mem_buf, int n)
383 {
384 PowerPCCPU *cpu = POWERPC_CPU(cs);
385 CPUPPCState *env = &cpu->env;
386
387 if (n < 32) {
388 ppc_avr_t *avr = cpu_avr_ptr(env, n);
389 ppc_maybe_bswap_register(env, mem_buf, 16);
390 avr->VsrD(0) = ldq_p(mem_buf);
391 avr->VsrD(1) = ldq_p(mem_buf + 8);
392 return 16;
393 }
394 if (n == 32) {
395 ppc_maybe_bswap_register(env, mem_buf, 4);
396 ppc_store_vscr(env, ldl_p(mem_buf));
397 return 4;
398 }
399 if (n == 33) {
400 ppc_maybe_bswap_register(env, mem_buf, 4);
401 env->spr[SPR_VRSAVE] = (target_ulong)ldl_p(mem_buf);
402 return 4;
403 }
404 return 0;
405 }
406
407 static int gdb_get_spe_reg(CPUState *cs, GByteArray *buf, int n)
408 {
409 PowerPCCPU *cpu = POWERPC_CPU(cs);
410 CPUPPCState *env = &cpu->env;
411
412 if (n < 32) {
413 #if defined(TARGET_PPC64)
414 gdb_get_reg32(buf, env->gpr[n] >> 32);
415 ppc_maybe_bswap_register(env, gdb_get_reg_ptr(buf, 4), 4);
416 #else
417 gdb_get_reg32(buf, env->gprh[n]);
418 #endif
419 return 4;
420 }
421 if (n == 32) {
422 gdb_get_reg64(buf, env->spe_acc);
423 ppc_maybe_bswap_register(env, gdb_get_reg_ptr(buf, 8), 8);
424 return 8;
425 }
426 if (n == 33) {
427 gdb_get_reg32(buf, env->spe_fscr);
428 ppc_maybe_bswap_register(env, gdb_get_reg_ptr(buf, 4), 4);
429 return 4;
430 }
431 return 0;
432 }
433
434 static int gdb_set_spe_reg(CPUState *cs, uint8_t *mem_buf, int n)
435 {
436 PowerPCCPU *cpu = POWERPC_CPU(cs);
437 CPUPPCState *env = &cpu->env;
438
439 if (n < 32) {
440 #if defined(TARGET_PPC64)
441 target_ulong lo = (uint32_t)env->gpr[n];
442 target_ulong hi;
443
444 ppc_maybe_bswap_register(env, mem_buf, 4);
445
446 hi = (target_ulong)ldl_p(mem_buf) << 32;
447 env->gpr[n] = lo | hi;
448 #else
449 env->gprh[n] = ldl_p(mem_buf);
450 #endif
451 return 4;
452 }
453 if (n == 32) {
454 ppc_maybe_bswap_register(env, mem_buf, 8);
455 env->spe_acc = ldq_p(mem_buf);
456 return 8;
457 }
458 if (n == 33) {
459 ppc_maybe_bswap_register(env, mem_buf, 4);
460 env->spe_fscr = ldl_p(mem_buf);
461 return 4;
462 }
463 return 0;
464 }
465
466 static int gdb_get_vsx_reg(CPUState *cs, GByteArray *buf, int n)
467 {
468 PowerPCCPU *cpu = POWERPC_CPU(cs);
469 CPUPPCState *env = &cpu->env;
470
471 if (n < 32) {
472 gdb_get_reg64(buf, *cpu_vsrl_ptr(env, n));
473 ppc_maybe_bswap_register(env, gdb_get_reg_ptr(buf, 8), 8);
474 return 8;
475 }
476 return 0;
477 }
478
479 static int gdb_set_vsx_reg(CPUState *cs, uint8_t *mem_buf, int n)
480 {
481 PowerPCCPU *cpu = POWERPC_CPU(cs);
482 CPUPPCState *env = &cpu->env;
483
484 if (n < 32) {
485 ppc_maybe_bswap_register(env, mem_buf, 8);
486 *cpu_vsrl_ptr(env, n) = ldq_p(mem_buf);
487 return 8;
488 }
489 return 0;
490 }
491
492 const gchar *ppc_gdb_arch_name(CPUState *cs)
493 {
494 #if defined(TARGET_PPC64)
495 return "powerpc:common64";
496 #else
497 return "powerpc:common";
498 #endif
499 }
500
501 void ppc_gdb_init(CPUState *cs, PowerPCCPUClass *pcc)
502 {
503 if (pcc->insns_flags & PPC_FLOAT) {
504 gdb_register_coprocessor(cs, gdb_get_float_reg, gdb_set_float_reg,
505 gdb_find_static_feature("power-fpu.xml"));
506 }
507 if (pcc->insns_flags & PPC_ALTIVEC) {
508 gdb_register_coprocessor(cs, gdb_get_avr_reg, gdb_set_avr_reg,
509 gdb_find_static_feature("power-altivec.xml"));
510 }
511 if (pcc->insns_flags & PPC_SPE) {
512 gdb_register_coprocessor(cs, gdb_get_spe_reg, gdb_set_spe_reg,
513 gdb_find_static_feature("power-spe.xml"));
514 }
515 if (pcc->insns_flags2 & PPC2_VSX) {
516 gdb_register_coprocessor(cs, gdb_get_vsx_reg, gdb_set_vsx_reg,
517 gdb_find_static_feature("power-vsx.xml"));
518 }
519 #ifndef CONFIG_USER_ONLY
520 gdb_gen_spr_feature(cs);
521 gdb_register_coprocessor(cs, gdb_get_spr_reg, gdb_set_spr_reg,
522 &pcc->gdb_spr);
523 #endif
524 }