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,
  38                                              uint32_t code, 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);
  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, 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, 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);
 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, tec;
 130    int prot, excp;
 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        excp = mmu_translate(env, vaddr, access_type, asc, &raddr, &prot, &tec);
 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        excp = mmu_translate_real(env, vaddr, access_type, &raddr, &prot, &tec);
 150    } else {
 151        g_assert_not_reached();
 152    }
 153
 154    /* check out of RAM access */
 155    if (!excp &&
 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        excp = PGM_ADDRESSING;
 163        tec = 0; /* unused */
 164    }
 165
 166    if (!excp) {
 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    if (excp != PGM_ADDRESSING) {
 179        stq_phys(env_cpu(env)->as,
 180                 env->psa + offsetof(LowCore, trans_exc_code), tec);
 181    }
 182
 183    /*
 184     * For data accesses, ILEN will be filled in from the unwind info,
 185     * within cpu_loop_exit_restore.  For code accesses, retaddr == 0,
 186     * and so unwinding will not occur.  However, ILEN is also undefined
 187     * for that case -- we choose to set ILEN = 2.
 188     */
 189    env->int_pgm_ilen = 2;
 190    trigger_pgm_exception(env, excp);
 191    cpu_loop_exit_restore(cs, retaddr);
 192}
 193
 194static void do_program_interrupt(CPUS390XState *env)
 195{
 196    uint64_t mask, addr;
 197    LowCore *lowcore;
 198    int ilen = env->int_pgm_ilen;
 199
 200    assert(ilen == 2 || ilen == 4 || ilen == 6);
 201
 202    switch (env->int_pgm_code) {
 203    case PGM_PER:
 204        if (env->per_perc_atmid & PER_CODE_EVENT_NULLIFICATION) {
 205            break;
 206        }
 207        /* FALL THROUGH */
 208    case PGM_OPERATION:
 209    case PGM_PRIVILEGED:
 210    case PGM_EXECUTE:
 211    case PGM_PROTECTION:
 212    case PGM_ADDRESSING:
 213    case PGM_SPECIFICATION:
 214    case PGM_DATA:
 215    case PGM_FIXPT_OVERFLOW:
 216    case PGM_FIXPT_DIVIDE:
 217    case PGM_DEC_OVERFLOW:
 218    case PGM_DEC_DIVIDE:
 219    case PGM_HFP_EXP_OVERFLOW:
 220    case PGM_HFP_EXP_UNDERFLOW:
 221    case PGM_HFP_SIGNIFICANCE:
 222    case PGM_HFP_DIVIDE:
 223    case PGM_TRANS_SPEC:
 224    case PGM_SPECIAL_OP:
 225    case PGM_OPERAND:
 226    case PGM_HFP_SQRT:
 227    case PGM_PC_TRANS_SPEC:
 228    case PGM_ALET_SPEC:
 229    case PGM_MONITOR:
 230        /* advance the PSW if our exception is not nullifying */
 231        env->psw.addr += ilen;
 232        break;
 233    }
 234
 235    qemu_log_mask(CPU_LOG_INT,
 236                  "%s: code=0x%x ilen=%d psw: %" PRIx64 " %" PRIx64 "\n",
 237                  __func__, env->int_pgm_code, ilen, env->psw.mask,
 238                  env->psw.addr);
 239
 240    lowcore = cpu_map_lowcore(env);
 241
 242    /* Signal PER events with the exception.  */
 243    if (env->per_perc_atmid) {
 244        env->int_pgm_code |= PGM_PER;
 245        lowcore->per_address = cpu_to_be64(env->per_address);
 246        lowcore->per_perc_atmid = cpu_to_be16(env->per_perc_atmid);
 247        env->per_perc_atmid = 0;
 248    }
 249
 250    lowcore->pgm_ilen = cpu_to_be16(ilen);
 251    lowcore->pgm_code = cpu_to_be16(env->int_pgm_code);
 252    lowcore->program_old_psw.mask = cpu_to_be64(get_psw_mask(env));
 253    lowcore->program_old_psw.addr = cpu_to_be64(env->psw.addr);
 254    mask = be64_to_cpu(lowcore->program_new_psw.mask);
 255    addr = be64_to_cpu(lowcore->program_new_psw.addr);
 256    lowcore->per_breaking_event_addr = cpu_to_be64(env->gbea);
 257
 258    cpu_unmap_lowcore(lowcore);
 259
 260    load_psw(env, mask, addr);
 261}
 262
 263static void do_svc_interrupt(CPUS390XState *env)
 264{
 265    uint64_t mask, addr;
 266    LowCore *lowcore;
 267
 268    lowcore = cpu_map_lowcore(env);
 269
 270    lowcore->svc_code = cpu_to_be16(env->int_svc_code);
 271    lowcore->svc_ilen = cpu_to_be16(env->int_svc_ilen);
 272    lowcore->svc_old_psw.mask = cpu_to_be64(get_psw_mask(env));
 273    lowcore->svc_old_psw.addr = cpu_to_be64(env->psw.addr + env->int_svc_ilen);
 274    mask = be64_to_cpu(lowcore->svc_new_psw.mask);
 275    addr = be64_to_cpu(lowcore->svc_new_psw.addr);
 276
 277    cpu_unmap_lowcore(lowcore);
 278
 279    load_psw(env, mask, addr);
 280
 281    /* When a PER event is pending, the PER exception has to happen
 282       immediately after the SERVICE CALL one.  */
 283    if (env->per_perc_atmid) {
 284        env->int_pgm_code = PGM_PER;
 285        env->int_pgm_ilen = env->int_svc_ilen;
 286        do_program_interrupt(env);
 287    }
 288}
 289
 290#define VIRTIO_SUBCODE_64 0x0D00
 291
 292static void do_ext_interrupt(CPUS390XState *env)
 293{
 294    QEMUS390FLICState *flic = QEMU_S390_FLIC(s390_get_flic());
 295    S390CPU *cpu = env_archcpu(env);
 296    uint64_t mask, addr;
 297    uint16_t cpu_addr;
 298    LowCore *lowcore;
 299
 300    if (!(env->psw.mask & PSW_MASK_EXT)) {
 301        cpu_abort(CPU(cpu), "Ext int w/o ext mask\n");
 302    }
 303
 304    lowcore = cpu_map_lowcore(env);
 305
 306    if ((env->pending_int & INTERRUPT_EMERGENCY_SIGNAL) &&
 307        (env->cregs[0] & CR0_EMERGENCY_SIGNAL_SC)) {
 308        lowcore->ext_int_code = cpu_to_be16(EXT_EMERGENCY);
 309        cpu_addr = find_first_bit(env->emergency_signals, S390_MAX_CPUS);
 310        g_assert(cpu_addr < S390_MAX_CPUS);
 311        lowcore->cpu_addr = cpu_to_be16(cpu_addr);
 312        clear_bit(cpu_addr, env->emergency_signals);
 313#ifndef CONFIG_USER_ONLY
 314        MachineState *ms = MACHINE(qdev_get_machine());
 315        unsigned int max_cpus = ms->smp.max_cpus;
 316#endif
 317        if (bitmap_empty(env->emergency_signals, max_cpus)) {
 318            env->pending_int &= ~INTERRUPT_EMERGENCY_SIGNAL;
 319        }
 320    } else if ((env->pending_int & INTERRUPT_EXTERNAL_CALL) &&
 321               (env->cregs[0] & CR0_EXTERNAL_CALL_SC)) {
 322        lowcore->ext_int_code = cpu_to_be16(EXT_EXTERNAL_CALL);
 323        lowcore->cpu_addr = cpu_to_be16(env->external_call_addr);
 324        env->pending_int &= ~INTERRUPT_EXTERNAL_CALL;
 325    } else if ((env->pending_int & INTERRUPT_EXT_CLOCK_COMPARATOR) &&
 326               (env->cregs[0] & CR0_CKC_SC)) {
 327        lowcore->ext_int_code = cpu_to_be16(EXT_CLOCK_COMP);
 328        lowcore->cpu_addr = 0;
 329        env->pending_int &= ~INTERRUPT_EXT_CLOCK_COMPARATOR;
 330    } else if ((env->pending_int & INTERRUPT_EXT_CPU_TIMER) &&
 331               (env->cregs[0] & CR0_CPU_TIMER_SC)) {
 332        lowcore->ext_int_code = cpu_to_be16(EXT_CPU_TIMER);
 333        lowcore->cpu_addr = 0;
 334        env->pending_int &= ~INTERRUPT_EXT_CPU_TIMER;
 335    } else if (qemu_s390_flic_has_service(flic) &&
 336               (env->cregs[0] & CR0_SERVICE_SC)) {
 337        uint32_t param;
 338
 339        param = qemu_s390_flic_dequeue_service(flic);
 340        lowcore->ext_int_code = cpu_to_be16(EXT_SERVICE);
 341        lowcore->ext_params = cpu_to_be32(param);
 342        lowcore->cpu_addr = 0;
 343    } else {
 344        g_assert_not_reached();
 345    }
 346
 347    mask = be64_to_cpu(lowcore->external_new_psw.mask);
 348    addr = be64_to_cpu(lowcore->external_new_psw.addr);
 349    lowcore->external_old_psw.mask = cpu_to_be64(get_psw_mask(env));
 350    lowcore->external_old_psw.addr = cpu_to_be64(env->psw.addr);
 351
 352    cpu_unmap_lowcore(lowcore);
 353
 354    load_psw(env, mask, addr);
 355}
 356
 357static void do_io_interrupt(CPUS390XState *env)
 358{
 359    QEMUS390FLICState *flic = QEMU_S390_FLIC(s390_get_flic());
 360    uint64_t mask, addr;
 361    QEMUS390FlicIO *io;
 362    LowCore *lowcore;
 363
 364    g_assert(env->psw.mask & PSW_MASK_IO);
 365    io = qemu_s390_flic_dequeue_io(flic, env->cregs[6]);
 366    g_assert(io);
 367
 368    lowcore = cpu_map_lowcore(env);
 369
 370    lowcore->subchannel_id = cpu_to_be16(io->id);
 371    lowcore->subchannel_nr = cpu_to_be16(io->nr);
 372    lowcore->io_int_parm = cpu_to_be32(io->parm);
 373    lowcore->io_int_word = cpu_to_be32(io->word);
 374    lowcore->io_old_psw.mask = cpu_to_be64(get_psw_mask(env));
 375    lowcore->io_old_psw.addr = cpu_to_be64(env->psw.addr);
 376    mask = be64_to_cpu(lowcore->io_new_psw.mask);
 377    addr = be64_to_cpu(lowcore->io_new_psw.addr);
 378
 379    cpu_unmap_lowcore(lowcore);
 380    g_free(io);
 381
 382    load_psw(env, mask, addr);
 383}
 384
 385typedef struct MchkExtSaveArea {
 386    uint64_t    vregs[32][2];                     /* 0x0000 */
 387    uint8_t     pad_0x0200[0x0400 - 0x0200];      /* 0x0200 */
 388} MchkExtSaveArea;
 389QEMU_BUILD_BUG_ON(sizeof(MchkExtSaveArea) != 1024);
 390
 391static int mchk_store_vregs(CPUS390XState *env, uint64_t mcesao)
 392{
 393    hwaddr len = sizeof(MchkExtSaveArea);
 394    MchkExtSaveArea *sa;
 395    int i;
 396
 397    sa = cpu_physical_memory_map(mcesao, &len, 1);
 398    if (!sa) {
 399        return -EFAULT;
 400    }
 401    if (len != sizeof(MchkExtSaveArea)) {
 402        cpu_physical_memory_unmap(sa, len, 1, 0);
 403        return -EFAULT;
 404    }
 405
 406    for (i = 0; i < 32; i++) {
 407        sa->vregs[i][0] = cpu_to_be64(env->vregs[i][0]);
 408        sa->vregs[i][1] = cpu_to_be64(env->vregs[i][1]);
 409    }
 410
 411    cpu_physical_memory_unmap(sa, len, 1, len);
 412    return 0;
 413}
 414
 415static void do_mchk_interrupt(CPUS390XState *env)
 416{
 417    QEMUS390FLICState *flic = QEMU_S390_FLIC(s390_get_flic());
 418    uint64_t mcic = s390_build_validity_mcic() | MCIC_SC_CP;
 419    uint64_t mask, addr, mcesao = 0;
 420    LowCore *lowcore;
 421    int i;
 422
 423    /* for now we only support channel report machine checks (floating) */
 424    g_assert(env->psw.mask & PSW_MASK_MCHECK);
 425    g_assert(env->cregs[14] & CR14_CHANNEL_REPORT_SC);
 426
 427    qemu_s390_flic_dequeue_crw_mchk(flic);
 428
 429    lowcore = cpu_map_lowcore(env);
 430
 431    /* extended save area */
 432    if (mcic & MCIC_VB_VR) {
 433        /* length and alignment is 1024 bytes */
 434        mcesao = be64_to_cpu(lowcore->mcesad) & ~0x3ffull;
 435    }
 436
 437    /* try to store vector registers */
 438    if (!mcesao || mchk_store_vregs(env, mcesao)) {
 439        mcic &= ~MCIC_VB_VR;
 440    }
 441
 442    /* we are always in z/Architecture mode */
 443    lowcore->ar_access_id = 1;
 444
 445    for (i = 0; i < 16; i++) {
 446        lowcore->floating_pt_save_area[i] = cpu_to_be64(*get_freg(env, i));
 447        lowcore->gpregs_save_area[i] = cpu_to_be64(env->regs[i]);
 448        lowcore->access_regs_save_area[i] = cpu_to_be32(env->aregs[i]);
 449        lowcore->cregs_save_area[i] = cpu_to_be64(env->cregs[i]);
 450    }
 451    lowcore->prefixreg_save_area = cpu_to_be32(env->psa);
 452    lowcore->fpt_creg_save_area = cpu_to_be32(env->fpc);
 453    lowcore->tod_progreg_save_area = cpu_to_be32(env->todpr);
 454    lowcore->cpu_timer_save_area = cpu_to_be64(env->cputm);
 455    lowcore->clock_comp_save_area = cpu_to_be64(env->ckc >> 8);
 456
 457    lowcore->mcic = cpu_to_be64(mcic);
 458    lowcore->mcck_old_psw.mask = cpu_to_be64(get_psw_mask(env));
 459    lowcore->mcck_old_psw.addr = cpu_to_be64(env->psw.addr);
 460    mask = be64_to_cpu(lowcore->mcck_new_psw.mask);
 461    addr = be64_to_cpu(lowcore->mcck_new_psw.addr);
 462
 463    cpu_unmap_lowcore(lowcore);
 464
 465    load_psw(env, mask, addr);
 466}
 467
 468void s390_cpu_do_interrupt(CPUState *cs)
 469{
 470    QEMUS390FLICState *flic = QEMU_S390_FLIC(s390_get_flic());
 471    S390CPU *cpu = S390_CPU(cs);
 472    CPUS390XState *env = &cpu->env;
 473    bool stopped = false;
 474
 475    qemu_log_mask(CPU_LOG_INT, "%s: %d at psw=%" PRIx64 ":%" PRIx64 "\n",
 476                  __func__, cs->exception_index, env->psw.mask, env->psw.addr);
 477
 478try_deliver:
 479    /* handle machine checks */
 480    if (cs->exception_index == -1 && s390_cpu_has_mcck_int(cpu)) {
 481        cs->exception_index = EXCP_MCHK;
 482    }
 483    /* handle external interrupts */
 484    if (cs->exception_index == -1 && s390_cpu_has_ext_int(cpu)) {
 485        cs->exception_index = EXCP_EXT;
 486    }
 487    /* handle I/O interrupts */
 488    if (cs->exception_index == -1 && s390_cpu_has_io_int(cpu)) {
 489        cs->exception_index = EXCP_IO;
 490    }
 491    /* RESTART interrupt */
 492    if (cs->exception_index == -1 && s390_cpu_has_restart_int(cpu)) {
 493        cs->exception_index = EXCP_RESTART;
 494    }
 495    /* STOP interrupt has least priority */
 496    if (cs->exception_index == -1 && s390_cpu_has_stop_int(cpu)) {
 497        cs->exception_index = EXCP_STOP;
 498    }
 499
 500    switch (cs->exception_index) {
 501    case EXCP_PGM:
 502        do_program_interrupt(env);
 503        break;
 504    case EXCP_SVC:
 505        do_svc_interrupt(env);
 506        break;
 507    case EXCP_EXT:
 508        do_ext_interrupt(env);
 509        break;
 510    case EXCP_IO:
 511        do_io_interrupt(env);
 512        break;
 513    case EXCP_MCHK:
 514        do_mchk_interrupt(env);
 515        break;
 516    case EXCP_RESTART:
 517        do_restart_interrupt(env);
 518        break;
 519    case EXCP_STOP:
 520        do_stop_interrupt(env);
 521        stopped = true;
 522        break;
 523    }
 524
 525    if (cs->exception_index != -1 && !stopped) {
 526        /* check if there are more pending interrupts to deliver */
 527        cs->exception_index = -1;
 528        goto try_deliver;
 529    }
 530    cs->exception_index = -1;
 531
 532    /* we might still have pending interrupts, but not deliverable */
 533    if (!env->pending_int && !qemu_s390_flic_has_any(flic)) {
 534        cs->interrupt_request &= ~CPU_INTERRUPT_HARD;
 535    }
 536
 537    /* WAIT PSW during interrupt injection or STOP interrupt */
 538    if ((env->psw.mask & PSW_MASK_WAIT) || stopped) {
 539        /* don't trigger a cpu_loop_exit(), use an interrupt instead */
 540        cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HALT);
 541    } else if (cs->halted) {
 542        /* unhalt if we had a WAIT PSW somehwere in our injection chain */
 543        s390_cpu_unhalt(cpu);
 544    }
 545}
 546
 547bool s390_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
 548{
 549    if (interrupt_request & CPU_INTERRUPT_HARD) {
 550        S390CPU *cpu = S390_CPU(cs);
 551        CPUS390XState *env = &cpu->env;
 552
 553        if (env->ex_value) {
 554            /* Execution of the target insn is indivisible from
 555               the parent EXECUTE insn.  */
 556            return false;
 557        }
 558        if (s390_cpu_has_int(cpu)) {
 559            s390_cpu_do_interrupt(cs);
 560            return true;
 561        }
 562        if (env->psw.mask & PSW_MASK_WAIT) {
 563            /* Woken up because of a floating interrupt but it has already
 564             * been delivered. Go back to sleep. */
 565            cpu_interrupt(CPU(cpu), CPU_INTERRUPT_HALT);
 566        }
 567    }
 568    return false;
 569}
 570
 571void s390x_cpu_debug_excp_handler(CPUState *cs)
 572{
 573    S390CPU *cpu = S390_CPU(cs);
 574    CPUS390XState *env = &cpu->env;
 575    CPUWatchpoint *wp_hit = cs->watchpoint_hit;
 576
 577    if (wp_hit && wp_hit->flags & BP_CPU) {
 578        /* FIXME: When the storage-alteration-space control bit is set,
 579           the exception should only be triggered if the memory access
 580           is done using an address space with the storage-alteration-event
 581           bit set.  We have no way to detect that with the current
 582           watchpoint code.  */
 583        cs->watchpoint_hit = NULL;
 584
 585        env->per_address = env->psw.addr;
 586        env->per_perc_atmid |= PER_CODE_EVENT_STORE | get_per_atmid(env);
 587        /* FIXME: We currently no way to detect the address space used
 588           to trigger the watchpoint.  For now just consider it is the
 589           current default ASC. This turn to be true except when MVCP
 590           and MVCS instrutions are not used.  */
 591        env->per_perc_atmid |= env->psw.mask & (PSW_MASK_ASC) >> 46;
 592
 593        /* Remove all watchpoints to re-execute the code.  A PER exception
 594           will be triggered, it will call load_psw which will recompute
 595           the watchpoints.  */
 596        cpu_watchpoint_remove_all(cs, BP_CPU);
 597        cpu_loop_exit_noexc(cs);
 598    }
 599}
 600
 601/* Unaligned accesses are only diagnosed with MO_ALIGN.  At the moment,
 602   this is only for the atomic operations, for which we want to raise a
 603   specification exception.  */
 604void s390x_cpu_do_unaligned_access(CPUState *cs, vaddr addr,
 605                                   MMUAccessType access_type,
 606                                   int mmu_idx, uintptr_t retaddr)
 607{
 608    S390CPU *cpu = S390_CPU(cs);
 609    CPUS390XState *env = &cpu->env;
 610
 611    tcg_s390_program_interrupt(env, PGM_SPECIFICATION, retaddr);
 612}
 613
 614#endif /* CONFIG_USER_ONLY */
 615