1 /*
2 * s390x 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
21 #include "qemu/osdep.h"
22 #include "cpu.h"
23 #include "s390x-internal.h"
24 #include "exec/exec-all.h"
25 #include "exec/gdbstub.h"
26 #include "gdbstub/helpers.h"
27 #include "qemu/bitops.h"
28 #include "sysemu/hw_accel.h"
29 #include "sysemu/tcg.h"
30
s390_cpu_gdb_read_register(CPUState * cs,GByteArray * mem_buf,int n)31 int s390_cpu_gdb_read_register(CPUState *cs, GByteArray *mem_buf, int n)
32 {
33 CPUS390XState *env = cpu_env(cs);
34
35 switch (n) {
36 case S390_PSWM_REGNUM:
37 return gdb_get_regl(mem_buf, s390_cpu_get_psw_mask(env));
38 case S390_PSWA_REGNUM:
39 return gdb_get_regl(mem_buf, env->psw.addr);
40 case S390_R0_REGNUM ... S390_R15_REGNUM:
41 return gdb_get_regl(mem_buf, env->regs[n - S390_R0_REGNUM]);
42 }
43 return 0;
44 }
45
s390_cpu_gdb_write_register(CPUState * cs,uint8_t * mem_buf,int n)46 int s390_cpu_gdb_write_register(CPUState *cs, uint8_t *mem_buf, int n)
47 {
48 CPUS390XState *env = cpu_env(cs);
49 target_ulong tmpl = ldtul_p(mem_buf);
50
51 switch (n) {
52 case S390_PSWM_REGNUM:
53 s390_cpu_set_psw(env, tmpl, env->psw.addr);
54 break;
55 case S390_PSWA_REGNUM:
56 env->psw.addr = tmpl;
57 break;
58 case S390_R0_REGNUM ... S390_R15_REGNUM:
59 env->regs[n - S390_R0_REGNUM] = tmpl;
60 break;
61 default:
62 return 0;
63 }
64 return 8;
65 }
66
67 /* the values represent the positions in s390-acr.xml */
68 #define S390_A0_REGNUM 0
69 #define S390_A15_REGNUM 15
70
cpu_read_ac_reg(CPUState * cs,GByteArray * buf,int n)71 static int cpu_read_ac_reg(CPUState *cs, GByteArray *buf, int n)
72 {
73 S390CPU *cpu = S390_CPU(cs);
74 CPUS390XState *env = &cpu->env;
75
76 switch (n) {
77 case S390_A0_REGNUM ... S390_A15_REGNUM:
78 return gdb_get_reg32(buf, env->aregs[n]);
79 default:
80 return 0;
81 }
82 }
83
cpu_write_ac_reg(CPUState * cs,uint8_t * mem_buf,int n)84 static int cpu_write_ac_reg(CPUState *cs, uint8_t *mem_buf, int n)
85 {
86 S390CPU *cpu = S390_CPU(cs);
87 CPUS390XState *env = &cpu->env;
88
89 switch (n) {
90 case S390_A0_REGNUM ... S390_A15_REGNUM:
91 env->aregs[n] = ldl_p(mem_buf);
92 cpu_synchronize_post_init(env_cpu(env));
93 return 4;
94 default:
95 return 0;
96 }
97 }
98
99 /* the values represent the positions in s390-fpr.xml */
100 #define S390_FPC_REGNUM 0
101 #define S390_F0_REGNUM 1
102 #define S390_F15_REGNUM 16
103
cpu_read_fp_reg(CPUState * cs,GByteArray * buf,int n)104 static int cpu_read_fp_reg(CPUState *cs, GByteArray *buf, int n)
105 {
106 S390CPU *cpu = S390_CPU(cs);
107 CPUS390XState *env = &cpu->env;
108
109 switch (n) {
110 case S390_FPC_REGNUM:
111 return gdb_get_reg32(buf, env->fpc);
112 case S390_F0_REGNUM ... S390_F15_REGNUM:
113 return gdb_get_reg64(buf, *get_freg(env, n - S390_F0_REGNUM));
114 default:
115 return 0;
116 }
117 }
118
cpu_write_fp_reg(CPUState * cs,uint8_t * mem_buf,int n)119 static int cpu_write_fp_reg(CPUState *cs, uint8_t *mem_buf, int n)
120 {
121 S390CPU *cpu = S390_CPU(cs);
122 CPUS390XState *env = &cpu->env;
123
124 switch (n) {
125 case S390_FPC_REGNUM:
126 env->fpc = ldl_p(mem_buf);
127 return 4;
128 case S390_F0_REGNUM ... S390_F15_REGNUM:
129 *get_freg(env, n - S390_F0_REGNUM) = ldtul_p(mem_buf);
130 return 8;
131 default:
132 return 0;
133 }
134 }
135
136 /* the values represent the positions in s390-vx.xml */
137 #define S390_V0L_REGNUM 0
138 #define S390_V15L_REGNUM 15
139 #define S390_V16_REGNUM 16
140 #define S390_V31_REGNUM 31
141
cpu_read_vreg(CPUState * cs,GByteArray * buf,int n)142 static int cpu_read_vreg(CPUState *cs, GByteArray *buf, int n)
143 {
144 S390CPU *cpu = S390_CPU(cs);
145 CPUS390XState *env = &cpu->env;
146 int ret;
147
148 switch (n) {
149 case S390_V0L_REGNUM ... S390_V15L_REGNUM:
150 ret = gdb_get_reg64(buf, env->vregs[n][1]);
151 break;
152 case S390_V16_REGNUM ... S390_V31_REGNUM:
153 ret = gdb_get_reg64(buf, env->vregs[n][0]);
154 ret += gdb_get_reg64(buf, env->vregs[n][1]);
155 break;
156 default:
157 ret = 0;
158 }
159
160 return ret;
161 }
162
cpu_write_vreg(CPUState * cs,uint8_t * mem_buf,int n)163 static int cpu_write_vreg(CPUState *cs, uint8_t *mem_buf, int n)
164 {
165 S390CPU *cpu = S390_CPU(cs);
166 CPUS390XState *env = &cpu->env;
167
168 switch (n) {
169 case S390_V0L_REGNUM ... S390_V15L_REGNUM:
170 env->vregs[n][1] = ldtul_p(mem_buf + 8);
171 return 8;
172 case S390_V16_REGNUM ... S390_V31_REGNUM:
173 env->vregs[n][0] = ldtul_p(mem_buf);
174 env->vregs[n][1] = ldtul_p(mem_buf + 8);
175 return 16;
176 default:
177 return 0;
178 }
179 }
180
181 /* the values represent the positions in s390-cr.xml */
182 #define S390_C0_REGNUM 0
183 #define S390_C15_REGNUM 15
184
185 #ifndef CONFIG_USER_ONLY
cpu_read_c_reg(CPUState * cs,GByteArray * buf,int n)186 static int cpu_read_c_reg(CPUState *cs, GByteArray *buf, int n)
187 {
188 S390CPU *cpu = S390_CPU(cs);
189 CPUS390XState *env = &cpu->env;
190
191 switch (n) {
192 case S390_C0_REGNUM ... S390_C15_REGNUM:
193 return gdb_get_regl(buf, env->cregs[n]);
194 default:
195 return 0;
196 }
197 }
198
cpu_write_c_reg(CPUState * cs,uint8_t * mem_buf,int n)199 static int cpu_write_c_reg(CPUState *cs, uint8_t *mem_buf, int n)
200 {
201 S390CPU *cpu = S390_CPU(cs);
202 CPUS390XState *env = &cpu->env;
203
204 switch (n) {
205 case S390_C0_REGNUM ... S390_C15_REGNUM:
206 env->cregs[n] = ldtul_p(mem_buf);
207 if (tcg_enabled()) {
208 tlb_flush(env_cpu(env));
209 }
210 cpu_synchronize_post_init(env_cpu(env));
211 return 8;
212 default:
213 return 0;
214 }
215 }
216
217 /* the values represent the positions in s390-virt.xml */
218 #define S390_VIRT_CKC_REGNUM 0
219 #define S390_VIRT_CPUTM_REGNUM 1
220 #define S390_VIRT_BEA_REGNUM 2
221 #define S390_VIRT_PREFIX_REGNUM 3
222
cpu_read_virt_reg(CPUState * cs,GByteArray * mem_buf,int n)223 static int cpu_read_virt_reg(CPUState *cs, GByteArray *mem_buf, int n)
224 {
225 S390CPU *cpu = S390_CPU(cs);
226 CPUS390XState *env = &cpu->env;
227
228 switch (n) {
229 case S390_VIRT_CKC_REGNUM:
230 return gdb_get_regl(mem_buf, env->ckc);
231 case S390_VIRT_CPUTM_REGNUM:
232 return gdb_get_regl(mem_buf, env->cputm);
233 case S390_VIRT_BEA_REGNUM:
234 return gdb_get_regl(mem_buf, env->gbea);
235 case S390_VIRT_PREFIX_REGNUM:
236 return gdb_get_regl(mem_buf, env->psa);
237 default:
238 return 0;
239 }
240 }
241
cpu_write_virt_reg(CPUState * cs,uint8_t * mem_buf,int n)242 static int cpu_write_virt_reg(CPUState *cs, uint8_t *mem_buf, int n)
243 {
244 S390CPU *cpu = S390_CPU(cs);
245 CPUS390XState *env = &cpu->env;
246
247 switch (n) {
248 case S390_VIRT_CKC_REGNUM:
249 env->ckc = ldtul_p(mem_buf);
250 cpu_synchronize_post_init(cs);
251 return 8;
252 case S390_VIRT_CPUTM_REGNUM:
253 env->cputm = ldtul_p(mem_buf);
254 cpu_synchronize_post_init(cs);
255 return 8;
256 case S390_VIRT_BEA_REGNUM:
257 env->gbea = ldtul_p(mem_buf);
258 cpu_synchronize_post_init(cs);
259 return 8;
260 case S390_VIRT_PREFIX_REGNUM:
261 env->psa = ldtul_p(mem_buf);
262 cpu_synchronize_post_init(cs);
263 return 8;
264 default:
265 return 0;
266 }
267 }
268
269 /* the values represent the positions in s390-virt-kvm.xml */
270 #define S390_VIRT_KVM_PP_REGNUM 0
271 #define S390_VIRT_KVM_PFT_REGNUM 1
272 #define S390_VIRT_KVM_PFS_REGNUM 2
273 #define S390_VIRT_KVM_PFC_REGNUM 3
274
cpu_read_virt_kvm_reg(CPUState * cs,GByteArray * mem_buf,int n)275 static int cpu_read_virt_kvm_reg(CPUState *cs, GByteArray *mem_buf, int n)
276 {
277 S390CPU *cpu = S390_CPU(cs);
278 CPUS390XState *env = &cpu->env;
279
280 switch (n) {
281 case S390_VIRT_KVM_PP_REGNUM:
282 return gdb_get_regl(mem_buf, env->pp);
283 case S390_VIRT_KVM_PFT_REGNUM:
284 return gdb_get_regl(mem_buf, env->pfault_token);
285 case S390_VIRT_KVM_PFS_REGNUM:
286 return gdb_get_regl(mem_buf, env->pfault_select);
287 case S390_VIRT_KVM_PFC_REGNUM:
288 return gdb_get_regl(mem_buf, env->pfault_compare);
289 default:
290 return 0;
291 }
292 }
293
cpu_write_virt_kvm_reg(CPUState * cs,uint8_t * mem_buf,int n)294 static int cpu_write_virt_kvm_reg(CPUState *cs, uint8_t *mem_buf, int n)
295 {
296 S390CPU *cpu = S390_CPU(cs);
297 CPUS390XState *env = &cpu->env;
298
299 switch (n) {
300 case S390_VIRT_KVM_PP_REGNUM:
301 env->pp = ldtul_p(mem_buf);
302 cpu_synchronize_post_init(env_cpu(env));
303 return 8;
304 case S390_VIRT_KVM_PFT_REGNUM:
305 env->pfault_token = ldtul_p(mem_buf);
306 cpu_synchronize_post_init(env_cpu(env));
307 return 8;
308 case S390_VIRT_KVM_PFS_REGNUM:
309 env->pfault_select = ldtul_p(mem_buf);
310 cpu_synchronize_post_init(env_cpu(env));
311 return 8;
312 case S390_VIRT_KVM_PFC_REGNUM:
313 env->pfault_compare = ldtul_p(mem_buf);
314 cpu_synchronize_post_init(env_cpu(env));
315 return 8;
316 default:
317 return 0;
318 }
319 }
320 #endif
321
322 /* the values represent the positions in s390-gs.xml */
323 #define S390_GS_RESERVED_REGNUM 0
324 #define S390_GS_GSD_REGNUM 1
325 #define S390_GS_GSSM_REGNUM 2
326 #define S390_GS_GSEPLA_REGNUM 3
327
cpu_read_gs_reg(CPUState * cs,GByteArray * buf,int n)328 static int cpu_read_gs_reg(CPUState *cs, GByteArray *buf, int n)
329 {
330 S390CPU *cpu = S390_CPU(cs);
331 CPUS390XState *env = &cpu->env;
332
333 return gdb_get_regl(buf, env->gscb[n]);
334 }
335
cpu_write_gs_reg(CPUState * cs,uint8_t * mem_buf,int n)336 static int cpu_write_gs_reg(CPUState *cs, uint8_t *mem_buf, int n)
337 {
338 S390CPU *cpu = S390_CPU(cs);
339 CPUS390XState *env = &cpu->env;
340
341 env->gscb[n] = ldtul_p(mem_buf);
342 cpu_synchronize_post_init(env_cpu(env));
343 return 8;
344 }
345
s390_cpu_gdb_init(CPUState * cs)346 void s390_cpu_gdb_init(CPUState *cs)
347 {
348 gdb_register_coprocessor(cs, cpu_read_ac_reg,
349 cpu_write_ac_reg,
350 gdb_find_static_feature("s390-acr.xml"), 0);
351
352 gdb_register_coprocessor(cs, cpu_read_fp_reg,
353 cpu_write_fp_reg,
354 gdb_find_static_feature("s390-fpr.xml"), 0);
355
356 gdb_register_coprocessor(cs, cpu_read_vreg,
357 cpu_write_vreg,
358 gdb_find_static_feature("s390-vx.xml"), 0);
359
360 gdb_register_coprocessor(cs, cpu_read_gs_reg,
361 cpu_write_gs_reg,
362 gdb_find_static_feature("s390-gs.xml"), 0);
363
364 #ifndef CONFIG_USER_ONLY
365 gdb_register_coprocessor(cs, cpu_read_c_reg,
366 cpu_write_c_reg,
367 gdb_find_static_feature("s390-cr.xml"), 0);
368
369 gdb_register_coprocessor(cs, cpu_read_virt_reg,
370 cpu_write_virt_reg,
371 gdb_find_static_feature("s390-virt.xml"), 0);
372
373 if (kvm_enabled()) {
374 gdb_register_coprocessor(cs, cpu_read_virt_kvm_reg,
375 cpu_write_virt_kvm_reg,
376 gdb_find_static_feature("s390-virt-kvm.xml"),
377 0);
378 }
379 #endif
380 }
381