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 "gdbstub/helpers.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 ARMMMUIdx mmu_idx
= arm_stage1_mmu_idx(env
);
234 ARMVAParameters param
;
236 param
= aa64_va_parameters(env
, -is_high
, mmu_idx
, is_data
);
237 return gdb_get_reg64(buf
, pauth_ptr_mask(param
));
244 int aarch64_gdb_set_pauth_reg(CPUARMState
*env
, uint8_t *buf
, int reg
)
246 /* All pseudo registers are read-only. */
250 static void output_vector_union_type(GString
*s
, int reg_width
,
254 const char *gdb_type
;
259 static const struct TypeSize vec_lanes
[] = {
261 { "uint128", 128, 'q', 'u' },
262 { "int128", 128, 'q', 's' },
264 { "ieee_double", 64, 'd', 'f' },
265 { "uint64", 64, 'd', 'u' },
266 { "int64", 64, 'd', 's' },
268 { "ieee_single", 32, 's', 'f' },
269 { "uint32", 32, 's', 'u' },
270 { "int32", 32, 's', 's' },
272 { "ieee_half", 16, 'h', 'f' },
273 { "uint16", 16, 'h', 'u' },
274 { "int16", 16, 'h', 's' },
276 { "uint8", 8, 'b', 'u' },
277 { "int8", 8, 'b', 's' },
280 static const char suf
[] = { 'b', 'h', 's', 'd', 'q' };
283 /* First define types and totals in a whole VL */
284 for (i
= 0; i
< ARRAY_SIZE(vec_lanes
); i
++) {
285 g_string_append_printf(s
,
286 "<vector id=\"%s%c%c\" type=\"%s\" count=\"%d\"/>",
287 name
, vec_lanes
[i
].sz
, vec_lanes
[i
].suffix
,
288 vec_lanes
[i
].gdb_type
, reg_width
/ vec_lanes
[i
].size
);
292 * Now define a union for each size group containing unsigned and
293 * signed and potentially float versions of each size from 128 to
296 for (i
= 0; i
< ARRAY_SIZE(suf
); i
++) {
299 g_string_append_printf(s
, "<union id=\"%sn%c\">", name
, suf
[i
]);
300 for (j
= 0; j
< ARRAY_SIZE(vec_lanes
); j
++) {
301 if (vec_lanes
[j
].size
== bits
) {
302 g_string_append_printf(s
, "<field name=\"%c\" type=\"%s%c%c\"/>",
303 vec_lanes
[j
].suffix
, name
,
304 vec_lanes
[j
].sz
, vec_lanes
[j
].suffix
);
307 g_string_append(s
, "</union>");
310 /* And now the final union of unions */
311 g_string_append_printf(s
, "<union id=\"%s\">", name
);
312 for (i
= ARRAY_SIZE(suf
) - 1; i
>= 0; i
--) {
313 g_string_append_printf(s
, "<field name=\"%c\" type=\"%sn%c\"/>",
314 suf
[i
], name
, suf
[i
]);
316 g_string_append(s
, "</union>");
319 int arm_gen_dynamic_svereg_xml(CPUState
*cs
, int orig_base_reg
)
321 ARMCPU
*cpu
= ARM_CPU(cs
);
322 GString
*s
= g_string_new(NULL
);
323 DynamicGDBXMLInfo
*info
= &cpu
->dyn_svereg_xml
;
324 int reg_width
= cpu
->sve_max_vq
* 128;
325 int pred_width
= cpu
->sve_max_vq
* 16;
326 int base_reg
= orig_base_reg
;
329 g_string_printf(s
, "<?xml version=\"1.0\"?>");
330 g_string_append_printf(s
, "<!DOCTYPE target SYSTEM \"gdb-target.dtd\">");
331 g_string_append_printf(s
, "<feature name=\"org.gnu.gdb.aarch64.sve\">");
333 /* Create the vector union type. */
334 output_vector_union_type(s
, reg_width
, "svev");
336 /* Create the predicate vector type. */
337 g_string_append_printf(s
,
338 "<vector id=\"svep\" type=\"uint8\" count=\"%d\"/>",
341 /* Define the vector registers. */
342 for (i
= 0; i
< 32; i
++) {
343 g_string_append_printf(s
,
344 "<reg name=\"z%d\" bitsize=\"%d\""
345 " regnum=\"%d\" type=\"svev\"/>",
346 i
, reg_width
, base_reg
++);
349 /* fpscr & status registers */
350 g_string_append_printf(s
, "<reg name=\"fpsr\" bitsize=\"32\""
351 " regnum=\"%d\" group=\"float\""
352 " type=\"int\"/>", base_reg
++);
353 g_string_append_printf(s
, "<reg name=\"fpcr\" bitsize=\"32\""
354 " regnum=\"%d\" group=\"float\""
355 " type=\"int\"/>", base_reg
++);
357 /* Define the predicate registers. */
358 for (i
= 0; i
< 16; i
++) {
359 g_string_append_printf(s
,
360 "<reg name=\"p%d\" bitsize=\"%d\""
361 " regnum=\"%d\" type=\"svep\"/>",
362 i
, pred_width
, base_reg
++);
364 g_string_append_printf(s
,
365 "<reg name=\"ffr\" bitsize=\"%d\""
366 " regnum=\"%d\" group=\"vector\""
368 pred_width
, base_reg
++);
370 /* Define the vector length pseudo-register. */
371 g_string_append_printf(s
,
372 "<reg name=\"vg\" bitsize=\"64\""
373 " regnum=\"%d\" type=\"int\"/>",
376 g_string_append_printf(s
, "</feature>");
378 info
->desc
= g_string_free(s
, false);
379 info
->num
= base_reg
- orig_base_reg
;