xref: /openbmc/qemu/target/s390x/gdbstub.c (revision f6e33708)
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 
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 
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 /* total number of registers in s390-acr.xml */
71 #define S390_NUM_AC_REGS 16
72 
73 static int cpu_read_ac_reg(CPUS390XState *env, GByteArray *buf, int n)
74 {
75     switch (n) {
76     case S390_A0_REGNUM ... S390_A15_REGNUM:
77         return gdb_get_reg32(buf, env->aregs[n]);
78     default:
79         return 0;
80     }
81 }
82 
83 static int cpu_write_ac_reg(CPUS390XState *env, uint8_t *mem_buf, int n)
84 {
85     switch (n) {
86     case S390_A0_REGNUM ... S390_A15_REGNUM:
87         env->aregs[n] = ldl_p(mem_buf);
88         cpu_synchronize_post_init(env_cpu(env));
89         return 4;
90     default:
91         return 0;
92     }
93 }
94 
95 /* the values represent the positions in s390-fpr.xml */
96 #define S390_FPC_REGNUM 0
97 #define S390_F0_REGNUM 1
98 #define S390_F15_REGNUM 16
99 /* total number of registers in s390-fpr.xml */
100 #define S390_NUM_FP_REGS 17
101 
102 static int cpu_read_fp_reg(CPUS390XState *env, GByteArray *buf, int n)
103 {
104     switch (n) {
105     case S390_FPC_REGNUM:
106         return gdb_get_reg32(buf, env->fpc);
107     case S390_F0_REGNUM ... S390_F15_REGNUM:
108         return gdb_get_reg64(buf, *get_freg(env, n - S390_F0_REGNUM));
109     default:
110         return 0;
111     }
112 }
113 
114 static int cpu_write_fp_reg(CPUS390XState *env, uint8_t *mem_buf, int n)
115 {
116     switch (n) {
117     case S390_FPC_REGNUM:
118         env->fpc = ldl_p(mem_buf);
119         return 4;
120     case S390_F0_REGNUM ... S390_F15_REGNUM:
121         *get_freg(env, n - S390_F0_REGNUM) = ldtul_p(mem_buf);
122         return 8;
123     default:
124         return 0;
125     }
126 }
127 
128 /* the values represent the positions in s390-vx.xml */
129 #define S390_V0L_REGNUM 0
130 #define S390_V15L_REGNUM 15
131 #define S390_V16_REGNUM 16
132 #define S390_V31_REGNUM 31
133 /* total number of registers in s390-vx.xml */
134 #define S390_NUM_VREGS 32
135 
136 static int cpu_read_vreg(CPUS390XState *env, GByteArray *buf, int n)
137 {
138     int ret;
139 
140     switch (n) {
141     case S390_V0L_REGNUM ... S390_V15L_REGNUM:
142         ret = gdb_get_reg64(buf, env->vregs[n][1]);
143         break;
144     case S390_V16_REGNUM ... S390_V31_REGNUM:
145         ret = gdb_get_reg64(buf, env->vregs[n][0]);
146         ret += gdb_get_reg64(buf, env->vregs[n][1]);
147         break;
148     default:
149         ret = 0;
150     }
151 
152     return ret;
153 }
154 
155 static int cpu_write_vreg(CPUS390XState *env, uint8_t *mem_buf, int n)
156 {
157     switch (n) {
158     case S390_V0L_REGNUM ... S390_V15L_REGNUM:
159         env->vregs[n][1] = ldtul_p(mem_buf + 8);
160         return 8;
161     case S390_V16_REGNUM ... S390_V31_REGNUM:
162         env->vregs[n][0] = ldtul_p(mem_buf);
163         env->vregs[n][1] = ldtul_p(mem_buf + 8);
164         return 16;
165     default:
166         return 0;
167     }
168 }
169 
170 /* the values represent the positions in s390-cr.xml */
171 #define S390_C0_REGNUM 0
172 #define S390_C15_REGNUM 15
173 /* total number of registers in s390-cr.xml */
174 #define S390_NUM_C_REGS 16
175 
176 #ifndef CONFIG_USER_ONLY
177 static int cpu_read_c_reg(CPUS390XState *env, GByteArray *buf, int n)
178 {
179     switch (n) {
180     case S390_C0_REGNUM ... S390_C15_REGNUM:
181         return gdb_get_regl(buf, env->cregs[n]);
182     default:
183         return 0;
184     }
185 }
186 
187 static int cpu_write_c_reg(CPUS390XState *env, uint8_t *mem_buf, int n)
188 {
189     switch (n) {
190     case S390_C0_REGNUM ... S390_C15_REGNUM:
191         env->cregs[n] = ldtul_p(mem_buf);
192         if (tcg_enabled()) {
193             tlb_flush(env_cpu(env));
194         }
195         cpu_synchronize_post_init(env_cpu(env));
196         return 8;
197     default:
198         return 0;
199     }
200 }
201 
202 /* the values represent the positions in s390-virt.xml */
203 #define S390_VIRT_CKC_REGNUM    0
204 #define S390_VIRT_CPUTM_REGNUM  1
205 #define S390_VIRT_BEA_REGNUM    2
206 #define S390_VIRT_PREFIX_REGNUM 3
207 /* total number of registers in s390-virt.xml */
208 #define S390_NUM_VIRT_REGS 4
209 
210 static int cpu_read_virt_reg(CPUS390XState *env, GByteArray *mem_buf, int n)
211 {
212     switch (n) {
213     case S390_VIRT_CKC_REGNUM:
214         return gdb_get_regl(mem_buf, env->ckc);
215     case S390_VIRT_CPUTM_REGNUM:
216         return gdb_get_regl(mem_buf, env->cputm);
217     case S390_VIRT_BEA_REGNUM:
218         return gdb_get_regl(mem_buf, env->gbea);
219     case S390_VIRT_PREFIX_REGNUM:
220         return gdb_get_regl(mem_buf, env->psa);
221     default:
222         return 0;
223     }
224 }
225 
226 static int cpu_write_virt_reg(CPUS390XState *env, uint8_t *mem_buf, int n)
227 {
228     switch (n) {
229     case S390_VIRT_CKC_REGNUM:
230         env->ckc = ldtul_p(mem_buf);
231         cpu_synchronize_post_init(env_cpu(env));
232         return 8;
233     case S390_VIRT_CPUTM_REGNUM:
234         env->cputm = ldtul_p(mem_buf);
235         cpu_synchronize_post_init(env_cpu(env));
236         return 8;
237     case S390_VIRT_BEA_REGNUM:
238         env->gbea = ldtul_p(mem_buf);
239         cpu_synchronize_post_init(env_cpu(env));
240         return 8;
241     case S390_VIRT_PREFIX_REGNUM:
242         env->psa = ldtul_p(mem_buf);
243         cpu_synchronize_post_init(env_cpu(env));
244         return 8;
245     default:
246         return 0;
247     }
248 }
249 
250 /* the values represent the positions in s390-virt-kvm.xml */
251 #define S390_VIRT_KVM_PP_REGNUM     0
252 #define S390_VIRT_KVM_PFT_REGNUM    1
253 #define S390_VIRT_KVM_PFS_REGNUM    2
254 #define S390_VIRT_KVM_PFC_REGNUM    3
255 /* total number of registers in s390-virt-kvm.xml */
256 #define S390_NUM_VIRT_KVM_REGS 4
257 
258 static int cpu_read_virt_kvm_reg(CPUS390XState *env, GByteArray *mem_buf, int n)
259 {
260     switch (n) {
261     case S390_VIRT_KVM_PP_REGNUM:
262         return gdb_get_regl(mem_buf, env->pp);
263     case S390_VIRT_KVM_PFT_REGNUM:
264         return gdb_get_regl(mem_buf, env->pfault_token);
265     case S390_VIRT_KVM_PFS_REGNUM:
266         return gdb_get_regl(mem_buf, env->pfault_select);
267     case S390_VIRT_KVM_PFC_REGNUM:
268         return gdb_get_regl(mem_buf, env->pfault_compare);
269     default:
270         return 0;
271     }
272 }
273 
274 static int cpu_write_virt_kvm_reg(CPUS390XState *env, uint8_t *mem_buf, int n)
275 {
276     switch (n) {
277     case S390_VIRT_KVM_PP_REGNUM:
278         env->pp = ldtul_p(mem_buf);
279         cpu_synchronize_post_init(env_cpu(env));
280         return 8;
281     case S390_VIRT_KVM_PFT_REGNUM:
282         env->pfault_token = ldtul_p(mem_buf);
283         cpu_synchronize_post_init(env_cpu(env));
284         return 8;
285     case S390_VIRT_KVM_PFS_REGNUM:
286         env->pfault_select = ldtul_p(mem_buf);
287         cpu_synchronize_post_init(env_cpu(env));
288         return 8;
289     case S390_VIRT_KVM_PFC_REGNUM:
290         env->pfault_compare = ldtul_p(mem_buf);
291         cpu_synchronize_post_init(env_cpu(env));
292         return 8;
293     default:
294         return 0;
295     }
296 }
297 #endif
298 
299 /* the values represent the positions in s390-gs.xml */
300 #define S390_GS_RESERVED_REGNUM 0
301 #define S390_GS_GSD_REGNUM      1
302 #define S390_GS_GSSM_REGNUM     2
303 #define S390_GS_GSEPLA_REGNUM   3
304 /* total number of registers in s390-gs.xml */
305 #define S390_NUM_GS_REGS 4
306 
307 static int cpu_read_gs_reg(CPUS390XState *env, GByteArray *buf, int n)
308 {
309     return gdb_get_regl(buf, env->gscb[n]);
310 }
311 
312 static int cpu_write_gs_reg(CPUS390XState *env, uint8_t *mem_buf, int n)
313 {
314     env->gscb[n] = ldtul_p(mem_buf);
315     cpu_synchronize_post_init(env_cpu(env));
316     return 8;
317 }
318 
319 void s390_cpu_gdb_init(CPUState *cs)
320 {
321     gdb_register_coprocessor(cs, cpu_read_ac_reg,
322                              cpu_write_ac_reg,
323                              S390_NUM_AC_REGS, "s390-acr.xml", 0);
324 
325     gdb_register_coprocessor(cs, cpu_read_fp_reg,
326                              cpu_write_fp_reg,
327                              S390_NUM_FP_REGS, "s390-fpr.xml", 0);
328 
329     gdb_register_coprocessor(cs, cpu_read_vreg,
330                              cpu_write_vreg,
331                              S390_NUM_VREGS, "s390-vx.xml", 0);
332 
333     gdb_register_coprocessor(cs, cpu_read_gs_reg,
334                              cpu_write_gs_reg,
335                              S390_NUM_GS_REGS, "s390-gs.xml", 0);
336 
337 #ifndef CONFIG_USER_ONLY
338     gdb_register_coprocessor(cs, cpu_read_c_reg,
339                              cpu_write_c_reg,
340                              S390_NUM_C_REGS, "s390-cr.xml", 0);
341 
342     gdb_register_coprocessor(cs, cpu_read_virt_reg,
343                              cpu_write_virt_reg,
344                              S390_NUM_VIRT_REGS, "s390-virt.xml", 0);
345 
346     if (kvm_enabled()) {
347         gdb_register_coprocessor(cs, cpu_read_virt_kvm_reg,
348                                  cpu_write_virt_kvm_reg,
349                                  S390_NUM_VIRT_KVM_REGS, "s390-virt-kvm.xml",
350                                  0);
351     }
352 #endif
353 }
354