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
set_sigp_status(SigpInfo * si,uint64_t status)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
sigp_sense(S390CPU * dst_cpu,SigpInfo * si)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
sigp_external_call(S390CPU * src_cpu,S390CPU * dst_cpu,SigpInfo * si)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
sigp_emergency(S390CPU * src_cpu,S390CPU * dst_cpu,SigpInfo * si)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
sigp_start(CPUState * cs,run_on_cpu_data arg)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
sigp_stop(CPUState * cs,run_on_cpu_data arg)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
sigp_stop_and_store_status(CPUState * cs,run_on_cpu_data arg)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
sigp_store_status_at_address(CPUState * cs,run_on_cpu_data arg)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
sigp_store_adtl_status(CPUState * cs,run_on_cpu_data arg)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
sigp_restart(CPUState * cs,run_on_cpu_data arg)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
sigp_initial_cpu_reset(CPUState * cs,run_on_cpu_data arg)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
sigp_cpu_reset(CPUState * cs,run_on_cpu_data arg)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
sigp_set_prefix(CPUState * cs,run_on_cpu_data arg)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
sigp_cond_emergency(S390CPU * src_cpu,S390CPU * dst_cpu,SigpInfo * si)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
sigp_sense_running(S390CPU * dst_cpu,SigpInfo * si)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
handle_sigp_single_dst(S390CPU * cpu,S390CPU * dst_cpu,uint8_t order,uint64_t param,uint64_t * status_reg)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
sigp_set_architecture(S390CPU * cpu,uint32_t param,uint64_t * status_reg)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
s390_cpu_addr2state(uint16_t cpu_addr)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
handle_sigp(CPUS390XState * env,uint8_t order,uint64_t r1,uint64_t r3)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
s390_cpu_restart(S390CPU * cpu)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
do_stop_interrupt(CPUS390XState * env)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
s390_init_sigp(void)513 void s390_init_sigp(void)
514 {
515 qemu_mutex_init(&qemu_sigp_mutex);
516 }
517