target/ppc: Add support for Radix partition-scoped translation
[qemu/ar7.git] / target / ppc / excp_helper.c
blobf0529796647208372e79cf4be51abb8d52d2c537
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_HISI: /* Hypervisor instruction storage exception */
510 msr |= env->error_code;
511 case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception */
512 case POWERPC_EXCP_HDSI: /* Hypervisor data storage exception */
513 case POWERPC_EXCP_HDSEG: /* Hypervisor data segment exception */
514 case POWERPC_EXCP_HISEG: /* Hypervisor instruction segment exception */
515 case POWERPC_EXCP_SDOOR_HV: /* Hypervisor Doorbell interrupt */
516 case POWERPC_EXCP_HV_EMU:
517 case POWERPC_EXCP_HVIRT: /* Hypervisor virtualization */
518 srr0 = SPR_HSRR0;
519 srr1 = SPR_HSRR1;
520 new_msr |= (target_ulong)MSR_HVB;
521 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
522 break;
523 case POWERPC_EXCP_VPU: /* Vector unavailable exception */
524 case POWERPC_EXCP_VSXU: /* VSX unavailable exception */
525 case POWERPC_EXCP_FU: /* Facility unavailable exception */
526 #ifdef TARGET_PPC64
527 env->spr[SPR_FSCR] |= ((target_ulong)env->error_code << 56);
528 #endif
529 break;
530 case POWERPC_EXCP_HV_FU: /* Hypervisor Facility Unavailable Exception */
531 #ifdef TARGET_PPC64
532 env->spr[SPR_HFSCR] |= ((target_ulong)env->error_code << FSCR_IC_POS);
533 srr0 = SPR_HSRR0;
534 srr1 = SPR_HSRR1;
535 new_msr |= (target_ulong)MSR_HVB;
536 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
537 #endif
538 break;
539 case POWERPC_EXCP_PIT: /* Programmable interval timer interrupt */
540 LOG_EXCP("PIT exception\n");
541 break;
542 case POWERPC_EXCP_IO: /* IO error exception */
543 /* XXX: TODO */
544 cpu_abort(cs, "601 IO error exception is not implemented yet !\n");
545 break;
546 case POWERPC_EXCP_RUNM: /* Run mode exception */
547 /* XXX: TODO */
548 cpu_abort(cs, "601 run mode exception is not implemented yet !\n");
549 break;
550 case POWERPC_EXCP_EMUL: /* Emulation trap exception */
551 /* XXX: TODO */
552 cpu_abort(cs, "602 emulation trap exception "
553 "is not implemented yet !\n");
554 break;
555 case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */
556 switch (excp_model) {
557 case POWERPC_EXCP_602:
558 case POWERPC_EXCP_603:
559 case POWERPC_EXCP_603E:
560 case POWERPC_EXCP_G2:
561 goto tlb_miss_tgpr;
562 case POWERPC_EXCP_7x5:
563 goto tlb_miss;
564 case POWERPC_EXCP_74xx:
565 goto tlb_miss_74xx;
566 default:
567 cpu_abort(cs, "Invalid instruction TLB miss exception\n");
568 break;
570 break;
571 case POWERPC_EXCP_DLTLB: /* Data load TLB miss */
572 switch (excp_model) {
573 case POWERPC_EXCP_602:
574 case POWERPC_EXCP_603:
575 case POWERPC_EXCP_603E:
576 case POWERPC_EXCP_G2:
577 goto tlb_miss_tgpr;
578 case POWERPC_EXCP_7x5:
579 goto tlb_miss;
580 case POWERPC_EXCP_74xx:
581 goto tlb_miss_74xx;
582 default:
583 cpu_abort(cs, "Invalid data load TLB miss exception\n");
584 break;
586 break;
587 case POWERPC_EXCP_DSTLB: /* Data store TLB miss */
588 switch (excp_model) {
589 case POWERPC_EXCP_602:
590 case POWERPC_EXCP_603:
591 case POWERPC_EXCP_603E:
592 case POWERPC_EXCP_G2:
593 tlb_miss_tgpr:
594 /* Swap temporary saved registers with GPRs */
595 if (!(new_msr & ((target_ulong)1 << MSR_TGPR))) {
596 new_msr |= (target_ulong)1 << MSR_TGPR;
597 hreg_swap_gpr_tgpr(env);
599 goto tlb_miss;
600 case POWERPC_EXCP_7x5:
601 tlb_miss:
602 #if defined(DEBUG_SOFTWARE_TLB)
603 if (qemu_log_enabled()) {
604 const char *es;
605 target_ulong *miss, *cmp;
606 int en;
608 if (excp == POWERPC_EXCP_IFTLB) {
609 es = "I";
610 en = 'I';
611 miss = &env->spr[SPR_IMISS];
612 cmp = &env->spr[SPR_ICMP];
613 } else {
614 if (excp == POWERPC_EXCP_DLTLB) {
615 es = "DL";
616 } else {
617 es = "DS";
619 en = 'D';
620 miss = &env->spr[SPR_DMISS];
621 cmp = &env->spr[SPR_DCMP];
623 qemu_log("6xx %sTLB miss: %cM " TARGET_FMT_lx " %cC "
624 TARGET_FMT_lx " H1 " TARGET_FMT_lx " H2 "
625 TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp,
626 env->spr[SPR_HASH1], env->spr[SPR_HASH2],
627 env->error_code);
629 #endif
630 msr |= env->crf[0] << 28;
631 msr |= env->error_code; /* key, D/I, S/L bits */
632 /* Set way using a LRU mechanism */
633 msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17;
634 break;
635 case POWERPC_EXCP_74xx:
636 tlb_miss_74xx:
637 #if defined(DEBUG_SOFTWARE_TLB)
638 if (qemu_log_enabled()) {
639 const char *es;
640 target_ulong *miss, *cmp;
641 int en;
643 if (excp == POWERPC_EXCP_IFTLB) {
644 es = "I";
645 en = 'I';
646 miss = &env->spr[SPR_TLBMISS];
647 cmp = &env->spr[SPR_PTEHI];
648 } else {
649 if (excp == POWERPC_EXCP_DLTLB) {
650 es = "DL";
651 } else {
652 es = "DS";
654 en = 'D';
655 miss = &env->spr[SPR_TLBMISS];
656 cmp = &env->spr[SPR_PTEHI];
658 qemu_log("74xx %sTLB miss: %cM " TARGET_FMT_lx " %cC "
659 TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp,
660 env->error_code);
662 #endif
663 msr |= env->error_code; /* key bit */
664 break;
665 default:
666 cpu_abort(cs, "Invalid data store TLB miss exception\n");
667 break;
669 break;
670 case POWERPC_EXCP_FPA: /* Floating-point assist exception */
671 /* XXX: TODO */
672 cpu_abort(cs, "Floating point assist exception "
673 "is not implemented yet !\n");
674 break;
675 case POWERPC_EXCP_DABR: /* Data address breakpoint */
676 /* XXX: TODO */
677 cpu_abort(cs, "DABR exception is not implemented yet !\n");
678 break;
679 case POWERPC_EXCP_IABR: /* Instruction address breakpoint */
680 /* XXX: TODO */
681 cpu_abort(cs, "IABR exception is not implemented yet !\n");
682 break;
683 case POWERPC_EXCP_SMI: /* System management interrupt */
684 /* XXX: TODO */
685 cpu_abort(cs, "SMI exception is not implemented yet !\n");
686 break;
687 case POWERPC_EXCP_THERM: /* Thermal interrupt */
688 /* XXX: TODO */
689 cpu_abort(cs, "Thermal management exception "
690 "is not implemented yet !\n");
691 break;
692 case POWERPC_EXCP_PERFM: /* Embedded performance monitor interrupt */
693 /* XXX: TODO */
694 cpu_abort(cs,
695 "Performance counter exception is not implemented yet !\n");
696 break;
697 case POWERPC_EXCP_VPUA: /* Vector assist exception */
698 /* XXX: TODO */
699 cpu_abort(cs, "VPU assist exception is not implemented yet !\n");
700 break;
701 case POWERPC_EXCP_SOFTP: /* Soft patch exception */
702 /* XXX: TODO */
703 cpu_abort(cs,
704 "970 soft-patch exception is not implemented yet !\n");
705 break;
706 case POWERPC_EXCP_MAINT: /* Maintenance exception */
707 /* XXX: TODO */
708 cpu_abort(cs,
709 "970 maintenance exception is not implemented yet !\n");
710 break;
711 case POWERPC_EXCP_MEXTBR: /* Maskable external breakpoint */
712 /* XXX: TODO */
713 cpu_abort(cs, "Maskable external exception "
714 "is not implemented yet !\n");
715 break;
716 case POWERPC_EXCP_NMEXTBR: /* Non maskable external breakpoint */
717 /* XXX: TODO */
718 cpu_abort(cs, "Non maskable external exception "
719 "is not implemented yet !\n");
720 break;
721 default:
722 excp_invalid:
723 cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp);
724 break;
727 /* Save PC */
728 env->spr[srr0] = env->nip;
730 /* Save MSR */
731 env->spr[srr1] = msr;
733 /* Sanity check */
734 if (!(env->msr_mask & MSR_HVB)) {
735 if (new_msr & MSR_HVB) {
736 cpu_abort(cs, "Trying to deliver HV exception (MSR) %d with "
737 "no HV support\n", excp);
739 if (srr0 == SPR_HSRR0) {
740 cpu_abort(cs, "Trying to deliver HV exception (HSRR) %d with "
741 "no HV support\n", excp);
745 /* If any alternate SRR register are defined, duplicate saved values */
746 if (asrr0 != -1) {
747 env->spr[asrr0] = env->spr[srr0];
749 if (asrr1 != -1) {
750 env->spr[asrr1] = env->spr[srr1];
754 * Sort out endianness of interrupt, this differs depending on the
755 * CPU, the HV mode, etc...
757 #ifdef TARGET_PPC64
758 if (excp_model == POWERPC_EXCP_POWER7) {
759 if (!(new_msr & MSR_HVB) && (env->spr[SPR_LPCR] & LPCR_ILE)) {
760 new_msr |= (target_ulong)1 << MSR_LE;
762 } else if (excp_model == POWERPC_EXCP_POWER8) {
763 if (new_msr & MSR_HVB) {
764 if (env->spr[SPR_HID0] & HID0_HILE) {
765 new_msr |= (target_ulong)1 << MSR_LE;
767 } else if (env->spr[SPR_LPCR] & LPCR_ILE) {
768 new_msr |= (target_ulong)1 << MSR_LE;
770 } else if (excp_model == POWERPC_EXCP_POWER9) {
771 if (new_msr & MSR_HVB) {
772 if (env->spr[SPR_HID0] & HID0_POWER9_HILE) {
773 new_msr |= (target_ulong)1 << MSR_LE;
775 } else if (env->spr[SPR_LPCR] & LPCR_ILE) {
776 new_msr |= (target_ulong)1 << MSR_LE;
778 } else if (msr_ile) {
779 new_msr |= (target_ulong)1 << MSR_LE;
781 #else
782 if (msr_ile) {
783 new_msr |= (target_ulong)1 << MSR_LE;
785 #endif
787 /* Jump to handler */
788 vector = env->excp_vectors[excp];
789 if (vector == (target_ulong)-1ULL) {
790 cpu_abort(cs, "Raised an exception without defined vector %d\n",
791 excp);
793 vector |= env->excp_prefix;
796 * AIL only works if there is no HV transition and we are running
797 * with translations enabled
799 if (!((msr >> MSR_IR) & 1) || !((msr >> MSR_DR) & 1) ||
800 ((new_msr & MSR_HVB) && !(msr & MSR_HVB))) {
801 ail = 0;
803 /* Handle AIL */
804 if (ail) {
805 new_msr |= (1 << MSR_IR) | (1 << MSR_DR);
806 vector |= ppc_excp_vector_offset(cs, ail);
809 #if defined(TARGET_PPC64)
810 if (excp_model == POWERPC_EXCP_BOOKE) {
811 if (env->spr[SPR_BOOKE_EPCR] & EPCR_ICM) {
812 /* Cat.64-bit: EPCR.ICM is copied to MSR.CM */
813 new_msr |= (target_ulong)1 << MSR_CM;
814 } else {
815 vector = (uint32_t)vector;
817 } else {
818 if (!msr_isf && !(env->mmu_model & POWERPC_MMU_64)) {
819 vector = (uint32_t)vector;
820 } else {
821 new_msr |= (target_ulong)1 << MSR_SF;
824 #endif
826 powerpc_set_excp_state(cpu, vector, new_msr);
829 void ppc_cpu_do_interrupt(CPUState *cs)
831 PowerPCCPU *cpu = POWERPC_CPU(cs);
832 CPUPPCState *env = &cpu->env;
834 powerpc_excp(cpu, env->excp_model, cs->exception_index);
837 static void ppc_hw_interrupt(CPUPPCState *env)
839 PowerPCCPU *cpu = env_archcpu(env);
840 bool async_deliver;
842 /* External reset */
843 if (env->pending_interrupts & (1 << PPC_INTERRUPT_RESET)) {
844 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_RESET);
845 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_RESET);
846 return;
848 /* Machine check exception */
849 if (env->pending_interrupts & (1 << PPC_INTERRUPT_MCK)) {
850 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_MCK);
851 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_MCHECK);
852 return;
854 #if 0 /* TODO */
855 /* External debug exception */
856 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DEBUG)) {
857 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DEBUG);
858 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DEBUG);
859 return;
861 #endif
864 * For interrupts that gate on MSR:EE, we need to do something a
865 * bit more subtle, as we need to let them through even when EE is
866 * clear when coming out of some power management states (in order
867 * for them to become a 0x100).
869 async_deliver = (msr_ee != 0) || env->resume_as_sreset;
871 /* Hypervisor decrementer exception */
872 if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDECR)) {
873 /* LPCR will be clear when not supported so this will work */
874 bool hdice = !!(env->spr[SPR_LPCR] & LPCR_HDICE);
875 if ((async_deliver || msr_hv == 0) && hdice) {
876 /* HDEC clears on delivery */
877 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR);
878 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_HDECR);
879 return;
883 /* Hypervisor virtualization interrupt */
884 if (env->pending_interrupts & (1 << PPC_INTERRUPT_HVIRT)) {
885 /* LPCR will be clear when not supported so this will work */
886 bool hvice = !!(env->spr[SPR_LPCR] & LPCR_HVICE);
887 if ((async_deliver || msr_hv == 0) && hvice) {
888 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_HVIRT);
889 return;
893 /* External interrupt can ignore MSR:EE under some circumstances */
894 if (env->pending_interrupts & (1 << PPC_INTERRUPT_EXT)) {
895 bool lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0);
896 bool heic = !!(env->spr[SPR_LPCR] & LPCR_HEIC);
897 /* HEIC blocks delivery to the hypervisor */
898 if ((async_deliver && !(heic && msr_hv && !msr_pr)) ||
899 (env->has_hv_mode && msr_hv == 0 && !lpes0)) {
900 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_EXTERNAL);
901 return;
904 if (msr_ce != 0) {
905 /* External critical interrupt */
906 if (env->pending_interrupts & (1 << PPC_INTERRUPT_CEXT)) {
907 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_CRITICAL);
908 return;
911 if (async_deliver != 0) {
912 /* Watchdog timer on embedded PowerPC */
913 if (env->pending_interrupts & (1 << PPC_INTERRUPT_WDT)) {
914 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_WDT);
915 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_WDT);
916 return;
918 if (env->pending_interrupts & (1 << PPC_INTERRUPT_CDOORBELL)) {
919 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CDOORBELL);
920 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DOORCI);
921 return;
923 /* Fixed interval timer on embedded PowerPC */
924 if (env->pending_interrupts & (1 << PPC_INTERRUPT_FIT)) {
925 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_FIT);
926 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_FIT);
927 return;
929 /* Programmable interval timer on embedded PowerPC */
930 if (env->pending_interrupts & (1 << PPC_INTERRUPT_PIT)) {
931 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PIT);
932 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_PIT);
933 return;
935 /* Decrementer exception */
936 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DECR)) {
937 if (ppc_decr_clear_on_delivery(env)) {
938 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DECR);
940 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DECR);
941 return;
943 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DOORBELL)) {
944 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DOORBELL);
945 if (is_book3s_arch2x(env)) {
946 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_SDOOR);
947 } else {
948 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DOORI);
950 return;
952 if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDOORBELL)) {
953 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDOORBELL);
954 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_SDOOR_HV);
955 return;
957 if (env->pending_interrupts & (1 << PPC_INTERRUPT_PERFM)) {
958 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PERFM);
959 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_PERFM);
960 return;
962 /* Thermal interrupt */
963 if (env->pending_interrupts & (1 << PPC_INTERRUPT_THERM)) {
964 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_THERM);
965 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_THERM);
966 return;
970 if (env->resume_as_sreset) {
972 * This is a bug ! It means that has_work took us out of halt without
973 * anything to deliver while in a PM state that requires getting
974 * out via a 0x100
976 * This means we will incorrectly execute past the power management
977 * instruction instead of triggering a reset.
979 * It generally means a discrepancy between the wakup conditions in the
980 * processor has_work implementation and the logic in this function.
982 cpu_abort(env_cpu(env),
983 "Wakeup from PM state but interrupt Undelivered");
987 void ppc_cpu_do_system_reset(CPUState *cs)
989 PowerPCCPU *cpu = POWERPC_CPU(cs);
990 CPUPPCState *env = &cpu->env;
992 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_RESET);
995 void ppc_cpu_do_fwnmi_machine_check(CPUState *cs, target_ulong vector)
997 PowerPCCPU *cpu = POWERPC_CPU(cs);
998 CPUPPCState *env = &cpu->env;
999 PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
1000 target_ulong msr = 0;
1003 * Set MSR and NIP for the handler, SRR0/1, DAR and DSISR have already
1004 * been set by KVM.
1006 msr = (1ULL << MSR_ME);
1007 msr |= env->msr & (1ULL << MSR_SF);
1008 if (!(*pcc->interrupts_big_endian)(cpu)) {
1009 msr |= (1ULL << MSR_LE);
1012 powerpc_set_excp_state(cpu, vector, msr);
1014 #endif /* !CONFIG_USER_ONLY */
1016 bool ppc_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
1018 PowerPCCPU *cpu = POWERPC_CPU(cs);
1019 CPUPPCState *env = &cpu->env;
1021 if (interrupt_request & CPU_INTERRUPT_HARD) {
1022 ppc_hw_interrupt(env);
1023 if (env->pending_interrupts == 0) {
1024 cs->interrupt_request &= ~CPU_INTERRUPT_HARD;
1026 return true;
1028 return false;
1031 #if defined(DEBUG_OP)
1032 static void cpu_dump_rfi(target_ulong RA, target_ulong msr)
1034 qemu_log("Return from exception at " TARGET_FMT_lx " with flags "
1035 TARGET_FMT_lx "\n", RA, msr);
1037 #endif
1039 /*****************************************************************************/
1040 /* Exceptions processing helpers */
1042 void raise_exception_err_ra(CPUPPCState *env, uint32_t exception,
1043 uint32_t error_code, uintptr_t raddr)
1045 CPUState *cs = env_cpu(env);
1047 cs->exception_index = exception;
1048 env->error_code = error_code;
1049 cpu_loop_exit_restore(cs, raddr);
1052 void raise_exception_err(CPUPPCState *env, uint32_t exception,
1053 uint32_t error_code)
1055 raise_exception_err_ra(env, exception, error_code, 0);
1058 void raise_exception(CPUPPCState *env, uint32_t exception)
1060 raise_exception_err_ra(env, exception, 0, 0);
1063 void raise_exception_ra(CPUPPCState *env, uint32_t exception,
1064 uintptr_t raddr)
1066 raise_exception_err_ra(env, exception, 0, raddr);
1069 void helper_raise_exception_err(CPUPPCState *env, uint32_t exception,
1070 uint32_t error_code)
1072 raise_exception_err_ra(env, exception, error_code, 0);
1075 void helper_raise_exception(CPUPPCState *env, uint32_t exception)
1077 raise_exception_err_ra(env, exception, 0, 0);
1080 #if !defined(CONFIG_USER_ONLY)
1081 void helper_store_msr(CPUPPCState *env, target_ulong val)
1083 uint32_t excp = hreg_store_msr(env, val, 0);
1085 if (excp != 0) {
1086 CPUState *cs = env_cpu(env);
1087 cpu_interrupt_exittb(cs);
1088 raise_exception(env, excp);
1092 #if defined(TARGET_PPC64)
1093 void helper_pminsn(CPUPPCState *env, powerpc_pm_insn_t insn)
1095 CPUState *cs;
1097 cs = env_cpu(env);
1098 cs->halted = 1;
1101 * The architecture specifies that HDEC interrupts are discarded
1102 * in PM states
1104 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR);
1106 /* Condition for waking up at 0x100 */
1107 env->resume_as_sreset = (insn != PPC_PM_STOP) ||
1108 (env->spr[SPR_PSSCR] & PSSCR_EC);
1110 #endif /* defined(TARGET_PPC64) */
1112 static inline void do_rfi(CPUPPCState *env, target_ulong nip, target_ulong msr)
1114 CPUState *cs = env_cpu(env);
1116 /* MSR:POW cannot be set by any form of rfi */
1117 msr &= ~(1ULL << MSR_POW);
1119 #if defined(TARGET_PPC64)
1120 /* Switching to 32-bit ? Crop the nip */
1121 if (!msr_is_64bit(env, msr)) {
1122 nip = (uint32_t)nip;
1124 #else
1125 nip = (uint32_t)nip;
1126 #endif
1127 /* XXX: beware: this is false if VLE is supported */
1128 env->nip = nip & ~((target_ulong)0x00000003);
1129 hreg_store_msr(env, msr, 1);
1130 #if defined(DEBUG_OP)
1131 cpu_dump_rfi(env->nip, env->msr);
1132 #endif
1134 * No need to raise an exception here, as rfi is always the last
1135 * insn of a TB
1137 cpu_interrupt_exittb(cs);
1138 /* Reset the reservation */
1139 env->reserve_addr = -1;
1141 /* Context synchronizing: check if TCG TLB needs flush */
1142 check_tlb_flush(env, false);
1145 void helper_rfi(CPUPPCState *env)
1147 do_rfi(env, env->spr[SPR_SRR0], env->spr[SPR_SRR1] & 0xfffffffful);
1150 #define MSR_BOOK3S_MASK
1151 #if defined(TARGET_PPC64)
1152 void helper_rfid(CPUPPCState *env)
1155 * The architeture defines a number of rules for which bits can
1156 * change but in practice, we handle this in hreg_store_msr()
1157 * which will be called by do_rfi(), so there is no need to filter
1158 * here
1160 do_rfi(env, env->spr[SPR_SRR0], env->spr[SPR_SRR1]);
1163 void helper_hrfid(CPUPPCState *env)
1165 do_rfi(env, env->spr[SPR_HSRR0], env->spr[SPR_HSRR1]);
1167 #endif
1169 /*****************************************************************************/
1170 /* Embedded PowerPC specific helpers */
1171 void helper_40x_rfci(CPUPPCState *env)
1173 do_rfi(env, env->spr[SPR_40x_SRR2], env->spr[SPR_40x_SRR3]);
1176 void helper_rfci(CPUPPCState *env)
1178 do_rfi(env, env->spr[SPR_BOOKE_CSRR0], env->spr[SPR_BOOKE_CSRR1]);
1181 void helper_rfdi(CPUPPCState *env)
1183 /* FIXME: choose CSRR1 or DSRR1 based on cpu type */
1184 do_rfi(env, env->spr[SPR_BOOKE_DSRR0], env->spr[SPR_BOOKE_DSRR1]);
1187 void helper_rfmci(CPUPPCState *env)
1189 /* FIXME: choose CSRR1 or MCSRR1 based on cpu type */
1190 do_rfi(env, env->spr[SPR_BOOKE_MCSRR0], env->spr[SPR_BOOKE_MCSRR1]);
1192 #endif
1194 void helper_tw(CPUPPCState *env, target_ulong arg1, target_ulong arg2,
1195 uint32_t flags)
1197 if (!likely(!(((int32_t)arg1 < (int32_t)arg2 && (flags & 0x10)) ||
1198 ((int32_t)arg1 > (int32_t)arg2 && (flags & 0x08)) ||
1199 ((int32_t)arg1 == (int32_t)arg2 && (flags & 0x04)) ||
1200 ((uint32_t)arg1 < (uint32_t)arg2 && (flags & 0x02)) ||
1201 ((uint32_t)arg1 > (uint32_t)arg2 && (flags & 0x01))))) {
1202 raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
1203 POWERPC_EXCP_TRAP, GETPC());
1207 #if defined(TARGET_PPC64)
1208 void helper_td(CPUPPCState *env, target_ulong arg1, target_ulong arg2,
1209 uint32_t flags)
1211 if (!likely(!(((int64_t)arg1 < (int64_t)arg2 && (flags & 0x10)) ||
1212 ((int64_t)arg1 > (int64_t)arg2 && (flags & 0x08)) ||
1213 ((int64_t)arg1 == (int64_t)arg2 && (flags & 0x04)) ||
1214 ((uint64_t)arg1 < (uint64_t)arg2 && (flags & 0x02)) ||
1215 ((uint64_t)arg1 > (uint64_t)arg2 && (flags & 0x01))))) {
1216 raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
1217 POWERPC_EXCP_TRAP, GETPC());
1220 #endif
1222 #if !defined(CONFIG_USER_ONLY)
1223 /*****************************************************************************/
1224 /* PowerPC 601 specific instructions (POWER bridge) */
1226 void helper_rfsvc(CPUPPCState *env)
1228 do_rfi(env, env->lr, env->ctr & 0x0000FFFF);
1231 /* Embedded.Processor Control */
1232 static int dbell2irq(target_ulong rb)
1234 int msg = rb & DBELL_TYPE_MASK;
1235 int irq = -1;
1237 switch (msg) {
1238 case DBELL_TYPE_DBELL:
1239 irq = PPC_INTERRUPT_DOORBELL;
1240 break;
1241 case DBELL_TYPE_DBELL_CRIT:
1242 irq = PPC_INTERRUPT_CDOORBELL;
1243 break;
1244 case DBELL_TYPE_G_DBELL:
1245 case DBELL_TYPE_G_DBELL_CRIT:
1246 case DBELL_TYPE_G_DBELL_MC:
1247 /* XXX implement */
1248 default:
1249 break;
1252 return irq;
1255 void helper_msgclr(CPUPPCState *env, target_ulong rb)
1257 int irq = dbell2irq(rb);
1259 if (irq < 0) {
1260 return;
1263 env->pending_interrupts &= ~(1 << irq);
1266 void helper_msgsnd(target_ulong rb)
1268 int irq = dbell2irq(rb);
1269 int pir = rb & DBELL_PIRTAG_MASK;
1270 CPUState *cs;
1272 if (irq < 0) {
1273 return;
1276 qemu_mutex_lock_iothread();
1277 CPU_FOREACH(cs) {
1278 PowerPCCPU *cpu = POWERPC_CPU(cs);
1279 CPUPPCState *cenv = &cpu->env;
1281 if ((rb & DBELL_BRDCAST) || (cenv->spr[SPR_BOOKE_PIR] == pir)) {
1282 cenv->pending_interrupts |= 1 << irq;
1283 cpu_interrupt(cs, CPU_INTERRUPT_HARD);
1286 qemu_mutex_unlock_iothread();
1289 /* Server Processor Control */
1291 static bool dbell_type_server(target_ulong rb)
1294 * A Directed Hypervisor Doorbell message is sent only if the
1295 * message type is 5. All other types are reserved and the
1296 * instruction is a no-op
1298 return (rb & DBELL_TYPE_MASK) == DBELL_TYPE_DBELL_SERVER;
1301 void helper_book3s_msgclr(CPUPPCState *env, target_ulong rb)
1303 if (!dbell_type_server(rb)) {
1304 return;
1307 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDOORBELL);
1310 static void book3s_msgsnd_common(int pir, int irq)
1312 CPUState *cs;
1314 qemu_mutex_lock_iothread();
1315 CPU_FOREACH(cs) {
1316 PowerPCCPU *cpu = POWERPC_CPU(cs);
1317 CPUPPCState *cenv = &cpu->env;
1319 /* TODO: broadcast message to all threads of the same processor */
1320 if (cenv->spr_cb[SPR_PIR].default_value == pir) {
1321 cenv->pending_interrupts |= 1 << irq;
1322 cpu_interrupt(cs, CPU_INTERRUPT_HARD);
1325 qemu_mutex_unlock_iothread();
1328 void helper_book3s_msgsnd(target_ulong rb)
1330 int pir = rb & DBELL_PROCIDTAG_MASK;
1332 if (!dbell_type_server(rb)) {
1333 return;
1336 book3s_msgsnd_common(pir, PPC_INTERRUPT_HDOORBELL);
1339 #if defined(TARGET_PPC64)
1340 void helper_book3s_msgclrp(CPUPPCState *env, target_ulong rb)
1342 helper_hfscr_facility_check(env, HFSCR_MSGP, "msgclrp", HFSCR_IC_MSGP);
1344 if (!dbell_type_server(rb)) {
1345 return;
1348 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DOORBELL);
1352 * sends a message to other threads that are on the same
1353 * multi-threaded processor
1355 void helper_book3s_msgsndp(CPUPPCState *env, target_ulong rb)
1357 int pir = env->spr_cb[SPR_PIR].default_value;
1359 helper_hfscr_facility_check(env, HFSCR_MSGP, "msgsndp", HFSCR_IC_MSGP);
1361 if (!dbell_type_server(rb)) {
1362 return;
1365 /* TODO: TCG supports only one thread */
1367 book3s_msgsnd_common(pir, PPC_INTERRUPT_DOORBELL);
1369 #endif
1370 #endif
1372 void ppc_cpu_do_unaligned_access(CPUState *cs, vaddr vaddr,
1373 MMUAccessType access_type,
1374 int mmu_idx, uintptr_t retaddr)
1376 CPUPPCState *env = cs->env_ptr;
1377 uint32_t insn;
1379 /* Restore state and reload the insn we executed, for filling in DSISR. */
1380 cpu_restore_state(cs, retaddr, true);
1381 insn = cpu_ldl_code(env, env->nip);
1383 cs->exception_index = POWERPC_EXCP_ALIGN;
1384 env->error_code = insn & 0x03FF0000;
1385 cpu_loop_exit(cs);