remove space-tab sequences
[qemu/ar7.git] / target / s390x / sigp.c
blobc1f9245797e787ea926fd6ea4ab20a749fa94240
1 /*
2 * s390x SIGP instruction handling
4 * Copyright (c) 2009 Alexander Graf <agraf@suse.de>
5 * Copyright IBM Corp. 2012
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 */
11 #include "qemu/osdep.h"
12 #include "qemu-common.h"
13 #include "cpu.h"
14 #include "internal.h"
15 #include "sysemu/hw_accel.h"
16 #include "exec/address-spaces.h"
17 #include "exec/exec-all.h"
18 #include "sysemu/sysemu.h"
19 #include "trace.h"
20 #include "qapi/qapi-types-misc.h"
22 QemuMutex qemu_sigp_mutex;
24 typedef struct SigpInfo {
25 uint64_t param;
26 int cc;
27 uint64_t *status_reg;
28 } SigpInfo;
30 static void set_sigp_status(SigpInfo *si, uint64_t status)
32 *si->status_reg &= 0xffffffff00000000ULL;
33 *si->status_reg |= status;
34 si->cc = SIGP_CC_STATUS_STORED;
37 static void sigp_sense(S390CPU *dst_cpu, SigpInfo *si)
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;
43 if (!tcg_enabled()) {
44 /* handled in KVM */
45 set_sigp_status(si, SIGP_STAT_INVALID_ORDER);
46 return;
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;
56 if (state == S390_CPU_STATE_STOPPED) {
57 status |= SIGP_STAT_STOPPED;
59 set_sigp_status(si, status);
63 static void sigp_external_call(S390CPU *src_cpu, S390CPU *dst_cpu, SigpInfo *si)
65 int ret;
67 if (!tcg_enabled()) {
68 /* handled in KVM */
69 set_sigp_status(si, SIGP_STAT_INVALID_ORDER);
70 return;
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);
81 static void sigp_emergency(S390CPU *src_cpu, S390CPU *dst_cpu, SigpInfo *si)
83 if (!tcg_enabled()) {
84 /* handled in KVM */
85 set_sigp_status(si, SIGP_STAT_INVALID_ORDER);
86 return;
89 cpu_inject_emergency_signal(dst_cpu, src_cpu->env.core_id);
90 si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
93 static void sigp_start(CPUState *cs, run_on_cpu_data arg)
95 S390CPU *cpu = S390_CPU(cs);
96 SigpInfo *si = arg.host_ptr;
98 if (s390_cpu_get_state(cpu) != S390_CPU_STATE_STOPPED) {
99 si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
100 return;
103 s390_cpu_set_state(S390_CPU_STATE_OPERATING, cpu);
104 si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
107 static void sigp_stop(CPUState *cs, run_on_cpu_data arg)
109 S390CPU *cpu = S390_CPU(cs);
110 SigpInfo *si = arg.host_ptr;
112 if (s390_cpu_get_state(cpu) != S390_CPU_STATE_OPERATING) {
113 si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
114 return;
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);
125 si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
128 static void sigp_stop_and_store_status(CPUState *cs, run_on_cpu_data arg)
130 S390CPU *cpu = S390_CPU(cs);
131 SigpInfo *si = arg.host_ptr;
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);
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;
150 si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
153 static void sigp_store_status_at_address(CPUState *cs, run_on_cpu_data arg)
155 S390CPU *cpu = S390_CPU(cs);
156 SigpInfo *si = arg.host_ptr;
157 uint32_t address = si->param & 0x7ffffe00u;
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;
165 cpu_synchronize_state(cs);
167 if (s390_store_status(cpu, address, false)) {
168 set_sigp_status(si, SIGP_STAT_INVALID_PARAMETER);
169 return;
171 si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
174 #define ADTL_SAVE_LC_MASK 0xfUL
175 static void sigp_store_adtl_status(CPUState *cs, run_on_cpu_data arg)
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);
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;
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;
195 /* address must be aligned to length */
196 if (addr & (len - 1)) {
197 set_sigp_status(si, SIGP_STAT_INVALID_PARAMETER);
198 return;
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;
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;
218 cpu_synchronize_state(cs);
220 if (s390_store_adtl_status(cpu, addr, len)) {
221 set_sigp_status(si, SIGP_STAT_INVALID_PARAMETER);
222 return;
224 si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
227 static void sigp_restart(CPUState *cs, run_on_cpu_data arg)
229 S390CPU *cpu = S390_CPU(cs);
230 SigpInfo *si = arg.host_ptr;
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);
237 * Set OPERATING (and unhalting) before loading the restart PSW.
238 * load_psw() will then properly halt the CPU again if necessary (TCG).
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;
247 si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
250 static void sigp_initial_cpu_reset(CPUState *cs, run_on_cpu_data arg)
252 S390CPU *cpu = S390_CPU(cs);
253 S390CPUClass *scc = S390_CPU_GET_CLASS(cpu);
254 SigpInfo *si = arg.host_ptr;
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;
262 static void sigp_cpu_reset(CPUState *cs, run_on_cpu_data arg)
264 S390CPU *cpu = S390_CPU(cs);
265 S390CPUClass *scc = S390_CPU_GET_CLASS(cpu);
266 SigpInfo *si = arg.host_ptr;
268 cpu_synchronize_state(cs);
269 scc->cpu_reset(cs);
270 cpu_synchronize_post_reset(cs);
271 si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
274 static void sigp_set_prefix(CPUState *cs, run_on_cpu_data arg)
276 S390CPU *cpu = S390_CPU(cs);
277 SigpInfo *si = arg.host_ptr;
278 uint32_t addr = si->param & 0x7fffe000u;
280 cpu_synchronize_state(cs);
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;
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;
295 cpu->env.psa = addr;
296 tlb_flush(cs);
297 cpu_synchronize_post_init(cs);
298 si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
301 static void sigp_cond_emergency(S390CPU *src_cpu, S390CPU *dst_cpu,
302 SigpInfo *si)
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;
309 if (!tcg_enabled()) {
310 /* handled in KVM */
311 set_sigp_status(si, SIGP_STAT_INVALID_ORDER);
312 return;
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 */
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);
332 si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
335 static void sigp_sense_running(S390CPU *dst_cpu, SigpInfo *si)
337 if (!tcg_enabled()) {
338 /* handled in KVM */
339 set_sigp_status(si, SIGP_STAT_INVALID_ORDER);
340 return;
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;
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);
357 static int handle_sigp_single_dst(S390CPU *cpu, S390CPU *dst_cpu, uint8_t order,
358 uint64_t param, uint64_t *status_reg)
360 SigpInfo si = {
361 .param = param,
362 .status_reg = status_reg,
365 /* cpu available? */
366 if (dst_cpu == NULL) {
367 return SIGP_CC_NOT_OPERATIONAL;
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;
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);
424 return si.cc;
427 static int sigp_set_architecture(S390CPU *cpu, uint32_t param,
428 uint64_t *status_reg)
430 CPUState *cur_cs;
431 S390CPU *cur_cpu;
432 bool all_stopped = true;
434 CPU_FOREACH(cur_cs) {
435 cur_cpu = S390_CPU(cur_cs);
437 if (cur_cpu == cpu) {
438 continue;
440 if (s390_cpu_get_state(cur_cpu) != S390_CPU_STATE_STOPPED) {
441 all_stopped = false;
445 *status_reg &= 0xffffffff00000000ULL;
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;
453 int handle_sigp(CPUS390XState *env, uint8_t order, uint64_t r1, uint64_t r3)
455 uint64_t *status_reg = &env->regs[r1];
456 uint64_t param = (r1 % 2) ? env->regs[r1] : env->regs[r1 + 1];
457 S390CPU *cpu = s390_env_get_cpu(env);
458 S390CPU *dst_cpu = NULL;
459 int ret;
461 if (qemu_mutex_trylock(&qemu_sigp_mutex)) {
462 ret = SIGP_CC_BUSY;
463 goto out;
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);
475 qemu_mutex_unlock(&qemu_sigp_mutex);
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);
482 return ret;
485 int s390_cpu_restart(S390CPU *cpu)
487 SigpInfo si = {};
489 run_on_cpu(CPU(cpu), sigp_restart, RUN_ON_CPU_HOST_PTR(&si));
490 return 0;
493 void do_stop_interrupt(CPUS390XState *env)
495 S390CPU *cpu = s390_env_get_cpu(env);
497 if (s390_cpu_set_state(S390_CPU_STATE_STOPPED, cpu) == 0) {
498 qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
500 if (cpu->env.sigp_order == SIGP_STOP_STORE_STATUS) {
501 s390_store_status(cpu, S390_STORE_STATUS_DEF_ADDR, true);
503 env->sigp_order = 0;
504 env->pending_int &= ~INTERRUPT_STOP;
507 void s390_init_sigp(void)
509 qemu_mutex_init(&qemu_sigp_mutex);