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(CPUState
*cs
, GByteArray
*buf
, int reg
)
77 ARMCPU
*cpu
= ARM_CPU(cs
);
78 CPUARMState
*env
= &cpu
->env
;
83 /* 128 bit FP register - quads are in LE order */
84 uint64_t *q
= aa64_vfp_qreg(env
, reg
);
85 return gdb_get_reg128(buf
, q
[1], q
[0]);
89 return gdb_get_reg32(buf
, vfp_get_fpsr(env
));
92 return gdb_get_reg32(buf
, vfp_get_fpcr(env
));
98 int aarch64_gdb_set_fpu_reg(CPUState
*cs
, uint8_t *buf
, int reg
)
100 ARMCPU
*cpu
= ARM_CPU(cs
);
101 CPUARMState
*env
= &cpu
->env
;
105 /* 128 bit FP register */
107 uint64_t *q
= aa64_vfp_qreg(env
, reg
);
108 q
[0] = ldq_le_p(buf
);
109 q
[1] = ldq_le_p(buf
+ 8);
114 vfp_set_fpsr(env
, ldl_p(buf
));
118 vfp_set_fpcr(env
, ldl_p(buf
));
125 int aarch64_gdb_get_sve_reg(CPUState
*cs
, GByteArray
*buf
, int reg
)
127 ARMCPU
*cpu
= ARM_CPU(cs
);
128 CPUARMState
*env
= &cpu
->env
;
131 /* The first 32 registers are the zregs */
135 for (vq
= 0; vq
< cpu
->sve_max_vq
; vq
++) {
136 len
+= gdb_get_reg128(buf
,
137 env
->vfp
.zregs
[reg
].d
[vq
* 2 + 1],
138 env
->vfp
.zregs
[reg
].d
[vq
* 2]);
143 return gdb_get_reg32(buf
, vfp_get_fpsr(env
));
145 return gdb_get_reg32(buf
, vfp_get_fpcr(env
));
146 /* then 16 predicates and the ffr */
151 for (vq
= 0; vq
< cpu
->sve_max_vq
; vq
= vq
+ 4) {
152 len
+= gdb_get_reg64(buf
, env
->vfp
.pregs
[preg
].p
[vq
/ 4]);
159 * We report in Vector Granules (VG) which is 64bit in a Z reg
160 * while the ZCR works in Vector Quads (VQ) which is 128bit chunks.
162 int vq
= sve_vqm1_for_el(env
, arm_current_el(env
)) + 1;
163 return gdb_get_reg64(buf
, vq
* 2);
166 /* gdbstub asked for something out our range */
167 qemu_log_mask(LOG_UNIMP
, "%s: out of range register %d", __func__
, reg
);
174 int aarch64_gdb_set_sve_reg(CPUState
*cs
, uint8_t *buf
, int reg
)
176 ARMCPU
*cpu
= ARM_CPU(cs
);
177 CPUARMState
*env
= &cpu
->env
;
179 /* The first 32 registers are the zregs */
181 /* The first 32 registers are the zregs */
185 uint64_t *p
= (uint64_t *) buf
;
186 for (vq
= 0; vq
< cpu
->sve_max_vq
; vq
++) {
187 env
->vfp
.zregs
[reg
].d
[vq
* 2 + 1] = *p
++;
188 env
->vfp
.zregs
[reg
].d
[vq
* 2] = *p
++;
194 vfp_set_fpsr(env
, *(uint32_t *)buf
);
197 vfp_set_fpcr(env
, *(uint32_t *)buf
);
203 uint64_t *p
= (uint64_t *) buf
;
204 for (vq
= 0; vq
< cpu
->sve_max_vq
; vq
= vq
+ 4) {
205 env
->vfp
.pregs
[preg
].p
[vq
/ 4] = *p
++;
211 /* cannot set vg via gdbstub */
214 /* gdbstub asked for something out our range */
221 int aarch64_gdb_get_pauth_reg(CPUState
*cs
, GByteArray
*buf
, int reg
)
223 ARMCPU
*cpu
= ARM_CPU(cs
);
224 CPUARMState
*env
= &cpu
->env
;
227 case 0: /* pauth_dmask */
228 case 1: /* pauth_cmask */
229 case 2: /* pauth_dmask_high */
230 case 3: /* pauth_cmask_high */
232 * Note that older versions of this feature only contained
233 * pauth_{d,c}mask, for use with Linux user processes, and
234 * thus exclusively in the low half of the address space.
236 * To support system mode, and to debug kernels, two new regs
237 * were added to cover the high half of the address space.
238 * For the purpose of pauth_ptr_mask, we can use any well-formed
239 * address within the address space half -- here, 0 and -1.
242 bool is_data
= !(reg
& 1);
243 bool is_high
= reg
& 2;
244 ARMMMUIdx mmu_idx
= arm_stage1_mmu_idx(env
);
245 ARMVAParameters param
;
247 param
= aa64_va_parameters(env
, -is_high
, mmu_idx
, is_data
, false);
248 return gdb_get_reg64(buf
, pauth_ptr_mask(param
));
255 int aarch64_gdb_set_pauth_reg(CPUState
*cs
, uint8_t *buf
, int reg
)
257 /* All pseudo registers are read-only. */
261 static void output_vector_union_type(GDBFeatureBuilder
*builder
, int reg_width
,
265 const char *gdb_type
;
270 static const struct TypeSize vec_lanes
[] = {
272 { "uint128", 128, 'q', 'u' },
273 { "int128", 128, 'q', 's' },
275 { "ieee_double", 64, 'd', 'f' },
276 { "uint64", 64, 'd', 'u' },
277 { "int64", 64, 'd', 's' },
279 { "ieee_single", 32, 's', 'f' },
280 { "uint32", 32, 's', 'u' },
281 { "int32", 32, 's', 's' },
283 { "ieee_half", 16, 'h', 'f' },
284 { "uint16", 16, 'h', 'u' },
285 { "int16", 16, 'h', 's' },
287 { "uint8", 8, 'b', 'u' },
288 { "int8", 8, 'b', 's' },
291 static const char suf
[] = { 'b', 'h', 's', 'd', 'q' };
294 /* First define types and totals in a whole VL */
295 for (i
= 0; i
< ARRAY_SIZE(vec_lanes
); i
++) {
296 gdb_feature_builder_append_tag(
297 builder
, "<vector id=\"%s%c%c\" type=\"%s\" count=\"%d\"/>",
298 name
, vec_lanes
[i
].sz
, vec_lanes
[i
].suffix
,
299 vec_lanes
[i
].gdb_type
, reg_width
/ vec_lanes
[i
].size
);
303 * Now define a union for each size group containing unsigned and
304 * signed and potentially float versions of each size from 128 to
307 for (i
= 0; i
< ARRAY_SIZE(suf
); i
++) {
310 gdb_feature_builder_append_tag(builder
, "<union id=\"%sn%c\">",
312 for (j
= 0; j
< ARRAY_SIZE(vec_lanes
); j
++) {
313 if (vec_lanes
[j
].size
== bits
) {
314 gdb_feature_builder_append_tag(
315 builder
, "<field name=\"%c\" type=\"%s%c%c\"/>",
316 vec_lanes
[j
].suffix
, name
,
317 vec_lanes
[j
].sz
, vec_lanes
[j
].suffix
);
320 gdb_feature_builder_append_tag(builder
, "</union>");
323 /* And now the final union of unions */
324 gdb_feature_builder_append_tag(builder
, "<union id=\"%s\">", name
);
325 for (i
= ARRAY_SIZE(suf
) - 1; i
>= 0; i
--) {
326 gdb_feature_builder_append_tag(builder
,
327 "<field name=\"%c\" type=\"%sn%c\"/>",
328 suf
[i
], name
, suf
[i
]);
330 gdb_feature_builder_append_tag(builder
, "</union>");
333 GDBFeature
*arm_gen_dynamic_svereg_feature(CPUState
*cs
, int base_reg
)
335 ARMCPU
*cpu
= ARM_CPU(cs
);
336 int reg_width
= cpu
->sve_max_vq
* 128;
337 int pred_width
= cpu
->sve_max_vq
* 16;
338 GDBFeatureBuilder builder
;
343 gdb_feature_builder_init(&builder
, &cpu
->dyn_svereg_feature
.desc
,
344 "org.gnu.gdb.aarch64.sve", "sve-registers.xml",
347 /* Create the vector union type. */
348 output_vector_union_type(&builder
, reg_width
, "svev");
350 /* Create the predicate vector type. */
351 gdb_feature_builder_append_tag(
352 &builder
, "<vector id=\"svep\" type=\"uint8\" count=\"%d\"/>",
355 /* Define the vector registers. */
356 for (i
= 0; i
< 32; i
++) {
357 name
= g_strdup_printf("z%d", i
);
358 gdb_feature_builder_append_reg(&builder
, name
, reg_width
, reg
++,
362 /* fpscr & status registers */
363 gdb_feature_builder_append_reg(&builder
, "fpsr", 32, reg
++,
365 gdb_feature_builder_append_reg(&builder
, "fpcr", 32, reg
++,
368 /* Define the predicate registers. */
369 for (i
= 0; i
< 16; i
++) {
370 name
= g_strdup_printf("p%d", i
);
371 gdb_feature_builder_append_reg(&builder
, name
, pred_width
, reg
++,
374 gdb_feature_builder_append_reg(&builder
, "ffr", pred_width
, reg
++,
377 /* Define the vector length pseudo-register. */
378 gdb_feature_builder_append_reg(&builder
, "vg", 64, reg
++, "int", NULL
);
380 gdb_feature_builder_end(&builder
);
382 return &cpu
->dyn_svereg_feature
.desc
;