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_start(CPUState
*cs
, run_on_cpu_data arg
)
37 S390CPU
*cpu
= S390_CPU(cs
);
38 SigpInfo
*si
= arg
.host_ptr
;
40 if (s390_cpu_get_state(cpu
) != CPU_STATE_STOPPED
) {
41 si
->cc
= SIGP_CC_ORDER_CODE_ACCEPTED
;
45 s390_cpu_set_state(CPU_STATE_OPERATING
, cpu
);
46 si
->cc
= SIGP_CC_ORDER_CODE_ACCEPTED
;
49 static void sigp_stop(CPUState
*cs
, run_on_cpu_data arg
)
51 S390CPU
*cpu
= S390_CPU(cs
);
52 SigpInfo
*si
= arg
.host_ptr
;
54 if (s390_cpu_get_state(cpu
) != CPU_STATE_OPERATING
) {
55 si
->cc
= SIGP_CC_ORDER_CODE_ACCEPTED
;
59 /* disabled wait - sleeping in user space */
61 s390_cpu_set_state(CPU_STATE_STOPPED
, cpu
);
63 /* execute the stop function */
64 cpu
->env
.sigp_order
= SIGP_STOP
;
67 si
->cc
= SIGP_CC_ORDER_CODE_ACCEPTED
;
70 static void sigp_stop_and_store_status(CPUState
*cs
, run_on_cpu_data arg
)
72 S390CPU
*cpu
= S390_CPU(cs
);
73 SigpInfo
*si
= arg
.host_ptr
;
75 /* disabled wait - sleeping in user space */
76 if (s390_cpu_get_state(cpu
) == CPU_STATE_OPERATING
&& cs
->halted
) {
77 s390_cpu_set_state(CPU_STATE_STOPPED
, cpu
);
80 switch (s390_cpu_get_state(cpu
)) {
81 case CPU_STATE_OPERATING
:
82 cpu
->env
.sigp_order
= SIGP_STOP_STORE_STATUS
;
84 /* store will be performed in do_stop_interrup() */
86 case CPU_STATE_STOPPED
:
87 /* already stopped, just store the status */
88 cpu_synchronize_state(cs
);
89 s390_store_status(cpu
, S390_STORE_STATUS_DEF_ADDR
, true);
92 si
->cc
= SIGP_CC_ORDER_CODE_ACCEPTED
;
95 static void sigp_store_status_at_address(CPUState
*cs
, run_on_cpu_data arg
)
97 S390CPU
*cpu
= S390_CPU(cs
);
98 SigpInfo
*si
= arg
.host_ptr
;
99 uint32_t address
= si
->param
& 0x7ffffe00u
;
101 /* cpu has to be stopped */
102 if (s390_cpu_get_state(cpu
) != CPU_STATE_STOPPED
) {
103 set_sigp_status(si
, SIGP_STAT_INCORRECT_STATE
);
107 cpu_synchronize_state(cs
);
109 if (s390_store_status(cpu
, address
, false)) {
110 set_sigp_status(si
, SIGP_STAT_INVALID_PARAMETER
);
113 si
->cc
= SIGP_CC_ORDER_CODE_ACCEPTED
;
116 #define ADTL_SAVE_LC_MASK 0xfUL
117 static void sigp_store_adtl_status(CPUState
*cs
, run_on_cpu_data arg
)
119 S390CPU
*cpu
= S390_CPU(cs
);
120 SigpInfo
*si
= arg
.host_ptr
;
121 uint8_t lc
= si
->param
& ADTL_SAVE_LC_MASK
;
122 hwaddr addr
= si
->param
& ~ADTL_SAVE_LC_MASK
;
123 hwaddr len
= 1UL << (lc
? lc
: 10);
125 if (!s390_has_feat(S390_FEAT_VECTOR
) &&
126 !s390_has_feat(S390_FEAT_GUARDED_STORAGE
)) {
127 set_sigp_status(si
, SIGP_STAT_INVALID_ORDER
);
131 /* cpu has to be stopped */
132 if (s390_cpu_get_state(cpu
) != CPU_STATE_STOPPED
) {
133 set_sigp_status(si
, SIGP_STAT_INCORRECT_STATE
);
137 /* address must be aligned to length */
138 if (addr
& (len
- 1)) {
139 set_sigp_status(si
, SIGP_STAT_INVALID_PARAMETER
);
143 /* no GS: only lc == 0 is valid */
144 if (!s390_has_feat(S390_FEAT_GUARDED_STORAGE
) &&
146 set_sigp_status(si
, SIGP_STAT_INVALID_PARAMETER
);
150 /* GS: 0, 10, 11, 12 are valid */
151 if (s390_has_feat(S390_FEAT_GUARDED_STORAGE
) &&
156 set_sigp_status(si
, SIGP_STAT_INVALID_PARAMETER
);
160 cpu_synchronize_state(cs
);
162 if (s390_store_adtl_status(cpu
, addr
, len
)) {
163 set_sigp_status(si
, SIGP_STAT_INVALID_PARAMETER
);
166 si
->cc
= SIGP_CC_ORDER_CODE_ACCEPTED
;
169 static void sigp_restart(CPUState
*cs
, run_on_cpu_data arg
)
171 S390CPU
*cpu
= S390_CPU(cs
);
172 SigpInfo
*si
= arg
.host_ptr
;
174 switch (s390_cpu_get_state(cpu
)) {
175 case CPU_STATE_STOPPED
:
176 /* the restart irq has to be delivered prior to any other pending irq */
177 cpu_synchronize_state(cs
);
178 do_restart_interrupt(&cpu
->env
);
179 s390_cpu_set_state(CPU_STATE_OPERATING
, cpu
);
181 case CPU_STATE_OPERATING
:
182 cpu_inject_restart(cpu
);
185 si
->cc
= SIGP_CC_ORDER_CODE_ACCEPTED
;
188 static void sigp_initial_cpu_reset(CPUState
*cs
, run_on_cpu_data arg
)
190 S390CPU
*cpu
= S390_CPU(cs
);
191 S390CPUClass
*scc
= S390_CPU_GET_CLASS(cpu
);
192 SigpInfo
*si
= arg
.host_ptr
;
194 cpu_synchronize_state(cs
);
195 scc
->initial_cpu_reset(cs
);
196 cpu_synchronize_post_reset(cs
);
197 si
->cc
= SIGP_CC_ORDER_CODE_ACCEPTED
;
200 static void sigp_cpu_reset(CPUState
*cs
, run_on_cpu_data arg
)
202 S390CPU
*cpu
= S390_CPU(cs
);
203 S390CPUClass
*scc
= S390_CPU_GET_CLASS(cpu
);
204 SigpInfo
*si
= arg
.host_ptr
;
206 cpu_synchronize_state(cs
);
208 cpu_synchronize_post_reset(cs
);
209 si
->cc
= SIGP_CC_ORDER_CODE_ACCEPTED
;
212 static void sigp_set_prefix(CPUState
*cs
, run_on_cpu_data arg
)
214 S390CPU
*cpu
= S390_CPU(cs
);
215 SigpInfo
*si
= arg
.host_ptr
;
216 uint32_t addr
= si
->param
& 0x7fffe000u
;
218 cpu_synchronize_state(cs
);
220 if (!address_space_access_valid(&address_space_memory
, addr
,
221 sizeof(struct LowCore
), false)) {
222 set_sigp_status(si
, SIGP_STAT_INVALID_PARAMETER
);
226 /* cpu has to be stopped */
227 if (s390_cpu_get_state(cpu
) != CPU_STATE_STOPPED
) {
228 set_sigp_status(si
, SIGP_STAT_INCORRECT_STATE
);
233 cpu_synchronize_post_init(cs
);
234 si
->cc
= SIGP_CC_ORDER_CODE_ACCEPTED
;
237 static void sigp_sense_running(S390CPU
*dst_cpu
, SigpInfo
*si
)
239 if (!tcg_enabled()) {
241 set_sigp_status(si
, SIGP_STAT_INVALID_ORDER
);
245 /* sensing without locks is racy, but it's the same for real hw */
246 if (!s390_has_feat(S390_FEAT_SENSE_RUNNING_STATUS
)) {
247 set_sigp_status(si
, SIGP_STAT_INVALID_ORDER
);
251 /* If halted (which includes also STOPPED), it is not running */
252 if (CPU(dst_cpu
)->halted
) {
253 si
->cc
= SIGP_CC_ORDER_CODE_ACCEPTED
;
255 set_sigp_status(si
, SIGP_STAT_NOT_RUNNING
);
259 static int handle_sigp_single_dst(S390CPU
*dst_cpu
, uint8_t order
,
260 uint64_t param
, uint64_t *status_reg
)
264 .status_reg
= status_reg
,
268 if (dst_cpu
== NULL
) {
269 return SIGP_CC_NOT_OPERATIONAL
;
272 /* only resets can break pending orders */
273 if (dst_cpu
->env
.sigp_order
!= 0 &&
274 order
!= SIGP_CPU_RESET
&&
275 order
!= SIGP_INITIAL_CPU_RESET
) {
281 run_on_cpu(CPU(dst_cpu
), sigp_start
, RUN_ON_CPU_HOST_PTR(&si
));
284 run_on_cpu(CPU(dst_cpu
), sigp_stop
, RUN_ON_CPU_HOST_PTR(&si
));
287 run_on_cpu(CPU(dst_cpu
), sigp_restart
, RUN_ON_CPU_HOST_PTR(&si
));
289 case SIGP_STOP_STORE_STATUS
:
290 run_on_cpu(CPU(dst_cpu
), sigp_stop_and_store_status
, RUN_ON_CPU_HOST_PTR(&si
));
292 case SIGP_STORE_STATUS_ADDR
:
293 run_on_cpu(CPU(dst_cpu
), sigp_store_status_at_address
, RUN_ON_CPU_HOST_PTR(&si
));
295 case SIGP_STORE_ADTL_STATUS
:
296 run_on_cpu(CPU(dst_cpu
), sigp_store_adtl_status
, RUN_ON_CPU_HOST_PTR(&si
));
298 case SIGP_SET_PREFIX
:
299 run_on_cpu(CPU(dst_cpu
), sigp_set_prefix
, RUN_ON_CPU_HOST_PTR(&si
));
301 case SIGP_INITIAL_CPU_RESET
:
302 run_on_cpu(CPU(dst_cpu
), sigp_initial_cpu_reset
, RUN_ON_CPU_HOST_PTR(&si
));
305 run_on_cpu(CPU(dst_cpu
), sigp_cpu_reset
, RUN_ON_CPU_HOST_PTR(&si
));
307 case SIGP_SENSE_RUNNING
:
308 sigp_sense_running(dst_cpu
, &si
);
311 set_sigp_status(&si
, SIGP_STAT_INVALID_ORDER
);
317 static int sigp_set_architecture(S390CPU
*cpu
, uint32_t param
,
318 uint64_t *status_reg
)
322 bool all_stopped
= true;
324 CPU_FOREACH(cur_cs
) {
325 cur_cpu
= S390_CPU(cur_cs
);
327 if (cur_cpu
== cpu
) {
330 if (s390_cpu_get_state(cur_cpu
) != CPU_STATE_STOPPED
) {
335 *status_reg
&= 0xffffffff00000000ULL
;
337 /* Reject set arch order, with czam we're always in z/Arch mode. */
338 *status_reg
|= (all_stopped
? SIGP_STAT_INVALID_PARAMETER
:
339 SIGP_STAT_INCORRECT_STATE
);
340 return SIGP_CC_STATUS_STORED
;
343 int handle_sigp(CPUS390XState
*env
, uint8_t order
, uint64_t r1
, uint64_t r3
)
345 uint64_t *status_reg
= &env
->regs
[r1
];
346 uint64_t param
= (r1
% 2) ? env
->regs
[r1
] : env
->regs
[r1
+ 1];
347 S390CPU
*cpu
= s390_env_get_cpu(env
);
348 S390CPU
*dst_cpu
= NULL
;
351 if (qemu_mutex_trylock(&qemu_sigp_mutex
)) {
358 ret
= sigp_set_architecture(cpu
, param
, status_reg
);
361 /* all other sigp orders target a single vcpu */
362 dst_cpu
= s390_cpu_addr2state(env
->regs
[r3
]);
363 ret
= handle_sigp_single_dst(dst_cpu
, order
, param
, status_reg
);
365 qemu_mutex_unlock(&qemu_sigp_mutex
);
368 trace_sigp_finished(order
, CPU(cpu
)->cpu_index
,
369 dst_cpu
? CPU(dst_cpu
)->cpu_index
: -1, ret
);
375 int s390_cpu_restart(S390CPU
*cpu
)
384 run_on_cpu(CPU(cpu
), sigp_restart
, RUN_ON_CPU_HOST_PTR(&si
));
388 void do_stop_interrupt(CPUS390XState
*env
)
390 S390CPU
*cpu
= s390_env_get_cpu(env
);
392 if (s390_cpu_set_state(CPU_STATE_STOPPED
, cpu
) == 0) {
393 qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN
);
395 if (cpu
->env
.sigp_order
== SIGP_STOP_STORE_STATUS
) {
396 s390_store_status(cpu
, S390_STORE_STATUS_DEF_ADDR
, true);
401 void s390_init_sigp(void)
403 qemu_mutex_init(&qemu_sigp_mutex
);