]>
git.proxmox.com Git - mirror_qemu.git/blob - target/arm/gdbstub64.c
2 * ARM gdb server stub: AArch64 specific functions.
4 * Copyright (c) 2013 SUSE LINUX Products GmbH
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2.1 of the License, or (at your option) any later version.
11 * This library 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 GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19 #include "qemu/osdep.h"
22 #include "internals.h"
23 #include "exec/gdbstub.h"
25 int aarch64_cpu_gdb_read_register(CPUState
*cs
, GByteArray
*mem_buf
, int n
)
27 ARMCPU
*cpu
= ARM_CPU(cs
);
28 CPUARMState
*env
= &cpu
->env
;
31 /* Core integer register. */
32 return gdb_get_reg64(mem_buf
, env
->xregs
[n
]);
36 return gdb_get_reg64(mem_buf
, env
->xregs
[31]);
38 return gdb_get_reg64(mem_buf
, env
->pc
);
40 return gdb_get_reg32(mem_buf
, pstate_read(env
));
42 /* Unknown register. */
46 int aarch64_cpu_gdb_write_register(CPUState
*cs
, uint8_t *mem_buf
, int n
)
48 ARMCPU
*cpu
= ARM_CPU(cs
);
49 CPUARMState
*env
= &cpu
->env
;
55 /* Core integer register. */
68 pstate_write(env
, tmp
);
71 /* Unknown register. */
75 int aarch64_gdb_get_fpu_reg(CPUARMState
*env
, GByteArray
*buf
, int reg
)
80 /* 128 bit FP register - quads are in LE order */
81 uint64_t *q
= aa64_vfp_qreg(env
, reg
);
82 return gdb_get_reg128(buf
, q
[1], q
[0]);
86 return gdb_get_reg32(buf
, vfp_get_fpsr(env
));
89 return gdb_get_reg32(buf
, vfp_get_fpcr(env
));
95 int aarch64_gdb_set_fpu_reg(CPUARMState
*env
, uint8_t *buf
, int reg
)
99 /* 128 bit FP register */
101 uint64_t *q
= aa64_vfp_qreg(env
, reg
);
102 q
[0] = ldq_le_p(buf
);
103 q
[1] = ldq_le_p(buf
+ 8);
108 vfp_set_fpsr(env
, ldl_p(buf
));
112 vfp_set_fpcr(env
, ldl_p(buf
));
119 int aarch64_gdb_get_sve_reg(CPUARMState
*env
, GByteArray
*buf
, int reg
)
121 ARMCPU
*cpu
= env_archcpu(env
);
124 /* The first 32 registers are the zregs */
128 for (vq
= 0; vq
< cpu
->sve_max_vq
; vq
++) {
129 len
+= gdb_get_reg128(buf
,
130 env
->vfp
.zregs
[reg
].d
[vq
* 2 + 1],
131 env
->vfp
.zregs
[reg
].d
[vq
* 2]);
136 return gdb_get_reg32(buf
, vfp_get_fpsr(env
));
138 return gdb_get_reg32(buf
, vfp_get_fpcr(env
));
139 /* then 16 predicates and the ffr */
144 for (vq
= 0; vq
< cpu
->sve_max_vq
; vq
= vq
+ 4) {
145 len
+= gdb_get_reg64(buf
, env
->vfp
.pregs
[preg
].p
[vq
/ 4]);
152 * We report in Vector Granules (VG) which is 64bit in a Z reg
153 * while the ZCR works in Vector Quads (VQ) which is 128bit chunks.
155 int vq
= sve_vqm1_for_el(env
, arm_current_el(env
)) + 1;
156 return gdb_get_reg64(buf
, vq
* 2);
159 /* gdbstub asked for something out our range */
160 qemu_log_mask(LOG_UNIMP
, "%s: out of range register %d", __func__
, reg
);
167 int aarch64_gdb_set_sve_reg(CPUARMState
*env
, uint8_t *buf
, int reg
)
169 ARMCPU
*cpu
= env_archcpu(env
);
171 /* The first 32 registers are the zregs */
173 /* The first 32 registers are the zregs */
177 uint64_t *p
= (uint64_t *) buf
;
178 for (vq
= 0; vq
< cpu
->sve_max_vq
; vq
++) {
179 env
->vfp
.zregs
[reg
].d
[vq
* 2 + 1] = *p
++;
180 env
->vfp
.zregs
[reg
].d
[vq
* 2] = *p
++;
186 vfp_set_fpsr(env
, *(uint32_t *)buf
);
189 vfp_set_fpcr(env
, *(uint32_t *)buf
);
195 uint64_t *p
= (uint64_t *) buf
;
196 for (vq
= 0; vq
< cpu
->sve_max_vq
; vq
= vq
+ 4) {
197 env
->vfp
.pregs
[preg
].p
[vq
/ 4] = *p
++;
203 /* cannot set vg via gdbstub */
206 /* gdbstub asked for something out our range */
213 int aarch64_gdb_get_pauth_reg(CPUARMState
*env
, GByteArray
*buf
, int reg
)
216 case 0: /* pauth_dmask */
217 case 1: /* pauth_cmask */
218 case 2: /* pauth_dmask_high */
219 case 3: /* pauth_cmask_high */
221 * Note that older versions of this feature only contained
222 * pauth_{d,c}mask, for use with Linux user processes, and
223 * thus exclusively in the low half of the address space.
225 * To support system mode, and to debug kernels, two new regs
226 * were added to cover the high half of the address space.
227 * For the purpose of pauth_ptr_mask, we can use any well-formed
228 * address within the address space half -- here, 0 and -1.
231 bool is_data
= !(reg
& 1);
232 bool is_high
= reg
& 2;
233 uint64_t mask
= pauth_ptr_mask(env
, -is_high
, is_data
);
234 return gdb_get_reg64(buf
, mask
);
241 int aarch64_gdb_set_pauth_reg(CPUARMState
*env
, uint8_t *buf
, int reg
)
243 /* All pseudo registers are read-only. */
247 static void output_vector_union_type(GString
*s
, int reg_width
,
251 const char *gdb_type
;
256 static const struct TypeSize vec_lanes
[] = {
258 { "uint128", 128, 'q', 'u' },
259 { "int128", 128, 'q', 's' },
261 { "ieee_double", 64, 'd', 'f' },
262 { "uint64", 64, 'd', 'u' },
263 { "int64", 64, 'd', 's' },
265 { "ieee_single", 32, 's', 'f' },
266 { "uint32", 32, 's', 'u' },
267 { "int32", 32, 's', 's' },
269 { "ieee_half", 16, 'h', 'f' },
270 { "uint16", 16, 'h', 'u' },
271 { "int16", 16, 'h', 's' },
273 { "uint8", 8, 'b', 'u' },
274 { "int8", 8, 'b', 's' },
277 static const char suf
[] = { 'b', 'h', 's', 'd', 'q' };
280 /* First define types and totals in a whole VL */
281 for (i
= 0; i
< ARRAY_SIZE(vec_lanes
); i
++) {
282 g_string_append_printf(s
,
283 "<vector id=\"%s%c%c\" type=\"%s\" count=\"%d\"/>",
284 name
, vec_lanes
[i
].sz
, vec_lanes
[i
].suffix
,
285 vec_lanes
[i
].gdb_type
, reg_width
/ vec_lanes
[i
].size
);
289 * Now define a union for each size group containing unsigned and
290 * signed and potentially float versions of each size from 128 to
293 for (i
= 0; i
< ARRAY_SIZE(suf
); i
++) {
296 g_string_append_printf(s
, "<union id=\"%sn%c\">", name
, suf
[i
]);
297 for (j
= 0; j
< ARRAY_SIZE(vec_lanes
); j
++) {
298 if (vec_lanes
[j
].size
== bits
) {
299 g_string_append_printf(s
, "<field name=\"%c\" type=\"%s%c%c\"/>",
300 vec_lanes
[j
].suffix
, name
,
301 vec_lanes
[j
].sz
, vec_lanes
[j
].suffix
);
304 g_string_append(s
, "</union>");
307 /* And now the final union of unions */
308 g_string_append_printf(s
, "<union id=\"%s\">", name
);
309 for (i
= ARRAY_SIZE(suf
) - 1; i
>= 0; i
--) {
310 g_string_append_printf(s
, "<field name=\"%c\" type=\"%sn%c\"/>",
311 suf
[i
], name
, suf
[i
]);
313 g_string_append(s
, "</union>");
316 int arm_gen_dynamic_svereg_xml(CPUState
*cs
, int orig_base_reg
)
318 ARMCPU
*cpu
= ARM_CPU(cs
);
319 GString
*s
= g_string_new(NULL
);
320 DynamicGDBXMLInfo
*info
= &cpu
->dyn_svereg_xml
;
321 int reg_width
= cpu
->sve_max_vq
* 128;
322 int pred_width
= cpu
->sve_max_vq
* 16;
323 int base_reg
= orig_base_reg
;
326 g_string_printf(s
, "<?xml version=\"1.0\"?>");
327 g_string_append_printf(s
, "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">");
328 g_string_append_printf(s
, "<feature name=\"org.gnu.gdb.aarch64.sve\">");
330 /* Create the vector union type. */
331 output_vector_union_type(s
, reg_width
, "svev");
333 /* Create the predicate vector type. */
334 g_string_append_printf(s
,
335 "<vector id=\"svep\" type=\"uint8\" count=\"%d\"/>",
338 /* Define the vector registers. */
339 for (i
= 0; i
< 32; i
++) {
340 g_string_append_printf(s
,
341 "<reg name=\"z%d\" bitsize=\"%d\""
342 " regnum=\"%d\" type=\"svev\"/>",
343 i
, reg_width
, base_reg
++);
346 /* fpscr & status registers */
347 g_string_append_printf(s
, "<reg name=\"fpsr\" bitsize=\"32\""
348 " regnum=\"%d\" group=\"float\""
349 " type=\"int\"/>", base_reg
++);
350 g_string_append_printf(s
, "<reg name=\"fpcr\" bitsize=\"32\""
351 " regnum=\"%d\" group=\"float\""
352 " type=\"int\"/>", base_reg
++);
354 /* Define the predicate registers. */
355 for (i
= 0; i
< 16; i
++) {
356 g_string_append_printf(s
,
357 "<reg name=\"p%d\" bitsize=\"%d\""
358 " regnum=\"%d\" type=\"svep\"/>",
359 i
, pred_width
, base_reg
++);
361 g_string_append_printf(s
,
362 "<reg name=\"ffr\" bitsize=\"%d\""
363 " regnum=\"%d\" group=\"vector\""
365 pred_width
, base_reg
++);
367 /* Define the vector length pseudo-register. */
368 g_string_append_printf(s
,
369 "<reg name=\"vg\" bitsize=\"64\""
370 " regnum=\"%d\" type=\"int\"/>",
373 g_string_append_printf(s
, "</feature>");
375 info
->desc
= g_string_free(s
, false);
376 info
->num
= base_reg
- orig_base_reg
;