qemu/target/ppc/excp_helper.c
<<
>>
Prefs
   1/*
   2 *  PowerPC exception emulation helpers for QEMU.
   3 *
   4 *  Copyright (c) 2003-2007 Jocelyn Mayer
   5 *
   6 * This library is free software; you can redistribute it and/or
   7 * modify it under the terms of the GNU Lesser General Public
   8 * License as published by the Free Software Foundation; either
   9 * version 2 of the License, or (at your option) any later version.
  10 *
  11 * This library is distributed in the hope that it will be useful,
  12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
  14 * Lesser General Public License for more details.
  15 *
  16 * You should have received a copy of the GNU Lesser General Public
  17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
  18 */
  19#include "qemu/osdep.h"
  20#include "qemu/main-loop.h"
  21#include "cpu.h"
  22#include "exec/helper-proto.h"
  23#include "exec/exec-all.h"
  24#include "exec/cpu_ldst.h"
  25#include "internal.h"
  26#include "helper_regs.h"
  27
  28/* #define DEBUG_OP */
  29/* #define DEBUG_SOFTWARE_TLB */
  30/* #define DEBUG_EXCEPTIONS */
  31
  32#ifdef DEBUG_EXCEPTIONS
  33#  define LOG_EXCP(...) qemu_log(__VA_ARGS__)
  34#else
  35#  define LOG_EXCP(...) do { } while (0)
  36#endif
  37
  38/*****************************************************************************/
  39/* Exception processing */
  40#if defined(CONFIG_USER_ONLY)
  41void ppc_cpu_do_interrupt(CPUState *cs)
  42{
  43    PowerPCCPU *cpu = POWERPC_CPU(cs);
  44    CPUPPCState *env = &cpu->env;
  45
  46    cs->exception_index = POWERPC_EXCP_NONE;
  47    env->error_code = 0;
  48}
  49
  50static void ppc_hw_interrupt(CPUPPCState *env)
  51{
  52    CPUState *cs = env_cpu(env);
  53
  54    cs->exception_index = POWERPC_EXCP_NONE;
  55    env->error_code = 0;
  56}
  57#else /* defined(CONFIG_USER_ONLY) */
  58static inline void dump_syscall(CPUPPCState *env)
  59{
  60    qemu_log_mask(CPU_LOG_INT, "syscall r0=%016" PRIx64 " r3=%016" PRIx64
  61                  " r4=%016" PRIx64 " r5=%016" PRIx64 " r6=%016" PRIx64
  62                  " nip=" TARGET_FMT_lx "\n",
  63                  ppc_dump_gpr(env, 0), ppc_dump_gpr(env, 3),
  64                  ppc_dump_gpr(env, 4), ppc_dump_gpr(env, 5),
  65                  ppc_dump_gpr(env, 6), env->nip);
  66}
  67
  68static int powerpc_reset_wakeup(CPUState *cs, CPUPPCState *env, int excp,
  69                                target_ulong *msr)
  70{
  71    /* We no longer are in a PM state */
  72    env->resume_as_sreset = false;
  73
  74    /* Pretend to be returning from doze always as we don't lose state */
  75    *msr |= (0x1ull << (63 - 47));
  76
  77    /* Machine checks are sent normally */
  78    if (excp == POWERPC_EXCP_MCHECK) {
  79        return excp;
  80    }
  81    switch (excp) {
  82    case POWERPC_EXCP_RESET:
  83        *msr |= 0x4ull << (63 - 45);
  84        break;
  85    case POWERPC_EXCP_EXTERNAL:
  86        *msr |= 0x8ull << (63 - 45);
  87        break;
  88    case POWERPC_EXCP_DECR:
  89        *msr |= 0x6ull << (63 - 45);
  90        break;
  91    case POWERPC_EXCP_SDOOR:
  92        *msr |= 0x5ull << (63 - 45);
  93        break;
  94    case POWERPC_EXCP_SDOOR_HV:
  95        *msr |= 0x3ull << (63 - 45);
  96        break;
  97    case POWERPC_EXCP_HV_MAINT:
  98        *msr |= 0xaull << (63 - 45);
  99        break;
 100    case POWERPC_EXCP_HVIRT:
 101        *msr |= 0x9ull << (63 - 45);
 102        break;
 103    default:
 104        cpu_abort(cs, "Unsupported exception %d in Power Save mode\n",
 105                  excp);
 106    }
 107    return POWERPC_EXCP_RESET;
 108}
 109
 110static uint64_t ppc_excp_vector_offset(CPUState *cs, int ail)
 111{
 112    uint64_t offset = 0;
 113
 114    switch (ail) {
 115    case AIL_0001_8000:
 116        offset = 0x18000;
 117        break;
 118    case AIL_C000_0000_0000_4000:
 119        offset = 0xc000000000004000ull;
 120        break;
 121    default:
 122        cpu_abort(cs, "Invalid AIL combination %d\n", ail);
 123        break;
 124    }
 125
 126    return offset;
 127}
 128
 129/*
 130 * Note that this function should be greatly optimized when called
 131 * with a constant excp, from ppc_hw_interrupt
 132 */
 133static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
 134{
 135    CPUState *cs = CPU(cpu);
 136    CPUPPCState *env = &cpu->env;
 137    target_ulong msr, new_msr, vector;
 138    int srr0, srr1, asrr0, asrr1, lev, ail;
 139    bool lpes0;
 140
 141    qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx
 142                  " => %08x (%02x)\n", env->nip, excp, env->error_code);
 143
 144    /* new srr1 value excluding must-be-zero bits */
 145    if (excp_model == POWERPC_EXCP_BOOKE) {
 146        msr = env->msr;
 147    } else {
 148        msr = env->msr & ~0x783f0000ULL;
 149    }
 150
 151    /*
 152     * new interrupt handler msr preserves existing HV and ME unless
 153     * explicitly overriden
 154     */
 155    new_msr = env->msr & (((target_ulong)1 << MSR_ME) | MSR_HVB);
 156
 157    /* target registers */
 158    srr0 = SPR_SRR0;
 159    srr1 = SPR_SRR1;
 160    asrr0 = -1;
 161    asrr1 = -1;
 162
 163    /*
 164     * check for special resume at 0x100 from doze/nap/sleep/winkle on
 165     * P7/P8/P9
 166     */
 167    if (env->resume_as_sreset) {
 168        excp = powerpc_reset_wakeup(cs, env, excp, &msr);
 169    }
 170
 171    /*
 172     * Exception targetting modifiers
 173     *
 174     * LPES0 is supported on POWER7/8/9
 175     * LPES1 is not supported (old iSeries mode)
 176     *
 177     * On anything else, we behave as if LPES0 is 1
 178     * (externals don't alter MSR:HV)
 179     *
 180     * AIL is initialized here but can be cleared by
 181     * selected exceptions
 182     */
 183#if defined(TARGET_PPC64)
 184    if (excp_model == POWERPC_EXCP_POWER7 ||
 185        excp_model == POWERPC_EXCP_POWER8 ||
 186        excp_model == POWERPC_EXCP_POWER9) {
 187        lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0);
 188        if (excp_model != POWERPC_EXCP_POWER7) {
 189            ail = (env->spr[SPR_LPCR] & LPCR_AIL) >> LPCR_AIL_SHIFT;
 190        } else {
 191            ail = 0;
 192        }
 193    } else
 194#endif /* defined(TARGET_PPC64) */
 195    {
 196        lpes0 = true;
 197        ail = 0;
 198    }
 199
 200    /*
 201     * Hypervisor emulation assistance interrupt only exists on server
 202     * arch 2.05 server or later. We also don't want to generate it if
 203     * we don't have HVB in msr_mask (PAPR mode).
 204     */
 205    if (excp == POWERPC_EXCP_HV_EMU
 206#if defined(TARGET_PPC64)
 207        && !((env->mmu_model & POWERPC_MMU_64) && (env->msr_mask & MSR_HVB))
 208#endif /* defined(TARGET_PPC64) */
 209
 210    ) {
 211        excp = POWERPC_EXCP_PROGRAM;
 212    }
 213
 214    switch (excp) {
 215    case POWERPC_EXCP_NONE:
 216        /* Should never happen */
 217        return;
 218    case POWERPC_EXCP_CRITICAL:    /* Critical input                         */
 219        switch (excp_model) {
 220        case POWERPC_EXCP_40x:
 221            srr0 = SPR_40x_SRR2;
 222            srr1 = SPR_40x_SRR3;
 223            break;
 224        case POWERPC_EXCP_BOOKE:
 225            srr0 = SPR_BOOKE_CSRR0;
 226            srr1 = SPR_BOOKE_CSRR1;
 227            break;
 228        case POWERPC_EXCP_G2:
 229            break;
 230        default:
 231            goto excp_invalid;
 232        }
 233        break;
 234    case POWERPC_EXCP_MCHECK:    /* Machine check exception                  */
 235        if (msr_me == 0) {
 236            /*
 237             * Machine check exception is not enabled.  Enter
 238             * checkstop state.
 239             */
 240            fprintf(stderr, "Machine check while not allowed. "
 241                    "Entering checkstop state\n");
 242            if (qemu_log_separate()) {
 243                qemu_log("Machine check while not allowed. "
 244                        "Entering checkstop state\n");
 245            }
 246            cs->halted = 1;
 247            cpu_interrupt_exittb(cs);
 248        }
 249        if (env->msr_mask & MSR_HVB) {
 250            /*
 251             * ISA specifies HV, but can be delivered to guest with HV
 252             * clear (e.g., see FWNMI in PAPR).
 253             */
 254            new_msr |= (target_ulong)MSR_HVB;
 255        }
 256        ail = 0;
 257
 258        /* machine check exceptions don't have ME set */
 259        new_msr &= ~((target_ulong)1 << MSR_ME);
 260
 261        /* XXX: should also have something loaded in DAR / DSISR */
 262        switch (excp_model) {
 263        case POWERPC_EXCP_40x:
 264            srr0 = SPR_40x_SRR2;
 265            srr1 = SPR_40x_SRR3;
 266            break;
 267        case POWERPC_EXCP_BOOKE:
 268            /* FIXME: choose one or the other based on CPU type */
 269            srr0 = SPR_BOOKE_MCSRR0;
 270            srr1 = SPR_BOOKE_MCSRR1;
 271            asrr0 = SPR_BOOKE_CSRR0;
 272            asrr1 = SPR_BOOKE_CSRR1;
 273            break;
 274        default:
 275            break;
 276        }
 277        break;
 278    case POWERPC_EXCP_DSI:       /* Data storage exception                   */
 279        LOG_EXCP("DSI exception: DSISR=" TARGET_FMT_lx" DAR=" TARGET_FMT_lx
 280                 "\n", env->spr[SPR_DSISR], env->spr[SPR_DAR]);
 281        break;
 282    case POWERPC_EXCP_ISI:       /* Instruction storage exception            */
 283        LOG_EXCP("ISI exception: msr=" TARGET_FMT_lx ", nip=" TARGET_FMT_lx
 284                 "\n", msr, env->nip);
 285        msr |= env->error_code;
 286        break;
 287    case POWERPC_EXCP_EXTERNAL:  /* External input                           */
 288        cs = CPU(cpu);
 289
 290        if (!lpes0) {
 291            new_msr |= (target_ulong)MSR_HVB;
 292            new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
 293            srr0 = SPR_HSRR0;
 294            srr1 = SPR_HSRR1;
 295        }
 296        if (env->mpic_proxy) {
 297            /* IACK the IRQ on delivery */
 298            env->spr[SPR_BOOKE_EPR] = ldl_phys(cs->as, env->mpic_iack);
 299        }
 300        break;
 301    case POWERPC_EXCP_ALIGN:     /* Alignment exception                      */
 302        /* Get rS/rD and rA from faulting opcode */
 303        /*
 304         * Note: the opcode fields will not be set properly for a
 305         * direct store load/store, but nobody cares as nobody
 306         * actually uses direct store segments.
 307         */
 308        env->spr[SPR_DSISR] |= (env->error_code & 0x03FF0000) >> 16;
 309        break;
 310    case POWERPC_EXCP_PROGRAM:   /* Program exception                        */
 311        switch (env->error_code & ~0xF) {
 312        case POWERPC_EXCP_FP:
 313            if ((msr_fe0 == 0 && msr_fe1 == 0) || msr_fp == 0) {
 314                LOG_EXCP("Ignore floating point exception\n");
 315                cs->exception_index = POWERPC_EXCP_NONE;
 316                env->error_code = 0;
 317                return;
 318            }
 319
 320            /*
 321             * FP exceptions always have NIP pointing to the faulting
 322             * instruction, so always use store_next and claim we are
 323             * precise in the MSR.
 324             */
 325            msr |= 0x00100000;
 326            env->spr[SPR_BOOKE_ESR] = ESR_FP;
 327            break;
 328        case POWERPC_EXCP_INVAL:
 329            LOG_EXCP("Invalid instruction at " TARGET_FMT_lx "\n", env->nip);
 330            msr |= 0x00080000;
 331            env->spr[SPR_BOOKE_ESR] = ESR_PIL;
 332            break;
 333        case POWERPC_EXCP_PRIV:
 334            msr |= 0x00040000;
 335            env->spr[SPR_BOOKE_ESR] = ESR_PPR;
 336            break;
 337        case POWERPC_EXCP_TRAP:
 338            msr |= 0x00020000;
 339            env->spr[SPR_BOOKE_ESR] = ESR_PTR;
 340            break;
 341        default:
 342            /* Should never occur */
 343            cpu_abort(cs, "Invalid program exception %d. Aborting\n",
 344                      env->error_code);
 345            break;
 346        }
 347        break;
 348    case POWERPC_EXCP_SYSCALL:   /* System call exception                    */
 349        dump_syscall(env);
 350        lev = env->error_code;
 351
 352        /*
 353         * We need to correct the NIP which in this case is supposed
 354         * to point to the next instruction
 355         */
 356        env->nip += 4;
 357
 358        /* "PAPR mode" built-in hypercall emulation */
 359        if ((lev == 1) && cpu->vhyp) {
 360            PPCVirtualHypervisorClass *vhc =
 361                PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
 362            vhc->hypercall(cpu->vhyp, cpu);
 363            return;
 364        }
 365        if (lev == 1) {
 366            new_msr |= (target_ulong)MSR_HVB;
 367        }
 368        break;
 369    case POWERPC_EXCP_FPU:       /* Floating-point unavailable exception     */
 370    case POWERPC_EXCP_APU:       /* Auxiliary processor unavailable          */
 371    case POWERPC_EXCP_DECR:      /* Decrementer exception                    */
 372        break;
 373    case POWERPC_EXCP_FIT:       /* Fixed-interval timer interrupt           */
 374        /* FIT on 4xx */
 375        LOG_EXCP("FIT exception\n");
 376        break;
 377    case POWERPC_EXCP_WDT:       /* Watchdog timer interrupt                 */
 378        LOG_EXCP("WDT exception\n");
 379        switch (excp_model) {
 380        case POWERPC_EXCP_BOOKE:
 381            srr0 = SPR_BOOKE_CSRR0;
 382            srr1 = SPR_BOOKE_CSRR1;
 383            break;
 384        default:
 385            break;
 386        }
 387        break;
 388    case POWERPC_EXCP_DTLB:      /* Data TLB error                           */
 389    case POWERPC_EXCP_ITLB:      /* Instruction TLB error                    */
 390        break;
 391    case POWERPC_EXCP_DEBUG:     /* Debug interrupt                          */
 392        if (env->flags & POWERPC_FLAG_DE) {
 393            /* FIXME: choose one or the other based on CPU type */
 394            srr0 = SPR_BOOKE_DSRR0;
 395            srr1 = SPR_BOOKE_DSRR1;
 396            asrr0 = SPR_BOOKE_CSRR0;
 397            asrr1 = SPR_BOOKE_CSRR1;
 398            /* DBSR already modified by caller */
 399        } else {
 400            cpu_abort(cs, "Debug exception triggered on unsupported model\n");
 401        }
 402        break;
 403    case POWERPC_EXCP_SPEU:      /* SPE/embedded floating-point unavailable  */
 404        env->spr[SPR_BOOKE_ESR] = ESR_SPV;
 405        break;
 406    case POWERPC_EXCP_EFPDI:     /* Embedded floating-point data interrupt   */
 407        /* XXX: TODO */
 408        cpu_abort(cs, "Embedded floating point data exception "
 409                  "is not implemented yet !\n");
 410        env->spr[SPR_BOOKE_ESR] = ESR_SPV;
 411        break;
 412    case POWERPC_EXCP_EFPRI:     /* Embedded floating-point round interrupt  */
 413        /* XXX: TODO */
 414        cpu_abort(cs, "Embedded floating point round exception "
 415                  "is not implemented yet !\n");
 416        env->spr[SPR_BOOKE_ESR] = ESR_SPV;
 417        break;
 418    case POWERPC_EXCP_EPERFM:    /* Embedded performance monitor interrupt   */
 419        /* XXX: TODO */
 420        cpu_abort(cs,
 421                  "Performance counter exception is not implemented yet !\n");
 422        break;
 423    case POWERPC_EXCP_DOORI:     /* Embedded doorbell interrupt              */
 424        break;
 425    case POWERPC_EXCP_DOORCI:    /* Embedded doorbell critical interrupt     */
 426        srr0 = SPR_BOOKE_CSRR0;
 427        srr1 = SPR_BOOKE_CSRR1;
 428        break;
 429    case POWERPC_EXCP_RESET:     /* System reset exception                   */
 430        /* A power-saving exception sets ME, otherwise it is unchanged */
 431        if (msr_pow) {
 432            /* indicate that we resumed from power save mode */
 433            msr |= 0x10000;
 434            new_msr |= ((target_ulong)1 << MSR_ME);
 435        }
 436        if (env->msr_mask & MSR_HVB) {
 437            /*
 438             * ISA specifies HV, but can be delivered to guest with HV
 439             * clear (e.g., see FWNMI in PAPR, NMI injection in QEMU).
 440             */
 441            new_msr |= (target_ulong)MSR_HVB;
 442        } else {
 443            if (msr_pow) {
 444                cpu_abort(cs, "Trying to deliver power-saving system reset "
 445                          "exception %d with no HV support\n", excp);
 446            }
 447        }
 448        ail = 0;
 449        break;
 450    case POWERPC_EXCP_DSEG:      /* Data segment exception                   */
 451    case POWERPC_EXCP_ISEG:      /* Instruction segment exception            */
 452    case POWERPC_EXCP_TRACE:     /* Trace exception                          */
 453        break;
 454    case POWERPC_EXCP_HDECR:     /* Hypervisor decrementer exception         */
 455    case POWERPC_EXCP_HDSI:      /* Hypervisor data storage exception        */
 456    case POWERPC_EXCP_HISI:      /* Hypervisor instruction storage exception */
 457    case POWERPC_EXCP_HDSEG:     /* Hypervisor data segment exception        */
 458    case POWERPC_EXCP_HISEG:     /* Hypervisor instruction segment exception */
 459    case POWERPC_EXCP_SDOOR_HV:  /* Hypervisor Doorbell interrupt            */
 460    case POWERPC_EXCP_HV_EMU:
 461    case POWERPC_EXCP_HVIRT:     /* Hypervisor virtualization                */
 462        srr0 = SPR_HSRR0;
 463        srr1 = SPR_HSRR1;
 464        new_msr |= (target_ulong)MSR_HVB;
 465        new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
 466        break;
 467    case POWERPC_EXCP_VPU:       /* Vector unavailable exception             */
 468    case POWERPC_EXCP_VSXU:       /* VSX unavailable exception               */
 469    case POWERPC_EXCP_FU:         /* Facility unavailable exception          */
 470#ifdef TARGET_PPC64
 471        env->spr[SPR_FSCR] |= ((target_ulong)env->error_code << 56);
 472#endif
 473        break;
 474    case POWERPC_EXCP_PIT:       /* Programmable interval timer interrupt    */
 475        LOG_EXCP("PIT exception\n");
 476        break;
 477    case POWERPC_EXCP_IO:        /* IO error exception                       */
 478        /* XXX: TODO */
 479        cpu_abort(cs, "601 IO error exception is not implemented yet !\n");
 480        break;
 481    case POWERPC_EXCP_RUNM:      /* Run mode exception                       */
 482        /* XXX: TODO */
 483        cpu_abort(cs, "601 run mode exception is not implemented yet !\n");
 484        break;
 485    case POWERPC_EXCP_EMUL:      /* Emulation trap exception                 */
 486        /* XXX: TODO */
 487        cpu_abort(cs, "602 emulation trap exception "
 488                  "is not implemented yet !\n");
 489        break;
 490    case POWERPC_EXCP_IFTLB:     /* Instruction fetch TLB error              */
 491        switch (excp_model) {
 492        case POWERPC_EXCP_602:
 493        case POWERPC_EXCP_603:
 494        case POWERPC_EXCP_603E:
 495        case POWERPC_EXCP_G2:
 496            goto tlb_miss_tgpr;
 497        case POWERPC_EXCP_7x5:
 498            goto tlb_miss;
 499        case POWERPC_EXCP_74xx:
 500            goto tlb_miss_74xx;
 501        default:
 502            cpu_abort(cs, "Invalid instruction TLB miss exception\n");
 503            break;
 504        }
 505        break;
 506    case POWERPC_EXCP_DLTLB:     /* Data load TLB miss                       */
 507        switch (excp_model) {
 508        case POWERPC_EXCP_602:
 509        case POWERPC_EXCP_603:
 510        case POWERPC_EXCP_603E:
 511        case POWERPC_EXCP_G2:
 512            goto tlb_miss_tgpr;
 513        case POWERPC_EXCP_7x5:
 514            goto tlb_miss;
 515        case POWERPC_EXCP_74xx:
 516            goto tlb_miss_74xx;
 517        default:
 518            cpu_abort(cs, "Invalid data load TLB miss exception\n");
 519            break;
 520        }
 521        break;
 522    case POWERPC_EXCP_DSTLB:     /* Data store TLB miss                      */
 523        switch (excp_model) {
 524        case POWERPC_EXCP_602:
 525        case POWERPC_EXCP_603:
 526        case POWERPC_EXCP_603E:
 527        case POWERPC_EXCP_G2:
 528        tlb_miss_tgpr:
 529            /* Swap temporary saved registers with GPRs */
 530            if (!(new_msr & ((target_ulong)1 << MSR_TGPR))) {
 531                new_msr |= (target_ulong)1 << MSR_TGPR;
 532                hreg_swap_gpr_tgpr(env);
 533            }
 534            goto tlb_miss;
 535        case POWERPC_EXCP_7x5:
 536        tlb_miss:
 537#if defined(DEBUG_SOFTWARE_TLB)
 538            if (qemu_log_enabled()) {
 539                const char *es;
 540                target_ulong *miss, *cmp;
 541                int en;
 542
 543                if (excp == POWERPC_EXCP_IFTLB) {
 544                    es = "I";
 545                    en = 'I';
 546                    miss = &env->spr[SPR_IMISS];
 547                    cmp = &env->spr[SPR_ICMP];
 548                } else {
 549                    if (excp == POWERPC_EXCP_DLTLB) {
 550                        es = "DL";
 551                    } else {
 552                        es = "DS";
 553                    }
 554                    en = 'D';
 555                    miss = &env->spr[SPR_DMISS];
 556                    cmp = &env->spr[SPR_DCMP];
 557                }
 558                qemu_log("6xx %sTLB miss: %cM " TARGET_FMT_lx " %cC "
 559                         TARGET_FMT_lx " H1 " TARGET_FMT_lx " H2 "
 560                         TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp,
 561                         env->spr[SPR_HASH1], env->spr[SPR_HASH2],
 562                         env->error_code);
 563            }
 564#endif
 565            msr |= env->crf[0] << 28;
 566            msr |= env->error_code; /* key, D/I, S/L bits */
 567            /* Set way using a LRU mechanism */
 568            msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17;
 569            break;
 570        case POWERPC_EXCP_74xx:
 571        tlb_miss_74xx:
 572#if defined(DEBUG_SOFTWARE_TLB)
 573            if (qemu_log_enabled()) {
 574                const char *es;
 575                target_ulong *miss, *cmp;
 576                int en;
 577
 578                if (excp == POWERPC_EXCP_IFTLB) {
 579                    es = "I";
 580                    en = 'I';
 581                    miss = &env->spr[SPR_TLBMISS];
 582                    cmp = &env->spr[SPR_PTEHI];
 583                } else {
 584                    if (excp == POWERPC_EXCP_DLTLB) {
 585                        es = "DL";
 586                    } else {
 587                        es = "DS";
 588                    }
 589                    en = 'D';
 590                    miss = &env->spr[SPR_TLBMISS];
 591                    cmp = &env->spr[SPR_PTEHI];
 592                }
 593                qemu_log("74xx %sTLB miss: %cM " TARGET_FMT_lx " %cC "
 594                         TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp,
 595                         env->error_code);
 596            }
 597#endif
 598            msr |= env->error_code; /* key bit */
 599            break;
 600        default:
 601            cpu_abort(cs, "Invalid data store TLB miss exception\n");
 602            break;
 603        }
 604        break;
 605    case POWERPC_EXCP_FPA:       /* Floating-point assist exception          */
 606        /* XXX: TODO */
 607        cpu_abort(cs, "Floating point assist exception "
 608                  "is not implemented yet !\n");
 609        break;
 610    case POWERPC_EXCP_DABR:      /* Data address breakpoint                  */
 611        /* XXX: TODO */
 612        cpu_abort(cs, "DABR exception is not implemented yet !\n");
 613        break;
 614    case POWERPC_EXCP_IABR:      /* Instruction address breakpoint           */
 615        /* XXX: TODO */
 616        cpu_abort(cs, "IABR exception is not implemented yet !\n");
 617        break;
 618    case POWERPC_EXCP_SMI:       /* System management interrupt              */
 619        /* XXX: TODO */
 620        cpu_abort(cs, "SMI exception is not implemented yet !\n");
 621        break;
 622    case POWERPC_EXCP_THERM:     /* Thermal interrupt                        */
 623        /* XXX: TODO */
 624        cpu_abort(cs, "Thermal management exception "
 625                  "is not implemented yet !\n");
 626        break;
 627    case POWERPC_EXCP_PERFM:     /* Embedded performance monitor interrupt   */
 628        /* XXX: TODO */
 629        cpu_abort(cs,
 630                  "Performance counter exception is not implemented yet !\n");
 631        break;
 632    case POWERPC_EXCP_VPUA:      /* Vector assist exception                  */
 633        /* XXX: TODO */
 634        cpu_abort(cs, "VPU assist exception is not implemented yet !\n");
 635        break;
 636    case POWERPC_EXCP_SOFTP:     /* Soft patch exception                     */
 637        /* XXX: TODO */
 638        cpu_abort(cs,
 639                  "970 soft-patch exception is not implemented yet !\n");
 640        break;
 641    case POWERPC_EXCP_MAINT:     /* Maintenance exception                    */
 642        /* XXX: TODO */
 643        cpu_abort(cs,
 644                  "970 maintenance exception is not implemented yet !\n");
 645        break;
 646    case POWERPC_EXCP_MEXTBR:    /* Maskable external breakpoint             */
 647        /* XXX: TODO */
 648        cpu_abort(cs, "Maskable external exception "
 649                  "is not implemented yet !\n");
 650        break;
 651    case POWERPC_EXCP_NMEXTBR:   /* Non maskable external breakpoint         */
 652        /* XXX: TODO */
 653        cpu_abort(cs, "Non maskable external exception "
 654                  "is not implemented yet !\n");
 655        break;
 656    default:
 657    excp_invalid:
 658        cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp);
 659        break;
 660    }
 661
 662    /* Save PC */
 663    env->spr[srr0] = env->nip;
 664
 665    /* Save MSR */
 666    env->spr[srr1] = msr;
 667
 668    /* Sanity check */
 669    if (!(env->msr_mask & MSR_HVB)) {
 670        if (new_msr & MSR_HVB) {
 671            cpu_abort(cs, "Trying to deliver HV exception (MSR) %d with "
 672                      "no HV support\n", excp);
 673        }
 674        if (srr0 == SPR_HSRR0) {
 675            cpu_abort(cs, "Trying to deliver HV exception (HSRR) %d with "
 676                      "no HV support\n", excp);
 677        }
 678    }
 679
 680    /* If any alternate SRR register are defined, duplicate saved values */
 681    if (asrr0 != -1) {
 682        env->spr[asrr0] = env->spr[srr0];
 683    }
 684    if (asrr1 != -1) {
 685        env->spr[asrr1] = env->spr[srr1];
 686    }
 687
 688    /*
 689     * Sort out endianness of interrupt, this differs depending on the
 690     * CPU, the HV mode, etc...
 691     */
 692#ifdef TARGET_PPC64
 693    if (excp_model == POWERPC_EXCP_POWER7) {
 694        if (!(new_msr & MSR_HVB) && (env->spr[SPR_LPCR] & LPCR_ILE)) {
 695            new_msr |= (target_ulong)1 << MSR_LE;
 696        }
 697    } else if (excp_model == POWERPC_EXCP_POWER8) {
 698        if (new_msr & MSR_HVB) {
 699            if (env->spr[SPR_HID0] & HID0_HILE) {
 700                new_msr |= (target_ulong)1 << MSR_LE;
 701            }
 702        } else if (env->spr[SPR_LPCR] & LPCR_ILE) {
 703            new_msr |= (target_ulong)1 << MSR_LE;
 704        }
 705    } else if (excp_model == POWERPC_EXCP_POWER9) {
 706        if (new_msr & MSR_HVB) {
 707            if (env->spr[SPR_HID0] & HID0_POWER9_HILE) {
 708                new_msr |= (target_ulong)1 << MSR_LE;
 709            }
 710        } else if (env->spr[SPR_LPCR] & LPCR_ILE) {
 711            new_msr |= (target_ulong)1 << MSR_LE;
 712        }
 713    } else if (msr_ile) {
 714        new_msr |= (target_ulong)1 << MSR_LE;
 715    }
 716#else
 717    if (msr_ile) {
 718        new_msr |= (target_ulong)1 << MSR_LE;
 719    }
 720#endif
 721
 722    /* Jump to handler */
 723    vector = env->excp_vectors[excp];
 724    if (vector == (target_ulong)-1ULL) {
 725        cpu_abort(cs, "Raised an exception without defined vector %d\n",
 726                  excp);
 727    }
 728    vector |= env->excp_prefix;
 729
 730    /*
 731     * AIL only works if there is no HV transition and we are running
 732     * with translations enabled
 733     */
 734    if (!((msr >> MSR_IR) & 1) || !((msr >> MSR_DR) & 1) ||
 735        ((new_msr & MSR_HVB) && !(msr & MSR_HVB))) {
 736        ail = 0;
 737    }
 738    /* Handle AIL */
 739    if (ail) {
 740        new_msr |= (1 << MSR_IR) | (1 << MSR_DR);
 741        vector |= ppc_excp_vector_offset(cs, ail);
 742    }
 743
 744#if defined(TARGET_PPC64)
 745    if (excp_model == POWERPC_EXCP_BOOKE) {
 746        if (env->spr[SPR_BOOKE_EPCR] & EPCR_ICM) {
 747            /* Cat.64-bit: EPCR.ICM is copied to MSR.CM */
 748            new_msr |= (target_ulong)1 << MSR_CM;
 749        } else {
 750            vector = (uint32_t)vector;
 751        }
 752    } else {
 753        if (!msr_isf && !(env->mmu_model & POWERPC_MMU_64)) {
 754            vector = (uint32_t)vector;
 755        } else {
 756            new_msr |= (target_ulong)1 << MSR_SF;
 757        }
 758    }
 759#endif
 760    /*
 761     * We don't use hreg_store_msr here as already have treated any
 762     * special case that could occur. Just store MSR and update hflags
 763     *
 764     * Note: We *MUST* not use hreg_store_msr() as-is anyway because it
 765     * will prevent setting of the HV bit which some exceptions might need
 766     * to do.
 767     */
 768    env->msr = new_msr & env->msr_mask;
 769    hreg_compute_hflags(env);
 770    env->nip = vector;
 771    /* Reset exception state */
 772    cs->exception_index = POWERPC_EXCP_NONE;
 773    env->error_code = 0;
 774
 775    /* Reset the reservation */
 776    env->reserve_addr = -1;
 777
 778    /*
 779     * Any interrupt is context synchronizing, check if TCG TLB needs
 780     * a delayed flush on ppc64
 781     */
 782    check_tlb_flush(env, false);
 783}
 784
 785void ppc_cpu_do_interrupt(CPUState *cs)
 786{
 787    PowerPCCPU *cpu = POWERPC_CPU(cs);
 788    CPUPPCState *env = &cpu->env;
 789
 790    powerpc_excp(cpu, env->excp_model, cs->exception_index);
 791}
 792
 793static void ppc_hw_interrupt(CPUPPCState *env)
 794{
 795    PowerPCCPU *cpu = env_archcpu(env);
 796    bool async_deliver;
 797
 798    /* External reset */
 799    if (env->pending_interrupts & (1 << PPC_INTERRUPT_RESET)) {
 800        env->pending_interrupts &= ~(1 << PPC_INTERRUPT_RESET);
 801        powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_RESET);
 802        return;
 803    }
 804    /* Machine check exception */
 805    if (env->pending_interrupts & (1 << PPC_INTERRUPT_MCK)) {
 806        env->pending_interrupts &= ~(1 << PPC_INTERRUPT_MCK);
 807        powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_MCHECK);
 808        return;
 809    }
 810#if 0 /* TODO */
 811    /* External debug exception */
 812    if (env->pending_interrupts & (1 << PPC_INTERRUPT_DEBUG)) {
 813        env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DEBUG);
 814        powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DEBUG);
 815        return;
 816    }
 817#endif
 818
 819    /*
 820     * For interrupts that gate on MSR:EE, we need to do something a
 821     * bit more subtle, as we need to let them through even when EE is
 822     * clear when coming out of some power management states (in order
 823     * for them to become a 0x100).
 824     */
 825    async_deliver = (msr_ee != 0) || env->resume_as_sreset;
 826
 827    /* Hypervisor decrementer exception */
 828    if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDECR)) {
 829        /* LPCR will be clear when not supported so this will work */
 830        bool hdice = !!(env->spr[SPR_LPCR] & LPCR_HDICE);
 831        if ((async_deliver || msr_hv == 0) && hdice) {
 832            /* HDEC clears on delivery */
 833            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR);
 834            powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_HDECR);
 835            return;
 836        }
 837    }
 838
 839    /* Hypervisor virtualization interrupt */
 840    if (env->pending_interrupts & (1 << PPC_INTERRUPT_HVIRT)) {
 841        /* LPCR will be clear when not supported so this will work */
 842        bool hvice = !!(env->spr[SPR_LPCR] & LPCR_HVICE);
 843        if ((async_deliver || msr_hv == 0) && hvice) {
 844            powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_HVIRT);
 845            return;
 846        }
 847    }
 848
 849    /* External interrupt can ignore MSR:EE under some circumstances */
 850    if (env->pending_interrupts & (1 << PPC_INTERRUPT_EXT)) {
 851        bool lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0);
 852        bool heic = !!(env->spr[SPR_LPCR] & LPCR_HEIC);
 853        /* HEIC blocks delivery to the hypervisor */
 854        if ((async_deliver && !(heic && msr_hv && !msr_pr)) ||
 855            (env->has_hv_mode && msr_hv == 0 && !lpes0)) {
 856            powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_EXTERNAL);
 857            return;
 858        }
 859    }
 860    if (msr_ce != 0) {
 861        /* External critical interrupt */
 862        if (env->pending_interrupts & (1 << PPC_INTERRUPT_CEXT)) {
 863            powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_CRITICAL);
 864            return;
 865        }
 866    }
 867    if (async_deliver != 0) {
 868        /* Watchdog timer on embedded PowerPC */
 869        if (env->pending_interrupts & (1 << PPC_INTERRUPT_WDT)) {
 870            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_WDT);
 871            powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_WDT);
 872            return;
 873        }
 874        if (env->pending_interrupts & (1 << PPC_INTERRUPT_CDOORBELL)) {
 875            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CDOORBELL);
 876            powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DOORCI);
 877            return;
 878        }
 879        /* Fixed interval timer on embedded PowerPC */
 880        if (env->pending_interrupts & (1 << PPC_INTERRUPT_FIT)) {
 881            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_FIT);
 882            powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_FIT);
 883            return;
 884        }
 885        /* Programmable interval timer on embedded PowerPC */
 886        if (env->pending_interrupts & (1 << PPC_INTERRUPT_PIT)) {
 887            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PIT);
 888            powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_PIT);
 889            return;
 890        }
 891        /* Decrementer exception */
 892        if (env->pending_interrupts & (1 << PPC_INTERRUPT_DECR)) {
 893            if (ppc_decr_clear_on_delivery(env)) {
 894                env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DECR);
 895            }
 896            powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DECR);
 897            return;
 898        }
 899        if (env->pending_interrupts & (1 << PPC_INTERRUPT_DOORBELL)) {
 900            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DOORBELL);
 901            powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DOORI);
 902            return;
 903        }
 904        if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDOORBELL)) {
 905            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDOORBELL);
 906            powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_SDOOR_HV);
 907            return;
 908        }
 909        if (env->pending_interrupts & (1 << PPC_INTERRUPT_PERFM)) {
 910            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PERFM);
 911            powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_PERFM);
 912            return;
 913        }
 914        /* Thermal interrupt */
 915        if (env->pending_interrupts & (1 << PPC_INTERRUPT_THERM)) {
 916            env->pending_interrupts &= ~(1 << PPC_INTERRUPT_THERM);
 917            powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_THERM);
 918            return;
 919        }
 920    }
 921
 922    if (env->resume_as_sreset) {
 923        /*
 924         * This is a bug ! It means that has_work took us out of halt without
 925         * anything to deliver while in a PM state that requires getting
 926         * out via a 0x100
 927         *
 928         * This means we will incorrectly execute past the power management
 929         * instruction instead of triggering a reset.
 930         *
 931         * It generally means a discrepancy between the wakup conditions in the
 932         * processor has_work implementation and the logic in this function.
 933         */
 934        cpu_abort(env_cpu(env),
 935                  "Wakeup from PM state but interrupt Undelivered");
 936    }
 937}
 938
 939void ppc_cpu_do_system_reset(CPUState *cs)
 940{
 941    PowerPCCPU *cpu = POWERPC_CPU(cs);
 942    CPUPPCState *env = &cpu->env;
 943
 944    powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_RESET);
 945}
 946#endif /* !CONFIG_USER_ONLY */
 947
 948bool ppc_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
 949{
 950    PowerPCCPU *cpu = POWERPC_CPU(cs);
 951    CPUPPCState *env = &cpu->env;
 952
 953    if (interrupt_request & CPU_INTERRUPT_HARD) {
 954        ppc_hw_interrupt(env);
 955        if (env->pending_interrupts == 0) {
 956            cs->interrupt_request &= ~CPU_INTERRUPT_HARD;
 957        }
 958        return true;
 959    }
 960    return false;
 961}
 962
 963#if defined(DEBUG_OP)
 964static void cpu_dump_rfi(target_ulong RA, target_ulong msr)
 965{
 966    qemu_log("Return from exception at " TARGET_FMT_lx " with flags "
 967             TARGET_FMT_lx "\n", RA, msr);
 968}
 969#endif
 970
 971/*****************************************************************************/
 972/* Exceptions processing helpers */
 973
 974void raise_exception_err_ra(CPUPPCState *env, uint32_t exception,
 975                            uint32_t error_code, uintptr_t raddr)
 976{
 977    CPUState *cs = env_cpu(env);
 978
 979    cs->exception_index = exception;
 980    env->error_code = error_code;
 981    cpu_loop_exit_restore(cs, raddr);
 982}
 983
 984void raise_exception_err(CPUPPCState *env, uint32_t exception,
 985                         uint32_t error_code)
 986{
 987    raise_exception_err_ra(env, exception, error_code, 0);
 988}
 989
 990void raise_exception(CPUPPCState *env, uint32_t exception)
 991{
 992    raise_exception_err_ra(env, exception, 0, 0);
 993}
 994
 995void raise_exception_ra(CPUPPCState *env, uint32_t exception,
 996                        uintptr_t raddr)
 997{
 998    raise_exception_err_ra(env, exception, 0, raddr);
 999}
1000
1001void helper_raise_exception_err(CPUPPCState *env, uint32_t exception,
1002                                uint32_t error_code)
1003{
1004    raise_exception_err_ra(env, exception, error_code, 0);
1005}
1006
1007void helper_raise_exception(CPUPPCState *env, uint32_t exception)
1008{
1009    raise_exception_err_ra(env, exception, 0, 0);
1010}
1011
1012#if !defined(CONFIG_USER_ONLY)
1013void helper_store_msr(CPUPPCState *env, target_ulong val)
1014{
1015    uint32_t excp = hreg_store_msr(env, val, 0);
1016
1017    if (excp != 0) {
1018        CPUState *cs = env_cpu(env);
1019        cpu_interrupt_exittb(cs);
1020        raise_exception(env, excp);
1021    }
1022}
1023
1024#if defined(TARGET_PPC64)
1025void helper_pminsn(CPUPPCState *env, powerpc_pm_insn_t insn)
1026{
1027    CPUState *cs;
1028
1029    cs = env_cpu(env);
1030    cs->halted = 1;
1031
1032    /*
1033     * The architecture specifies that HDEC interrupts are discarded
1034     * in PM states
1035     */
1036    env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR);
1037
1038    /* Condition for waking up at 0x100 */
1039    env->resume_as_sreset = (insn != PPC_PM_STOP) ||
1040        (env->spr[SPR_PSSCR] & PSSCR_EC);
1041}
1042#endif /* defined(TARGET_PPC64) */
1043
1044static inline void do_rfi(CPUPPCState *env, target_ulong nip, target_ulong msr)
1045{
1046    CPUState *cs = env_cpu(env);
1047
1048    /* MSR:POW cannot be set by any form of rfi */
1049    msr &= ~(1ULL << MSR_POW);
1050
1051#if defined(TARGET_PPC64)
1052    /* Switching to 32-bit ? Crop the nip */
1053    if (!msr_is_64bit(env, msr)) {
1054        nip = (uint32_t)nip;
1055    }
1056#else
1057    nip = (uint32_t)nip;
1058#endif
1059    /* XXX: beware: this is false if VLE is supported */
1060    env->nip = nip & ~((target_ulong)0x00000003);
1061    hreg_store_msr(env, msr, 1);
1062#if defined(DEBUG_OP)
1063    cpu_dump_rfi(env->nip, env->msr);
1064#endif
1065    /*
1066     * No need to raise an exception here, as rfi is always the last
1067     * insn of a TB
1068     */
1069    cpu_interrupt_exittb(cs);
1070    /* Reset the reservation */
1071    env->reserve_addr = -1;
1072
1073    /* Context synchronizing: check if TCG TLB needs flush */
1074    check_tlb_flush(env, false);
1075}
1076
1077void helper_rfi(CPUPPCState *env)
1078{
1079    do_rfi(env, env->spr[SPR_SRR0], env->spr[SPR_SRR1] & 0xfffffffful);
1080}
1081
1082#define MSR_BOOK3S_MASK
1083#if defined(TARGET_PPC64)
1084void helper_rfid(CPUPPCState *env)
1085{
1086    /*
1087     * The architeture defines a number of rules for which bits can
1088     * change but in practice, we handle this in hreg_store_msr()
1089     * which will be called by do_rfi(), so there is no need to filter
1090     * here
1091     */
1092    do_rfi(env, env->spr[SPR_SRR0], env->spr[SPR_SRR1]);
1093}
1094
1095void helper_hrfid(CPUPPCState *env)
1096{
1097    do_rfi(env, env->spr[SPR_HSRR0], env->spr[SPR_HSRR1]);
1098}
1099#endif
1100
1101/*****************************************************************************/
1102/* Embedded PowerPC specific helpers */
1103void helper_40x_rfci(CPUPPCState *env)
1104{
1105    do_rfi(env, env->spr[SPR_40x_SRR2], env->spr[SPR_40x_SRR3]);
1106}
1107
1108void helper_rfci(CPUPPCState *env)
1109{
1110    do_rfi(env, env->spr[SPR_BOOKE_CSRR0], env->spr[SPR_BOOKE_CSRR1]);
1111}
1112
1113void helper_rfdi(CPUPPCState *env)
1114{
1115    /* FIXME: choose CSRR1 or DSRR1 based on cpu type */
1116    do_rfi(env, env->spr[SPR_BOOKE_DSRR0], env->spr[SPR_BOOKE_DSRR1]);
1117}
1118
1119void helper_rfmci(CPUPPCState *env)
1120{
1121    /* FIXME: choose CSRR1 or MCSRR1 based on cpu type */
1122    do_rfi(env, env->spr[SPR_BOOKE_MCSRR0], env->spr[SPR_BOOKE_MCSRR1]);
1123}
1124#endif
1125
1126void helper_tw(CPUPPCState *env, target_ulong arg1, target_ulong arg2,
1127               uint32_t flags)
1128{
1129    if (!likely(!(((int32_t)arg1 < (int32_t)arg2 && (flags & 0x10)) ||
1130                  ((int32_t)arg1 > (int32_t)arg2 && (flags & 0x08)) ||
1131                  ((int32_t)arg1 == (int32_t)arg2 && (flags & 0x04)) ||
1132                  ((uint32_t)arg1 < (uint32_t)arg2 && (flags & 0x02)) ||
1133                  ((uint32_t)arg1 > (uint32_t)arg2 && (flags & 0x01))))) {
1134        raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
1135                               POWERPC_EXCP_TRAP, GETPC());
1136    }
1137}
1138
1139#if defined(TARGET_PPC64)
1140void helper_td(CPUPPCState *env, target_ulong arg1, target_ulong arg2,
1141               uint32_t flags)
1142{
1143    if (!likely(!(((int64_t)arg1 < (int64_t)arg2 && (flags & 0x10)) ||
1144                  ((int64_t)arg1 > (int64_t)arg2 && (flags & 0x08)) ||
1145                  ((int64_t)arg1 == (int64_t)arg2 && (flags & 0x04)) ||
1146                  ((uint64_t)arg1 < (uint64_t)arg2 && (flags & 0x02)) ||
1147                  ((uint64_t)arg1 > (uint64_t)arg2 && (flags & 0x01))))) {
1148        raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
1149                               POWERPC_EXCP_TRAP, GETPC());
1150    }
1151}
1152#endif
1153
1154#if !defined(CONFIG_USER_ONLY)
1155/*****************************************************************************/
1156/* PowerPC 601 specific instructions (POWER bridge) */
1157
1158void helper_rfsvc(CPUPPCState *env)
1159{
1160    do_rfi(env, env->lr, env->ctr & 0x0000FFFF);
1161}
1162
1163/* Embedded.Processor Control */
1164static int dbell2irq(target_ulong rb)
1165{
1166    int msg = rb & DBELL_TYPE_MASK;
1167    int irq = -1;
1168
1169    switch (msg) {
1170    case DBELL_TYPE_DBELL:
1171        irq = PPC_INTERRUPT_DOORBELL;
1172        break;
1173    case DBELL_TYPE_DBELL_CRIT:
1174        irq = PPC_INTERRUPT_CDOORBELL;
1175        break;
1176    case DBELL_TYPE_G_DBELL:
1177    case DBELL_TYPE_G_DBELL_CRIT:
1178    case DBELL_TYPE_G_DBELL_MC:
1179        /* XXX implement */
1180    default:
1181        break;
1182    }
1183
1184    return irq;
1185}
1186
1187void helper_msgclr(CPUPPCState *env, target_ulong rb)
1188{
1189    int irq = dbell2irq(rb);
1190
1191    if (irq < 0) {
1192        return;
1193    }
1194
1195    env->pending_interrupts &= ~(1 << irq);
1196}
1197
1198void helper_msgsnd(target_ulong rb)
1199{
1200    int irq = dbell2irq(rb);
1201    int pir = rb & DBELL_PIRTAG_MASK;
1202    CPUState *cs;
1203
1204    if (irq < 0) {
1205        return;
1206    }
1207
1208    qemu_mutex_lock_iothread();
1209    CPU_FOREACH(cs) {
1210        PowerPCCPU *cpu = POWERPC_CPU(cs);
1211        CPUPPCState *cenv = &cpu->env;
1212
1213        if ((rb & DBELL_BRDCAST) || (cenv->spr[SPR_BOOKE_PIR] == pir)) {
1214            cenv->pending_interrupts |= 1 << irq;
1215            cpu_interrupt(cs, CPU_INTERRUPT_HARD);
1216        }
1217    }
1218    qemu_mutex_unlock_iothread();
1219}
1220
1221/* Server Processor Control */
1222static int book3s_dbell2irq(target_ulong rb)
1223{
1224    int msg = rb & DBELL_TYPE_MASK;
1225
1226    /*
1227     * A Directed Hypervisor Doorbell message is sent only if the
1228     * message type is 5. All other types are reserved and the
1229     * instruction is a no-op
1230     */
1231    return msg == DBELL_TYPE_DBELL_SERVER ? PPC_INTERRUPT_HDOORBELL : -1;
1232}
1233
1234void helper_book3s_msgclr(CPUPPCState *env, target_ulong rb)
1235{
1236    int irq = book3s_dbell2irq(rb);
1237
1238    if (irq < 0) {
1239        return;
1240    }
1241
1242    env->pending_interrupts &= ~(1 << irq);
1243}
1244
1245void helper_book3s_msgsnd(target_ulong rb)
1246{
1247    int irq = book3s_dbell2irq(rb);
1248    int pir = rb & DBELL_PROCIDTAG_MASK;
1249    CPUState *cs;
1250
1251    if (irq < 0) {
1252        return;
1253    }
1254
1255    qemu_mutex_lock_iothread();
1256    CPU_FOREACH(cs) {
1257        PowerPCCPU *cpu = POWERPC_CPU(cs);
1258        CPUPPCState *cenv = &cpu->env;
1259
1260        /* TODO: broadcast message to all threads of the same  processor */
1261        if (cenv->spr_cb[SPR_PIR].default_value == pir) {
1262            cenv->pending_interrupts |= 1 << irq;
1263            cpu_interrupt(cs, CPU_INTERRUPT_HARD);
1264        }
1265    }
1266    qemu_mutex_unlock_iothread();
1267}
1268#endif
1269
1270void ppc_cpu_do_unaligned_access(CPUState *cs, vaddr vaddr,
1271                                 MMUAccessType access_type,
1272                                 int mmu_idx, uintptr_t retaddr)
1273{
1274    CPUPPCState *env = cs->env_ptr;
1275    uint32_t insn;
1276
1277    /* Restore state and reload the insn we executed, for filling in DSISR.  */
1278    cpu_restore_state(cs, retaddr, true);
1279    insn = cpu_ldl_code(env, env->nip);
1280
1281    cs->exception_index = POWERPC_EXCP_ALIGN;
1282    env->error_code = insn & 0x03FF0000;
1283    cpu_loop_exit(cs);
1284}
1285