qemu/target/s390x/sigp.c
<<
>>
Prefs
   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 "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"
  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         * load_psw() will then properly halt the CPU again if necessary (TCG).
 239         */
 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;
 246    }
 247    si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
 248}
 249
 250static void sigp_initial_cpu_reset(CPUState *cs, run_on_cpu_data arg)
 251{
 252    S390CPU *cpu = S390_CPU(cs);
 253    S390CPUClass *scc = S390_CPU_GET_CLASS(cpu);
 254    SigpInfo *si = arg.host_ptr;
 255
 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;
 260}
 261
 262static void sigp_cpu_reset(CPUState *cs, run_on_cpu_data arg)
 263{
 264    S390CPU *cpu = S390_CPU(cs);
 265    S390CPUClass *scc = S390_CPU_GET_CLASS(cpu);
 266    SigpInfo *si = arg.host_ptr;
 267
 268    cpu_synchronize_state(cs);
 269    scc->cpu_reset(cs);
 270    cpu_synchronize_post_reset(cs);
 271    si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
 272}
 273
 274static void sigp_set_prefix(CPUState *cs, run_on_cpu_data arg)
 275{
 276    S390CPU *cpu = S390_CPU(cs);
 277    SigpInfo *si = arg.host_ptr;
 278    uint32_t addr = si->param & 0x7fffe000u;
 279
 280    cpu_synchronize_state(cs);
 281
 282    if (!address_space_access_valid(&address_space_memory, addr,
 283                                    sizeof(struct LowCore), false)) {
 284        set_sigp_status(si, SIGP_STAT_INVALID_PARAMETER);
 285        return;
 286    }
 287
 288    /* cpu has to be stopped */
 289    if (s390_cpu_get_state(cpu) != S390_CPU_STATE_STOPPED) {
 290        set_sigp_status(si, SIGP_STAT_INCORRECT_STATE);
 291        return;
 292    }
 293
 294    cpu->env.psa = addr;
 295    tlb_flush(cs);
 296    cpu_synchronize_post_init(cs);
 297    si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
 298}
 299
 300static void sigp_cond_emergency(S390CPU *src_cpu, S390CPU *dst_cpu,
 301                                SigpInfo *si)
 302{
 303    const uint64_t psw_int_mask = PSW_MASK_IO | PSW_MASK_EXT;
 304    uint16_t p_asn, s_asn, asn;
 305    uint64_t psw_addr, psw_mask;
 306    bool idle;
 307
 308    if (!tcg_enabled()) {
 309        /* handled in KVM */
 310        set_sigp_status(si, SIGP_STAT_INVALID_ORDER);
 311        return;
 312    }
 313
 314    /* this looks racy, but these values are only used when STOPPED */
 315    idle = CPU(dst_cpu)->halted;
 316    psw_addr = dst_cpu->env.psw.addr;
 317    psw_mask = dst_cpu->env.psw.mask;
 318    asn = si->param;
 319    p_asn = dst_cpu->env.cregs[4] & 0xffff;  /* Primary ASN */
 320    s_asn = dst_cpu->env.cregs[3] & 0xffff;  /* Secondary ASN */
 321
 322    if (s390_cpu_get_state(dst_cpu) != S390_CPU_STATE_STOPPED ||
 323        (psw_mask & psw_int_mask) != psw_int_mask ||
 324        (idle && psw_addr != 0) ||
 325        (!idle && (asn == p_asn || asn == s_asn))) {
 326        cpu_inject_emergency_signal(dst_cpu, src_cpu->env.core_id);
 327    } else {
 328        set_sigp_status(si, SIGP_STAT_INCORRECT_STATE);
 329    }
 330
 331    si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
 332}
 333
 334static void sigp_sense_running(S390CPU *dst_cpu, SigpInfo *si)
 335{
 336    if (!tcg_enabled()) {
 337        /* handled in KVM */
 338        set_sigp_status(si, SIGP_STAT_INVALID_ORDER);
 339        return;
 340    }
 341
 342    /* sensing without locks is racy, but it's the same for real hw */
 343    if (!s390_has_feat(S390_FEAT_SENSE_RUNNING_STATUS)) {
 344        set_sigp_status(si, SIGP_STAT_INVALID_ORDER);
 345        return;
 346    }
 347
 348    /* If halted (which includes also STOPPED), it is not running */
 349    if (CPU(dst_cpu)->halted) {
 350        si->cc = SIGP_CC_ORDER_CODE_ACCEPTED;
 351    } else {
 352        set_sigp_status(si, SIGP_STAT_NOT_RUNNING);
 353    }
 354}
 355
 356static int handle_sigp_single_dst(S390CPU *cpu, S390CPU *dst_cpu, uint8_t order,
 357                                  uint64_t param, uint64_t *status_reg)
 358{
 359    SigpInfo si = {
 360        .param = param,
 361        .status_reg = status_reg,
 362    };
 363
 364    /* cpu available? */
 365    if (dst_cpu == NULL) {
 366        return SIGP_CC_NOT_OPERATIONAL;
 367    }
 368
 369    /* only resets can break pending orders */
 370    if (dst_cpu->env.sigp_order != 0 &&
 371        order != SIGP_CPU_RESET &&
 372        order != SIGP_INITIAL_CPU_RESET) {
 373        return SIGP_CC_BUSY;
 374    }
 375
 376    switch (order) {
 377    case SIGP_SENSE:
 378        sigp_sense(dst_cpu, &si);
 379        break;
 380    case SIGP_EXTERNAL_CALL:
 381        sigp_external_call(cpu, dst_cpu, &si);
 382        break;
 383    case SIGP_EMERGENCY:
 384        sigp_emergency(cpu, dst_cpu, &si);
 385        break;
 386    case SIGP_START:
 387        run_on_cpu(CPU(dst_cpu), sigp_start, RUN_ON_CPU_HOST_PTR(&si));
 388        break;
 389    case SIGP_STOP:
 390        run_on_cpu(CPU(dst_cpu), sigp_stop, RUN_ON_CPU_HOST_PTR(&si));
 391        break;
 392    case SIGP_RESTART:
 393        run_on_cpu(CPU(dst_cpu), sigp_restart, RUN_ON_CPU_HOST_PTR(&si));
 394        break;
 395    case SIGP_STOP_STORE_STATUS:
 396        run_on_cpu(CPU(dst_cpu), sigp_stop_and_store_status, RUN_ON_CPU_HOST_PTR(&si));
 397        break;
 398    case SIGP_STORE_STATUS_ADDR:
 399        run_on_cpu(CPU(dst_cpu), sigp_store_status_at_address, RUN_ON_CPU_HOST_PTR(&si));
 400        break;
 401    case SIGP_STORE_ADTL_STATUS:
 402        run_on_cpu(CPU(dst_cpu), sigp_store_adtl_status, RUN_ON_CPU_HOST_PTR(&si));
 403        break;
 404    case SIGP_SET_PREFIX:
 405        run_on_cpu(CPU(dst_cpu), sigp_set_prefix, RUN_ON_CPU_HOST_PTR(&si));
 406        break;
 407    case SIGP_INITIAL_CPU_RESET:
 408        run_on_cpu(CPU(dst_cpu), sigp_initial_cpu_reset, RUN_ON_CPU_HOST_PTR(&si));
 409        break;
 410    case SIGP_CPU_RESET:
 411        run_on_cpu(CPU(dst_cpu), sigp_cpu_reset, RUN_ON_CPU_HOST_PTR(&si));
 412        break;
 413    case SIGP_COND_EMERGENCY:
 414        sigp_cond_emergency(cpu, dst_cpu, &si);
 415        break;
 416    case SIGP_SENSE_RUNNING:
 417        sigp_sense_running(dst_cpu, &si);
 418        break;
 419    default:
 420        set_sigp_status(&si, SIGP_STAT_INVALID_ORDER);
 421    }
 422
 423    return si.cc;
 424}
 425
 426static int sigp_set_architecture(S390CPU *cpu, uint32_t param,
 427                                 uint64_t *status_reg)
 428{
 429    CPUState *cur_cs;
 430    S390CPU *cur_cpu;
 431    bool all_stopped = true;
 432
 433    CPU_FOREACH(cur_cs) {
 434        cur_cpu = S390_CPU(cur_cs);
 435
 436        if (cur_cpu == cpu) {
 437            continue;
 438        }
 439        if (s390_cpu_get_state(cur_cpu) != S390_CPU_STATE_STOPPED) {
 440            all_stopped = false;
 441        }
 442    }
 443
 444    *status_reg &= 0xffffffff00000000ULL;
 445
 446    /* Reject set arch order, with czam we're always in z/Arch mode. */
 447    *status_reg |= (all_stopped ? SIGP_STAT_INVALID_PARAMETER :
 448                    SIGP_STAT_INCORRECT_STATE);
 449    return SIGP_CC_STATUS_STORED;
 450}
 451
 452int handle_sigp(CPUS390XState *env, uint8_t order, uint64_t r1, uint64_t r3)
 453{
 454    uint64_t *status_reg = &env->regs[r1];
 455    uint64_t param = (r1 % 2) ? env->regs[r1] : env->regs[r1 + 1];
 456    S390CPU *cpu = s390_env_get_cpu(env);
 457    S390CPU *dst_cpu = NULL;
 458    int ret;
 459
 460    if (qemu_mutex_trylock(&qemu_sigp_mutex)) {
 461        ret = SIGP_CC_BUSY;
 462        goto out;
 463    }
 464
 465    switch (order) {
 466    case SIGP_SET_ARCH:
 467        ret = sigp_set_architecture(cpu, param, status_reg);
 468        break;
 469    default:
 470        /* all other sigp orders target a single vcpu */
 471        dst_cpu = s390_cpu_addr2state(env->regs[r3]);
 472        ret = handle_sigp_single_dst(cpu, dst_cpu, order, param, status_reg);
 473    }
 474    qemu_mutex_unlock(&qemu_sigp_mutex);
 475
 476out:
 477    trace_sigp_finished(order, CPU(cpu)->cpu_index,
 478                        dst_cpu ? CPU(dst_cpu)->cpu_index : -1, ret);
 479    g_assert(ret >= 0);
 480
 481    return ret;
 482}
 483
 484int s390_cpu_restart(S390CPU *cpu)
 485{
 486    SigpInfo si = {};
 487
 488    run_on_cpu(CPU(cpu), sigp_restart, RUN_ON_CPU_HOST_PTR(&si));
 489    return 0;
 490}
 491
 492void do_stop_interrupt(CPUS390XState *env)
 493{
 494    S390CPU *cpu = s390_env_get_cpu(env);
 495
 496    if (s390_cpu_set_state(S390_CPU_STATE_STOPPED, cpu) == 0) {
 497        qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
 498    }
 499    if (cpu->env.sigp_order == SIGP_STOP_STORE_STATUS) {
 500        s390_store_status(cpu, S390_STORE_STATUS_DEF_ADDR, true);
 501    }
 502    env->sigp_order = 0;
 503    env->pending_int &= ~INTERRUPT_STOP;
 504}
 505
 506void s390_init_sigp(void)
 507{
 508    qemu_mutex_init(&qemu_sigp_mutex);
 509}
 510