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