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