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"
12 #include "qemu-common.h"
15 #include "sysemu/hw_accel.h"
16 #include "exec/address-spaces.h"
17 #include "sysemu/sysemu.h"
20 QemuMutex qemu_sigp_mutex
;
22 typedef struct SigpInfo
{
28 static void set_sigp_status(SigpInfo
*si
, uint64_t status
)
30 *si
->status_reg
&= 0xffffffff00000000ULL
;
31 *si
->status_reg
|= status
;
32 si
->cc
= SIGP_CC_STATUS_STORED
;
35 static void sigp_sense(S390CPU
*dst_cpu
, SigpInfo
*si
)
37 uint8_t state
= s390_cpu_get_state(dst_cpu
);
38 bool ext_call
= dst_cpu
->env
.pending_int
& INTERRUPT_EXTERNAL_CALL
;
43 set_sigp_status(si
, SIGP_STAT_INVALID_ORDER
);
47 /* sensing without locks is racy, but it's the same for real hw */
48 if (state
!= CPU_STATE_STOPPED
&& !ext_call
) {
49 si
->cc
= SIGP_CC_ORDER_CODE_ACCEPTED
;
52 status
|= SIGP_STAT_EXT_CALL_PENDING
;
54 if (state
== CPU_STATE_STOPPED
) {
55 status
|= SIGP_STAT_STOPPED
;
57 set_sigp_status(si
, status
);
61 static void sigp_external_call(S390CPU
*src_cpu
, S390CPU
*dst_cpu
, SigpInfo
*si
)
67 set_sigp_status(si
, SIGP_STAT_INVALID_ORDER
);
71 ret
= cpu_inject_external_call(dst_cpu
, src_cpu
->env
.core_id
);
73 si
->cc
= SIGP_CC_ORDER_CODE_ACCEPTED
;
75 set_sigp_status(si
, SIGP_STAT_EXT_CALL_PENDING
);
79 static void sigp_emergency(S390CPU
*src_cpu
, S390CPU
*dst_cpu
, SigpInfo
*si
)
83 set_sigp_status(si
, SIGP_STAT_INVALID_ORDER
);
87 cpu_inject_emergency_signal(dst_cpu
, src_cpu
->env
.core_id
);
88 si
->cc
= SIGP_CC_ORDER_CODE_ACCEPTED
;
91 static void sigp_start(CPUState
*cs
, run_on_cpu_data arg
)
93 S390CPU
*cpu
= S390_CPU(cs
);
94 SigpInfo
*si
= arg
.host_ptr
;
96 if (s390_cpu_get_state(cpu
) != CPU_STATE_STOPPED
) {
97 si
->cc
= SIGP_CC_ORDER_CODE_ACCEPTED
;
101 s390_cpu_set_state(CPU_STATE_OPERATING
, cpu
);
102 si
->cc
= SIGP_CC_ORDER_CODE_ACCEPTED
;
105 static void sigp_stop(CPUState
*cs
, run_on_cpu_data arg
)
107 S390CPU
*cpu
= S390_CPU(cs
);
108 SigpInfo
*si
= arg
.host_ptr
;
110 if (s390_cpu_get_state(cpu
) != CPU_STATE_OPERATING
) {
111 si
->cc
= SIGP_CC_ORDER_CODE_ACCEPTED
;
115 /* disabled wait - sleeping in user space */
117 s390_cpu_set_state(CPU_STATE_STOPPED
, cpu
);
119 /* execute the stop function */
120 cpu
->env
.sigp_order
= SIGP_STOP
;
121 cpu_inject_stop(cpu
);
123 si
->cc
= SIGP_CC_ORDER_CODE_ACCEPTED
;
126 static void sigp_stop_and_store_status(CPUState
*cs
, run_on_cpu_data arg
)
128 S390CPU
*cpu
= S390_CPU(cs
);
129 SigpInfo
*si
= arg
.host_ptr
;
131 /* disabled wait - sleeping in user space */
132 if (s390_cpu_get_state(cpu
) == CPU_STATE_OPERATING
&& cs
->halted
) {
133 s390_cpu_set_state(CPU_STATE_STOPPED
, cpu
);
136 switch (s390_cpu_get_state(cpu
)) {
137 case CPU_STATE_OPERATING
:
138 cpu
->env
.sigp_order
= SIGP_STOP_STORE_STATUS
;
139 cpu_inject_stop(cpu
);
140 /* store will be performed in do_stop_interrup() */
142 case CPU_STATE_STOPPED
:
143 /* already stopped, just store the status */
144 cpu_synchronize_state(cs
);
145 s390_store_status(cpu
, S390_STORE_STATUS_DEF_ADDR
, true);
148 si
->cc
= SIGP_CC_ORDER_CODE_ACCEPTED
;
151 static void sigp_store_status_at_address(CPUState
*cs
, run_on_cpu_data arg
)
153 S390CPU
*cpu
= S390_CPU(cs
);
154 SigpInfo
*si
= arg
.host_ptr
;
155 uint32_t address
= si
->param
& 0x7ffffe00u
;
157 /* cpu has to be stopped */
158 if (s390_cpu_get_state(cpu
) != CPU_STATE_STOPPED
) {
159 set_sigp_status(si
, SIGP_STAT_INCORRECT_STATE
);
163 cpu_synchronize_state(cs
);
165 if (s390_store_status(cpu
, address
, false)) {
166 set_sigp_status(si
, SIGP_STAT_INVALID_PARAMETER
);
169 si
->cc
= SIGP_CC_ORDER_CODE_ACCEPTED
;
172 #define ADTL_SAVE_LC_MASK 0xfUL
173 static void sigp_store_adtl_status(CPUState
*cs
, run_on_cpu_data arg
)
175 S390CPU
*cpu
= S390_CPU(cs
);
176 SigpInfo
*si
= arg
.host_ptr
;
177 uint8_t lc
= si
->param
& ADTL_SAVE_LC_MASK
;
178 hwaddr addr
= si
->param
& ~ADTL_SAVE_LC_MASK
;
179 hwaddr len
= 1UL << (lc
? lc
: 10);
181 if (!s390_has_feat(S390_FEAT_VECTOR
) &&
182 !s390_has_feat(S390_FEAT_GUARDED_STORAGE
)) {
183 set_sigp_status(si
, SIGP_STAT_INVALID_ORDER
);
187 /* cpu has to be stopped */
188 if (s390_cpu_get_state(cpu
) != CPU_STATE_STOPPED
) {
189 set_sigp_status(si
, SIGP_STAT_INCORRECT_STATE
);
193 /* address must be aligned to length */
194 if (addr
& (len
- 1)) {
195 set_sigp_status(si
, SIGP_STAT_INVALID_PARAMETER
);
199 /* no GS: only lc == 0 is valid */
200 if (!s390_has_feat(S390_FEAT_GUARDED_STORAGE
) &&
202 set_sigp_status(si
, SIGP_STAT_INVALID_PARAMETER
);
206 /* GS: 0, 10, 11, 12 are valid */
207 if (s390_has_feat(S390_FEAT_GUARDED_STORAGE
) &&
212 set_sigp_status(si
, SIGP_STAT_INVALID_PARAMETER
);
216 cpu_synchronize_state(cs
);
218 if (s390_store_adtl_status(cpu
, addr
, len
)) {
219 set_sigp_status(si
, SIGP_STAT_INVALID_PARAMETER
);
222 si
->cc
= SIGP_CC_ORDER_CODE_ACCEPTED
;
225 static void sigp_restart(CPUState
*cs
, run_on_cpu_data arg
)
227 S390CPU
*cpu
= S390_CPU(cs
);
228 SigpInfo
*si
= arg
.host_ptr
;
230 switch (s390_cpu_get_state(cpu
)) {
231 case CPU_STATE_STOPPED
:
232 /* the restart irq has to be delivered prior to any other pending irq */
233 cpu_synchronize_state(cs
);
234 do_restart_interrupt(&cpu
->env
);
235 s390_cpu_set_state(CPU_STATE_OPERATING
, cpu
);
237 case CPU_STATE_OPERATING
:
238 cpu_inject_restart(cpu
);
241 si
->cc
= SIGP_CC_ORDER_CODE_ACCEPTED
;
244 static void sigp_initial_cpu_reset(CPUState
*cs
, run_on_cpu_data arg
)
246 S390CPU
*cpu
= S390_CPU(cs
);
247 S390CPUClass
*scc
= S390_CPU_GET_CLASS(cpu
);
248 SigpInfo
*si
= arg
.host_ptr
;
250 cpu_synchronize_state(cs
);
251 scc
->initial_cpu_reset(cs
);
252 cpu_synchronize_post_reset(cs
);
253 si
->cc
= SIGP_CC_ORDER_CODE_ACCEPTED
;
256 static void sigp_cpu_reset(CPUState
*cs
, run_on_cpu_data arg
)
258 S390CPU
*cpu
= S390_CPU(cs
);
259 S390CPUClass
*scc
= S390_CPU_GET_CLASS(cpu
);
260 SigpInfo
*si
= arg
.host_ptr
;
262 cpu_synchronize_state(cs
);
264 cpu_synchronize_post_reset(cs
);
265 si
->cc
= SIGP_CC_ORDER_CODE_ACCEPTED
;
268 static void sigp_set_prefix(CPUState
*cs
, run_on_cpu_data arg
)
270 S390CPU
*cpu
= S390_CPU(cs
);
271 SigpInfo
*si
= arg
.host_ptr
;
272 uint32_t addr
= si
->param
& 0x7fffe000u
;
274 cpu_synchronize_state(cs
);
276 if (!address_space_access_valid(&address_space_memory
, addr
,
277 sizeof(struct LowCore
), false)) {
278 set_sigp_status(si
, SIGP_STAT_INVALID_PARAMETER
);
282 /* cpu has to be stopped */
283 if (s390_cpu_get_state(cpu
) != CPU_STATE_STOPPED
) {
284 set_sigp_status(si
, SIGP_STAT_INCORRECT_STATE
);
289 cpu_synchronize_post_init(cs
);
290 si
->cc
= SIGP_CC_ORDER_CODE_ACCEPTED
;
293 static void sigp_sense_running(S390CPU
*dst_cpu
, SigpInfo
*si
)
295 if (!tcg_enabled()) {
297 set_sigp_status(si
, SIGP_STAT_INVALID_ORDER
);
301 /* sensing without locks is racy, but it's the same for real hw */
302 if (!s390_has_feat(S390_FEAT_SENSE_RUNNING_STATUS
)) {
303 set_sigp_status(si
, SIGP_STAT_INVALID_ORDER
);
307 /* If halted (which includes also STOPPED), it is not running */
308 if (CPU(dst_cpu
)->halted
) {
309 si
->cc
= SIGP_CC_ORDER_CODE_ACCEPTED
;
311 set_sigp_status(si
, SIGP_STAT_NOT_RUNNING
);
315 static int handle_sigp_single_dst(S390CPU
*cpu
, S390CPU
*dst_cpu
, uint8_t order
,
316 uint64_t param
, uint64_t *status_reg
)
320 .status_reg
= status_reg
,
324 if (dst_cpu
== NULL
) {
325 return SIGP_CC_NOT_OPERATIONAL
;
328 /* only resets can break pending orders */
329 if (dst_cpu
->env
.sigp_order
!= 0 &&
330 order
!= SIGP_CPU_RESET
&&
331 order
!= SIGP_INITIAL_CPU_RESET
) {
337 sigp_sense(dst_cpu
, &si
);
339 case SIGP_EXTERNAL_CALL
:
340 sigp_external_call(cpu
, dst_cpu
, &si
);
343 sigp_emergency(cpu
, dst_cpu
, &si
);
346 run_on_cpu(CPU(dst_cpu
), sigp_start
, RUN_ON_CPU_HOST_PTR(&si
));
349 run_on_cpu(CPU(dst_cpu
), sigp_stop
, RUN_ON_CPU_HOST_PTR(&si
));
352 run_on_cpu(CPU(dst_cpu
), sigp_restart
, RUN_ON_CPU_HOST_PTR(&si
));
354 case SIGP_STOP_STORE_STATUS
:
355 run_on_cpu(CPU(dst_cpu
), sigp_stop_and_store_status
, RUN_ON_CPU_HOST_PTR(&si
));
357 case SIGP_STORE_STATUS_ADDR
:
358 run_on_cpu(CPU(dst_cpu
), sigp_store_status_at_address
, RUN_ON_CPU_HOST_PTR(&si
));
360 case SIGP_STORE_ADTL_STATUS
:
361 run_on_cpu(CPU(dst_cpu
), sigp_store_adtl_status
, RUN_ON_CPU_HOST_PTR(&si
));
363 case SIGP_SET_PREFIX
:
364 run_on_cpu(CPU(dst_cpu
), sigp_set_prefix
, RUN_ON_CPU_HOST_PTR(&si
));
366 case SIGP_INITIAL_CPU_RESET
:
367 run_on_cpu(CPU(dst_cpu
), sigp_initial_cpu_reset
, RUN_ON_CPU_HOST_PTR(&si
));
370 run_on_cpu(CPU(dst_cpu
), sigp_cpu_reset
, RUN_ON_CPU_HOST_PTR(&si
));
372 case SIGP_SENSE_RUNNING
:
373 sigp_sense_running(dst_cpu
, &si
);
376 set_sigp_status(&si
, SIGP_STAT_INVALID_ORDER
);
382 static int sigp_set_architecture(S390CPU
*cpu
, uint32_t param
,
383 uint64_t *status_reg
)
387 bool all_stopped
= true;
389 CPU_FOREACH(cur_cs
) {
390 cur_cpu
= S390_CPU(cur_cs
);
392 if (cur_cpu
== cpu
) {
395 if (s390_cpu_get_state(cur_cpu
) != CPU_STATE_STOPPED
) {
400 *status_reg
&= 0xffffffff00000000ULL
;
402 /* Reject set arch order, with czam we're always in z/Arch mode. */
403 *status_reg
|= (all_stopped
? SIGP_STAT_INVALID_PARAMETER
:
404 SIGP_STAT_INCORRECT_STATE
);
405 return SIGP_CC_STATUS_STORED
;
408 int handle_sigp(CPUS390XState
*env
, uint8_t order
, uint64_t r1
, uint64_t r3
)
410 uint64_t *status_reg
= &env
->regs
[r1
];
411 uint64_t param
= (r1
% 2) ? env
->regs
[r1
] : env
->regs
[r1
+ 1];
412 S390CPU
*cpu
= s390_env_get_cpu(env
);
413 S390CPU
*dst_cpu
= NULL
;
416 if (qemu_mutex_trylock(&qemu_sigp_mutex
)) {
423 ret
= sigp_set_architecture(cpu
, param
, status_reg
);
426 /* all other sigp orders target a single vcpu */
427 dst_cpu
= s390_cpu_addr2state(env
->regs
[r3
]);
428 ret
= handle_sigp_single_dst(cpu
, dst_cpu
, order
, param
, status_reg
);
430 qemu_mutex_unlock(&qemu_sigp_mutex
);
433 trace_sigp_finished(order
, CPU(cpu
)->cpu_index
,
434 dst_cpu
? CPU(dst_cpu
)->cpu_index
: -1, ret
);
440 int s390_cpu_restart(S390CPU
*cpu
)
449 run_on_cpu(CPU(cpu
), sigp_restart
, RUN_ON_CPU_HOST_PTR(&si
));
453 void do_stop_interrupt(CPUS390XState
*env
)
455 S390CPU
*cpu
= s390_env_get_cpu(env
);
457 if (s390_cpu_set_state(CPU_STATE_STOPPED
, cpu
) == 0) {
458 qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN
);
460 if (cpu
->env
.sigp_order
== SIGP_STOP_STORE_STATUS
) {
461 s390_store_status(cpu
, S390_STORE_STATUS_DEF_ADDR
, true);
466 void s390_init_sigp(void)
468 qemu_mutex_init(&qemu_sigp_mutex
);