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