sigp.c (14489B)
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 "sysemu/hw_accel.h" 15#include "sysemu/runstate.h" 16#include "exec/address-spaces.h" 17#include "exec/exec-all.h" 18#include "sysemu/tcg.h" 19#include "trace.h" 20#include "qapi/qapi-types-machine.h" 21 22QemuMutex qemu_sigp_mutex; 23 24typedef struct SigpInfo { 25 uint64_t param; 26 int cc; 27 uint64_t *status_reg; 28} SigpInfo; 29 30static void set_sigp_status(SigpInfo *si, uint64_t status) 31{ 32 *si->status_reg &= 0xffffffff00000000ULL; 33 *si->status_reg |= status; 34 si->cc = SIGP_CC_STATUS_STORED; 35} 36 37static void sigp_sense(S390CPU *dst_cpu, SigpInfo *si) 38{ 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; 42 43 if (!tcg_enabled()) { 44 /* handled in KVM */ 45 set_sigp_status(si, SIGP_STAT_INVALID_ORDER); 46 return; 47 } 48 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; 55 } 56 if (state == S390_CPU_STATE_STOPPED) { 57 status |= SIGP_STAT_STOPPED; 58 } 59 set_sigp_status(si, status); 60 } 61} 62 63static void sigp_external_call(S390CPU *src_cpu, S390CPU *dst_cpu, SigpInfo *si) 64{ 65 int ret; 66 67 if (!tcg_enabled()) { 68 /* handled in KVM */ 69 set_sigp_status(si, SIGP_STAT_INVALID_ORDER); 70 return; 71 } 72 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); 78 } 79} 80 81static void sigp_emergency(S390CPU *src_cpu, S390CPU *dst_cpu, SigpInfo *si) 82{ 83 if (!tcg_enabled()) { 84 /* handled in KVM */ 85 set_sigp_status(si, SIGP_STAT_INVALID_ORDER); 86 return; 87 } 88 89 cpu_inject_emergency_signal(dst_cpu, src_cpu->env.core_id); 90 si->cc = SIGP_CC_ORDER_CODE_ACCEPTED; 91} 92 93static void sigp_start(CPUState *cs, run_on_cpu_data arg) 94{ 95 S390CPU *cpu = S390_CPU(cs); 96 SigpInfo *si = arg.host_ptr; 97 98 if (s390_cpu_get_state(cpu) != S390_CPU_STATE_STOPPED) { 99 si->cc = SIGP_CC_ORDER_CODE_ACCEPTED; 100 return; 101 } 102 103 s390_cpu_set_state(S390_CPU_STATE_OPERATING, cpu); 104 si->cc = SIGP_CC_ORDER_CODE_ACCEPTED; 105} 106 107static void sigp_stop(CPUState *cs, run_on_cpu_data arg) 108{ 109 S390CPU *cpu = S390_CPU(cs); 110 SigpInfo *si = arg.host_ptr; 111 112 if (s390_cpu_get_state(cpu) != S390_CPU_STATE_OPERATING) { 113 si->cc = SIGP_CC_ORDER_CODE_ACCEPTED; 114 return; 115 } 116 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); 124 } 125 si->cc = SIGP_CC_ORDER_CODE_ACCEPTED; 126} 127 128static void sigp_stop_and_store_status(CPUState *cs, run_on_cpu_data arg) 129{ 130 S390CPU *cpu = S390_CPU(cs); 131 SigpInfo *si = arg.host_ptr; 132 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); 136 } 137 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; 149 } 150 si->cc = SIGP_CC_ORDER_CODE_ACCEPTED; 151} 152 153static void sigp_store_status_at_address(CPUState *cs, run_on_cpu_data arg) 154{ 155 S390CPU *cpu = S390_CPU(cs); 156 SigpInfo *si = arg.host_ptr; 157 uint32_t address = si->param & 0x7ffffe00u; 158 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; 163 } 164 165 cpu_synchronize_state(cs); 166 167 if (s390_store_status(cpu, address, false)) { 168 set_sigp_status(si, SIGP_STAT_INVALID_PARAMETER); 169 return; 170 } 171 si->cc = SIGP_CC_ORDER_CODE_ACCEPTED; 172} 173 174#define ADTL_SAVE_LC_MASK 0xfUL 175static void sigp_store_adtl_status(CPUState *cs, run_on_cpu_data arg) 176{ 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); 182 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; 187 } 188 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; 193 } 194 195 /* address must be aligned to length */ 196 if (addr & (len - 1)) { 197 set_sigp_status(si, SIGP_STAT_INVALID_PARAMETER); 198 return; 199 } 200 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; 206 } 207 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; 216 } 217 218 cpu_synchronize_state(cs); 219 220 if (s390_store_adtl_status(cpu, addr, len)) { 221 set_sigp_status(si, SIGP_STAT_INVALID_PARAMETER); 222 return; 223 } 224 si->cc = SIGP_CC_ORDER_CODE_ACCEPTED; 225} 226 227static void sigp_restart(CPUState *cs, run_on_cpu_data arg) 228{ 229 S390CPU *cpu = S390_CPU(cs); 230 SigpInfo *si = arg.host_ptr; 231 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); 236 /* 237 * Set OPERATING (and unhalting) before loading the restart PSW. 238 * s390_cpu_set_psw() will then properly halt the CPU again if 239 * necessary (TCG). 240 */ 241 s390_cpu_set_state(S390_CPU_STATE_OPERATING, cpu); 242 do_restart_interrupt(&cpu->env); 243 break; 244 case S390_CPU_STATE_OPERATING: 245 cpu_inject_restart(cpu); 246 break; 247 } 248 si->cc = SIGP_CC_ORDER_CODE_ACCEPTED; 249} 250 251static void sigp_initial_cpu_reset(CPUState *cs, run_on_cpu_data arg) 252{ 253 S390CPU *cpu = S390_CPU(cs); 254 S390CPUClass *scc = S390_CPU_GET_CLASS(cpu); 255 SigpInfo *si = arg.host_ptr; 256 257 cpu_synchronize_state(cs); 258 scc->reset(cs, S390_CPU_RESET_INITIAL); 259 cpu_synchronize_post_reset(cs); 260 si->cc = SIGP_CC_ORDER_CODE_ACCEPTED; 261} 262 263static void sigp_cpu_reset(CPUState *cs, run_on_cpu_data arg) 264{ 265 S390CPU *cpu = S390_CPU(cs); 266 S390CPUClass *scc = S390_CPU_GET_CLASS(cpu); 267 SigpInfo *si = arg.host_ptr; 268 269 cpu_synchronize_state(cs); 270 scc->reset(cs, S390_CPU_RESET_NORMAL); 271 cpu_synchronize_post_reset(cs); 272 si->cc = SIGP_CC_ORDER_CODE_ACCEPTED; 273} 274 275static void sigp_set_prefix(CPUState *cs, run_on_cpu_data arg) 276{ 277 S390CPU *cpu = S390_CPU(cs); 278 SigpInfo *si = arg.host_ptr; 279 uint32_t addr = si->param & 0x7fffe000u; 280 281 cpu_synchronize_state(cs); 282 283 if (!address_space_access_valid(&address_space_memory, addr, 284 sizeof(struct LowCore), false, 285 MEMTXATTRS_UNSPECIFIED)) { 286 set_sigp_status(si, SIGP_STAT_INVALID_PARAMETER); 287 return; 288 } 289 290 /* cpu has to be stopped */ 291 if (s390_cpu_get_state(cpu) != S390_CPU_STATE_STOPPED) { 292 set_sigp_status(si, SIGP_STAT_INCORRECT_STATE); 293 return; 294 } 295 296 cpu->env.psa = addr; 297 tlb_flush(cs); 298 cpu_synchronize_post_init(cs); 299 si->cc = SIGP_CC_ORDER_CODE_ACCEPTED; 300} 301 302static void sigp_cond_emergency(S390CPU *src_cpu, S390CPU *dst_cpu, 303 SigpInfo *si) 304{ 305 const uint64_t psw_int_mask = PSW_MASK_IO | PSW_MASK_EXT; 306 uint16_t p_asn, s_asn, asn; 307 uint64_t psw_addr, psw_mask; 308 bool idle; 309 310 if (!tcg_enabled()) { 311 /* handled in KVM */ 312 set_sigp_status(si, SIGP_STAT_INVALID_ORDER); 313 return; 314 } 315 316 /* this looks racy, but these values are only used when STOPPED */ 317 idle = CPU(dst_cpu)->halted; 318 psw_addr = dst_cpu->env.psw.addr; 319 psw_mask = dst_cpu->env.psw.mask; 320 asn = si->param; 321 p_asn = dst_cpu->env.cregs[4] & 0xffff; /* Primary ASN */ 322 s_asn = dst_cpu->env.cregs[3] & 0xffff; /* Secondary ASN */ 323 324 if (s390_cpu_get_state(dst_cpu) != S390_CPU_STATE_STOPPED || 325 (psw_mask & psw_int_mask) != psw_int_mask || 326 (idle && psw_addr != 0) || 327 (!idle && (asn == p_asn || asn == s_asn))) { 328 cpu_inject_emergency_signal(dst_cpu, src_cpu->env.core_id); 329 } else { 330 set_sigp_status(si, SIGP_STAT_INCORRECT_STATE); 331 } 332 333 si->cc = SIGP_CC_ORDER_CODE_ACCEPTED; 334} 335 336static void sigp_sense_running(S390CPU *dst_cpu, SigpInfo *si) 337{ 338 if (!tcg_enabled()) { 339 /* handled in KVM */ 340 set_sigp_status(si, SIGP_STAT_INVALID_ORDER); 341 return; 342 } 343 344 /* sensing without locks is racy, but it's the same for real hw */ 345 if (!s390_has_feat(S390_FEAT_SENSE_RUNNING_STATUS)) { 346 set_sigp_status(si, SIGP_STAT_INVALID_ORDER); 347 return; 348 } 349 350 /* If halted (which includes also STOPPED), it is not running */ 351 if (CPU(dst_cpu)->halted) { 352 set_sigp_status(si, SIGP_STAT_NOT_RUNNING); 353 } else { 354 si->cc = SIGP_CC_ORDER_CODE_ACCEPTED; 355 } 356} 357 358static int handle_sigp_single_dst(S390CPU *cpu, S390CPU *dst_cpu, uint8_t order, 359 uint64_t param, uint64_t *status_reg) 360{ 361 SigpInfo si = { 362 .param = param, 363 .status_reg = status_reg, 364 }; 365 366 /* cpu available? */ 367 if (dst_cpu == NULL) { 368 return SIGP_CC_NOT_OPERATIONAL; 369 } 370 371 /* only resets can break pending orders */ 372 if (dst_cpu->env.sigp_order != 0 && 373 order != SIGP_CPU_RESET && 374 order != SIGP_INITIAL_CPU_RESET) { 375 return SIGP_CC_BUSY; 376 } 377 378 switch (order) { 379 case SIGP_SENSE: 380 sigp_sense(dst_cpu, &si); 381 break; 382 case SIGP_EXTERNAL_CALL: 383 sigp_external_call(cpu, dst_cpu, &si); 384 break; 385 case SIGP_EMERGENCY: 386 sigp_emergency(cpu, dst_cpu, &si); 387 break; 388 case SIGP_START: 389 run_on_cpu(CPU(dst_cpu), sigp_start, RUN_ON_CPU_HOST_PTR(&si)); 390 break; 391 case SIGP_STOP: 392 run_on_cpu(CPU(dst_cpu), sigp_stop, RUN_ON_CPU_HOST_PTR(&si)); 393 break; 394 case SIGP_RESTART: 395 run_on_cpu(CPU(dst_cpu), sigp_restart, RUN_ON_CPU_HOST_PTR(&si)); 396 break; 397 case SIGP_STOP_STORE_STATUS: 398 run_on_cpu(CPU(dst_cpu), sigp_stop_and_store_status, RUN_ON_CPU_HOST_PTR(&si)); 399 break; 400 case SIGP_STORE_STATUS_ADDR: 401 run_on_cpu(CPU(dst_cpu), sigp_store_status_at_address, RUN_ON_CPU_HOST_PTR(&si)); 402 break; 403 case SIGP_STORE_ADTL_STATUS: 404 run_on_cpu(CPU(dst_cpu), sigp_store_adtl_status, RUN_ON_CPU_HOST_PTR(&si)); 405 break; 406 case SIGP_SET_PREFIX: 407 run_on_cpu(CPU(dst_cpu), sigp_set_prefix, RUN_ON_CPU_HOST_PTR(&si)); 408 break; 409 case SIGP_INITIAL_CPU_RESET: 410 run_on_cpu(CPU(dst_cpu), sigp_initial_cpu_reset, RUN_ON_CPU_HOST_PTR(&si)); 411 break; 412 case SIGP_CPU_RESET: 413 run_on_cpu(CPU(dst_cpu), sigp_cpu_reset, RUN_ON_CPU_HOST_PTR(&si)); 414 break; 415 case SIGP_COND_EMERGENCY: 416 sigp_cond_emergency(cpu, dst_cpu, &si); 417 break; 418 case SIGP_SENSE_RUNNING: 419 sigp_sense_running(dst_cpu, &si); 420 break; 421 default: 422 set_sigp_status(&si, SIGP_STAT_INVALID_ORDER); 423 } 424 425 return si.cc; 426} 427 428static int sigp_set_architecture(S390CPU *cpu, uint32_t param, 429 uint64_t *status_reg) 430{ 431 CPUState *cur_cs; 432 S390CPU *cur_cpu; 433 bool all_stopped = true; 434 435 CPU_FOREACH(cur_cs) { 436 cur_cpu = S390_CPU(cur_cs); 437 438 if (cur_cpu == cpu) { 439 continue; 440 } 441 if (s390_cpu_get_state(cur_cpu) != S390_CPU_STATE_STOPPED) { 442 all_stopped = false; 443 } 444 } 445 446 *status_reg &= 0xffffffff00000000ULL; 447 448 /* Reject set arch order, with czam we're always in z/Arch mode. */ 449 *status_reg |= (all_stopped ? SIGP_STAT_INVALID_PARAMETER : 450 SIGP_STAT_INCORRECT_STATE); 451 return SIGP_CC_STATUS_STORED; 452} 453 454int handle_sigp(CPUS390XState *env, uint8_t order, uint64_t r1, uint64_t r3) 455{ 456 uint64_t *status_reg = &env->regs[r1]; 457 uint64_t param = (r1 % 2) ? env->regs[r1] : env->regs[r1 + 1]; 458 S390CPU *cpu = env_archcpu(env); 459 S390CPU *dst_cpu = NULL; 460 int ret; 461 462 if (qemu_mutex_trylock(&qemu_sigp_mutex)) { 463 ret = SIGP_CC_BUSY; 464 goto out; 465 } 466 467 switch (order) { 468 case SIGP_SET_ARCH: 469 ret = sigp_set_architecture(cpu, param, status_reg); 470 break; 471 default: 472 /* all other sigp orders target a single vcpu */ 473 dst_cpu = s390_cpu_addr2state(env->regs[r3]); 474 ret = handle_sigp_single_dst(cpu, dst_cpu, order, param, status_reg); 475 } 476 qemu_mutex_unlock(&qemu_sigp_mutex); 477 478out: 479 trace_sigp_finished(order, CPU(cpu)->cpu_index, 480 dst_cpu ? CPU(dst_cpu)->cpu_index : -1, ret); 481 g_assert(ret >= 0); 482 483 return ret; 484} 485 486int s390_cpu_restart(S390CPU *cpu) 487{ 488 SigpInfo si = {}; 489 490 run_on_cpu(CPU(cpu), sigp_restart, RUN_ON_CPU_HOST_PTR(&si)); 491 return 0; 492} 493 494void do_stop_interrupt(CPUS390XState *env) 495{ 496 S390CPU *cpu = env_archcpu(env); 497 498 if (s390_cpu_set_state(S390_CPU_STATE_STOPPED, cpu) == 0) { 499 qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN); 500 } 501 if (cpu->env.sigp_order == SIGP_STOP_STORE_STATUS) { 502 s390_store_status(cpu, S390_STORE_STATUS_DEF_ADDR, true); 503 } 504 env->sigp_order = 0; 505 env->pending_int &= ~INTERRUPT_STOP; 506} 507 508void s390_init_sigp(void) 509{ 510 qemu_mutex_init(&qemu_sigp_mutex); 511}