1ad71ed68SBlue Swirl /* 2ad71ed68SBlue Swirl * PowerPC exception emulation helpers for QEMU. 3ad71ed68SBlue Swirl * 4ad71ed68SBlue Swirl * Copyright (c) 2003-2007 Jocelyn Mayer 5ad71ed68SBlue Swirl * 6ad71ed68SBlue Swirl * This library is free software; you can redistribute it and/or 7ad71ed68SBlue Swirl * modify it under the terms of the GNU Lesser General Public 8ad71ed68SBlue Swirl * License as published by the Free Software Foundation; either 9ad71ed68SBlue Swirl * version 2 of the License, or (at your option) any later version. 10ad71ed68SBlue Swirl * 11ad71ed68SBlue Swirl * This library is distributed in the hope that it will be useful, 12ad71ed68SBlue Swirl * but WITHOUT ANY WARRANTY; without even the implied warranty of 13ad71ed68SBlue Swirl * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 14ad71ed68SBlue Swirl * Lesser General Public License for more details. 15ad71ed68SBlue Swirl * 16ad71ed68SBlue Swirl * You should have received a copy of the GNU Lesser General Public 17ad71ed68SBlue Swirl * License along with this library; if not, see <http://www.gnu.org/licenses/>. 18ad71ed68SBlue Swirl */ 190d75590dSPeter Maydell #include "qemu/osdep.h" 20f1c29ebcSThomas Huth #include "qemu/main-loop.h" 21ad71ed68SBlue Swirl #include "cpu.h" 222ef6175aSRichard Henderson #include "exec/helper-proto.h" 2363c91552SPaolo Bonzini #include "exec/exec-all.h" 24f08b6170SPaolo Bonzini #include "exec/cpu_ldst.h" 250f3110faSRichard Henderson #include "internal.h" 26ad71ed68SBlue Swirl #include "helper_regs.h" 27ad71ed68SBlue Swirl 2847733729SDavid Gibson /* #define DEBUG_OP */ 2947733729SDavid Gibson /* #define DEBUG_SOFTWARE_TLB */ 3047733729SDavid Gibson /* #define DEBUG_EXCEPTIONS */ 31ad71ed68SBlue Swirl 32c79c73f6SBlue Swirl #ifdef DEBUG_EXCEPTIONS 33c79c73f6SBlue Swirl # define LOG_EXCP(...) qemu_log(__VA_ARGS__) 34c79c73f6SBlue Swirl #else 35c79c73f6SBlue Swirl # define LOG_EXCP(...) do { } while (0) 36c79c73f6SBlue Swirl #endif 37c79c73f6SBlue Swirl 38c79c73f6SBlue Swirl /*****************************************************************************/ 39c79c73f6SBlue Swirl /* Exception processing */ 40c79c73f6SBlue Swirl #if defined(CONFIG_USER_ONLY) 4197a8ea5aSAndreas Färber void ppc_cpu_do_interrupt(CPUState *cs) 42c79c73f6SBlue Swirl { 4397a8ea5aSAndreas Färber PowerPCCPU *cpu = POWERPC_CPU(cs); 4497a8ea5aSAndreas Färber CPUPPCState *env = &cpu->env; 4597a8ea5aSAndreas Färber 4627103424SAndreas Färber cs->exception_index = POWERPC_EXCP_NONE; 47c79c73f6SBlue Swirl env->error_code = 0; 48c79c73f6SBlue Swirl } 49c79c73f6SBlue Swirl 50458dd766SRichard Henderson static void ppc_hw_interrupt(CPUPPCState *env) 51c79c73f6SBlue Swirl { 52db70b311SRichard Henderson CPUState *cs = env_cpu(env); 5327103424SAndreas Färber 5427103424SAndreas Färber cs->exception_index = POWERPC_EXCP_NONE; 55c79c73f6SBlue Swirl env->error_code = 0; 56c79c73f6SBlue Swirl } 57c79c73f6SBlue Swirl #else /* defined(CONFIG_USER_ONLY) */ 58c79c73f6SBlue Swirl static inline void dump_syscall(CPUPPCState *env) 59c79c73f6SBlue Swirl { 60c79c73f6SBlue Swirl qemu_log_mask(CPU_LOG_INT, "syscall r0=%016" PRIx64 " r3=%016" PRIx64 61c79c73f6SBlue Swirl " r4=%016" PRIx64 " r5=%016" PRIx64 " r6=%016" PRIx64 62c79c73f6SBlue Swirl " nip=" TARGET_FMT_lx "\n", 63c79c73f6SBlue Swirl ppc_dump_gpr(env, 0), ppc_dump_gpr(env, 3), 64c79c73f6SBlue Swirl ppc_dump_gpr(env, 4), ppc_dump_gpr(env, 5), 65c79c73f6SBlue Swirl ppc_dump_gpr(env, 6), env->nip); 66c79c73f6SBlue Swirl } 67c79c73f6SBlue Swirl 68dead760bSBenjamin Herrenschmidt static int powerpc_reset_wakeup(CPUState *cs, CPUPPCState *env, int excp, 69dead760bSBenjamin Herrenschmidt target_ulong *msr) 70dead760bSBenjamin Herrenschmidt { 71dead760bSBenjamin Herrenschmidt /* We no longer are in a PM state */ 721e7fd61dSBenjamin Herrenschmidt env->resume_as_sreset = false; 73dead760bSBenjamin Herrenschmidt 74dead760bSBenjamin Herrenschmidt /* Pretend to be returning from doze always as we don't lose state */ 75dead760bSBenjamin Herrenschmidt *msr |= (0x1ull << (63 - 47)); 76dead760bSBenjamin Herrenschmidt 77dead760bSBenjamin Herrenschmidt /* Machine checks are sent normally */ 78dead760bSBenjamin Herrenschmidt if (excp == POWERPC_EXCP_MCHECK) { 79dead760bSBenjamin Herrenschmidt return excp; 80dead760bSBenjamin Herrenschmidt } 81dead760bSBenjamin Herrenschmidt switch (excp) { 82dead760bSBenjamin Herrenschmidt case POWERPC_EXCP_RESET: 83dead760bSBenjamin Herrenschmidt *msr |= 0x4ull << (63 - 45); 84dead760bSBenjamin Herrenschmidt break; 85dead760bSBenjamin Herrenschmidt case POWERPC_EXCP_EXTERNAL: 86dead760bSBenjamin Herrenschmidt *msr |= 0x8ull << (63 - 45); 87dead760bSBenjamin Herrenschmidt break; 88dead760bSBenjamin Herrenschmidt case POWERPC_EXCP_DECR: 89dead760bSBenjamin Herrenschmidt *msr |= 0x6ull << (63 - 45); 90dead760bSBenjamin Herrenschmidt break; 91dead760bSBenjamin Herrenschmidt case POWERPC_EXCP_SDOOR: 92dead760bSBenjamin Herrenschmidt *msr |= 0x5ull << (63 - 45); 93dead760bSBenjamin Herrenschmidt break; 94dead760bSBenjamin Herrenschmidt case POWERPC_EXCP_SDOOR_HV: 95dead760bSBenjamin Herrenschmidt *msr |= 0x3ull << (63 - 45); 96dead760bSBenjamin Herrenschmidt break; 97dead760bSBenjamin Herrenschmidt case POWERPC_EXCP_HV_MAINT: 98dead760bSBenjamin Herrenschmidt *msr |= 0xaull << (63 - 45); 99dead760bSBenjamin Herrenschmidt break; 100d8ce5fd6SBenjamin Herrenschmidt case POWERPC_EXCP_HVIRT: 101d8ce5fd6SBenjamin Herrenschmidt *msr |= 0x9ull << (63 - 45); 102d8ce5fd6SBenjamin Herrenschmidt break; 103dead760bSBenjamin Herrenschmidt default: 104dead760bSBenjamin Herrenschmidt cpu_abort(cs, "Unsupported exception %d in Power Save mode\n", 105dead760bSBenjamin Herrenschmidt excp); 106dead760bSBenjamin Herrenschmidt } 107dead760bSBenjamin Herrenschmidt return POWERPC_EXCP_RESET; 108dead760bSBenjamin Herrenschmidt } 109dead760bSBenjamin Herrenschmidt 1102586a4d7SFabiano Rosas static uint64_t ppc_excp_vector_offset(CPUState *cs, int ail) 1112586a4d7SFabiano Rosas { 1122586a4d7SFabiano Rosas uint64_t offset = 0; 1132586a4d7SFabiano Rosas 1142586a4d7SFabiano Rosas switch (ail) { 115bc5fdfc0SFabiano Rosas case AIL_NONE: 116bc5fdfc0SFabiano Rosas break; 1172586a4d7SFabiano Rosas case AIL_0001_8000: 1182586a4d7SFabiano Rosas offset = 0x18000; 1192586a4d7SFabiano Rosas break; 1202586a4d7SFabiano Rosas case AIL_C000_0000_0000_4000: 1212586a4d7SFabiano Rosas offset = 0xc000000000004000ull; 1222586a4d7SFabiano Rosas break; 1232586a4d7SFabiano Rosas default: 1242586a4d7SFabiano Rosas cpu_abort(cs, "Invalid AIL combination %d\n", ail); 1252586a4d7SFabiano Rosas break; 1262586a4d7SFabiano Rosas } 1272586a4d7SFabiano Rosas 1282586a4d7SFabiano Rosas return offset; 1292586a4d7SFabiano Rosas } 130dead760bSBenjamin Herrenschmidt 131*ad77c6caSNicholas Piggin static inline void powerpc_set_excp_state(PowerPCCPU *cpu, 132*ad77c6caSNicholas Piggin target_ulong vector, target_ulong msr) 133*ad77c6caSNicholas Piggin { 134*ad77c6caSNicholas Piggin CPUState *cs = CPU(cpu); 135*ad77c6caSNicholas Piggin CPUPPCState *env = &cpu->env; 136*ad77c6caSNicholas Piggin 137*ad77c6caSNicholas Piggin /* 138*ad77c6caSNicholas Piggin * We don't use hreg_store_msr here as already have treated any 139*ad77c6caSNicholas Piggin * special case that could occur. Just store MSR and update hflags 140*ad77c6caSNicholas Piggin * 141*ad77c6caSNicholas Piggin * Note: We *MUST* not use hreg_store_msr() as-is anyway because it 142*ad77c6caSNicholas Piggin * will prevent setting of the HV bit which some exceptions might need 143*ad77c6caSNicholas Piggin * to do. 144*ad77c6caSNicholas Piggin */ 145*ad77c6caSNicholas Piggin env->msr = msr & env->msr_mask; 146*ad77c6caSNicholas Piggin hreg_compute_hflags(env); 147*ad77c6caSNicholas Piggin env->nip = vector; 148*ad77c6caSNicholas Piggin /* Reset exception state */ 149*ad77c6caSNicholas Piggin cs->exception_index = POWERPC_EXCP_NONE; 150*ad77c6caSNicholas Piggin env->error_code = 0; 151*ad77c6caSNicholas Piggin 152*ad77c6caSNicholas Piggin /* Reset the reservation */ 153*ad77c6caSNicholas Piggin env->reserve_addr = -1; 154*ad77c6caSNicholas Piggin 155*ad77c6caSNicholas Piggin /* 156*ad77c6caSNicholas Piggin * Any interrupt is context synchronizing, check if TCG TLB needs 157*ad77c6caSNicholas Piggin * a delayed flush on ppc64 158*ad77c6caSNicholas Piggin */ 159*ad77c6caSNicholas Piggin check_tlb_flush(env, false); 160*ad77c6caSNicholas Piggin } 161*ad77c6caSNicholas Piggin 16247733729SDavid Gibson /* 16347733729SDavid Gibson * Note that this function should be greatly optimized when called 16447733729SDavid Gibson * with a constant excp, from ppc_hw_interrupt 165c79c73f6SBlue Swirl */ 1665c26a5b3SAndreas Färber static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp) 167c79c73f6SBlue Swirl { 16827103424SAndreas Färber CPUState *cs = CPU(cpu); 1695c26a5b3SAndreas Färber CPUPPCState *env = &cpu->env; 170c79c73f6SBlue Swirl target_ulong msr, new_msr, vector; 1716d49d6d4SBenjamin Herrenschmidt int srr0, srr1, asrr0, asrr1, lev, ail; 1726d49d6d4SBenjamin Herrenschmidt bool lpes0; 173c79c73f6SBlue Swirl 174c79c73f6SBlue Swirl qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx 175c79c73f6SBlue Swirl " => %08x (%02x)\n", env->nip, excp, env->error_code); 176c79c73f6SBlue Swirl 177c79c73f6SBlue Swirl /* new srr1 value excluding must-be-zero bits */ 178a1bb7384SScott Wood if (excp_model == POWERPC_EXCP_BOOKE) { 179a1bb7384SScott Wood msr = env->msr; 180a1bb7384SScott Wood } else { 181c79c73f6SBlue Swirl msr = env->msr & ~0x783f0000ULL; 182a1bb7384SScott Wood } 183c79c73f6SBlue Swirl 18447733729SDavid Gibson /* 18547733729SDavid Gibson * new interrupt handler msr preserves existing HV and ME unless 1866d49d6d4SBenjamin Herrenschmidt * explicitly overriden 1876d49d6d4SBenjamin Herrenschmidt */ 1886d49d6d4SBenjamin Herrenschmidt new_msr = env->msr & (((target_ulong)1 << MSR_ME) | MSR_HVB); 189c79c73f6SBlue Swirl 190c79c73f6SBlue Swirl /* target registers */ 191c79c73f6SBlue Swirl srr0 = SPR_SRR0; 192c79c73f6SBlue Swirl srr1 = SPR_SRR1; 193c79c73f6SBlue Swirl asrr0 = -1; 194c79c73f6SBlue Swirl asrr1 = -1; 195c79c73f6SBlue Swirl 19621c0d66aSBenjamin Herrenschmidt /* 19721c0d66aSBenjamin Herrenschmidt * check for special resume at 0x100 from doze/nap/sleep/winkle on 19821c0d66aSBenjamin Herrenschmidt * P7/P8/P9 19921c0d66aSBenjamin Herrenschmidt */ 2001e7fd61dSBenjamin Herrenschmidt if (env->resume_as_sreset) { 201dead760bSBenjamin Herrenschmidt excp = powerpc_reset_wakeup(cs, env, excp, &msr); 2027778a575SBenjamin Herrenschmidt } 2037778a575SBenjamin Herrenschmidt 20447733729SDavid Gibson /* 20547733729SDavid Gibson * Exception targetting modifiers 2065c94b2a5SCédric Le Goater * 207a790e82bSBenjamin Herrenschmidt * LPES0 is supported on POWER7/8/9 2086d49d6d4SBenjamin Herrenschmidt * LPES1 is not supported (old iSeries mode) 2096d49d6d4SBenjamin Herrenschmidt * 2106d49d6d4SBenjamin Herrenschmidt * On anything else, we behave as if LPES0 is 1 2116d49d6d4SBenjamin Herrenschmidt * (externals don't alter MSR:HV) 2126d49d6d4SBenjamin Herrenschmidt * 2135c94b2a5SCédric Le Goater * AIL is initialized here but can be cleared by 2145c94b2a5SCédric Le Goater * selected exceptions 2155c94b2a5SCédric Le Goater */ 2165c94b2a5SCédric Le Goater #if defined(TARGET_PPC64) 2175c94b2a5SCédric Le Goater if (excp_model == POWERPC_EXCP_POWER7 || 218a790e82bSBenjamin Herrenschmidt excp_model == POWERPC_EXCP_POWER8 || 219a790e82bSBenjamin Herrenschmidt excp_model == POWERPC_EXCP_POWER9) { 2206d49d6d4SBenjamin Herrenschmidt lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0); 221a790e82bSBenjamin Herrenschmidt if (excp_model != POWERPC_EXCP_POWER7) { 2225c94b2a5SCédric Le Goater ail = (env->spr[SPR_LPCR] & LPCR_AIL) >> LPCR_AIL_SHIFT; 2235c94b2a5SCédric Le Goater } else { 2245c94b2a5SCédric Le Goater ail = 0; 2255c94b2a5SCédric Le Goater } 2265c94b2a5SCédric Le Goater } else 2275c94b2a5SCédric Le Goater #endif /* defined(TARGET_PPC64) */ 2285c94b2a5SCédric Le Goater { 2296d49d6d4SBenjamin Herrenschmidt lpes0 = true; 2305c94b2a5SCédric Le Goater ail = 0; 2315c94b2a5SCédric Le Goater } 2325c94b2a5SCédric Le Goater 23347733729SDavid Gibson /* 23447733729SDavid Gibson * Hypervisor emulation assistance interrupt only exists on server 2359b2faddaSBenjamin Herrenschmidt * arch 2.05 server or later. We also don't want to generate it if 2369b2faddaSBenjamin Herrenschmidt * we don't have HVB in msr_mask (PAPR mode). 2379b2faddaSBenjamin Herrenschmidt */ 2389b2faddaSBenjamin Herrenschmidt if (excp == POWERPC_EXCP_HV_EMU 2399b2faddaSBenjamin Herrenschmidt #if defined(TARGET_PPC64) 2409b2faddaSBenjamin Herrenschmidt && !((env->mmu_model & POWERPC_MMU_64) && (env->msr_mask & MSR_HVB)) 2419b2faddaSBenjamin Herrenschmidt #endif /* defined(TARGET_PPC64) */ 2429b2faddaSBenjamin Herrenschmidt 2439b2faddaSBenjamin Herrenschmidt ) { 2449b2faddaSBenjamin Herrenschmidt excp = POWERPC_EXCP_PROGRAM; 2459b2faddaSBenjamin Herrenschmidt } 2469b2faddaSBenjamin Herrenschmidt 247c79c73f6SBlue Swirl switch (excp) { 248c79c73f6SBlue Swirl case POWERPC_EXCP_NONE: 249c79c73f6SBlue Swirl /* Should never happen */ 250c79c73f6SBlue Swirl return; 251c79c73f6SBlue Swirl case POWERPC_EXCP_CRITICAL: /* Critical input */ 252c79c73f6SBlue Swirl switch (excp_model) { 253c79c73f6SBlue Swirl case POWERPC_EXCP_40x: 254c79c73f6SBlue Swirl srr0 = SPR_40x_SRR2; 255c79c73f6SBlue Swirl srr1 = SPR_40x_SRR3; 256c79c73f6SBlue Swirl break; 257c79c73f6SBlue Swirl case POWERPC_EXCP_BOOKE: 258c79c73f6SBlue Swirl srr0 = SPR_BOOKE_CSRR0; 259c79c73f6SBlue Swirl srr1 = SPR_BOOKE_CSRR1; 260c79c73f6SBlue Swirl break; 261c79c73f6SBlue Swirl case POWERPC_EXCP_G2: 262c79c73f6SBlue Swirl break; 263c79c73f6SBlue Swirl default: 264c79c73f6SBlue Swirl goto excp_invalid; 265c79c73f6SBlue Swirl } 266bd6fefe7SBenjamin Herrenschmidt break; 267c79c73f6SBlue Swirl case POWERPC_EXCP_MCHECK: /* Machine check exception */ 268c79c73f6SBlue Swirl if (msr_me == 0) { 26947733729SDavid Gibson /* 27047733729SDavid Gibson * Machine check exception is not enabled. Enter 27147733729SDavid Gibson * checkstop state. 272c79c73f6SBlue Swirl */ 273c79c73f6SBlue Swirl fprintf(stderr, "Machine check while not allowed. " 274c79c73f6SBlue Swirl "Entering checkstop state\n"); 275013a2942SPaolo Bonzini if (qemu_log_separate()) { 276013a2942SPaolo Bonzini qemu_log("Machine check while not allowed. " 277013a2942SPaolo Bonzini "Entering checkstop state\n"); 278c79c73f6SBlue Swirl } 279259186a7SAndreas Färber cs->halted = 1; 280044897efSRichard Purdie cpu_interrupt_exittb(cs); 281c79c73f6SBlue Swirl } 28210c21b5cSNicholas Piggin if (env->msr_mask & MSR_HVB) { 28347733729SDavid Gibson /* 28447733729SDavid Gibson * ISA specifies HV, but can be delivered to guest with HV 28547733729SDavid Gibson * clear (e.g., see FWNMI in PAPR). 28610c21b5cSNicholas Piggin */ 287c79c73f6SBlue Swirl new_msr |= (target_ulong)MSR_HVB; 28810c21b5cSNicholas Piggin } 2895c94b2a5SCédric Le Goater ail = 0; 290c79c73f6SBlue Swirl 291c79c73f6SBlue Swirl /* machine check exceptions don't have ME set */ 292c79c73f6SBlue Swirl new_msr &= ~((target_ulong)1 << MSR_ME); 293c79c73f6SBlue Swirl 294c79c73f6SBlue Swirl /* XXX: should also have something loaded in DAR / DSISR */ 295c79c73f6SBlue Swirl switch (excp_model) { 296c79c73f6SBlue Swirl case POWERPC_EXCP_40x: 297c79c73f6SBlue Swirl srr0 = SPR_40x_SRR2; 298c79c73f6SBlue Swirl srr1 = SPR_40x_SRR3; 299c79c73f6SBlue Swirl break; 300c79c73f6SBlue Swirl case POWERPC_EXCP_BOOKE: 301a1bb7384SScott Wood /* FIXME: choose one or the other based on CPU type */ 302c79c73f6SBlue Swirl srr0 = SPR_BOOKE_MCSRR0; 303c79c73f6SBlue Swirl srr1 = SPR_BOOKE_MCSRR1; 304c79c73f6SBlue Swirl asrr0 = SPR_BOOKE_CSRR0; 305c79c73f6SBlue Swirl asrr1 = SPR_BOOKE_CSRR1; 306c79c73f6SBlue Swirl break; 307c79c73f6SBlue Swirl default: 308c79c73f6SBlue Swirl break; 309c79c73f6SBlue Swirl } 310bd6fefe7SBenjamin Herrenschmidt break; 311c79c73f6SBlue Swirl case POWERPC_EXCP_DSI: /* Data storage exception */ 312c79c73f6SBlue Swirl LOG_EXCP("DSI exception: DSISR=" TARGET_FMT_lx" DAR=" TARGET_FMT_lx 313c79c73f6SBlue Swirl "\n", env->spr[SPR_DSISR], env->spr[SPR_DAR]); 314bd6fefe7SBenjamin Herrenschmidt break; 315c79c73f6SBlue Swirl case POWERPC_EXCP_ISI: /* Instruction storage exception */ 316c79c73f6SBlue Swirl LOG_EXCP("ISI exception: msr=" TARGET_FMT_lx ", nip=" TARGET_FMT_lx 317c79c73f6SBlue Swirl "\n", msr, env->nip); 318c79c73f6SBlue Swirl msr |= env->error_code; 319bd6fefe7SBenjamin Herrenschmidt break; 320c79c73f6SBlue Swirl case POWERPC_EXCP_EXTERNAL: /* External input */ 321fdfba1a2SEdgar E. Iglesias cs = CPU(cpu); 322fdfba1a2SEdgar E. Iglesias 3236d49d6d4SBenjamin Herrenschmidt if (!lpes0) { 324c79c73f6SBlue Swirl new_msr |= (target_ulong)MSR_HVB; 3256d49d6d4SBenjamin Herrenschmidt new_msr |= env->msr & ((target_ulong)1 << MSR_RI); 3266d49d6d4SBenjamin Herrenschmidt srr0 = SPR_HSRR0; 3276d49d6d4SBenjamin Herrenschmidt srr1 = SPR_HSRR1; 328c79c73f6SBlue Swirl } 32968c2dd70SAlexander Graf if (env->mpic_proxy) { 33068c2dd70SAlexander Graf /* IACK the IRQ on delivery */ 331fdfba1a2SEdgar E. Iglesias env->spr[SPR_BOOKE_EPR] = ldl_phys(cs->as, env->mpic_iack); 33268c2dd70SAlexander Graf } 333bd6fefe7SBenjamin Herrenschmidt break; 334c79c73f6SBlue Swirl case POWERPC_EXCP_ALIGN: /* Alignment exception */ 335c79c73f6SBlue Swirl /* Get rS/rD and rA from faulting opcode */ 33647733729SDavid Gibson /* 33747733729SDavid Gibson * Note: the opcode fields will not be set properly for a 33847733729SDavid Gibson * direct store load/store, but nobody cares as nobody 33947733729SDavid Gibson * actually uses direct store segments. 3403433b732SBenjamin Herrenschmidt */ 3413433b732SBenjamin Herrenschmidt env->spr[SPR_DSISR] |= (env->error_code & 0x03FF0000) >> 16; 342bd6fefe7SBenjamin Herrenschmidt break; 343c79c73f6SBlue Swirl case POWERPC_EXCP_PROGRAM: /* Program exception */ 344c79c73f6SBlue Swirl switch (env->error_code & ~0xF) { 345c79c73f6SBlue Swirl case POWERPC_EXCP_FP: 346c79c73f6SBlue Swirl if ((msr_fe0 == 0 && msr_fe1 == 0) || msr_fp == 0) { 347c79c73f6SBlue Swirl LOG_EXCP("Ignore floating point exception\n"); 34827103424SAndreas Färber cs->exception_index = POWERPC_EXCP_NONE; 349c79c73f6SBlue Swirl env->error_code = 0; 350c79c73f6SBlue Swirl return; 351c79c73f6SBlue Swirl } 3521b7d17caSBenjamin Herrenschmidt 35347733729SDavid Gibson /* 35447733729SDavid Gibson * FP exceptions always have NIP pointing to the faulting 3551b7d17caSBenjamin Herrenschmidt * instruction, so always use store_next and claim we are 3561b7d17caSBenjamin Herrenschmidt * precise in the MSR. 3571b7d17caSBenjamin Herrenschmidt */ 358c79c73f6SBlue Swirl msr |= 0x00100000; 3590ee604abSAaron Larson env->spr[SPR_BOOKE_ESR] = ESR_FP; 360bd6fefe7SBenjamin Herrenschmidt break; 361c79c73f6SBlue Swirl case POWERPC_EXCP_INVAL: 362c79c73f6SBlue Swirl LOG_EXCP("Invalid instruction at " TARGET_FMT_lx "\n", env->nip); 363c79c73f6SBlue Swirl msr |= 0x00080000; 364c79c73f6SBlue Swirl env->spr[SPR_BOOKE_ESR] = ESR_PIL; 365c79c73f6SBlue Swirl break; 366c79c73f6SBlue Swirl case POWERPC_EXCP_PRIV: 367c79c73f6SBlue Swirl msr |= 0x00040000; 368c79c73f6SBlue Swirl env->spr[SPR_BOOKE_ESR] = ESR_PPR; 369c79c73f6SBlue Swirl break; 370c79c73f6SBlue Swirl case POWERPC_EXCP_TRAP: 371c79c73f6SBlue Swirl msr |= 0x00020000; 372c79c73f6SBlue Swirl env->spr[SPR_BOOKE_ESR] = ESR_PTR; 373c79c73f6SBlue Swirl break; 374c79c73f6SBlue Swirl default: 375c79c73f6SBlue Swirl /* Should never occur */ 376a47dddd7SAndreas Färber cpu_abort(cs, "Invalid program exception %d. Aborting\n", 377c79c73f6SBlue Swirl env->error_code); 378c79c73f6SBlue Swirl break; 379c79c73f6SBlue Swirl } 380bd6fefe7SBenjamin Herrenschmidt break; 381c79c73f6SBlue Swirl case POWERPC_EXCP_SYSCALL: /* System call exception */ 382c79c73f6SBlue Swirl dump_syscall(env); 383c79c73f6SBlue Swirl lev = env->error_code; 3846d49d6d4SBenjamin Herrenschmidt 38547733729SDavid Gibson /* 38647733729SDavid Gibson * We need to correct the NIP which in this case is supposed 387bd6fefe7SBenjamin Herrenschmidt * to point to the next instruction 388bd6fefe7SBenjamin Herrenschmidt */ 389bd6fefe7SBenjamin Herrenschmidt env->nip += 4; 390bd6fefe7SBenjamin Herrenschmidt 3916d49d6d4SBenjamin Herrenschmidt /* "PAPR mode" built-in hypercall emulation */ 3921d1be34dSDavid Gibson if ((lev == 1) && cpu->vhyp) { 3931d1be34dSDavid Gibson PPCVirtualHypervisorClass *vhc = 3941d1be34dSDavid Gibson PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp); 3951d1be34dSDavid Gibson vhc->hypercall(cpu->vhyp, cpu); 396c79c73f6SBlue Swirl return; 397c79c73f6SBlue Swirl } 3986d49d6d4SBenjamin Herrenschmidt if (lev == 1) { 399c79c73f6SBlue Swirl new_msr |= (target_ulong)MSR_HVB; 400c79c73f6SBlue Swirl } 401bd6fefe7SBenjamin Herrenschmidt break; 402bd6fefe7SBenjamin Herrenschmidt case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */ 403c79c73f6SBlue Swirl case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */ 404c79c73f6SBlue Swirl case POWERPC_EXCP_DECR: /* Decrementer exception */ 405bd6fefe7SBenjamin Herrenschmidt break; 406c79c73f6SBlue Swirl case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */ 407c79c73f6SBlue Swirl /* FIT on 4xx */ 408c79c73f6SBlue Swirl LOG_EXCP("FIT exception\n"); 409bd6fefe7SBenjamin Herrenschmidt break; 410c79c73f6SBlue Swirl case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */ 411c79c73f6SBlue Swirl LOG_EXCP("WDT exception\n"); 412c79c73f6SBlue Swirl switch (excp_model) { 413c79c73f6SBlue Swirl case POWERPC_EXCP_BOOKE: 414c79c73f6SBlue Swirl srr0 = SPR_BOOKE_CSRR0; 415c79c73f6SBlue Swirl srr1 = SPR_BOOKE_CSRR1; 416c79c73f6SBlue Swirl break; 417c79c73f6SBlue Swirl default: 418c79c73f6SBlue Swirl break; 419c79c73f6SBlue Swirl } 420bd6fefe7SBenjamin Herrenschmidt break; 421c79c73f6SBlue Swirl case POWERPC_EXCP_DTLB: /* Data TLB error */ 422c79c73f6SBlue Swirl case POWERPC_EXCP_ITLB: /* Instruction TLB error */ 423bd6fefe7SBenjamin Herrenschmidt break; 424c79c73f6SBlue Swirl case POWERPC_EXCP_DEBUG: /* Debug interrupt */ 4250e3bf489SRoman Kapl if (env->flags & POWERPC_FLAG_DE) { 426a1bb7384SScott Wood /* FIXME: choose one or the other based on CPU type */ 427c79c73f6SBlue Swirl srr0 = SPR_BOOKE_DSRR0; 428c79c73f6SBlue Swirl srr1 = SPR_BOOKE_DSRR1; 429c79c73f6SBlue Swirl asrr0 = SPR_BOOKE_CSRR0; 430c79c73f6SBlue Swirl asrr1 = SPR_BOOKE_CSRR1; 4310e3bf489SRoman Kapl /* DBSR already modified by caller */ 4320e3bf489SRoman Kapl } else { 4330e3bf489SRoman Kapl cpu_abort(cs, "Debug exception triggered on unsupported model\n"); 434c79c73f6SBlue Swirl } 435bd6fefe7SBenjamin Herrenschmidt break; 436c79c73f6SBlue Swirl case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavailable */ 437c79c73f6SBlue Swirl env->spr[SPR_BOOKE_ESR] = ESR_SPV; 438bd6fefe7SBenjamin Herrenschmidt break; 439c79c73f6SBlue Swirl case POWERPC_EXCP_EFPDI: /* Embedded floating-point data interrupt */ 440c79c73f6SBlue Swirl /* XXX: TODO */ 441a47dddd7SAndreas Färber cpu_abort(cs, "Embedded floating point data exception " 442c79c73f6SBlue Swirl "is not implemented yet !\n"); 443c79c73f6SBlue Swirl env->spr[SPR_BOOKE_ESR] = ESR_SPV; 444bd6fefe7SBenjamin Herrenschmidt break; 445c79c73f6SBlue Swirl case POWERPC_EXCP_EFPRI: /* Embedded floating-point round interrupt */ 446c79c73f6SBlue Swirl /* XXX: TODO */ 447a47dddd7SAndreas Färber cpu_abort(cs, "Embedded floating point round exception " 448c79c73f6SBlue Swirl "is not implemented yet !\n"); 449c79c73f6SBlue Swirl env->spr[SPR_BOOKE_ESR] = ESR_SPV; 450bd6fefe7SBenjamin Herrenschmidt break; 451c79c73f6SBlue Swirl case POWERPC_EXCP_EPERFM: /* Embedded performance monitor interrupt */ 452c79c73f6SBlue Swirl /* XXX: TODO */ 453a47dddd7SAndreas Färber cpu_abort(cs, 454c79c73f6SBlue Swirl "Performance counter exception is not implemented yet !\n"); 455bd6fefe7SBenjamin Herrenschmidt break; 456c79c73f6SBlue Swirl case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */ 457bd6fefe7SBenjamin Herrenschmidt break; 458c79c73f6SBlue Swirl case POWERPC_EXCP_DOORCI: /* Embedded doorbell critical interrupt */ 459c79c73f6SBlue Swirl srr0 = SPR_BOOKE_CSRR0; 460c79c73f6SBlue Swirl srr1 = SPR_BOOKE_CSRR1; 461bd6fefe7SBenjamin Herrenschmidt break; 462c79c73f6SBlue Swirl case POWERPC_EXCP_RESET: /* System reset exception */ 463f85bcec3SNicholas Piggin /* A power-saving exception sets ME, otherwise it is unchanged */ 464c79c73f6SBlue Swirl if (msr_pow) { 465c79c73f6SBlue Swirl /* indicate that we resumed from power save mode */ 466c79c73f6SBlue Swirl msr |= 0x10000; 467f85bcec3SNicholas Piggin new_msr |= ((target_ulong)1 << MSR_ME); 468c79c73f6SBlue Swirl } 46910c21b5cSNicholas Piggin if (env->msr_mask & MSR_HVB) { 47047733729SDavid Gibson /* 47147733729SDavid Gibson * ISA specifies HV, but can be delivered to guest with HV 47247733729SDavid Gibson * clear (e.g., see FWNMI in PAPR, NMI injection in QEMU). 47310c21b5cSNicholas Piggin */ 474c79c73f6SBlue Swirl new_msr |= (target_ulong)MSR_HVB; 47510c21b5cSNicholas Piggin } else { 47610c21b5cSNicholas Piggin if (msr_pow) { 47710c21b5cSNicholas Piggin cpu_abort(cs, "Trying to deliver power-saving system reset " 47810c21b5cSNicholas Piggin "exception %d with no HV support\n", excp); 47910c21b5cSNicholas Piggin } 48010c21b5cSNicholas Piggin } 4815c94b2a5SCédric Le Goater ail = 0; 482bd6fefe7SBenjamin Herrenschmidt break; 483c79c73f6SBlue Swirl case POWERPC_EXCP_DSEG: /* Data segment exception */ 484c79c73f6SBlue Swirl case POWERPC_EXCP_ISEG: /* Instruction segment exception */ 485c79c73f6SBlue Swirl case POWERPC_EXCP_TRACE: /* Trace exception */ 486bd6fefe7SBenjamin Herrenschmidt break; 487bd6fefe7SBenjamin Herrenschmidt case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception */ 488c79c73f6SBlue Swirl case POWERPC_EXCP_HDSI: /* Hypervisor data storage exception */ 489c79c73f6SBlue Swirl case POWERPC_EXCP_HISI: /* Hypervisor instruction storage exception */ 490c79c73f6SBlue Swirl case POWERPC_EXCP_HDSEG: /* Hypervisor data segment exception */ 491c79c73f6SBlue Swirl case POWERPC_EXCP_HISEG: /* Hypervisor instruction segment exception */ 4927af1e7b0SCédric Le Goater case POWERPC_EXCP_SDOOR_HV: /* Hypervisor Doorbell interrupt */ 493bd6fefe7SBenjamin Herrenschmidt case POWERPC_EXCP_HV_EMU: 494d8ce5fd6SBenjamin Herrenschmidt case POWERPC_EXCP_HVIRT: /* Hypervisor virtualization */ 495c79c73f6SBlue Swirl srr0 = SPR_HSRR0; 496c79c73f6SBlue Swirl srr1 = SPR_HSRR1; 497c79c73f6SBlue Swirl new_msr |= (target_ulong)MSR_HVB; 498c79c73f6SBlue Swirl new_msr |= env->msr & ((target_ulong)1 << MSR_RI); 499bd6fefe7SBenjamin Herrenschmidt break; 500c79c73f6SBlue Swirl case POWERPC_EXCP_VPU: /* Vector unavailable exception */ 5011f29871cSTom Musta case POWERPC_EXCP_VSXU: /* VSX unavailable exception */ 5027019cb3dSAlexey Kardashevskiy case POWERPC_EXCP_FU: /* Facility unavailable exception */ 5035310799aSBalbir Singh #ifdef TARGET_PPC64 5045310799aSBalbir Singh env->spr[SPR_FSCR] |= ((target_ulong)env->error_code << 56); 5055310799aSBalbir Singh #endif 506bd6fefe7SBenjamin Herrenschmidt break; 507493028d8SCédric Le Goater case POWERPC_EXCP_HV_FU: /* Hypervisor Facility Unavailable Exception */ 508493028d8SCédric Le Goater #ifdef TARGET_PPC64 509493028d8SCédric Le Goater env->spr[SPR_HFSCR] |= ((target_ulong)env->error_code << FSCR_IC_POS); 510493028d8SCédric Le Goater srr0 = SPR_HSRR0; 511493028d8SCédric Le Goater srr1 = SPR_HSRR1; 512493028d8SCédric Le Goater new_msr |= (target_ulong)MSR_HVB; 513493028d8SCédric Le Goater new_msr |= env->msr & ((target_ulong)1 << MSR_RI); 514493028d8SCédric Le Goater #endif 515493028d8SCédric Le Goater break; 516c79c73f6SBlue Swirl case POWERPC_EXCP_PIT: /* Programmable interval timer interrupt */ 517c79c73f6SBlue Swirl LOG_EXCP("PIT exception\n"); 518bd6fefe7SBenjamin Herrenschmidt break; 519c79c73f6SBlue Swirl case POWERPC_EXCP_IO: /* IO error exception */ 520c79c73f6SBlue Swirl /* XXX: TODO */ 521a47dddd7SAndreas Färber cpu_abort(cs, "601 IO error exception is not implemented yet !\n"); 522bd6fefe7SBenjamin Herrenschmidt break; 523c79c73f6SBlue Swirl case POWERPC_EXCP_RUNM: /* Run mode exception */ 524c79c73f6SBlue Swirl /* XXX: TODO */ 525a47dddd7SAndreas Färber cpu_abort(cs, "601 run mode exception is not implemented yet !\n"); 526bd6fefe7SBenjamin Herrenschmidt break; 527c79c73f6SBlue Swirl case POWERPC_EXCP_EMUL: /* Emulation trap exception */ 528c79c73f6SBlue Swirl /* XXX: TODO */ 529a47dddd7SAndreas Färber cpu_abort(cs, "602 emulation trap exception " 530c79c73f6SBlue Swirl "is not implemented yet !\n"); 531bd6fefe7SBenjamin Herrenschmidt break; 532c79c73f6SBlue Swirl case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */ 533c79c73f6SBlue Swirl switch (excp_model) { 534c79c73f6SBlue Swirl case POWERPC_EXCP_602: 535c79c73f6SBlue Swirl case POWERPC_EXCP_603: 536c79c73f6SBlue Swirl case POWERPC_EXCP_603E: 537c79c73f6SBlue Swirl case POWERPC_EXCP_G2: 538c79c73f6SBlue Swirl goto tlb_miss_tgpr; 539c79c73f6SBlue Swirl case POWERPC_EXCP_7x5: 540c79c73f6SBlue Swirl goto tlb_miss; 541c79c73f6SBlue Swirl case POWERPC_EXCP_74xx: 542c79c73f6SBlue Swirl goto tlb_miss_74xx; 543c79c73f6SBlue Swirl default: 544a47dddd7SAndreas Färber cpu_abort(cs, "Invalid instruction TLB miss exception\n"); 545c79c73f6SBlue Swirl break; 546c79c73f6SBlue Swirl } 547c79c73f6SBlue Swirl break; 548c79c73f6SBlue Swirl case POWERPC_EXCP_DLTLB: /* Data load TLB miss */ 549c79c73f6SBlue Swirl switch (excp_model) { 550c79c73f6SBlue Swirl case POWERPC_EXCP_602: 551c79c73f6SBlue Swirl case POWERPC_EXCP_603: 552c79c73f6SBlue Swirl case POWERPC_EXCP_603E: 553c79c73f6SBlue Swirl case POWERPC_EXCP_G2: 554c79c73f6SBlue Swirl goto tlb_miss_tgpr; 555c79c73f6SBlue Swirl case POWERPC_EXCP_7x5: 556c79c73f6SBlue Swirl goto tlb_miss; 557c79c73f6SBlue Swirl case POWERPC_EXCP_74xx: 558c79c73f6SBlue Swirl goto tlb_miss_74xx; 559c79c73f6SBlue Swirl default: 560a47dddd7SAndreas Färber cpu_abort(cs, "Invalid data load TLB miss exception\n"); 561c79c73f6SBlue Swirl break; 562c79c73f6SBlue Swirl } 563c79c73f6SBlue Swirl break; 564c79c73f6SBlue Swirl case POWERPC_EXCP_DSTLB: /* Data store TLB miss */ 565c79c73f6SBlue Swirl switch (excp_model) { 566c79c73f6SBlue Swirl case POWERPC_EXCP_602: 567c79c73f6SBlue Swirl case POWERPC_EXCP_603: 568c79c73f6SBlue Swirl case POWERPC_EXCP_603E: 569c79c73f6SBlue Swirl case POWERPC_EXCP_G2: 570c79c73f6SBlue Swirl tlb_miss_tgpr: 571c79c73f6SBlue Swirl /* Swap temporary saved registers with GPRs */ 572c79c73f6SBlue Swirl if (!(new_msr & ((target_ulong)1 << MSR_TGPR))) { 573c79c73f6SBlue Swirl new_msr |= (target_ulong)1 << MSR_TGPR; 574c79c73f6SBlue Swirl hreg_swap_gpr_tgpr(env); 575c79c73f6SBlue Swirl } 576c79c73f6SBlue Swirl goto tlb_miss; 577c79c73f6SBlue Swirl case POWERPC_EXCP_7x5: 578c79c73f6SBlue Swirl tlb_miss: 579c79c73f6SBlue Swirl #if defined(DEBUG_SOFTWARE_TLB) 580c79c73f6SBlue Swirl if (qemu_log_enabled()) { 581c79c73f6SBlue Swirl const char *es; 582c79c73f6SBlue Swirl target_ulong *miss, *cmp; 583c79c73f6SBlue Swirl int en; 584c79c73f6SBlue Swirl 585c79c73f6SBlue Swirl if (excp == POWERPC_EXCP_IFTLB) { 586c79c73f6SBlue Swirl es = "I"; 587c79c73f6SBlue Swirl en = 'I'; 588c79c73f6SBlue Swirl miss = &env->spr[SPR_IMISS]; 589c79c73f6SBlue Swirl cmp = &env->spr[SPR_ICMP]; 590c79c73f6SBlue Swirl } else { 591c79c73f6SBlue Swirl if (excp == POWERPC_EXCP_DLTLB) { 592c79c73f6SBlue Swirl es = "DL"; 593c79c73f6SBlue Swirl } else { 594c79c73f6SBlue Swirl es = "DS"; 595c79c73f6SBlue Swirl } 596c79c73f6SBlue Swirl en = 'D'; 597c79c73f6SBlue Swirl miss = &env->spr[SPR_DMISS]; 598c79c73f6SBlue Swirl cmp = &env->spr[SPR_DCMP]; 599c79c73f6SBlue Swirl } 600c79c73f6SBlue Swirl qemu_log("6xx %sTLB miss: %cM " TARGET_FMT_lx " %cC " 601c79c73f6SBlue Swirl TARGET_FMT_lx " H1 " TARGET_FMT_lx " H2 " 602c79c73f6SBlue Swirl TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp, 603c79c73f6SBlue Swirl env->spr[SPR_HASH1], env->spr[SPR_HASH2], 604c79c73f6SBlue Swirl env->error_code); 605c79c73f6SBlue Swirl } 606c79c73f6SBlue Swirl #endif 607c79c73f6SBlue Swirl msr |= env->crf[0] << 28; 608c79c73f6SBlue Swirl msr |= env->error_code; /* key, D/I, S/L bits */ 609c79c73f6SBlue Swirl /* Set way using a LRU mechanism */ 610c79c73f6SBlue Swirl msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17; 611c79c73f6SBlue Swirl break; 612c79c73f6SBlue Swirl case POWERPC_EXCP_74xx: 613c79c73f6SBlue Swirl tlb_miss_74xx: 614c79c73f6SBlue Swirl #if defined(DEBUG_SOFTWARE_TLB) 615c79c73f6SBlue Swirl if (qemu_log_enabled()) { 616c79c73f6SBlue Swirl const char *es; 617c79c73f6SBlue Swirl target_ulong *miss, *cmp; 618c79c73f6SBlue Swirl int en; 619c79c73f6SBlue Swirl 620c79c73f6SBlue Swirl if (excp == POWERPC_EXCP_IFTLB) { 621c79c73f6SBlue Swirl es = "I"; 622c79c73f6SBlue Swirl en = 'I'; 623c79c73f6SBlue Swirl miss = &env->spr[SPR_TLBMISS]; 624c79c73f6SBlue Swirl cmp = &env->spr[SPR_PTEHI]; 625c79c73f6SBlue Swirl } else { 626c79c73f6SBlue Swirl if (excp == POWERPC_EXCP_DLTLB) { 627c79c73f6SBlue Swirl es = "DL"; 628c79c73f6SBlue Swirl } else { 629c79c73f6SBlue Swirl es = "DS"; 630c79c73f6SBlue Swirl } 631c79c73f6SBlue Swirl en = 'D'; 632c79c73f6SBlue Swirl miss = &env->spr[SPR_TLBMISS]; 633c79c73f6SBlue Swirl cmp = &env->spr[SPR_PTEHI]; 634c79c73f6SBlue Swirl } 635c79c73f6SBlue Swirl qemu_log("74xx %sTLB miss: %cM " TARGET_FMT_lx " %cC " 636c79c73f6SBlue Swirl TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp, 637c79c73f6SBlue Swirl env->error_code); 638c79c73f6SBlue Swirl } 639c79c73f6SBlue Swirl #endif 640c79c73f6SBlue Swirl msr |= env->error_code; /* key bit */ 641c79c73f6SBlue Swirl break; 642c79c73f6SBlue Swirl default: 643a47dddd7SAndreas Färber cpu_abort(cs, "Invalid data store TLB miss exception\n"); 644c79c73f6SBlue Swirl break; 645c79c73f6SBlue Swirl } 646bd6fefe7SBenjamin Herrenschmidt break; 647c79c73f6SBlue Swirl case POWERPC_EXCP_FPA: /* Floating-point assist exception */ 648c79c73f6SBlue Swirl /* XXX: TODO */ 649a47dddd7SAndreas Färber cpu_abort(cs, "Floating point assist exception " 650c79c73f6SBlue Swirl "is not implemented yet !\n"); 651bd6fefe7SBenjamin Herrenschmidt break; 652c79c73f6SBlue Swirl case POWERPC_EXCP_DABR: /* Data address breakpoint */ 653c79c73f6SBlue Swirl /* XXX: TODO */ 654a47dddd7SAndreas Färber cpu_abort(cs, "DABR exception is not implemented yet !\n"); 655bd6fefe7SBenjamin Herrenschmidt break; 656c79c73f6SBlue Swirl case POWERPC_EXCP_IABR: /* Instruction address breakpoint */ 657c79c73f6SBlue Swirl /* XXX: TODO */ 658a47dddd7SAndreas Färber cpu_abort(cs, "IABR exception is not implemented yet !\n"); 659bd6fefe7SBenjamin Herrenschmidt break; 660c79c73f6SBlue Swirl case POWERPC_EXCP_SMI: /* System management interrupt */ 661c79c73f6SBlue Swirl /* XXX: TODO */ 662a47dddd7SAndreas Färber cpu_abort(cs, "SMI exception is not implemented yet !\n"); 663bd6fefe7SBenjamin Herrenschmidt break; 664c79c73f6SBlue Swirl case POWERPC_EXCP_THERM: /* Thermal interrupt */ 665c79c73f6SBlue Swirl /* XXX: TODO */ 666a47dddd7SAndreas Färber cpu_abort(cs, "Thermal management exception " 667c79c73f6SBlue Swirl "is not implemented yet !\n"); 668bd6fefe7SBenjamin Herrenschmidt break; 669c79c73f6SBlue Swirl case POWERPC_EXCP_PERFM: /* Embedded performance monitor interrupt */ 670c79c73f6SBlue Swirl /* XXX: TODO */ 671a47dddd7SAndreas Färber cpu_abort(cs, 672c79c73f6SBlue Swirl "Performance counter exception is not implemented yet !\n"); 673bd6fefe7SBenjamin Herrenschmidt break; 674c79c73f6SBlue Swirl case POWERPC_EXCP_VPUA: /* Vector assist exception */ 675c79c73f6SBlue Swirl /* XXX: TODO */ 676a47dddd7SAndreas Färber cpu_abort(cs, "VPU assist exception is not implemented yet !\n"); 677bd6fefe7SBenjamin Herrenschmidt break; 678c79c73f6SBlue Swirl case POWERPC_EXCP_SOFTP: /* Soft patch exception */ 679c79c73f6SBlue Swirl /* XXX: TODO */ 680a47dddd7SAndreas Färber cpu_abort(cs, 681c79c73f6SBlue Swirl "970 soft-patch exception is not implemented yet !\n"); 682bd6fefe7SBenjamin Herrenschmidt break; 683c79c73f6SBlue Swirl case POWERPC_EXCP_MAINT: /* Maintenance exception */ 684c79c73f6SBlue Swirl /* XXX: TODO */ 685a47dddd7SAndreas Färber cpu_abort(cs, 686c79c73f6SBlue Swirl "970 maintenance exception is not implemented yet !\n"); 687bd6fefe7SBenjamin Herrenschmidt break; 688c79c73f6SBlue Swirl case POWERPC_EXCP_MEXTBR: /* Maskable external breakpoint */ 689c79c73f6SBlue Swirl /* XXX: TODO */ 690a47dddd7SAndreas Färber cpu_abort(cs, "Maskable external exception " 691c79c73f6SBlue Swirl "is not implemented yet !\n"); 692bd6fefe7SBenjamin Herrenschmidt break; 693c79c73f6SBlue Swirl case POWERPC_EXCP_NMEXTBR: /* Non maskable external breakpoint */ 694c79c73f6SBlue Swirl /* XXX: TODO */ 695a47dddd7SAndreas Färber cpu_abort(cs, "Non maskable external exception " 696c79c73f6SBlue Swirl "is not implemented yet !\n"); 697bd6fefe7SBenjamin Herrenschmidt break; 698c79c73f6SBlue Swirl default: 699c79c73f6SBlue Swirl excp_invalid: 700a47dddd7SAndreas Färber cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp); 701c79c73f6SBlue Swirl break; 702c79c73f6SBlue Swirl } 703bd6fefe7SBenjamin Herrenschmidt 704bd6fefe7SBenjamin Herrenschmidt /* Save PC */ 705bd6fefe7SBenjamin Herrenschmidt env->spr[srr0] = env->nip; 706bd6fefe7SBenjamin Herrenschmidt 707c79c73f6SBlue Swirl /* Save MSR */ 708c79c73f6SBlue Swirl env->spr[srr1] = msr; 7096d49d6d4SBenjamin Herrenschmidt 7106d49d6d4SBenjamin Herrenschmidt /* Sanity check */ 71110c21b5cSNicholas Piggin if (!(env->msr_mask & MSR_HVB)) { 71210c21b5cSNicholas Piggin if (new_msr & MSR_HVB) { 71310c21b5cSNicholas Piggin cpu_abort(cs, "Trying to deliver HV exception (MSR) %d with " 7146d49d6d4SBenjamin Herrenschmidt "no HV support\n", excp); 7156d49d6d4SBenjamin Herrenschmidt } 71610c21b5cSNicholas Piggin if (srr0 == SPR_HSRR0) { 71710c21b5cSNicholas Piggin cpu_abort(cs, "Trying to deliver HV exception (HSRR) %d with " 71810c21b5cSNicholas Piggin "no HV support\n", excp); 71910c21b5cSNicholas Piggin } 72010c21b5cSNicholas Piggin } 7216d49d6d4SBenjamin Herrenschmidt 722c79c73f6SBlue Swirl /* If any alternate SRR register are defined, duplicate saved values */ 723c79c73f6SBlue Swirl if (asrr0 != -1) { 724c79c73f6SBlue Swirl env->spr[asrr0] = env->spr[srr0]; 725c79c73f6SBlue Swirl } 726c79c73f6SBlue Swirl if (asrr1 != -1) { 727c79c73f6SBlue Swirl env->spr[asrr1] = env->spr[srr1]; 728c79c73f6SBlue Swirl } 729d5ac4f54SAlexey Kardashevskiy 73047733729SDavid Gibson /* 73147733729SDavid Gibson * Sort out endianness of interrupt, this differs depending on the 7326d49d6d4SBenjamin Herrenschmidt * CPU, the HV mode, etc... 7336d49d6d4SBenjamin Herrenschmidt */ 7341e0c7e55SAnton Blanchard #ifdef TARGET_PPC64 7356d49d6d4SBenjamin Herrenschmidt if (excp_model == POWERPC_EXCP_POWER7) { 7366d49d6d4SBenjamin Herrenschmidt if (!(new_msr & MSR_HVB) && (env->spr[SPR_LPCR] & LPCR_ILE)) { 7376d49d6d4SBenjamin Herrenschmidt new_msr |= (target_ulong)1 << MSR_LE; 7386d49d6d4SBenjamin Herrenschmidt } 7396d49d6d4SBenjamin Herrenschmidt } else if (excp_model == POWERPC_EXCP_POWER8) { 7406d49d6d4SBenjamin Herrenschmidt if (new_msr & MSR_HVB) { 741a790e82bSBenjamin Herrenschmidt if (env->spr[SPR_HID0] & HID0_HILE) { 742a790e82bSBenjamin Herrenschmidt new_msr |= (target_ulong)1 << MSR_LE; 743a790e82bSBenjamin Herrenschmidt } 744a790e82bSBenjamin Herrenschmidt } else if (env->spr[SPR_LPCR] & LPCR_ILE) { 745a790e82bSBenjamin Herrenschmidt new_msr |= (target_ulong)1 << MSR_LE; 746a790e82bSBenjamin Herrenschmidt } 747a790e82bSBenjamin Herrenschmidt } else if (excp_model == POWERPC_EXCP_POWER9) { 748a790e82bSBenjamin Herrenschmidt if (new_msr & MSR_HVB) { 749a790e82bSBenjamin Herrenschmidt if (env->spr[SPR_HID0] & HID0_POWER9_HILE) { 7506d49d6d4SBenjamin Herrenschmidt new_msr |= (target_ulong)1 << MSR_LE; 7516d49d6d4SBenjamin Herrenschmidt } 7526d49d6d4SBenjamin Herrenschmidt } else if (env->spr[SPR_LPCR] & LPCR_ILE) { 7531e0c7e55SAnton Blanchard new_msr |= (target_ulong)1 << MSR_LE; 7541e0c7e55SAnton Blanchard } 7551e0c7e55SAnton Blanchard } else if (msr_ile) { 7561e0c7e55SAnton Blanchard new_msr |= (target_ulong)1 << MSR_LE; 7571e0c7e55SAnton Blanchard } 7581e0c7e55SAnton Blanchard #else 759c79c73f6SBlue Swirl if (msr_ile) { 760c79c73f6SBlue Swirl new_msr |= (target_ulong)1 << MSR_LE; 761c79c73f6SBlue Swirl } 7621e0c7e55SAnton Blanchard #endif 763c79c73f6SBlue Swirl 764c79c73f6SBlue Swirl /* Jump to handler */ 765c79c73f6SBlue Swirl vector = env->excp_vectors[excp]; 766c79c73f6SBlue Swirl if (vector == (target_ulong)-1ULL) { 767a47dddd7SAndreas Färber cpu_abort(cs, "Raised an exception without defined vector %d\n", 768c79c73f6SBlue Swirl excp); 769c79c73f6SBlue Swirl } 770c79c73f6SBlue Swirl vector |= env->excp_prefix; 7715c94b2a5SCédric Le Goater 77247733729SDavid Gibson /* 77347733729SDavid Gibson * AIL only works if there is no HV transition and we are running 77447733729SDavid Gibson * with translations enabled 7755c94b2a5SCédric Le Goater */ 7766d49d6d4SBenjamin Herrenschmidt if (!((msr >> MSR_IR) & 1) || !((msr >> MSR_DR) & 1) || 7776d49d6d4SBenjamin Herrenschmidt ((new_msr & MSR_HVB) && !(msr & MSR_HVB))) { 7785c94b2a5SCédric Le Goater ail = 0; 7795c94b2a5SCédric Le Goater } 7805c94b2a5SCédric Le Goater /* Handle AIL */ 7815c94b2a5SCédric Le Goater if (ail) { 7825c94b2a5SCédric Le Goater new_msr |= (1 << MSR_IR) | (1 << MSR_DR); 7832586a4d7SFabiano Rosas vector |= ppc_excp_vector_offset(cs, ail); 7845c94b2a5SCédric Le Goater } 7855c94b2a5SCédric Le Goater 786c79c73f6SBlue Swirl #if defined(TARGET_PPC64) 787c79c73f6SBlue Swirl if (excp_model == POWERPC_EXCP_BOOKE) { 788e42a61f1SAlexander Graf if (env->spr[SPR_BOOKE_EPCR] & EPCR_ICM) { 789e42a61f1SAlexander Graf /* Cat.64-bit: EPCR.ICM is copied to MSR.CM */ 790c79c73f6SBlue Swirl new_msr |= (target_ulong)1 << MSR_CM; 791e42a61f1SAlexander Graf } else { 792e42a61f1SAlexander Graf vector = (uint32_t)vector; 793c79c73f6SBlue Swirl } 794c79c73f6SBlue Swirl } else { 795c79c73f6SBlue Swirl if (!msr_isf && !(env->mmu_model & POWERPC_MMU_64)) { 796c79c73f6SBlue Swirl vector = (uint32_t)vector; 797c79c73f6SBlue Swirl } else { 798c79c73f6SBlue Swirl new_msr |= (target_ulong)1 << MSR_SF; 799c79c73f6SBlue Swirl } 800c79c73f6SBlue Swirl } 801c79c73f6SBlue Swirl #endif 802cd0c6f47SBenjamin Herrenschmidt 803*ad77c6caSNicholas Piggin powerpc_set_excp_state(cpu, vector, new_msr); 804c79c73f6SBlue Swirl } 805c79c73f6SBlue Swirl 80697a8ea5aSAndreas Färber void ppc_cpu_do_interrupt(CPUState *cs) 807c79c73f6SBlue Swirl { 80897a8ea5aSAndreas Färber PowerPCCPU *cpu = POWERPC_CPU(cs); 80997a8ea5aSAndreas Färber CPUPPCState *env = &cpu->env; 8105c26a5b3SAndreas Färber 81127103424SAndreas Färber powerpc_excp(cpu, env->excp_model, cs->exception_index); 812c79c73f6SBlue Swirl } 813c79c73f6SBlue Swirl 814458dd766SRichard Henderson static void ppc_hw_interrupt(CPUPPCState *env) 815c79c73f6SBlue Swirl { 816db70b311SRichard Henderson PowerPCCPU *cpu = env_archcpu(env); 8173621e2c9SBenjamin Herrenschmidt bool async_deliver; 818259186a7SAndreas Färber 819c79c73f6SBlue Swirl /* External reset */ 820c79c73f6SBlue Swirl if (env->pending_interrupts & (1 << PPC_INTERRUPT_RESET)) { 821c79c73f6SBlue Swirl env->pending_interrupts &= ~(1 << PPC_INTERRUPT_RESET); 8225c26a5b3SAndreas Färber powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_RESET); 823c79c73f6SBlue Swirl return; 824c79c73f6SBlue Swirl } 825c79c73f6SBlue Swirl /* Machine check exception */ 826c79c73f6SBlue Swirl if (env->pending_interrupts & (1 << PPC_INTERRUPT_MCK)) { 827c79c73f6SBlue Swirl env->pending_interrupts &= ~(1 << PPC_INTERRUPT_MCK); 8285c26a5b3SAndreas Färber powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_MCHECK); 829c79c73f6SBlue Swirl return; 830c79c73f6SBlue Swirl } 831c79c73f6SBlue Swirl #if 0 /* TODO */ 832c79c73f6SBlue Swirl /* External debug exception */ 833c79c73f6SBlue Swirl if (env->pending_interrupts & (1 << PPC_INTERRUPT_DEBUG)) { 834c79c73f6SBlue Swirl env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DEBUG); 8355c26a5b3SAndreas Färber powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DEBUG); 836c79c73f6SBlue Swirl return; 837c79c73f6SBlue Swirl } 838c79c73f6SBlue Swirl #endif 8393621e2c9SBenjamin Herrenschmidt 8403621e2c9SBenjamin Herrenschmidt /* 8413621e2c9SBenjamin Herrenschmidt * For interrupts that gate on MSR:EE, we need to do something a 8423621e2c9SBenjamin Herrenschmidt * bit more subtle, as we need to let them through even when EE is 8433621e2c9SBenjamin Herrenschmidt * clear when coming out of some power management states (in order 8443621e2c9SBenjamin Herrenschmidt * for them to become a 0x100). 8453621e2c9SBenjamin Herrenschmidt */ 8461e7fd61dSBenjamin Herrenschmidt async_deliver = (msr_ee != 0) || env->resume_as_sreset; 8473621e2c9SBenjamin Herrenschmidt 848c79c73f6SBlue Swirl /* Hypervisor decrementer exception */ 849c79c73f6SBlue Swirl if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDECR)) { 8504b236b62SBenjamin Herrenschmidt /* LPCR will be clear when not supported so this will work */ 8514b236b62SBenjamin Herrenschmidt bool hdice = !!(env->spr[SPR_LPCR] & LPCR_HDICE); 8523621e2c9SBenjamin Herrenschmidt if ((async_deliver || msr_hv == 0) && hdice) { 8534b236b62SBenjamin Herrenschmidt /* HDEC clears on delivery */ 8544b236b62SBenjamin Herrenschmidt env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR); 8555c26a5b3SAndreas Färber powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_HDECR); 856c79c73f6SBlue Swirl return; 857c79c73f6SBlue Swirl } 858c79c73f6SBlue Swirl } 859d8ce5fd6SBenjamin Herrenschmidt 860d8ce5fd6SBenjamin Herrenschmidt /* Hypervisor virtualization interrupt */ 861d8ce5fd6SBenjamin Herrenschmidt if (env->pending_interrupts & (1 << PPC_INTERRUPT_HVIRT)) { 862d8ce5fd6SBenjamin Herrenschmidt /* LPCR will be clear when not supported so this will work */ 863d8ce5fd6SBenjamin Herrenschmidt bool hvice = !!(env->spr[SPR_LPCR] & LPCR_HVICE); 864d8ce5fd6SBenjamin Herrenschmidt if ((async_deliver || msr_hv == 0) && hvice) { 865d8ce5fd6SBenjamin Herrenschmidt powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_HVIRT); 866d8ce5fd6SBenjamin Herrenschmidt return; 867d8ce5fd6SBenjamin Herrenschmidt } 868d8ce5fd6SBenjamin Herrenschmidt } 869d8ce5fd6SBenjamin Herrenschmidt 870d8ce5fd6SBenjamin Herrenschmidt /* External interrupt can ignore MSR:EE under some circumstances */ 871d1dbe37cSBenjamin Herrenschmidt if (env->pending_interrupts & (1 << PPC_INTERRUPT_EXT)) { 872d1dbe37cSBenjamin Herrenschmidt bool lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0); 8736eebe6dcSBenjamin Herrenschmidt bool heic = !!(env->spr[SPR_LPCR] & LPCR_HEIC); 8746eebe6dcSBenjamin Herrenschmidt /* HEIC blocks delivery to the hypervisor */ 8756eebe6dcSBenjamin Herrenschmidt if ((async_deliver && !(heic && msr_hv && !msr_pr)) || 8766eebe6dcSBenjamin Herrenschmidt (env->has_hv_mode && msr_hv == 0 && !lpes0)) { 877d1dbe37cSBenjamin Herrenschmidt powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_EXTERNAL); 878d1dbe37cSBenjamin Herrenschmidt return; 879d1dbe37cSBenjamin Herrenschmidt } 880d1dbe37cSBenjamin Herrenschmidt } 881c79c73f6SBlue Swirl if (msr_ce != 0) { 882c79c73f6SBlue Swirl /* External critical interrupt */ 883c79c73f6SBlue Swirl if (env->pending_interrupts & (1 << PPC_INTERRUPT_CEXT)) { 8845c26a5b3SAndreas Färber powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_CRITICAL); 885c79c73f6SBlue Swirl return; 886c79c73f6SBlue Swirl } 887c79c73f6SBlue Swirl } 8883621e2c9SBenjamin Herrenschmidt if (async_deliver != 0) { 889c79c73f6SBlue Swirl /* Watchdog timer on embedded PowerPC */ 890c79c73f6SBlue Swirl if (env->pending_interrupts & (1 << PPC_INTERRUPT_WDT)) { 891c79c73f6SBlue Swirl env->pending_interrupts &= ~(1 << PPC_INTERRUPT_WDT); 8925c26a5b3SAndreas Färber powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_WDT); 893c79c73f6SBlue Swirl return; 894c79c73f6SBlue Swirl } 895c79c73f6SBlue Swirl if (env->pending_interrupts & (1 << PPC_INTERRUPT_CDOORBELL)) { 896c79c73f6SBlue Swirl env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CDOORBELL); 8975c26a5b3SAndreas Färber powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DOORCI); 898c79c73f6SBlue Swirl return; 899c79c73f6SBlue Swirl } 900c79c73f6SBlue Swirl /* Fixed interval timer on embedded PowerPC */ 901c79c73f6SBlue Swirl if (env->pending_interrupts & (1 << PPC_INTERRUPT_FIT)) { 902c79c73f6SBlue Swirl env->pending_interrupts &= ~(1 << PPC_INTERRUPT_FIT); 9035c26a5b3SAndreas Färber powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_FIT); 904c79c73f6SBlue Swirl return; 905c79c73f6SBlue Swirl } 906c79c73f6SBlue Swirl /* Programmable interval timer on embedded PowerPC */ 907c79c73f6SBlue Swirl if (env->pending_interrupts & (1 << PPC_INTERRUPT_PIT)) { 908c79c73f6SBlue Swirl env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PIT); 9095c26a5b3SAndreas Färber powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_PIT); 910c79c73f6SBlue Swirl return; 911c79c73f6SBlue Swirl } 912c79c73f6SBlue Swirl /* Decrementer exception */ 913c79c73f6SBlue Swirl if (env->pending_interrupts & (1 << PPC_INTERRUPT_DECR)) { 914e81a982aSAlexander Graf if (ppc_decr_clear_on_delivery(env)) { 915c79c73f6SBlue Swirl env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DECR); 916e81a982aSAlexander Graf } 9175c26a5b3SAndreas Färber powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DECR); 918c79c73f6SBlue Swirl return; 919c79c73f6SBlue Swirl } 920c79c73f6SBlue Swirl if (env->pending_interrupts & (1 << PPC_INTERRUPT_DOORBELL)) { 921c79c73f6SBlue Swirl env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DOORBELL); 9225ba7ba1dSCédric Le Goater if (is_book3s_arch2x(env)) { 9235ba7ba1dSCédric Le Goater powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_SDOOR); 9245ba7ba1dSCédric Le Goater } else { 9255c26a5b3SAndreas Färber powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DOORI); 9265ba7ba1dSCédric Le Goater } 927c79c73f6SBlue Swirl return; 928c79c73f6SBlue Swirl } 9297af1e7b0SCédric Le Goater if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDOORBELL)) { 9307af1e7b0SCédric Le Goater env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDOORBELL); 9317af1e7b0SCédric Le Goater powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_SDOOR_HV); 9327af1e7b0SCédric Le Goater return; 9337af1e7b0SCédric Le Goater } 934c79c73f6SBlue Swirl if (env->pending_interrupts & (1 << PPC_INTERRUPT_PERFM)) { 935c79c73f6SBlue Swirl env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PERFM); 9365c26a5b3SAndreas Färber powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_PERFM); 937c79c73f6SBlue Swirl return; 938c79c73f6SBlue Swirl } 939c79c73f6SBlue Swirl /* Thermal interrupt */ 940c79c73f6SBlue Swirl if (env->pending_interrupts & (1 << PPC_INTERRUPT_THERM)) { 941c79c73f6SBlue Swirl env->pending_interrupts &= ~(1 << PPC_INTERRUPT_THERM); 9425c26a5b3SAndreas Färber powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_THERM); 943c79c73f6SBlue Swirl return; 944c79c73f6SBlue Swirl } 945c79c73f6SBlue Swirl } 946f8154fd2SBenjamin Herrenschmidt 947f8154fd2SBenjamin Herrenschmidt if (env->resume_as_sreset) { 948f8154fd2SBenjamin Herrenschmidt /* 949f8154fd2SBenjamin Herrenschmidt * This is a bug ! It means that has_work took us out of halt without 950f8154fd2SBenjamin Herrenschmidt * anything to deliver while in a PM state that requires getting 951f8154fd2SBenjamin Herrenschmidt * out via a 0x100 952f8154fd2SBenjamin Herrenschmidt * 953f8154fd2SBenjamin Herrenschmidt * This means we will incorrectly execute past the power management 954f8154fd2SBenjamin Herrenschmidt * instruction instead of triggering a reset. 955f8154fd2SBenjamin Herrenschmidt * 956f8154fd2SBenjamin Herrenschmidt * It generally means a discrepancy between the wakup conditions in the 957f8154fd2SBenjamin Herrenschmidt * processor has_work implementation and the logic in this function. 958f8154fd2SBenjamin Herrenschmidt */ 959db70b311SRichard Henderson cpu_abort(env_cpu(env), 960f8154fd2SBenjamin Herrenschmidt "Wakeup from PM state but interrupt Undelivered"); 961f8154fd2SBenjamin Herrenschmidt } 962c79c73f6SBlue Swirl } 96334316482SAlexey Kardashevskiy 96434316482SAlexey Kardashevskiy void ppc_cpu_do_system_reset(CPUState *cs) 96534316482SAlexey Kardashevskiy { 96634316482SAlexey Kardashevskiy PowerPCCPU *cpu = POWERPC_CPU(cs); 96734316482SAlexey Kardashevskiy CPUPPCState *env = &cpu->env; 96834316482SAlexey Kardashevskiy 96934316482SAlexey Kardashevskiy powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_RESET); 97034316482SAlexey Kardashevskiy } 971*ad77c6caSNicholas Piggin 972*ad77c6caSNicholas Piggin void ppc_cpu_do_fwnmi_machine_check(CPUState *cs, target_ulong vector) 973*ad77c6caSNicholas Piggin { 974*ad77c6caSNicholas Piggin PowerPCCPU *cpu = POWERPC_CPU(cs); 975*ad77c6caSNicholas Piggin CPUPPCState *env = &cpu->env; 976*ad77c6caSNicholas Piggin PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu); 977*ad77c6caSNicholas Piggin target_ulong msr = 0; 978*ad77c6caSNicholas Piggin 979*ad77c6caSNicholas Piggin /* 980*ad77c6caSNicholas Piggin * Set MSR and NIP for the handler, SRR0/1, DAR and DSISR have already 981*ad77c6caSNicholas Piggin * been set by KVM. 982*ad77c6caSNicholas Piggin */ 983*ad77c6caSNicholas Piggin msr = (1ULL << MSR_ME); 984*ad77c6caSNicholas Piggin msr |= env->msr & (1ULL << MSR_SF); 985*ad77c6caSNicholas Piggin if (!(*pcc->interrupts_big_endian)(cpu)) { 986*ad77c6caSNicholas Piggin msr |= (1ULL << MSR_LE); 987*ad77c6caSNicholas Piggin } 988*ad77c6caSNicholas Piggin 989*ad77c6caSNicholas Piggin powerpc_set_excp_state(cpu, vector, msr); 990*ad77c6caSNicholas Piggin } 991c79c73f6SBlue Swirl #endif /* !CONFIG_USER_ONLY */ 992c79c73f6SBlue Swirl 993458dd766SRichard Henderson bool ppc_cpu_exec_interrupt(CPUState *cs, int interrupt_request) 994458dd766SRichard Henderson { 995458dd766SRichard Henderson PowerPCCPU *cpu = POWERPC_CPU(cs); 996458dd766SRichard Henderson CPUPPCState *env = &cpu->env; 997458dd766SRichard Henderson 998458dd766SRichard Henderson if (interrupt_request & CPU_INTERRUPT_HARD) { 999458dd766SRichard Henderson ppc_hw_interrupt(env); 1000458dd766SRichard Henderson if (env->pending_interrupts == 0) { 1001458dd766SRichard Henderson cs->interrupt_request &= ~CPU_INTERRUPT_HARD; 1002458dd766SRichard Henderson } 1003458dd766SRichard Henderson return true; 1004458dd766SRichard Henderson } 1005458dd766SRichard Henderson return false; 1006458dd766SRichard Henderson } 1007458dd766SRichard Henderson 1008c79c73f6SBlue Swirl #if defined(DEBUG_OP) 1009c79c73f6SBlue Swirl static void cpu_dump_rfi(target_ulong RA, target_ulong msr) 1010c79c73f6SBlue Swirl { 1011c79c73f6SBlue Swirl qemu_log("Return from exception at " TARGET_FMT_lx " with flags " 1012c79c73f6SBlue Swirl TARGET_FMT_lx "\n", RA, msr); 1013c79c73f6SBlue Swirl } 1014c79c73f6SBlue Swirl #endif 1015c79c73f6SBlue Swirl 1016ad71ed68SBlue Swirl /*****************************************************************************/ 1017ad71ed68SBlue Swirl /* Exceptions processing helpers */ 1018ad71ed68SBlue Swirl 1019db789c6cSBenjamin Herrenschmidt void raise_exception_err_ra(CPUPPCState *env, uint32_t exception, 1020db789c6cSBenjamin Herrenschmidt uint32_t error_code, uintptr_t raddr) 1021ad71ed68SBlue Swirl { 1022db70b311SRichard Henderson CPUState *cs = env_cpu(env); 102327103424SAndreas Färber 102427103424SAndreas Färber cs->exception_index = exception; 1025ad71ed68SBlue Swirl env->error_code = error_code; 1026db789c6cSBenjamin Herrenschmidt cpu_loop_exit_restore(cs, raddr); 1027db789c6cSBenjamin Herrenschmidt } 1028db789c6cSBenjamin Herrenschmidt 1029db789c6cSBenjamin Herrenschmidt void raise_exception_err(CPUPPCState *env, uint32_t exception, 1030db789c6cSBenjamin Herrenschmidt uint32_t error_code) 1031db789c6cSBenjamin Herrenschmidt { 1032db789c6cSBenjamin Herrenschmidt raise_exception_err_ra(env, exception, error_code, 0); 1033db789c6cSBenjamin Herrenschmidt } 1034db789c6cSBenjamin Herrenschmidt 1035db789c6cSBenjamin Herrenschmidt void raise_exception(CPUPPCState *env, uint32_t exception) 1036db789c6cSBenjamin Herrenschmidt { 1037db789c6cSBenjamin Herrenschmidt raise_exception_err_ra(env, exception, 0, 0); 1038db789c6cSBenjamin Herrenschmidt } 1039db789c6cSBenjamin Herrenschmidt 1040db789c6cSBenjamin Herrenschmidt void raise_exception_ra(CPUPPCState *env, uint32_t exception, 1041db789c6cSBenjamin Herrenschmidt uintptr_t raddr) 1042db789c6cSBenjamin Herrenschmidt { 1043db789c6cSBenjamin Herrenschmidt raise_exception_err_ra(env, exception, 0, raddr); 1044db789c6cSBenjamin Herrenschmidt } 1045db789c6cSBenjamin Herrenschmidt 1046db789c6cSBenjamin Herrenschmidt void helper_raise_exception_err(CPUPPCState *env, uint32_t exception, 1047db789c6cSBenjamin Herrenschmidt uint32_t error_code) 1048db789c6cSBenjamin Herrenschmidt { 1049db789c6cSBenjamin Herrenschmidt raise_exception_err_ra(env, exception, error_code, 0); 1050ad71ed68SBlue Swirl } 1051ad71ed68SBlue Swirl 1052e5f17ac6SBlue Swirl void helper_raise_exception(CPUPPCState *env, uint32_t exception) 1053ad71ed68SBlue Swirl { 1054db789c6cSBenjamin Herrenschmidt raise_exception_err_ra(env, exception, 0, 0); 1055ad71ed68SBlue Swirl } 1056ad71ed68SBlue Swirl 1057ad71ed68SBlue Swirl #if !defined(CONFIG_USER_ONLY) 1058e5f17ac6SBlue Swirl void helper_store_msr(CPUPPCState *env, target_ulong val) 1059ad71ed68SBlue Swirl { 1060db789c6cSBenjamin Herrenschmidt uint32_t excp = hreg_store_msr(env, val, 0); 1061259186a7SAndreas Färber 1062db789c6cSBenjamin Herrenschmidt if (excp != 0) { 1063db70b311SRichard Henderson CPUState *cs = env_cpu(env); 1064044897efSRichard Purdie cpu_interrupt_exittb(cs); 1065db789c6cSBenjamin Herrenschmidt raise_exception(env, excp); 1066ad71ed68SBlue Swirl } 1067ad71ed68SBlue Swirl } 1068ad71ed68SBlue Swirl 10697778a575SBenjamin Herrenschmidt #if defined(TARGET_PPC64) 10707778a575SBenjamin Herrenschmidt void helper_pminsn(CPUPPCState *env, powerpc_pm_insn_t insn) 10717778a575SBenjamin Herrenschmidt { 10727778a575SBenjamin Herrenschmidt CPUState *cs; 10737778a575SBenjamin Herrenschmidt 1074db70b311SRichard Henderson cs = env_cpu(env); 10757778a575SBenjamin Herrenschmidt cs->halted = 1; 10767778a575SBenjamin Herrenschmidt 107747733729SDavid Gibson /* 107847733729SDavid Gibson * The architecture specifies that HDEC interrupts are discarded 107947733729SDavid Gibson * in PM states 10804b236b62SBenjamin Herrenschmidt */ 10814b236b62SBenjamin Herrenschmidt env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR); 10824b236b62SBenjamin Herrenschmidt 10833621e2c9SBenjamin Herrenschmidt /* Condition for waking up at 0x100 */ 10841e7fd61dSBenjamin Herrenschmidt env->resume_as_sreset = (insn != PPC_PM_STOP) || 108521c0d66aSBenjamin Herrenschmidt (env->spr[SPR_PSSCR] & PSSCR_EC); 10867778a575SBenjamin Herrenschmidt } 10877778a575SBenjamin Herrenschmidt #endif /* defined(TARGET_PPC64) */ 10887778a575SBenjamin Herrenschmidt 1089a2e71b28SBenjamin Herrenschmidt static inline void do_rfi(CPUPPCState *env, target_ulong nip, target_ulong msr) 1090ad71ed68SBlue Swirl { 1091db70b311SRichard Henderson CPUState *cs = env_cpu(env); 1092259186a7SAndreas Färber 1093a2e71b28SBenjamin Herrenschmidt /* MSR:POW cannot be set by any form of rfi */ 1094a2e71b28SBenjamin Herrenschmidt msr &= ~(1ULL << MSR_POW); 1095a2e71b28SBenjamin Herrenschmidt 1096ad71ed68SBlue Swirl #if defined(TARGET_PPC64) 1097a2e71b28SBenjamin Herrenschmidt /* Switching to 32-bit ? Crop the nip */ 1098a2e71b28SBenjamin Herrenschmidt if (!msr_is_64bit(env, msr)) { 1099ad71ed68SBlue Swirl nip = (uint32_t)nip; 1100ad71ed68SBlue Swirl } 1101ad71ed68SBlue Swirl #else 1102ad71ed68SBlue Swirl nip = (uint32_t)nip; 1103ad71ed68SBlue Swirl #endif 1104ad71ed68SBlue Swirl /* XXX: beware: this is false if VLE is supported */ 1105ad71ed68SBlue Swirl env->nip = nip & ~((target_ulong)0x00000003); 1106ad71ed68SBlue Swirl hreg_store_msr(env, msr, 1); 1107ad71ed68SBlue Swirl #if defined(DEBUG_OP) 1108ad71ed68SBlue Swirl cpu_dump_rfi(env->nip, env->msr); 1109ad71ed68SBlue Swirl #endif 111047733729SDavid Gibson /* 111147733729SDavid Gibson * No need to raise an exception here, as rfi is always the last 111247733729SDavid Gibson * insn of a TB 1113ad71ed68SBlue Swirl */ 1114044897efSRichard Purdie cpu_interrupt_exittb(cs); 1115a8b73734SNikunj A Dadhania /* Reset the reservation */ 1116a8b73734SNikunj A Dadhania env->reserve_addr = -1; 1117a8b73734SNikunj A Dadhania 1118cd0c6f47SBenjamin Herrenschmidt /* Context synchronizing: check if TCG TLB needs flush */ 1119e3cffe6fSNikunj A Dadhania check_tlb_flush(env, false); 1120ad71ed68SBlue Swirl } 1121ad71ed68SBlue Swirl 1122e5f17ac6SBlue Swirl void helper_rfi(CPUPPCState *env) 1123ad71ed68SBlue Swirl { 1124a2e71b28SBenjamin Herrenschmidt do_rfi(env, env->spr[SPR_SRR0], env->spr[SPR_SRR1] & 0xfffffffful); 1125a1bb7384SScott Wood } 1126ad71ed68SBlue Swirl 1127a2e71b28SBenjamin Herrenschmidt #define MSR_BOOK3S_MASK 1128ad71ed68SBlue Swirl #if defined(TARGET_PPC64) 1129e5f17ac6SBlue Swirl void helper_rfid(CPUPPCState *env) 1130ad71ed68SBlue Swirl { 113147733729SDavid Gibson /* 113247733729SDavid Gibson * The architeture defines a number of rules for which bits can 113347733729SDavid Gibson * change but in practice, we handle this in hreg_store_msr() 1134a2e71b28SBenjamin Herrenschmidt * which will be called by do_rfi(), so there is no need to filter 1135a2e71b28SBenjamin Herrenschmidt * here 1136a2e71b28SBenjamin Herrenschmidt */ 1137a2e71b28SBenjamin Herrenschmidt do_rfi(env, env->spr[SPR_SRR0], env->spr[SPR_SRR1]); 1138ad71ed68SBlue Swirl } 1139ad71ed68SBlue Swirl 1140e5f17ac6SBlue Swirl void helper_hrfid(CPUPPCState *env) 1141ad71ed68SBlue Swirl { 1142a2e71b28SBenjamin Herrenschmidt do_rfi(env, env->spr[SPR_HSRR0], env->spr[SPR_HSRR1]); 1143ad71ed68SBlue Swirl } 1144ad71ed68SBlue Swirl #endif 1145ad71ed68SBlue Swirl 1146ad71ed68SBlue Swirl /*****************************************************************************/ 1147ad71ed68SBlue Swirl /* Embedded PowerPC specific helpers */ 1148e5f17ac6SBlue Swirl void helper_40x_rfci(CPUPPCState *env) 1149ad71ed68SBlue Swirl { 1150a2e71b28SBenjamin Herrenschmidt do_rfi(env, env->spr[SPR_40x_SRR2], env->spr[SPR_40x_SRR3]); 1151ad71ed68SBlue Swirl } 1152ad71ed68SBlue Swirl 1153e5f17ac6SBlue Swirl void helper_rfci(CPUPPCState *env) 1154ad71ed68SBlue Swirl { 1155a2e71b28SBenjamin Herrenschmidt do_rfi(env, env->spr[SPR_BOOKE_CSRR0], env->spr[SPR_BOOKE_CSRR1]); 1156ad71ed68SBlue Swirl } 1157ad71ed68SBlue Swirl 1158e5f17ac6SBlue Swirl void helper_rfdi(CPUPPCState *env) 1159ad71ed68SBlue Swirl { 1160a1bb7384SScott Wood /* FIXME: choose CSRR1 or DSRR1 based on cpu type */ 1161a2e71b28SBenjamin Herrenschmidt do_rfi(env, env->spr[SPR_BOOKE_DSRR0], env->spr[SPR_BOOKE_DSRR1]); 1162ad71ed68SBlue Swirl } 1163ad71ed68SBlue Swirl 1164e5f17ac6SBlue Swirl void helper_rfmci(CPUPPCState *env) 1165ad71ed68SBlue Swirl { 1166a1bb7384SScott Wood /* FIXME: choose CSRR1 or MCSRR1 based on cpu type */ 1167a2e71b28SBenjamin Herrenschmidt do_rfi(env, env->spr[SPR_BOOKE_MCSRR0], env->spr[SPR_BOOKE_MCSRR1]); 1168ad71ed68SBlue Swirl } 1169ad71ed68SBlue Swirl #endif 1170ad71ed68SBlue Swirl 1171e5f17ac6SBlue Swirl void helper_tw(CPUPPCState *env, target_ulong arg1, target_ulong arg2, 1172e5f17ac6SBlue Swirl uint32_t flags) 1173ad71ed68SBlue Swirl { 1174ad71ed68SBlue Swirl if (!likely(!(((int32_t)arg1 < (int32_t)arg2 && (flags & 0x10)) || 1175ad71ed68SBlue Swirl ((int32_t)arg1 > (int32_t)arg2 && (flags & 0x08)) || 1176ad71ed68SBlue Swirl ((int32_t)arg1 == (int32_t)arg2 && (flags & 0x04)) || 1177ad71ed68SBlue Swirl ((uint32_t)arg1 < (uint32_t)arg2 && (flags & 0x02)) || 1178ad71ed68SBlue Swirl ((uint32_t)arg1 > (uint32_t)arg2 && (flags & 0x01))))) { 117972073dccSBenjamin Herrenschmidt raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM, 118072073dccSBenjamin Herrenschmidt POWERPC_EXCP_TRAP, GETPC()); 1181ad71ed68SBlue Swirl } 1182ad71ed68SBlue Swirl } 1183ad71ed68SBlue Swirl 1184ad71ed68SBlue Swirl #if defined(TARGET_PPC64) 1185e5f17ac6SBlue Swirl void helper_td(CPUPPCState *env, target_ulong arg1, target_ulong arg2, 1186e5f17ac6SBlue Swirl uint32_t flags) 1187ad71ed68SBlue Swirl { 1188ad71ed68SBlue Swirl if (!likely(!(((int64_t)arg1 < (int64_t)arg2 && (flags & 0x10)) || 1189ad71ed68SBlue Swirl ((int64_t)arg1 > (int64_t)arg2 && (flags & 0x08)) || 1190ad71ed68SBlue Swirl ((int64_t)arg1 == (int64_t)arg2 && (flags & 0x04)) || 1191ad71ed68SBlue Swirl ((uint64_t)arg1 < (uint64_t)arg2 && (flags & 0x02)) || 1192ad71ed68SBlue Swirl ((uint64_t)arg1 > (uint64_t)arg2 && (flags & 0x01))))) { 119372073dccSBenjamin Herrenschmidt raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM, 119472073dccSBenjamin Herrenschmidt POWERPC_EXCP_TRAP, GETPC()); 1195ad71ed68SBlue Swirl } 1196ad71ed68SBlue Swirl } 1197ad71ed68SBlue Swirl #endif 1198ad71ed68SBlue Swirl 1199ad71ed68SBlue Swirl #if !defined(CONFIG_USER_ONLY) 1200ad71ed68SBlue Swirl /*****************************************************************************/ 1201ad71ed68SBlue Swirl /* PowerPC 601 specific instructions (POWER bridge) */ 1202ad71ed68SBlue Swirl 1203e5f17ac6SBlue Swirl void helper_rfsvc(CPUPPCState *env) 1204ad71ed68SBlue Swirl { 1205a2e71b28SBenjamin Herrenschmidt do_rfi(env, env->lr, env->ctr & 0x0000FFFF); 1206ad71ed68SBlue Swirl } 1207ad71ed68SBlue Swirl 1208ad71ed68SBlue Swirl /* Embedded.Processor Control */ 1209ad71ed68SBlue Swirl static int dbell2irq(target_ulong rb) 1210ad71ed68SBlue Swirl { 1211ad71ed68SBlue Swirl int msg = rb & DBELL_TYPE_MASK; 1212ad71ed68SBlue Swirl int irq = -1; 1213ad71ed68SBlue Swirl 1214ad71ed68SBlue Swirl switch (msg) { 1215ad71ed68SBlue Swirl case DBELL_TYPE_DBELL: 1216ad71ed68SBlue Swirl irq = PPC_INTERRUPT_DOORBELL; 1217ad71ed68SBlue Swirl break; 1218ad71ed68SBlue Swirl case DBELL_TYPE_DBELL_CRIT: 1219ad71ed68SBlue Swirl irq = PPC_INTERRUPT_CDOORBELL; 1220ad71ed68SBlue Swirl break; 1221ad71ed68SBlue Swirl case DBELL_TYPE_G_DBELL: 1222ad71ed68SBlue Swirl case DBELL_TYPE_G_DBELL_CRIT: 1223ad71ed68SBlue Swirl case DBELL_TYPE_G_DBELL_MC: 1224ad71ed68SBlue Swirl /* XXX implement */ 1225ad71ed68SBlue Swirl default: 1226ad71ed68SBlue Swirl break; 1227ad71ed68SBlue Swirl } 1228ad71ed68SBlue Swirl 1229ad71ed68SBlue Swirl return irq; 1230ad71ed68SBlue Swirl } 1231ad71ed68SBlue Swirl 1232e5f17ac6SBlue Swirl void helper_msgclr(CPUPPCState *env, target_ulong rb) 1233ad71ed68SBlue Swirl { 1234ad71ed68SBlue Swirl int irq = dbell2irq(rb); 1235ad71ed68SBlue Swirl 1236ad71ed68SBlue Swirl if (irq < 0) { 1237ad71ed68SBlue Swirl return; 1238ad71ed68SBlue Swirl } 1239ad71ed68SBlue Swirl 1240ad71ed68SBlue Swirl env->pending_interrupts &= ~(1 << irq); 1241ad71ed68SBlue Swirl } 1242ad71ed68SBlue Swirl 1243ad71ed68SBlue Swirl void helper_msgsnd(target_ulong rb) 1244ad71ed68SBlue Swirl { 1245ad71ed68SBlue Swirl int irq = dbell2irq(rb); 1246ad71ed68SBlue Swirl int pir = rb & DBELL_PIRTAG_MASK; 1247182735efSAndreas Färber CPUState *cs; 1248ad71ed68SBlue Swirl 1249ad71ed68SBlue Swirl if (irq < 0) { 1250ad71ed68SBlue Swirl return; 1251ad71ed68SBlue Swirl } 1252ad71ed68SBlue Swirl 1253f1c29ebcSThomas Huth qemu_mutex_lock_iothread(); 1254bdc44640SAndreas Färber CPU_FOREACH(cs) { 1255182735efSAndreas Färber PowerPCCPU *cpu = POWERPC_CPU(cs); 1256182735efSAndreas Färber CPUPPCState *cenv = &cpu->env; 1257182735efSAndreas Färber 1258ad71ed68SBlue Swirl if ((rb & DBELL_BRDCAST) || (cenv->spr[SPR_BOOKE_PIR] == pir)) { 1259ad71ed68SBlue Swirl cenv->pending_interrupts |= 1 << irq; 1260182735efSAndreas Färber cpu_interrupt(cs, CPU_INTERRUPT_HARD); 1261ad71ed68SBlue Swirl } 1262ad71ed68SBlue Swirl } 1263f1c29ebcSThomas Huth qemu_mutex_unlock_iothread(); 1264ad71ed68SBlue Swirl } 12657af1e7b0SCédric Le Goater 12667af1e7b0SCédric Le Goater /* Server Processor Control */ 12677af1e7b0SCédric Le Goater 12685ba7ba1dSCédric Le Goater static bool dbell_type_server(target_ulong rb) 12695ba7ba1dSCédric Le Goater { 127047733729SDavid Gibson /* 127147733729SDavid Gibson * A Directed Hypervisor Doorbell message is sent only if the 12727af1e7b0SCédric Le Goater * message type is 5. All other types are reserved and the 127347733729SDavid Gibson * instruction is a no-op 127447733729SDavid Gibson */ 12755ba7ba1dSCédric Le Goater return (rb & DBELL_TYPE_MASK) == DBELL_TYPE_DBELL_SERVER; 12767af1e7b0SCédric Le Goater } 12777af1e7b0SCédric Le Goater 12787af1e7b0SCédric Le Goater void helper_book3s_msgclr(CPUPPCState *env, target_ulong rb) 12797af1e7b0SCédric Le Goater { 12805ba7ba1dSCédric Le Goater if (!dbell_type_server(rb)) { 12817af1e7b0SCédric Le Goater return; 12827af1e7b0SCédric Le Goater } 12837af1e7b0SCédric Le Goater 12845ba7ba1dSCédric Le Goater env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDOORBELL); 12857af1e7b0SCédric Le Goater } 12867af1e7b0SCédric Le Goater 12875ba7ba1dSCédric Le Goater static void book3s_msgsnd_common(int pir, int irq) 12887af1e7b0SCédric Le Goater { 12897af1e7b0SCédric Le Goater CPUState *cs; 12907af1e7b0SCédric Le Goater 12917af1e7b0SCédric Le Goater qemu_mutex_lock_iothread(); 12927af1e7b0SCédric Le Goater CPU_FOREACH(cs) { 12937af1e7b0SCédric Le Goater PowerPCCPU *cpu = POWERPC_CPU(cs); 12947af1e7b0SCédric Le Goater CPUPPCState *cenv = &cpu->env; 12957af1e7b0SCédric Le Goater 12967af1e7b0SCédric Le Goater /* TODO: broadcast message to all threads of the same processor */ 12977af1e7b0SCédric Le Goater if (cenv->spr_cb[SPR_PIR].default_value == pir) { 12987af1e7b0SCédric Le Goater cenv->pending_interrupts |= 1 << irq; 12997af1e7b0SCédric Le Goater cpu_interrupt(cs, CPU_INTERRUPT_HARD); 13007af1e7b0SCédric Le Goater } 13017af1e7b0SCédric Le Goater } 13027af1e7b0SCédric Le Goater qemu_mutex_unlock_iothread(); 13037af1e7b0SCédric Le Goater } 13045ba7ba1dSCédric Le Goater 13055ba7ba1dSCédric Le Goater void helper_book3s_msgsnd(target_ulong rb) 13065ba7ba1dSCédric Le Goater { 13075ba7ba1dSCédric Le Goater int pir = rb & DBELL_PROCIDTAG_MASK; 13085ba7ba1dSCédric Le Goater 13095ba7ba1dSCédric Le Goater if (!dbell_type_server(rb)) { 13105ba7ba1dSCédric Le Goater return; 13115ba7ba1dSCédric Le Goater } 13125ba7ba1dSCédric Le Goater 13135ba7ba1dSCédric Le Goater book3s_msgsnd_common(pir, PPC_INTERRUPT_HDOORBELL); 13145ba7ba1dSCédric Le Goater } 13155ba7ba1dSCédric Le Goater 13165ba7ba1dSCédric Le Goater #if defined(TARGET_PPC64) 13175ba7ba1dSCédric Le Goater void helper_book3s_msgclrp(CPUPPCState *env, target_ulong rb) 13185ba7ba1dSCédric Le Goater { 1319493028d8SCédric Le Goater helper_hfscr_facility_check(env, HFSCR_MSGP, "msgclrp", HFSCR_IC_MSGP); 1320493028d8SCédric Le Goater 13215ba7ba1dSCédric Le Goater if (!dbell_type_server(rb)) { 13225ba7ba1dSCédric Le Goater return; 13235ba7ba1dSCédric Le Goater } 13245ba7ba1dSCédric Le Goater 13255ba7ba1dSCédric Le Goater env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DOORBELL); 13265ba7ba1dSCédric Le Goater } 13275ba7ba1dSCédric Le Goater 13285ba7ba1dSCédric Le Goater /* 13295ba7ba1dSCédric Le Goater * sends a message to other threads that are on the same 13305ba7ba1dSCédric Le Goater * multi-threaded processor 13315ba7ba1dSCédric Le Goater */ 13325ba7ba1dSCédric Le Goater void helper_book3s_msgsndp(CPUPPCState *env, target_ulong rb) 13335ba7ba1dSCédric Le Goater { 13345ba7ba1dSCédric Le Goater int pir = env->spr_cb[SPR_PIR].default_value; 13355ba7ba1dSCédric Le Goater 1336493028d8SCédric Le Goater helper_hfscr_facility_check(env, HFSCR_MSGP, "msgsndp", HFSCR_IC_MSGP); 1337493028d8SCédric Le Goater 13385ba7ba1dSCédric Le Goater if (!dbell_type_server(rb)) { 13395ba7ba1dSCédric Le Goater return; 13405ba7ba1dSCédric Le Goater } 13415ba7ba1dSCédric Le Goater 13425ba7ba1dSCédric Le Goater /* TODO: TCG supports only one thread */ 13435ba7ba1dSCédric Le Goater 13445ba7ba1dSCédric Le Goater book3s_msgsnd_common(pir, PPC_INTERRUPT_DOORBELL); 13455ba7ba1dSCédric Le Goater } 13465ba7ba1dSCédric Le Goater #endif 1347ad71ed68SBlue Swirl #endif 13480f3110faSRichard Henderson 13490f3110faSRichard Henderson void ppc_cpu_do_unaligned_access(CPUState *cs, vaddr vaddr, 13500f3110faSRichard Henderson MMUAccessType access_type, 13510f3110faSRichard Henderson int mmu_idx, uintptr_t retaddr) 13520f3110faSRichard Henderson { 13530f3110faSRichard Henderson CPUPPCState *env = cs->env_ptr; 13540f3110faSRichard Henderson uint32_t insn; 13550f3110faSRichard Henderson 13560f3110faSRichard Henderson /* Restore state and reload the insn we executed, for filling in DSISR. */ 13570f3110faSRichard Henderson cpu_restore_state(cs, retaddr, true); 13580f3110faSRichard Henderson insn = cpu_ldl_code(env, env->nip); 13590f3110faSRichard Henderson 13600f3110faSRichard Henderson cs->exception_index = POWERPC_EXCP_ALIGN; 13610f3110faSRichard Henderson env->error_code = insn & 0x03FF0000; 13620f3110faSRichard Henderson cpu_loop_exit(cs); 13630f3110faSRichard Henderson } 1364