xref: /openbmc/qemu/target/ppc/tcg-excp_helper.c (revision 71569cd8aba31fcb3a326c56c307d2b811417c0b)
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