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 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 | |
24 | static int ppc_gdb_register_len_apple(int n) |
25 | { |
26 | switch (n) { |
27 | case 0 ... 31: |
28 | /* gprs */ |
29 | return 8; |
30 | case 32 ... 63: |
31 | /* fprs */ |
32 | return 8; |
33 | case 64 ... 95: |
34 | return 16; |
35 | case 64 + 32: /* nip */ |
36 | case 65 + 32: /* msr */ |
37 | case 67 + 32: /* lr */ |
38 | case 68 + 32: /* ctr */ |
39 | case 70 + 32: /* fpscr */ |
40 | return 8; |
41 | case 66 + 32: /* cr */ |
42 | case 69 + 32: /* xer */ |
43 | return 4; |
44 | default: |
45 | return 0; |
46 | } |
47 | } |
48 | |
49 | static int ppc_gdb_register_len(int n) |
50 | { |
51 | switch (n) { |
52 | case 0 ... 31: |
53 | /* gprs */ |
54 | return sizeof(target_ulong); |
55 | case 32 ... 63: |
56 | /* fprs */ |
57 | if (gdb_has_xml) { |
58 | return 0; |
59 | } |
60 | return 8; |
61 | case 66: |
62 | /* cr */ |
63 | case 69: |
64 | /* xer */ |
65 | return 4; |
66 | case 64: |
67 | /* nip */ |
68 | case 65: |
69 | /* msr */ |
70 | case 67: |
71 | /* lr */ |
72 | case 68: |
73 | /* ctr */ |
74 | return sizeof(target_ulong); |
75 | case 70: |
76 | /* fpscr */ |
77 | if (gdb_has_xml) { |
78 | return 0; |
79 | } |
80 | return sizeof(target_ulong); |
81 | default: |
82 | return 0; |
83 | } |
84 | } |
85 | |
86 | /* |
87 | * We need to present the registers to gdb in the "current" memory |
88 | * ordering. For user-only mode we get this for free; |
89 | * TARGET_WORDS_BIGENDIAN is set to the proper ordering for the |
90 | * binary, and cannot be changed. For system mode, |
91 | * TARGET_WORDS_BIGENDIAN is always set, and we must check the current |
92 | * mode of the chip to see if we're running in little-endian. |
93 | */ |
94 | void ppc_maybe_bswap_register(CPUPPCState *env, uint8_t *mem_buf, int len) |
95 | { |
96 | #ifndef CONFIG_USER_ONLY |
97 | if (!msr_le) { |
98 | /* do nothing */ |
99 | } else if (len == 4) { |
100 | bswap32s((uint32_t *)mem_buf); |
101 | } else if (len == 8) { |
102 | bswap64s((uint64_t *)mem_buf); |
103 | } else { |
104 | g_assert_not_reached(); |
105 | } |
106 | #endif |
107 | } |
108 | |
109 | /* |
110 | * Old gdb always expects FP registers. Newer (xml-aware) gdb only |
111 | * expects whatever the target description contains. Due to a |
112 | * historical mishap the FP registers appear in between core integer |
113 | * regs and PC, MSR, CR, and so forth. We hack round this by giving |
114 | * the FP regs zero size when talking to a newer gdb. |
115 | */ |
116 | |
117 | int ppc_cpu_gdb_read_register(CPUState *cs, uint8_t *mem_buf, int n) |
118 | { |
119 | PowerPCCPU *cpu = POWERPC_CPU(cs); |
120 | CPUPPCState *env = &cpu->env; |
121 | int r = ppc_gdb_register_len(n); |
122 | |
123 | if (!r) { |
124 | return r; |
125 | } |
126 | |
127 | if (n < 32) { |
128 | /* gprs */ |
129 | gdb_get_regl(mem_buf, env->gpr[n]); |
130 | } else if (n < 64) { |
131 | /* fprs */ |
132 | stfq_p(mem_buf, *cpu_fpr_ptr(env, n - 32)); |
133 | } else { |
134 | switch (n) { |
135 | case 64: |
136 | gdb_get_regl(mem_buf, env->nip); |
137 | break; |
138 | case 65: |
139 | gdb_get_regl(mem_buf, env->msr); |
140 | break; |
141 | case 66: |
142 | { |
143 | uint32_t cr = 0; |
144 | int i; |
145 | for (i = 0; i < 8; i++) { |
146 | cr |= env->crf[i] << (32 - ((i + 1) * 4)); |
147 | } |
148 | gdb_get_reg32(mem_buf, cr); |
149 | break; |
150 | } |
151 | case 67: |
152 | gdb_get_regl(mem_buf, env->lr); |
153 | break; |
154 | case 68: |
155 | gdb_get_regl(mem_buf, env->ctr); |
156 | break; |
157 | case 69: |
158 | gdb_get_reg32(mem_buf, env->xer); |
159 | break; |
160 | case 70: |
161 | gdb_get_reg32(mem_buf, env->fpscr); |
162 | break; |
163 | } |
164 | } |
165 | ppc_maybe_bswap_register(env, mem_buf, r); |
166 | return r; |
167 | } |
168 | |
169 | int ppc_cpu_gdb_read_register_apple(CPUState *cs, uint8_t *mem_buf, int n) |
170 | { |
171 | PowerPCCPU *cpu = POWERPC_CPU(cs); |
172 | CPUPPCState *env = &cpu->env; |
173 | int r = ppc_gdb_register_len_apple(n); |
174 | |
175 | if (!r) { |
176 | return r; |
177 | } |
178 | |
179 | if (n < 32) { |
180 | /* gprs */ |
181 | gdb_get_reg64(mem_buf, env->gpr[n]); |
182 | } else if (n < 64) { |
183 | /* fprs */ |
184 | stfq_p(mem_buf, *cpu_fpr_ptr(env, n - 32)); |
185 | } else if (n < 96) { |
186 | /* Altivec */ |
187 | stq_p(mem_buf, n - 64); |
188 | stq_p(mem_buf + 8, 0); |
189 | } else { |
190 | switch (n) { |
191 | case 64 + 32: |
192 | gdb_get_reg64(mem_buf, env->nip); |
193 | break; |
194 | case 65 + 32: |
195 | gdb_get_reg64(mem_buf, env->msr); |
196 | break; |
197 | case 66 + 32: |
198 | { |
199 | uint32_t cr = 0; |
200 | int i; |
201 | for (i = 0; i < 8; i++) { |
202 | cr |= env->crf[i] << (32 - ((i + 1) * 4)); |
203 | } |
204 | gdb_get_reg32(mem_buf, cr); |
205 | break; |
206 | } |
207 | case 67 + 32: |
208 | gdb_get_reg64(mem_buf, env->lr); |
209 | break; |
210 | case 68 + 32: |
211 | gdb_get_reg64(mem_buf, env->ctr); |
212 | break; |
213 | case 69 + 32: |
214 | gdb_get_reg32(mem_buf, env->xer); |
215 | break; |
216 | case 70 + 32: |
217 | gdb_get_reg64(mem_buf, env->fpscr); |
218 | break; |
219 | } |
220 | } |
221 | ppc_maybe_bswap_register(env, mem_buf, r); |
222 | return r; |
223 | } |
224 | |
225 | int ppc_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n) |
226 | { |
227 | PowerPCCPU *cpu = POWERPC_CPU(cs); |
228 | CPUPPCState *env = &cpu->env; |
229 | int r = ppc_gdb_register_len(n); |
230 | |
231 | if (!r) { |
232 | return r; |
233 | } |
234 | ppc_maybe_bswap_register(env, mem_buf, r); |
235 | if (n < 32) { |
236 | /* gprs */ |
237 | env->gpr[n] = ldtul_p(mem_buf); |
238 | } else if (n < 64) { |
239 | /* fprs */ |
240 | *cpu_fpr_ptr(env, n - 32) = ldfq_p(mem_buf); |
241 | } else { |
242 | switch (n) { |
243 | case 64: |
244 | env->nip = ldtul_p(mem_buf); |
245 | break; |
246 | case 65: |
247 | ppc_store_msr(env, ldtul_p(mem_buf)); |
248 | break; |
249 | case 66: |
250 | { |
251 | uint32_t cr = ldl_p(mem_buf); |
252 | int i; |
253 | for (i = 0; i < 8; i++) { |
254 | env->crf[i] = (cr >> (32 - ((i + 1) * 4))) & 0xF; |
255 | } |
256 | break; |
257 | } |
258 | case 67: |
259 | env->lr = ldtul_p(mem_buf); |
260 | break; |
261 | case 68: |
262 | env->ctr = ldtul_p(mem_buf); |
263 | break; |
264 | case 69: |
265 | env->xer = ldl_p(mem_buf); |
266 | break; |
267 | case 70: |
268 | /* fpscr */ |
269 | store_fpscr(env, ldtul_p(mem_buf), 0xffffffff); |
270 | break; |
271 | } |
272 | } |
273 | return r; |
274 | } |
275 | int ppc_cpu_gdb_write_register_apple(CPUState *cs, uint8_t *mem_buf, int n) |
276 | { |
277 | PowerPCCPU *cpu = POWERPC_CPU(cs); |
278 | CPUPPCState *env = &cpu->env; |
279 | int r = ppc_gdb_register_len_apple(n); |
280 | |
281 | if (!r) { |
282 | return r; |
283 | } |
284 | ppc_maybe_bswap_register(env, mem_buf, r); |
285 | if (n < 32) { |
286 | /* gprs */ |
287 | env->gpr[n] = ldq_p(mem_buf); |
288 | } else if (n < 64) { |
289 | /* fprs */ |
290 | *cpu_fpr_ptr(env, n - 32) = ldfq_p(mem_buf); |
291 | } else { |
292 | switch (n) { |
293 | case 64 + 32: |
294 | env->nip = ldq_p(mem_buf); |
295 | break; |
296 | case 65 + 32: |
297 | ppc_store_msr(env, ldq_p(mem_buf)); |
298 | break; |
299 | case 66 + 32: |
300 | { |
301 | uint32_t cr = ldl_p(mem_buf); |
302 | int i; |
303 | for (i = 0; i < 8; i++) { |
304 | env->crf[i] = (cr >> (32 - ((i + 1) * 4))) & 0xF; |
305 | } |
306 | break; |
307 | } |
308 | case 67 + 32: |
309 | env->lr = ldq_p(mem_buf); |
310 | break; |
311 | case 68 + 32: |
312 | env->ctr = ldq_p(mem_buf); |
313 | break; |
314 | case 69 + 32: |
315 | env->xer = ldl_p(mem_buf); |
316 | break; |
317 | case 70 + 32: |
318 | /* fpscr */ |
319 | store_fpscr(env, ldq_p(mem_buf), 0xffffffff); |
320 | break; |
321 | } |
322 | } |
323 | return r; |
324 | } |
325 | |
326 | #ifndef CONFIG_USER_ONLY |
327 | void ppc_gdb_gen_spr_xml(PowerPCCPU *cpu) |
328 | { |
329 | PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu); |
330 | CPUPPCState *env = &cpu->env; |
331 | GString *xml; |
332 | char *spr_name; |
333 | unsigned int num_regs = 0; |
334 | int i; |
335 | |
336 | if (pcc->gdb_spr_xml) { |
337 | return; |
338 | } |
339 | |
340 | xml = g_string_new("<?xml version=\"1.0\"?>" ); |
341 | g_string_append(xml, "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">" ); |
342 | g_string_append(xml, "<feature name=\"org.qemu.power.spr\">" ); |
343 | |
344 | for (i = 0; i < ARRAY_SIZE(env->spr_cb); i++) { |
345 | ppc_spr_t *spr = &env->spr_cb[i]; |
346 | |
347 | if (!spr->name) { |
348 | continue; |
349 | } |
350 | |
351 | spr_name = g_ascii_strdown(spr->name, -1); |
352 | g_string_append_printf(xml, "<reg name=\"%s\"" , spr_name); |
353 | g_free(spr_name); |
354 | |
355 | g_string_append_printf(xml, " bitsize=\"%d\"" , TARGET_LONG_BITS); |
356 | g_string_append(xml, " group=\"spr\"/>" ); |
357 | |
358 | /* |
359 | * GDB identifies registers based on the order they are |
360 | * presented in the XML. These ids will not match QEMU's |
361 | * representation (which follows the PowerISA). |
362 | * |
363 | * Store the position of the current register description so |
364 | * we can make the correspondence later. |
365 | */ |
366 | spr->gdb_id = num_regs; |
367 | num_regs++; |
368 | } |
369 | |
370 | g_string_append(xml, "</feature>" ); |
371 | |
372 | pcc->gdb_num_sprs = num_regs; |
373 | pcc->gdb_spr_xml = g_string_free(xml, false); |
374 | } |
375 | |
376 | const char *ppc_gdb_get_dynamic_xml(CPUState *cs, const char *xml_name) |
377 | { |
378 | PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cs); |
379 | |
380 | if (strcmp(xml_name, "power-spr.xml" ) == 0) { |
381 | return pcc->gdb_spr_xml; |
382 | } |
383 | return NULL; |
384 | } |
385 | #endif |
386 | |