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