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.
11 #include "qemu/osdep.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"
21 #include "qapi/qapi-types-machine.h"
23 QemuMutex qemu_sigp_mutex
;
25 typedef struct SigpInfo
{
31 static void set_sigp_status(SigpInfo
*si
, uint64_t status
)
33 *si
->status_reg
&= 0xffffffff00000000ULL
;
34 *si
->status_reg
|= status
;
35 si
->cc
= SIGP_CC_STATUS_STORED
;
38 static void sigp_sense(S390CPU
*dst_cpu
, SigpInfo
*si
)
40 uint8_t state
= s390_cpu_get_state(dst_cpu
);
41 bool ext_call
= dst_cpu
->env
.pending_int
& INTERRUPT_EXTERNAL_CALL
;
46 set_sigp_status(si
, SIGP_STAT_INVALID_ORDER
);
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
;
55 status
|= SIGP_STAT_EXT_CALL_PENDING
;
57 if (state
== S390_CPU_STATE_STOPPED
) {
58 status
|= SIGP_STAT_STOPPED
;
60 set_sigp_status(si
, status
);
64 static void sigp_external_call(S390CPU
*src_cpu
, S390CPU
*dst_cpu
, SigpInfo
*si
)
70 set_sigp_status(si
, SIGP_STAT_INVALID_ORDER
);
74 ret
= cpu_inject_external_call(dst_cpu
, src_cpu
->env
.core_id
);
76 si
->cc
= SIGP_CC_ORDER_CODE_ACCEPTED
;
78 set_sigp_status(si
, SIGP_STAT_EXT_CALL_PENDING
);
82 static void sigp_emergency(S390CPU
*src_cpu
, S390CPU
*dst_cpu
, SigpInfo
*si
)
86 set_sigp_status(si
, SIGP_STAT_INVALID_ORDER
);
90 cpu_inject_emergency_signal(dst_cpu
, src_cpu
->env
.core_id
);
91 si
->cc
= SIGP_CC_ORDER_CODE_ACCEPTED
;
94 static void sigp_start(CPUState
*cs
, run_on_cpu_data arg
)
96 S390CPU
*cpu
= S390_CPU(cs
);
97 SigpInfo
*si
= arg
.host_ptr
;
99 if (s390_cpu_get_state(cpu
) != S390_CPU_STATE_STOPPED
) {
100 si
->cc
= SIGP_CC_ORDER_CODE_ACCEPTED
;
104 s390_cpu_set_state(S390_CPU_STATE_OPERATING
, cpu
);
105 si
->cc
= SIGP_CC_ORDER_CODE_ACCEPTED
;
108 static void sigp_stop(CPUState
*cs
, run_on_cpu_data arg
)
110 S390CPU
*cpu
= S390_CPU(cs
);
111 SigpInfo
*si
= arg
.host_ptr
;
113 if (s390_cpu_get_state(cpu
) != S390_CPU_STATE_OPERATING
) {
114 si
->cc
= SIGP_CC_ORDER_CODE_ACCEPTED
;
118 /* disabled wait - sleeping in user space */
120 s390_cpu_set_state(S390_CPU_STATE_STOPPED
, cpu
);
122 /* execute the stop function */
123 cpu
->env
.sigp_order
= SIGP_STOP
;
124 cpu_inject_stop(cpu
);
126 si
->cc
= SIGP_CC_ORDER_CODE_ACCEPTED
;
129 static void sigp_stop_and_store_status(CPUState
*cs
, run_on_cpu_data arg
)
131 S390CPU
*cpu
= S390_CPU(cs
);
132 SigpInfo
*si
= arg
.host_ptr
;
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
);
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() */
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);
151 si
->cc
= SIGP_CC_ORDER_CODE_ACCEPTED
;
154 static void sigp_store_status_at_address(CPUState
*cs
, run_on_cpu_data arg
)
156 S390CPU
*cpu
= S390_CPU(cs
);
157 SigpInfo
*si
= arg
.host_ptr
;
158 uint32_t address
= si
->param
& 0x7ffffe00u
;
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
);
166 cpu_synchronize_state(cs
);
168 if (s390_store_status(cpu
, address
, false)) {
169 set_sigp_status(si
, SIGP_STAT_INVALID_PARAMETER
);
172 si
->cc
= SIGP_CC_ORDER_CODE_ACCEPTED
;
175 #define ADTL_SAVE_LC_MASK 0xfUL
176 static void sigp_store_adtl_status(CPUState
*cs
, run_on_cpu_data arg
)
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);
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
);
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
);
196 /* address must be aligned to length */
197 if (addr
& (len
- 1)) {
198 set_sigp_status(si
, SIGP_STAT_INVALID_PARAMETER
);
202 /* no GS: only lc == 0 is valid */
203 if (!s390_has_feat(S390_FEAT_GUARDED_STORAGE
) &&
205 set_sigp_status(si
, SIGP_STAT_INVALID_PARAMETER
);
209 /* GS: 0, 10, 11, 12 are valid */
210 if (s390_has_feat(S390_FEAT_GUARDED_STORAGE
) &&
215 set_sigp_status(si
, SIGP_STAT_INVALID_PARAMETER
);
219 cpu_synchronize_state(cs
);
221 if (s390_store_adtl_status(cpu
, addr
, len
)) {
222 set_sigp_status(si
, SIGP_STAT_INVALID_PARAMETER
);
225 si
->cc
= SIGP_CC_ORDER_CODE_ACCEPTED
;
228 static void sigp_restart(CPUState
*cs
, run_on_cpu_data arg
)
230 S390CPU
*cpu
= S390_CPU(cs
);
231 SigpInfo
*si
= arg
.host_ptr
;
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
);
238 * Set OPERATING (and unhalting) before loading the restart PSW.
239 * s390_cpu_set_psw() will then properly halt the CPU again if
242 s390_cpu_set_state(S390_CPU_STATE_OPERATING
, cpu
);
243 do_restart_interrupt(&cpu
->env
);
245 case S390_CPU_STATE_OPERATING
:
246 cpu_inject_restart(cpu
);
249 si
->cc
= SIGP_CC_ORDER_CODE_ACCEPTED
;
252 static void sigp_initial_cpu_reset(CPUState
*cs
, run_on_cpu_data arg
)
254 S390CPU
*cpu
= S390_CPU(cs
);
255 S390CPUClass
*scc
= S390_CPU_GET_CLASS(cpu
);
256 SigpInfo
*si
= arg
.host_ptr
;
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
;
264 static void sigp_cpu_reset(CPUState
*cs
, run_on_cpu_data arg
)
266 S390CPU
*cpu
= S390_CPU(cs
);
267 S390CPUClass
*scc
= S390_CPU_GET_CLASS(cpu
);
268 SigpInfo
*si
= arg
.host_ptr
;
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
;
276 static void sigp_set_prefix(CPUState
*cs
, run_on_cpu_data arg
)
278 S390CPU
*cpu
= S390_CPU(cs
);
279 SigpInfo
*si
= arg
.host_ptr
;
280 uint32_t addr
= si
->param
& 0x7fffe000u
;
282 cpu_synchronize_state(cs
);
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
);
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
);
299 cpu_synchronize_post_init(cs
);
300 si
->cc
= SIGP_CC_ORDER_CODE_ACCEPTED
;
303 static void sigp_cond_emergency(S390CPU
*src_cpu
, S390CPU
*dst_cpu
,
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
;
311 if (!tcg_enabled()) {
313 set_sigp_status(si
, SIGP_STAT_INVALID_ORDER
);
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
;
322 p_asn
= dst_cpu
->env
.cregs
[4] & 0xffff; /* Primary ASN */
323 s_asn
= dst_cpu
->env
.cregs
[3] & 0xffff; /* Secondary ASN */
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
);
331 set_sigp_status(si
, SIGP_STAT_INCORRECT_STATE
);
334 si
->cc
= SIGP_CC_ORDER_CODE_ACCEPTED
;
337 static void sigp_sense_running(S390CPU
*dst_cpu
, SigpInfo
*si
)
339 if (!tcg_enabled()) {
341 set_sigp_status(si
, SIGP_STAT_INVALID_ORDER
);
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
);
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
);
355 si
->cc
= SIGP_CC_ORDER_CODE_ACCEPTED
;
359 static int handle_sigp_single_dst(S390CPU
*cpu
, S390CPU
*dst_cpu
, uint8_t order
,
360 uint64_t param
, uint64_t *status_reg
)
364 .status_reg
= status_reg
,
368 if (dst_cpu
== NULL
) {
369 return SIGP_CC_NOT_OPERATIONAL
;
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
) {
381 sigp_sense(dst_cpu
, &si
);
383 case SIGP_EXTERNAL_CALL
:
384 sigp_external_call(cpu
, dst_cpu
, &si
);
387 sigp_emergency(cpu
, dst_cpu
, &si
);
390 run_on_cpu(CPU(dst_cpu
), sigp_start
, RUN_ON_CPU_HOST_PTR(&si
));
393 run_on_cpu(CPU(dst_cpu
), sigp_stop
, RUN_ON_CPU_HOST_PTR(&si
));
396 run_on_cpu(CPU(dst_cpu
), sigp_restart
, RUN_ON_CPU_HOST_PTR(&si
));
398 case SIGP_STOP_STORE_STATUS
:
399 run_on_cpu(CPU(dst_cpu
), sigp_stop_and_store_status
, RUN_ON_CPU_HOST_PTR(&si
));
401 case SIGP_STORE_STATUS_ADDR
:
402 run_on_cpu(CPU(dst_cpu
), sigp_store_status_at_address
, RUN_ON_CPU_HOST_PTR(&si
));
404 case SIGP_STORE_ADTL_STATUS
:
405 run_on_cpu(CPU(dst_cpu
), sigp_store_adtl_status
, RUN_ON_CPU_HOST_PTR(&si
));
407 case SIGP_SET_PREFIX
:
408 run_on_cpu(CPU(dst_cpu
), sigp_set_prefix
, RUN_ON_CPU_HOST_PTR(&si
));
410 case SIGP_INITIAL_CPU_RESET
:
411 run_on_cpu(CPU(dst_cpu
), sigp_initial_cpu_reset
, RUN_ON_CPU_HOST_PTR(&si
));
414 run_on_cpu(CPU(dst_cpu
), sigp_cpu_reset
, RUN_ON_CPU_HOST_PTR(&si
));
416 case SIGP_COND_EMERGENCY
:
417 sigp_cond_emergency(cpu
, dst_cpu
, &si
);
419 case SIGP_SENSE_RUNNING
:
420 sigp_sense_running(dst_cpu
, &si
);
423 set_sigp_status(&si
, SIGP_STAT_INVALID_ORDER
);
429 static int sigp_set_architecture(S390CPU
*cpu
, uint32_t param
,
430 uint64_t *status_reg
)
432 *status_reg
&= 0xffffffff00000000ULL
;
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
;
439 S390CPU
*s390_cpu_addr2state(uint16_t cpu_addr
)
441 static MachineState
*ms
;
444 ms
= MACHINE(qdev_get_machine());
445 g_assert(ms
->possible_cpus
);
448 /* CPU address corresponds to the core_id and the index */
449 if (cpu_addr
>= ms
->possible_cpus
->len
) {
452 return S390_CPU(ms
->possible_cpus
->cpus
[cpu_addr
].cpu
);
455 int handle_sigp(CPUS390XState
*env
, uint8_t order
, uint64_t r1
, uint64_t r3
)
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
;
463 if (qemu_mutex_trylock(&qemu_sigp_mutex
)) {
470 ret
= sigp_set_architecture(cpu
, param
, status_reg
);
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
);
477 qemu_mutex_unlock(&qemu_sigp_mutex
);
480 trace_sigp_finished(order
, CPU(cpu
)->cpu_index
,
481 dst_cpu
? CPU(dst_cpu
)->cpu_index
: -1, ret
);
487 int s390_cpu_restart(S390CPU
*cpu
)
491 run_on_cpu(CPU(cpu
), sigp_restart
, RUN_ON_CPU_HOST_PTR(&si
));
495 void do_stop_interrupt(CPUS390XState
*env
)
497 S390CPU
*cpu
= env_archcpu(env
);
500 * Complete the STOP operation before exposing the CPU as
501 * STOPPED to the system.
503 if (cpu
->env
.sigp_order
== SIGP_STOP_STORE_STATUS
) {
504 s390_store_status(cpu
, S390_STORE_STATUS_DEF_ADDR
, true);
507 if (s390_cpu_set_state(S390_CPU_STATE_STOPPED
, cpu
) == 0) {
508 qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN
);
510 env
->pending_int
&= ~INTERRUPT_STOP
;
513 void s390_init_sigp(void)
515 qemu_mutex_init(&qemu_sigp_mutex
);