xref: /openbmc/qemu/target/s390x/sigp.c (revision 2f95279a)
1 /*
2  * s390x SIGP instruction handling
3  *
4  * Copyright (c) 2009 Alexander Graf <agraf@suse.de>
5  * Copyright IBM Corp. 2012
6  *
7  * This work is licensed under the terms of the GNU GPL, version 2 or later.
8  * See the COPYING file in the top-level directory.
9  */
10 
11 #include "qemu/osdep.h"
12 #include "cpu.h"
13 #include "s390x-internal.h"
14 #include "hw/boards.h"
15 #include "sysemu/hw_accel.h"
16 #include "sysemu/runstate.h"
17 #include "exec/address-spaces.h"
18 #include "exec/exec-all.h"
19 #include "sysemu/tcg.h"
20 #include "trace.h"
21 #include "qapi/qapi-types-machine.h"
22 
23 QemuMutex qemu_sigp_mutex;
24 
25 typedef struct SigpInfo {
26     uint64_t param;
27     int cc;
28     uint64_t *status_reg;
29 } SigpInfo;
30 
31 static void set_sigp_status(SigpInfo *si, uint64_t status)
32 {
33     *si->status_reg &= 0xffffffff00000000ULL;
34     *si->status_reg |= status;
35     si->cc = SIGP_CC_STATUS_STORED;
36 }
37 
38 static void sigp_sense(S390CPU *dst_cpu, SigpInfo *si)
39 {
40     uint8_t state = s390_cpu_get_state(dst_cpu);
41     bool ext_call = dst_cpu->env.pending_int & INTERRUPT_EXTERNAL_CALL;
42     uint64_t status = 0;
43 
44     if (!tcg_enabled()) {
45         /* handled in KVM */
46         set_sigp_status(si, SIGP_STAT_INVALID_ORDER);
47         return;
48     }
49 
50     /* sensing without locks is racy, but it's the same for real hw */
51     if (state != S390_CPU_STATE_STOPPED && !ext_call) {
52         si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
53     } else {
54         if (ext_call) {
55             status |= SIGP_STAT_EXT_CALL_PENDING;
56         }
57         if (state == S390_CPU_STATE_STOPPED) {
58             status |= SIGP_STAT_STOPPED;
59         }
60         set_sigp_status(si, status);
61     }
62 }
63 
64 static void sigp_external_call(S390CPU *src_cpu, S390CPU *dst_cpu, SigpInfo *si)
65 {
66     int ret;
67 
68     if (!tcg_enabled()) {
69         /* handled in KVM */
70         set_sigp_status(si, SIGP_STAT_INVALID_ORDER);
71         return;
72     }
73 
74     ret = cpu_inject_external_call(dst_cpu, src_cpu->env.core_id);
75     if (!ret) {
76         si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
77     } else {
78         set_sigp_status(si, SIGP_STAT_EXT_CALL_PENDING);
79     }
80 }
81 
82 static void sigp_emergency(S390CPU *src_cpu, S390CPU *dst_cpu, SigpInfo *si)
83 {
84     if (!tcg_enabled()) {
85         /* handled in KVM */
86         set_sigp_status(si, SIGP_STAT_INVALID_ORDER);
87         return;
88     }
89 
90     cpu_inject_emergency_signal(dst_cpu, src_cpu->env.core_id);
91     si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
92 }
93 
94 static void sigp_start(CPUState *cs, run_on_cpu_data arg)
95 {
96     S390CPU *cpu = S390_CPU(cs);
97     SigpInfo *si = arg.host_ptr;
98 
99     if (s390_cpu_get_state(cpu) != S390_CPU_STATE_STOPPED) {
100         si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
101         return;
102     }
103 
104     s390_cpu_set_state(S390_CPU_STATE_OPERATING, cpu);
105     si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
106 }
107 
108 static void sigp_stop(CPUState *cs, run_on_cpu_data arg)
109 {
110     S390CPU *cpu = S390_CPU(cs);
111     SigpInfo *si = arg.host_ptr;
112 
113     if (s390_cpu_get_state(cpu) != S390_CPU_STATE_OPERATING) {
114         si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
115         return;
116     }
117 
118     /* disabled wait - sleeping in user space */
119     if (cs->halted) {
120         s390_cpu_set_state(S390_CPU_STATE_STOPPED, cpu);
121     } else {
122         /* execute the stop function */
123         cpu->env.sigp_order = SIGP_STOP;
124         cpu_inject_stop(cpu);
125     }
126     si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
127 }
128 
129 static void sigp_stop_and_store_status(CPUState *cs, run_on_cpu_data arg)
130 {
131     S390CPU *cpu = S390_CPU(cs);
132     SigpInfo *si = arg.host_ptr;
133 
134     /* disabled wait - sleeping in user space */
135     if (s390_cpu_get_state(cpu) == S390_CPU_STATE_OPERATING && cs->halted) {
136         s390_cpu_set_state(S390_CPU_STATE_STOPPED, cpu);
137     }
138 
139     switch (s390_cpu_get_state(cpu)) {
140     case S390_CPU_STATE_OPERATING:
141         cpu->env.sigp_order = SIGP_STOP_STORE_STATUS;
142         cpu_inject_stop(cpu);
143         /* store will be performed in do_stop_interrupt() */
144         break;
145     case S390_CPU_STATE_STOPPED:
146         /* already stopped, just store the status */
147         cpu_synchronize_state(cs);
148         s390_store_status(cpu, S390_STORE_STATUS_DEF_ADDR, true);
149         break;
150     }
151     si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
152 }
153 
154 static void sigp_store_status_at_address(CPUState *cs, run_on_cpu_data arg)
155 {
156     S390CPU *cpu = S390_CPU(cs);
157     SigpInfo *si = arg.host_ptr;
158     uint32_t address = si->param & 0x7ffffe00u;
159 
160     /* cpu has to be stopped */
161     if (s390_cpu_get_state(cpu) != S390_CPU_STATE_STOPPED) {
162         set_sigp_status(si, SIGP_STAT_INCORRECT_STATE);
163         return;
164     }
165 
166     cpu_synchronize_state(cs);
167 
168     if (s390_store_status(cpu, address, false)) {
169         set_sigp_status(si, SIGP_STAT_INVALID_PARAMETER);
170         return;
171     }
172     si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
173 }
174 
175 #define ADTL_SAVE_LC_MASK  0xfUL
176 static void sigp_store_adtl_status(CPUState *cs, run_on_cpu_data arg)
177 {
178     S390CPU *cpu = S390_CPU(cs);
179     SigpInfo *si = arg.host_ptr;
180     uint8_t lc = si->param & ADTL_SAVE_LC_MASK;
181     hwaddr addr = si->param & ~ADTL_SAVE_LC_MASK;
182     hwaddr len = 1UL << (lc ? lc : 10);
183 
184     if (!s390_has_feat(S390_FEAT_VECTOR) &&
185         !s390_has_feat(S390_FEAT_GUARDED_STORAGE)) {
186         set_sigp_status(si, SIGP_STAT_INVALID_ORDER);
187         return;
188     }
189 
190     /* cpu has to be stopped */
191     if (s390_cpu_get_state(cpu) != S390_CPU_STATE_STOPPED) {
192         set_sigp_status(si, SIGP_STAT_INCORRECT_STATE);
193         return;
194     }
195 
196     /* address must be aligned to length */
197     if (addr & (len - 1)) {
198         set_sigp_status(si, SIGP_STAT_INVALID_PARAMETER);
199         return;
200     }
201 
202     /* no GS: only lc == 0 is valid */
203     if (!s390_has_feat(S390_FEAT_GUARDED_STORAGE) &&
204         lc != 0) {
205         set_sigp_status(si, SIGP_STAT_INVALID_PARAMETER);
206         return;
207     }
208 
209     /* GS: 0, 10, 11, 12 are valid */
210     if (s390_has_feat(S390_FEAT_GUARDED_STORAGE) &&
211         lc != 0 &&
212         lc != 10 &&
213         lc != 11 &&
214         lc != 12) {
215         set_sigp_status(si, SIGP_STAT_INVALID_PARAMETER);
216         return;
217     }
218 
219     cpu_synchronize_state(cs);
220 
221     if (s390_store_adtl_status(cpu, addr, len)) {
222         set_sigp_status(si, SIGP_STAT_INVALID_PARAMETER);
223         return;
224     }
225     si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
226 }
227 
228 static void sigp_restart(CPUState *cs, run_on_cpu_data arg)
229 {
230     S390CPU *cpu = S390_CPU(cs);
231     SigpInfo *si = arg.host_ptr;
232 
233     switch (s390_cpu_get_state(cpu)) {
234     case S390_CPU_STATE_STOPPED:
235         /* the restart irq has to be delivered prior to any other pending irq */
236         cpu_synchronize_state(cs);
237         /*
238          * Set OPERATING (and unhalting) before loading the restart PSW.
239          * s390_cpu_set_psw() will then properly halt the CPU again if
240          * necessary (TCG).
241          */
242         s390_cpu_set_state(S390_CPU_STATE_OPERATING, cpu);
243         do_restart_interrupt(&cpu->env);
244         break;
245     case S390_CPU_STATE_OPERATING:
246         cpu_inject_restart(cpu);
247         break;
248     }
249     si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
250 }
251 
252 static void sigp_initial_cpu_reset(CPUState *cs, run_on_cpu_data arg)
253 {
254     S390CPU *cpu = S390_CPU(cs);
255     S390CPUClass *scc = S390_CPU_GET_CLASS(cpu);
256     SigpInfo *si = arg.host_ptr;
257 
258     cpu_synchronize_state(cs);
259     scc->reset(cs, S390_CPU_RESET_INITIAL);
260     cpu_synchronize_post_reset(cs);
261     si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
262 }
263 
264 static void sigp_cpu_reset(CPUState *cs, run_on_cpu_data arg)
265 {
266     S390CPU *cpu = S390_CPU(cs);
267     S390CPUClass *scc = S390_CPU_GET_CLASS(cpu);
268     SigpInfo *si = arg.host_ptr;
269 
270     cpu_synchronize_state(cs);
271     scc->reset(cs, S390_CPU_RESET_NORMAL);
272     cpu_synchronize_post_reset(cs);
273     si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
274 }
275 
276 static void sigp_set_prefix(CPUState *cs, run_on_cpu_data arg)
277 {
278     S390CPU *cpu = S390_CPU(cs);
279     SigpInfo *si = arg.host_ptr;
280     uint32_t addr = si->param & 0x7fffe000u;
281 
282     cpu_synchronize_state(cs);
283 
284     if (!address_space_access_valid(&address_space_memory, addr,
285                                     sizeof(struct LowCore), false,
286                                     MEMTXATTRS_UNSPECIFIED)) {
287         set_sigp_status(si, SIGP_STAT_INVALID_PARAMETER);
288         return;
289     }
290 
291     /* cpu has to be stopped */
292     if (s390_cpu_get_state(cpu) != S390_CPU_STATE_STOPPED) {
293         set_sigp_status(si, SIGP_STAT_INCORRECT_STATE);
294         return;
295     }
296 
297     cpu->env.psa = addr;
298     tlb_flush(cs);
299     cpu_synchronize_post_init(cs);
300     si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
301 }
302 
303 static void sigp_cond_emergency(S390CPU *src_cpu, S390CPU *dst_cpu,
304                                 SigpInfo *si)
305 {
306     const uint64_t psw_int_mask = PSW_MASK_IO | PSW_MASK_EXT;
307     uint16_t p_asn, s_asn, asn;
308     uint64_t psw_addr, psw_mask;
309     bool idle;
310 
311     if (!tcg_enabled()) {
312         /* handled in KVM */
313         set_sigp_status(si, SIGP_STAT_INVALID_ORDER);
314         return;
315     }
316 
317     /* this looks racy, but these values are only used when STOPPED */
318     idle = CPU(dst_cpu)->halted;
319     psw_addr = dst_cpu->env.psw.addr;
320     psw_mask = dst_cpu->env.psw.mask;
321     asn = si->param;
322     p_asn = dst_cpu->env.cregs[4] & 0xffff;  /* Primary ASN */
323     s_asn = dst_cpu->env.cregs[3] & 0xffff;  /* Secondary ASN */
324 
325     if (s390_cpu_get_state(dst_cpu) != S390_CPU_STATE_STOPPED ||
326         (psw_mask & psw_int_mask) != psw_int_mask ||
327         (idle && psw_addr != 0) ||
328         (!idle && (asn == p_asn || asn == s_asn))) {
329         cpu_inject_emergency_signal(dst_cpu, src_cpu->env.core_id);
330     } else {
331         set_sigp_status(si, SIGP_STAT_INCORRECT_STATE);
332     }
333 
334     si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
335 }
336 
337 static void sigp_sense_running(S390CPU *dst_cpu, SigpInfo *si)
338 {
339     if (!tcg_enabled()) {
340         /* handled in KVM */
341         set_sigp_status(si, SIGP_STAT_INVALID_ORDER);
342         return;
343     }
344 
345     /* sensing without locks is racy, but it's the same for real hw */
346     if (!s390_has_feat(S390_FEAT_SENSE_RUNNING_STATUS)) {
347         set_sigp_status(si, SIGP_STAT_INVALID_ORDER);
348         return;
349     }
350 
351     /* If halted (which includes also STOPPED), it is not running */
352     if (CPU(dst_cpu)->halted) {
353         set_sigp_status(si, SIGP_STAT_NOT_RUNNING);
354     } else {
355         si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
356     }
357 }
358 
359 static int handle_sigp_single_dst(S390CPU *cpu, S390CPU *dst_cpu, uint8_t order,
360                                   uint64_t param, uint64_t *status_reg)
361 {
362     SigpInfo si = {
363         .param = param,
364         .status_reg = status_reg,
365     };
366 
367     /* cpu available? */
368     if (dst_cpu == NULL) {
369         return SIGP_CC_NOT_OPERATIONAL;
370     }
371 
372     /* only resets can break pending orders */
373     if (dst_cpu->env.sigp_order != 0 &&
374         order != SIGP_CPU_RESET &&
375         order != SIGP_INITIAL_CPU_RESET) {
376         return SIGP_CC_BUSY;
377     }
378 
379     switch (order) {
380     case SIGP_SENSE:
381         sigp_sense(dst_cpu, &si);
382         break;
383     case SIGP_EXTERNAL_CALL:
384         sigp_external_call(cpu, dst_cpu, &si);
385         break;
386     case SIGP_EMERGENCY:
387         sigp_emergency(cpu, dst_cpu, &si);
388         break;
389     case SIGP_START:
390         run_on_cpu(CPU(dst_cpu), sigp_start, RUN_ON_CPU_HOST_PTR(&si));
391         break;
392     case SIGP_STOP:
393         run_on_cpu(CPU(dst_cpu), sigp_stop, RUN_ON_CPU_HOST_PTR(&si));
394         break;
395     case SIGP_RESTART:
396         run_on_cpu(CPU(dst_cpu), sigp_restart, RUN_ON_CPU_HOST_PTR(&si));
397         break;
398     case SIGP_STOP_STORE_STATUS:
399         run_on_cpu(CPU(dst_cpu), sigp_stop_and_store_status, RUN_ON_CPU_HOST_PTR(&si));
400         break;
401     case SIGP_STORE_STATUS_ADDR:
402         run_on_cpu(CPU(dst_cpu), sigp_store_status_at_address, RUN_ON_CPU_HOST_PTR(&si));
403         break;
404     case SIGP_STORE_ADTL_STATUS:
405         run_on_cpu(CPU(dst_cpu), sigp_store_adtl_status, RUN_ON_CPU_HOST_PTR(&si));
406         break;
407     case SIGP_SET_PREFIX:
408         run_on_cpu(CPU(dst_cpu), sigp_set_prefix, RUN_ON_CPU_HOST_PTR(&si));
409         break;
410     case SIGP_INITIAL_CPU_RESET:
411         run_on_cpu(CPU(dst_cpu), sigp_initial_cpu_reset, RUN_ON_CPU_HOST_PTR(&si));
412         break;
413     case SIGP_CPU_RESET:
414         run_on_cpu(CPU(dst_cpu), sigp_cpu_reset, RUN_ON_CPU_HOST_PTR(&si));
415         break;
416     case SIGP_COND_EMERGENCY:
417         sigp_cond_emergency(cpu, dst_cpu, &si);
418         break;
419     case SIGP_SENSE_RUNNING:
420         sigp_sense_running(dst_cpu, &si);
421         break;
422     default:
423         set_sigp_status(&si, SIGP_STAT_INVALID_ORDER);
424     }
425 
426     return si.cc;
427 }
428 
429 static int sigp_set_architecture(S390CPU *cpu, uint32_t param,
430                                  uint64_t *status_reg)
431 {
432     *status_reg &= 0xffffffff00000000ULL;
433 
434     /* Reject set arch order, with czam we're always in z/Arch mode. */
435     *status_reg |= SIGP_STAT_INVALID_PARAMETER;
436     return SIGP_CC_STATUS_STORED;
437 }
438 
439 S390CPU *s390_cpu_addr2state(uint16_t cpu_addr)
440 {
441     static MachineState *ms;
442 
443     if (!ms) {
444         ms = MACHINE(qdev_get_machine());
445         g_assert(ms->possible_cpus);
446     }
447 
448     /* CPU address corresponds to the core_id and the index */
449     if (cpu_addr >= ms->possible_cpus->len) {
450         return NULL;
451     }
452     return S390_CPU(ms->possible_cpus->cpus[cpu_addr].cpu);
453 }
454 
455 int handle_sigp(CPUS390XState *env, uint8_t order, uint64_t r1, uint64_t r3)
456 {
457     uint64_t *status_reg = &env->regs[r1];
458     uint64_t param = (r1 % 2) ? env->regs[r1] : env->regs[r1 + 1];
459     S390CPU *cpu = env_archcpu(env);
460     S390CPU *dst_cpu = NULL;
461     int ret;
462 
463     if (qemu_mutex_trylock(&qemu_sigp_mutex)) {
464         ret = SIGP_CC_BUSY;
465         goto out;
466     }
467 
468     switch (order) {
469     case SIGP_SET_ARCH:
470         ret = sigp_set_architecture(cpu, param, status_reg);
471         break;
472     default:
473         /* all other sigp orders target a single vcpu */
474         dst_cpu = s390_cpu_addr2state(env->regs[r3]);
475         ret = handle_sigp_single_dst(cpu, dst_cpu, order, param, status_reg);
476     }
477     qemu_mutex_unlock(&qemu_sigp_mutex);
478 
479 out:
480     trace_sigp_finished(order, CPU(cpu)->cpu_index,
481                         dst_cpu ? CPU(dst_cpu)->cpu_index : -1, ret);
482     g_assert(ret >= 0);
483 
484     return ret;
485 }
486 
487 int s390_cpu_restart(S390CPU *cpu)
488 {
489     SigpInfo si = {};
490 
491     run_on_cpu(CPU(cpu), sigp_restart, RUN_ON_CPU_HOST_PTR(&si));
492     return 0;
493 }
494 
495 void do_stop_interrupt(CPUS390XState *env)
496 {
497     S390CPU *cpu = env_archcpu(env);
498 
499     /*
500      * Complete the STOP operation before exposing the CPU as
501      * STOPPED to the system.
502      */
503     if (cpu->env.sigp_order == SIGP_STOP_STORE_STATUS) {
504         s390_store_status(cpu, S390_STORE_STATUS_DEF_ADDR, true);
505     }
506     env->sigp_order = 0;
507     if (s390_cpu_set_state(S390_CPU_STATE_STOPPED, cpu) == 0) {
508         qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
509     }
510     env->pending_int &= ~INTERRUPT_STOP;
511 }
512 
513 void s390_init_sigp(void)
514 {
515     qemu_mutex_init(&qemu_sigp_mutex);
516 }
517