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 "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_interrupt() */
 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    *status_reg &= 0xffffffff00000000ULL;
 432
 433    /* Reject set arch order, with czam we're always in z/Arch mode. */
 434    *status_reg |= SIGP_STAT_INVALID_PARAMETER;
 435    return SIGP_CC_STATUS_STORED;
 436}
 437
 438int handle_sigp(CPUS390XState *env, uint8_t order, uint64_t r1, uint64_t r3)
 439{
 440    uint64_t *status_reg = &env->regs[r1];
 441    uint64_t param = (r1 % 2) ? env->regs[r1] : env->regs[r1 + 1];
 442    S390CPU *cpu = env_archcpu(env);
 443    S390CPU *dst_cpu = NULL;
 444    int ret;
 445
 446    if (qemu_mutex_trylock(&qemu_sigp_mutex)) {
 447        ret = SIGP_CC_BUSY;
 448        goto out;
 449    }
 450
 451    switch (order) {
 452    case SIGP_SET_ARCH:
 453        ret = sigp_set_architecture(cpu, param, status_reg);
 454        break;
 455    default:
 456        /* all other sigp orders target a single vcpu */
 457        dst_cpu = s390_cpu_addr2state(env->regs[r3]);
 458        ret = handle_sigp_single_dst(cpu, dst_cpu, order, param, status_reg);
 459    }
 460    qemu_mutex_unlock(&qemu_sigp_mutex);
 461
 462out:
 463    trace_sigp_finished(order, CPU(cpu)->cpu_index,
 464                        dst_cpu ? CPU(dst_cpu)->cpu_index : -1, ret);
 465    g_assert(ret >= 0);
 466
 467    return ret;
 468}
 469
 470int s390_cpu_restart(S390CPU *cpu)
 471{
 472    SigpInfo si = {};
 473
 474    run_on_cpu(CPU(cpu), sigp_restart, RUN_ON_CPU_HOST_PTR(&si));
 475    return 0;
 476}
 477
 478void do_stop_interrupt(CPUS390XState *env)
 479{
 480    S390CPU *cpu = env_archcpu(env);
 481
 482    /*
 483     * Complete the STOP operation before exposing the CPU as
 484     * STOPPED to the system.
 485     */
 486    if (cpu->env.sigp_order == SIGP_STOP_STORE_STATUS) {
 487        s390_store_status(cpu, S390_STORE_STATUS_DEF_ADDR, true);
 488    }
 489    env->sigp_order = 0;
 490    if (s390_cpu_set_state(S390_CPU_STATE_STOPPED, cpu) == 0) {
 491        qemu_system_shutdown_request(SHUTDOWN_CAUSE_GUEST_SHUTDOWN);
 492    }
 493    env->pending_int &= ~INTERRUPT_STOP;
 494}
 495
 496void s390_init_sigp(void)
 497{
 498    qemu_mutex_init(&qemu_sigp_mutex);
 499}
 500