qemu/target/s390x/excp_helper.c
<<
>>
Prefs
   1/*
   2 * s390x exception / interrupt helpers
   3 *
   4 *  Copyright (c) 2009 Ulrich Hecht
   5 *  Copyright (c) 2011 Alexander Graf
   6 *
   7 * This library is free software; you can redistribute it and/or
   8 * modify it under the terms of the GNU Lesser General Public
   9 * License as published by the Free Software Foundation; either
  10 * version 2.1 of the License, or (at your option) any later version.
  11 *
  12 * This library is distributed in the hope that it will be useful,
  13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  15 * Lesser General Public License for more details.
  16 *
  17 * You should have received a copy of the GNU Lesser General Public
  18 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  19 */
  20
  21#include "qemu/osdep.h"
  22#include "cpu.h"
  23#include "internal.h"
  24#include "exec/helper-proto.h"
  25#include "qemu/timer.h"
  26#include "exec/exec-all.h"
  27#include "exec/cpu_ldst.h"
  28#include "hw/s390x/ioinst.h"
  29#include "exec/address-spaces.h"
  30#include "tcg_s390x.h"
  31#ifndef CONFIG_USER_ONLY
  32#include "sysemu/sysemu.h"
  33#include "hw/s390x/s390_flic.h"
  34#include "hw/boards.h"
  35#endif
  36
  37void QEMU_NORETURN tcg_s390_program_interrupt(CPUS390XState *env, uint32_t code,
  38                                              int ilen, uintptr_t ra)
  39{
  40    CPUState *cs = env_cpu(env);
  41
  42    cpu_restore_state(cs, ra, true);
  43    qemu_log_mask(CPU_LOG_INT, "program interrupt at %#" PRIx64 "\n",
  44                  env->psw.addr);
  45    trigger_pgm_exception(env, code, ilen);
  46    cpu_loop_exit(cs);
  47}
  48
  49void QEMU_NORETURN tcg_s390_data_exception(CPUS390XState *env, uint32_t dxc,
  50                                           uintptr_t ra)
  51{
  52    g_assert(dxc <= 0xff);
  53#if !defined(CONFIG_USER_ONLY)
  54    /* Store the DXC into the lowcore */
  55    stl_phys(env_cpu(env)->as,
  56             env->psa + offsetof(LowCore, data_exc_code), dxc);
  57#endif
  58
  59    /* Store the DXC into the FPC if AFP is enabled */
  60    if (env->cregs[0] & CR0_AFP) {
  61        env->fpc = deposit32(env->fpc, 8, 8, dxc);
  62    }
  63    tcg_s390_program_interrupt(env, PGM_DATA, ILEN_AUTO, ra);
  64}
  65
  66void QEMU_NORETURN tcg_s390_vector_exception(CPUS390XState *env, uint32_t vxc,
  67                                             uintptr_t ra)
  68{
  69    g_assert(vxc <= 0xff);
  70#if !defined(CONFIG_USER_ONLY)
  71    /* Always store the VXC into the lowcore, without AFP it is undefined */
  72    stl_phys(env_cpu(env)->as,
  73             env->psa + offsetof(LowCore, data_exc_code), vxc);
  74#endif
  75
  76    /* Always store the VXC into the FPC, without AFP it is undefined */
  77    env->fpc = deposit32(env->fpc, 8, 8, vxc);
  78    tcg_s390_program_interrupt(env, PGM_VECTOR_PROCESSING, ILEN_AUTO, ra);
  79}
  80
  81void HELPER(data_exception)(CPUS390XState *env, uint32_t dxc)
  82{
  83    tcg_s390_data_exception(env, dxc, GETPC());
  84}
  85
  86#if defined(CONFIG_USER_ONLY)
  87
  88void s390_cpu_do_interrupt(CPUState *cs)
  89{
  90    cs->exception_index = -1;
  91}
  92
  93bool s390_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
  94                       MMUAccessType access_type, int mmu_idx,
  95                       bool probe, uintptr_t retaddr)
  96{
  97    S390CPU *cpu = S390_CPU(cs);
  98
  99    trigger_pgm_exception(&cpu->env, PGM_ADDRESSING, ILEN_AUTO);
 100    /* On real machines this value is dropped into LowMem.  Since this
 101       is userland, simply put this someplace that cpu_loop can find it.  */
 102    cpu->env.__excp_addr = address;
 103    cpu_loop_exit_restore(cs, retaddr);
 104}
 105
 106#else /* !CONFIG_USER_ONLY */
 107
 108static inline uint64_t cpu_mmu_idx_to_asc(int mmu_idx)
 109{
 110    switch (mmu_idx) {
 111    case MMU_PRIMARY_IDX:
 112        return PSW_ASC_PRIMARY;
 113    case MMU_SECONDARY_IDX:
 114        return PSW_ASC_SECONDARY;
 115    case MMU_HOME_IDX:
 116        return PSW_ASC_HOME;
 117    default:
 118        abort();
 119    }
 120}
 121
 122bool s390_cpu_tlb_fill(CPUState *cs, vaddr address, int size,
 123                       MMUAccessType access_type, int mmu_idx,
 124                       bool probe, uintptr_t retaddr)
 125{
 126    S390CPU *cpu = S390_CPU(cs);
 127    CPUS390XState *env = &cpu->env;
 128    target_ulong vaddr, raddr;
 129    uint64_t asc;
 130    int prot, fail;
 131
 132    qemu_log_mask(CPU_LOG_MMU, "%s: addr 0x%" VADDR_PRIx " rw %d mmu_idx %d\n",
 133                  __func__, address, access_type, mmu_idx);
 134
 135    vaddr = address;
 136
 137    if (mmu_idx < MMU_REAL_IDX) {
 138        asc = cpu_mmu_idx_to_asc(mmu_idx);
 139        /* 31-Bit mode */
 140        if (!(env->psw.mask & PSW_MASK_64)) {
 141            vaddr &= 0x7fffffff;
 142        }
 143        fail = mmu_translate(env, vaddr, access_type, asc, &raddr, &prot, true);
 144    } else if (mmu_idx == MMU_REAL_IDX) {
 145        /* 31-Bit mode */
 146        if (!(env->psw.mask & PSW_MASK_64)) {
 147            vaddr &= 0x7fffffff;
 148        }
 149        fail = mmu_translate_real(env, vaddr, access_type, &raddr, &prot);
 150    } else {
 151        g_assert_not_reached();
 152    }
 153
 154    /* check out of RAM access */
 155    if (!fail &&
 156        !address_space_access_valid(&address_space_memory, raddr,
 157                                    TARGET_PAGE_SIZE, access_type,
 158                                    MEMTXATTRS_UNSPECIFIED)) {
 159        qemu_log_mask(CPU_LOG_MMU,
 160                      "%s: raddr %" PRIx64 " > ram_size %" PRIx64 "\n",
 161                      __func__, (uint64_t)raddr, (uint64_t)ram_size);
 162        trigger_pgm_exception(env, PGM_ADDRESSING, ILEN_AUTO);
 163        fail = 1;
 164    }
 165
 166    if (!fail) {
 167        qemu_log_mask(CPU_LOG_MMU,
 168                      "%s: set tlb %" PRIx64 " -> %" PRIx64 " (%x)\n",
 169                      __func__, (uint64_t)vaddr, (uint64_t)raddr, prot);
 170        tlb_set_page(cs, address & TARGET_PAGE_MASK, raddr, prot,
 171                     mmu_idx, TARGET_PAGE_SIZE);
 172        return true;
 173    }
 174    if (probe) {
 175        return false;
 176    }
 177
 178    cpu_restore_state(cs, retaddr, true);
 179
 180    /*
 181     * The ILC value for code accesses is undefined.  The important
 182     * thing here is to *not* leave env->int_pgm_ilen set to ILEN_AUTO,
 183     * which would cause do_program_interrupt to attempt to read from
 184     * env->psw.addr again.  C.f. the condition in trigger_page_fault,
 185     * but is not universally applied.
 186     *
 187     * ??? If we remove ILEN_AUTO, by moving the computation of ILEN
 188     * into cpu_restore_state, then we may remove this entirely.
 189     */
 190    if (access_type == MMU_INST_FETCH) {
 191        env->int_pgm_ilen = 2;
 192    }
 193
 194    cpu_loop_exit(cs);
 195}
 196
 197static void do_program_interrupt(CPUS390XState *env)
 198{
 199    uint64_t mask, addr;
 200    LowCore *lowcore;
 201    int ilen = env->int_pgm_ilen;
 202
 203    if (ilen == ILEN_AUTO) {
 204        ilen = get_ilen(cpu_ldub_code(env, env->psw.addr));
 205    }
 206    assert(ilen == 2 || ilen == 4 || ilen == 6);
 207
 208    switch (env->int_pgm_code) {
 209    case PGM_PER:
 210        if (env->per_perc_atmid & PER_CODE_EVENT_NULLIFICATION) {
 211            break;
 212        }
 213        /* FALL THROUGH */
 214    case PGM_OPERATION:
 215    case PGM_PRIVILEGED:
 216    case PGM_EXECUTE:
 217    case PGM_PROTECTION:
 218    case PGM_ADDRESSING:
 219    case PGM_SPECIFICATION:
 220    case PGM_DATA:
 221    case PGM_FIXPT_OVERFLOW:
 222    case PGM_FIXPT_DIVIDE:
 223    case PGM_DEC_OVERFLOW:
 224    case PGM_DEC_DIVIDE:
 225    case PGM_HFP_EXP_OVERFLOW:
 226    case PGM_HFP_EXP_UNDERFLOW:
 227    case PGM_HFP_SIGNIFICANCE:
 228    case PGM_HFP_DIVIDE:
 229    case PGM_TRANS_SPEC:
 230    case PGM_SPECIAL_OP:
 231    case PGM_OPERAND:
 232    case PGM_HFP_SQRT:
 233    case PGM_PC_TRANS_SPEC:
 234    case PGM_ALET_SPEC:
 235    case PGM_MONITOR:
 236        /* advance the PSW if our exception is not nullifying */
 237        env->psw.addr += ilen;
 238        break;
 239    }
 240
 241    qemu_log_mask(CPU_LOG_INT,
 242                  "%s: code=0x%x ilen=%d psw: %" PRIx64 " %" PRIx64 "\n",
 243                  __func__, env->int_pgm_code, ilen, env->psw.mask,
 244                  env->psw.addr);
 245
 246    lowcore = cpu_map_lowcore(env);
 247
 248    /* Signal PER events with the exception.  */
 249    if (env->per_perc_atmid) {
 250        env->int_pgm_code |= PGM_PER;
 251        lowcore->per_address = cpu_to_be64(env->per_address);
 252        lowcore->per_perc_atmid = cpu_to_be16(env->per_perc_atmid);
 253        env->per_perc_atmid = 0;
 254    }
 255
 256    lowcore->pgm_ilen = cpu_to_be16(ilen);
 257    lowcore->pgm_code = cpu_to_be16(env->int_pgm_code);
 258    lowcore->program_old_psw.mask = cpu_to_be64(get_psw_mask(env));
 259    lowcore->program_old_psw.addr = cpu_to_be64(env->psw.addr);
 260    mask = be64_to_cpu(lowcore->program_new_psw.mask);
 261    addr = be64_to_cpu(lowcore->program_new_psw.addr);
 262    lowcore->per_breaking_event_addr = cpu_to_be64(env->gbea);
 263
 264    cpu_unmap_lowcore(lowcore);
 265
 266    load_psw(env, mask, addr);
 267}
 268
 269static void do_svc_interrupt(CPUS390XState *env)
 270{
 271    uint64_t mask, addr;
 272    LowCore *lowcore;
 273
 274    lowcore = cpu_map_lowcore(env);
 275
 276    lowcore->svc_code = cpu_to_be16(env->int_svc_code);
 277    lowcore->svc_ilen = cpu_to_be16(env->int_svc_ilen);
 278    lowcore->svc_old_psw.mask = cpu_to_be64(get_psw_mask(env));
 279    lowcore->svc_old_psw.addr = cpu_to_be64(env->psw.addr + env->int_svc_ilen);
 280    mask = be64_to_cpu(lowcore->svc_new_psw.mask);
 281    addr = be64_to_cpu(lowcore->svc_new_psw.addr);
 282
 283    cpu_unmap_lowcore(lowcore);
 284
 285    load_psw(env, mask, addr);
 286
 287    /* When a PER event is pending, the PER exception has to happen
 288       immediately after the SERVICE CALL one.  */
 289    if (env->per_perc_atmid) {
 290        env->int_pgm_code = PGM_PER;
 291        env->int_pgm_ilen = env->int_svc_ilen;
 292        do_program_interrupt(env);
 293    }
 294}
 295
 296#define VIRTIO_SUBCODE_64 0x0D00
 297
 298static void do_ext_interrupt(CPUS390XState *env)
 299{
 300    QEMUS390FLICState *flic = QEMU_S390_FLIC(s390_get_flic());
 301    S390CPU *cpu = env_archcpu(env);
 302    uint64_t mask, addr;
 303    uint16_t cpu_addr;
 304    LowCore *lowcore;
 305
 306    if (!(env->psw.mask & PSW_MASK_EXT)) {
 307        cpu_abort(CPU(cpu), "Ext int w/o ext mask\n");
 308    }
 309
 310    lowcore = cpu_map_lowcore(env);
 311
 312    if ((env->pending_int & INTERRUPT_EMERGENCY_SIGNAL) &&
 313        (env->cregs[0] & CR0_EMERGENCY_SIGNAL_SC)) {
 314        lowcore->ext_int_code = cpu_to_be16(EXT_EMERGENCY);
 315        cpu_addr = find_first_bit(env->emergency_signals, S390_MAX_CPUS);
 316        g_assert(cpu_addr < S390_MAX_CPUS);
 317        lowcore->cpu_addr = cpu_to_be16(cpu_addr);
 318        clear_bit(cpu_addr, env->emergency_signals);
 319#ifndef CONFIG_USER_ONLY
 320        MachineState *ms = MACHINE(qdev_get_machine());
 321        unsigned int max_cpus = ms->smp.max_cpus;
 322#endif
 323        if (bitmap_empty(env->emergency_signals, max_cpus)) {
 324            env->pending_int &= ~INTERRUPT_EMERGENCY_SIGNAL;
 325        }
 326    } else if ((env->pending_int & INTERRUPT_EXTERNAL_CALL) &&
 327               (env->cregs[0] & CR0_EXTERNAL_CALL_SC)) {
 328        lowcore->ext_int_code = cpu_to_be16(EXT_EXTERNAL_CALL);
 329        lowcore->cpu_addr = cpu_to_be16(env->external_call_addr);
 330        env->pending_int &= ~INTERRUPT_EXTERNAL_CALL;
 331    } else if ((env->pending_int & INTERRUPT_EXT_CLOCK_COMPARATOR) &&
 332               (env->cregs[0] & CR0_CKC_SC)) {
 333        lowcore->ext_int_code = cpu_to_be16(EXT_CLOCK_COMP);
 334        lowcore->cpu_addr = 0;
 335        env->pending_int &= ~INTERRUPT_EXT_CLOCK_COMPARATOR;
 336    } else if ((env->pending_int & INTERRUPT_EXT_CPU_TIMER) &&
 337               (env->cregs[0] & CR0_CPU_TIMER_SC)) {
 338        lowcore->ext_int_code = cpu_to_be16(EXT_CPU_TIMER);
 339        lowcore->cpu_addr = 0;
 340        env->pending_int &= ~INTERRUPT_EXT_CPU_TIMER;
 341    } else if (qemu_s390_flic_has_service(flic) &&
 342               (env->cregs[0] & CR0_SERVICE_SC)) {
 343        uint32_t param;
 344
 345        param = qemu_s390_flic_dequeue_service(flic);
 346        lowcore->ext_int_code = cpu_to_be16(EXT_SERVICE);
 347        lowcore->ext_params = cpu_to_be32(param);
 348        lowcore->cpu_addr = 0;
 349    } else {
 350        g_assert_not_reached();
 351    }
 352
 353    mask = be64_to_cpu(lowcore->external_new_psw.mask);
 354    addr = be64_to_cpu(lowcore->external_new_psw.addr);
 355    lowcore->external_old_psw.mask = cpu_to_be64(get_psw_mask(env));
 356    lowcore->external_old_psw.addr = cpu_to_be64(env->psw.addr);
 357
 358    cpu_unmap_lowcore(lowcore);
 359
 360    load_psw(env, mask, addr);
 361}
 362
 363static void do_io_interrupt(CPUS390XState *env)
 364{
 365    QEMUS390FLICState *flic = QEMU_S390_FLIC(s390_get_flic());
 366    uint64_t mask, addr;
 367    QEMUS390FlicIO *io;
 368    LowCore *lowcore;
 369
 370    g_assert(env->psw.mask & PSW_MASK_IO);
 371    io = qemu_s390_flic_dequeue_io(flic, env->cregs[6]);
 372    g_assert(io);
 373
 374    lowcore = cpu_map_lowcore(env);
 375
 376    lowcore->subchannel_id = cpu_to_be16(io->id);
 377    lowcore->subchannel_nr = cpu_to_be16(io->nr);
 378    lowcore->io_int_parm = cpu_to_be32(io->parm);
 379    lowcore->io_int_word = cpu_to_be32(io->word);
 380    lowcore->io_old_psw.mask = cpu_to_be64(get_psw_mask(env));
 381    lowcore->io_old_psw.addr = cpu_to_be64(env->psw.addr);
 382    mask = be64_to_cpu(lowcore->io_new_psw.mask);
 383    addr = be64_to_cpu(lowcore->io_new_psw.addr);
 384
 385    cpu_unmap_lowcore(lowcore);
 386    g_free(io);
 387
 388    load_psw(env, mask, addr);
 389}
 390
 391typedef struct MchkExtSaveArea {
 392    uint64_t    vregs[32][2];                     /* 0x0000 */
 393    uint8_t     pad_0x0200[0x0400 - 0x0200];      /* 0x0200 */
 394} MchkExtSaveArea;
 395QEMU_BUILD_BUG_ON(sizeof(MchkExtSaveArea) != 1024);
 396
 397static int mchk_store_vregs(CPUS390XState *env, uint64_t mcesao)
 398{
 399    hwaddr len = sizeof(MchkExtSaveArea);
 400    MchkExtSaveArea *sa;
 401    int i;
 402
 403    sa = cpu_physical_memory_map(mcesao, &len, 1);
 404    if (!sa) {
 405        return -EFAULT;
 406    }
 407    if (len != sizeof(MchkExtSaveArea)) {
 408        cpu_physical_memory_unmap(sa, len, 1, 0);
 409        return -EFAULT;
 410    }
 411
 412    for (i = 0; i < 32; i++) {
 413        sa->vregs[i][0] = cpu_to_be64(env->vregs[i][0]);
 414        sa->vregs[i][1] = cpu_to_be64(env->vregs[i][1]);
 415    }
 416
 417    cpu_physical_memory_unmap(sa, len, 1, len);
 418    return 0;
 419}
 420
 421static void do_mchk_interrupt(CPUS390XState *env)
 422{
 423    QEMUS390FLICState *flic = QEMU_S390_FLIC(s390_get_flic());
 424    uint64_t mcic = s390_build_validity_mcic() | MCIC_SC_CP;
 425    uint64_t mask, addr, mcesao = 0;
 426    LowCore *lowcore;
 427    int i;
 428
 429    /* for now we only support channel report machine checks (floating) */
 430    g_assert(env->psw.mask & PSW_MASK_MCHECK);
 431    g_assert(env->cregs[14] & CR14_CHANNEL_REPORT_SC);
 432
 433    qemu_s390_flic_dequeue_crw_mchk(flic);
 434
 435    lowcore = cpu_map_lowcore(env);
 436
 437    /* extended save area */
 438    if (mcic & MCIC_VB_VR) {
 439        /* length and alignment is 1024 bytes */
 440        mcesao = be64_to_cpu(lowcore->mcesad) & ~0x3ffull;
 441    }
 442
 443    /* try to store vector registers */
 444    if (!mcesao || mchk_store_vregs(env, mcesao)) {
 445        mcic &= ~MCIC_VB_VR;
 446    }
 447
 448    /* we are always in z/Architecture mode */
 449    lowcore->ar_access_id = 1;
 450
 451    for (i = 0; i < 16; i++) {
 452        lowcore->floating_pt_save_area[i] = cpu_to_be64(*get_freg(env, i));
 453        lowcore->gpregs_save_area[i] = cpu_to_be64(env->regs[i]);
 454        lowcore->access_regs_save_area[i] = cpu_to_be32(env->aregs[i]);
 455        lowcore->cregs_save_area[i] = cpu_to_be64(env->cregs[i]);
 456    }
 457    lowcore->prefixreg_save_area = cpu_to_be32(env->psa);
 458    lowcore->fpt_creg_save_area = cpu_to_be32(env->fpc);
 459    lowcore->tod_progreg_save_area = cpu_to_be32(env->todpr);
 460    lowcore->cpu_timer_save_area = cpu_to_be64(env->cputm);
 461    lowcore->clock_comp_save_area = cpu_to_be64(env->ckc >> 8);
 462
 463    lowcore->mcic = cpu_to_be64(mcic);
 464    lowcore->mcck_old_psw.mask = cpu_to_be64(get_psw_mask(env));
 465    lowcore->mcck_old_psw.addr = cpu_to_be64(env->psw.addr);
 466    mask = be64_to_cpu(lowcore->mcck_new_psw.mask);
 467    addr = be64_to_cpu(lowcore->mcck_new_psw.addr);
 468
 469    cpu_unmap_lowcore(lowcore);
 470
 471    load_psw(env, mask, addr);
 472}
 473
 474void s390_cpu_do_interrupt(CPUState *cs)
 475{
 476    QEMUS390FLICState *flic = QEMU_S390_FLIC(s390_get_flic());
 477    S390CPU *cpu = S390_CPU(cs);
 478    CPUS390XState *env = &cpu->env;
 479    bool stopped = false;
 480
 481    qemu_log_mask(CPU_LOG_INT, "%s: %d at psw=%" PRIx64 ":%" PRIx64 "\n",
 482                  __func__, cs->exception_index, env->psw.mask, env->psw.addr);
 483
 484try_deliver:
 485    /* handle machine checks */
 486    if (cs->exception_index == -1 && s390_cpu_has_mcck_int(cpu)) {
 487        cs->exception_index = EXCP_MCHK;
 488    }
 489    /* handle external interrupts */
 490    if (cs->exception_index == -1 && s390_cpu_has_ext_int(cpu)) {
 491        cs->exception_index = EXCP_EXT;
 492    }
 493    /* handle I/O interrupts */
 494    if (cs->exception_index == -1 && s390_cpu_has_io_int(cpu)) {
 495        cs->exception_index = EXCP_IO;
 496    }
 497    /* RESTART interrupt */
 498    if (cs->exception_index == -1 && s390_cpu_has_restart_int(cpu)) {
 499        cs->exception_index = EXCP_RESTART;
 500    }
 501    /* STOP interrupt has least priority */
 502    if (cs->exception_index == -1 && s390_cpu_has_stop_int(cpu)) {
 503        cs->exception_index = EXCP_STOP;
 504    }
 505
 506    switch (cs->exception_index) {
 507    case EXCP_PGM:
 508        do_program_interrupt(env);
 509        break;
 510    case EXCP_SVC:
 511        do_svc_interrupt(env);
 512        break;
 513    case EXCP_EXT:
 514        do_ext_interrupt(env);
 515        break;
 516    case EXCP_IO:
 517        do_io_interrupt(env);
 518        break;
 519    case EXCP_MCHK:
 520        do_mchk_interrupt(env);
 521        break;
 522    case EXCP_RESTART:
 523        do_restart_interrupt(env);
 524        break;
 525    case EXCP_STOP:
 526        do_stop_interrupt(env);
 527        stopped = true;
 528        break;
 529    }
 530
 531    if (cs->exception_index != -1 && !stopped) {
 532        /* check if there are more pending interrupts to deliver */
 533        cs->exception_index = -1;
 534        goto try_deliver;
 535    }
 536    cs->exception_index = -1;
 537
 538    /* we might still have pending interrupts, but not deliverable */
 539    if (!env->pending_int && !qemu_s390_flic_has_any(flic)) {
 540        cs->interrupt_request &= ~CPU_INTERRUPT_HARD;
 541    }
 542
 543    /* WAIT PSW during interrupt injection or STOP interrupt */
 544    if ((env->psw.mask & PSW_MASK_WAIT) || stopped) {
 545        /* don't trigger a cpu_loop_exit(), use an interrupt instead */
 546        cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HALT);
 547    } else if (cs->halted) {
 548        /* unhalt if we had a WAIT PSW somehwere in our injection chain */
 549        s390_cpu_unhalt(cpu);
 550    }
 551}
 552
 553bool s390_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
 554{
 555    if (interrupt_request & CPU_INTERRUPT_HARD) {
 556        S390CPU *cpu = S390_CPU(cs);
 557        CPUS390XState *env = &cpu->env;
 558
 559        if (env->ex_value) {
 560            /* Execution of the target insn is indivisible from
 561               the parent EXECUTE insn.  */
 562            return false;
 563        }
 564        if (s390_cpu_has_int(cpu)) {
 565            s390_cpu_do_interrupt(cs);
 566            return true;
 567        }
 568        if (env->psw.mask & PSW_MASK_WAIT) {
 569            /* Woken up because of a floating interrupt but it has already
 570             * been delivered. Go back to sleep. */
 571            cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HALT);
 572        }
 573    }
 574    return false;
 575}
 576
 577void s390x_cpu_debug_excp_handler(CPUState *cs)
 578{
 579    S390CPU *cpu = S390_CPU(cs);
 580    CPUS390XState *env = &cpu->env;
 581    CPUWatchpoint *wp_hit = cs->watchpoint_hit;
 582
 583    if (wp_hit && wp_hit->flags & BP_CPU) {
 584        /* FIXME: When the storage-alteration-space control bit is set,
 585           the exception should only be triggered if the memory access
 586           is done using an address space with the storage-alteration-event
 587           bit set.  We have no way to detect that with the current
 588           watchpoint code.  */
 589        cs->watchpoint_hit = NULL;
 590
 591        env->per_address = env->psw.addr;
 592        env->per_perc_atmid |= PER_CODE_EVENT_STORE | get_per_atmid(env);
 593        /* FIXME: We currently no way to detect the address space used
 594           to trigger the watchpoint.  For now just consider it is the
 595           current default ASC. This turn to be true except when MVCP
 596           and MVCS instrutions are not used.  */
 597        env->per_perc_atmid |= env->psw.mask & (PSW_MASK_ASC) >> 46;
 598
 599        /* Remove all watchpoints to re-execute the code.  A PER exception
 600           will be triggered, it will call load_psw which will recompute
 601           the watchpoints.  */
 602        cpu_watchpoint_remove_all(cs, BP_CPU);
 603        cpu_loop_exit_noexc(cs);
 604    }
 605}
 606
 607/* Unaligned accesses are only diagnosed with MO_ALIGN.  At the moment,
 608   this is only for the atomic operations, for which we want to raise a
 609   specification exception.  */
 610void s390x_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
 611                                   MMUAccessType access_type,
 612                                   int mmu_idx, uintptr_t retaddr)
 613{
 614    S390CPU *cpu = S390_CPU(cs);
 615    CPUS390XState *env = &cpu->env;
 616
 617    s390_program_interrupt(env, PGM_SPECIFICATION, ILEN_AUTO, retaddr);
 618}
 619
 620#endif /* CONFIG_USER_ONLY */
 621