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