s390: Add a hypercall registration interface.
[sdk/emulator/qemu.git] / target-s390x / misc_helper.c
1 /*
2  *  S/390 misc helper routines
3  *
4  *  Copyright (c) 2009 Ulrich Hecht
5  *  Copyright (c) 2009 Alexander Graf
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
21 #include "cpu.h"
22 #include "exec/memory.h"
23 #include "qemu/host-utils.h"
24 #include "helper.h"
25 #include <string.h>
26 #include "sysemu/kvm.h"
27 #include "qemu/timer.h"
28 #ifdef CONFIG_KVM
29 #include <linux/kvm.h>
30 #endif
31
32 #if !defined(CONFIG_USER_ONLY)
33 #include "exec/softmmu_exec.h"
34 #include "sysemu/sysemu.h"
35 #endif
36
37 /* #define DEBUG_HELPER */
38 #ifdef DEBUG_HELPER
39 #define HELPER_LOG(x...) qemu_log(x)
40 #else
41 #define HELPER_LOG(x...)
42 #endif
43
44 /* Raise an exception dynamically from a helper function.  */
45 void QEMU_NORETURN runtime_exception(CPUS390XState *env, int excp,
46                                      uintptr_t retaddr)
47 {
48     int t;
49
50     env->exception_index = EXCP_PGM;
51     env->int_pgm_code = excp;
52
53     /* Use the (ultimate) callers address to find the insn that trapped.  */
54     cpu_restore_state(env, retaddr);
55
56     /* Advance past the insn.  */
57     t = cpu_ldub_code(env, env->psw.addr);
58     env->int_pgm_ilen = t = get_ilen(t);
59     env->psw.addr += 2 * t;
60
61     cpu_loop_exit(env);
62 }
63
64 /* Raise an exception statically from a TB.  */
65 void HELPER(exception)(CPUS390XState *env, uint32_t excp)
66 {
67     HELPER_LOG("%s: exception %d\n", __func__, excp);
68     env->exception_index = excp;
69     cpu_loop_exit(env);
70 }
71
72 #ifndef CONFIG_USER_ONLY
73
74 /* EBCDIC handling */
75 static const uint8_t ebcdic2ascii[] = {
76     0x00, 0x01, 0x02, 0x03, 0x07, 0x09, 0x07, 0x7F,
77     0x07, 0x07, 0x07, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
78     0x10, 0x11, 0x12, 0x13, 0x07, 0x0A, 0x08, 0x07,
79     0x18, 0x19, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
80     0x07, 0x07, 0x1C, 0x07, 0x07, 0x0A, 0x17, 0x1B,
81     0x07, 0x07, 0x07, 0x07, 0x07, 0x05, 0x06, 0x07,
82     0x07, 0x07, 0x16, 0x07, 0x07, 0x07, 0x07, 0x04,
83     0x07, 0x07, 0x07, 0x07, 0x14, 0x15, 0x07, 0x1A,
84     0x20, 0xFF, 0x83, 0x84, 0x85, 0xA0, 0x07, 0x86,
85     0x87, 0xA4, 0x5B, 0x2E, 0x3C, 0x28, 0x2B, 0x21,
86     0x26, 0x82, 0x88, 0x89, 0x8A, 0xA1, 0x8C, 0x07,
87     0x8D, 0xE1, 0x5D, 0x24, 0x2A, 0x29, 0x3B, 0x5E,
88     0x2D, 0x2F, 0x07, 0x8E, 0x07, 0x07, 0x07, 0x8F,
89     0x80, 0xA5, 0x07, 0x2C, 0x25, 0x5F, 0x3E, 0x3F,
90     0x07, 0x90, 0x07, 0x07, 0x07, 0x07, 0x07, 0x07,
91     0x70, 0x60, 0x3A, 0x23, 0x40, 0x27, 0x3D, 0x22,
92     0x07, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
93     0x68, 0x69, 0xAE, 0xAF, 0x07, 0x07, 0x07, 0xF1,
94     0xF8, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70,
95     0x71, 0x72, 0xA6, 0xA7, 0x91, 0x07, 0x92, 0x07,
96     0xE6, 0x7E, 0x73, 0x74, 0x75, 0x76, 0x77, 0x78,
97     0x79, 0x7A, 0xAD, 0xAB, 0x07, 0x07, 0x07, 0x07,
98     0x9B, 0x9C, 0x9D, 0xFA, 0x07, 0x07, 0x07, 0xAC,
99     0xAB, 0x07, 0xAA, 0x7C, 0x07, 0x07, 0x07, 0x07,
100     0x7B, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
101     0x48, 0x49, 0x07, 0x93, 0x94, 0x95, 0xA2, 0x07,
102     0x7D, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50,
103     0x51, 0x52, 0x07, 0x96, 0x81, 0x97, 0xA3, 0x98,
104     0x5C, 0xF6, 0x53, 0x54, 0x55, 0x56, 0x57, 0x58,
105     0x59, 0x5A, 0xFD, 0x07, 0x99, 0x07, 0x07, 0x07,
106     0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37,
107     0x38, 0x39, 0x07, 0x07, 0x9A, 0x07, 0x07, 0x07,
108 };
109
110 static const uint8_t ascii2ebcdic[] = {
111     0x00, 0x01, 0x02, 0x03, 0x37, 0x2D, 0x2E, 0x2F,
112     0x16, 0x05, 0x15, 0x0B, 0x0C, 0x0D, 0x0E, 0x0F,
113     0x10, 0x11, 0x12, 0x13, 0x3C, 0x3D, 0x32, 0x26,
114     0x18, 0x19, 0x3F, 0x27, 0x22, 0x1D, 0x1E, 0x1F,
115     0x40, 0x5A, 0x7F, 0x7B, 0x5B, 0x6C, 0x50, 0x7D,
116     0x4D, 0x5D, 0x5C, 0x4E, 0x6B, 0x60, 0x4B, 0x61,
117     0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7,
118     0xF8, 0xF9, 0x7A, 0x5E, 0x4C, 0x7E, 0x6E, 0x6F,
119     0x7C, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7,
120     0xC8, 0xC9, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6,
121     0xD7, 0xD8, 0xD9, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6,
122     0xE7, 0xE8, 0xE9, 0xBA, 0xE0, 0xBB, 0xB0, 0x6D,
123     0x79, 0x81, 0x82, 0x83, 0x84, 0x85, 0x86, 0x87,
124     0x88, 0x89, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96,
125     0x97, 0x98, 0x99, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6,
126     0xA7, 0xA8, 0xA9, 0xC0, 0x4F, 0xD0, 0xA1, 0x07,
127     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
128     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
129     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
130     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
131     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
132     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
133     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
134     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
135     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
136     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
137     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
138     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
139     0x3F, 0x59, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
140     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
141     0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F, 0x3F,
142     0x90, 0x3F, 0x3F, 0x3F, 0x3F, 0xEA, 0x3F, 0xFF
143 };
144
145 static inline void ebcdic_put(uint8_t *p, const char *ascii, int len)
146 {
147     int i;
148
149     for (i = 0; i < len; i++) {
150         p[i] = ascii2ebcdic[(uint8_t)ascii[i]];
151     }
152 }
153
154 void program_interrupt(CPUS390XState *env, uint32_t code, int ilen)
155 {
156     qemu_log_mask(CPU_LOG_INT, "program interrupt at %#" PRIx64 "\n",
157                   env->psw.addr);
158
159     if (kvm_enabled()) {
160 #ifdef CONFIG_KVM
161         kvm_s390_interrupt(s390_env_get_cpu(env), KVM_S390_PROGRAM_INT, code);
162 #endif
163     } else {
164         env->int_pgm_code = code;
165         env->int_pgm_ilen = ilen;
166         env->exception_index = EXCP_PGM;
167         cpu_loop_exit(env);
168     }
169 }
170
171 /* SCLP service call */
172 uint32_t HELPER(servc)(CPUS390XState *env, uint64_t r1, uint64_t r2)
173 {
174     int r = sclp_service_call(r1, r2);
175     if (r < 0) {
176         program_interrupt(env, -r, 4);
177         return 0;
178     }
179     return r;
180 }
181
182 /* DIAG */
183 uint64_t HELPER(diag)(CPUS390XState *env, uint32_t num, uint64_t mem,
184                       uint64_t code)
185 {
186     uint64_t r;
187
188     switch (num) {
189     case 0x500:
190         /* KVM hypercall */
191         r = s390_virtio_hypercall(env);
192         break;
193     case 0x44:
194         /* yield */
195         r = 0;
196         break;
197     case 0x308:
198         /* ipl */
199         r = 0;
200         break;
201     default:
202         r = -1;
203         break;
204     }
205
206     if (r) {
207         program_interrupt(env, PGM_OPERATION, ILEN_LATER_INC);
208     }
209
210     return r;
211 }
212
213 /* Set Prefix */
214 void HELPER(spx)(CPUS390XState *env, uint64_t a1)
215 {
216     uint32_t prefix = a1 & 0x7fffe000;
217     env->psa = prefix;
218     qemu_log("prefix: %#x\n", prefix);
219     tlb_flush_page(env, 0);
220     tlb_flush_page(env, TARGET_PAGE_SIZE);
221 }
222
223 static inline uint64_t clock_value(CPUS390XState *env)
224 {
225     uint64_t time;
226
227     time = env->tod_offset +
228         time2tod(qemu_get_clock_ns(vm_clock) - env->tod_basetime);
229
230     return time;
231 }
232
233 /* Store Clock */
234 uint64_t HELPER(stck)(CPUS390XState *env)
235 {
236     return clock_value(env);
237 }
238
239 /* Set Clock Comparator */
240 void HELPER(sckc)(CPUS390XState *env, uint64_t time)
241 {
242     if (time == -1ULL) {
243         return;
244     }
245
246     /* difference between now and then */
247     time -= clock_value(env);
248     /* nanoseconds */
249     time = (time * 125) >> 9;
250
251     qemu_mod_timer(env->tod_timer, qemu_get_clock_ns(vm_clock) + time);
252 }
253
254 /* Store Clock Comparator */
255 uint64_t HELPER(stckc)(CPUS390XState *env)
256 {
257     /* XXX implement */
258     return 0;
259 }
260
261 /* Set CPU Timer */
262 void HELPER(spt)(CPUS390XState *env, uint64_t time)
263 {
264     if (time == -1ULL) {
265         return;
266     }
267
268     /* nanoseconds */
269     time = (time * 125) >> 9;
270
271     qemu_mod_timer(env->cpu_timer, qemu_get_clock_ns(vm_clock) + time);
272 }
273
274 /* Store CPU Timer */
275 uint64_t HELPER(stpt)(CPUS390XState *env)
276 {
277     /* XXX implement */
278     return 0;
279 }
280
281 /* Store System Information */
282 uint32_t HELPER(stsi)(CPUS390XState *env, uint64_t a0,
283                       uint64_t r0, uint64_t r1)
284 {
285     int cc = 0;
286     int sel1, sel2;
287
288     if ((r0 & STSI_LEVEL_MASK) <= STSI_LEVEL_3 &&
289         ((r0 & STSI_R0_RESERVED_MASK) || (r1 & STSI_R1_RESERVED_MASK))) {
290         /* valid function code, invalid reserved bits */
291         program_interrupt(env, PGM_SPECIFICATION, 2);
292     }
293
294     sel1 = r0 & STSI_R0_SEL1_MASK;
295     sel2 = r1 & STSI_R1_SEL2_MASK;
296
297     /* XXX: spec exception if sysib is not 4k-aligned */
298
299     switch (r0 & STSI_LEVEL_MASK) {
300     case STSI_LEVEL_1:
301         if ((sel1 == 1) && (sel2 == 1)) {
302             /* Basic Machine Configuration */
303             struct sysib_111 sysib;
304
305             memset(&sysib, 0, sizeof(sysib));
306             ebcdic_put(sysib.manuf, "QEMU            ", 16);
307             /* same as machine type number in STORE CPU ID */
308             ebcdic_put(sysib.type, "QEMU", 4);
309             /* same as model number in STORE CPU ID */
310             ebcdic_put(sysib.model, "QEMU            ", 16);
311             ebcdic_put(sysib.sequence, "QEMU            ", 16);
312             ebcdic_put(sysib.plant, "QEMU", 4);
313             cpu_physical_memory_rw(a0, (uint8_t *)&sysib, sizeof(sysib), 1);
314         } else if ((sel1 == 2) && (sel2 == 1)) {
315             /* Basic Machine CPU */
316             struct sysib_121 sysib;
317
318             memset(&sysib, 0, sizeof(sysib));
319             /* XXX make different for different CPUs? */
320             ebcdic_put(sysib.sequence, "QEMUQEMUQEMUQEMU", 16);
321             ebcdic_put(sysib.plant, "QEMU", 4);
322             stw_p(&sysib.cpu_addr, env->cpu_num);
323             cpu_physical_memory_rw(a0, (uint8_t *)&sysib, sizeof(sysib), 1);
324         } else if ((sel1 == 2) && (sel2 == 2)) {
325             /* Basic Machine CPUs */
326             struct sysib_122 sysib;
327
328             memset(&sysib, 0, sizeof(sysib));
329             stl_p(&sysib.capability, 0x443afc29);
330             /* XXX change when SMP comes */
331             stw_p(&sysib.total_cpus, 1);
332             stw_p(&sysib.active_cpus, 1);
333             stw_p(&sysib.standby_cpus, 0);
334             stw_p(&sysib.reserved_cpus, 0);
335             cpu_physical_memory_rw(a0, (uint8_t *)&sysib, sizeof(sysib), 1);
336         } else {
337             cc = 3;
338         }
339         break;
340     case STSI_LEVEL_2:
341         {
342             if ((sel1 == 2) && (sel2 == 1)) {
343                 /* LPAR CPU */
344                 struct sysib_221 sysib;
345
346                 memset(&sysib, 0, sizeof(sysib));
347                 /* XXX make different for different CPUs? */
348                 ebcdic_put(sysib.sequence, "QEMUQEMUQEMUQEMU", 16);
349                 ebcdic_put(sysib.plant, "QEMU", 4);
350                 stw_p(&sysib.cpu_addr, env->cpu_num);
351                 stw_p(&sysib.cpu_id, 0);
352                 cpu_physical_memory_rw(a0, (uint8_t *)&sysib, sizeof(sysib), 1);
353             } else if ((sel1 == 2) && (sel2 == 2)) {
354                 /* LPAR CPUs */
355                 struct sysib_222 sysib;
356
357                 memset(&sysib, 0, sizeof(sysib));
358                 stw_p(&sysib.lpar_num, 0);
359                 sysib.lcpuc = 0;
360                 /* XXX change when SMP comes */
361                 stw_p(&sysib.total_cpus, 1);
362                 stw_p(&sysib.conf_cpus, 1);
363                 stw_p(&sysib.standby_cpus, 0);
364                 stw_p(&sysib.reserved_cpus, 0);
365                 ebcdic_put(sysib.name, "QEMU    ", 8);
366                 stl_p(&sysib.caf, 1000);
367                 stw_p(&sysib.dedicated_cpus, 0);
368                 stw_p(&sysib.shared_cpus, 0);
369                 cpu_physical_memory_rw(a0, (uint8_t *)&sysib, sizeof(sysib), 1);
370             } else {
371                 cc = 3;
372             }
373             break;
374         }
375     case STSI_LEVEL_3:
376         {
377             if ((sel1 == 2) && (sel2 == 2)) {
378                 /* VM CPUs */
379                 struct sysib_322 sysib;
380
381                 memset(&sysib, 0, sizeof(sysib));
382                 sysib.count = 1;
383                 /* XXX change when SMP comes */
384                 stw_p(&sysib.vm[0].total_cpus, 1);
385                 stw_p(&sysib.vm[0].conf_cpus, 1);
386                 stw_p(&sysib.vm[0].standby_cpus, 0);
387                 stw_p(&sysib.vm[0].reserved_cpus, 0);
388                 ebcdic_put(sysib.vm[0].name, "KVMguest", 8);
389                 stl_p(&sysib.vm[0].caf, 1000);
390                 ebcdic_put(sysib.vm[0].cpi, "KVM/Linux       ", 16);
391                 cpu_physical_memory_rw(a0, (uint8_t *)&sysib, sizeof(sysib), 1);
392             } else {
393                 cc = 3;
394             }
395             break;
396         }
397     case STSI_LEVEL_CURRENT:
398         env->regs[0] = STSI_LEVEL_3;
399         break;
400     default:
401         cc = 3;
402         break;
403     }
404
405     return cc;
406 }
407
408 uint32_t HELPER(sigp)(CPUS390XState *env, uint64_t order_code, uint32_t r1,
409                       uint64_t cpu_addr)
410 {
411     int cc = 0;
412
413     HELPER_LOG("%s: %016" PRIx64 " %08x %016" PRIx64 "\n",
414                __func__, order_code, r1, cpu_addr);
415
416     /* Remember: Use "R1 or R1 + 1, whichever is the odd-numbered register"
417        as parameter (input). Status (output) is always R1. */
418
419     switch (order_code) {
420     case SIGP_SET_ARCH:
421         /* switch arch */
422         break;
423     case SIGP_SENSE:
424         /* enumerate CPU status */
425         if (cpu_addr) {
426             /* XXX implement when SMP comes */
427             return 3;
428         }
429         env->regs[r1] &= 0xffffffff00000000ULL;
430         cc = 1;
431         break;
432 #if !defined(CONFIG_USER_ONLY)
433     case SIGP_RESTART:
434         qemu_system_reset_request();
435         cpu_loop_exit(env);
436         break;
437     case SIGP_STOP:
438         qemu_system_shutdown_request();
439         cpu_loop_exit(env);
440         break;
441 #endif
442     default:
443         /* unknown sigp */
444         fprintf(stderr, "XXX unknown sigp: 0x%" PRIx64 "\n", order_code);
445         cc = 3;
446     }
447
448     return cc;
449 }
450 #endif