10fc76338SPhilippe Mathieu-Daudé /*
20fc76338SPhilippe Mathieu-Daudé * PowerPC exception emulation helpers for QEMU (TCG specific)
30fc76338SPhilippe Mathieu-Daudé *
40fc76338SPhilippe Mathieu-Daudé * Copyright (c) 2003-2007 Jocelyn Mayer
50fc76338SPhilippe Mathieu-Daudé *
60fc76338SPhilippe Mathieu-Daudé * This library is free software; you can redistribute it and/or
70fc76338SPhilippe Mathieu-Daudé * modify it under the terms of the GNU Lesser General Public
80fc76338SPhilippe Mathieu-Daudé * License as published by the Free Software Foundation; either
90fc76338SPhilippe Mathieu-Daudé * version 2.1 of the License, or (at your option) any later version.
100fc76338SPhilippe Mathieu-Daudé *
110fc76338SPhilippe Mathieu-Daudé * This library is distributed in the hope that it will be useful,
120fc76338SPhilippe Mathieu-Daudé * but WITHOUT ANY WARRANTY; without even the implied warranty of
130fc76338SPhilippe Mathieu-Daudé * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
140fc76338SPhilippe Mathieu-Daudé * Lesser General Public License for more details.
150fc76338SPhilippe Mathieu-Daudé *
160fc76338SPhilippe Mathieu-Daudé * You should have received a copy of the GNU Lesser General Public
170fc76338SPhilippe Mathieu-Daudé * License along with this library; if not, see <http://www.gnu.org/licenses/>.
180fc76338SPhilippe Mathieu-Daudé */
190fc76338SPhilippe Mathieu-Daudé #include "qemu/osdep.h"
20c2c68701SPhilippe Mathieu-Daudé #include "qemu/main-loop.h"
212f96c00bSPhilippe Mathieu-Daudé #include "qemu/log.h"
220fc76338SPhilippe Mathieu-Daudé #include "exec/cpu_ldst.h"
231d0b82f8SPhilippe Mathieu-Daudé #include "exec/exec-all.h"
241d0b82f8SPhilippe Mathieu-Daudé #include "exec/helper-proto.h"
252f96c00bSPhilippe Mathieu-Daudé #include "system/runstate.h"
260fc76338SPhilippe Mathieu-Daudé
271d0b82f8SPhilippe Mathieu-Daudé #include "helper_regs.h"
280fc76338SPhilippe Mathieu-Daudé #include "hw/ppc/ppc.h"
290fc76338SPhilippe Mathieu-Daudé #include "internal.h"
300fc76338SPhilippe Mathieu-Daudé #include "cpu.h"
310fc76338SPhilippe Mathieu-Daudé #include "trace.h"
320fc76338SPhilippe Mathieu-Daudé
331d0b82f8SPhilippe Mathieu-Daudé /*****************************************************************************/
341d0b82f8SPhilippe Mathieu-Daudé /* Exceptions processing helpers */
351d0b82f8SPhilippe Mathieu-Daudé
raise_exception_err_ra(CPUPPCState * env,uint32_t exception,uint32_t error_code,uintptr_t raddr)361d0b82f8SPhilippe Mathieu-Daudé void raise_exception_err_ra(CPUPPCState *env, uint32_t exception,
371d0b82f8SPhilippe Mathieu-Daudé uint32_t error_code, uintptr_t raddr)
381d0b82f8SPhilippe Mathieu-Daudé {
391d0b82f8SPhilippe Mathieu-Daudé CPUState *cs = env_cpu(env);
401d0b82f8SPhilippe Mathieu-Daudé
411d0b82f8SPhilippe Mathieu-Daudé cs->exception_index = exception;
421d0b82f8SPhilippe Mathieu-Daudé env->error_code = error_code;
431d0b82f8SPhilippe Mathieu-Daudé cpu_loop_exit_restore(cs, raddr);
441d0b82f8SPhilippe Mathieu-Daudé }
451d0b82f8SPhilippe Mathieu-Daudé
helper_raise_exception_err(CPUPPCState * env,uint32_t exception,uint32_t error_code)461d0b82f8SPhilippe Mathieu-Daudé void helper_raise_exception_err(CPUPPCState *env, uint32_t exception,
471d0b82f8SPhilippe Mathieu-Daudé uint32_t error_code)
481d0b82f8SPhilippe Mathieu-Daudé {
491d0b82f8SPhilippe Mathieu-Daudé raise_exception_err_ra(env, exception, error_code, 0);
501d0b82f8SPhilippe Mathieu-Daudé }
511d0b82f8SPhilippe Mathieu-Daudé
helper_raise_exception(CPUPPCState * env,uint32_t exception)521d0b82f8SPhilippe Mathieu-Daudé void helper_raise_exception(CPUPPCState *env, uint32_t exception)
531d0b82f8SPhilippe Mathieu-Daudé {
541d0b82f8SPhilippe Mathieu-Daudé raise_exception_err_ra(env, exception, 0, 0);
551d0b82f8SPhilippe Mathieu-Daudé }
561d0b82f8SPhilippe Mathieu-Daudé
570fc76338SPhilippe Mathieu-Daudé #ifndef CONFIG_USER_ONLY
580fc76338SPhilippe Mathieu-Daudé
raise_exception_err(CPUPPCState * env,uint32_t exception,uint32_t error_code)59c2c68701SPhilippe Mathieu-Daudé static G_NORETURN void raise_exception_err(CPUPPCState *env, uint32_t exception,
601d0b82f8SPhilippe Mathieu-Daudé uint32_t error_code)
611d0b82f8SPhilippe Mathieu-Daudé {
621d0b82f8SPhilippe Mathieu-Daudé raise_exception_err_ra(env, exception, error_code, 0);
631d0b82f8SPhilippe Mathieu-Daudé }
641d0b82f8SPhilippe Mathieu-Daudé
raise_exception(CPUPPCState * env,uint32_t exception)65c2c68701SPhilippe Mathieu-Daudé static G_NORETURN void raise_exception(CPUPPCState *env, uint32_t exception)
661d0b82f8SPhilippe Mathieu-Daudé {
671d0b82f8SPhilippe Mathieu-Daudé raise_exception_err_ra(env, exception, 0, 0);
681d0b82f8SPhilippe Mathieu-Daudé }
691d0b82f8SPhilippe Mathieu-Daudé
70ad8ad893SPhilippe Mathieu-Daudé #endif /* !CONFIG_USER_ONLY */
71ad8ad893SPhilippe Mathieu-Daudé
helper_TW(CPUPPCState * env,target_ulong arg1,target_ulong arg2,uint32_t flags)72ad8ad893SPhilippe Mathieu-Daudé void helper_TW(CPUPPCState *env, target_ulong arg1, target_ulong arg2,
73ad8ad893SPhilippe Mathieu-Daudé uint32_t flags)
74ad8ad893SPhilippe Mathieu-Daudé {
75ad8ad893SPhilippe Mathieu-Daudé if (!likely(!(((int32_t)arg1 < (int32_t)arg2 && (flags & 0x10)) ||
76ad8ad893SPhilippe Mathieu-Daudé ((int32_t)arg1 > (int32_t)arg2 && (flags & 0x08)) ||
77ad8ad893SPhilippe Mathieu-Daudé ((int32_t)arg1 == (int32_t)arg2 && (flags & 0x04)) ||
78ad8ad893SPhilippe Mathieu-Daudé ((uint32_t)arg1 < (uint32_t)arg2 && (flags & 0x02)) ||
79ad8ad893SPhilippe Mathieu-Daudé ((uint32_t)arg1 > (uint32_t)arg2 && (flags & 0x01))))) {
80ad8ad893SPhilippe Mathieu-Daudé raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
81ad8ad893SPhilippe Mathieu-Daudé POWERPC_EXCP_TRAP, GETPC());
82ad8ad893SPhilippe Mathieu-Daudé }
83ad8ad893SPhilippe Mathieu-Daudé }
84ad8ad893SPhilippe Mathieu-Daudé
85ad8ad893SPhilippe Mathieu-Daudé #ifdef TARGET_PPC64
helper_TD(CPUPPCState * env,target_ulong arg1,target_ulong arg2,uint32_t flags)86ad8ad893SPhilippe Mathieu-Daudé void helper_TD(CPUPPCState *env, target_ulong arg1, target_ulong arg2,
87ad8ad893SPhilippe Mathieu-Daudé uint32_t flags)
88ad8ad893SPhilippe Mathieu-Daudé {
89ad8ad893SPhilippe Mathieu-Daudé if (!likely(!(((int64_t)arg1 < (int64_t)arg2 && (flags & 0x10)) ||
90ad8ad893SPhilippe Mathieu-Daudé ((int64_t)arg1 > (int64_t)arg2 && (flags & 0x08)) ||
91ad8ad893SPhilippe Mathieu-Daudé ((int64_t)arg1 == (int64_t)arg2 && (flags & 0x04)) ||
92ad8ad893SPhilippe Mathieu-Daudé ((uint64_t)arg1 < (uint64_t)arg2 && (flags & 0x02)) ||
93ad8ad893SPhilippe Mathieu-Daudé ((uint64_t)arg1 > (uint64_t)arg2 && (flags & 0x01))))) {
94ad8ad893SPhilippe Mathieu-Daudé raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
95ad8ad893SPhilippe Mathieu-Daudé POWERPC_EXCP_TRAP, GETPC());
96ad8ad893SPhilippe Mathieu-Daudé }
97ad8ad893SPhilippe Mathieu-Daudé }
98ad8ad893SPhilippe Mathieu-Daudé #endif /* TARGET_PPC64 */
99ad8ad893SPhilippe Mathieu-Daudé
helper_SIMON_LIKE_32_64(uint32_t x,uint64_t key,uint32_t lane)100ad8ad893SPhilippe Mathieu-Daudé static uint32_t helper_SIMON_LIKE_32_64(uint32_t x, uint64_t key, uint32_t lane)
101ad8ad893SPhilippe Mathieu-Daudé {
102ad8ad893SPhilippe Mathieu-Daudé const uint16_t c = 0xfffc;
103ad8ad893SPhilippe Mathieu-Daudé const uint64_t z0 = 0xfa2561cdf44ac398ULL;
104ad8ad893SPhilippe Mathieu-Daudé uint16_t z = 0, temp;
105ad8ad893SPhilippe Mathieu-Daudé uint16_t k[32], eff_k[32], xleft[33], xright[33], fxleft[32];
106ad8ad893SPhilippe Mathieu-Daudé
107ad8ad893SPhilippe Mathieu-Daudé for (int i = 3; i >= 0; i--) {
108ad8ad893SPhilippe Mathieu-Daudé k[i] = key & 0xffff;
109ad8ad893SPhilippe Mathieu-Daudé key >>= 16;
110ad8ad893SPhilippe Mathieu-Daudé }
111ad8ad893SPhilippe Mathieu-Daudé xleft[0] = x & 0xffff;
112ad8ad893SPhilippe Mathieu-Daudé xright[0] = (x >> 16) & 0xffff;
113ad8ad893SPhilippe Mathieu-Daudé
114ad8ad893SPhilippe Mathieu-Daudé for (int i = 0; i < 28; i++) {
115ad8ad893SPhilippe Mathieu-Daudé z = (z0 >> (63 - i)) & 1;
116ad8ad893SPhilippe Mathieu-Daudé temp = ror16(k[i + 3], 3) ^ k[i + 1];
117ad8ad893SPhilippe Mathieu-Daudé k[i + 4] = c ^ z ^ k[i] ^ temp ^ ror16(temp, 1);
118ad8ad893SPhilippe Mathieu-Daudé }
119ad8ad893SPhilippe Mathieu-Daudé
120ad8ad893SPhilippe Mathieu-Daudé for (int i = 0; i < 8; i++) {
121ad8ad893SPhilippe Mathieu-Daudé eff_k[4 * i + 0] = k[4 * i + ((0 + lane) % 4)];
122ad8ad893SPhilippe Mathieu-Daudé eff_k[4 * i + 1] = k[4 * i + ((1 + lane) % 4)];
123ad8ad893SPhilippe Mathieu-Daudé eff_k[4 * i + 2] = k[4 * i + ((2 + lane) % 4)];
124ad8ad893SPhilippe Mathieu-Daudé eff_k[4 * i + 3] = k[4 * i + ((3 + lane) % 4)];
125ad8ad893SPhilippe Mathieu-Daudé }
126ad8ad893SPhilippe Mathieu-Daudé
127ad8ad893SPhilippe Mathieu-Daudé for (int i = 0; i < 32; i++) {
128ad8ad893SPhilippe Mathieu-Daudé fxleft[i] = (rol16(xleft[i], 1) &
129ad8ad893SPhilippe Mathieu-Daudé rol16(xleft[i], 8)) ^ rol16(xleft[i], 2);
130ad8ad893SPhilippe Mathieu-Daudé xleft[i + 1] = xright[i] ^ fxleft[i] ^ eff_k[i];
131ad8ad893SPhilippe Mathieu-Daudé xright[i + 1] = xleft[i];
132ad8ad893SPhilippe Mathieu-Daudé }
133ad8ad893SPhilippe Mathieu-Daudé
134ad8ad893SPhilippe Mathieu-Daudé return (((uint32_t)xright[32]) << 16) | xleft[32];
135ad8ad893SPhilippe Mathieu-Daudé }
136ad8ad893SPhilippe Mathieu-Daudé
hash_digest(uint64_t ra,uint64_t rb,uint64_t key)137ad8ad893SPhilippe Mathieu-Daudé static uint64_t hash_digest(uint64_t ra, uint64_t rb, uint64_t key)
138ad8ad893SPhilippe Mathieu-Daudé {
139ad8ad893SPhilippe Mathieu-Daudé uint64_t stage0_h = 0ULL, stage0_l = 0ULL;
140ad8ad893SPhilippe Mathieu-Daudé uint64_t stage1_h, stage1_l;
141ad8ad893SPhilippe Mathieu-Daudé
142ad8ad893SPhilippe Mathieu-Daudé for (int i = 0; i < 4; i++) {
143ad8ad893SPhilippe Mathieu-Daudé stage0_h |= ror64(rb & 0xff, 8 * (2 * i + 1));
144ad8ad893SPhilippe Mathieu-Daudé stage0_h |= ((ra >> 32) & 0xff) << (8 * 2 * i);
145ad8ad893SPhilippe Mathieu-Daudé stage0_l |= ror64((rb >> 32) & 0xff, 8 * (2 * i + 1));
146ad8ad893SPhilippe Mathieu-Daudé stage0_l |= (ra & 0xff) << (8 * 2 * i);
147ad8ad893SPhilippe Mathieu-Daudé rb >>= 8;
148ad8ad893SPhilippe Mathieu-Daudé ra >>= 8;
149ad8ad893SPhilippe Mathieu-Daudé }
150ad8ad893SPhilippe Mathieu-Daudé
151ad8ad893SPhilippe Mathieu-Daudé stage1_h = (uint64_t)helper_SIMON_LIKE_32_64(stage0_h >> 32, key, 0) << 32;
152ad8ad893SPhilippe Mathieu-Daudé stage1_h |= helper_SIMON_LIKE_32_64(stage0_h, key, 1);
153ad8ad893SPhilippe Mathieu-Daudé stage1_l = (uint64_t)helper_SIMON_LIKE_32_64(stage0_l >> 32, key, 2) << 32;
154ad8ad893SPhilippe Mathieu-Daudé stage1_l |= helper_SIMON_LIKE_32_64(stage0_l, key, 3);
155ad8ad893SPhilippe Mathieu-Daudé
156ad8ad893SPhilippe Mathieu-Daudé return stage1_h ^ stage1_l;
157ad8ad893SPhilippe Mathieu-Daudé }
158ad8ad893SPhilippe Mathieu-Daudé
do_hash(CPUPPCState * env,target_ulong ea,target_ulong ra,target_ulong rb,uint64_t key,bool store)159ad8ad893SPhilippe Mathieu-Daudé static void do_hash(CPUPPCState *env, target_ulong ea, target_ulong ra,
160ad8ad893SPhilippe Mathieu-Daudé target_ulong rb, uint64_t key, bool store)
161ad8ad893SPhilippe Mathieu-Daudé {
162ad8ad893SPhilippe Mathieu-Daudé uint64_t calculated_hash = hash_digest(ra, rb, key), loaded_hash;
163ad8ad893SPhilippe Mathieu-Daudé
164ad8ad893SPhilippe Mathieu-Daudé if (store) {
165ad8ad893SPhilippe Mathieu-Daudé cpu_stq_data_ra(env, ea, calculated_hash, GETPC());
166ad8ad893SPhilippe Mathieu-Daudé } else {
167ad8ad893SPhilippe Mathieu-Daudé loaded_hash = cpu_ldq_data_ra(env, ea, GETPC());
168ad8ad893SPhilippe Mathieu-Daudé if (loaded_hash != calculated_hash) {
169ad8ad893SPhilippe Mathieu-Daudé raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
170ad8ad893SPhilippe Mathieu-Daudé POWERPC_EXCP_TRAP, GETPC());
171ad8ad893SPhilippe Mathieu-Daudé }
172ad8ad893SPhilippe Mathieu-Daudé }
173ad8ad893SPhilippe Mathieu-Daudé }
174ad8ad893SPhilippe Mathieu-Daudé
175ad8ad893SPhilippe Mathieu-Daudé #include "qemu/guest-random.h"
176ad8ad893SPhilippe Mathieu-Daudé
177ad8ad893SPhilippe Mathieu-Daudé #ifdef TARGET_PPC64
178ad8ad893SPhilippe Mathieu-Daudé #define HELPER_HASH(op, key, store, dexcr_aspect) \
179ad8ad893SPhilippe Mathieu-Daudé void helper_##op(CPUPPCState *env, target_ulong ea, target_ulong ra, \
180ad8ad893SPhilippe Mathieu-Daudé target_ulong rb) \
181ad8ad893SPhilippe Mathieu-Daudé { \
182ad8ad893SPhilippe Mathieu-Daudé if (env->msr & R_MSR_PR_MASK) { \
183ad8ad893SPhilippe Mathieu-Daudé if (!(env->spr[SPR_DEXCR] & R_DEXCR_PRO_##dexcr_aspect##_MASK || \
184ad8ad893SPhilippe Mathieu-Daudé env->spr[SPR_HDEXCR] & R_HDEXCR_ENF_##dexcr_aspect##_MASK)) \
185ad8ad893SPhilippe Mathieu-Daudé return; \
186ad8ad893SPhilippe Mathieu-Daudé } else if (!(env->msr & R_MSR_HV_MASK)) { \
187ad8ad893SPhilippe Mathieu-Daudé if (!(env->spr[SPR_DEXCR] & R_DEXCR_PNH_##dexcr_aspect##_MASK || \
188ad8ad893SPhilippe Mathieu-Daudé env->spr[SPR_HDEXCR] & R_HDEXCR_ENF_##dexcr_aspect##_MASK)) \
189ad8ad893SPhilippe Mathieu-Daudé return; \
190ad8ad893SPhilippe Mathieu-Daudé } else if (!(env->msr & R_MSR_S_MASK)) { \
191ad8ad893SPhilippe Mathieu-Daudé if (!(env->spr[SPR_HDEXCR] & R_HDEXCR_HNU_##dexcr_aspect##_MASK)) \
192ad8ad893SPhilippe Mathieu-Daudé return; \
193ad8ad893SPhilippe Mathieu-Daudé } \
194ad8ad893SPhilippe Mathieu-Daudé \
195ad8ad893SPhilippe Mathieu-Daudé do_hash(env, ea, ra, rb, key, store); \
196ad8ad893SPhilippe Mathieu-Daudé }
197ad8ad893SPhilippe Mathieu-Daudé #else
198ad8ad893SPhilippe Mathieu-Daudé #define HELPER_HASH(op, key, store, dexcr_aspect) \
199ad8ad893SPhilippe Mathieu-Daudé void helper_##op(CPUPPCState *env, target_ulong ea, target_ulong ra, \
200ad8ad893SPhilippe Mathieu-Daudé target_ulong rb) \
201ad8ad893SPhilippe Mathieu-Daudé { \
202ad8ad893SPhilippe Mathieu-Daudé do_hash(env, ea, ra, rb, key, store); \
203ad8ad893SPhilippe Mathieu-Daudé }
204ad8ad893SPhilippe Mathieu-Daudé #endif /* TARGET_PPC64 */
205ad8ad893SPhilippe Mathieu-Daudé
206ad8ad893SPhilippe Mathieu-Daudé HELPER_HASH(HASHST, env->spr[SPR_HASHKEYR], true, NPHIE)
207ad8ad893SPhilippe Mathieu-Daudé HELPER_HASH(HASHCHK, env->spr[SPR_HASHKEYR], false, NPHIE)
208ad8ad893SPhilippe Mathieu-Daudé HELPER_HASH(HASHSTP, env->spr[SPR_HASHPKEYR], true, PHIE)
209ad8ad893SPhilippe Mathieu-Daudé HELPER_HASH(HASHCHKP, env->spr[SPR_HASHPKEYR], false, PHIE)
210ad8ad893SPhilippe Mathieu-Daudé
211ad8ad893SPhilippe Mathieu-Daudé #ifndef CONFIG_USER_ONLY
212ad8ad893SPhilippe Mathieu-Daudé
ppc_cpu_do_unaligned_access(CPUState * cs,vaddr vaddr,MMUAccessType access_type,int mmu_idx,uintptr_t retaddr)2130fc76338SPhilippe Mathieu-Daudé void ppc_cpu_do_unaligned_access(CPUState *cs, vaddr vaddr,
2140fc76338SPhilippe Mathieu-Daudé MMUAccessType access_type,
2150fc76338SPhilippe Mathieu-Daudé int mmu_idx, uintptr_t retaddr)
2160fc76338SPhilippe Mathieu-Daudé {
2170fc76338SPhilippe Mathieu-Daudé CPUPPCState *env = cpu_env(cs);
2180fc76338SPhilippe Mathieu-Daudé uint32_t insn;
2190fc76338SPhilippe Mathieu-Daudé
2200fc76338SPhilippe Mathieu-Daudé /* Restore state and reload the insn we executed, for filling in DSISR. */
2210fc76338SPhilippe Mathieu-Daudé cpu_restore_state(cs, retaddr);
2220fc76338SPhilippe Mathieu-Daudé insn = ppc_ldl_code(env, env->nip);
2230fc76338SPhilippe Mathieu-Daudé
2240fc76338SPhilippe Mathieu-Daudé switch (env->mmu_model) {
2250fc76338SPhilippe Mathieu-Daudé case POWERPC_MMU_SOFT_4xx:
2260fc76338SPhilippe Mathieu-Daudé env->spr[SPR_40x_DEAR] = vaddr;
2270fc76338SPhilippe Mathieu-Daudé break;
2280fc76338SPhilippe Mathieu-Daudé case POWERPC_MMU_BOOKE:
2290fc76338SPhilippe Mathieu-Daudé case POWERPC_MMU_BOOKE206:
2300fc76338SPhilippe Mathieu-Daudé env->spr[SPR_BOOKE_DEAR] = vaddr;
2310fc76338SPhilippe Mathieu-Daudé break;
2320fc76338SPhilippe Mathieu-Daudé default:
2330fc76338SPhilippe Mathieu-Daudé env->spr[SPR_DAR] = vaddr;
2340fc76338SPhilippe Mathieu-Daudé break;
2350fc76338SPhilippe Mathieu-Daudé }
2360fc76338SPhilippe Mathieu-Daudé
2370fc76338SPhilippe Mathieu-Daudé cs->exception_index = POWERPC_EXCP_ALIGN;
2380fc76338SPhilippe Mathieu-Daudé env->error_code = insn & 0x03FF0000;
2390fc76338SPhilippe Mathieu-Daudé cpu_loop_exit(cs);
2400fc76338SPhilippe Mathieu-Daudé }
2410fc76338SPhilippe Mathieu-Daudé
ppc_cpu_do_transaction_failed(CPUState * cs,hwaddr physaddr,vaddr vaddr,unsigned size,MMUAccessType access_type,int mmu_idx,MemTxAttrs attrs,MemTxResult response,uintptr_t retaddr)2420fc76338SPhilippe Mathieu-Daudé void ppc_cpu_do_transaction_failed(CPUState *cs, hwaddr physaddr,
2430fc76338SPhilippe Mathieu-Daudé vaddr vaddr, unsigned size,
2440fc76338SPhilippe Mathieu-Daudé MMUAccessType access_type,
2450fc76338SPhilippe Mathieu-Daudé int mmu_idx, MemTxAttrs attrs,
2460fc76338SPhilippe Mathieu-Daudé MemTxResult response, uintptr_t retaddr)
2470fc76338SPhilippe Mathieu-Daudé {
2480fc76338SPhilippe Mathieu-Daudé CPUPPCState *env = cpu_env(cs);
2490fc76338SPhilippe Mathieu-Daudé
2500fc76338SPhilippe Mathieu-Daudé switch (env->excp_model) {
2510fc76338SPhilippe Mathieu-Daudé #if defined(TARGET_PPC64)
2520fc76338SPhilippe Mathieu-Daudé case POWERPC_EXCP_POWER8:
2530fc76338SPhilippe Mathieu-Daudé case POWERPC_EXCP_POWER9:
2540fc76338SPhilippe Mathieu-Daudé case POWERPC_EXCP_POWER10:
2550fc76338SPhilippe Mathieu-Daudé case POWERPC_EXCP_POWER11:
2560fc76338SPhilippe Mathieu-Daudé /*
2570fc76338SPhilippe Mathieu-Daudé * Machine check codes can be found in processor User Manual or
2580fc76338SPhilippe Mathieu-Daudé * Linux or skiboot source.
2590fc76338SPhilippe Mathieu-Daudé */
2600fc76338SPhilippe Mathieu-Daudé if (access_type == MMU_DATA_LOAD) {
2610fc76338SPhilippe Mathieu-Daudé env->spr[SPR_DAR] = vaddr;
2620fc76338SPhilippe Mathieu-Daudé env->spr[SPR_DSISR] = PPC_BIT(57);
2630fc76338SPhilippe Mathieu-Daudé env->error_code = PPC_BIT(42);
2640fc76338SPhilippe Mathieu-Daudé
2650fc76338SPhilippe Mathieu-Daudé } else if (access_type == MMU_DATA_STORE) {
2660fc76338SPhilippe Mathieu-Daudé /*
2670fc76338SPhilippe Mathieu-Daudé * MCE for stores in POWER is asynchronous so hardware does
2680fc76338SPhilippe Mathieu-Daudé * not set DAR, but QEMU can do better.
2690fc76338SPhilippe Mathieu-Daudé */
2700fc76338SPhilippe Mathieu-Daudé env->spr[SPR_DAR] = vaddr;
2710fc76338SPhilippe Mathieu-Daudé env->error_code = PPC_BIT(36) | PPC_BIT(43) | PPC_BIT(45);
2720fc76338SPhilippe Mathieu-Daudé env->error_code |= PPC_BIT(42);
2730fc76338SPhilippe Mathieu-Daudé
2740fc76338SPhilippe Mathieu-Daudé } else { /* Fetch */
2750fc76338SPhilippe Mathieu-Daudé /*
2760fc76338SPhilippe Mathieu-Daudé * is_prefix_insn_excp() tests !PPC_BIT(42) to avoid fetching
2770fc76338SPhilippe Mathieu-Daudé * the instruction, so that must always be clear for fetches.
2780fc76338SPhilippe Mathieu-Daudé */
2790fc76338SPhilippe Mathieu-Daudé env->error_code = PPC_BIT(36) | PPC_BIT(44) | PPC_BIT(45);
2800fc76338SPhilippe Mathieu-Daudé }
2810fc76338SPhilippe Mathieu-Daudé break;
2820fc76338SPhilippe Mathieu-Daudé #endif
2830fc76338SPhilippe Mathieu-Daudé default:
2840fc76338SPhilippe Mathieu-Daudé /*
2850fc76338SPhilippe Mathieu-Daudé * TODO: Check behaviour for other CPUs, for now do nothing.
2860fc76338SPhilippe Mathieu-Daudé * Could add a basic MCE even if real hardware ignores.
2870fc76338SPhilippe Mathieu-Daudé */
2880fc76338SPhilippe Mathieu-Daudé return;
2890fc76338SPhilippe Mathieu-Daudé }
2900fc76338SPhilippe Mathieu-Daudé
2910fc76338SPhilippe Mathieu-Daudé cs->exception_index = POWERPC_EXCP_MCHECK;
2920fc76338SPhilippe Mathieu-Daudé cpu_loop_exit_restore(cs, retaddr);
2930fc76338SPhilippe Mathieu-Daudé }
2940fc76338SPhilippe Mathieu-Daudé
ppc_cpu_debug_excp_handler(CPUState * cs)2950fc76338SPhilippe Mathieu-Daudé void ppc_cpu_debug_excp_handler(CPUState *cs)
2960fc76338SPhilippe Mathieu-Daudé {
2970fc76338SPhilippe Mathieu-Daudé #if defined(TARGET_PPC64)
2980fc76338SPhilippe Mathieu-Daudé CPUPPCState *env = cpu_env(cs);
2990fc76338SPhilippe Mathieu-Daudé
3000fc76338SPhilippe Mathieu-Daudé if (env->insns_flags2 & PPC2_ISA207S) {
3010fc76338SPhilippe Mathieu-Daudé if (cs->watchpoint_hit) {
3020fc76338SPhilippe Mathieu-Daudé if (cs->watchpoint_hit->flags & BP_CPU) {
3030fc76338SPhilippe Mathieu-Daudé env->spr[SPR_DAR] = cs->watchpoint_hit->hitaddr;
3040fc76338SPhilippe Mathieu-Daudé env->spr[SPR_DSISR] = PPC_BIT(41);
3050fc76338SPhilippe Mathieu-Daudé cs->watchpoint_hit = NULL;
3060fc76338SPhilippe Mathieu-Daudé raise_exception(env, POWERPC_EXCP_DSI);
3070fc76338SPhilippe Mathieu-Daudé }
3080fc76338SPhilippe Mathieu-Daudé cs->watchpoint_hit = NULL;
3090fc76338SPhilippe Mathieu-Daudé } else if (cpu_breakpoint_test(cs, env->nip, BP_CPU)) {
3100fc76338SPhilippe Mathieu-Daudé raise_exception_err(env, POWERPC_EXCP_TRACE,
3110fc76338SPhilippe Mathieu-Daudé PPC_BIT(33) | PPC_BIT(43));
3120fc76338SPhilippe Mathieu-Daudé }
3130fc76338SPhilippe Mathieu-Daudé }
3140fc76338SPhilippe Mathieu-Daudé #endif
3150fc76338SPhilippe Mathieu-Daudé }
3160fc76338SPhilippe Mathieu-Daudé
ppc_cpu_debug_check_breakpoint(CPUState * cs)3170fc76338SPhilippe Mathieu-Daudé bool ppc_cpu_debug_check_breakpoint(CPUState *cs)
3180fc76338SPhilippe Mathieu-Daudé {
3190fc76338SPhilippe Mathieu-Daudé #if defined(TARGET_PPC64)
3200fc76338SPhilippe Mathieu-Daudé CPUPPCState *env = cpu_env(cs);
3210fc76338SPhilippe Mathieu-Daudé
3220fc76338SPhilippe Mathieu-Daudé if (env->insns_flags2 & PPC2_ISA207S) {
3230fc76338SPhilippe Mathieu-Daudé target_ulong priv;
3240fc76338SPhilippe Mathieu-Daudé
3250fc76338SPhilippe Mathieu-Daudé priv = env->spr[SPR_CIABR] & PPC_BITMASK(62, 63);
3260fc76338SPhilippe Mathieu-Daudé switch (priv) {
3270fc76338SPhilippe Mathieu-Daudé case 0x1: /* problem */
3280fc76338SPhilippe Mathieu-Daudé return env->msr & ((target_ulong)1 << MSR_PR);
3290fc76338SPhilippe Mathieu-Daudé case 0x2: /* supervisor */
3300fc76338SPhilippe Mathieu-Daudé return (!(env->msr & ((target_ulong)1 << MSR_PR)) &&
3310fc76338SPhilippe Mathieu-Daudé !(env->msr & ((target_ulong)1 << MSR_HV)));
3320fc76338SPhilippe Mathieu-Daudé case 0x3: /* hypervisor */
3330fc76338SPhilippe Mathieu-Daudé return (!(env->msr & ((target_ulong)1 << MSR_PR)) &&
3340fc76338SPhilippe Mathieu-Daudé (env->msr & ((target_ulong)1 << MSR_HV)));
3350fc76338SPhilippe Mathieu-Daudé default:
3360fc76338SPhilippe Mathieu-Daudé g_assert_not_reached();
3370fc76338SPhilippe Mathieu-Daudé }
3380fc76338SPhilippe Mathieu-Daudé }
3390fc76338SPhilippe Mathieu-Daudé #endif
3400fc76338SPhilippe Mathieu-Daudé
3410fc76338SPhilippe Mathieu-Daudé return false;
3420fc76338SPhilippe Mathieu-Daudé }
3430fc76338SPhilippe Mathieu-Daudé
ppc_cpu_debug_check_watchpoint(CPUState * cs,CPUWatchpoint * wp)3440fc76338SPhilippe Mathieu-Daudé bool ppc_cpu_debug_check_watchpoint(CPUState *cs, CPUWatchpoint *wp)
3450fc76338SPhilippe Mathieu-Daudé {
3460fc76338SPhilippe Mathieu-Daudé #if defined(TARGET_PPC64)
3470fc76338SPhilippe Mathieu-Daudé CPUPPCState *env = cpu_env(cs);
348*7ea6e125SShivaprasad G Bhat bool wt, wti, hv, sv, pr;
349*7ea6e125SShivaprasad G Bhat uint32_t dawrx;
3500fc76338SPhilippe Mathieu-Daudé
351*7ea6e125SShivaprasad G Bhat if ((env->insns_flags2 & PPC2_ISA207S) &&
352*7ea6e125SShivaprasad G Bhat (wp == env->dawr_watchpoint[0])) {
353*7ea6e125SShivaprasad G Bhat dawrx = env->spr[SPR_DAWRX0];
354*7ea6e125SShivaprasad G Bhat } else if ((env->insns_flags2 & PPC2_ISA310) &&
355*7ea6e125SShivaprasad G Bhat (wp == env->dawr_watchpoint[1])) {
356*7ea6e125SShivaprasad G Bhat dawrx = env->spr[SPR_DAWRX1];
357*7ea6e125SShivaprasad G Bhat } else {
358*7ea6e125SShivaprasad G Bhat return false;
359*7ea6e125SShivaprasad G Bhat }
360*7ea6e125SShivaprasad G Bhat
361*7ea6e125SShivaprasad G Bhat wt = extract32(dawrx, PPC_BIT_NR(59), 1);
362*7ea6e125SShivaprasad G Bhat wti = extract32(dawrx, PPC_BIT_NR(60), 1);
363*7ea6e125SShivaprasad G Bhat hv = extract32(dawrx, PPC_BIT_NR(61), 1);
364*7ea6e125SShivaprasad G Bhat sv = extract32(dawrx, PPC_BIT_NR(62), 1);
365*7ea6e125SShivaprasad G Bhat pr = extract32(dawrx, PPC_BIT_NR(62), 1);
3660fc76338SPhilippe Mathieu-Daudé
3670fc76338SPhilippe Mathieu-Daudé if ((env->msr & ((target_ulong)1 << MSR_PR)) && !pr) {
3680fc76338SPhilippe Mathieu-Daudé return false;
3690fc76338SPhilippe Mathieu-Daudé } else if ((env->msr & ((target_ulong)1 << MSR_HV)) && !hv) {
3700fc76338SPhilippe Mathieu-Daudé return false;
3710fc76338SPhilippe Mathieu-Daudé } else if (!sv) {
3720fc76338SPhilippe Mathieu-Daudé return false;
3730fc76338SPhilippe Mathieu-Daudé }
3740fc76338SPhilippe Mathieu-Daudé
3750fc76338SPhilippe Mathieu-Daudé if (!wti) {
3760fc76338SPhilippe Mathieu-Daudé if (env->msr & ((target_ulong)1 << MSR_DR)) {
377*7ea6e125SShivaprasad G Bhat return wt;
3780fc76338SPhilippe Mathieu-Daudé } else {
379*7ea6e125SShivaprasad G Bhat return !wt;
3800fc76338SPhilippe Mathieu-Daudé }
3810fc76338SPhilippe Mathieu-Daudé }
3820fc76338SPhilippe Mathieu-Daudé
3830fc76338SPhilippe Mathieu-Daudé return true;
3840fc76338SPhilippe Mathieu-Daudé #endif
3850fc76338SPhilippe Mathieu-Daudé
3860fc76338SPhilippe Mathieu-Daudé return false;
3870fc76338SPhilippe Mathieu-Daudé }
3880fc76338SPhilippe Mathieu-Daudé
3892f96c00bSPhilippe Mathieu-Daudé /*
3902f96c00bSPhilippe Mathieu-Daudé * This stops the machine and logs CPU state without killing QEMU (like
3912f96c00bSPhilippe Mathieu-Daudé * cpu_abort()) because it is often a guest error as opposed to a QEMU error,
3922f96c00bSPhilippe Mathieu-Daudé * so the machine can still be debugged.
3932f96c00bSPhilippe Mathieu-Daudé */
powerpc_checkstop(CPUPPCState * env,const char * reason)3942f96c00bSPhilippe Mathieu-Daudé G_NORETURN void powerpc_checkstop(CPUPPCState *env, const char *reason)
3952f96c00bSPhilippe Mathieu-Daudé {
3962f96c00bSPhilippe Mathieu-Daudé CPUState *cs = env_cpu(env);
3972f96c00bSPhilippe Mathieu-Daudé FILE *f;
3982f96c00bSPhilippe Mathieu-Daudé
3992f96c00bSPhilippe Mathieu-Daudé f = qemu_log_trylock();
4002f96c00bSPhilippe Mathieu-Daudé if (f) {
4012f96c00bSPhilippe Mathieu-Daudé fprintf(f, "Entering checkstop state: %s\n", reason);
4022f96c00bSPhilippe Mathieu-Daudé cpu_dump_state(cs, f, CPU_DUMP_FPU | CPU_DUMP_CCOP);
4032f96c00bSPhilippe Mathieu-Daudé qemu_log_unlock(f);
4042f96c00bSPhilippe Mathieu-Daudé }
4052f96c00bSPhilippe Mathieu-Daudé
4062f96c00bSPhilippe Mathieu-Daudé /*
4072f96c00bSPhilippe Mathieu-Daudé * This stops the machine and logs CPU state without killing QEMU
4082f96c00bSPhilippe Mathieu-Daudé * (like cpu_abort()) so the machine can still be debugged (because
4092f96c00bSPhilippe Mathieu-Daudé * it is often a guest error).
4102f96c00bSPhilippe Mathieu-Daudé */
4112f96c00bSPhilippe Mathieu-Daudé qemu_system_guest_panicked(NULL);
4122f96c00bSPhilippe Mathieu-Daudé cpu_loop_exit_noexc(cs);
4132f96c00bSPhilippe Mathieu-Daudé }
4142f96c00bSPhilippe Mathieu-Daudé
415720c2f2dSPhilippe Mathieu-Daudé /* Return true iff byteswap is needed to load instruction */
insn_need_byteswap(CPUArchState * env)416720c2f2dSPhilippe Mathieu-Daudé static inline bool insn_need_byteswap(CPUArchState *env)
417720c2f2dSPhilippe Mathieu-Daudé {
418720c2f2dSPhilippe Mathieu-Daudé /* SYSTEM builds TARGET_BIG_ENDIAN. Need to swap when MSR[LE] is set */
419720c2f2dSPhilippe Mathieu-Daudé return !!(env->msr & ((target_ulong)1 << MSR_LE));
420720c2f2dSPhilippe Mathieu-Daudé }
421720c2f2dSPhilippe Mathieu-Daudé
ppc_ldl_code(CPUArchState * env,target_ulong addr)422720c2f2dSPhilippe Mathieu-Daudé uint32_t ppc_ldl_code(CPUArchState *env, target_ulong addr)
423720c2f2dSPhilippe Mathieu-Daudé {
424720c2f2dSPhilippe Mathieu-Daudé uint32_t insn = cpu_ldl_code(env, addr);
425720c2f2dSPhilippe Mathieu-Daudé
426720c2f2dSPhilippe Mathieu-Daudé if (insn_need_byteswap(env)) {
427720c2f2dSPhilippe Mathieu-Daudé insn = bswap32(insn);
428720c2f2dSPhilippe Mathieu-Daudé }
429720c2f2dSPhilippe Mathieu-Daudé
430720c2f2dSPhilippe Mathieu-Daudé return insn;
431720c2f2dSPhilippe Mathieu-Daudé }
432720c2f2dSPhilippe Mathieu-Daudé
433c2c68701SPhilippe Mathieu-Daudé #if defined(TARGET_PPC64)
helper_attn(CPUPPCState * env)434c2c68701SPhilippe Mathieu-Daudé void helper_attn(CPUPPCState *env)
435c2c68701SPhilippe Mathieu-Daudé {
436c2c68701SPhilippe Mathieu-Daudé /* POWER attn is unprivileged when enabled by HID, otherwise illegal */
437c2c68701SPhilippe Mathieu-Daudé if ((*env->check_attn)(env)) {
438c2c68701SPhilippe Mathieu-Daudé powerpc_checkstop(env, "host executed attn");
439c2c68701SPhilippe Mathieu-Daudé } else {
440c2c68701SPhilippe Mathieu-Daudé raise_exception_err(env, POWERPC_EXCP_HV_EMU,
441c2c68701SPhilippe Mathieu-Daudé POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL);
442c2c68701SPhilippe Mathieu-Daudé }
443c2c68701SPhilippe Mathieu-Daudé }
444c2c68701SPhilippe Mathieu-Daudé
helper_scv(CPUPPCState * env,uint32_t lev)445c2c68701SPhilippe Mathieu-Daudé void helper_scv(CPUPPCState *env, uint32_t lev)
446c2c68701SPhilippe Mathieu-Daudé {
447c2c68701SPhilippe Mathieu-Daudé if (env->spr[SPR_FSCR] & (1ull << FSCR_SCV)) {
448c2c68701SPhilippe Mathieu-Daudé raise_exception_err(env, POWERPC_EXCP_SYSCALL_VECTORED, lev);
449c2c68701SPhilippe Mathieu-Daudé } else {
450c2c68701SPhilippe Mathieu-Daudé raise_exception_err(env, POWERPC_EXCP_FU, FSCR_IC_SCV);
451c2c68701SPhilippe Mathieu-Daudé }
452c2c68701SPhilippe Mathieu-Daudé }
453c2c68701SPhilippe Mathieu-Daudé
helper_pminsn(CPUPPCState * env,uint32_t insn)454c2c68701SPhilippe Mathieu-Daudé void helper_pminsn(CPUPPCState *env, uint32_t insn)
455c2c68701SPhilippe Mathieu-Daudé {
456c2c68701SPhilippe Mathieu-Daudé CPUState *cs = env_cpu(env);
457c2c68701SPhilippe Mathieu-Daudé
458c2c68701SPhilippe Mathieu-Daudé cs->halted = 1;
459c2c68701SPhilippe Mathieu-Daudé
460c2c68701SPhilippe Mathieu-Daudé /* Condition for waking up at 0x100 */
461c2c68701SPhilippe Mathieu-Daudé env->resume_as_sreset = (insn != PPC_PM_STOP) ||
462c2c68701SPhilippe Mathieu-Daudé (env->spr[SPR_PSSCR] & PSSCR_EC);
463c2c68701SPhilippe Mathieu-Daudé
464c2c68701SPhilippe Mathieu-Daudé /* HDECR is not to wake from PM state, it may have already fired */
465c2c68701SPhilippe Mathieu-Daudé if (env->resume_as_sreset) {
466c2c68701SPhilippe Mathieu-Daudé PowerPCCPU *cpu = env_archcpu(env);
467c2c68701SPhilippe Mathieu-Daudé ppc_set_irq(cpu, PPC_INTERRUPT_HDECR, 0);
468c2c68701SPhilippe Mathieu-Daudé }
469c2c68701SPhilippe Mathieu-Daudé
470c2c68701SPhilippe Mathieu-Daudé ppc_maybe_interrupt(env);
471c2c68701SPhilippe Mathieu-Daudé }
472c2c68701SPhilippe Mathieu-Daudé
473c2c68701SPhilippe Mathieu-Daudé #endif /* TARGET_PPC64 */
helper_store_msr(CPUPPCState * env,target_ulong val)474c2c68701SPhilippe Mathieu-Daudé void helper_store_msr(CPUPPCState *env, target_ulong val)
475c2c68701SPhilippe Mathieu-Daudé {
476c2c68701SPhilippe Mathieu-Daudé uint32_t excp = hreg_store_msr(env, val, 0);
477c2c68701SPhilippe Mathieu-Daudé
478c2c68701SPhilippe Mathieu-Daudé if (excp != 0) {
479c2c68701SPhilippe Mathieu-Daudé cpu_interrupt_exittb(env_cpu(env));
480c2c68701SPhilippe Mathieu-Daudé raise_exception(env, excp);
481c2c68701SPhilippe Mathieu-Daudé }
482c2c68701SPhilippe Mathieu-Daudé }
483c2c68701SPhilippe Mathieu-Daudé
helper_ppc_maybe_interrupt(CPUPPCState * env)484c2c68701SPhilippe Mathieu-Daudé void helper_ppc_maybe_interrupt(CPUPPCState *env)
485c2c68701SPhilippe Mathieu-Daudé {
486c2c68701SPhilippe Mathieu-Daudé ppc_maybe_interrupt(env);
487c2c68701SPhilippe Mathieu-Daudé }
488c2c68701SPhilippe Mathieu-Daudé
do_rfi(CPUPPCState * env,target_ulong nip,target_ulong msr)489c2c68701SPhilippe Mathieu-Daudé static void do_rfi(CPUPPCState *env, target_ulong nip, target_ulong msr)
490c2c68701SPhilippe Mathieu-Daudé {
491c2c68701SPhilippe Mathieu-Daudé /* MSR:POW cannot be set by any form of rfi */
492c2c68701SPhilippe Mathieu-Daudé msr &= ~(1ULL << MSR_POW);
493c2c68701SPhilippe Mathieu-Daudé
494c2c68701SPhilippe Mathieu-Daudé /* MSR:TGPR cannot be set by any form of rfi */
495c2c68701SPhilippe Mathieu-Daudé if (env->flags & POWERPC_FLAG_TGPR) {
496c2c68701SPhilippe Mathieu-Daudé msr &= ~(1ULL << MSR_TGPR);
497c2c68701SPhilippe Mathieu-Daudé }
498c2c68701SPhilippe Mathieu-Daudé
499c2c68701SPhilippe Mathieu-Daudé #ifdef TARGET_PPC64
500c2c68701SPhilippe Mathieu-Daudé /* Switching to 32-bit ? Crop the nip */
501c2c68701SPhilippe Mathieu-Daudé if (!msr_is_64bit(env, msr)) {
502c2c68701SPhilippe Mathieu-Daudé nip = (uint32_t)nip;
503c2c68701SPhilippe Mathieu-Daudé }
504c2c68701SPhilippe Mathieu-Daudé #else
505c2c68701SPhilippe Mathieu-Daudé nip = (uint32_t)nip;
506c2c68701SPhilippe Mathieu-Daudé #endif
507c2c68701SPhilippe Mathieu-Daudé /* XXX: beware: this is false if VLE is supported */
508c2c68701SPhilippe Mathieu-Daudé env->nip = nip & ~((target_ulong)0x00000003);
509c2c68701SPhilippe Mathieu-Daudé hreg_store_msr(env, msr, 1);
510c2c68701SPhilippe Mathieu-Daudé trace_ppc_excp_rfi(env->nip, env->msr);
511c2c68701SPhilippe Mathieu-Daudé /*
512c2c68701SPhilippe Mathieu-Daudé * No need to raise an exception here, as rfi is always the last
513c2c68701SPhilippe Mathieu-Daudé * insn of a TB
514c2c68701SPhilippe Mathieu-Daudé */
515c2c68701SPhilippe Mathieu-Daudé cpu_interrupt_exittb(env_cpu(env));
516c2c68701SPhilippe Mathieu-Daudé /* Reset the reservation */
517c2c68701SPhilippe Mathieu-Daudé env->reserve_addr = -1;
518c2c68701SPhilippe Mathieu-Daudé
519c2c68701SPhilippe Mathieu-Daudé /* Context synchronizing: check if TCG TLB needs flush */
520c2c68701SPhilippe Mathieu-Daudé check_tlb_flush(env, false);
521c2c68701SPhilippe Mathieu-Daudé }
522c2c68701SPhilippe Mathieu-Daudé
helper_rfi(CPUPPCState * env)523c2c68701SPhilippe Mathieu-Daudé void helper_rfi(CPUPPCState *env)
524c2c68701SPhilippe Mathieu-Daudé {
525c2c68701SPhilippe Mathieu-Daudé do_rfi(env, env->spr[SPR_SRR0], env->spr[SPR_SRR1] & 0xfffffffful);
526c2c68701SPhilippe Mathieu-Daudé }
527c2c68701SPhilippe Mathieu-Daudé
528c2c68701SPhilippe Mathieu-Daudé #ifdef TARGET_PPC64
helper_rfid(CPUPPCState * env)529c2c68701SPhilippe Mathieu-Daudé void helper_rfid(CPUPPCState *env)
530c2c68701SPhilippe Mathieu-Daudé {
531c2c68701SPhilippe Mathieu-Daudé /*
532c2c68701SPhilippe Mathieu-Daudé * The architecture defines a number of rules for which bits can
533c2c68701SPhilippe Mathieu-Daudé * change but in practice, we handle this in hreg_store_msr()
534c2c68701SPhilippe Mathieu-Daudé * which will be called by do_rfi(), so there is no need to filter
535c2c68701SPhilippe Mathieu-Daudé * here
536c2c68701SPhilippe Mathieu-Daudé */
537c2c68701SPhilippe Mathieu-Daudé do_rfi(env, env->spr[SPR_SRR0], env->spr[SPR_SRR1]);
538c2c68701SPhilippe Mathieu-Daudé }
539c2c68701SPhilippe Mathieu-Daudé
helper_rfscv(CPUPPCState * env)540c2c68701SPhilippe Mathieu-Daudé void helper_rfscv(CPUPPCState *env)
541c2c68701SPhilippe Mathieu-Daudé {
542c2c68701SPhilippe Mathieu-Daudé do_rfi(env, env->lr, env->ctr);
543c2c68701SPhilippe Mathieu-Daudé }
544c2c68701SPhilippe Mathieu-Daudé
helper_hrfid(CPUPPCState * env)545c2c68701SPhilippe Mathieu-Daudé void helper_hrfid(CPUPPCState *env)
546c2c68701SPhilippe Mathieu-Daudé {
547c2c68701SPhilippe Mathieu-Daudé do_rfi(env, env->spr[SPR_HSRR0], env->spr[SPR_HSRR1]);
548c2c68701SPhilippe Mathieu-Daudé }
549c2c68701SPhilippe Mathieu-Daudé
helper_rfebb(CPUPPCState * env,target_ulong s)550c2c68701SPhilippe Mathieu-Daudé void helper_rfebb(CPUPPCState *env, target_ulong s)
551c2c68701SPhilippe Mathieu-Daudé {
552c2c68701SPhilippe Mathieu-Daudé target_ulong msr = env->msr;
553c2c68701SPhilippe Mathieu-Daudé
554c2c68701SPhilippe Mathieu-Daudé /*
555c2c68701SPhilippe Mathieu-Daudé * Handling of BESCR bits 32:33 according to PowerISA v3.1:
556c2c68701SPhilippe Mathieu-Daudé *
557c2c68701SPhilippe Mathieu-Daudé * "If BESCR 32:33 != 0b00 the instruction is treated as if
558c2c68701SPhilippe Mathieu-Daudé * the instruction form were invalid."
559c2c68701SPhilippe Mathieu-Daudé */
560c2c68701SPhilippe Mathieu-Daudé if (env->spr[SPR_BESCR] & BESCR_INVALID) {
561c2c68701SPhilippe Mathieu-Daudé raise_exception_err(env, POWERPC_EXCP_PROGRAM,
562c2c68701SPhilippe Mathieu-Daudé POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL);
563c2c68701SPhilippe Mathieu-Daudé }
564c2c68701SPhilippe Mathieu-Daudé
565c2c68701SPhilippe Mathieu-Daudé env->nip = env->spr[SPR_EBBRR];
566c2c68701SPhilippe Mathieu-Daudé
567c2c68701SPhilippe Mathieu-Daudé /* Switching to 32-bit ? Crop the nip */
568c2c68701SPhilippe Mathieu-Daudé if (!msr_is_64bit(env, msr)) {
569c2c68701SPhilippe Mathieu-Daudé env->nip = (uint32_t)env->spr[SPR_EBBRR];
570c2c68701SPhilippe Mathieu-Daudé }
571c2c68701SPhilippe Mathieu-Daudé
572c2c68701SPhilippe Mathieu-Daudé if (s) {
573c2c68701SPhilippe Mathieu-Daudé env->spr[SPR_BESCR] |= BESCR_GE;
574c2c68701SPhilippe Mathieu-Daudé } else {
575c2c68701SPhilippe Mathieu-Daudé env->spr[SPR_BESCR] &= ~BESCR_GE;
576c2c68701SPhilippe Mathieu-Daudé }
577c2c68701SPhilippe Mathieu-Daudé }
578c2c68701SPhilippe Mathieu-Daudé
579c2c68701SPhilippe Mathieu-Daudé /*
580c2c68701SPhilippe Mathieu-Daudé * Triggers or queues an 'ebb_excp' EBB exception. All checks
581c2c68701SPhilippe Mathieu-Daudé * but FSCR, HFSCR and msr_pr must be done beforehand.
582c2c68701SPhilippe Mathieu-Daudé *
583c2c68701SPhilippe Mathieu-Daudé * PowerISA v3.1 isn't clear about whether an EBB should be
584c2c68701SPhilippe Mathieu-Daudé * postponed or cancelled if the EBB facility is unavailable.
585c2c68701SPhilippe Mathieu-Daudé * Our assumption here is that the EBB is cancelled if both
586c2c68701SPhilippe Mathieu-Daudé * FSCR and HFSCR EBB facilities aren't available.
587c2c68701SPhilippe Mathieu-Daudé */
do_ebb(CPUPPCState * env,int ebb_excp)588c2c68701SPhilippe Mathieu-Daudé static void do_ebb(CPUPPCState *env, int ebb_excp)
589c2c68701SPhilippe Mathieu-Daudé {
590c2c68701SPhilippe Mathieu-Daudé PowerPCCPU *cpu = env_archcpu(env);
591c2c68701SPhilippe Mathieu-Daudé
592c2c68701SPhilippe Mathieu-Daudé /*
593c2c68701SPhilippe Mathieu-Daudé * FSCR_EBB and FSCR_IC_EBB are the same bits used with
594c2c68701SPhilippe Mathieu-Daudé * HFSCR.
595c2c68701SPhilippe Mathieu-Daudé */
596c2c68701SPhilippe Mathieu-Daudé helper_fscr_facility_check(env, FSCR_EBB, 0, FSCR_IC_EBB);
597c2c68701SPhilippe Mathieu-Daudé helper_hfscr_facility_check(env, FSCR_EBB, "EBB", FSCR_IC_EBB);
598c2c68701SPhilippe Mathieu-Daudé
599c2c68701SPhilippe Mathieu-Daudé if (ebb_excp == POWERPC_EXCP_PERFM_EBB) {
600c2c68701SPhilippe Mathieu-Daudé env->spr[SPR_BESCR] |= BESCR_PMEO;
601c2c68701SPhilippe Mathieu-Daudé } else if (ebb_excp == POWERPC_EXCP_EXTERNAL_EBB) {
602c2c68701SPhilippe Mathieu-Daudé env->spr[SPR_BESCR] |= BESCR_EEO;
603c2c68701SPhilippe Mathieu-Daudé }
604c2c68701SPhilippe Mathieu-Daudé
605c2c68701SPhilippe Mathieu-Daudé if (FIELD_EX64(env->msr, MSR, PR)) {
606c2c68701SPhilippe Mathieu-Daudé powerpc_excp(cpu, ebb_excp);
607c2c68701SPhilippe Mathieu-Daudé } else {
608c2c68701SPhilippe Mathieu-Daudé ppc_set_irq(cpu, PPC_INTERRUPT_EBB, 1);
609c2c68701SPhilippe Mathieu-Daudé }
610c2c68701SPhilippe Mathieu-Daudé }
611c2c68701SPhilippe Mathieu-Daudé
raise_ebb_perfm_exception(CPUPPCState * env)612c2c68701SPhilippe Mathieu-Daudé void raise_ebb_perfm_exception(CPUPPCState *env)
613c2c68701SPhilippe Mathieu-Daudé {
614c2c68701SPhilippe Mathieu-Daudé bool perfm_ebb_enabled = env->spr[SPR_POWER_MMCR0] & MMCR0_EBE &&
615c2c68701SPhilippe Mathieu-Daudé env->spr[SPR_BESCR] & BESCR_PME &&
616c2c68701SPhilippe Mathieu-Daudé env->spr[SPR_BESCR] & BESCR_GE;
617c2c68701SPhilippe Mathieu-Daudé
618c2c68701SPhilippe Mathieu-Daudé if (!perfm_ebb_enabled) {
619c2c68701SPhilippe Mathieu-Daudé return;
620c2c68701SPhilippe Mathieu-Daudé }
621c2c68701SPhilippe Mathieu-Daudé
622c2c68701SPhilippe Mathieu-Daudé do_ebb(env, POWERPC_EXCP_PERFM_EBB);
623c2c68701SPhilippe Mathieu-Daudé }
624c2c68701SPhilippe Mathieu-Daudé #endif /* TARGET_PPC64 */
625c2c68701SPhilippe Mathieu-Daudé
626c2c68701SPhilippe Mathieu-Daudé /*****************************************************************************/
627c2c68701SPhilippe Mathieu-Daudé /* Embedded PowerPC specific helpers */
helper_40x_rfci(CPUPPCState * env)628c2c68701SPhilippe Mathieu-Daudé void helper_40x_rfci(CPUPPCState *env)
629c2c68701SPhilippe Mathieu-Daudé {
630c2c68701SPhilippe Mathieu-Daudé do_rfi(env, env->spr[SPR_40x_SRR2], env->spr[SPR_40x_SRR3]);
631c2c68701SPhilippe Mathieu-Daudé }
632c2c68701SPhilippe Mathieu-Daudé
helper_rfci(CPUPPCState * env)633c2c68701SPhilippe Mathieu-Daudé void helper_rfci(CPUPPCState *env)
634c2c68701SPhilippe Mathieu-Daudé {
635c2c68701SPhilippe Mathieu-Daudé do_rfi(env, env->spr[SPR_BOOKE_CSRR0], env->spr[SPR_BOOKE_CSRR1]);
636c2c68701SPhilippe Mathieu-Daudé }
637c2c68701SPhilippe Mathieu-Daudé
helper_rfdi(CPUPPCState * env)638c2c68701SPhilippe Mathieu-Daudé void helper_rfdi(CPUPPCState *env)
639c2c68701SPhilippe Mathieu-Daudé {
640c2c68701SPhilippe Mathieu-Daudé /* FIXME: choose CSRR1 or DSRR1 based on cpu type */
641c2c68701SPhilippe Mathieu-Daudé do_rfi(env, env->spr[SPR_BOOKE_DSRR0], env->spr[SPR_BOOKE_DSRR1]);
642c2c68701SPhilippe Mathieu-Daudé }
643c2c68701SPhilippe Mathieu-Daudé
helper_rfmci(CPUPPCState * env)644c2c68701SPhilippe Mathieu-Daudé void helper_rfmci(CPUPPCState *env)
645c2c68701SPhilippe Mathieu-Daudé {
646c2c68701SPhilippe Mathieu-Daudé /* FIXME: choose CSRR1 or MCSRR1 based on cpu type */
647c2c68701SPhilippe Mathieu-Daudé do_rfi(env, env->spr[SPR_BOOKE_MCSRR0], env->spr[SPR_BOOKE_MCSRR1]);
648c2c68701SPhilippe Mathieu-Daudé }
649c2c68701SPhilippe Mathieu-Daudé
650c2c68701SPhilippe Mathieu-Daudé /* Embedded.Processor Control */
dbell2irq(target_ulong rb)651c2c68701SPhilippe Mathieu-Daudé static int dbell2irq(target_ulong rb)
652c2c68701SPhilippe Mathieu-Daudé {
653c2c68701SPhilippe Mathieu-Daudé int msg = rb & DBELL_TYPE_MASK;
654c2c68701SPhilippe Mathieu-Daudé int irq = -1;
655c2c68701SPhilippe Mathieu-Daudé
656c2c68701SPhilippe Mathieu-Daudé switch (msg) {
657c2c68701SPhilippe Mathieu-Daudé case DBELL_TYPE_DBELL:
658c2c68701SPhilippe Mathieu-Daudé irq = PPC_INTERRUPT_DOORBELL;
659c2c68701SPhilippe Mathieu-Daudé break;
660c2c68701SPhilippe Mathieu-Daudé case DBELL_TYPE_DBELL_CRIT:
661c2c68701SPhilippe Mathieu-Daudé irq = PPC_INTERRUPT_CDOORBELL;
662c2c68701SPhilippe Mathieu-Daudé break;
663c2c68701SPhilippe Mathieu-Daudé case DBELL_TYPE_G_DBELL:
664c2c68701SPhilippe Mathieu-Daudé case DBELL_TYPE_G_DBELL_CRIT:
665c2c68701SPhilippe Mathieu-Daudé case DBELL_TYPE_G_DBELL_MC:
666c2c68701SPhilippe Mathieu-Daudé /* XXX implement */
667c2c68701SPhilippe Mathieu-Daudé default:
668c2c68701SPhilippe Mathieu-Daudé break;
669c2c68701SPhilippe Mathieu-Daudé }
670c2c68701SPhilippe Mathieu-Daudé
671c2c68701SPhilippe Mathieu-Daudé return irq;
672c2c68701SPhilippe Mathieu-Daudé }
673c2c68701SPhilippe Mathieu-Daudé
helper_msgclr(CPUPPCState * env,target_ulong rb)674c2c68701SPhilippe Mathieu-Daudé void helper_msgclr(CPUPPCState *env, target_ulong rb)
675c2c68701SPhilippe Mathieu-Daudé {
676c2c68701SPhilippe Mathieu-Daudé int irq = dbell2irq(rb);
677c2c68701SPhilippe Mathieu-Daudé
678c2c68701SPhilippe Mathieu-Daudé if (irq < 0) {
679c2c68701SPhilippe Mathieu-Daudé return;
680c2c68701SPhilippe Mathieu-Daudé }
681c2c68701SPhilippe Mathieu-Daudé
682c2c68701SPhilippe Mathieu-Daudé ppc_set_irq(env_archcpu(env), irq, 0);
683c2c68701SPhilippe Mathieu-Daudé }
684c2c68701SPhilippe Mathieu-Daudé
helper_msgsnd(target_ulong rb)685c2c68701SPhilippe Mathieu-Daudé void helper_msgsnd(target_ulong rb)
686c2c68701SPhilippe Mathieu-Daudé {
687c2c68701SPhilippe Mathieu-Daudé int irq = dbell2irq(rb);
688c2c68701SPhilippe Mathieu-Daudé int pir = rb & DBELL_PIRTAG_MASK;
689c2c68701SPhilippe Mathieu-Daudé CPUState *cs;
690c2c68701SPhilippe Mathieu-Daudé
691c2c68701SPhilippe Mathieu-Daudé if (irq < 0) {
692c2c68701SPhilippe Mathieu-Daudé return;
693c2c68701SPhilippe Mathieu-Daudé }
694c2c68701SPhilippe Mathieu-Daudé
695c2c68701SPhilippe Mathieu-Daudé bql_lock();
696c2c68701SPhilippe Mathieu-Daudé CPU_FOREACH(cs) {
697c2c68701SPhilippe Mathieu-Daudé PowerPCCPU *cpu = POWERPC_CPU(cs);
698c2c68701SPhilippe Mathieu-Daudé CPUPPCState *cenv = &cpu->env;
699c2c68701SPhilippe Mathieu-Daudé
700c2c68701SPhilippe Mathieu-Daudé if ((rb & DBELL_BRDCAST_MASK) || (cenv->spr[SPR_BOOKE_PIR] == pir)) {
701c2c68701SPhilippe Mathieu-Daudé ppc_set_irq(cpu, irq, 1);
702c2c68701SPhilippe Mathieu-Daudé }
703c2c68701SPhilippe Mathieu-Daudé }
704c2c68701SPhilippe Mathieu-Daudé bql_unlock();
705c2c68701SPhilippe Mathieu-Daudé }
706c2c68701SPhilippe Mathieu-Daudé
707c2c68701SPhilippe Mathieu-Daudé /* Server Processor Control */
708c2c68701SPhilippe Mathieu-Daudé
dbell_type_server(target_ulong rb)709c2c68701SPhilippe Mathieu-Daudé static bool dbell_type_server(target_ulong rb)
710c2c68701SPhilippe Mathieu-Daudé {
711c2c68701SPhilippe Mathieu-Daudé /*
712c2c68701SPhilippe Mathieu-Daudé * A Directed Hypervisor Doorbell message is sent only if the
713c2c68701SPhilippe Mathieu-Daudé * message type is 5. All other types are reserved and the
714c2c68701SPhilippe Mathieu-Daudé * instruction is a no-op
715c2c68701SPhilippe Mathieu-Daudé */
716c2c68701SPhilippe Mathieu-Daudé return (rb & DBELL_TYPE_MASK) == DBELL_TYPE_DBELL_SERVER;
717c2c68701SPhilippe Mathieu-Daudé }
718c2c68701SPhilippe Mathieu-Daudé
dbell_bcast_core(target_ulong rb)719c2c68701SPhilippe Mathieu-Daudé static inline bool dbell_bcast_core(target_ulong rb)
720c2c68701SPhilippe Mathieu-Daudé {
721c2c68701SPhilippe Mathieu-Daudé return (rb & DBELL_BRDCAST_MASK) == DBELL_BRDCAST_CORE;
722c2c68701SPhilippe Mathieu-Daudé }
723c2c68701SPhilippe Mathieu-Daudé
dbell_bcast_subproc(target_ulong rb)724c2c68701SPhilippe Mathieu-Daudé static inline bool dbell_bcast_subproc(target_ulong rb)
725c2c68701SPhilippe Mathieu-Daudé {
726c2c68701SPhilippe Mathieu-Daudé return (rb & DBELL_BRDCAST_MASK) == DBELL_BRDCAST_SUBPROC;
727c2c68701SPhilippe Mathieu-Daudé }
728c2c68701SPhilippe Mathieu-Daudé
729c2c68701SPhilippe Mathieu-Daudé /*
730c2c68701SPhilippe Mathieu-Daudé * Send an interrupt to a thread in the same core as env).
731c2c68701SPhilippe Mathieu-Daudé */
msgsnd_core_tir(CPUPPCState * env,uint32_t target_tir,int irq)732c2c68701SPhilippe Mathieu-Daudé static void msgsnd_core_tir(CPUPPCState *env, uint32_t target_tir, int irq)
733c2c68701SPhilippe Mathieu-Daudé {
734c2c68701SPhilippe Mathieu-Daudé PowerPCCPU *cpu = env_archcpu(env);
735c2c68701SPhilippe Mathieu-Daudé CPUState *cs = env_cpu(env);
736c2c68701SPhilippe Mathieu-Daudé
737c2c68701SPhilippe Mathieu-Daudé if (ppc_cpu_lpar_single_threaded(cs)) {
738c2c68701SPhilippe Mathieu-Daudé if (target_tir == 0) {
739c2c68701SPhilippe Mathieu-Daudé ppc_set_irq(cpu, irq, 1);
740c2c68701SPhilippe Mathieu-Daudé }
741c2c68701SPhilippe Mathieu-Daudé } else {
742c2c68701SPhilippe Mathieu-Daudé CPUState *ccs;
743c2c68701SPhilippe Mathieu-Daudé
744c2c68701SPhilippe Mathieu-Daudé /* Does iothread need to be locked for walking CPU list? */
745c2c68701SPhilippe Mathieu-Daudé bql_lock();
746c2c68701SPhilippe Mathieu-Daudé THREAD_SIBLING_FOREACH(cs, ccs) {
747c2c68701SPhilippe Mathieu-Daudé PowerPCCPU *ccpu = POWERPC_CPU(ccs);
748c2c68701SPhilippe Mathieu-Daudé if (target_tir == ppc_cpu_tir(ccpu)) {
749c2c68701SPhilippe Mathieu-Daudé ppc_set_irq(ccpu, irq, 1);
750c2c68701SPhilippe Mathieu-Daudé break;
751c2c68701SPhilippe Mathieu-Daudé }
752c2c68701SPhilippe Mathieu-Daudé }
753c2c68701SPhilippe Mathieu-Daudé bql_unlock();
754c2c68701SPhilippe Mathieu-Daudé }
755c2c68701SPhilippe Mathieu-Daudé }
756c2c68701SPhilippe Mathieu-Daudé
helper_book3s_msgclr(CPUPPCState * env,target_ulong rb)757c2c68701SPhilippe Mathieu-Daudé void helper_book3s_msgclr(CPUPPCState *env, target_ulong rb)
758c2c68701SPhilippe Mathieu-Daudé {
759c2c68701SPhilippe Mathieu-Daudé if (!dbell_type_server(rb)) {
760c2c68701SPhilippe Mathieu-Daudé return;
761c2c68701SPhilippe Mathieu-Daudé }
762c2c68701SPhilippe Mathieu-Daudé
763c2c68701SPhilippe Mathieu-Daudé ppc_set_irq(env_archcpu(env), PPC_INTERRUPT_HDOORBELL, 0);
764c2c68701SPhilippe Mathieu-Daudé }
765c2c68701SPhilippe Mathieu-Daudé
helper_book3s_msgsnd(CPUPPCState * env,target_ulong rb)766c2c68701SPhilippe Mathieu-Daudé void helper_book3s_msgsnd(CPUPPCState *env, target_ulong rb)
767c2c68701SPhilippe Mathieu-Daudé {
768c2c68701SPhilippe Mathieu-Daudé int pir = rb & DBELL_PROCIDTAG_MASK;
769c2c68701SPhilippe Mathieu-Daudé bool brdcast = false;
770c2c68701SPhilippe Mathieu-Daudé CPUState *cs, *ccs;
771c2c68701SPhilippe Mathieu-Daudé PowerPCCPU *cpu;
772c2c68701SPhilippe Mathieu-Daudé
773c2c68701SPhilippe Mathieu-Daudé if (!dbell_type_server(rb)) {
774c2c68701SPhilippe Mathieu-Daudé return;
775c2c68701SPhilippe Mathieu-Daudé }
776c2c68701SPhilippe Mathieu-Daudé
777c2c68701SPhilippe Mathieu-Daudé /* POWER8 msgsnd is like msgsndp (targets a thread within core) */
778c2c68701SPhilippe Mathieu-Daudé if (!(env->insns_flags2 & PPC2_ISA300)) {
779c2c68701SPhilippe Mathieu-Daudé msgsnd_core_tir(env, rb & PPC_BITMASK(57, 63), PPC_INTERRUPT_HDOORBELL);
780c2c68701SPhilippe Mathieu-Daudé return;
781c2c68701SPhilippe Mathieu-Daudé }
782c2c68701SPhilippe Mathieu-Daudé
783c2c68701SPhilippe Mathieu-Daudé /* POWER9 and later msgsnd is a global (targets any thread) */
784c2c68701SPhilippe Mathieu-Daudé cpu = ppc_get_vcpu_by_pir(pir);
785c2c68701SPhilippe Mathieu-Daudé if (!cpu) {
786c2c68701SPhilippe Mathieu-Daudé return;
787c2c68701SPhilippe Mathieu-Daudé }
788c2c68701SPhilippe Mathieu-Daudé cs = CPU(cpu);
789c2c68701SPhilippe Mathieu-Daudé
790c2c68701SPhilippe Mathieu-Daudé if (dbell_bcast_core(rb) || (dbell_bcast_subproc(rb) &&
791c2c68701SPhilippe Mathieu-Daudé (env->flags & POWERPC_FLAG_SMT_1LPAR))) {
792c2c68701SPhilippe Mathieu-Daudé brdcast = true;
793c2c68701SPhilippe Mathieu-Daudé }
794c2c68701SPhilippe Mathieu-Daudé
795c2c68701SPhilippe Mathieu-Daudé if (ppc_cpu_core_single_threaded(cs) || !brdcast) {
796c2c68701SPhilippe Mathieu-Daudé ppc_set_irq(cpu, PPC_INTERRUPT_HDOORBELL, 1);
797c2c68701SPhilippe Mathieu-Daudé return;
798c2c68701SPhilippe Mathieu-Daudé }
799c2c68701SPhilippe Mathieu-Daudé
800c2c68701SPhilippe Mathieu-Daudé /*
801c2c68701SPhilippe Mathieu-Daudé * Why is bql needed for walking CPU list? Answer seems to be because ppc
802c2c68701SPhilippe Mathieu-Daudé * irq handling needs it, but ppc_set_irq takes the lock itself if needed,
803c2c68701SPhilippe Mathieu-Daudé * so could this be removed?
804c2c68701SPhilippe Mathieu-Daudé */
805c2c68701SPhilippe Mathieu-Daudé bql_lock();
806c2c68701SPhilippe Mathieu-Daudé THREAD_SIBLING_FOREACH(cs, ccs) {
807c2c68701SPhilippe Mathieu-Daudé ppc_set_irq(POWERPC_CPU(ccs), PPC_INTERRUPT_HDOORBELL, 1);
808c2c68701SPhilippe Mathieu-Daudé }
809c2c68701SPhilippe Mathieu-Daudé bql_unlock();
810c2c68701SPhilippe Mathieu-Daudé }
811c2c68701SPhilippe Mathieu-Daudé
812c2c68701SPhilippe Mathieu-Daudé #ifdef TARGET_PPC64
helper_book3s_msgclrp(CPUPPCState * env,target_ulong rb)813c2c68701SPhilippe Mathieu-Daudé void helper_book3s_msgclrp(CPUPPCState *env, target_ulong rb)
814c2c68701SPhilippe Mathieu-Daudé {
815c2c68701SPhilippe Mathieu-Daudé helper_hfscr_facility_check(env, HFSCR_MSGP, "msgclrp", HFSCR_IC_MSGP);
816c2c68701SPhilippe Mathieu-Daudé
817c2c68701SPhilippe Mathieu-Daudé if (!dbell_type_server(rb)) {
818c2c68701SPhilippe Mathieu-Daudé return;
819c2c68701SPhilippe Mathieu-Daudé }
820c2c68701SPhilippe Mathieu-Daudé
821c2c68701SPhilippe Mathieu-Daudé ppc_set_irq(env_archcpu(env), PPC_INTERRUPT_DOORBELL, 0);
822c2c68701SPhilippe Mathieu-Daudé }
823c2c68701SPhilippe Mathieu-Daudé
824c2c68701SPhilippe Mathieu-Daudé /*
825c2c68701SPhilippe Mathieu-Daudé * sends a message to another thread on the same
826c2c68701SPhilippe Mathieu-Daudé * multi-threaded processor
827c2c68701SPhilippe Mathieu-Daudé */
helper_book3s_msgsndp(CPUPPCState * env,target_ulong rb)828c2c68701SPhilippe Mathieu-Daudé void helper_book3s_msgsndp(CPUPPCState *env, target_ulong rb)
829c2c68701SPhilippe Mathieu-Daudé {
830c2c68701SPhilippe Mathieu-Daudé helper_hfscr_facility_check(env, HFSCR_MSGP, "msgsndp", HFSCR_IC_MSGP);
831c2c68701SPhilippe Mathieu-Daudé
832c2c68701SPhilippe Mathieu-Daudé if (!dbell_type_server(rb)) {
833c2c68701SPhilippe Mathieu-Daudé return;
834c2c68701SPhilippe Mathieu-Daudé }
835c2c68701SPhilippe Mathieu-Daudé
836c2c68701SPhilippe Mathieu-Daudé msgsnd_core_tir(env, rb & PPC_BITMASK(57, 63), PPC_INTERRUPT_DOORBELL);
837c2c68701SPhilippe Mathieu-Daudé }
838c2c68701SPhilippe Mathieu-Daudé #endif /* TARGET_PPC64 */
839c2c68701SPhilippe Mathieu-Daudé
840c2c68701SPhilippe Mathieu-Daudé /* Single-step tracing */
helper_book3s_trace(CPUPPCState * env,target_ulong prev_ip)841c2c68701SPhilippe Mathieu-Daudé void helper_book3s_trace(CPUPPCState *env, target_ulong prev_ip)
842c2c68701SPhilippe Mathieu-Daudé {
843c2c68701SPhilippe Mathieu-Daudé uint32_t error_code = 0;
844c2c68701SPhilippe Mathieu-Daudé if (env->insns_flags2 & PPC2_ISA207S) {
845c2c68701SPhilippe Mathieu-Daudé /* Load/store reporting, SRR1[35, 36] and SDAR, are not implemented. */
846c2c68701SPhilippe Mathieu-Daudé env->spr[SPR_POWER_SIAR] = prev_ip;
847c2c68701SPhilippe Mathieu-Daudé error_code = PPC_BIT(33);
848c2c68701SPhilippe Mathieu-Daudé }
849c2c68701SPhilippe Mathieu-Daudé raise_exception_err(env, POWERPC_EXCP_TRACE, error_code);
850c2c68701SPhilippe Mathieu-Daudé }
8510fc76338SPhilippe Mathieu-Daudé #endif /* !CONFIG_USER_ONLY */
852