target/ppc: Improve syscall exception logging
[qemu/rayw.git] / target / ppc / excp_helper.c
blob81ee19ebae57d549fe068d626b2d4f8201356e02
1 /*
2 * PowerPC exception emulation helpers for QEMU.
4 * Copyright (c) 2003-2007 Jocelyn Mayer
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19 #include "qemu/osdep.h"
20 #include "qemu/main-loop.h"
21 #include "cpu.h"
22 #include "exec/helper-proto.h"
23 #include "exec/exec-all.h"
24 #include "exec/cpu_ldst.h"
25 #include "internal.h"
26 #include "helper_regs.h"
28 /* #define DEBUG_OP */
29 /* #define DEBUG_SOFTWARE_TLB */
30 /* #define DEBUG_EXCEPTIONS */
32 #ifdef DEBUG_EXCEPTIONS
33 # define LOG_EXCP(...) qemu_log(__VA_ARGS__)
34 #else
35 # define LOG_EXCP(...) do { } while (0)
36 #endif
38 /*****************************************************************************/
39 /* Exception processing */
40 #if defined(CONFIG_USER_ONLY)
41 void ppc_cpu_do_interrupt(CPUState *cs)
43 PowerPCCPU *cpu = POWERPC_CPU(cs);
44 CPUPPCState *env = &cpu->env;
46 cs->exception_index = POWERPC_EXCP_NONE;
47 env->error_code = 0;
50 static void ppc_hw_interrupt(CPUPPCState *env)
52 CPUState *cs = env_cpu(env);
54 cs->exception_index = POWERPC_EXCP_NONE;
55 env->error_code = 0;
57 #else /* defined(CONFIG_USER_ONLY) */
58 static inline void dump_syscall(CPUPPCState *env)
60 qemu_log_mask(CPU_LOG_INT, "syscall r0=%016" PRIx64
61 " r3=%016" PRIx64 " r4=%016" PRIx64 " r5=%016" PRIx64
62 " r6=%016" PRIx64 " r7=%016" PRIx64 " r8=%016" PRIx64
63 " nip=" TARGET_FMT_lx "\n",
64 ppc_dump_gpr(env, 0), ppc_dump_gpr(env, 3),
65 ppc_dump_gpr(env, 4), ppc_dump_gpr(env, 5),
66 ppc_dump_gpr(env, 6), ppc_dump_gpr(env, 7),
67 ppc_dump_gpr(env, 8), env->nip);
70 static inline void dump_hcall(CPUPPCState *env)
72 qemu_log_mask(CPU_LOG_INT, "hypercall r3=%016" PRIx64
73 " r4=%016" PRIx64 " r5=%016" PRIx64 " r6=%016" PRIx64
74 " r7=%016" PRIx64 " r8=%016" PRIx64 " r9=%016" PRIx64
75 " r10=%016" PRIx64 " r11=%016" PRIx64 " r12=%016" PRIx64
76 " nip=" TARGET_FMT_lx "\n",
77 ppc_dump_gpr(env, 3), ppc_dump_gpr(env, 4),
78 ppc_dump_gpr(env, 5), ppc_dump_gpr(env, 6),
79 ppc_dump_gpr(env, 7), ppc_dump_gpr(env, 8),
80 ppc_dump_gpr(env, 9), ppc_dump_gpr(env, 10),
81 ppc_dump_gpr(env, 11), ppc_dump_gpr(env, 12),
82 env->nip);
85 static int powerpc_reset_wakeup(CPUState *cs, CPUPPCState *env, int excp,
86 target_ulong *msr)
88 /* We no longer are in a PM state */
89 env->resume_as_sreset = false;
91 /* Pretend to be returning from doze always as we don't lose state */
92 *msr |= (0x1ull << (63 - 47));
94 /* Machine checks are sent normally */
95 if (excp == POWERPC_EXCP_MCHECK) {
96 return excp;
98 switch (excp) {
99 case POWERPC_EXCP_RESET:
100 *msr |= 0x4ull << (63 - 45);
101 break;
102 case POWERPC_EXCP_EXTERNAL:
103 *msr |= 0x8ull << (63 - 45);
104 break;
105 case POWERPC_EXCP_DECR:
106 *msr |= 0x6ull << (63 - 45);
107 break;
108 case POWERPC_EXCP_SDOOR:
109 *msr |= 0x5ull << (63 - 45);
110 break;
111 case POWERPC_EXCP_SDOOR_HV:
112 *msr |= 0x3ull << (63 - 45);
113 break;
114 case POWERPC_EXCP_HV_MAINT:
115 *msr |= 0xaull << (63 - 45);
116 break;
117 case POWERPC_EXCP_HVIRT:
118 *msr |= 0x9ull << (63 - 45);
119 break;
120 default:
121 cpu_abort(cs, "Unsupported exception %d in Power Save mode\n",
122 excp);
124 return POWERPC_EXCP_RESET;
127 static uint64_t ppc_excp_vector_offset(CPUState *cs, int ail)
129 uint64_t offset = 0;
131 switch (ail) {
132 case AIL_NONE:
133 break;
134 case AIL_0001_8000:
135 offset = 0x18000;
136 break;
137 case AIL_C000_0000_0000_4000:
138 offset = 0xc000000000004000ull;
139 break;
140 default:
141 cpu_abort(cs, "Invalid AIL combination %d\n", ail);
142 break;
145 return offset;
148 static inline void powerpc_set_excp_state(PowerPCCPU *cpu,
149 target_ulong vector, target_ulong msr)
151 CPUState *cs = CPU(cpu);
152 CPUPPCState *env = &cpu->env;
155 * We don't use hreg_store_msr here as already have treated any
156 * special case that could occur. Just store MSR and update hflags
158 * Note: We *MUST* not use hreg_store_msr() as-is anyway because it
159 * will prevent setting of the HV bit which some exceptions might need
160 * to do.
162 env->msr = msr & env->msr_mask;
163 hreg_compute_hflags(env);
164 env->nip = vector;
165 /* Reset exception state */
166 cs->exception_index = POWERPC_EXCP_NONE;
167 env->error_code = 0;
169 /* Reset the reservation */
170 env->reserve_addr = -1;
173 * Any interrupt is context synchronizing, check if TCG TLB needs
174 * a delayed flush on ppc64
176 check_tlb_flush(env, false);
180 * Note that this function should be greatly optimized when called
181 * with a constant excp, from ppc_hw_interrupt
183 static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
185 CPUState *cs = CPU(cpu);
186 CPUPPCState *env = &cpu->env;
187 target_ulong msr, new_msr, vector;
188 int srr0, srr1, asrr0, asrr1, lev, ail;
189 bool lpes0;
191 qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx
192 " => %08x (%02x)\n", env->nip, excp, env->error_code);
194 /* new srr1 value excluding must-be-zero bits */
195 if (excp_model == POWERPC_EXCP_BOOKE) {
196 msr = env->msr;
197 } else {
198 msr = env->msr & ~0x783f0000ULL;
202 * new interrupt handler msr preserves existing HV and ME unless
203 * explicitly overriden
205 new_msr = env->msr & (((target_ulong)1 << MSR_ME) | MSR_HVB);
207 /* target registers */
208 srr0 = SPR_SRR0;
209 srr1 = SPR_SRR1;
210 asrr0 = -1;
211 asrr1 = -1;
214 * check for special resume at 0x100 from doze/nap/sleep/winkle on
215 * P7/P8/P9
217 if (env->resume_as_sreset) {
218 excp = powerpc_reset_wakeup(cs, env, excp, &msr);
222 * Exception targetting modifiers
224 * LPES0 is supported on POWER7/8/9
225 * LPES1 is not supported (old iSeries mode)
227 * On anything else, we behave as if LPES0 is 1
228 * (externals don't alter MSR:HV)
230 * AIL is initialized here but can be cleared by
231 * selected exceptions
233 #if defined(TARGET_PPC64)
234 if (excp_model == POWERPC_EXCP_POWER7 ||
235 excp_model == POWERPC_EXCP_POWER8 ||
236 excp_model == POWERPC_EXCP_POWER9) {
237 lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0);
238 if (excp_model != POWERPC_EXCP_POWER7) {
239 ail = (env->spr[SPR_LPCR] & LPCR_AIL) >> LPCR_AIL_SHIFT;
240 } else {
241 ail = 0;
243 } else
244 #endif /* defined(TARGET_PPC64) */
246 lpes0 = true;
247 ail = 0;
251 * Hypervisor emulation assistance interrupt only exists on server
252 * arch 2.05 server or later. We also don't want to generate it if
253 * we don't have HVB in msr_mask (PAPR mode).
255 if (excp == POWERPC_EXCP_HV_EMU
256 #if defined(TARGET_PPC64)
257 && !((env->mmu_model & POWERPC_MMU_64) && (env->msr_mask & MSR_HVB))
258 #endif /* defined(TARGET_PPC64) */
261 excp = POWERPC_EXCP_PROGRAM;
264 switch (excp) {
265 case POWERPC_EXCP_NONE:
266 /* Should never happen */
267 return;
268 case POWERPC_EXCP_CRITICAL: /* Critical input */
269 switch (excp_model) {
270 case POWERPC_EXCP_40x:
271 srr0 = SPR_40x_SRR2;
272 srr1 = SPR_40x_SRR3;
273 break;
274 case POWERPC_EXCP_BOOKE:
275 srr0 = SPR_BOOKE_CSRR0;
276 srr1 = SPR_BOOKE_CSRR1;
277 break;
278 case POWERPC_EXCP_G2:
279 break;
280 default:
281 goto excp_invalid;
283 break;
284 case POWERPC_EXCP_MCHECK: /* Machine check exception */
285 if (msr_me == 0) {
287 * Machine check exception is not enabled. Enter
288 * checkstop state.
290 fprintf(stderr, "Machine check while not allowed. "
291 "Entering checkstop state\n");
292 if (qemu_log_separate()) {
293 qemu_log("Machine check while not allowed. "
294 "Entering checkstop state\n");
296 cs->halted = 1;
297 cpu_interrupt_exittb(cs);
299 if (env->msr_mask & MSR_HVB) {
301 * ISA specifies HV, but can be delivered to guest with HV
302 * clear (e.g., see FWNMI in PAPR).
304 new_msr |= (target_ulong)MSR_HVB;
306 ail = 0;
308 /* machine check exceptions don't have ME set */
309 new_msr &= ~((target_ulong)1 << MSR_ME);
311 /* XXX: should also have something loaded in DAR / DSISR */
312 switch (excp_model) {
313 case POWERPC_EXCP_40x:
314 srr0 = SPR_40x_SRR2;
315 srr1 = SPR_40x_SRR3;
316 break;
317 case POWERPC_EXCP_BOOKE:
318 /* FIXME: choose one or the other based on CPU type */
319 srr0 = SPR_BOOKE_MCSRR0;
320 srr1 = SPR_BOOKE_MCSRR1;
321 asrr0 = SPR_BOOKE_CSRR0;
322 asrr1 = SPR_BOOKE_CSRR1;
323 break;
324 default:
325 break;
327 break;
328 case POWERPC_EXCP_DSI: /* Data storage exception */
329 LOG_EXCP("DSI exception: DSISR=" TARGET_FMT_lx" DAR=" TARGET_FMT_lx
330 "\n", env->spr[SPR_DSISR], env->spr[SPR_DAR]);
331 break;
332 case POWERPC_EXCP_ISI: /* Instruction storage exception */
333 LOG_EXCP("ISI exception: msr=" TARGET_FMT_lx ", nip=" TARGET_FMT_lx
334 "\n", msr, env->nip);
335 msr |= env->error_code;
336 break;
337 case POWERPC_EXCP_EXTERNAL: /* External input */
338 cs = CPU(cpu);
340 if (!lpes0) {
341 new_msr |= (target_ulong)MSR_HVB;
342 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
343 srr0 = SPR_HSRR0;
344 srr1 = SPR_HSRR1;
346 if (env->mpic_proxy) {
347 /* IACK the IRQ on delivery */
348 env->spr[SPR_BOOKE_EPR] = ldl_phys(cs->as, env->mpic_iack);
350 break;
351 case POWERPC_EXCP_ALIGN: /* Alignment exception */
352 /* Get rS/rD and rA from faulting opcode */
354 * Note: the opcode fields will not be set properly for a
355 * direct store load/store, but nobody cares as nobody
356 * actually uses direct store segments.
358 env->spr[SPR_DSISR] |= (env->error_code & 0x03FF0000) >> 16;
359 break;
360 case POWERPC_EXCP_PROGRAM: /* Program exception */
361 switch (env->error_code & ~0xF) {
362 case POWERPC_EXCP_FP:
363 if ((msr_fe0 == 0 && msr_fe1 == 0) || msr_fp == 0) {
364 LOG_EXCP("Ignore floating point exception\n");
365 cs->exception_index = POWERPC_EXCP_NONE;
366 env->error_code = 0;
367 return;
371 * FP exceptions always have NIP pointing to the faulting
372 * instruction, so always use store_next and claim we are
373 * precise in the MSR.
375 msr |= 0x00100000;
376 env->spr[SPR_BOOKE_ESR] = ESR_FP;
377 break;
378 case POWERPC_EXCP_INVAL:
379 LOG_EXCP("Invalid instruction at " TARGET_FMT_lx "\n", env->nip);
380 msr |= 0x00080000;
381 env->spr[SPR_BOOKE_ESR] = ESR_PIL;
382 break;
383 case POWERPC_EXCP_PRIV:
384 msr |= 0x00040000;
385 env->spr[SPR_BOOKE_ESR] = ESR_PPR;
386 break;
387 case POWERPC_EXCP_TRAP:
388 msr |= 0x00020000;
389 env->spr[SPR_BOOKE_ESR] = ESR_PTR;
390 break;
391 default:
392 /* Should never occur */
393 cpu_abort(cs, "Invalid program exception %d. Aborting\n",
394 env->error_code);
395 break;
397 break;
398 case POWERPC_EXCP_SYSCALL: /* System call exception */
399 lev = env->error_code;
401 if ((lev == 1) && cpu->vhyp) {
402 dump_hcall(env);
403 } else {
404 dump_syscall(env);
408 * We need to correct the NIP which in this case is supposed
409 * to point to the next instruction
411 env->nip += 4;
413 /* "PAPR mode" built-in hypercall emulation */
414 if ((lev == 1) && cpu->vhyp) {
415 PPCVirtualHypervisorClass *vhc =
416 PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
417 vhc->hypercall(cpu->vhyp, cpu);
418 return;
420 if (lev == 1) {
421 new_msr |= (target_ulong)MSR_HVB;
423 break;
424 case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */
425 case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */
426 case POWERPC_EXCP_DECR: /* Decrementer exception */
427 break;
428 case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */
429 /* FIT on 4xx */
430 LOG_EXCP("FIT exception\n");
431 break;
432 case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */
433 LOG_EXCP("WDT exception\n");
434 switch (excp_model) {
435 case POWERPC_EXCP_BOOKE:
436 srr0 = SPR_BOOKE_CSRR0;
437 srr1 = SPR_BOOKE_CSRR1;
438 break;
439 default:
440 break;
442 break;
443 case POWERPC_EXCP_DTLB: /* Data TLB error */
444 case POWERPC_EXCP_ITLB: /* Instruction TLB error */
445 break;
446 case POWERPC_EXCP_DEBUG: /* Debug interrupt */
447 if (env->flags & POWERPC_FLAG_DE) {
448 /* FIXME: choose one or the other based on CPU type */
449 srr0 = SPR_BOOKE_DSRR0;
450 srr1 = SPR_BOOKE_DSRR1;
451 asrr0 = SPR_BOOKE_CSRR0;
452 asrr1 = SPR_BOOKE_CSRR1;
453 /* DBSR already modified by caller */
454 } else {
455 cpu_abort(cs, "Debug exception triggered on unsupported model\n");
457 break;
458 case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavailable */
459 env->spr[SPR_BOOKE_ESR] = ESR_SPV;
460 break;
461 case POWERPC_EXCP_EFPDI: /* Embedded floating-point data interrupt */
462 /* XXX: TODO */
463 cpu_abort(cs, "Embedded floating point data exception "
464 "is not implemented yet !\n");
465 env->spr[SPR_BOOKE_ESR] = ESR_SPV;
466 break;
467 case POWERPC_EXCP_EFPRI: /* Embedded floating-point round interrupt */
468 /* XXX: TODO */
469 cpu_abort(cs, "Embedded floating point round exception "
470 "is not implemented yet !\n");
471 env->spr[SPR_BOOKE_ESR] = ESR_SPV;
472 break;
473 case POWERPC_EXCP_EPERFM: /* Embedded performance monitor interrupt */
474 /* XXX: TODO */
475 cpu_abort(cs,
476 "Performance counter exception is not implemented yet !\n");
477 break;
478 case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */
479 break;
480 case POWERPC_EXCP_DOORCI: /* Embedded doorbell critical interrupt */
481 srr0 = SPR_BOOKE_CSRR0;
482 srr1 = SPR_BOOKE_CSRR1;
483 break;
484 case POWERPC_EXCP_RESET: /* System reset exception */
485 /* A power-saving exception sets ME, otherwise it is unchanged */
486 if (msr_pow) {
487 /* indicate that we resumed from power save mode */
488 msr |= 0x10000;
489 new_msr |= ((target_ulong)1 << MSR_ME);
491 if (env->msr_mask & MSR_HVB) {
493 * ISA specifies HV, but can be delivered to guest with HV
494 * clear (e.g., see FWNMI in PAPR, NMI injection in QEMU).
496 new_msr |= (target_ulong)MSR_HVB;
497 } else {
498 if (msr_pow) {
499 cpu_abort(cs, "Trying to deliver power-saving system reset "
500 "exception %d with no HV support\n", excp);
503 ail = 0;
504 break;
505 case POWERPC_EXCP_DSEG: /* Data segment exception */
506 case POWERPC_EXCP_ISEG: /* Instruction segment exception */
507 case POWERPC_EXCP_TRACE: /* Trace exception */
508 break;
509 case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception */
510 case POWERPC_EXCP_HDSI: /* Hypervisor data storage exception */
511 case POWERPC_EXCP_HISI: /* Hypervisor instruction storage exception */
512 case POWERPC_EXCP_HDSEG: /* Hypervisor data segment exception */
513 case POWERPC_EXCP_HISEG: /* Hypervisor instruction segment exception */
514 case POWERPC_EXCP_SDOOR_HV: /* Hypervisor Doorbell interrupt */
515 case POWERPC_EXCP_HV_EMU:
516 case POWERPC_EXCP_HVIRT: /* Hypervisor virtualization */
517 srr0 = SPR_HSRR0;
518 srr1 = SPR_HSRR1;
519 new_msr |= (target_ulong)MSR_HVB;
520 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
521 break;
522 case POWERPC_EXCP_VPU: /* Vector unavailable exception */
523 case POWERPC_EXCP_VSXU: /* VSX unavailable exception */
524 case POWERPC_EXCP_FU: /* Facility unavailable exception */
525 #ifdef TARGET_PPC64
526 env->spr[SPR_FSCR] |= ((target_ulong)env->error_code << 56);
527 #endif
528 break;
529 case POWERPC_EXCP_HV_FU: /* Hypervisor Facility Unavailable Exception */
530 #ifdef TARGET_PPC64
531 env->spr[SPR_HFSCR] |= ((target_ulong)env->error_code << FSCR_IC_POS);
532 srr0 = SPR_HSRR0;
533 srr1 = SPR_HSRR1;
534 new_msr |= (target_ulong)MSR_HVB;
535 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
536 #endif
537 break;
538 case POWERPC_EXCP_PIT: /* Programmable interval timer interrupt */
539 LOG_EXCP("PIT exception\n");
540 break;
541 case POWERPC_EXCP_IO: /* IO error exception */
542 /* XXX: TODO */
543 cpu_abort(cs, "601 IO error exception is not implemented yet !\n");
544 break;
545 case POWERPC_EXCP_RUNM: /* Run mode exception */
546 /* XXX: TODO */
547 cpu_abort(cs, "601 run mode exception is not implemented yet !\n");
548 break;
549 case POWERPC_EXCP_EMUL: /* Emulation trap exception */
550 /* XXX: TODO */
551 cpu_abort(cs, "602 emulation trap exception "
552 "is not implemented yet !\n");
553 break;
554 case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */
555 switch (excp_model) {
556 case POWERPC_EXCP_602:
557 case POWERPC_EXCP_603:
558 case POWERPC_EXCP_603E:
559 case POWERPC_EXCP_G2:
560 goto tlb_miss_tgpr;
561 case POWERPC_EXCP_7x5:
562 goto tlb_miss;
563 case POWERPC_EXCP_74xx:
564 goto tlb_miss_74xx;
565 default:
566 cpu_abort(cs, "Invalid instruction TLB miss exception\n");
567 break;
569 break;
570 case POWERPC_EXCP_DLTLB: /* Data load TLB miss */
571 switch (excp_model) {
572 case POWERPC_EXCP_602:
573 case POWERPC_EXCP_603:
574 case POWERPC_EXCP_603E:
575 case POWERPC_EXCP_G2:
576 goto tlb_miss_tgpr;
577 case POWERPC_EXCP_7x5:
578 goto tlb_miss;
579 case POWERPC_EXCP_74xx:
580 goto tlb_miss_74xx;
581 default:
582 cpu_abort(cs, "Invalid data load TLB miss exception\n");
583 break;
585 break;
586 case POWERPC_EXCP_DSTLB: /* Data store TLB miss */
587 switch (excp_model) {
588 case POWERPC_EXCP_602:
589 case POWERPC_EXCP_603:
590 case POWERPC_EXCP_603E:
591 case POWERPC_EXCP_G2:
592 tlb_miss_tgpr:
593 /* Swap temporary saved registers with GPRs */
594 if (!(new_msr & ((target_ulong)1 << MSR_TGPR))) {
595 new_msr |= (target_ulong)1 << MSR_TGPR;
596 hreg_swap_gpr_tgpr(env);
598 goto tlb_miss;
599 case POWERPC_EXCP_7x5:
600 tlb_miss:
601 #if defined(DEBUG_SOFTWARE_TLB)
602 if (qemu_log_enabled()) {
603 const char *es;
604 target_ulong *miss, *cmp;
605 int en;
607 if (excp == POWERPC_EXCP_IFTLB) {
608 es = "I";
609 en = 'I';
610 miss = &env->spr[SPR_IMISS];
611 cmp = &env->spr[SPR_ICMP];
612 } else {
613 if (excp == POWERPC_EXCP_DLTLB) {
614 es = "DL";
615 } else {
616 es = "DS";
618 en = 'D';
619 miss = &env->spr[SPR_DMISS];
620 cmp = &env->spr[SPR_DCMP];
622 qemu_log("6xx %sTLB miss: %cM " TARGET_FMT_lx " %cC "
623 TARGET_FMT_lx " H1 " TARGET_FMT_lx " H2 "
624 TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp,
625 env->spr[SPR_HASH1], env->spr[SPR_HASH2],
626 env->error_code);
628 #endif
629 msr |= env->crf[0] << 28;
630 msr |= env->error_code; /* key, D/I, S/L bits */
631 /* Set way using a LRU mechanism */
632 msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17;
633 break;
634 case POWERPC_EXCP_74xx:
635 tlb_miss_74xx:
636 #if defined(DEBUG_SOFTWARE_TLB)
637 if (qemu_log_enabled()) {
638 const char *es;
639 target_ulong *miss, *cmp;
640 int en;
642 if (excp == POWERPC_EXCP_IFTLB) {
643 es = "I";
644 en = 'I';
645 miss = &env->spr[SPR_TLBMISS];
646 cmp = &env->spr[SPR_PTEHI];
647 } else {
648 if (excp == POWERPC_EXCP_DLTLB) {
649 es = "DL";
650 } else {
651 es = "DS";
653 en = 'D';
654 miss = &env->spr[SPR_TLBMISS];
655 cmp = &env->spr[SPR_PTEHI];
657 qemu_log("74xx %sTLB miss: %cM " TARGET_FMT_lx " %cC "
658 TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp,
659 env->error_code);
661 #endif
662 msr |= env->error_code; /* key bit */
663 break;
664 default:
665 cpu_abort(cs, "Invalid data store TLB miss exception\n");
666 break;
668 break;
669 case POWERPC_EXCP_FPA: /* Floating-point assist exception */
670 /* XXX: TODO */
671 cpu_abort(cs, "Floating point assist exception "
672 "is not implemented yet !\n");
673 break;
674 case POWERPC_EXCP_DABR: /* Data address breakpoint */
675 /* XXX: TODO */
676 cpu_abort(cs, "DABR exception is not implemented yet !\n");
677 break;
678 case POWERPC_EXCP_IABR: /* Instruction address breakpoint */
679 /* XXX: TODO */
680 cpu_abort(cs, "IABR exception is not implemented yet !\n");
681 break;
682 case POWERPC_EXCP_SMI: /* System management interrupt */
683 /* XXX: TODO */
684 cpu_abort(cs, "SMI exception is not implemented yet !\n");
685 break;
686 case POWERPC_EXCP_THERM: /* Thermal interrupt */
687 /* XXX: TODO */
688 cpu_abort(cs, "Thermal management exception "
689 "is not implemented yet !\n");
690 break;
691 case POWERPC_EXCP_PERFM: /* Embedded performance monitor interrupt */
692 /* XXX: TODO */
693 cpu_abort(cs,
694 "Performance counter exception is not implemented yet !\n");
695 break;
696 case POWERPC_EXCP_VPUA: /* Vector assist exception */
697 /* XXX: TODO */
698 cpu_abort(cs, "VPU assist exception is not implemented yet !\n");
699 break;
700 case POWERPC_EXCP_SOFTP: /* Soft patch exception */
701 /* XXX: TODO */
702 cpu_abort(cs,
703 "970 soft-patch exception is not implemented yet !\n");
704 break;
705 case POWERPC_EXCP_MAINT: /* Maintenance exception */
706 /* XXX: TODO */
707 cpu_abort(cs,
708 "970 maintenance exception is not implemented yet !\n");
709 break;
710 case POWERPC_EXCP_MEXTBR: /* Maskable external breakpoint */
711 /* XXX: TODO */
712 cpu_abort(cs, "Maskable external exception "
713 "is not implemented yet !\n");
714 break;
715 case POWERPC_EXCP_NMEXTBR: /* Non maskable external breakpoint */
716 /* XXX: TODO */
717 cpu_abort(cs, "Non maskable external exception "
718 "is not implemented yet !\n");
719 break;
720 default:
721 excp_invalid:
722 cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp);
723 break;
726 /* Save PC */
727 env->spr[srr0] = env->nip;
729 /* Save MSR */
730 env->spr[srr1] = msr;
732 /* Sanity check */
733 if (!(env->msr_mask & MSR_HVB)) {
734 if (new_msr & MSR_HVB) {
735 cpu_abort(cs, "Trying to deliver HV exception (MSR) %d with "
736 "no HV support\n", excp);
738 if (srr0 == SPR_HSRR0) {
739 cpu_abort(cs, "Trying to deliver HV exception (HSRR) %d with "
740 "no HV support\n", excp);
744 /* If any alternate SRR register are defined, duplicate saved values */
745 if (asrr0 != -1) {
746 env->spr[asrr0] = env->spr[srr0];
748 if (asrr1 != -1) {
749 env->spr[asrr1] = env->spr[srr1];
753 * Sort out endianness of interrupt, this differs depending on the
754 * CPU, the HV mode, etc...
756 #ifdef TARGET_PPC64
757 if (excp_model == POWERPC_EXCP_POWER7) {
758 if (!(new_msr & MSR_HVB) && (env->spr[SPR_LPCR] & LPCR_ILE)) {
759 new_msr |= (target_ulong)1 << MSR_LE;
761 } else if (excp_model == POWERPC_EXCP_POWER8) {
762 if (new_msr & MSR_HVB) {
763 if (env->spr[SPR_HID0] & HID0_HILE) {
764 new_msr |= (target_ulong)1 << MSR_LE;
766 } else if (env->spr[SPR_LPCR] & LPCR_ILE) {
767 new_msr |= (target_ulong)1 << MSR_LE;
769 } else if (excp_model == POWERPC_EXCP_POWER9) {
770 if (new_msr & MSR_HVB) {
771 if (env->spr[SPR_HID0] & HID0_POWER9_HILE) {
772 new_msr |= (target_ulong)1 << MSR_LE;
774 } else if (env->spr[SPR_LPCR] & LPCR_ILE) {
775 new_msr |= (target_ulong)1 << MSR_LE;
777 } else if (msr_ile) {
778 new_msr |= (target_ulong)1 << MSR_LE;
780 #else
781 if (msr_ile) {
782 new_msr |= (target_ulong)1 << MSR_LE;
784 #endif
786 /* Jump to handler */
787 vector = env->excp_vectors[excp];
788 if (vector == (target_ulong)-1ULL) {
789 cpu_abort(cs, "Raised an exception without defined vector %d\n",
790 excp);
792 vector |= env->excp_prefix;
795 * AIL only works if there is no HV transition and we are running
796 * with translations enabled
798 if (!((msr >> MSR_IR) & 1) || !((msr >> MSR_DR) & 1) ||
799 ((new_msr & MSR_HVB) && !(msr & MSR_HVB))) {
800 ail = 0;
802 /* Handle AIL */
803 if (ail) {
804 new_msr |= (1 << MSR_IR) | (1 << MSR_DR);
805 vector |= ppc_excp_vector_offset(cs, ail);
808 #if defined(TARGET_PPC64)
809 if (excp_model == POWERPC_EXCP_BOOKE) {
810 if (env->spr[SPR_BOOKE_EPCR] & EPCR_ICM) {
811 /* Cat.64-bit: EPCR.ICM is copied to MSR.CM */
812 new_msr |= (target_ulong)1 << MSR_CM;
813 } else {
814 vector = (uint32_t)vector;
816 } else {
817 if (!msr_isf && !(env->mmu_model & POWERPC_MMU_64)) {
818 vector = (uint32_t)vector;
819 } else {
820 new_msr |= (target_ulong)1 << MSR_SF;
823 #endif
825 powerpc_set_excp_state(cpu, vector, new_msr);
828 void ppc_cpu_do_interrupt(CPUState *cs)
830 PowerPCCPU *cpu = POWERPC_CPU(cs);
831 CPUPPCState *env = &cpu->env;
833 powerpc_excp(cpu, env->excp_model, cs->exception_index);
836 static void ppc_hw_interrupt(CPUPPCState *env)
838 PowerPCCPU *cpu = env_archcpu(env);
839 bool async_deliver;
841 /* External reset */
842 if (env->pending_interrupts & (1 << PPC_INTERRUPT_RESET)) {
843 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_RESET);
844 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_RESET);
845 return;
847 /* Machine check exception */
848 if (env->pending_interrupts & (1 << PPC_INTERRUPT_MCK)) {
849 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_MCK);
850 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_MCHECK);
851 return;
853 #if 0 /* TODO */
854 /* External debug exception */
855 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DEBUG)) {
856 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DEBUG);
857 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DEBUG);
858 return;
860 #endif
863 * For interrupts that gate on MSR:EE, we need to do something a
864 * bit more subtle, as we need to let them through even when EE is
865 * clear when coming out of some power management states (in order
866 * for them to become a 0x100).
868 async_deliver = (msr_ee != 0) || env->resume_as_sreset;
870 /* Hypervisor decrementer exception */
871 if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDECR)) {
872 /* LPCR will be clear when not supported so this will work */
873 bool hdice = !!(env->spr[SPR_LPCR] & LPCR_HDICE);
874 if ((async_deliver || msr_hv == 0) && hdice) {
875 /* HDEC clears on delivery */
876 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR);
877 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_HDECR);
878 return;
882 /* Hypervisor virtualization interrupt */
883 if (env->pending_interrupts & (1 << PPC_INTERRUPT_HVIRT)) {
884 /* LPCR will be clear when not supported so this will work */
885 bool hvice = !!(env->spr[SPR_LPCR] & LPCR_HVICE);
886 if ((async_deliver || msr_hv == 0) && hvice) {
887 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_HVIRT);
888 return;
892 /* External interrupt can ignore MSR:EE under some circumstances */
893 if (env->pending_interrupts & (1 << PPC_INTERRUPT_EXT)) {
894 bool lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0);
895 bool heic = !!(env->spr[SPR_LPCR] & LPCR_HEIC);
896 /* HEIC blocks delivery to the hypervisor */
897 if ((async_deliver && !(heic && msr_hv && !msr_pr)) ||
898 (env->has_hv_mode && msr_hv == 0 && !lpes0)) {
899 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_EXTERNAL);
900 return;
903 if (msr_ce != 0) {
904 /* External critical interrupt */
905 if (env->pending_interrupts & (1 << PPC_INTERRUPT_CEXT)) {
906 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_CRITICAL);
907 return;
910 if (async_deliver != 0) {
911 /* Watchdog timer on embedded PowerPC */
912 if (env->pending_interrupts & (1 << PPC_INTERRUPT_WDT)) {
913 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_WDT);
914 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_WDT);
915 return;
917 if (env->pending_interrupts & (1 << PPC_INTERRUPT_CDOORBELL)) {
918 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CDOORBELL);
919 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DOORCI);
920 return;
922 /* Fixed interval timer on embedded PowerPC */
923 if (env->pending_interrupts & (1 << PPC_INTERRUPT_FIT)) {
924 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_FIT);
925 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_FIT);
926 return;
928 /* Programmable interval timer on embedded PowerPC */
929 if (env->pending_interrupts & (1 << PPC_INTERRUPT_PIT)) {
930 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PIT);
931 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_PIT);
932 return;
934 /* Decrementer exception */
935 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DECR)) {
936 if (ppc_decr_clear_on_delivery(env)) {
937 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DECR);
939 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DECR);
940 return;
942 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DOORBELL)) {
943 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DOORBELL);
944 if (is_book3s_arch2x(env)) {
945 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_SDOOR);
946 } else {
947 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DOORI);
949 return;
951 if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDOORBELL)) {
952 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDOORBELL);
953 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_SDOOR_HV);
954 return;
956 if (env->pending_interrupts & (1 << PPC_INTERRUPT_PERFM)) {
957 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PERFM);
958 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_PERFM);
959 return;
961 /* Thermal interrupt */
962 if (env->pending_interrupts & (1 << PPC_INTERRUPT_THERM)) {
963 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_THERM);
964 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_THERM);
965 return;
969 if (env->resume_as_sreset) {
971 * This is a bug ! It means that has_work took us out of halt without
972 * anything to deliver while in a PM state that requires getting
973 * out via a 0x100
975 * This means we will incorrectly execute past the power management
976 * instruction instead of triggering a reset.
978 * It generally means a discrepancy between the wakup conditions in the
979 * processor has_work implementation and the logic in this function.
981 cpu_abort(env_cpu(env),
982 "Wakeup from PM state but interrupt Undelivered");
986 void ppc_cpu_do_system_reset(CPUState *cs, target_ulong vector)
988 PowerPCCPU *cpu = POWERPC_CPU(cs);
989 CPUPPCState *env = &cpu->env;
991 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_RESET);
992 if (vector != -1) {
993 env->nip = vector;
997 void ppc_cpu_do_fwnmi_machine_check(CPUState *cs, target_ulong vector)
999 PowerPCCPU *cpu = POWERPC_CPU(cs);
1000 CPUPPCState *env = &cpu->env;
1001 PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
1002 target_ulong msr = 0;
1005 * Set MSR and NIP for the handler, SRR0/1, DAR and DSISR have already
1006 * been set by KVM.
1008 msr = (1ULL << MSR_ME);
1009 msr |= env->msr & (1ULL << MSR_SF);
1010 if (!(*pcc->interrupts_big_endian)(cpu)) {
1011 msr |= (1ULL << MSR_LE);
1014 powerpc_set_excp_state(cpu, vector, msr);
1016 #endif /* !CONFIG_USER_ONLY */
1018 bool ppc_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
1020 PowerPCCPU *cpu = POWERPC_CPU(cs);
1021 CPUPPCState *env = &cpu->env;
1023 if (interrupt_request & CPU_INTERRUPT_HARD) {
1024 ppc_hw_interrupt(env);
1025 if (env->pending_interrupts == 0) {
1026 cs->interrupt_request &= ~CPU_INTERRUPT_HARD;
1028 return true;
1030 return false;
1033 #if defined(DEBUG_OP)
1034 static void cpu_dump_rfi(target_ulong RA, target_ulong msr)
1036 qemu_log("Return from exception at " TARGET_FMT_lx " with flags "
1037 TARGET_FMT_lx "\n", RA, msr);
1039 #endif
1041 /*****************************************************************************/
1042 /* Exceptions processing helpers */
1044 void raise_exception_err_ra(CPUPPCState *env, uint32_t exception,
1045 uint32_t error_code, uintptr_t raddr)
1047 CPUState *cs = env_cpu(env);
1049 cs->exception_index = exception;
1050 env->error_code = error_code;
1051 cpu_loop_exit_restore(cs, raddr);
1054 void raise_exception_err(CPUPPCState *env, uint32_t exception,
1055 uint32_t error_code)
1057 raise_exception_err_ra(env, exception, error_code, 0);
1060 void raise_exception(CPUPPCState *env, uint32_t exception)
1062 raise_exception_err_ra(env, exception, 0, 0);
1065 void raise_exception_ra(CPUPPCState *env, uint32_t exception,
1066 uintptr_t raddr)
1068 raise_exception_err_ra(env, exception, 0, raddr);
1071 void helper_raise_exception_err(CPUPPCState *env, uint32_t exception,
1072 uint32_t error_code)
1074 raise_exception_err_ra(env, exception, error_code, 0);
1077 void helper_raise_exception(CPUPPCState *env, uint32_t exception)
1079 raise_exception_err_ra(env, exception, 0, 0);
1082 #if !defined(CONFIG_USER_ONLY)
1083 void helper_store_msr(CPUPPCState *env, target_ulong val)
1085 uint32_t excp = hreg_store_msr(env, val, 0);
1087 if (excp != 0) {
1088 CPUState *cs = env_cpu(env);
1089 cpu_interrupt_exittb(cs);
1090 raise_exception(env, excp);
1094 #if defined(TARGET_PPC64)
1095 void helper_pminsn(CPUPPCState *env, powerpc_pm_insn_t insn)
1097 CPUState *cs;
1099 cs = env_cpu(env);
1100 cs->halted = 1;
1103 * The architecture specifies that HDEC interrupts are discarded
1104 * in PM states
1106 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR);
1108 /* Condition for waking up at 0x100 */
1109 env->resume_as_sreset = (insn != PPC_PM_STOP) ||
1110 (env->spr[SPR_PSSCR] & PSSCR_EC);
1112 #endif /* defined(TARGET_PPC64) */
1114 static inline void do_rfi(CPUPPCState *env, target_ulong nip, target_ulong msr)
1116 CPUState *cs = env_cpu(env);
1118 /* MSR:POW cannot be set by any form of rfi */
1119 msr &= ~(1ULL << MSR_POW);
1121 #if defined(TARGET_PPC64)
1122 /* Switching to 32-bit ? Crop the nip */
1123 if (!msr_is_64bit(env, msr)) {
1124 nip = (uint32_t)nip;
1126 #else
1127 nip = (uint32_t)nip;
1128 #endif
1129 /* XXX: beware: this is false if VLE is supported */
1130 env->nip = nip & ~((target_ulong)0x00000003);
1131 hreg_store_msr(env, msr, 1);
1132 #if defined(DEBUG_OP)
1133 cpu_dump_rfi(env->nip, env->msr);
1134 #endif
1136 * No need to raise an exception here, as rfi is always the last
1137 * insn of a TB
1139 cpu_interrupt_exittb(cs);
1140 /* Reset the reservation */
1141 env->reserve_addr = -1;
1143 /* Context synchronizing: check if TCG TLB needs flush */
1144 check_tlb_flush(env, false);
1147 void helper_rfi(CPUPPCState *env)
1149 do_rfi(env, env->spr[SPR_SRR0], env->spr[SPR_SRR1] & 0xfffffffful);
1152 #define MSR_BOOK3S_MASK
1153 #if defined(TARGET_PPC64)
1154 void helper_rfid(CPUPPCState *env)
1157 * The architeture defines a number of rules for which bits can
1158 * change but in practice, we handle this in hreg_store_msr()
1159 * which will be called by do_rfi(), so there is no need to filter
1160 * here
1162 do_rfi(env, env->spr[SPR_SRR0], env->spr[SPR_SRR1]);
1165 void helper_hrfid(CPUPPCState *env)
1167 do_rfi(env, env->spr[SPR_HSRR0], env->spr[SPR_HSRR1]);
1169 #endif
1171 /*****************************************************************************/
1172 /* Embedded PowerPC specific helpers */
1173 void helper_40x_rfci(CPUPPCState *env)
1175 do_rfi(env, env->spr[SPR_40x_SRR2], env->spr[SPR_40x_SRR3]);
1178 void helper_rfci(CPUPPCState *env)
1180 do_rfi(env, env->spr[SPR_BOOKE_CSRR0], env->spr[SPR_BOOKE_CSRR1]);
1183 void helper_rfdi(CPUPPCState *env)
1185 /* FIXME: choose CSRR1 or DSRR1 based on cpu type */
1186 do_rfi(env, env->spr[SPR_BOOKE_DSRR0], env->spr[SPR_BOOKE_DSRR1]);
1189 void helper_rfmci(CPUPPCState *env)
1191 /* FIXME: choose CSRR1 or MCSRR1 based on cpu type */
1192 do_rfi(env, env->spr[SPR_BOOKE_MCSRR0], env->spr[SPR_BOOKE_MCSRR1]);
1194 #endif
1196 void helper_tw(CPUPPCState *env, target_ulong arg1, target_ulong arg2,
1197 uint32_t flags)
1199 if (!likely(!(((int32_t)arg1 < (int32_t)arg2 && (flags & 0x10)) ||
1200 ((int32_t)arg1 > (int32_t)arg2 && (flags & 0x08)) ||
1201 ((int32_t)arg1 == (int32_t)arg2 && (flags & 0x04)) ||
1202 ((uint32_t)arg1 < (uint32_t)arg2 && (flags & 0x02)) ||
1203 ((uint32_t)arg1 > (uint32_t)arg2 && (flags & 0x01))))) {
1204 raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
1205 POWERPC_EXCP_TRAP, GETPC());
1209 #if defined(TARGET_PPC64)
1210 void helper_td(CPUPPCState *env, target_ulong arg1, target_ulong arg2,
1211 uint32_t flags)
1213 if (!likely(!(((int64_t)arg1 < (int64_t)arg2 && (flags & 0x10)) ||
1214 ((int64_t)arg1 > (int64_t)arg2 && (flags & 0x08)) ||
1215 ((int64_t)arg1 == (int64_t)arg2 && (flags & 0x04)) ||
1216 ((uint64_t)arg1 < (uint64_t)arg2 && (flags & 0x02)) ||
1217 ((uint64_t)arg1 > (uint64_t)arg2 && (flags & 0x01))))) {
1218 raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
1219 POWERPC_EXCP_TRAP, GETPC());
1222 #endif
1224 #if !defined(CONFIG_USER_ONLY)
1225 /*****************************************************************************/
1226 /* PowerPC 601 specific instructions (POWER bridge) */
1228 void helper_rfsvc(CPUPPCState *env)
1230 do_rfi(env, env->lr, env->ctr & 0x0000FFFF);
1233 /* Embedded.Processor Control */
1234 static int dbell2irq(target_ulong rb)
1236 int msg = rb & DBELL_TYPE_MASK;
1237 int irq = -1;
1239 switch (msg) {
1240 case DBELL_TYPE_DBELL:
1241 irq = PPC_INTERRUPT_DOORBELL;
1242 break;
1243 case DBELL_TYPE_DBELL_CRIT:
1244 irq = PPC_INTERRUPT_CDOORBELL;
1245 break;
1246 case DBELL_TYPE_G_DBELL:
1247 case DBELL_TYPE_G_DBELL_CRIT:
1248 case DBELL_TYPE_G_DBELL_MC:
1249 /* XXX implement */
1250 default:
1251 break;
1254 return irq;
1257 void helper_msgclr(CPUPPCState *env, target_ulong rb)
1259 int irq = dbell2irq(rb);
1261 if (irq < 0) {
1262 return;
1265 env->pending_interrupts &= ~(1 << irq);
1268 void helper_msgsnd(target_ulong rb)
1270 int irq = dbell2irq(rb);
1271 int pir = rb & DBELL_PIRTAG_MASK;
1272 CPUState *cs;
1274 if (irq < 0) {
1275 return;
1278 qemu_mutex_lock_iothread();
1279 CPU_FOREACH(cs) {
1280 PowerPCCPU *cpu = POWERPC_CPU(cs);
1281 CPUPPCState *cenv = &cpu->env;
1283 if ((rb & DBELL_BRDCAST) || (cenv->spr[SPR_BOOKE_PIR] == pir)) {
1284 cenv->pending_interrupts |= 1 << irq;
1285 cpu_interrupt(cs, CPU_INTERRUPT_HARD);
1288 qemu_mutex_unlock_iothread();
1291 /* Server Processor Control */
1293 static bool dbell_type_server(target_ulong rb)
1296 * A Directed Hypervisor Doorbell message is sent only if the
1297 * message type is 5. All other types are reserved and the
1298 * instruction is a no-op
1300 return (rb & DBELL_TYPE_MASK) == DBELL_TYPE_DBELL_SERVER;
1303 void helper_book3s_msgclr(CPUPPCState *env, target_ulong rb)
1305 if (!dbell_type_server(rb)) {
1306 return;
1309 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDOORBELL);
1312 static void book3s_msgsnd_common(int pir, int irq)
1314 CPUState *cs;
1316 qemu_mutex_lock_iothread();
1317 CPU_FOREACH(cs) {
1318 PowerPCCPU *cpu = POWERPC_CPU(cs);
1319 CPUPPCState *cenv = &cpu->env;
1321 /* TODO: broadcast message to all threads of the same processor */
1322 if (cenv->spr_cb[SPR_PIR].default_value == pir) {
1323 cenv->pending_interrupts |= 1 << irq;
1324 cpu_interrupt(cs, CPU_INTERRUPT_HARD);
1327 qemu_mutex_unlock_iothread();
1330 void helper_book3s_msgsnd(target_ulong rb)
1332 int pir = rb & DBELL_PROCIDTAG_MASK;
1334 if (!dbell_type_server(rb)) {
1335 return;
1338 book3s_msgsnd_common(pir, PPC_INTERRUPT_HDOORBELL);
1341 #if defined(TARGET_PPC64)
1342 void helper_book3s_msgclrp(CPUPPCState *env, target_ulong rb)
1344 helper_hfscr_facility_check(env, HFSCR_MSGP, "msgclrp", HFSCR_IC_MSGP);
1346 if (!dbell_type_server(rb)) {
1347 return;
1350 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DOORBELL);
1354 * sends a message to other threads that are on the same
1355 * multi-threaded processor
1357 void helper_book3s_msgsndp(CPUPPCState *env, target_ulong rb)
1359 int pir = env->spr_cb[SPR_PIR].default_value;
1361 helper_hfscr_facility_check(env, HFSCR_MSGP, "msgsndp", HFSCR_IC_MSGP);
1363 if (!dbell_type_server(rb)) {
1364 return;
1367 /* TODO: TCG supports only one thread */
1369 book3s_msgsnd_common(pir, PPC_INTERRUPT_DOORBELL);
1371 #endif
1372 #endif
1374 void ppc_cpu_do_unaligned_access(CPUState *cs, vaddr vaddr,
1375 MMUAccessType access_type,
1376 int mmu_idx, uintptr_t retaddr)
1378 CPUPPCState *env = cs->env_ptr;
1379 uint32_t insn;
1381 /* Restore state and reload the insn we executed, for filling in DSISR. */
1382 cpu_restore_state(cs, retaddr, true);
1383 insn = cpu_ldl_code(env, env->nip);
1385 cs->exception_index = POWERPC_EXCP_ALIGN;
1386 env->error_code = insn & 0x03FF0000;
1387 cpu_loop_exit(cs);