]> git.proxmox.com Git - qemu.git/blame - target-s390x/misc_helper.c
main-loop: narrow win32 pollfds_fill() event bitmasks
[qemu.git] / target-s390x / misc_helper.c
CommitLineData
10ec5117 1/*
aea1e885 2 * S/390 misc helper routines
10ec5117 3 *
defb0e31 4 * Copyright (c) 2009 Ulrich Hecht
10ec5117
AG
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
70539e18 18 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
10ec5117
AG
19 */
20
3e457172 21#include "cpu.h"
022c62cb 22#include "exec/memory.h"
1de7afc9 23#include "qemu/host-utils.h"
3208afbe 24#include "helper.h"
defb0e31 25#include <string.h>
9c17d615 26#include "sysemu/kvm.h"
1de7afc9 27#include "qemu/timer.h"
af2be207
JK
28#ifdef CONFIG_KVM
29#include <linux/kvm.h>
30#endif
10ec5117 31
71e47088 32#if !defined(CONFIG_USER_ONLY)
022c62cb 33#include "exec/softmmu_exec.h"
9c17d615 34#include "sysemu/sysemu.h"
10ec5117 35#endif
d5a43964 36
defb0e31
AG
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
b4e2bd35
RH
44/* Raise an exception dynamically from a helper function. */
45void 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
d5a103cd 64/* Raise an exception statically from a TB. */
089f5c06 65void HELPER(exception)(CPUS390XState *env, uint32_t excp)
defb0e31 66{
71e47088 67 HELPER_LOG("%s: exception %d\n", __func__, excp);
defb0e31 68 env->exception_index = excp;
1162c041 69 cpu_loop_exit(env);
defb0e31
AG
70}
71
defb0e31 72#ifndef CONFIG_USER_ONLY
a158986d
SW
73
74/* EBCDIC handling */
75static 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
110static 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
145static 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
d5a103cd 154void program_interrupt(CPUS390XState *env, uint32_t code, int ilen)
defb0e31 155{
0d404541
RH
156 qemu_log_mask(CPU_LOG_INT, "program interrupt at %#" PRIx64 "\n",
157 env->psw.addr);
defb0e31
AG
158
159 if (kvm_enabled()) {
af2be207 160#ifdef CONFIG_KVM
1bc22652 161 kvm_s390_interrupt(s390_env_get_cpu(env), KVM_S390_PROGRAM_INT, code);
af2be207 162#endif
defb0e31
AG
163 } else {
164 env->int_pgm_code = code;
d5a103cd 165 env->int_pgm_ilen = ilen;
defb0e31 166 env->exception_index = EXCP_PGM;
1162c041 167 cpu_loop_exit(env);
defb0e31
AG
168 }
169}
170
defb0e31 171/* SCLP service call */
dc458df9 172uint32_t HELPER(servc)(CPUS390XState *env, uint64_t r1, uint64_t r2)
defb0e31 173{
dc458df9 174 int r = sclp_service_call(r1, r2);
9abf567d
CB
175 if (r < 0) {
176 program_interrupt(env, -r, 4);
177 return 0;
178 }
179 return r;
defb0e31
AG
180}
181
182/* DIAG */
089f5c06
BS
183uint64_t HELPER(diag)(CPUS390XState *env, uint32_t num, uint64_t mem,
184 uint64_t code)
defb0e31
AG
185{
186 uint64_t r;
187
188 switch (num) {
189 case 0x500:
190 /* KVM hypercall */
28e942f8 191 r = s390_virtio_hypercall(env);
defb0e31
AG
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) {
d5a103cd 207 program_interrupt(env, PGM_OPERATION, ILEN_LATER_INC);
defb0e31
AG
208 }
209
210 return r;
211}
212
defb0e31 213/* Set Prefix */
089f5c06 214void HELPER(spx)(CPUS390XState *env, uint64_t a1)
defb0e31 215{
e805a0d3
RH
216 uint32_t prefix = a1 & 0x7fffe000;
217 env->psa = prefix;
defb0e31
AG
218 qemu_log("prefix: %#x\n", prefix);
219 tlb_flush_page(env, 0);
220 tlb_flush_page(env, TARGET_PAGE_SIZE);
221}
222
a4e3ad19 223static inline uint64_t clock_value(CPUS390XState *env)
defb0e31
AG
224{
225 uint64_t time;
226
227 time = env->tod_offset +
71e47088 228 time2tod(qemu_get_clock_ns(vm_clock) - env->tod_basetime);
defb0e31
AG
229
230 return time;
231}
232
233/* Store Clock */
434c91a5 234uint64_t HELPER(stck)(CPUS390XState *env)
defb0e31 235{
434c91a5 236 return clock_value(env);
defb0e31
AG
237}
238
defb0e31 239/* Set Clock Comparator */
dd3eb7b5 240void HELPER(sckc)(CPUS390XState *env, uint64_t time)
defb0e31 241{
defb0e31
AG
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 */
dd3eb7b5 255uint64_t HELPER(stckc)(CPUS390XState *env)
defb0e31
AG
256{
257 /* XXX implement */
dd3eb7b5 258 return 0;
defb0e31
AG
259}
260
261/* Set CPU Timer */
c4f0a863 262void HELPER(spt)(CPUS390XState *env, uint64_t time)
defb0e31 263{
defb0e31
AG
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 */
c4f0a863 275uint64_t HELPER(stpt)(CPUS390XState *env)
defb0e31
AG
276{
277 /* XXX implement */
c4f0a863 278 return 0;
defb0e31
AG
279}
280
281/* Store System Information */
d14b3e09
RH
282uint32_t HELPER(stsi)(CPUS390XState *env, uint64_t a0,
283 uint64_t r0, uint64_t r1)
defb0e31
AG
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);
71e47088 313 cpu_physical_memory_rw(a0, (uint8_t *)&sysib, sizeof(sysib), 1);
defb0e31
AG
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);
71e47088 323 cpu_physical_memory_rw(a0, (uint8_t *)&sysib, sizeof(sysib), 1);
defb0e31
AG
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);
71e47088 335 cpu_physical_memory_rw(a0, (uint8_t *)&sysib, sizeof(sysib), 1);
defb0e31
AG
336 } else {
337 cc = 3;
338 }
339 break;
340 case STSI_LEVEL_2:
71e47088
BS
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;
defb0e31 374 }
defb0e31 375 case STSI_LEVEL_3:
71e47088
BS
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;
defb0e31 396 }
defb0e31
AG
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
089f5c06
BS
408uint32_t HELPER(sigp)(CPUS390XState *env, uint64_t order_code, uint32_t r1,
409 uint64_t cpu_addr)
defb0e31
AG
410{
411 int cc = 0;
412
413 HELPER_LOG("%s: %016" PRIx64 " %08x %016" PRIx64 "\n",
71e47088 414 __func__, order_code, r1, cpu_addr);
defb0e31 415
71e47088 416 /* Remember: Use "R1 or R1 + 1, whichever is the odd-numbered register"
defb0e31
AG
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;
71e47088 432#if !defined(CONFIG_USER_ONLY)
1864b94a
AG
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
defb0e31
AG
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}
defb0e31 450#endif