]> Git Repo - qemu.git/blob - target/s390x/misc_helper.c
Merge remote-tracking branch 'remotes/ehabkost/tags/machine-next-pull-request' into...
[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 "qemu/osdep.h"
22 #include "qemu/main-loop.h"
23 #include "cpu.h"
24 #include "internal.h"
25 #include "exec/memory.h"
26 #include "qemu/host-utils.h"
27 #include "exec/helper-proto.h"
28 #include "qemu/timer.h"
29 #include "exec/address-spaces.h"
30 #include "exec/exec-all.h"
31 #include "exec/cpu_ldst.h"
32
33 #if !defined(CONFIG_USER_ONLY)
34 #include "sysemu/cpus.h"
35 #include "sysemu/sysemu.h"
36 #include "hw/s390x/ebcdic.h"
37 #include "hw/s390x/s390-virtio-hcall.h"
38 #include "hw/s390x/sclp.h"
39 #endif
40
41 /* #define DEBUG_HELPER */
42 #ifdef DEBUG_HELPER
43 #define HELPER_LOG(x...) qemu_log(x)
44 #else
45 #define HELPER_LOG(x...)
46 #endif
47
48 /* Raise an exception dynamically from a helper function.  */
49 void QEMU_NORETURN runtime_exception(CPUS390XState *env, int excp,
50                                      uintptr_t retaddr)
51 {
52     CPUState *cs = CPU(s390_env_get_cpu(env));
53
54     cs->exception_index = EXCP_PGM;
55     env->int_pgm_code = excp;
56     env->int_pgm_ilen = ILEN_AUTO;
57
58     /* Use the (ultimate) callers address to find the insn that trapped.  */
59     cpu_restore_state(cs, retaddr);
60
61     cpu_loop_exit(cs);
62 }
63
64 /* Raise an exception statically from a TB.  */
65 void HELPER(exception)(CPUS390XState *env, uint32_t excp)
66 {
67     CPUState *cs = CPU(s390_env_get_cpu(env));
68
69     HELPER_LOG("%s: exception %d\n", __func__, excp);
70     cs->exception_index = excp;
71     cpu_loop_exit(cs);
72 }
73
74 #ifndef CONFIG_USER_ONLY
75
76 /* SCLP service call */
77 uint32_t HELPER(servc)(CPUS390XState *env, uint64_t r1, uint64_t r2)
78 {
79     qemu_mutex_lock_iothread();
80     int r = sclp_service_call(env, r1, r2);
81     if (r < 0) {
82         program_interrupt(env, -r, 4);
83         r = 0;
84     }
85     qemu_mutex_unlock_iothread();
86     return r;
87 }
88
89 void HELPER(diag)(CPUS390XState *env, uint32_t r1, uint32_t r3, uint32_t num)
90 {
91     uint64_t r;
92
93     switch (num) {
94     case 0x500:
95         /* KVM hypercall */
96         qemu_mutex_lock_iothread();
97         r = s390_virtio_hypercall(env);
98         qemu_mutex_unlock_iothread();
99         break;
100     case 0x44:
101         /* yield */
102         r = 0;
103         break;
104     case 0x308:
105         /* ipl */
106         handle_diag_308(env, r1, r3);
107         r = 0;
108         break;
109     case 0x288:
110         /* time bomb (watchdog) */
111         r = handle_diag_288(env, r1, r3);
112         break;
113     default:
114         r = -1;
115         break;
116     }
117
118     if (r) {
119         program_interrupt(env, PGM_SPECIFICATION, ILEN_AUTO);
120     }
121 }
122
123 /* Set Prefix */
124 void HELPER(spx)(CPUS390XState *env, uint64_t a1)
125 {
126     CPUState *cs = CPU(s390_env_get_cpu(env));
127     uint32_t prefix = a1 & 0x7fffe000;
128
129     env->psa = prefix;
130     HELPER_LOG("prefix: %#x\n", prefix);
131     tlb_flush_page(cs, 0);
132     tlb_flush_page(cs, TARGET_PAGE_SIZE);
133 }
134
135 /* Store Clock */
136 uint64_t HELPER(stck)(CPUS390XState *env)
137 {
138     uint64_t time;
139
140     time = env->tod_offset +
141         time2tod(qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) - env->tod_basetime);
142
143     return time;
144 }
145
146 /* Set Clock Comparator */
147 void HELPER(sckc)(CPUS390XState *env, uint64_t time)
148 {
149     if (time == -1ULL) {
150         return;
151     }
152
153     env->ckc = time;
154
155     /* difference between origins */
156     time -= env->tod_offset;
157
158     /* nanoseconds */
159     time = tod2time(time);
160
161     timer_mod(env->tod_timer, env->tod_basetime + time);
162 }
163
164 /* Store Clock Comparator */
165 uint64_t HELPER(stckc)(CPUS390XState *env)
166 {
167     return env->ckc;
168 }
169
170 /* Set CPU Timer */
171 void HELPER(spt)(CPUS390XState *env, uint64_t time)
172 {
173     if (time == -1ULL) {
174         return;
175     }
176
177     /* nanoseconds */
178     time = tod2time(time);
179
180     env->cputm = qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL) + time;
181
182     timer_mod(env->cpu_timer, env->cputm);
183 }
184
185 /* Store CPU Timer */
186 uint64_t HELPER(stpt)(CPUS390XState *env)
187 {
188     return time2tod(env->cputm - qemu_clock_get_ns(QEMU_CLOCK_VIRTUAL));
189 }
190
191 /* Store System Information */
192 uint32_t HELPER(stsi)(CPUS390XState *env, uint64_t a0,
193                       uint64_t r0, uint64_t r1)
194 {
195     S390CPU *cpu = s390_env_get_cpu(env);
196     int cc = 0;
197     int sel1, sel2;
198
199     if ((r0 & STSI_LEVEL_MASK) <= STSI_LEVEL_3 &&
200         ((r0 & STSI_R0_RESERVED_MASK) || (r1 & STSI_R1_RESERVED_MASK))) {
201         /* valid function code, invalid reserved bits */
202         program_interrupt(env, PGM_SPECIFICATION, 4);
203     }
204
205     sel1 = r0 & STSI_R0_SEL1_MASK;
206     sel2 = r1 & STSI_R1_SEL2_MASK;
207
208     /* XXX: spec exception if sysib is not 4k-aligned */
209
210     switch (r0 & STSI_LEVEL_MASK) {
211     case STSI_LEVEL_1:
212         if ((sel1 == 1) && (sel2 == 1)) {
213             /* Basic Machine Configuration */
214             struct sysib_111 sysib;
215             char type[5] = {};
216
217             memset(&sysib, 0, sizeof(sysib));
218             ebcdic_put(sysib.manuf, "QEMU            ", 16);
219             /* same as machine type number in STORE CPU ID, but in EBCDIC */
220             snprintf(type, ARRAY_SIZE(type), "%X", cpu->model->def->type);
221             ebcdic_put(sysib.type, type, 4);
222             /* model number (not stored in STORE CPU ID for z/Architecure) */
223             ebcdic_put(sysib.model, "QEMU            ", 16);
224             ebcdic_put(sysib.sequence, "QEMU            ", 16);
225             ebcdic_put(sysib.plant, "QEMU", 4);
226             cpu_physical_memory_write(a0, &sysib, sizeof(sysib));
227         } else if ((sel1 == 2) && (sel2 == 1)) {
228             /* Basic Machine CPU */
229             struct sysib_121 sysib;
230
231             memset(&sysib, 0, sizeof(sysib));
232             /* XXX make different for different CPUs? */
233             ebcdic_put(sysib.sequence, "QEMUQEMUQEMUQEMU", 16);
234             ebcdic_put(sysib.plant, "QEMU", 4);
235             stw_p(&sysib.cpu_addr, env->core_id);
236             cpu_physical_memory_write(a0, &sysib, sizeof(sysib));
237         } else if ((sel1 == 2) && (sel2 == 2)) {
238             /* Basic Machine CPUs */
239             struct sysib_122 sysib;
240
241             memset(&sysib, 0, sizeof(sysib));
242             stl_p(&sysib.capability, 0x443afc29);
243             /* XXX change when SMP comes */
244             stw_p(&sysib.total_cpus, 1);
245             stw_p(&sysib.active_cpus, 1);
246             stw_p(&sysib.standby_cpus, 0);
247             stw_p(&sysib.reserved_cpus, 0);
248             cpu_physical_memory_write(a0, &sysib, sizeof(sysib));
249         } else {
250             cc = 3;
251         }
252         break;
253     case STSI_LEVEL_2:
254         {
255             if ((sel1 == 2) && (sel2 == 1)) {
256                 /* LPAR CPU */
257                 struct sysib_221 sysib;
258
259                 memset(&sysib, 0, sizeof(sysib));
260                 /* XXX make different for different CPUs? */
261                 ebcdic_put(sysib.sequence, "QEMUQEMUQEMUQEMU", 16);
262                 ebcdic_put(sysib.plant, "QEMU", 4);
263                 stw_p(&sysib.cpu_addr, env->core_id);
264                 stw_p(&sysib.cpu_id, 0);
265                 cpu_physical_memory_write(a0, &sysib, sizeof(sysib));
266             } else if ((sel1 == 2) && (sel2 == 2)) {
267                 /* LPAR CPUs */
268                 struct sysib_222 sysib;
269
270                 memset(&sysib, 0, sizeof(sysib));
271                 stw_p(&sysib.lpar_num, 0);
272                 sysib.lcpuc = 0;
273                 /* XXX change when SMP comes */
274                 stw_p(&sysib.total_cpus, 1);
275                 stw_p(&sysib.conf_cpus, 1);
276                 stw_p(&sysib.standby_cpus, 0);
277                 stw_p(&sysib.reserved_cpus, 0);
278                 ebcdic_put(sysib.name, "QEMU    ", 8);
279                 stl_p(&sysib.caf, 1000);
280                 stw_p(&sysib.dedicated_cpus, 0);
281                 stw_p(&sysib.shared_cpus, 0);
282                 cpu_physical_memory_write(a0, &sysib, sizeof(sysib));
283             } else {
284                 cc = 3;
285             }
286             break;
287         }
288     case STSI_LEVEL_3:
289         {
290             if ((sel1 == 2) && (sel2 == 2)) {
291                 /* VM CPUs */
292                 struct sysib_322 sysib;
293
294                 memset(&sysib, 0, sizeof(sysib));
295                 sysib.count = 1;
296                 /* XXX change when SMP comes */
297                 stw_p(&sysib.vm[0].total_cpus, 1);
298                 stw_p(&sysib.vm[0].conf_cpus, 1);
299                 stw_p(&sysib.vm[0].standby_cpus, 0);
300                 stw_p(&sysib.vm[0].reserved_cpus, 0);
301                 ebcdic_put(sysib.vm[0].name, "KVMguest", 8);
302                 stl_p(&sysib.vm[0].caf, 1000);
303                 ebcdic_put(sysib.vm[0].cpi, "KVM/Linux       ", 16);
304                 cpu_physical_memory_write(a0, &sysib, sizeof(sysib));
305             } else {
306                 cc = 3;
307             }
308             break;
309         }
310     case STSI_LEVEL_CURRENT:
311         env->regs[0] = STSI_LEVEL_3;
312         break;
313     default:
314         cc = 3;
315         break;
316     }
317
318     return cc;
319 }
320
321 uint32_t HELPER(sigp)(CPUS390XState *env, uint64_t order_code, uint32_t r1,
322                       uint64_t cpu_addr)
323 {
324     int cc = SIGP_CC_ORDER_CODE_ACCEPTED;
325
326     HELPER_LOG("%s: %016" PRIx64 " %08x %016" PRIx64 "\n",
327                __func__, order_code, r1, cpu_addr);
328
329     /* Remember: Use "R1 or R1 + 1, whichever is the odd-numbered register"
330        as parameter (input). Status (output) is always R1. */
331
332     switch (order_code & SIGP_ORDER_MASK) {
333     case SIGP_SET_ARCH:
334         /* switch arch */
335         break;
336     case SIGP_SENSE:
337         /* enumerate CPU status */
338         if (cpu_addr) {
339             /* XXX implement when SMP comes */
340             return 3;
341         }
342         env->regs[r1] &= 0xffffffff00000000ULL;
343         cc = 1;
344         break;
345 #if !defined(CONFIG_USER_ONLY)
346     case SIGP_RESTART:
347         qemu_system_reset_request(SHUTDOWN_CAUSE_GUEST_RESET);
348         cpu_loop_exit(CPU(s390_env_get_cpu(env)));
349         break;
350     case SIGP_STOP:
351         qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
352         cpu_loop_exit(CPU(s390_env_get_cpu(env)));
353         break;
354 #endif
355     default:
356         /* unknown sigp */
357         fprintf(stderr, "XXX unknown sigp: 0x%" PRIx64 "\n", order_code);
358         cc = SIGP_CC_NOT_OPERATIONAL;
359     }
360
361     return cc;
362 }
363 #endif
364
365 #ifndef CONFIG_USER_ONLY
366 void HELPER(xsch)(CPUS390XState *env, uint64_t r1)
367 {
368     S390CPU *cpu = s390_env_get_cpu(env);
369     qemu_mutex_lock_iothread();
370     ioinst_handle_xsch(cpu, r1);
371     qemu_mutex_unlock_iothread();
372 }
373
374 void HELPER(csch)(CPUS390XState *env, uint64_t r1)
375 {
376     S390CPU *cpu = s390_env_get_cpu(env);
377     qemu_mutex_lock_iothread();
378     ioinst_handle_csch(cpu, r1);
379     qemu_mutex_unlock_iothread();
380 }
381
382 void HELPER(hsch)(CPUS390XState *env, uint64_t r1)
383 {
384     S390CPU *cpu = s390_env_get_cpu(env);
385     qemu_mutex_lock_iothread();
386     ioinst_handle_hsch(cpu, r1);
387     qemu_mutex_unlock_iothread();
388 }
389
390 void HELPER(msch)(CPUS390XState *env, uint64_t r1, uint64_t inst)
391 {
392     S390CPU *cpu = s390_env_get_cpu(env);
393     qemu_mutex_lock_iothread();
394     ioinst_handle_msch(cpu, r1, inst >> 16);
395     qemu_mutex_unlock_iothread();
396 }
397
398 void HELPER(rchp)(CPUS390XState *env, uint64_t r1)
399 {
400     S390CPU *cpu = s390_env_get_cpu(env);
401     qemu_mutex_lock_iothread();
402     ioinst_handle_rchp(cpu, r1);
403     qemu_mutex_unlock_iothread();
404 }
405
406 void HELPER(rsch)(CPUS390XState *env, uint64_t r1)
407 {
408     S390CPU *cpu = s390_env_get_cpu(env);
409     qemu_mutex_lock_iothread();
410     ioinst_handle_rsch(cpu, r1);
411     qemu_mutex_unlock_iothread();
412 }
413
414 void HELPER(ssch)(CPUS390XState *env, uint64_t r1, uint64_t inst)
415 {
416     S390CPU *cpu = s390_env_get_cpu(env);
417     qemu_mutex_lock_iothread();
418     ioinst_handle_ssch(cpu, r1, inst >> 16);
419     qemu_mutex_unlock_iothread();
420 }
421
422 void HELPER(stsch)(CPUS390XState *env, uint64_t r1, uint64_t inst)
423 {
424     S390CPU *cpu = s390_env_get_cpu(env);
425     qemu_mutex_lock_iothread();
426     ioinst_handle_stsch(cpu, r1, inst >> 16);
427     qemu_mutex_unlock_iothread();
428 }
429
430 void HELPER(tsch)(CPUS390XState *env, uint64_t r1, uint64_t inst)
431 {
432     S390CPU *cpu = s390_env_get_cpu(env);
433     qemu_mutex_lock_iothread();
434     ioinst_handle_tsch(cpu, r1, inst >> 16);
435     qemu_mutex_unlock_iothread();
436 }
437
438 void HELPER(chsc)(CPUS390XState *env, uint64_t inst)
439 {
440     S390CPU *cpu = s390_env_get_cpu(env);
441     qemu_mutex_lock_iothread();
442     ioinst_handle_chsc(cpu, inst >> 16);
443     qemu_mutex_unlock_iothread();
444 }
445 #endif
446
447 #ifndef CONFIG_USER_ONLY
448 void HELPER(per_check_exception)(CPUS390XState *env)
449 {
450     uint32_t ilen;
451
452     if (env->per_perc_atmid) {
453         /*
454          * FIXME: ILEN_AUTO is most probably the right thing to use. ilen
455          * always has to match the instruction referenced in the PSW. E.g.
456          * if a PER interrupt is triggered via EXECUTE, we have to use ilen
457          * of EXECUTE, while per_address contains the target of EXECUTE.
458          */
459         ilen = get_ilen(cpu_ldub_code(env, env->per_address));
460         program_interrupt(env, PGM_PER, ilen);
461     }
462 }
463
464 /* Check if an address is within the PER starting address and the PER
465    ending address.  The address range might loop.  */
466 static inline bool get_per_in_range(CPUS390XState *env, uint64_t addr)
467 {
468     if (env->cregs[10] <= env->cregs[11]) {
469         return env->cregs[10] <= addr && addr <= env->cregs[11];
470     } else {
471         return env->cregs[10] <= addr || addr <= env->cregs[11];
472     }
473 }
474
475 void HELPER(per_branch)(CPUS390XState *env, uint64_t from, uint64_t to)
476 {
477     if ((env->cregs[9] & PER_CR9_EVENT_BRANCH)) {
478         if (!(env->cregs[9] & PER_CR9_CONTROL_BRANCH_ADDRESS)
479             || get_per_in_range(env, to)) {
480             env->per_address = from;
481             env->per_perc_atmid = PER_CODE_EVENT_BRANCH | get_per_atmid(env);
482         }
483     }
484 }
485
486 void HELPER(per_ifetch)(CPUS390XState *env, uint64_t addr)
487 {
488     if ((env->cregs[9] & PER_CR9_EVENT_IFETCH) && get_per_in_range(env, addr)) {
489         env->per_address = addr;
490         env->per_perc_atmid = PER_CODE_EVENT_IFETCH | get_per_atmid(env);
491
492         /* If the instruction has to be nullified, trigger the
493            exception immediately. */
494         if (env->cregs[9] & PER_CR9_EVENT_NULLIFICATION) {
495             CPUState *cs = CPU(s390_env_get_cpu(env));
496
497             env->per_perc_atmid |= PER_CODE_EVENT_NULLIFICATION;
498             env->int_pgm_code = PGM_PER;
499             env->int_pgm_ilen = get_ilen(cpu_ldub_code(env, addr));
500
501             cs->exception_index = EXCP_PGM;
502             cpu_loop_exit(cs);
503         }
504     }
505 }
506 #endif
507
508 /* The maximum bit defined at the moment is 129.  */
509 #define MAX_STFL_WORDS  3
510
511 /* Canonicalize the current cpu's features into the 64-bit words required
512    by STFLE.  Return the index-1 of the max word that is non-zero.  */
513 static unsigned do_stfle(CPUS390XState *env, uint64_t words[MAX_STFL_WORDS])
514 {
515     S390CPU *cpu = s390_env_get_cpu(env);
516     const unsigned long *features = cpu->model->features;
517     unsigned max_bit = 0;
518     S390Feat feat;
519
520     memset(words, 0, sizeof(uint64_t) * MAX_STFL_WORDS);
521
522     if (test_bit(S390_FEAT_ZARCH, features)) {
523         /* z/Architecture is always active if around */
524         words[0] = 1ull << (63 - 2);
525     }
526
527     for (feat = find_first_bit(features, S390_FEAT_MAX);
528          feat < S390_FEAT_MAX;
529          feat = find_next_bit(features, S390_FEAT_MAX, feat + 1)) {
530         const S390FeatDef *def = s390_feat_def(feat);
531         if (def->type == S390_FEAT_TYPE_STFL) {
532             unsigned bit = def->bit;
533             if (bit > max_bit) {
534                 max_bit = bit;
535             }
536             assert(bit / 64 < MAX_STFL_WORDS);
537             words[bit / 64] |= 1ULL << (63 - bit % 64);
538         }
539     }
540
541     return max_bit / 64;
542 }
543
544 void HELPER(stfl)(CPUS390XState *env)
545 {
546     uint64_t words[MAX_STFL_WORDS];
547
548     do_stfle(env, words);
549     cpu_stl_data(env, 200, words[0] >> 32);
550 }
551
552 uint32_t HELPER(stfle)(CPUS390XState *env, uint64_t addr)
553 {
554     uint64_t words[MAX_STFL_WORDS];
555     unsigned count_m1 = env->regs[0] & 0xff;
556     unsigned max_m1 = do_stfle(env, words);
557     unsigned i;
558
559     for (i = 0; i <= count_m1; ++i) {
560         cpu_stq_data(env, addr + 8 * i, words[i]);
561     }
562
563     env->regs[0] = deposit64(env->regs[0], 0, 8, max_m1);
564     return (count_m1 >= max_m1 ? 0 : 3);
565 }
This page took 0.052873 seconds and 4 git commands to generate.