1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19#include "qemu/osdep.h"
20#include "qemu/main-loop.h"
21#include "cpu.h"
22#include "exec/exec-all.h"
23#include "internal.h"
24#include "helper_regs.h"
25
26#ifdef CONFIG_TCG
27#include "exec/helper-proto.h"
28#include "exec/cpu_ldst.h"
29#endif
30
31
32
33
34
35#ifdef DEBUG_EXCEPTIONS
36# define LOG_EXCP(...) qemu_log(__VA_ARGS__)
37#else
38# define LOG_EXCP(...) do { } while (0)
39#endif
40
41
42
43#if defined(CONFIG_USER_ONLY)
44void ppc_cpu_do_interrupt(CPUState *cs)
45{
46 PowerPCCPU *cpu = POWERPC_CPU(cs);
47 CPUPPCState *env = &cpu->env;
48
49 cs->exception_index = POWERPC_EXCP_NONE;
50 env->error_code = 0;
51}
52
53static void ppc_hw_interrupt(CPUPPCState *env)
54{
55 CPUState *cs = env_cpu(env);
56
57 cs->exception_index = POWERPC_EXCP_NONE;
58 env->error_code = 0;
59}
60#else
61static inline void dump_syscall(CPUPPCState *env)
62{
63 qemu_log_mask(CPU_LOG_INT, "syscall r0=%016" PRIx64
64 " r3=%016" PRIx64 " r4=%016" PRIx64 " r5=%016" PRIx64
65 " r6=%016" PRIx64 " r7=%016" PRIx64 " r8=%016" PRIx64
66 " nip=" TARGET_FMT_lx "\n",
67 ppc_dump_gpr(env, 0), ppc_dump_gpr(env, 3),
68 ppc_dump_gpr(env, 4), ppc_dump_gpr(env, 5),
69 ppc_dump_gpr(env, 6), ppc_dump_gpr(env, 7),
70 ppc_dump_gpr(env, 8), env->nip);
71}
72
73static inline void dump_hcall(CPUPPCState *env)
74{
75 qemu_log_mask(CPU_LOG_INT, "hypercall r3=%016" PRIx64
76 " r4=%016" PRIx64 " r5=%016" PRIx64 " r6=%016" PRIx64
77 " r7=%016" PRIx64 " r8=%016" PRIx64 " r9=%016" PRIx64
78 " r10=%016" PRIx64 " r11=%016" PRIx64 " r12=%016" PRIx64
79 " nip=" TARGET_FMT_lx "\n",
80 ppc_dump_gpr(env, 3), ppc_dump_gpr(env, 4),
81 ppc_dump_gpr(env, 5), ppc_dump_gpr(env, 6),
82 ppc_dump_gpr(env, 7), ppc_dump_gpr(env, 8),
83 ppc_dump_gpr(env, 9), ppc_dump_gpr(env, 10),
84 ppc_dump_gpr(env, 11), ppc_dump_gpr(env, 12),
85 env->nip);
86}
87
88static int powerpc_reset_wakeup(CPUState *cs, CPUPPCState *env, int excp,
89 target_ulong *msr)
90{
91
92 env->resume_as_sreset = false;
93
94
95 *msr |= SRR1_WS_NOLOSS;
96
97
98 if (excp == POWERPC_EXCP_MCHECK) {
99 return excp;
100 }
101 switch (excp) {
102 case POWERPC_EXCP_RESET:
103 *msr |= SRR1_WAKERESET;
104 break;
105 case POWERPC_EXCP_EXTERNAL:
106 *msr |= SRR1_WAKEEE;
107 break;
108 case POWERPC_EXCP_DECR:
109 *msr |= SRR1_WAKEDEC;
110 break;
111 case POWERPC_EXCP_SDOOR:
112 *msr |= SRR1_WAKEDBELL;
113 break;
114 case POWERPC_EXCP_SDOOR_HV:
115 *msr |= SRR1_WAKEHDBELL;
116 break;
117 case POWERPC_EXCP_HV_MAINT:
118 *msr |= SRR1_WAKEHMI;
119 break;
120 case POWERPC_EXCP_HVIRT:
121 *msr |= SRR1_WAKEHVI;
122 break;
123 default:
124 cpu_abort(cs, "Unsupported exception %d in Power Save mode\n",
125 excp);
126 }
127 return POWERPC_EXCP_RESET;
128}
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186static inline void ppc_excp_apply_ail(PowerPCCPU *cpu, int excp_model, int excp,
187 target_ulong msr,
188 target_ulong *new_msr,
189 target_ulong *vector)
190{
191#if defined(TARGET_PPC64)
192 CPUPPCState *env = &cpu->env;
193 bool mmu_all_on = ((msr >> MSR_IR) & 1) && ((msr >> MSR_DR) & 1);
194 bool hv_escalation = !(msr & MSR_HVB) && (*new_msr & MSR_HVB);
195 int ail = 0;
196
197 if (excp == POWERPC_EXCP_MCHECK ||
198 excp == POWERPC_EXCP_RESET ||
199 excp == POWERPC_EXCP_HV_MAINT) {
200
201 return;
202 }
203
204 if (excp_model == POWERPC_EXCP_POWER8 ||
205 excp_model == POWERPC_EXCP_POWER9) {
206 if (!mmu_all_on) {
207
208 return;
209 }
210 if (hv_escalation && !(env->spr[SPR_LPCR] & LPCR_HR)) {
211
212
213
214
215
216 return;
217 }
218
219 ail = (env->spr[SPR_LPCR] & LPCR_AIL) >> LPCR_AIL_SHIFT;
220 if (ail == 0) {
221 return;
222 }
223 if (ail == 1) {
224
225 return;
226 }
227
228 } else if (excp_model == POWERPC_EXCP_POWER10) {
229 if (!mmu_all_on && !hv_escalation) {
230
231
232
233
234 return;
235 }
236
237 if (*new_msr & MSR_HVB) {
238 if (!(env->spr[SPR_LPCR] & LPCR_HAIL)) {
239
240 return;
241 }
242 ail = 3;
243 } else {
244 ail = (env->spr[SPR_LPCR] & LPCR_AIL) >> LPCR_AIL_SHIFT;
245 }
246 if (ail == 0) {
247 return;
248 }
249 if (ail == 1 || ail == 2) {
250
251 return;
252 }
253 } else {
254
255 return;
256 }
257
258
259
260
261
262 *new_msr |= (1 << MSR_IR) | (1 << MSR_DR);
263
264 if (excp != POWERPC_EXCP_SYSCALL_VECTORED) {
265 if (ail == 2) {
266 *vector |= 0x0000000000018000ull;
267 } else if (ail == 3) {
268 *vector |= 0xc000000000004000ull;
269 }
270 } else {
271
272
273
274
275 if (ail == 3) {
276 *vector &= ~0x0000000000017000ull;
277 *vector |= 0xc000000000003000ull;
278 }
279 }
280#endif
281}
282
283static inline void powerpc_set_excp_state(PowerPCCPU *cpu,
284 target_ulong vector, target_ulong msr)
285{
286 CPUState *cs = CPU(cpu);
287 CPUPPCState *env = &cpu->env;
288
289
290
291
292
293
294
295
296
297 env->msr = msr & env->msr_mask;
298 hreg_compute_hflags(env);
299 env->nip = vector;
300
301 cs->exception_index = POWERPC_EXCP_NONE;
302 env->error_code = 0;
303
304
305 env->reserve_addr = -1;
306
307
308
309
310
311 check_tlb_flush(env, false);
312}
313
314
315
316
317
318static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
319{
320 CPUState *cs = CPU(cpu);
321 CPUPPCState *env = &cpu->env;
322 target_ulong msr, new_msr, vector;
323 int srr0, srr1, asrr0, asrr1, lev = -1;
324
325 qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx
326 " => %08x (%02x)\n", env->nip, excp, env->error_code);
327
328
329 if (excp_model == POWERPC_EXCP_BOOKE) {
330 msr = env->msr;
331 } else {
332 msr = env->msr & ~0x783f0000ULL;
333 }
334
335
336
337
338
339 new_msr = env->msr & (((target_ulong)1 << MSR_ME) | MSR_HVB);
340
341
342 srr0 = SPR_SRR0;
343 srr1 = SPR_SRR1;
344 asrr0 = -1;
345 asrr1 = -1;
346
347
348
349
350
351 if (env->resume_as_sreset) {
352 excp = powerpc_reset_wakeup(cs, env, excp, &msr);
353 }
354
355
356
357
358
359
360 if (excp == POWERPC_EXCP_HV_EMU
361#if defined(TARGET_PPC64)
362 && !(mmu_is_64bit(env->mmu_model) && (env->msr_mask & MSR_HVB))
363#endif
364
365 ) {
366 excp = POWERPC_EXCP_PROGRAM;
367 }
368
369 switch (excp) {
370 case POWERPC_EXCP_NONE:
371
372 return;
373 case POWERPC_EXCP_CRITICAL:
374 switch (excp_model) {
375 case POWERPC_EXCP_40x:
376 srr0 = SPR_40x_SRR2;
377 srr1 = SPR_40x_SRR3;
378 break;
379 case POWERPC_EXCP_BOOKE:
380 srr0 = SPR_BOOKE_CSRR0;
381 srr1 = SPR_BOOKE_CSRR1;
382 break;
383 case POWERPC_EXCP_G2:
384 break;
385 default:
386 goto excp_invalid;
387 }
388 break;
389 case POWERPC_EXCP_MCHECK:
390 if (msr_me == 0) {
391
392
393
394
395 fprintf(stderr, "Machine check while not allowed. "
396 "Entering checkstop state\n");
397 if (qemu_log_separate()) {
398 qemu_log("Machine check while not allowed. "
399 "Entering checkstop state\n");
400 }
401 cs->halted = 1;
402 cpu_interrupt_exittb(cs);
403 }
404 if (env->msr_mask & MSR_HVB) {
405
406
407
408
409 new_msr |= (target_ulong)MSR_HVB;
410 }
411
412
413 new_msr &= ~((target_ulong)1 << MSR_ME);
414
415
416 switch (excp_model) {
417 case POWERPC_EXCP_40x:
418 srr0 = SPR_40x_SRR2;
419 srr1 = SPR_40x_SRR3;
420 break;
421 case POWERPC_EXCP_BOOKE:
422
423 srr0 = SPR_BOOKE_MCSRR0;
424 srr1 = SPR_BOOKE_MCSRR1;
425 asrr0 = SPR_BOOKE_CSRR0;
426 asrr1 = SPR_BOOKE_CSRR1;
427 break;
428 default:
429 break;
430 }
431 break;
432 case POWERPC_EXCP_DSI:
433 LOG_EXCP("DSI exception: DSISR=" TARGET_FMT_lx" DAR=" TARGET_FMT_lx
434 "\n", env->spr[SPR_DSISR], env->spr[SPR_DAR]);
435 break;
436 case POWERPC_EXCP_ISI:
437 LOG_EXCP("ISI exception: msr=" TARGET_FMT_lx ", nip=" TARGET_FMT_lx
438 "\n", msr, env->nip);
439 msr |= env->error_code;
440 break;
441 case POWERPC_EXCP_EXTERNAL:
442 {
443 bool lpes0;
444
445 cs = CPU(cpu);
446
447
448
449
450
451
452
453
454
455
456#if defined(TARGET_PPC64)
457 if (excp_model == POWERPC_EXCP_POWER7 ||
458 excp_model == POWERPC_EXCP_POWER8 ||
459 excp_model == POWERPC_EXCP_POWER9 ||
460 excp_model == POWERPC_EXCP_POWER10) {
461 lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0);
462 } else
463#endif
464 {
465 lpes0 = true;
466 }
467
468 if (!lpes0) {
469 new_msr |= (target_ulong)MSR_HVB;
470 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
471 srr0 = SPR_HSRR0;
472 srr1 = SPR_HSRR1;
473 }
474 if (env->mpic_proxy) {
475
476 env->spr[SPR_BOOKE_EPR] = ldl_phys(cs->as, env->mpic_iack);
477 }
478 break;
479 }
480 case POWERPC_EXCP_ALIGN:
481
482
483
484
485
486
487 env->spr[SPR_DSISR] |= (env->error_code & 0x03FF0000) >> 16;
488 break;
489 case POWERPC_EXCP_PROGRAM:
490 switch (env->error_code & ~0xF) {
491 case POWERPC_EXCP_FP:
492 if ((msr_fe0 == 0 && msr_fe1 == 0) || msr_fp == 0) {
493 LOG_EXCP("Ignore floating point exception\n");
494 cs->exception_index = POWERPC_EXCP_NONE;
495 env->error_code = 0;
496 return;
497 }
498
499
500
501
502
503
504 msr |= 0x00100000;
505 env->spr[SPR_BOOKE_ESR] = ESR_FP;
506 break;
507 case POWERPC_EXCP_INVAL:
508 LOG_EXCP("Invalid instruction at " TARGET_FMT_lx "\n", env->nip);
509 msr |= 0x00080000;
510 env->spr[SPR_BOOKE_ESR] = ESR_PIL;
511 break;
512 case POWERPC_EXCP_PRIV:
513 msr |= 0x00040000;
514 env->spr[SPR_BOOKE_ESR] = ESR_PPR;
515 break;
516 case POWERPC_EXCP_TRAP:
517 msr |= 0x00020000;
518 env->spr[SPR_BOOKE_ESR] = ESR_PTR;
519 break;
520 default:
521
522 cpu_abort(cs, "Invalid program exception %d. Aborting\n",
523 env->error_code);
524 break;
525 }
526 break;
527 case POWERPC_EXCP_SYSCALL:
528 lev = env->error_code;
529
530 if ((lev == 1) && cpu->vhyp) {
531 dump_hcall(env);
532 } else {
533 dump_syscall(env);
534 }
535
536
537
538
539
540 env->nip += 4;
541
542
543 if ((lev == 1) && cpu->vhyp) {
544 PPCVirtualHypervisorClass *vhc =
545 PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
546 vhc->hypercall(cpu->vhyp, cpu);
547 return;
548 }
549 if (lev == 1) {
550 new_msr |= (target_ulong)MSR_HVB;
551 }
552 break;
553 case POWERPC_EXCP_SYSCALL_VECTORED:
554 lev = env->error_code;
555 dump_syscall(env);
556 env->nip += 4;
557 new_msr |= env->msr & ((target_ulong)1 << MSR_EE);
558 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
559 break;
560 case POWERPC_EXCP_FPU:
561 case POWERPC_EXCP_APU:
562 case POWERPC_EXCP_DECR:
563 break;
564 case POWERPC_EXCP_FIT:
565
566 LOG_EXCP("FIT exception\n");
567 break;
568 case POWERPC_EXCP_WDT:
569 LOG_EXCP("WDT exception\n");
570 switch (excp_model) {
571 case POWERPC_EXCP_BOOKE:
572 srr0 = SPR_BOOKE_CSRR0;
573 srr1 = SPR_BOOKE_CSRR1;
574 break;
575 default:
576 break;
577 }
578 break;
579 case POWERPC_EXCP_DTLB:
580 case POWERPC_EXCP_ITLB:
581 break;
582 case POWERPC_EXCP_DEBUG:
583 if (env->flags & POWERPC_FLAG_DE) {
584
585 srr0 = SPR_BOOKE_DSRR0;
586 srr1 = SPR_BOOKE_DSRR1;
587 asrr0 = SPR_BOOKE_CSRR0;
588 asrr1 = SPR_BOOKE_CSRR1;
589
590 } else {
591 cpu_abort(cs, "Debug exception triggered on unsupported model\n");
592 }
593 break;
594 case POWERPC_EXCP_SPEU:
595 env->spr[SPR_BOOKE_ESR] = ESR_SPV;
596 break;
597 case POWERPC_EXCP_EFPDI:
598
599 cpu_abort(cs, "Embedded floating point data exception "
600 "is not implemented yet !\n");
601 env->spr[SPR_BOOKE_ESR] = ESR_SPV;
602 break;
603 case POWERPC_EXCP_EFPRI:
604
605 cpu_abort(cs, "Embedded floating point round exception "
606 "is not implemented yet !\n");
607 env->spr[SPR_BOOKE_ESR] = ESR_SPV;
608 break;
609 case POWERPC_EXCP_EPERFM:
610
611 cpu_abort(cs,
612 "Performance counter exception is not implemented yet !\n");
613 break;
614 case POWERPC_EXCP_DOORI:
615 break;
616 case POWERPC_EXCP_DOORCI:
617 srr0 = SPR_BOOKE_CSRR0;
618 srr1 = SPR_BOOKE_CSRR1;
619 break;
620 case POWERPC_EXCP_RESET:
621
622 if (msr_pow) {
623
624 msr |= 0x10000;
625 new_msr |= ((target_ulong)1 << MSR_ME);
626 }
627 if (env->msr_mask & MSR_HVB) {
628
629
630
631
632 new_msr |= (target_ulong)MSR_HVB;
633 } else {
634 if (msr_pow) {
635 cpu_abort(cs, "Trying to deliver power-saving system reset "
636 "exception %d with no HV support\n", excp);
637 }
638 }
639 break;
640 case POWERPC_EXCP_DSEG:
641 case POWERPC_EXCP_ISEG:
642 case POWERPC_EXCP_TRACE:
643 break;
644 case POWERPC_EXCP_HISI:
645 msr |= env->error_code;
646
647 case POWERPC_EXCP_HDECR:
648 case POWERPC_EXCP_HDSI:
649 case POWERPC_EXCP_HDSEG:
650 case POWERPC_EXCP_HISEG:
651 case POWERPC_EXCP_SDOOR_HV:
652 case POWERPC_EXCP_HV_EMU:
653 case POWERPC_EXCP_HVIRT:
654 srr0 = SPR_HSRR0;
655 srr1 = SPR_HSRR1;
656 new_msr |= (target_ulong)MSR_HVB;
657 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
658 break;
659 case POWERPC_EXCP_VPU:
660 case POWERPC_EXCP_VSXU:
661 case POWERPC_EXCP_FU:
662#ifdef TARGET_PPC64
663 env->spr[SPR_FSCR] |= ((target_ulong)env->error_code << 56);
664#endif
665 break;
666 case POWERPC_EXCP_HV_FU:
667#ifdef TARGET_PPC64
668 env->spr[SPR_HFSCR] |= ((target_ulong)env->error_code << FSCR_IC_POS);
669 srr0 = SPR_HSRR0;
670 srr1 = SPR_HSRR1;
671 new_msr |= (target_ulong)MSR_HVB;
672 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
673#endif
674 break;
675 case POWERPC_EXCP_PIT:
676 LOG_EXCP("PIT exception\n");
677 break;
678 case POWERPC_EXCP_IO:
679
680 cpu_abort(cs, "601 IO error exception is not implemented yet !\n");
681 break;
682 case POWERPC_EXCP_RUNM:
683
684 cpu_abort(cs, "601 run mode exception is not implemented yet !\n");
685 break;
686 case POWERPC_EXCP_EMUL:
687
688 cpu_abort(cs, "602 emulation trap exception "
689 "is not implemented yet !\n");
690 break;
691 case POWERPC_EXCP_IFTLB:
692 case POWERPC_EXCP_DLTLB:
693 case POWERPC_EXCP_DSTLB:
694 switch (excp_model) {
695 case POWERPC_EXCP_602:
696 case POWERPC_EXCP_603:
697 case POWERPC_EXCP_603E:
698 case POWERPC_EXCP_G2:
699
700 if (!(new_msr & ((target_ulong)1 << MSR_TGPR))) {
701 new_msr |= (target_ulong)1 << MSR_TGPR;
702 hreg_swap_gpr_tgpr(env);
703 }
704
705 case POWERPC_EXCP_7x5:
706#if defined(DEBUG_SOFTWARE_TLB)
707 if (qemu_log_enabled()) {
708 const char *es;
709 target_ulong *miss, *cmp;
710 int en;
711
712 if (excp == POWERPC_EXCP_IFTLB) {
713 es = "I";
714 en = 'I';
715 miss = &env->spr[SPR_IMISS];
716 cmp = &env->spr[SPR_ICMP];
717 } else {
718 if (excp == POWERPC_EXCP_DLTLB) {
719 es = "DL";
720 } else {
721 es = "DS";
722 }
723 en = 'D';
724 miss = &env->spr[SPR_DMISS];
725 cmp = &env->spr[SPR_DCMP];
726 }
727 qemu_log("6xx %sTLB miss: %cM " TARGET_FMT_lx " %cC "
728 TARGET_FMT_lx " H1 " TARGET_FMT_lx " H2 "
729 TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp,
730 env->spr[SPR_HASH1], env->spr[SPR_HASH2],
731 env->error_code);
732 }
733#endif
734 msr |= env->crf[0] << 28;
735 msr |= env->error_code;
736
737 msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17;
738 break;
739 case POWERPC_EXCP_74xx:
740#if defined(DEBUG_SOFTWARE_TLB)
741 if (qemu_log_enabled()) {
742 const char *es;
743 target_ulong *miss, *cmp;
744 int en;
745
746 if (excp == POWERPC_EXCP_IFTLB) {
747 es = "I";
748 en = 'I';
749 miss = &env->spr[SPR_TLBMISS];
750 cmp = &env->spr[SPR_PTEHI];
751 } else {
752 if (excp == POWERPC_EXCP_DLTLB) {
753 es = "DL";
754 } else {
755 es = "DS";
756 }
757 en = 'D';
758 miss = &env->spr[SPR_TLBMISS];
759 cmp = &env->spr[SPR_PTEHI];
760 }
761 qemu_log("74xx %sTLB miss: %cM " TARGET_FMT_lx " %cC "
762 TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp,
763 env->error_code);
764 }
765#endif
766 msr |= env->error_code;
767 break;
768 default:
769 cpu_abort(cs, "Invalid TLB miss exception\n");
770 break;
771 }
772 break;
773 case POWERPC_EXCP_FPA:
774
775 cpu_abort(cs, "Floating point assist exception "
776 "is not implemented yet !\n");
777 break;
778 case POWERPC_EXCP_DABR:
779
780 cpu_abort(cs, "DABR exception is not implemented yet !\n");
781 break;
782 case POWERPC_EXCP_IABR:
783
784 cpu_abort(cs, "IABR exception is not implemented yet !\n");
785 break;
786 case POWERPC_EXCP_SMI:
787
788 cpu_abort(cs, "SMI exception is not implemented yet !\n");
789 break;
790 case POWERPC_EXCP_THERM:
791
792 cpu_abort(cs, "Thermal management exception "
793 "is not implemented yet !\n");
794 break;
795 case POWERPC_EXCP_PERFM:
796
797 cpu_abort(cs,
798 "Performance counter exception is not implemented yet !\n");
799 break;
800 case POWERPC_EXCP_VPUA:
801
802 cpu_abort(cs, "VPU assist exception is not implemented yet !\n");
803 break;
804 case POWERPC_EXCP_SOFTP:
805
806 cpu_abort(cs,
807 "970 soft-patch exception is not implemented yet !\n");
808 break;
809 case POWERPC_EXCP_MAINT:
810
811 cpu_abort(cs,
812 "970 maintenance exception is not implemented yet !\n");
813 break;
814 case POWERPC_EXCP_MEXTBR:
815
816 cpu_abort(cs, "Maskable external exception "
817 "is not implemented yet !\n");
818 break;
819 case POWERPC_EXCP_NMEXTBR:
820
821 cpu_abort(cs, "Non maskable external exception "
822 "is not implemented yet !\n");
823 break;
824 default:
825 excp_invalid:
826 cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp);
827 break;
828 }
829
830
831 if (!(env->msr_mask & MSR_HVB)) {
832 if (new_msr & MSR_HVB) {
833 cpu_abort(cs, "Trying to deliver HV exception (MSR) %d with "
834 "no HV support\n", excp);
835 }
836 if (srr0 == SPR_HSRR0) {
837 cpu_abort(cs, "Trying to deliver HV exception (HSRR) %d with "
838 "no HV support\n", excp);
839 }
840 }
841
842
843
844
845
846#ifdef TARGET_PPC64
847 if (excp_model == POWERPC_EXCP_POWER7) {
848 if (!(new_msr & MSR_HVB) && (env->spr[SPR_LPCR] & LPCR_ILE)) {
849 new_msr |= (target_ulong)1 << MSR_LE;
850 }
851 } else if (excp_model == POWERPC_EXCP_POWER8) {
852 if (new_msr & MSR_HVB) {
853 if (env->spr[SPR_HID0] & HID0_HILE) {
854 new_msr |= (target_ulong)1 << MSR_LE;
855 }
856 } else if (env->spr[SPR_LPCR] & LPCR_ILE) {
857 new_msr |= (target_ulong)1 << MSR_LE;
858 }
859 } else if (excp_model == POWERPC_EXCP_POWER9 ||
860 excp_model == POWERPC_EXCP_POWER10) {
861 if (new_msr & MSR_HVB) {
862 if (env->spr[SPR_HID0] & HID0_POWER9_HILE) {
863 new_msr |= (target_ulong)1 << MSR_LE;
864 }
865 } else if (env->spr[SPR_LPCR] & LPCR_ILE) {
866 new_msr |= (target_ulong)1 << MSR_LE;
867 }
868 } else if (msr_ile) {
869 new_msr |= (target_ulong)1 << MSR_LE;
870 }
871#else
872 if (msr_ile) {
873 new_msr |= (target_ulong)1 << MSR_LE;
874 }
875#endif
876
877 vector = env->excp_vectors[excp];
878 if (vector == (target_ulong)-1ULL) {
879 cpu_abort(cs, "Raised an exception without defined vector %d\n",
880 excp);
881 }
882
883 vector |= env->excp_prefix;
884
885
886 if (asrr0 != -1) {
887 env->spr[asrr0] = env->nip;
888 }
889 if (asrr1 != -1) {
890 env->spr[asrr1] = msr;
891 }
892
893#if defined(TARGET_PPC64)
894 if (excp_model == POWERPC_EXCP_BOOKE) {
895 if (env->spr[SPR_BOOKE_EPCR] & EPCR_ICM) {
896
897 new_msr |= (target_ulong)1 << MSR_CM;
898 } else {
899 vector = (uint32_t)vector;
900 }
901 } else {
902 if (!msr_isf && !mmu_is_64bit(env->mmu_model)) {
903 vector = (uint32_t)vector;
904 } else {
905 new_msr |= (target_ulong)1 << MSR_SF;
906 }
907 }
908#endif
909
910 if (excp != POWERPC_EXCP_SYSCALL_VECTORED) {
911
912 env->spr[srr0] = env->nip;
913
914
915 env->spr[srr1] = msr;
916
917#if defined(TARGET_PPC64)
918 } else {
919 vector += lev * 0x20;
920
921 env->lr = env->nip;
922 env->ctr = msr;
923#endif
924 }
925
926
927 ppc_excp_apply_ail(cpu, excp_model, excp, msr, &new_msr, &vector);
928
929 powerpc_set_excp_state(cpu, vector, new_msr);
930}
931
932void ppc_cpu_do_interrupt(CPUState *cs)
933{
934 PowerPCCPU *cpu = POWERPC_CPU(cs);
935 CPUPPCState *env = &cpu->env;
936
937 powerpc_excp(cpu, env->excp_model, cs->exception_index);
938}
939
940static void ppc_hw_interrupt(CPUPPCState *env)
941{
942 PowerPCCPU *cpu = env_archcpu(env);
943 bool async_deliver;
944
945
946 if (env->pending_interrupts & (1 << PPC_INTERRUPT_RESET)) {
947 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_RESET);
948 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_RESET);
949 return;
950 }
951
952 if (env->pending_interrupts & (1 << PPC_INTERRUPT_MCK)) {
953 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_MCK);
954 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_MCHECK);
955 return;
956 }
957#if 0
958
959 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DEBUG)) {
960 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DEBUG);
961 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DEBUG);
962 return;
963 }
964#endif
965
966
967
968
969
970
971
972 async_deliver = (msr_ee != 0) || env->resume_as_sreset;
973
974
975 if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDECR)) {
976
977 bool hdice = !!(env->spr[SPR_LPCR] & LPCR_HDICE);
978 if ((async_deliver || msr_hv == 0) && hdice) {
979
980 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR);
981 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_HDECR);
982 return;
983 }
984 }
985
986
987 if (env->pending_interrupts & (1 << PPC_INTERRUPT_HVIRT)) {
988
989 bool hvice = !!(env->spr[SPR_LPCR] & LPCR_HVICE);
990 if ((async_deliver || msr_hv == 0) && hvice) {
991 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_HVIRT);
992 return;
993 }
994 }
995
996
997 if (env->pending_interrupts & (1 << PPC_INTERRUPT_EXT)) {
998 bool lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0);
999 bool heic = !!(env->spr[SPR_LPCR] & LPCR_HEIC);
1000
1001 if ((async_deliver && !(heic && msr_hv && !msr_pr)) ||
1002 (env->has_hv_mode && msr_hv == 0 && !lpes0)) {
1003 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_EXTERNAL);
1004 return;
1005 }
1006 }
1007 if (msr_ce != 0) {
1008
1009 if (env->pending_interrupts & (1 << PPC_INTERRUPT_CEXT)) {
1010 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_CRITICAL);
1011 return;
1012 }
1013 }
1014 if (async_deliver != 0) {
1015
1016 if (env->pending_interrupts & (1 << PPC_INTERRUPT_WDT)) {
1017 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_WDT);
1018 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_WDT);
1019 return;
1020 }
1021 if (env->pending_interrupts & (1 << PPC_INTERRUPT_CDOORBELL)) {
1022 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CDOORBELL);
1023 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DOORCI);
1024 return;
1025 }
1026
1027 if (env->pending_interrupts & (1 << PPC_INTERRUPT_FIT)) {
1028 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_FIT);
1029 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_FIT);
1030 return;
1031 }
1032
1033 if (env->pending_interrupts & (1 << PPC_INTERRUPT_PIT)) {
1034 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PIT);
1035 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_PIT);
1036 return;
1037 }
1038
1039 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DECR)) {
1040 if (ppc_decr_clear_on_delivery(env)) {
1041 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DECR);
1042 }
1043 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DECR);
1044 return;
1045 }
1046 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DOORBELL)) {
1047 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DOORBELL);
1048 if (is_book3s_arch2x(env)) {
1049 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_SDOOR);
1050 } else {
1051 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DOORI);
1052 }
1053 return;
1054 }
1055 if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDOORBELL)) {
1056 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDOORBELL);
1057 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_SDOOR_HV);
1058 return;
1059 }
1060 if (env->pending_interrupts & (1 << PPC_INTERRUPT_PERFM)) {
1061 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PERFM);
1062 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_PERFM);
1063 return;
1064 }
1065
1066 if (env->pending_interrupts & (1 << PPC_INTERRUPT_THERM)) {
1067 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_THERM);
1068 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_THERM);
1069 return;
1070 }
1071 }
1072
1073 if (env->resume_as_sreset) {
1074
1075
1076
1077
1078
1079
1080
1081
1082
1083
1084
1085 cpu_abort(env_cpu(env),
1086 "Wakeup from PM state but interrupt Undelivered");
1087 }
1088}
1089
1090void ppc_cpu_do_system_reset(CPUState *cs)
1091{
1092 PowerPCCPU *cpu = POWERPC_CPU(cs);
1093 CPUPPCState *env = &cpu->env;
1094
1095 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_RESET);
1096}
1097
1098void ppc_cpu_do_fwnmi_machine_check(CPUState *cs, target_ulong vector)
1099{
1100 PowerPCCPU *cpu = POWERPC_CPU(cs);
1101 CPUPPCState *env = &cpu->env;
1102 target_ulong msr = 0;
1103
1104
1105
1106
1107
1108 msr = (1ULL << MSR_ME);
1109 msr |= env->msr & (1ULL << MSR_SF);
1110 if (ppc_interrupts_little_endian(cpu)) {
1111 msr |= (1ULL << MSR_LE);
1112 }
1113
1114 powerpc_set_excp_state(cpu, vector, msr);
1115}
1116#endif
1117
1118bool ppc_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
1119{
1120 PowerPCCPU *cpu = POWERPC_CPU(cs);
1121 CPUPPCState *env = &cpu->env;
1122
1123 if (interrupt_request & CPU_INTERRUPT_HARD) {
1124 ppc_hw_interrupt(env);
1125 if (env->pending_interrupts == 0) {
1126 cs->interrupt_request &= ~CPU_INTERRUPT_HARD;
1127 }
1128 return true;
1129 }
1130 return false;
1131}
1132
1133#if defined(DEBUG_OP)
1134static void cpu_dump_rfi(target_ulong RA, target_ulong msr)
1135{
1136 qemu_log("Return from exception at " TARGET_FMT_lx " with flags "
1137 TARGET_FMT_lx "\n", RA, msr);
1138}
1139#endif
1140
1141
1142
1143
1144void raise_exception_err_ra(CPUPPCState *env, uint32_t exception,
1145 uint32_t error_code, uintptr_t raddr)
1146{
1147 CPUState *cs = env_cpu(env);
1148
1149 cs->exception_index = exception;
1150 env->error_code = error_code;
1151 cpu_loop_exit_restore(cs, raddr);
1152}
1153
1154void raise_exception_err(CPUPPCState *env, uint32_t exception,
1155 uint32_t error_code)
1156{
1157 raise_exception_err_ra(env, exception, error_code, 0);
1158}
1159
1160void raise_exception(CPUPPCState *env, uint32_t exception)
1161{
1162 raise_exception_err_ra(env, exception, 0, 0);
1163}
1164
1165void raise_exception_ra(CPUPPCState *env, uint32_t exception,
1166 uintptr_t raddr)
1167{
1168 raise_exception_err_ra(env, exception, 0, raddr);
1169}
1170
1171#ifdef CONFIG_TCG
1172void helper_raise_exception_err(CPUPPCState *env, uint32_t exception,
1173 uint32_t error_code)
1174{
1175 raise_exception_err_ra(env, exception, error_code, 0);
1176}
1177
1178void helper_raise_exception(CPUPPCState *env, uint32_t exception)
1179{
1180 raise_exception_err_ra(env, exception, 0, 0);
1181}
1182#endif
1183
1184#if !defined(CONFIG_USER_ONLY)
1185#ifdef CONFIG_TCG
1186void helper_store_msr(CPUPPCState *env, target_ulong val)
1187{
1188 uint32_t excp = hreg_store_msr(env, val, 0);
1189
1190 if (excp != 0) {
1191 CPUState *cs = env_cpu(env);
1192 cpu_interrupt_exittb(cs);
1193 raise_exception(env, excp);
1194 }
1195}
1196
1197#if defined(TARGET_PPC64)
1198void helper_scv(CPUPPCState *env, uint32_t lev)
1199{
1200 if (env->spr[SPR_FSCR] & (1ull << FSCR_SCV)) {
1201 raise_exception_err(env, POWERPC_EXCP_SYSCALL_VECTORED, lev);
1202 } else {
1203 raise_exception_err(env, POWERPC_EXCP_FU, FSCR_IC_SCV);
1204 }
1205}
1206
1207void helper_pminsn(CPUPPCState *env, powerpc_pm_insn_t insn)
1208{
1209 CPUState *cs;
1210
1211 cs = env_cpu(env);
1212 cs->halted = 1;
1213
1214
1215
1216
1217
1218 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR);
1219
1220
1221 env->resume_as_sreset = (insn != PPC_PM_STOP) ||
1222 (env->spr[SPR_PSSCR] & PSSCR_EC);
1223}
1224#endif
1225#endif
1226
1227static inline void do_rfi(CPUPPCState *env, target_ulong nip, target_ulong msr)
1228{
1229 CPUState *cs = env_cpu(env);
1230
1231
1232 msr &= ~(1ULL << MSR_POW);
1233
1234#if defined(TARGET_PPC64)
1235
1236 if (!msr_is_64bit(env, msr)) {
1237 nip = (uint32_t)nip;
1238 }
1239#else
1240 nip = (uint32_t)nip;
1241#endif
1242
1243 env->nip = nip & ~((target_ulong)0x00000003);
1244 hreg_store_msr(env, msr, 1);
1245#if defined(DEBUG_OP)
1246 cpu_dump_rfi(env->nip, env->msr);
1247#endif
1248
1249
1250
1251
1252 cpu_interrupt_exittb(cs);
1253
1254 env->reserve_addr = -1;
1255
1256
1257 check_tlb_flush(env, false);
1258}
1259
1260#ifdef CONFIG_TCG
1261void helper_rfi(CPUPPCState *env)
1262{
1263 do_rfi(env, env->spr[SPR_SRR0], env->spr[SPR_SRR1] & 0xfffffffful);
1264}
1265
1266#define MSR_BOOK3S_MASK
1267#if defined(TARGET_PPC64)
1268void helper_rfid(CPUPPCState *env)
1269{
1270
1271
1272
1273
1274
1275
1276 do_rfi(env, env->spr[SPR_SRR0], env->spr[SPR_SRR1]);
1277}
1278
1279void helper_rfscv(CPUPPCState *env)
1280{
1281 do_rfi(env, env->lr, env->ctr);
1282}
1283
1284void helper_hrfid(CPUPPCState *env)
1285{
1286 do_rfi(env, env->spr[SPR_HSRR0], env->spr[SPR_HSRR1]);
1287}
1288#endif
1289
1290
1291
1292void helper_40x_rfci(CPUPPCState *env)
1293{
1294 do_rfi(env, env->spr[SPR_40x_SRR2], env->spr[SPR_40x_SRR3]);
1295}
1296
1297void helper_rfci(CPUPPCState *env)
1298{
1299 do_rfi(env, env->spr[SPR_BOOKE_CSRR0], env->spr[SPR_BOOKE_CSRR1]);
1300}
1301
1302void helper_rfdi(CPUPPCState *env)
1303{
1304
1305 do_rfi(env, env->spr[SPR_BOOKE_DSRR0], env->spr[SPR_BOOKE_DSRR1]);
1306}
1307
1308void helper_rfmci(CPUPPCState *env)
1309{
1310
1311 do_rfi(env, env->spr[SPR_BOOKE_MCSRR0], env->spr[SPR_BOOKE_MCSRR1]);
1312}
1313#endif
1314#endif
1315
1316#ifdef CONFIG_TCG
1317void helper_tw(CPUPPCState *env, target_ulong arg1, target_ulong arg2,
1318 uint32_t flags)
1319{
1320 if (!likely(!(((int32_t)arg1 < (int32_t)arg2 && (flags & 0x10)) ||
1321 ((int32_t)arg1 > (int32_t)arg2 && (flags & 0x08)) ||
1322 ((int32_t)arg1 == (int32_t)arg2 && (flags & 0x04)) ||
1323 ((uint32_t)arg1 < (uint32_t)arg2 && (flags & 0x02)) ||
1324 ((uint32_t)arg1 > (uint32_t)arg2 && (flags & 0x01))))) {
1325 raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
1326 POWERPC_EXCP_TRAP, GETPC());
1327 }
1328}
1329
1330#if defined(TARGET_PPC64)
1331void helper_td(CPUPPCState *env, target_ulong arg1, target_ulong arg2,
1332 uint32_t flags)
1333{
1334 if (!likely(!(((int64_t)arg1 < (int64_t)arg2 && (flags & 0x10)) ||
1335 ((int64_t)arg1 > (int64_t)arg2 && (flags & 0x08)) ||
1336 ((int64_t)arg1 == (int64_t)arg2 && (flags & 0x04)) ||
1337 ((uint64_t)arg1 < (uint64_t)arg2 && (flags & 0x02)) ||
1338 ((uint64_t)arg1 > (uint64_t)arg2 && (flags & 0x01))))) {
1339 raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
1340 POWERPC_EXCP_TRAP, GETPC());
1341 }
1342}
1343#endif
1344#endif
1345
1346#if !defined(CONFIG_USER_ONLY)
1347
1348
1349
1350#ifdef CONFIG_TCG
1351void helper_rfsvc(CPUPPCState *env)
1352{
1353 do_rfi(env, env->lr, env->ctr & 0x0000FFFF);
1354}
1355
1356
1357static int dbell2irq(target_ulong rb)
1358{
1359 int msg = rb & DBELL_TYPE_MASK;
1360 int irq = -1;
1361
1362 switch (msg) {
1363 case DBELL_TYPE_DBELL:
1364 irq = PPC_INTERRUPT_DOORBELL;
1365 break;
1366 case DBELL_TYPE_DBELL_CRIT:
1367 irq = PPC_INTERRUPT_CDOORBELL;
1368 break;
1369 case DBELL_TYPE_G_DBELL:
1370 case DBELL_TYPE_G_DBELL_CRIT:
1371 case DBELL_TYPE_G_DBELL_MC:
1372
1373 default:
1374 break;
1375 }
1376
1377 return irq;
1378}
1379
1380void helper_msgclr(CPUPPCState *env, target_ulong rb)
1381{
1382 int irq = dbell2irq(rb);
1383
1384 if (irq < 0) {
1385 return;
1386 }
1387
1388 env->pending_interrupts &= ~(1 << irq);
1389}
1390
1391void helper_msgsnd(target_ulong rb)
1392{
1393 int irq = dbell2irq(rb);
1394 int pir = rb & DBELL_PIRTAG_MASK;
1395 CPUState *cs;
1396
1397 if (irq < 0) {
1398 return;
1399 }
1400
1401 qemu_mutex_lock_iothread();
1402 CPU_FOREACH(cs) {
1403 PowerPCCPU *cpu = POWERPC_CPU(cs);
1404 CPUPPCState *cenv = &cpu->env;
1405
1406 if ((rb & DBELL_BRDCAST) || (cenv->spr[SPR_BOOKE_PIR] == pir)) {
1407 cenv->pending_interrupts |= 1 << irq;
1408 cpu_interrupt(cs, CPU_INTERRUPT_HARD);
1409 }
1410 }
1411 qemu_mutex_unlock_iothread();
1412}
1413
1414
1415
1416static bool dbell_type_server(target_ulong rb)
1417{
1418
1419
1420
1421
1422
1423 return (rb & DBELL_TYPE_MASK) == DBELL_TYPE_DBELL_SERVER;
1424}
1425
1426void helper_book3s_msgclr(CPUPPCState *env, target_ulong rb)
1427{
1428 if (!dbell_type_server(rb)) {
1429 return;
1430 }
1431
1432 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDOORBELL);
1433}
1434
1435static void book3s_msgsnd_common(int pir, int irq)
1436{
1437 CPUState *cs;
1438
1439 qemu_mutex_lock_iothread();
1440 CPU_FOREACH(cs) {
1441 PowerPCCPU *cpu = POWERPC_CPU(cs);
1442 CPUPPCState *cenv = &cpu->env;
1443
1444
1445 if (cenv->spr_cb[SPR_PIR].default_value == pir) {
1446 cenv->pending_interrupts |= 1 << irq;
1447 cpu_interrupt(cs, CPU_INTERRUPT_HARD);
1448 }
1449 }
1450 qemu_mutex_unlock_iothread();
1451}
1452
1453void helper_book3s_msgsnd(target_ulong rb)
1454{
1455 int pir = rb & DBELL_PROCIDTAG_MASK;
1456
1457 if (!dbell_type_server(rb)) {
1458 return;
1459 }
1460
1461 book3s_msgsnd_common(pir, PPC_INTERRUPT_HDOORBELL);
1462}
1463
1464#if defined(TARGET_PPC64)
1465void helper_book3s_msgclrp(CPUPPCState *env, target_ulong rb)
1466{
1467 helper_hfscr_facility_check(env, HFSCR_MSGP, "msgclrp", HFSCR_IC_MSGP);
1468
1469 if (!dbell_type_server(rb)) {
1470 return;
1471 }
1472
1473 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DOORBELL);
1474}
1475
1476
1477
1478
1479
1480void helper_book3s_msgsndp(CPUPPCState *env, target_ulong rb)
1481{
1482 int pir = env->spr_cb[SPR_PIR].default_value;
1483
1484 helper_hfscr_facility_check(env, HFSCR_MSGP, "msgsndp", HFSCR_IC_MSGP);
1485
1486 if (!dbell_type_server(rb)) {
1487 return;
1488 }
1489
1490
1491
1492 book3s_msgsnd_common(pir, PPC_INTERRUPT_DOORBELL);
1493}
1494#endif
1495#endif
1496#endif
1497
1498#ifdef CONFIG_TCG
1499void ppc_cpu_do_unaligned_access(CPUState *cs, vaddr vaddr,
1500 MMUAccessType access_type,
1501 int mmu_idx, uintptr_t retaddr)
1502{
1503 CPUPPCState *env = cs->env_ptr;
1504 uint32_t insn;
1505
1506
1507 cpu_restore_state(cs, retaddr, true);
1508 insn = cpu_ldl_code(env, env->nip);
1509
1510 cs->exception_index = POWERPC_EXCP_ALIGN;
1511 env->error_code = insn & 0x03FF0000;
1512 cpu_loop_exit(cs);
1513}
1514#endif
1515