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 "qemu/log.h"
22#include "cpu.h"
23#include "exec/exec-all.h"
24#include "internal.h"
25#include "helper_regs.h"
26#include "hw/ppc/ppc.h"
27
28#include "trace.h"
29
30#ifdef CONFIG_TCG
31#include "exec/helper-proto.h"
32#include "exec/cpu_ldst.h"
33#endif
34
35
36
37#if !defined(CONFIG_USER_ONLY)
38
39static const char *powerpc_excp_name(int excp)
40{
41 switch (excp) {
42 case POWERPC_EXCP_CRITICAL: return "CRITICAL";
43 case POWERPC_EXCP_MCHECK: return "MCHECK";
44 case POWERPC_EXCP_DSI: return "DSI";
45 case POWERPC_EXCP_ISI: return "ISI";
46 case POWERPC_EXCP_EXTERNAL: return "EXTERNAL";
47 case POWERPC_EXCP_ALIGN: return "ALIGN";
48 case POWERPC_EXCP_PROGRAM: return "PROGRAM";
49 case POWERPC_EXCP_FPU: return "FPU";
50 case POWERPC_EXCP_SYSCALL: return "SYSCALL";
51 case POWERPC_EXCP_APU: return "APU";
52 case POWERPC_EXCP_DECR: return "DECR";
53 case POWERPC_EXCP_FIT: return "FIT";
54 case POWERPC_EXCP_WDT: return "WDT";
55 case POWERPC_EXCP_DTLB: return "DTLB";
56 case POWERPC_EXCP_ITLB: return "ITLB";
57 case POWERPC_EXCP_DEBUG: return "DEBUG";
58 case POWERPC_EXCP_SPEU: return "SPEU";
59 case POWERPC_EXCP_EFPDI: return "EFPDI";
60 case POWERPC_EXCP_EFPRI: return "EFPRI";
61 case POWERPC_EXCP_EPERFM: return "EPERFM";
62 case POWERPC_EXCP_DOORI: return "DOORI";
63 case POWERPC_EXCP_DOORCI: return "DOORCI";
64 case POWERPC_EXCP_GDOORI: return "GDOORI";
65 case POWERPC_EXCP_GDOORCI: return "GDOORCI";
66 case POWERPC_EXCP_HYPPRIV: return "HYPPRIV";
67 case POWERPC_EXCP_RESET: return "RESET";
68 case POWERPC_EXCP_DSEG: return "DSEG";
69 case POWERPC_EXCP_ISEG: return "ISEG";
70 case POWERPC_EXCP_HDECR: return "HDECR";
71 case POWERPC_EXCP_TRACE: return "TRACE";
72 case POWERPC_EXCP_HDSI: return "HDSI";
73 case POWERPC_EXCP_HISI: return "HISI";
74 case POWERPC_EXCP_HDSEG: return "HDSEG";
75 case POWERPC_EXCP_HISEG: return "HISEG";
76 case POWERPC_EXCP_VPU: return "VPU";
77 case POWERPC_EXCP_PIT: return "PIT";
78 case POWERPC_EXCP_EMUL: return "EMUL";
79 case POWERPC_EXCP_IFTLB: return "IFTLB";
80 case POWERPC_EXCP_DLTLB: return "DLTLB";
81 case POWERPC_EXCP_DSTLB: return "DSTLB";
82 case POWERPC_EXCP_FPA: return "FPA";
83 case POWERPC_EXCP_DABR: return "DABR";
84 case POWERPC_EXCP_IABR: return "IABR";
85 case POWERPC_EXCP_SMI: return "SMI";
86 case POWERPC_EXCP_PERFM: return "PERFM";
87 case POWERPC_EXCP_THERM: return "THERM";
88 case POWERPC_EXCP_VPUA: return "VPUA";
89 case POWERPC_EXCP_SOFTP: return "SOFTP";
90 case POWERPC_EXCP_MAINT: return "MAINT";
91 case POWERPC_EXCP_MEXTBR: return "MEXTBR";
92 case POWERPC_EXCP_NMEXTBR: return "NMEXTBR";
93 case POWERPC_EXCP_ITLBE: return "ITLBE";
94 case POWERPC_EXCP_DTLBE: return "DTLBE";
95 case POWERPC_EXCP_VSXU: return "VSXU";
96 case POWERPC_EXCP_FU: return "FU";
97 case POWERPC_EXCP_HV_EMU: return "HV_EMU";
98 case POWERPC_EXCP_HV_MAINT: return "HV_MAINT";
99 case POWERPC_EXCP_HV_FU: return "HV_FU";
100 case POWERPC_EXCP_SDOOR: return "SDOOR";
101 case POWERPC_EXCP_SDOOR_HV: return "SDOOR_HV";
102 case POWERPC_EXCP_HVIRT: return "HVIRT";
103 case POWERPC_EXCP_SYSCALL_VECTORED: return "SYSCALL_VECTORED";
104 default:
105 g_assert_not_reached();
106 }
107}
108
109static void dump_syscall(CPUPPCState *env)
110{
111 qemu_log_mask(CPU_LOG_INT, "syscall r0=%016" PRIx64
112 " r3=%016" PRIx64 " r4=%016" PRIx64 " r5=%016" PRIx64
113 " r6=%016" PRIx64 " r7=%016" PRIx64 " r8=%016" PRIx64
114 " nip=" TARGET_FMT_lx "\n",
115 ppc_dump_gpr(env, 0), ppc_dump_gpr(env, 3),
116 ppc_dump_gpr(env, 4), ppc_dump_gpr(env, 5),
117 ppc_dump_gpr(env, 6), ppc_dump_gpr(env, 7),
118 ppc_dump_gpr(env, 8), env->nip);
119}
120
121static void dump_hcall(CPUPPCState *env)
122{
123 qemu_log_mask(CPU_LOG_INT, "hypercall r3=%016" PRIx64
124 " r4=%016" PRIx64 " r5=%016" PRIx64 " r6=%016" PRIx64
125 " r7=%016" PRIx64 " r8=%016" PRIx64 " r9=%016" PRIx64
126 " r10=%016" PRIx64 " r11=%016" PRIx64 " r12=%016" PRIx64
127 " nip=" TARGET_FMT_lx "\n",
128 ppc_dump_gpr(env, 3), ppc_dump_gpr(env, 4),
129 ppc_dump_gpr(env, 5), ppc_dump_gpr(env, 6),
130 ppc_dump_gpr(env, 7), ppc_dump_gpr(env, 8),
131 ppc_dump_gpr(env, 9), ppc_dump_gpr(env, 10),
132 ppc_dump_gpr(env, 11), ppc_dump_gpr(env, 12),
133 env->nip);
134}
135
136static void ppc_excp_debug_sw_tlb(CPUPPCState *env, int excp)
137{
138 const char *es;
139 target_ulong *miss, *cmp;
140 int en;
141
142 if (!qemu_loglevel_mask(CPU_LOG_MMU)) {
143 return;
144 }
145
146 if (excp == POWERPC_EXCP_IFTLB) {
147 es = "I";
148 en = 'I';
149 miss = &env->spr[SPR_IMISS];
150 cmp = &env->spr[SPR_ICMP];
151 } else {
152 if (excp == POWERPC_EXCP_DLTLB) {
153 es = "DL";
154 } else {
155 es = "DS";
156 }
157 en = 'D';
158 miss = &env->spr[SPR_DMISS];
159 cmp = &env->spr[SPR_DCMP];
160 }
161 qemu_log("6xx %sTLB miss: %cM " TARGET_FMT_lx " %cC "
162 TARGET_FMT_lx " H1 " TARGET_FMT_lx " H2 "
163 TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp,
164 env->spr[SPR_HASH1], env->spr[SPR_HASH2],
165 env->error_code);
166}
167
168#if defined(TARGET_PPC64)
169static int powerpc_reset_wakeup(CPUState *cs, CPUPPCState *env, int excp,
170 target_ulong *msr)
171{
172
173 env->resume_as_sreset = false;
174
175
176 *msr |= SRR1_WS_NOLOSS;
177
178
179 if (excp == POWERPC_EXCP_MCHECK) {
180 return excp;
181 }
182 switch (excp) {
183 case POWERPC_EXCP_RESET:
184 *msr |= SRR1_WAKERESET;
185 break;
186 case POWERPC_EXCP_EXTERNAL:
187 *msr |= SRR1_WAKEEE;
188 break;
189 case POWERPC_EXCP_DECR:
190 *msr |= SRR1_WAKEDEC;
191 break;
192 case POWERPC_EXCP_SDOOR:
193 *msr |= SRR1_WAKEDBELL;
194 break;
195 case POWERPC_EXCP_SDOOR_HV:
196 *msr |= SRR1_WAKEHDBELL;
197 break;
198 case POWERPC_EXCP_HV_MAINT:
199 *msr |= SRR1_WAKEHMI;
200 break;
201 case POWERPC_EXCP_HVIRT:
202 *msr |= SRR1_WAKEHVI;
203 break;
204 default:
205 cpu_abort(cs, "Unsupported exception %d in Power Save mode\n",
206 excp);
207 }
208 return POWERPC_EXCP_RESET;
209}
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267static void ppc_excp_apply_ail(PowerPCCPU *cpu, int excp, target_ulong msr,
268 target_ulong *new_msr, target_ulong *vector)
269{
270 PowerPCCPUClass *pcc = POWERPC_CPU_GET_CLASS(cpu);
271 CPUPPCState *env = &cpu->env;
272 bool mmu_all_on = ((msr >> MSR_IR) & 1) && ((msr >> MSR_DR) & 1);
273 bool hv_escalation = !(msr & MSR_HVB) && (*new_msr & MSR_HVB);
274 int ail = 0;
275
276 if (excp == POWERPC_EXCP_MCHECK ||
277 excp == POWERPC_EXCP_RESET ||
278 excp == POWERPC_EXCP_HV_MAINT) {
279
280 return;
281 }
282
283 if (!(pcc->lpcr_mask & LPCR_AIL)) {
284
285 return;
286 }
287
288
289 if (!(pcc->lpcr_mask & LPCR_HAIL)) {
290 if (!mmu_all_on) {
291
292 return;
293 }
294 if (hv_escalation && !(env->spr[SPR_LPCR] & LPCR_HR)) {
295
296
297
298
299
300 return;
301 }
302
303 ail = (env->spr[SPR_LPCR] & LPCR_AIL) >> LPCR_AIL_SHIFT;
304 if (ail == 0) {
305 return;
306 }
307 if (ail == 1) {
308
309 return;
310 }
311
312
313 } else {
314 if (!mmu_all_on && !hv_escalation) {
315
316
317
318
319 return;
320 }
321
322 if (*new_msr & MSR_HVB) {
323 if (!(env->spr[SPR_LPCR] & LPCR_HAIL)) {
324
325 return;
326 }
327 ail = 3;
328 } else {
329 ail = (env->spr[SPR_LPCR] & LPCR_AIL) >> LPCR_AIL_SHIFT;
330 }
331 if (ail == 0) {
332 return;
333 }
334 if (ail == 1 || ail == 2) {
335
336 return;
337 }
338 }
339
340
341
342
343
344 *new_msr |= (1 << MSR_IR) | (1 << MSR_DR);
345
346 if (excp != POWERPC_EXCP_SYSCALL_VECTORED) {
347 if (ail == 2) {
348 *vector |= 0x0000000000018000ull;
349 } else if (ail == 3) {
350 *vector |= 0xc000000000004000ull;
351 }
352 } else {
353
354
355
356
357 if (ail == 3) {
358 *vector &= ~0x0000000000017000ull;
359 *vector |= 0xc000000000003000ull;
360 }
361 }
362}
363#endif
364
365static void powerpc_reset_excp_state(PowerPCCPU *cpu)
366{
367 CPUState *cs = CPU(cpu);
368 CPUPPCState *env = &cpu->env;
369
370
371 cs->exception_index = POWERPC_EXCP_NONE;
372 env->error_code = 0;
373}
374
375static void powerpc_set_excp_state(PowerPCCPU *cpu, target_ulong vector,
376 target_ulong msr)
377{
378 CPUPPCState *env = &cpu->env;
379
380 assert((msr & env->msr_mask) == msr);
381
382
383
384
385
386
387
388
389
390 env->nip = vector;
391 env->msr = msr;
392 hreg_compute_hflags(env);
393 ppc_maybe_interrupt(env);
394
395 powerpc_reset_excp_state(cpu);
396
397
398
399
400
401 check_tlb_flush(env, false);
402
403
404 env->reserve_addr = -1;
405}
406
407static void powerpc_excp_40x(PowerPCCPU *cpu, int excp)
408{
409 CPUState *cs = CPU(cpu);
410 CPUPPCState *env = &cpu->env;
411 target_ulong msr, new_msr, vector;
412 int srr0, srr1;
413
414
415 msr = env->msr & ~0x783f0000ULL;
416
417
418
419
420
421 new_msr = env->msr & (((target_ulong)1 << MSR_ME));
422
423
424 srr0 = SPR_SRR0;
425 srr1 = SPR_SRR1;
426
427
428
429
430
431 if (excp == POWERPC_EXCP_HV_EMU) {
432 excp = POWERPC_EXCP_PROGRAM;
433 }
434
435 vector = env->excp_vectors[excp];
436 if (vector == (target_ulong)-1ULL) {
437 cpu_abort(cs, "Raised an exception without defined vector %d\n",
438 excp);
439 }
440
441 vector |= env->excp_prefix;
442
443 switch (excp) {
444 case POWERPC_EXCP_CRITICAL:
445 srr0 = SPR_40x_SRR2;
446 srr1 = SPR_40x_SRR3;
447 break;
448 case POWERPC_EXCP_MCHECK:
449 if (!FIELD_EX64(env->msr, MSR, ME)) {
450
451
452
453
454 fprintf(stderr, "Machine check while not allowed. "
455 "Entering checkstop state\n");
456 if (qemu_log_separate()) {
457 qemu_log("Machine check while not allowed. "
458 "Entering checkstop state\n");
459 }
460 cs->halted = 1;
461 cpu_interrupt_exittb(cs);
462 }
463
464
465 new_msr &= ~((target_ulong)1 << MSR_ME);
466
467 srr0 = SPR_40x_SRR2;
468 srr1 = SPR_40x_SRR3;
469 break;
470 case POWERPC_EXCP_DSI:
471 trace_ppc_excp_dsi(env->spr[SPR_40x_ESR], env->spr[SPR_40x_DEAR]);
472 break;
473 case POWERPC_EXCP_ISI:
474 trace_ppc_excp_isi(msr, env->nip);
475 break;
476 case POWERPC_EXCP_EXTERNAL:
477 break;
478 case POWERPC_EXCP_ALIGN:
479 break;
480 case POWERPC_EXCP_PROGRAM:
481 switch (env->error_code & ~0xF) {
482 case POWERPC_EXCP_FP:
483 if (!FIELD_EX64_FE(env->msr) || !FIELD_EX64(env->msr, MSR, FP)) {
484 trace_ppc_excp_fp_ignore();
485 powerpc_reset_excp_state(cpu);
486 return;
487 }
488 env->spr[SPR_40x_ESR] = ESR_FP;
489 break;
490 case POWERPC_EXCP_INVAL:
491 trace_ppc_excp_inval(env->nip);
492 env->spr[SPR_40x_ESR] = ESR_PIL;
493 break;
494 case POWERPC_EXCP_PRIV:
495 env->spr[SPR_40x_ESR] = ESR_PPR;
496 break;
497 case POWERPC_EXCP_TRAP:
498 env->spr[SPR_40x_ESR] = ESR_PTR;
499 break;
500 default:
501 cpu_abort(cs, "Invalid program exception %d. Aborting\n",
502 env->error_code);
503 break;
504 }
505 break;
506 case POWERPC_EXCP_SYSCALL:
507 dump_syscall(env);
508
509
510
511
512
513 env->nip += 4;
514 break;
515 case POWERPC_EXCP_FIT:
516 trace_ppc_excp_print("FIT");
517 break;
518 case POWERPC_EXCP_WDT:
519 trace_ppc_excp_print("WDT");
520 break;
521 case POWERPC_EXCP_DTLB:
522 case POWERPC_EXCP_ITLB:
523 break;
524 case POWERPC_EXCP_PIT:
525 trace_ppc_excp_print("PIT");
526 break;
527 case POWERPC_EXCP_DEBUG:
528 cpu_abort(cs, "%s exception not implemented\n",
529 powerpc_excp_name(excp));
530 break;
531 default:
532 cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp);
533 break;
534 }
535
536
537 env->spr[srr0] = env->nip;
538
539
540 env->spr[srr1] = msr;
541
542 powerpc_set_excp_state(cpu, vector, new_msr);
543}
544
545static void powerpc_excp_6xx(PowerPCCPU *cpu, int excp)
546{
547 CPUState *cs = CPU(cpu);
548 CPUPPCState *env = &cpu->env;
549 target_ulong msr, new_msr, vector;
550
551
552 msr = env->msr & ~0x783f0000ULL;
553
554
555
556
557
558 new_msr = env->msr & ((target_ulong)1 << MSR_ME);
559
560
561
562
563
564 if (excp == POWERPC_EXCP_HV_EMU) {
565 excp = POWERPC_EXCP_PROGRAM;
566 }
567
568 vector = env->excp_vectors[excp];
569 if (vector == (target_ulong)-1ULL) {
570 cpu_abort(cs, "Raised an exception without defined vector %d\n",
571 excp);
572 }
573
574 vector |= env->excp_prefix;
575
576 switch (excp) {
577 case POWERPC_EXCP_CRITICAL:
578 break;
579 case POWERPC_EXCP_MCHECK:
580 if (!FIELD_EX64(env->msr, MSR, ME)) {
581
582
583
584
585 fprintf(stderr, "Machine check while not allowed. "
586 "Entering checkstop state\n");
587 if (qemu_log_separate()) {
588 qemu_log("Machine check while not allowed. "
589 "Entering checkstop state\n");
590 }
591 cs->halted = 1;
592 cpu_interrupt_exittb(cs);
593 }
594
595
596 new_msr &= ~((target_ulong)1 << MSR_ME);
597
598 break;
599 case POWERPC_EXCP_DSI:
600 trace_ppc_excp_dsi(env->spr[SPR_DSISR], env->spr[SPR_DAR]);
601 break;
602 case POWERPC_EXCP_ISI:
603 trace_ppc_excp_isi(msr, env->nip);
604 msr |= env->error_code;
605 break;
606 case POWERPC_EXCP_EXTERNAL:
607 break;
608 case POWERPC_EXCP_ALIGN:
609
610
611
612
613
614
615 env->spr[SPR_DSISR] |= (env->error_code & 0x03FF0000) >> 16;
616 break;
617 case POWERPC_EXCP_PROGRAM:
618 switch (env->error_code & ~0xF) {
619 case POWERPC_EXCP_FP:
620 if (!FIELD_EX64_FE(env->msr) || !FIELD_EX64(env->msr, MSR, FP)) {
621 trace_ppc_excp_fp_ignore();
622 powerpc_reset_excp_state(cpu);
623 return;
624 }
625
626
627
628
629
630
631 msr |= 0x00100000;
632 break;
633 case POWERPC_EXCP_INVAL:
634 trace_ppc_excp_inval(env->nip);
635 msr |= 0x00080000;
636 break;
637 case POWERPC_EXCP_PRIV:
638 msr |= 0x00040000;
639 break;
640 case POWERPC_EXCP_TRAP:
641 msr |= 0x00020000;
642 break;
643 default:
644
645 cpu_abort(cs, "Invalid program exception %d. Aborting\n",
646 env->error_code);
647 break;
648 }
649 break;
650 case POWERPC_EXCP_SYSCALL:
651 dump_syscall(env);
652
653
654
655
656
657 env->nip += 4;
658 break;
659 case POWERPC_EXCP_FPU:
660 case POWERPC_EXCP_DECR:
661 break;
662 case POWERPC_EXCP_DTLB:
663 case POWERPC_EXCP_ITLB:
664 break;
665 case POWERPC_EXCP_RESET:
666 if (FIELD_EX64(env->msr, MSR, POW)) {
667 cpu_abort(cs, "Trying to deliver power-saving system reset "
668 "exception %d with no HV support\n", excp);
669 }
670 break;
671 case POWERPC_EXCP_TRACE:
672 break;
673 case POWERPC_EXCP_IFTLB:
674 case POWERPC_EXCP_DLTLB:
675 case POWERPC_EXCP_DSTLB:
676
677 if (!(new_msr & ((target_ulong)1 << MSR_TGPR))) {
678 new_msr |= (target_ulong)1 << MSR_TGPR;
679 hreg_swap_gpr_tgpr(env);
680 }
681
682 ppc_excp_debug_sw_tlb(env, excp);
683
684 msr |= env->crf[0] << 28;
685 msr |= env->error_code;
686
687 msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17;
688 break;
689 case POWERPC_EXCP_FPA:
690 case POWERPC_EXCP_DABR:
691 case POWERPC_EXCP_IABR:
692 case POWERPC_EXCP_SMI:
693 case POWERPC_EXCP_MEXTBR:
694 case POWERPC_EXCP_NMEXTBR:
695 cpu_abort(cs, "%s exception not implemented\n",
696 powerpc_excp_name(excp));
697 break;
698 default:
699 cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp);
700 break;
701 }
702
703
704
705
706
707 if (ppc_interrupts_little_endian(cpu, !!(new_msr & MSR_HVB))) {
708 new_msr |= (target_ulong)1 << MSR_LE;
709 }
710
711
712 env->spr[SPR_SRR0] = env->nip;
713
714
715 env->spr[SPR_SRR1] = msr;
716
717 powerpc_set_excp_state(cpu, vector, new_msr);
718}
719
720static void powerpc_excp_7xx(PowerPCCPU *cpu, int excp)
721{
722 CPUState *cs = CPU(cpu);
723 CPUPPCState *env = &cpu->env;
724 target_ulong msr, new_msr, vector;
725
726
727 msr = env->msr & ~0x783f0000ULL;
728
729
730
731
732
733 new_msr = env->msr & ((target_ulong)1 << MSR_ME);
734
735
736
737
738
739 if (excp == POWERPC_EXCP_HV_EMU) {
740 excp = POWERPC_EXCP_PROGRAM;
741 }
742
743 vector = env->excp_vectors[excp];
744 if (vector == (target_ulong)-1ULL) {
745 cpu_abort(cs, "Raised an exception without defined vector %d\n",
746 excp);
747 }
748
749 vector |= env->excp_prefix;
750
751 switch (excp) {
752 case POWERPC_EXCP_MCHECK:
753 if (!FIELD_EX64(env->msr, MSR, ME)) {
754
755
756
757
758 fprintf(stderr, "Machine check while not allowed. "
759 "Entering checkstop state\n");
760 if (qemu_log_separate()) {
761 qemu_log("Machine check while not allowed. "
762 "Entering checkstop state\n");
763 }
764 cs->halted = 1;
765 cpu_interrupt_exittb(cs);
766 }
767
768
769 new_msr &= ~((target_ulong)1 << MSR_ME);
770
771 break;
772 case POWERPC_EXCP_DSI:
773 trace_ppc_excp_dsi(env->spr[SPR_DSISR], env->spr[SPR_DAR]);
774 break;
775 case POWERPC_EXCP_ISI:
776 trace_ppc_excp_isi(msr, env->nip);
777 msr |= env->error_code;
778 break;
779 case POWERPC_EXCP_EXTERNAL:
780 break;
781 case POWERPC_EXCP_ALIGN:
782
783
784
785
786
787
788 env->spr[SPR_DSISR] |= (env->error_code & 0x03FF0000) >> 16;
789 break;
790 case POWERPC_EXCP_PROGRAM:
791 switch (env->error_code & ~0xF) {
792 case POWERPC_EXCP_FP:
793 if (!FIELD_EX64_FE(env->msr) || !FIELD_EX64(env->msr, MSR, FP)) {
794 trace_ppc_excp_fp_ignore();
795 powerpc_reset_excp_state(cpu);
796 return;
797 }
798
799
800
801
802
803
804 msr |= 0x00100000;
805 break;
806 case POWERPC_EXCP_INVAL:
807 trace_ppc_excp_inval(env->nip);
808 msr |= 0x00080000;
809 break;
810 case POWERPC_EXCP_PRIV:
811 msr |= 0x00040000;
812 break;
813 case POWERPC_EXCP_TRAP:
814 msr |= 0x00020000;
815 break;
816 default:
817
818 cpu_abort(cs, "Invalid program exception %d. Aborting\n",
819 env->error_code);
820 break;
821 }
822 break;
823 case POWERPC_EXCP_SYSCALL:
824 {
825 int lev = env->error_code;
826
827 if (lev == 1 && cpu->vhyp) {
828 dump_hcall(env);
829 } else {
830 dump_syscall(env);
831 }
832
833
834
835
836
837 env->nip += 4;
838
839
840
841
842
843
844
845 if (lev == 1 && cpu->vhyp) {
846 PPCVirtualHypervisorClass *vhc =
847 PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
848 vhc->hypercall(cpu->vhyp, cpu);
849 return;
850 }
851
852 break;
853 }
854 case POWERPC_EXCP_FPU:
855 case POWERPC_EXCP_DECR:
856 break;
857 case POWERPC_EXCP_RESET:
858 if (FIELD_EX64(env->msr, MSR, POW)) {
859 cpu_abort(cs, "Trying to deliver power-saving system reset "
860 "exception %d with no HV support\n", excp);
861 }
862 break;
863 case POWERPC_EXCP_TRACE:
864 break;
865 case POWERPC_EXCP_IFTLB:
866 case POWERPC_EXCP_DLTLB:
867 case POWERPC_EXCP_DSTLB:
868 ppc_excp_debug_sw_tlb(env, excp);
869
870 msr |= env->crf[0] << 28;
871 msr |= env->error_code;
872
873 msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17;
874
875 break;
876 case POWERPC_EXCP_IABR:
877 case POWERPC_EXCP_SMI:
878 case POWERPC_EXCP_THERM:
879 case POWERPC_EXCP_PERFM:
880 cpu_abort(cs, "%s exception not implemented\n",
881 powerpc_excp_name(excp));
882 break;
883 default:
884 cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp);
885 break;
886 }
887
888
889
890
891
892 if (ppc_interrupts_little_endian(cpu, !!(new_msr & MSR_HVB))) {
893 new_msr |= (target_ulong)1 << MSR_LE;
894 }
895
896
897 env->spr[SPR_SRR0] = env->nip;
898
899
900 env->spr[SPR_SRR1] = msr;
901
902 powerpc_set_excp_state(cpu, vector, new_msr);
903}
904
905static void powerpc_excp_74xx(PowerPCCPU *cpu, int excp)
906{
907 CPUState *cs = CPU(cpu);
908 CPUPPCState *env = &cpu->env;
909 target_ulong msr, new_msr, vector;
910
911
912 msr = env->msr & ~0x783f0000ULL;
913
914
915
916
917
918 new_msr = env->msr & ((target_ulong)1 << MSR_ME);
919
920
921
922
923
924 if (excp == POWERPC_EXCP_HV_EMU) {
925 excp = POWERPC_EXCP_PROGRAM;
926 }
927
928 vector = env->excp_vectors[excp];
929 if (vector == (target_ulong)-1ULL) {
930 cpu_abort(cs, "Raised an exception without defined vector %d\n",
931 excp);
932 }
933
934 vector |= env->excp_prefix;
935
936 switch (excp) {
937 case POWERPC_EXCP_MCHECK:
938 if (!FIELD_EX64(env->msr, MSR, ME)) {
939
940
941
942
943 fprintf(stderr, "Machine check while not allowed. "
944 "Entering checkstop state\n");
945 if (qemu_log_separate()) {
946 qemu_log("Machine check while not allowed. "
947 "Entering checkstop state\n");
948 }
949 cs->halted = 1;
950 cpu_interrupt_exittb(cs);
951 }
952
953
954 new_msr &= ~((target_ulong)1 << MSR_ME);
955
956 break;
957 case POWERPC_EXCP_DSI:
958 trace_ppc_excp_dsi(env->spr[SPR_DSISR], env->spr[SPR_DAR]);
959 break;
960 case POWERPC_EXCP_ISI:
961 trace_ppc_excp_isi(msr, env->nip);
962 msr |= env->error_code;
963 break;
964 case POWERPC_EXCP_EXTERNAL:
965 break;
966 case POWERPC_EXCP_ALIGN:
967
968
969
970
971
972
973 env->spr[SPR_DSISR] |= (env->error_code & 0x03FF0000) >> 16;
974 break;
975 case POWERPC_EXCP_PROGRAM:
976 switch (env->error_code & ~0xF) {
977 case POWERPC_EXCP_FP:
978 if (!FIELD_EX64_FE(env->msr) || !FIELD_EX64(env->msr, MSR, FP)) {
979 trace_ppc_excp_fp_ignore();
980 powerpc_reset_excp_state(cpu);
981 return;
982 }
983
984
985
986
987
988
989 msr |= 0x00100000;
990 break;
991 case POWERPC_EXCP_INVAL:
992 trace_ppc_excp_inval(env->nip);
993 msr |= 0x00080000;
994 break;
995 case POWERPC_EXCP_PRIV:
996 msr |= 0x00040000;
997 break;
998 case POWERPC_EXCP_TRAP:
999 msr |= 0x00020000;
1000 break;
1001 default:
1002
1003 cpu_abort(cs, "Invalid program exception %d. Aborting\n",
1004 env->error_code);
1005 break;
1006 }
1007 break;
1008 case POWERPC_EXCP_SYSCALL:
1009 {
1010 int lev = env->error_code;
1011
1012 if ((lev == 1) && cpu->vhyp) {
1013 dump_hcall(env);
1014 } else {
1015 dump_syscall(env);
1016 }
1017
1018
1019
1020
1021
1022 env->nip += 4;
1023
1024
1025
1026
1027
1028
1029
1030 if ((lev == 1) && cpu->vhyp) {
1031 PPCVirtualHypervisorClass *vhc =
1032 PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
1033 vhc->hypercall(cpu->vhyp, cpu);
1034 return;
1035 }
1036
1037 break;
1038 }
1039 case POWERPC_EXCP_FPU:
1040 case POWERPC_EXCP_DECR:
1041 break;
1042 case POWERPC_EXCP_RESET:
1043 if (FIELD_EX64(env->msr, MSR, POW)) {
1044 cpu_abort(cs, "Trying to deliver power-saving system reset "
1045 "exception %d with no HV support\n", excp);
1046 }
1047 break;
1048 case POWERPC_EXCP_TRACE:
1049 break;
1050 case POWERPC_EXCP_VPU:
1051 break;
1052 case POWERPC_EXCP_IABR:
1053 case POWERPC_EXCP_SMI:
1054 case POWERPC_EXCP_THERM:
1055 case POWERPC_EXCP_PERFM:
1056 case POWERPC_EXCP_VPUA:
1057 cpu_abort(cs, "%s exception not implemented\n",
1058 powerpc_excp_name(excp));
1059 break;
1060 default:
1061 cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp);
1062 break;
1063 }
1064
1065
1066
1067
1068
1069 if (ppc_interrupts_little_endian(cpu, !!(new_msr & MSR_HVB))) {
1070 new_msr |= (target_ulong)1 << MSR_LE;
1071 }
1072
1073
1074 env->spr[SPR_SRR0] = env->nip;
1075
1076
1077 env->spr[SPR_SRR1] = msr;
1078
1079 powerpc_set_excp_state(cpu, vector, new_msr);
1080}
1081
1082static void powerpc_excp_booke(PowerPCCPU *cpu, int excp)
1083{
1084 CPUState *cs = CPU(cpu);
1085 CPUPPCState *env = &cpu->env;
1086 target_ulong msr, new_msr, vector;
1087 int srr0, srr1;
1088
1089 msr = env->msr;
1090
1091
1092
1093
1094
1095 new_msr = env->msr & ((target_ulong)1 << MSR_ME);
1096
1097
1098 srr0 = SPR_SRR0;
1099 srr1 = SPR_SRR1;
1100
1101
1102
1103
1104
1105 if (excp == POWERPC_EXCP_HV_EMU) {
1106 excp = POWERPC_EXCP_PROGRAM;
1107 }
1108
1109#ifdef TARGET_PPC64
1110
1111
1112
1113
1114 if (excp == POWERPC_EXCP_VPU) {
1115 excp = POWERPC_EXCP_SPEU;
1116 }
1117#endif
1118
1119 vector = env->excp_vectors[excp];
1120 if (vector == (target_ulong)-1ULL) {
1121 cpu_abort(cs, "Raised an exception without defined vector %d\n",
1122 excp);
1123 }
1124
1125 vector |= env->excp_prefix;
1126
1127 switch (excp) {
1128 case POWERPC_EXCP_CRITICAL:
1129 srr0 = SPR_BOOKE_CSRR0;
1130 srr1 = SPR_BOOKE_CSRR1;
1131 break;
1132 case POWERPC_EXCP_MCHECK:
1133 if (!FIELD_EX64(env->msr, MSR, ME)) {
1134
1135
1136
1137
1138 fprintf(stderr, "Machine check while not allowed. "
1139 "Entering checkstop state\n");
1140 if (qemu_log_separate()) {
1141 qemu_log("Machine check while not allowed. "
1142 "Entering checkstop state\n");
1143 }
1144 cs->halted = 1;
1145 cpu_interrupt_exittb(cs);
1146 }
1147
1148
1149 new_msr &= ~((target_ulong)1 << MSR_ME);
1150
1151
1152 srr0 = SPR_BOOKE_MCSRR0;
1153 srr1 = SPR_BOOKE_MCSRR1;
1154
1155 env->spr[SPR_BOOKE_CSRR0] = env->nip;
1156 env->spr[SPR_BOOKE_CSRR1] = msr;
1157
1158 break;
1159 case POWERPC_EXCP_DSI:
1160 trace_ppc_excp_dsi(env->spr[SPR_BOOKE_ESR], env->spr[SPR_BOOKE_DEAR]);
1161 break;
1162 case POWERPC_EXCP_ISI:
1163 trace_ppc_excp_isi(msr, env->nip);
1164 break;
1165 case POWERPC_EXCP_EXTERNAL:
1166 if (env->mpic_proxy) {
1167
1168 env->spr[SPR_BOOKE_EPR] = ldl_phys(cs->as, env->mpic_iack);
1169 }
1170 break;
1171 case POWERPC_EXCP_ALIGN:
1172 break;
1173 case POWERPC_EXCP_PROGRAM:
1174 switch (env->error_code & ~0xF) {
1175 case POWERPC_EXCP_FP:
1176 if (!FIELD_EX64_FE(env->msr) || !FIELD_EX64(env->msr, MSR, FP)) {
1177 trace_ppc_excp_fp_ignore();
1178 powerpc_reset_excp_state(cpu);
1179 return;
1180 }
1181
1182
1183
1184
1185
1186
1187 msr |= 0x00100000;
1188 env->spr[SPR_BOOKE_ESR] = ESR_FP;
1189 break;
1190 case POWERPC_EXCP_INVAL:
1191 trace_ppc_excp_inval(env->nip);
1192 msr |= 0x00080000;
1193 env->spr[SPR_BOOKE_ESR] = ESR_PIL;
1194 break;
1195 case POWERPC_EXCP_PRIV:
1196 msr |= 0x00040000;
1197 env->spr[SPR_BOOKE_ESR] = ESR_PPR;
1198 break;
1199 case POWERPC_EXCP_TRAP:
1200 msr |= 0x00020000;
1201 env->spr[SPR_BOOKE_ESR] = ESR_PTR;
1202 break;
1203 default:
1204
1205 cpu_abort(cs, "Invalid program exception %d. Aborting\n",
1206 env->error_code);
1207 break;
1208 }
1209 break;
1210 case POWERPC_EXCP_SYSCALL:
1211 dump_syscall(env);
1212
1213
1214
1215
1216
1217 env->nip += 4;
1218 break;
1219 case POWERPC_EXCP_FPU:
1220 case POWERPC_EXCP_APU:
1221 case POWERPC_EXCP_DECR:
1222 break;
1223 case POWERPC_EXCP_FIT:
1224
1225 trace_ppc_excp_print("FIT");
1226 break;
1227 case POWERPC_EXCP_WDT:
1228 trace_ppc_excp_print("WDT");
1229 srr0 = SPR_BOOKE_CSRR0;
1230 srr1 = SPR_BOOKE_CSRR1;
1231 break;
1232 case POWERPC_EXCP_DTLB:
1233 case POWERPC_EXCP_ITLB:
1234 break;
1235 case POWERPC_EXCP_DEBUG:
1236 if (env->flags & POWERPC_FLAG_DE) {
1237
1238 srr0 = SPR_BOOKE_DSRR0;
1239 srr1 = SPR_BOOKE_DSRR1;
1240
1241 env->spr[SPR_BOOKE_CSRR0] = env->nip;
1242 env->spr[SPR_BOOKE_CSRR1] = msr;
1243
1244
1245 } else {
1246 cpu_abort(cs, "Debug exception triggered on unsupported model\n");
1247 }
1248 break;
1249 case POWERPC_EXCP_SPEU:
1250 env->spr[SPR_BOOKE_ESR] = ESR_SPV;
1251 break;
1252 case POWERPC_EXCP_DOORI:
1253 break;
1254 case POWERPC_EXCP_DOORCI:
1255 srr0 = SPR_BOOKE_CSRR0;
1256 srr1 = SPR_BOOKE_CSRR1;
1257 break;
1258 case POWERPC_EXCP_RESET:
1259 if (FIELD_EX64(env->msr, MSR, POW)) {
1260 cpu_abort(cs, "Trying to deliver power-saving system reset "
1261 "exception %d with no HV support\n", excp);
1262 }
1263 break;
1264 case POWERPC_EXCP_EFPDI:
1265 case POWERPC_EXCP_EFPRI:
1266 cpu_abort(cs, "%s exception not implemented\n",
1267 powerpc_excp_name(excp));
1268 break;
1269 default:
1270 cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp);
1271 break;
1272 }
1273
1274#if defined(TARGET_PPC64)
1275 if (env->spr[SPR_BOOKE_EPCR] & EPCR_ICM) {
1276
1277 new_msr |= (target_ulong)1 << MSR_CM;
1278 } else {
1279 vector = (uint32_t)vector;
1280 }
1281#endif
1282
1283
1284 env->spr[srr0] = env->nip;
1285
1286
1287 env->spr[srr1] = msr;
1288
1289 powerpc_set_excp_state(cpu, vector, new_msr);
1290}
1291
1292
1293
1294
1295
1296static bool books_vhyp_promotes_external_to_hvirt(PowerPCCPU *cpu)
1297{
1298 if (cpu->vhyp) {
1299 return vhyp_cpu_in_nested(cpu);
1300 }
1301 return false;
1302}
1303
1304#ifdef TARGET_PPC64
1305
1306
1307
1308
1309static bool books_vhyp_handles_hcall(PowerPCCPU *cpu)
1310{
1311 if (cpu->vhyp) {
1312 return !vhyp_cpu_in_nested(cpu);
1313 }
1314 return false;
1315}
1316
1317
1318
1319
1320
1321
1322
1323static bool books_vhyp_handles_hv_excp(PowerPCCPU *cpu)
1324{
1325 if (cpu->vhyp) {
1326 return vhyp_cpu_in_nested(cpu);
1327 }
1328 return false;
1329}
1330
1331static void powerpc_excp_books(PowerPCCPU *cpu, int excp)
1332{
1333 CPUState *cs = CPU(cpu);
1334 CPUPPCState *env = &cpu->env;
1335 target_ulong msr, new_msr, vector;
1336 int srr0, srr1, lev = -1;
1337
1338
1339 msr = env->msr & ~0x783f0000ULL;
1340
1341
1342
1343
1344
1345 new_msr = env->msr & (((target_ulong)1 << MSR_ME) | MSR_HVB);
1346
1347
1348 srr0 = SPR_SRR0;
1349 srr1 = SPR_SRR1;
1350
1351
1352
1353
1354
1355 if (env->resume_as_sreset) {
1356 excp = powerpc_reset_wakeup(cs, env, excp, &msr);
1357 }
1358
1359
1360
1361
1362
1363
1364
1365 if (excp == POWERPC_EXCP_HV_EMU && !(env->msr_mask & MSR_HVB) &&
1366 !books_vhyp_handles_hv_excp(cpu)) {
1367 excp = POWERPC_EXCP_PROGRAM;
1368 }
1369
1370 vector = env->excp_vectors[excp];
1371 if (vector == (target_ulong)-1ULL) {
1372 cpu_abort(cs, "Raised an exception without defined vector %d\n",
1373 excp);
1374 }
1375
1376 vector |= env->excp_prefix;
1377
1378 switch (excp) {
1379 case POWERPC_EXCP_MCHECK:
1380 if (!FIELD_EX64(env->msr, MSR, ME)) {
1381
1382
1383
1384
1385 fprintf(stderr, "Machine check while not allowed. "
1386 "Entering checkstop state\n");
1387 if (qemu_log_separate()) {
1388 qemu_log("Machine check while not allowed. "
1389 "Entering checkstop state\n");
1390 }
1391 cs->halted = 1;
1392 cpu_interrupt_exittb(cs);
1393 }
1394 if (env->msr_mask & MSR_HVB) {
1395
1396
1397
1398
1399 new_msr |= (target_ulong)MSR_HVB;
1400 }
1401
1402
1403 new_msr &= ~((target_ulong)1 << MSR_ME);
1404
1405 break;
1406 case POWERPC_EXCP_DSI:
1407 trace_ppc_excp_dsi(env->spr[SPR_DSISR], env->spr[SPR_DAR]);
1408 break;
1409 case POWERPC_EXCP_ISI:
1410 trace_ppc_excp_isi(msr, env->nip);
1411 msr |= env->error_code;
1412 break;
1413 case POWERPC_EXCP_EXTERNAL:
1414 {
1415 bool lpes0;
1416
1417
1418
1419
1420
1421 if (!env->has_hv_mode) {
1422 break;
1423 }
1424
1425 lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0);
1426
1427 if (!lpes0) {
1428 new_msr |= (target_ulong)MSR_HVB;
1429 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
1430 srr0 = SPR_HSRR0;
1431 srr1 = SPR_HSRR1;
1432 }
1433
1434 break;
1435 }
1436 case POWERPC_EXCP_ALIGN:
1437
1438
1439
1440
1441
1442
1443 env->spr[SPR_DSISR] |= (env->error_code & 0x03FF0000) >> 16;
1444 break;
1445 case POWERPC_EXCP_PROGRAM:
1446 switch (env->error_code & ~0xF) {
1447 case POWERPC_EXCP_FP:
1448 if (!FIELD_EX64_FE(env->msr) || !FIELD_EX64(env->msr, MSR, FP)) {
1449 trace_ppc_excp_fp_ignore();
1450 powerpc_reset_excp_state(cpu);
1451 return;
1452 }
1453
1454
1455
1456
1457
1458
1459 msr |= 0x00100000;
1460 break;
1461 case POWERPC_EXCP_INVAL:
1462 trace_ppc_excp_inval(env->nip);
1463 msr |= 0x00080000;
1464 break;
1465 case POWERPC_EXCP_PRIV:
1466 msr |= 0x00040000;
1467 break;
1468 case POWERPC_EXCP_TRAP:
1469 msr |= 0x00020000;
1470 break;
1471 default:
1472
1473 cpu_abort(cs, "Invalid program exception %d. Aborting\n",
1474 env->error_code);
1475 break;
1476 }
1477 break;
1478 case POWERPC_EXCP_SYSCALL:
1479 lev = env->error_code;
1480
1481 if ((lev == 1) && cpu->vhyp) {
1482 dump_hcall(env);
1483 } else {
1484 dump_syscall(env);
1485 }
1486
1487
1488
1489
1490
1491 env->nip += 4;
1492
1493
1494 if ((lev == 1) && books_vhyp_handles_hcall(cpu)) {
1495 PPCVirtualHypervisorClass *vhc =
1496 PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
1497 vhc->hypercall(cpu->vhyp, cpu);
1498 return;
1499 }
1500 if (lev == 1) {
1501 new_msr |= (target_ulong)MSR_HVB;
1502 }
1503 break;
1504 case POWERPC_EXCP_SYSCALL_VECTORED:
1505 lev = env->error_code;
1506 dump_syscall(env);
1507 env->nip += 4;
1508 new_msr |= env->msr & ((target_ulong)1 << MSR_EE);
1509 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
1510
1511 vector += lev * 0x20;
1512
1513 env->lr = env->nip;
1514 env->ctr = msr;
1515 break;
1516 case POWERPC_EXCP_FPU:
1517 case POWERPC_EXCP_DECR:
1518 break;
1519 case POWERPC_EXCP_RESET:
1520
1521 if (FIELD_EX64(env->msr, MSR, POW)) {
1522
1523 msr |= 0x10000;
1524 new_msr |= ((target_ulong)1 << MSR_ME);
1525 }
1526 if (env->msr_mask & MSR_HVB) {
1527
1528
1529
1530
1531 new_msr |= (target_ulong)MSR_HVB;
1532 } else {
1533 if (FIELD_EX64(env->msr, MSR, POW)) {
1534 cpu_abort(cs, "Trying to deliver power-saving system reset "
1535 "exception %d with no HV support\n", excp);
1536 }
1537 }
1538 break;
1539 case POWERPC_EXCP_DSEG:
1540 case POWERPC_EXCP_ISEG:
1541 case POWERPC_EXCP_TRACE:
1542 break;
1543 case POWERPC_EXCP_HISI:
1544 msr |= env->error_code;
1545
1546 case POWERPC_EXCP_HDECR:
1547 case POWERPC_EXCP_HDSI:
1548 case POWERPC_EXCP_SDOOR_HV:
1549 case POWERPC_EXCP_HV_EMU:
1550 case POWERPC_EXCP_HVIRT:
1551 srr0 = SPR_HSRR0;
1552 srr1 = SPR_HSRR1;
1553 new_msr |= (target_ulong)MSR_HVB;
1554 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
1555 break;
1556 case POWERPC_EXCP_VPU:
1557 case POWERPC_EXCP_VSXU:
1558 case POWERPC_EXCP_FU:
1559 env->spr[SPR_FSCR] |= ((target_ulong)env->error_code << 56);
1560 break;
1561 case POWERPC_EXCP_HV_FU:
1562 env->spr[SPR_HFSCR] |= ((target_ulong)env->error_code << FSCR_IC_POS);
1563 srr0 = SPR_HSRR0;
1564 srr1 = SPR_HSRR1;
1565 new_msr |= (target_ulong)MSR_HVB;
1566 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
1567 break;
1568 case POWERPC_EXCP_PERFM_EBB:
1569 case POWERPC_EXCP_EXTERNAL_EBB:
1570 env->spr[SPR_BESCR] &= ~BESCR_GE;
1571
1572
1573
1574
1575
1576 env->spr[SPR_EBBRR] = env->nip;
1577 powerpc_set_excp_state(cpu, env->spr[SPR_EBBHR], env->msr);
1578
1579
1580
1581
1582 return;
1583 case POWERPC_EXCP_THERM:
1584 case POWERPC_EXCP_PERFM:
1585 case POWERPC_EXCP_VPUA:
1586 case POWERPC_EXCP_MAINT:
1587 case POWERPC_EXCP_SDOOR:
1588 case POWERPC_EXCP_HV_MAINT:
1589 cpu_abort(cs, "%s exception not implemented\n",
1590 powerpc_excp_name(excp));
1591 break;
1592 default:
1593 cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp);
1594 break;
1595 }
1596
1597
1598
1599
1600
1601 if (ppc_interrupts_little_endian(cpu, !!(new_msr & MSR_HVB))) {
1602 new_msr |= (target_ulong)1 << MSR_LE;
1603 }
1604
1605 new_msr |= (target_ulong)1 << MSR_SF;
1606
1607 if (excp != POWERPC_EXCP_SYSCALL_VECTORED) {
1608
1609 env->spr[srr0] = env->nip;
1610
1611
1612 env->spr[srr1] = msr;
1613 }
1614
1615 if ((new_msr & MSR_HVB) && books_vhyp_handles_hv_excp(cpu)) {
1616 PPCVirtualHypervisorClass *vhc =
1617 PPC_VIRTUAL_HYPERVISOR_GET_CLASS(cpu->vhyp);
1618
1619 vhc->deliver_hv_excp(cpu, excp);
1620
1621 powerpc_reset_excp_state(cpu);
1622
1623 } else {
1624
1625 if (!(env->msr_mask & MSR_HVB) && srr0 == SPR_HSRR0) {
1626 cpu_abort(cs, "Trying to deliver HV exception (HSRR) %d with "
1627 "no HV support\n", excp);
1628 }
1629
1630
1631 ppc_excp_apply_ail(cpu, excp, msr, &new_msr, &vector);
1632
1633 powerpc_set_excp_state(cpu, vector, new_msr);
1634 }
1635}
1636#else
1637static inline void powerpc_excp_books(PowerPCCPU *cpu, int excp)
1638{
1639 g_assert_not_reached();
1640}
1641#endif
1642
1643static void powerpc_excp(PowerPCCPU *cpu, int excp)
1644{
1645 CPUState *cs = CPU(cpu);
1646 CPUPPCState *env = &cpu->env;
1647
1648 if (excp <= POWERPC_EXCP_NONE || excp >= POWERPC_EXCP_NB) {
1649 cpu_abort(cs, "Invalid PowerPC exception %d. Aborting\n", excp);
1650 }
1651
1652 qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx
1653 " => %s (%d) error=%02x\n", env->nip, powerpc_excp_name(excp),
1654 excp, env->error_code);
1655
1656 switch (env->excp_model) {
1657 case POWERPC_EXCP_40x:
1658 powerpc_excp_40x(cpu, excp);
1659 break;
1660 case POWERPC_EXCP_6xx:
1661 powerpc_excp_6xx(cpu, excp);
1662 break;
1663 case POWERPC_EXCP_7xx:
1664 powerpc_excp_7xx(cpu, excp);
1665 break;
1666 case POWERPC_EXCP_74xx:
1667 powerpc_excp_74xx(cpu, excp);
1668 break;
1669 case POWERPC_EXCP_BOOKE:
1670 powerpc_excp_booke(cpu, excp);
1671 break;
1672 case POWERPC_EXCP_970:
1673 case POWERPC_EXCP_POWER7:
1674 case POWERPC_EXCP_POWER8:
1675 case POWERPC_EXCP_POWER9:
1676 case POWERPC_EXCP_POWER10:
1677 powerpc_excp_books(cpu, excp);
1678 break;
1679 default:
1680 g_assert_not_reached();
1681 }
1682}
1683
1684void ppc_cpu_do_interrupt(CPUState *cs)
1685{
1686 PowerPCCPU *cpu = POWERPC_CPU(cs);
1687
1688 powerpc_excp(cpu, cs->exception_index);
1689}
1690
1691#if defined(TARGET_PPC64)
1692#define P7_UNUSED_INTERRUPTS \
1693 (PPC_INTERRUPT_RESET | PPC_INTERRUPT_HVIRT | PPC_INTERRUPT_CEXT | \
1694 PPC_INTERRUPT_WDT | PPC_INTERRUPT_CDOORBELL | PPC_INTERRUPT_FIT | \
1695 PPC_INTERRUPT_PIT | PPC_INTERRUPT_DOORBELL | PPC_INTERRUPT_HDOORBELL | \
1696 PPC_INTERRUPT_THERM | PPC_INTERRUPT_EBB)
1697
1698static int p7_interrupt_powersave(CPUPPCState *env)
1699{
1700 if ((env->pending_interrupts & PPC_INTERRUPT_EXT) &&
1701 (env->spr[SPR_LPCR] & LPCR_P7_PECE0)) {
1702 return PPC_INTERRUPT_EXT;
1703 }
1704 if ((env->pending_interrupts & PPC_INTERRUPT_DECR) &&
1705 (env->spr[SPR_LPCR] & LPCR_P7_PECE1)) {
1706 return PPC_INTERRUPT_DECR;
1707 }
1708 if ((env->pending_interrupts & PPC_INTERRUPT_MCK) &&
1709 (env->spr[SPR_LPCR] & LPCR_P7_PECE2)) {
1710 return PPC_INTERRUPT_MCK;
1711 }
1712 if ((env->pending_interrupts & PPC_INTERRUPT_HMI) &&
1713 (env->spr[SPR_LPCR] & LPCR_P7_PECE2)) {
1714 return PPC_INTERRUPT_HMI;
1715 }
1716 if (env->pending_interrupts & PPC_INTERRUPT_RESET) {
1717 return PPC_INTERRUPT_RESET;
1718 }
1719 return 0;
1720}
1721
1722static int p7_next_unmasked_interrupt(CPUPPCState *env)
1723{
1724 PowerPCCPU *cpu = env_archcpu(env);
1725 CPUState *cs = CPU(cpu);
1726
1727 bool msr_ee = FIELD_EX64(env->msr, MSR, EE) || env->resume_as_sreset;
1728
1729 assert((env->pending_interrupts & P7_UNUSED_INTERRUPTS) == 0);
1730
1731 if (cs->halted) {
1732
1733 return p7_interrupt_powersave(env);
1734 }
1735
1736
1737 if (env->pending_interrupts & PPC_INTERRUPT_MCK) {
1738 return PPC_INTERRUPT_MCK;
1739 }
1740
1741
1742 if (env->pending_interrupts & PPC_INTERRUPT_HDECR) {
1743
1744 bool hdice = !!(env->spr[SPR_LPCR] & LPCR_HDICE);
1745 if ((msr_ee || !FIELD_EX64_HV(env->msr)) && hdice) {
1746
1747 return PPC_INTERRUPT_HDECR;
1748 }
1749 }
1750
1751
1752 if (env->pending_interrupts & PPC_INTERRUPT_EXT) {
1753 bool lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0);
1754 bool heic = !!(env->spr[SPR_LPCR] & LPCR_HEIC);
1755
1756 if ((msr_ee && !(heic && FIELD_EX64_HV(env->msr) &&
1757 !FIELD_EX64(env->msr, MSR, PR))) ||
1758 (env->has_hv_mode && !FIELD_EX64_HV(env->msr) && !lpes0)) {
1759 return PPC_INTERRUPT_EXT;
1760 }
1761 }
1762 if (msr_ee != 0) {
1763
1764 if (env->pending_interrupts & PPC_INTERRUPT_DECR) {
1765 return PPC_INTERRUPT_DECR;
1766 }
1767 if (env->pending_interrupts & PPC_INTERRUPT_PERFM) {
1768 return PPC_INTERRUPT_PERFM;
1769 }
1770 }
1771
1772 return 0;
1773}
1774
1775#define P8_UNUSED_INTERRUPTS \
1776 (PPC_INTERRUPT_RESET | PPC_INTERRUPT_DEBUG | PPC_INTERRUPT_HVIRT | \
1777 PPC_INTERRUPT_CEXT | PPC_INTERRUPT_WDT | PPC_INTERRUPT_CDOORBELL | \
1778 PPC_INTERRUPT_FIT | PPC_INTERRUPT_PIT | PPC_INTERRUPT_THERM)
1779
1780static int p8_interrupt_powersave(CPUPPCState *env)
1781{
1782 if ((env->pending_interrupts & PPC_INTERRUPT_EXT) &&
1783 (env->spr[SPR_LPCR] & LPCR_P8_PECE2)) {
1784 return PPC_INTERRUPT_EXT;
1785 }
1786 if ((env->pending_interrupts & PPC_INTERRUPT_DECR) &&
1787 (env->spr[SPR_LPCR] & LPCR_P8_PECE3)) {
1788 return PPC_INTERRUPT_DECR;
1789 }
1790 if ((env->pending_interrupts & PPC_INTERRUPT_MCK) &&
1791 (env->spr[SPR_LPCR] & LPCR_P8_PECE4)) {
1792 return PPC_INTERRUPT_MCK;
1793 }
1794 if ((env->pending_interrupts & PPC_INTERRUPT_HMI) &&
1795 (env->spr[SPR_LPCR] & LPCR_P8_PECE4)) {
1796 return PPC_INTERRUPT_HMI;
1797 }
1798 if ((env->pending_interrupts & PPC_INTERRUPT_DOORBELL) &&
1799 (env->spr[SPR_LPCR] & LPCR_P8_PECE0)) {
1800 return PPC_INTERRUPT_DOORBELL;
1801 }
1802 if ((env->pending_interrupts & PPC_INTERRUPT_HDOORBELL) &&
1803 (env->spr[SPR_LPCR] & LPCR_P8_PECE1)) {
1804 return PPC_INTERRUPT_HDOORBELL;
1805 }
1806 if (env->pending_interrupts & PPC_INTERRUPT_RESET) {
1807 return PPC_INTERRUPT_RESET;
1808 }
1809 return 0;
1810}
1811
1812static int p8_next_unmasked_interrupt(CPUPPCState *env)
1813{
1814 PowerPCCPU *cpu = env_archcpu(env);
1815 CPUState *cs = CPU(cpu);
1816
1817 bool msr_ee = FIELD_EX64(env->msr, MSR, EE) || env->resume_as_sreset;
1818
1819 assert((env->pending_interrupts & P8_UNUSED_INTERRUPTS) == 0);
1820
1821 if (cs->halted) {
1822
1823 return p8_interrupt_powersave(env);
1824 }
1825
1826
1827 if (env->pending_interrupts & PPC_INTERRUPT_MCK) {
1828 return PPC_INTERRUPT_MCK;
1829 }
1830
1831
1832 if (env->pending_interrupts & PPC_INTERRUPT_HDECR) {
1833
1834 bool hdice = !!(env->spr[SPR_LPCR] & LPCR_HDICE);
1835 if ((msr_ee || !FIELD_EX64_HV(env->msr)) && hdice) {
1836
1837 return PPC_INTERRUPT_HDECR;
1838 }
1839 }
1840
1841
1842 if (env->pending_interrupts & PPC_INTERRUPT_EXT) {
1843 bool lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0);
1844 bool heic = !!(env->spr[SPR_LPCR] & LPCR_HEIC);
1845
1846 if ((msr_ee && !(heic && FIELD_EX64_HV(env->msr) &&
1847 !FIELD_EX64(env->msr, MSR, PR))) ||
1848 (env->has_hv_mode && !FIELD_EX64_HV(env->msr) && !lpes0)) {
1849 return PPC_INTERRUPT_EXT;
1850 }
1851 }
1852 if (msr_ee != 0) {
1853
1854 if (env->pending_interrupts & PPC_INTERRUPT_DECR) {
1855 return PPC_INTERRUPT_DECR;
1856 }
1857 if (env->pending_interrupts & PPC_INTERRUPT_DOORBELL) {
1858 return PPC_INTERRUPT_DOORBELL;
1859 }
1860 if (env->pending_interrupts & PPC_INTERRUPT_HDOORBELL) {
1861 return PPC_INTERRUPT_HDOORBELL;
1862 }
1863 if (env->pending_interrupts & PPC_INTERRUPT_PERFM) {
1864 return PPC_INTERRUPT_PERFM;
1865 }
1866
1867 if (env->pending_interrupts & PPC_INTERRUPT_EBB) {
1868
1869
1870
1871
1872 if (FIELD_EX64(env->msr, MSR, PR) &&
1873 (env->spr[SPR_BESCR] & BESCR_GE)) {
1874 return PPC_INTERRUPT_EBB;
1875 }
1876 }
1877 }
1878
1879 return 0;
1880}
1881
1882#define P9_UNUSED_INTERRUPTS \
1883 (PPC_INTERRUPT_RESET | PPC_INTERRUPT_DEBUG | PPC_INTERRUPT_CEXT | \
1884 PPC_INTERRUPT_WDT | PPC_INTERRUPT_CDOORBELL | PPC_INTERRUPT_FIT | \
1885 PPC_INTERRUPT_PIT | PPC_INTERRUPT_THERM)
1886
1887static int p9_interrupt_powersave(CPUPPCState *env)
1888{
1889
1890 if ((env->pending_interrupts & PPC_INTERRUPT_EXT) &&
1891 (env->spr[SPR_LPCR] & LPCR_EEE)) {
1892 bool heic = !!(env->spr[SPR_LPCR] & LPCR_HEIC);
1893 if (!heic || !FIELD_EX64_HV(env->msr) ||
1894 FIELD_EX64(env->msr, MSR, PR)) {
1895 return PPC_INTERRUPT_EXT;
1896 }
1897 }
1898
1899 if ((env->pending_interrupts & PPC_INTERRUPT_DECR) &&
1900 (env->spr[SPR_LPCR] & LPCR_DEE)) {
1901 return PPC_INTERRUPT_DECR;
1902 }
1903
1904 if (env->spr[SPR_LPCR] & LPCR_OEE) {
1905 if (env->pending_interrupts & PPC_INTERRUPT_MCK) {
1906 return PPC_INTERRUPT_MCK;
1907 }
1908 if (env->pending_interrupts & PPC_INTERRUPT_HMI) {
1909 return PPC_INTERRUPT_HMI;
1910 }
1911 }
1912
1913 if ((env->pending_interrupts & PPC_INTERRUPT_DOORBELL) &&
1914 (env->spr[SPR_LPCR] & LPCR_PDEE)) {
1915 return PPC_INTERRUPT_DOORBELL;
1916 }
1917
1918 if ((env->pending_interrupts & PPC_INTERRUPT_HDOORBELL) &&
1919 (env->spr[SPR_LPCR] & LPCR_HDEE)) {
1920 return PPC_INTERRUPT_HDOORBELL;
1921 }
1922
1923 if ((env->pending_interrupts & PPC_INTERRUPT_HVIRT) &&
1924 (env->spr[SPR_LPCR] & LPCR_HVEE)) {
1925 return PPC_INTERRUPT_HVIRT;
1926 }
1927 if (env->pending_interrupts & PPC_INTERRUPT_RESET) {
1928 return PPC_INTERRUPT_RESET;
1929 }
1930 return 0;
1931}
1932
1933static int p9_next_unmasked_interrupt(CPUPPCState *env)
1934{
1935 PowerPCCPU *cpu = env_archcpu(env);
1936 CPUState *cs = CPU(cpu);
1937
1938 bool msr_ee = FIELD_EX64(env->msr, MSR, EE) || env->resume_as_sreset;
1939
1940 assert((env->pending_interrupts & P9_UNUSED_INTERRUPTS) == 0);
1941
1942 if (cs->halted) {
1943 if (env->spr[SPR_PSSCR] & PSSCR_EC) {
1944
1945
1946
1947
1948 return p9_interrupt_powersave(env);
1949 } else {
1950
1951
1952
1953
1954 msr_ee = true;
1955 }
1956 }
1957
1958
1959 if (env->pending_interrupts & PPC_INTERRUPT_MCK) {
1960 return PPC_INTERRUPT_MCK;
1961 }
1962
1963
1964 if (env->pending_interrupts & PPC_INTERRUPT_HDECR) {
1965
1966 bool hdice = !!(env->spr[SPR_LPCR] & LPCR_HDICE);
1967 if ((msr_ee || !FIELD_EX64_HV(env->msr)) && hdice) {
1968
1969 return PPC_INTERRUPT_HDECR;
1970 }
1971 }
1972
1973
1974 if (env->pending_interrupts & PPC_INTERRUPT_HVIRT) {
1975
1976 bool hvice = !!(env->spr[SPR_LPCR] & LPCR_HVICE);
1977 if ((msr_ee || !FIELD_EX64_HV(env->msr)) && hvice) {
1978 return PPC_INTERRUPT_HVIRT;
1979 }
1980 }
1981
1982
1983 if (env->pending_interrupts & PPC_INTERRUPT_EXT) {
1984 bool lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0);
1985 bool heic = !!(env->spr[SPR_LPCR] & LPCR_HEIC);
1986
1987 if ((msr_ee && !(heic && FIELD_EX64_HV(env->msr) &&
1988 !FIELD_EX64(env->msr, MSR, PR))) ||
1989 (env->has_hv_mode && !FIELD_EX64_HV(env->msr) && !lpes0)) {
1990 return PPC_INTERRUPT_EXT;
1991 }
1992 }
1993 if (msr_ee != 0) {
1994
1995 if (env->pending_interrupts & PPC_INTERRUPT_DECR) {
1996 return PPC_INTERRUPT_DECR;
1997 }
1998 if (env->pending_interrupts & PPC_INTERRUPT_DOORBELL) {
1999 return PPC_INTERRUPT_DOORBELL;
2000 }
2001 if (env->pending_interrupts & PPC_INTERRUPT_HDOORBELL) {
2002 return PPC_INTERRUPT_HDOORBELL;
2003 }
2004 if (env->pending_interrupts & PPC_INTERRUPT_PERFM) {
2005 return PPC_INTERRUPT_PERFM;
2006 }
2007
2008 if (env->pending_interrupts & PPC_INTERRUPT_EBB) {
2009
2010
2011
2012
2013 if (FIELD_EX64(env->msr, MSR, PR) &&
2014 (env->spr[SPR_BESCR] & BESCR_GE)) {
2015 return PPC_INTERRUPT_EBB;
2016 }
2017 }
2018 }
2019
2020 return 0;
2021}
2022#endif
2023
2024static int ppc_next_unmasked_interrupt_generic(CPUPPCState *env)
2025{
2026 bool async_deliver;
2027
2028
2029 if (env->pending_interrupts & PPC_INTERRUPT_RESET) {
2030 return PPC_INTERRUPT_RESET;
2031 }
2032
2033 if (env->pending_interrupts & PPC_INTERRUPT_MCK) {
2034 return PPC_INTERRUPT_MCK;
2035 }
2036#if 0
2037
2038 if (env->pending_interrupts & PPC_INTERRUPT_DEBUG) {
2039 return PPC_INTERRUPT_DEBUG;
2040 }
2041#endif
2042
2043
2044
2045
2046
2047
2048
2049 async_deliver = FIELD_EX64(env->msr, MSR, EE) || env->resume_as_sreset;
2050
2051
2052 if (env->pending_interrupts & PPC_INTERRUPT_HDECR) {
2053
2054 bool hdice = !!(env->spr[SPR_LPCR] & LPCR_HDICE);
2055 if ((async_deliver || !FIELD_EX64_HV(env->msr)) && hdice) {
2056
2057 return PPC_INTERRUPT_HDECR;
2058 }
2059 }
2060
2061
2062 if (env->pending_interrupts & PPC_INTERRUPT_HVIRT) {
2063
2064 bool hvice = !!(env->spr[SPR_LPCR] & LPCR_HVICE);
2065 if ((async_deliver || !FIELD_EX64_HV(env->msr)) && hvice) {
2066 return PPC_INTERRUPT_HVIRT;
2067 }
2068 }
2069
2070
2071 if (env->pending_interrupts & PPC_INTERRUPT_EXT) {
2072 bool lpes0 = !!(env->spr[SPR_LPCR] & LPCR_LPES0);
2073 bool heic = !!(env->spr[SPR_LPCR] & LPCR_HEIC);
2074
2075 if ((async_deliver && !(heic && FIELD_EX64_HV(env->msr) &&
2076 !FIELD_EX64(env->msr, MSR, PR))) ||
2077 (env->has_hv_mode && !FIELD_EX64_HV(env->msr) && !lpes0)) {
2078 return PPC_INTERRUPT_EXT;
2079 }
2080 }
2081 if (FIELD_EX64(env->msr, MSR, CE)) {
2082
2083 if (env->pending_interrupts & PPC_INTERRUPT_CEXT) {
2084 return PPC_INTERRUPT_CEXT;
2085 }
2086 }
2087 if (async_deliver != 0) {
2088
2089 if (env->pending_interrupts & PPC_INTERRUPT_WDT) {
2090 return PPC_INTERRUPT_WDT;
2091 }
2092 if (env->pending_interrupts & PPC_INTERRUPT_CDOORBELL) {
2093 return PPC_INTERRUPT_CDOORBELL;
2094 }
2095
2096 if (env->pending_interrupts & PPC_INTERRUPT_FIT) {
2097 return PPC_INTERRUPT_FIT;
2098 }
2099
2100 if (env->pending_interrupts & PPC_INTERRUPT_PIT) {
2101 return PPC_INTERRUPT_PIT;
2102 }
2103
2104 if (env->pending_interrupts & PPC_INTERRUPT_DECR) {
2105 return PPC_INTERRUPT_DECR;
2106 }
2107 if (env->pending_interrupts & PPC_INTERRUPT_DOORBELL) {
2108 return PPC_INTERRUPT_DOORBELL;
2109 }
2110 if (env->pending_interrupts & PPC_INTERRUPT_HDOORBELL) {
2111 return PPC_INTERRUPT_HDOORBELL;
2112 }
2113 if (env->pending_interrupts & PPC_INTERRUPT_PERFM) {
2114 return PPC_INTERRUPT_PERFM;
2115 }
2116
2117 if (env->pending_interrupts & PPC_INTERRUPT_THERM) {
2118 return PPC_INTERRUPT_THERM;
2119 }
2120
2121 if (env->pending_interrupts & PPC_INTERRUPT_EBB) {
2122
2123
2124
2125
2126 if (FIELD_EX64(env->msr, MSR, PR) &&
2127 (env->spr[SPR_BESCR] & BESCR_GE)) {
2128 return PPC_INTERRUPT_EBB;
2129 }
2130 }
2131 }
2132
2133 return 0;
2134}
2135
2136static int ppc_next_unmasked_interrupt(CPUPPCState *env)
2137{
2138 switch (env->excp_model) {
2139#if defined(TARGET_PPC64)
2140 case POWERPC_EXCP_POWER7:
2141 return p7_next_unmasked_interrupt(env);
2142 case POWERPC_EXCP_POWER8:
2143 return p8_next_unmasked_interrupt(env);
2144 case POWERPC_EXCP_POWER9:
2145 case POWERPC_EXCP_POWER10:
2146 return p9_next_unmasked_interrupt(env);
2147#endif
2148 default:
2149 return ppc_next_unmasked_interrupt_generic(env);
2150 }
2151}
2152
2153
2154
2155
2156
2157
2158
2159
2160
2161
2162
2163
2164
2165
2166void ppc_maybe_interrupt(CPUPPCState *env)
2167{
2168 CPUState *cs = env_cpu(env);
2169 QEMU_IOTHREAD_LOCK_GUARD();
2170
2171 if (ppc_next_unmasked_interrupt(env)) {
2172 cpu_interrupt(cs, CPU_INTERRUPT_HARD);
2173 } else {
2174 cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
2175 }
2176}
2177
2178#if defined(TARGET_PPC64)
2179static void p7_deliver_interrupt(CPUPPCState *env, int interrupt)
2180{
2181 PowerPCCPU *cpu = env_archcpu(env);
2182 CPUState *cs = env_cpu(env);
2183
2184 switch (interrupt) {
2185 case PPC_INTERRUPT_MCK:
2186 env->pending_interrupts &= ~PPC_INTERRUPT_MCK;
2187 powerpc_excp(cpu, POWERPC_EXCP_MCHECK);
2188 break;
2189
2190 case PPC_INTERRUPT_HDECR:
2191
2192 env->pending_interrupts &= ~PPC_INTERRUPT_HDECR;
2193 powerpc_excp(cpu, POWERPC_EXCP_HDECR);
2194 break;
2195
2196 case PPC_INTERRUPT_EXT:
2197 if (books_vhyp_promotes_external_to_hvirt(cpu)) {
2198 powerpc_excp(cpu, POWERPC_EXCP_HVIRT);
2199 } else {
2200 powerpc_excp(cpu, POWERPC_EXCP_EXTERNAL);
2201 }
2202 break;
2203
2204 case PPC_INTERRUPT_DECR:
2205 powerpc_excp(cpu, POWERPC_EXCP_DECR);
2206 break;
2207 case PPC_INTERRUPT_PERFM:
2208 env->pending_interrupts &= ~PPC_INTERRUPT_PERFM;
2209 powerpc_excp(cpu, POWERPC_EXCP_PERFM);
2210 break;
2211 case 0:
2212
2213
2214
2215
2216
2217
2218
2219
2220
2221
2222
2223 assert(!env->resume_as_sreset);
2224 break;
2225 default:
2226 cpu_abort(cs, "Invalid PowerPC interrupt %d. Aborting\n", interrupt);
2227 }
2228}
2229
2230static void p8_deliver_interrupt(CPUPPCState *env, int interrupt)
2231{
2232 PowerPCCPU *cpu = env_archcpu(env);
2233 CPUState *cs = env_cpu(env);
2234
2235 switch (interrupt) {
2236 case PPC_INTERRUPT_MCK:
2237 env->pending_interrupts &= ~PPC_INTERRUPT_MCK;
2238 powerpc_excp(cpu, POWERPC_EXCP_MCHECK);
2239 break;
2240
2241 case PPC_INTERRUPT_HDECR:
2242
2243 env->pending_interrupts &= ~PPC_INTERRUPT_HDECR;
2244 powerpc_excp(cpu, POWERPC_EXCP_HDECR);
2245 break;
2246
2247 case PPC_INTERRUPT_EXT:
2248 if (books_vhyp_promotes_external_to_hvirt(cpu)) {
2249 powerpc_excp(cpu, POWERPC_EXCP_HVIRT);
2250 } else {
2251 powerpc_excp(cpu, POWERPC_EXCP_EXTERNAL);
2252 }
2253 break;
2254
2255 case PPC_INTERRUPT_DECR:
2256 powerpc_excp(cpu, POWERPC_EXCP_DECR);
2257 break;
2258 case PPC_INTERRUPT_DOORBELL:
2259 env->pending_interrupts &= ~PPC_INTERRUPT_DOORBELL;
2260 if (is_book3s_arch2x(env)) {
2261 powerpc_excp(cpu, POWERPC_EXCP_SDOOR);
2262 } else {
2263 powerpc_excp(cpu, POWERPC_EXCP_DOORI);
2264 }
2265 break;
2266 case PPC_INTERRUPT_HDOORBELL:
2267 env->pending_interrupts &= ~PPC_INTERRUPT_HDOORBELL;
2268 powerpc_excp(cpu, POWERPC_EXCP_SDOOR_HV);
2269 break;
2270 case PPC_INTERRUPT_PERFM:
2271 env->pending_interrupts &= ~PPC_INTERRUPT_PERFM;
2272 powerpc_excp(cpu, POWERPC_EXCP_PERFM);
2273 break;
2274 case PPC_INTERRUPT_EBB:
2275 env->pending_interrupts &= ~PPC_INTERRUPT_EBB;
2276 if (env->spr[SPR_BESCR] & BESCR_PMEO) {
2277 powerpc_excp(cpu, POWERPC_EXCP_PERFM_EBB);
2278 } else if (env->spr[SPR_BESCR] & BESCR_EEO) {
2279 powerpc_excp(cpu, POWERPC_EXCP_EXTERNAL_EBB);
2280 }
2281 break;
2282 case 0:
2283
2284
2285
2286
2287
2288
2289
2290
2291
2292
2293
2294 assert(!env->resume_as_sreset);
2295 break;
2296 default:
2297 cpu_abort(cs, "Invalid PowerPC interrupt %d. Aborting\n", interrupt);
2298 }
2299}
2300
2301static void p9_deliver_interrupt(CPUPPCState *env, int interrupt)
2302{
2303 PowerPCCPU *cpu = env_archcpu(env);
2304 CPUState *cs = env_cpu(env);
2305
2306 if (cs->halted && !(env->spr[SPR_PSSCR] & PSSCR_EC) &&
2307 !FIELD_EX64(env->msr, MSR, EE)) {
2308
2309
2310
2311
2312 return;
2313 }
2314
2315 switch (interrupt) {
2316 case PPC_INTERRUPT_MCK:
2317 env->pending_interrupts &= ~PPC_INTERRUPT_MCK;
2318 powerpc_excp(cpu, POWERPC_EXCP_MCHECK);
2319 break;
2320
2321 case PPC_INTERRUPT_HDECR:
2322
2323 env->pending_interrupts &= ~PPC_INTERRUPT_HDECR;
2324 powerpc_excp(cpu, POWERPC_EXCP_HDECR);
2325 break;
2326 case PPC_INTERRUPT_HVIRT:
2327 powerpc_excp(cpu, POWERPC_EXCP_HVIRT);
2328 break;
2329
2330 case PPC_INTERRUPT_EXT:
2331 if (books_vhyp_promotes_external_to_hvirt(cpu)) {
2332 powerpc_excp(cpu, POWERPC_EXCP_HVIRT);
2333 } else {
2334 powerpc_excp(cpu, POWERPC_EXCP_EXTERNAL);
2335 }
2336 break;
2337
2338 case PPC_INTERRUPT_DECR:
2339 powerpc_excp(cpu, POWERPC_EXCP_DECR);
2340 break;
2341 case PPC_INTERRUPT_DOORBELL:
2342 env->pending_interrupts &= ~PPC_INTERRUPT_DOORBELL;
2343 powerpc_excp(cpu, POWERPC_EXCP_SDOOR);
2344 break;
2345 case PPC_INTERRUPT_HDOORBELL:
2346 env->pending_interrupts &= ~PPC_INTERRUPT_HDOORBELL;
2347 powerpc_excp(cpu, POWERPC_EXCP_SDOOR_HV);
2348 break;
2349 case PPC_INTERRUPT_PERFM:
2350 env->pending_interrupts &= ~PPC_INTERRUPT_PERFM;
2351 powerpc_excp(cpu, POWERPC_EXCP_PERFM);
2352 break;
2353 case PPC_INTERRUPT_EBB:
2354 env->pending_interrupts &= ~PPC_INTERRUPT_EBB;
2355 if (env->spr[SPR_BESCR] & BESCR_PMEO) {
2356 powerpc_excp(cpu, POWERPC_EXCP_PERFM_EBB);
2357 } else if (env->spr[SPR_BESCR] & BESCR_EEO) {
2358 powerpc_excp(cpu, POWERPC_EXCP_EXTERNAL_EBB);
2359 }
2360 break;
2361 case 0:
2362
2363
2364
2365
2366
2367
2368
2369
2370
2371
2372
2373 assert(!env->resume_as_sreset);
2374 break;
2375 default:
2376 cpu_abort(cs, "Invalid PowerPC interrupt %d. Aborting\n", interrupt);
2377 }
2378}
2379#endif
2380
2381static void ppc_deliver_interrupt_generic(CPUPPCState *env, int interrupt)
2382{
2383 PowerPCCPU *cpu = env_archcpu(env);
2384 CPUState *cs = env_cpu(env);
2385
2386 switch (interrupt) {
2387 case PPC_INTERRUPT_RESET:
2388 env->pending_interrupts &= ~PPC_INTERRUPT_RESET;
2389 powerpc_excp(cpu, POWERPC_EXCP_RESET);
2390 break;
2391 case PPC_INTERRUPT_MCK:
2392 env->pending_interrupts &= ~PPC_INTERRUPT_MCK;
2393 powerpc_excp(cpu, POWERPC_EXCP_MCHECK);
2394 break;
2395
2396 case PPC_INTERRUPT_HDECR:
2397
2398 env->pending_interrupts &= ~PPC_INTERRUPT_HDECR;
2399 powerpc_excp(cpu, POWERPC_EXCP_HDECR);
2400 break;
2401 case PPC_INTERRUPT_HVIRT:
2402 powerpc_excp(cpu, POWERPC_EXCP_HVIRT);
2403 break;
2404
2405 case PPC_INTERRUPT_EXT:
2406 if (books_vhyp_promotes_external_to_hvirt(cpu)) {
2407 powerpc_excp(cpu, POWERPC_EXCP_HVIRT);
2408 } else {
2409 powerpc_excp(cpu, POWERPC_EXCP_EXTERNAL);
2410 }
2411 break;
2412 case PPC_INTERRUPT_CEXT:
2413 powerpc_excp(cpu, POWERPC_EXCP_CRITICAL);
2414 break;
2415
2416 case PPC_INTERRUPT_WDT:
2417 env->pending_interrupts &= ~PPC_INTERRUPT_WDT;
2418 powerpc_excp(cpu, POWERPC_EXCP_WDT);
2419 break;
2420 case PPC_INTERRUPT_CDOORBELL:
2421 env->pending_interrupts &= ~PPC_INTERRUPT_CDOORBELL;
2422 powerpc_excp(cpu, POWERPC_EXCP_DOORCI);
2423 break;
2424 case PPC_INTERRUPT_FIT:
2425 env->pending_interrupts &= ~PPC_INTERRUPT_FIT;
2426 powerpc_excp(cpu, POWERPC_EXCP_FIT);
2427 break;
2428 case PPC_INTERRUPT_PIT:
2429 env->pending_interrupts &= ~PPC_INTERRUPT_PIT;
2430 powerpc_excp(cpu, POWERPC_EXCP_PIT);
2431 break;
2432 case PPC_INTERRUPT_DECR:
2433 if (ppc_decr_clear_on_delivery(env)) {
2434 env->pending_interrupts &= ~PPC_INTERRUPT_DECR;
2435 }
2436 powerpc_excp(cpu, POWERPC_EXCP_DECR);
2437 break;
2438 case PPC_INTERRUPT_DOORBELL:
2439 env->pending_interrupts &= ~PPC_INTERRUPT_DOORBELL;
2440 if (is_book3s_arch2x(env)) {
2441 powerpc_excp(cpu, POWERPC_EXCP_SDOOR);
2442 } else {
2443 powerpc_excp(cpu, POWERPC_EXCP_DOORI);
2444 }
2445 break;
2446 case PPC_INTERRUPT_HDOORBELL:
2447 env->pending_interrupts &= ~PPC_INTERRUPT_HDOORBELL;
2448 powerpc_excp(cpu, POWERPC_EXCP_SDOOR_HV);
2449 break;
2450 case PPC_INTERRUPT_PERFM:
2451 env->pending_interrupts &= ~PPC_INTERRUPT_PERFM;
2452 powerpc_excp(cpu, POWERPC_EXCP_PERFM);
2453 break;
2454 case PPC_INTERRUPT_THERM:
2455 env->pending_interrupts &= ~PPC_INTERRUPT_THERM;
2456 powerpc_excp(cpu, POWERPC_EXCP_THERM);
2457 break;
2458 case PPC_INTERRUPT_EBB:
2459 env->pending_interrupts &= ~PPC_INTERRUPT_EBB;
2460 if (env->spr[SPR_BESCR] & BESCR_PMEO) {
2461 powerpc_excp(cpu, POWERPC_EXCP_PERFM_EBB);
2462 } else if (env->spr[SPR_BESCR] & BESCR_EEO) {
2463 powerpc_excp(cpu, POWERPC_EXCP_EXTERNAL_EBB);
2464 }
2465 break;
2466 case 0:
2467
2468
2469
2470
2471
2472
2473
2474
2475
2476
2477
2478 assert(!env->resume_as_sreset);
2479 break;
2480 default:
2481 cpu_abort(cs, "Invalid PowerPC interrupt %d. Aborting\n", interrupt);
2482 }
2483}
2484
2485static void ppc_deliver_interrupt(CPUPPCState *env, int interrupt)
2486{
2487 switch (env->excp_model) {
2488#if defined(TARGET_PPC64)
2489 case POWERPC_EXCP_POWER7:
2490 p7_deliver_interrupt(env, interrupt);
2491 break;
2492 case POWERPC_EXCP_POWER8:
2493 p8_deliver_interrupt(env, interrupt);
2494 break;
2495 case POWERPC_EXCP_POWER9:
2496 case POWERPC_EXCP_POWER10:
2497 p9_deliver_interrupt(env, interrupt);
2498 break;
2499#endif
2500 default:
2501 ppc_deliver_interrupt_generic(env, interrupt);
2502 }
2503}
2504
2505void ppc_cpu_do_system_reset(CPUState *cs)
2506{
2507 PowerPCCPU *cpu = POWERPC_CPU(cs);
2508
2509 powerpc_excp(cpu, POWERPC_EXCP_RESET);
2510}
2511
2512void ppc_cpu_do_fwnmi_machine_check(CPUState *cs, target_ulong vector)
2513{
2514 PowerPCCPU *cpu = POWERPC_CPU(cs);
2515 CPUPPCState *env = &cpu->env;
2516 target_ulong msr = 0;
2517
2518
2519
2520
2521
2522 msr = (1ULL << MSR_ME);
2523 msr |= env->msr & (1ULL << MSR_SF);
2524 if (ppc_interrupts_little_endian(cpu, false)) {
2525 msr |= (1ULL << MSR_LE);
2526 }
2527
2528
2529
2530 powerpc_set_excp_state(cpu, vector, msr);
2531}
2532
2533bool ppc_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
2534{
2535 PowerPCCPU *cpu = POWERPC_CPU(cs);
2536 CPUPPCState *env = &cpu->env;
2537 int interrupt;
2538
2539 if ((interrupt_request & CPU_INTERRUPT_HARD) == 0) {
2540 return false;
2541 }
2542
2543 interrupt = ppc_next_unmasked_interrupt(env);
2544 if (interrupt == 0) {
2545 return false;
2546 }
2547
2548 ppc_deliver_interrupt(env, interrupt);
2549 if (env->pending_interrupts == 0) {
2550 cpu_reset_interrupt(cs, CPU_INTERRUPT_HARD);
2551 }
2552 return true;
2553}
2554
2555#endif
2556
2557
2558
2559
2560void raise_exception_err_ra(CPUPPCState *env, uint32_t exception,
2561 uint32_t error_code, uintptr_t raddr)
2562{
2563 CPUState *cs = env_cpu(env);
2564
2565 cs->exception_index = exception;
2566 env->error_code = error_code;
2567 cpu_loop_exit_restore(cs, raddr);
2568}
2569
2570void raise_exception_err(CPUPPCState *env, uint32_t exception,
2571 uint32_t error_code)
2572{
2573 raise_exception_err_ra(env, exception, error_code, 0);
2574}
2575
2576void raise_exception(CPUPPCState *env, uint32_t exception)
2577{
2578 raise_exception_err_ra(env, exception, 0, 0);
2579}
2580
2581void raise_exception_ra(CPUPPCState *env, uint32_t exception,
2582 uintptr_t raddr)
2583{
2584 raise_exception_err_ra(env, exception, 0, raddr);
2585}
2586
2587#ifdef CONFIG_TCG
2588void helper_raise_exception_err(CPUPPCState *env, uint32_t exception,
2589 uint32_t error_code)
2590{
2591 raise_exception_err_ra(env, exception, error_code, 0);
2592}
2593
2594void helper_raise_exception(CPUPPCState *env, uint32_t exception)
2595{
2596 raise_exception_err_ra(env, exception, 0, 0);
2597}
2598#endif
2599
2600#if !defined(CONFIG_USER_ONLY)
2601#ifdef CONFIG_TCG
2602void helper_store_msr(CPUPPCState *env, target_ulong val)
2603{
2604 uint32_t excp = hreg_store_msr(env, val, 0);
2605
2606 if (excp != 0) {
2607 CPUState *cs = env_cpu(env);
2608 cpu_interrupt_exittb(cs);
2609 raise_exception(env, excp);
2610 }
2611}
2612
2613void helper_ppc_maybe_interrupt(CPUPPCState *env)
2614{
2615 ppc_maybe_interrupt(env);
2616}
2617
2618#if defined(TARGET_PPC64)
2619void helper_scv(CPUPPCState *env, uint32_t lev)
2620{
2621 if (env->spr[SPR_FSCR] & (1ull << FSCR_SCV)) {
2622 raise_exception_err(env, POWERPC_EXCP_SYSCALL_VECTORED, lev);
2623 } else {
2624 raise_exception_err(env, POWERPC_EXCP_FU, FSCR_IC_SCV);
2625 }
2626}
2627
2628void helper_pminsn(CPUPPCState *env, uint32_t insn)
2629{
2630 CPUState *cs;
2631
2632 cs = env_cpu(env);
2633 cs->halted = 1;
2634
2635
2636 env->resume_as_sreset = (insn != PPC_PM_STOP) ||
2637 (env->spr[SPR_PSSCR] & PSSCR_EC);
2638
2639
2640 if (env->resume_as_sreset) {
2641 PowerPCCPU *cpu = env_archcpu(env);
2642 ppc_set_irq(cpu, PPC_INTERRUPT_HDECR, 0);
2643 }
2644
2645 ppc_maybe_interrupt(env);
2646}
2647#endif
2648
2649static void do_rfi(CPUPPCState *env, target_ulong nip, target_ulong msr)
2650{
2651 CPUState *cs = env_cpu(env);
2652
2653
2654 msr &= ~(1ULL << MSR_POW);
2655
2656
2657 if (env->flags & POWERPC_FLAG_TGPR)
2658 msr &= ~(1ULL << MSR_TGPR);
2659
2660#if defined(TARGET_PPC64)
2661
2662 if (!msr_is_64bit(env, msr)) {
2663 nip = (uint32_t)nip;
2664 }
2665#else
2666 nip = (uint32_t)nip;
2667#endif
2668
2669 env->nip = nip & ~((target_ulong)0x00000003);
2670 hreg_store_msr(env, msr, 1);
2671 trace_ppc_excp_rfi(env->nip, env->msr);
2672
2673
2674
2675
2676 cpu_interrupt_exittb(cs);
2677
2678 env->reserve_addr = -1;
2679
2680
2681 check_tlb_flush(env, false);
2682}
2683
2684void helper_rfi(CPUPPCState *env)
2685{
2686 do_rfi(env, env->spr[SPR_SRR0], env->spr[SPR_SRR1] & 0xfffffffful);
2687}
2688
2689#if defined(TARGET_PPC64)
2690void helper_rfid(CPUPPCState *env)
2691{
2692
2693
2694
2695
2696
2697
2698 do_rfi(env, env->spr[SPR_SRR0], env->spr[SPR_SRR1]);
2699}
2700
2701void helper_rfscv(CPUPPCState *env)
2702{
2703 do_rfi(env, env->lr, env->ctr);
2704}
2705
2706void helper_hrfid(CPUPPCState *env)
2707{
2708 do_rfi(env, env->spr[SPR_HSRR0], env->spr[SPR_HSRR1]);
2709}
2710#endif
2711
2712#if defined(TARGET_PPC64) && !defined(CONFIG_USER_ONLY)
2713void helper_rfebb(CPUPPCState *env, target_ulong s)
2714{
2715 target_ulong msr = env->msr;
2716
2717
2718
2719
2720
2721
2722
2723 if (env->spr[SPR_BESCR] & BESCR_INVALID) {
2724 raise_exception_err(env, POWERPC_EXCP_PROGRAM,
2725 POWERPC_EXCP_INVAL | POWERPC_EXCP_INVAL_INVAL);
2726 }
2727
2728 env->nip = env->spr[SPR_EBBRR];
2729
2730
2731 if (!msr_is_64bit(env, msr)) {
2732 env->nip = (uint32_t)env->spr[SPR_EBBRR];
2733 }
2734
2735 if (s) {
2736 env->spr[SPR_BESCR] |= BESCR_GE;
2737 } else {
2738 env->spr[SPR_BESCR] &= ~BESCR_GE;
2739 }
2740}
2741
2742
2743
2744
2745
2746
2747
2748
2749
2750
2751static void do_ebb(CPUPPCState *env, int ebb_excp)
2752{
2753 PowerPCCPU *cpu = env_archcpu(env);
2754
2755
2756
2757
2758
2759 helper_fscr_facility_check(env, FSCR_EBB, 0, FSCR_IC_EBB);
2760 helper_hfscr_facility_check(env, FSCR_EBB, "EBB", FSCR_IC_EBB);
2761
2762 if (ebb_excp == POWERPC_EXCP_PERFM_EBB) {
2763 env->spr[SPR_BESCR] |= BESCR_PMEO;
2764 } else if (ebb_excp == POWERPC_EXCP_EXTERNAL_EBB) {
2765 env->spr[SPR_BESCR] |= BESCR_EEO;
2766 }
2767
2768 if (FIELD_EX64(env->msr, MSR, PR)) {
2769 powerpc_excp(cpu, ebb_excp);
2770 } else {
2771 ppc_set_irq(cpu, PPC_INTERRUPT_EBB, 1);
2772 }
2773}
2774
2775void raise_ebb_perfm_exception(CPUPPCState *env)
2776{
2777 bool perfm_ebb_enabled = env->spr[SPR_POWER_MMCR0] & MMCR0_EBE &&
2778 env->spr[SPR_BESCR] & BESCR_PME &&
2779 env->spr[SPR_BESCR] & BESCR_GE;
2780
2781 if (!perfm_ebb_enabled) {
2782 return;
2783 }
2784
2785 do_ebb(env, POWERPC_EXCP_PERFM_EBB);
2786}
2787#endif
2788
2789
2790
2791void helper_40x_rfci(CPUPPCState *env)
2792{
2793 do_rfi(env, env->spr[SPR_40x_SRR2], env->spr[SPR_40x_SRR3]);
2794}
2795
2796void helper_rfci(CPUPPCState *env)
2797{
2798 do_rfi(env, env->spr[SPR_BOOKE_CSRR0], env->spr[SPR_BOOKE_CSRR1]);
2799}
2800
2801void helper_rfdi(CPUPPCState *env)
2802{
2803
2804 do_rfi(env, env->spr[SPR_BOOKE_DSRR0], env->spr[SPR_BOOKE_DSRR1]);
2805}
2806
2807void helper_rfmci(CPUPPCState *env)
2808{
2809
2810 do_rfi(env, env->spr[SPR_BOOKE_MCSRR0], env->spr[SPR_BOOKE_MCSRR1]);
2811}
2812#endif
2813#endif
2814
2815#ifdef CONFIG_TCG
2816void helper_tw(CPUPPCState *env, target_ulong arg1, target_ulong arg2,
2817 uint32_t flags)
2818{
2819 if (!likely(!(((int32_t)arg1 < (int32_t)arg2 && (flags & 0x10)) ||
2820 ((int32_t)arg1 > (int32_t)arg2 && (flags & 0x08)) ||
2821 ((int32_t)arg1 == (int32_t)arg2 && (flags & 0x04)) ||
2822 ((uint32_t)arg1 < (uint32_t)arg2 && (flags & 0x02)) ||
2823 ((uint32_t)arg1 > (uint32_t)arg2 && (flags & 0x01))))) {
2824 raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
2825 POWERPC_EXCP_TRAP, GETPC());
2826 }
2827}
2828
2829#if defined(TARGET_PPC64)
2830void helper_td(CPUPPCState *env, target_ulong arg1, target_ulong arg2,
2831 uint32_t flags)
2832{
2833 if (!likely(!(((int64_t)arg1 < (int64_t)arg2 && (flags & 0x10)) ||
2834 ((int64_t)arg1 > (int64_t)arg2 && (flags & 0x08)) ||
2835 ((int64_t)arg1 == (int64_t)arg2 && (flags & 0x04)) ||
2836 ((uint64_t)arg1 < (uint64_t)arg2 && (flags & 0x02)) ||
2837 ((uint64_t)arg1 > (uint64_t)arg2 && (flags & 0x01))))) {
2838 raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
2839 POWERPC_EXCP_TRAP, GETPC());
2840 }
2841}
2842#endif
2843#endif
2844
2845#ifdef CONFIG_TCG
2846static uint32_t helper_SIMON_LIKE_32_64(uint32_t x, uint64_t key, uint32_t lane)
2847{
2848 const uint16_t c = 0xfffc;
2849 const uint64_t z0 = 0xfa2561cdf44ac398ULL;
2850 uint16_t z = 0, temp;
2851 uint16_t k[32], eff_k[32], xleft[33], xright[33], fxleft[32];
2852
2853 for (int i = 3; i >= 0; i--) {
2854 k[i] = key & 0xffff;
2855 key >>= 16;
2856 }
2857 xleft[0] = x & 0xffff;
2858 xright[0] = (x >> 16) & 0xffff;
2859
2860 for (int i = 0; i < 28; i++) {
2861 z = (z0 >> (63 - i)) & 1;
2862 temp = ror16(k[i + 3], 3) ^ k[i + 1];
2863 k[i + 4] = c ^ z ^ k[i] ^ temp ^ ror16(temp, 1);
2864 }
2865
2866 for (int i = 0; i < 8; i++) {
2867 eff_k[4 * i + 0] = k[4 * i + ((0 + lane) % 4)];
2868 eff_k[4 * i + 1] = k[4 * i + ((1 + lane) % 4)];
2869 eff_k[4 * i + 2] = k[4 * i + ((2 + lane) % 4)];
2870 eff_k[4 * i + 3] = k[4 * i + ((3 + lane) % 4)];
2871 }
2872
2873 for (int i = 0; i < 32; i++) {
2874 fxleft[i] = (rol16(xleft[i], 1) &
2875 rol16(xleft[i], 8)) ^ rol16(xleft[i], 2);
2876 xleft[i + 1] = xright[i] ^ fxleft[i] ^ eff_k[i];
2877 xright[i + 1] = xleft[i];
2878 }
2879
2880 return (((uint32_t)xright[32]) << 16) | xleft[32];
2881}
2882
2883static uint64_t hash_digest(uint64_t ra, uint64_t rb, uint64_t key)
2884{
2885 uint64_t stage0_h = 0ULL, stage0_l = 0ULL;
2886 uint64_t stage1_h, stage1_l;
2887
2888 for (int i = 0; i < 4; i++) {
2889 stage0_h |= ror64(rb & 0xff, 8 * (2 * i + 1));
2890 stage0_h |= ((ra >> 32) & 0xff) << (8 * 2 * i);
2891 stage0_l |= ror64((rb >> 32) & 0xff, 8 * (2 * i + 1));
2892 stage0_l |= (ra & 0xff) << (8 * 2 * i);
2893 rb >>= 8;
2894 ra >>= 8;
2895 }
2896
2897 stage1_h = (uint64_t)helper_SIMON_LIKE_32_64(stage0_h >> 32, key, 0) << 32;
2898 stage1_h |= helper_SIMON_LIKE_32_64(stage0_h, key, 1);
2899 stage1_l = (uint64_t)helper_SIMON_LIKE_32_64(stage0_l >> 32, key, 2) << 32;
2900 stage1_l |= helper_SIMON_LIKE_32_64(stage0_l, key, 3);
2901
2902 return stage1_h ^ stage1_l;
2903}
2904
2905static void do_hash(CPUPPCState *env, target_ulong ea, target_ulong ra,
2906 target_ulong rb, uint64_t key, bool store)
2907{
2908 uint64_t calculated_hash = hash_digest(ra, rb, key), loaded_hash;
2909
2910 if (store) {
2911 cpu_stq_data_ra(env, ea, calculated_hash, GETPC());
2912 } else {
2913 loaded_hash = cpu_ldq_data_ra(env, ea, GETPC());
2914 if (loaded_hash != calculated_hash) {
2915 raise_exception_err_ra(env, POWERPC_EXCP_PROGRAM,
2916 POWERPC_EXCP_TRAP, GETPC());
2917 }
2918 }
2919}
2920
2921#include "qemu/guest-random.h"
2922
2923#ifdef TARGET_PPC64
2924#define HELPER_HASH(op, key, store, dexcr_aspect) \
2925void helper_##op(CPUPPCState *env, target_ulong ea, target_ulong ra, \
2926 target_ulong rb) \
2927{ \
2928 if (env->msr & R_MSR_PR_MASK) { \
2929 if (!(env->spr[SPR_DEXCR] & R_DEXCR_PRO_##dexcr_aspect##_MASK || \
2930 env->spr[SPR_HDEXCR] & R_HDEXCR_ENF_##dexcr_aspect##_MASK)) \
2931 return; \
2932 } else if (!(env->msr & R_MSR_HV_MASK)) { \
2933 if (!(env->spr[SPR_DEXCR] & R_DEXCR_PNH_##dexcr_aspect##_MASK || \
2934 env->spr[SPR_HDEXCR] & R_HDEXCR_ENF_##dexcr_aspect##_MASK)) \
2935 return; \
2936 } else if (!(env->msr & R_MSR_S_MASK)) { \
2937 if (!(env->spr[SPR_HDEXCR] & R_HDEXCR_HNU_##dexcr_aspect##_MASK)) \
2938 return; \
2939 } \
2940 \
2941 do_hash(env, ea, ra, rb, key, store); \
2942}
2943#else
2944#define HELPER_HASH(op, key, store, dexcr_aspect) \
2945void helper_##op(CPUPPCState *env, target_ulong ea, target_ulong ra, \
2946 target_ulong rb) \
2947{ \
2948 do_hash(env, ea, ra, rb, key, store); \
2949}
2950#endif
2951
2952HELPER_HASH(HASHST, env->spr[SPR_HASHKEYR], true, NPHIE)
2953HELPER_HASH(HASHCHK, env->spr[SPR_HASHKEYR], false, NPHIE)
2954HELPER_HASH(HASHSTP, env->spr[SPR_HASHPKEYR], true, PHIE)
2955HELPER_HASH(HASHCHKP, env->spr[SPR_HASHPKEYR], false, PHIE)
2956#endif
2957
2958#if !defined(CONFIG_USER_ONLY)
2959
2960#ifdef CONFIG_TCG
2961
2962
2963static int dbell2irq(target_ulong rb)
2964{
2965 int msg = rb & DBELL_TYPE_MASK;
2966 int irq = -1;
2967
2968 switch (msg) {
2969 case DBELL_TYPE_DBELL:
2970 irq = PPC_INTERRUPT_DOORBELL;
2971 break;
2972 case DBELL_TYPE_DBELL_CRIT:
2973 irq = PPC_INTERRUPT_CDOORBELL;
2974 break;
2975 case DBELL_TYPE_G_DBELL:
2976 case DBELL_TYPE_G_DBELL_CRIT:
2977 case DBELL_TYPE_G_DBELL_MC:
2978
2979 default:
2980 break;
2981 }
2982
2983 return irq;
2984}
2985
2986void helper_msgclr(CPUPPCState *env, target_ulong rb)
2987{
2988 int irq = dbell2irq(rb);
2989
2990 if (irq < 0) {
2991 return;
2992 }
2993
2994 ppc_set_irq(env_archcpu(env), irq, 0);
2995}
2996
2997void helper_msgsnd(target_ulong rb)
2998{
2999 int irq = dbell2irq(rb);
3000 int pir = rb & DBELL_PIRTAG_MASK;
3001 CPUState *cs;
3002
3003 if (irq < 0) {
3004 return;
3005 }
3006
3007 qemu_mutex_lock_iothread();
3008 CPU_FOREACH(cs) {
3009 PowerPCCPU *cpu = POWERPC_CPU(cs);
3010 CPUPPCState *cenv = &cpu->env;
3011
3012 if ((rb & DBELL_BRDCAST) || (cenv->spr[SPR_BOOKE_PIR] == pir)) {
3013 ppc_set_irq(cpu, irq, 1);
3014 }
3015 }
3016 qemu_mutex_unlock_iothread();
3017}
3018
3019
3020
3021static bool dbell_type_server(target_ulong rb)
3022{
3023
3024
3025
3026
3027
3028 return (rb & DBELL_TYPE_MASK) == DBELL_TYPE_DBELL_SERVER;
3029}
3030
3031void helper_book3s_msgclr(CPUPPCState *env, target_ulong rb)
3032{
3033 if (!dbell_type_server(rb)) {
3034 return;
3035 }
3036
3037 ppc_set_irq(env_archcpu(env), PPC_INTERRUPT_HDOORBELL, 0);
3038}
3039
3040static void book3s_msgsnd_common(int pir, int irq)
3041{
3042 CPUState *cs;
3043
3044 qemu_mutex_lock_iothread();
3045 CPU_FOREACH(cs) {
3046 PowerPCCPU *cpu = POWERPC_CPU(cs);
3047 CPUPPCState *cenv = &cpu->env;
3048
3049
3050 if (cenv->spr_cb[SPR_PIR].default_value == pir) {
3051 ppc_set_irq(cpu, irq, 1);
3052 }
3053 }
3054 qemu_mutex_unlock_iothread();
3055}
3056
3057void helper_book3s_msgsnd(target_ulong rb)
3058{
3059 int pir = rb & DBELL_PROCIDTAG_MASK;
3060
3061 if (!dbell_type_server(rb)) {
3062 return;
3063 }
3064
3065 book3s_msgsnd_common(pir, PPC_INTERRUPT_HDOORBELL);
3066}
3067
3068#if defined(TARGET_PPC64)
3069void helper_book3s_msgclrp(CPUPPCState *env, target_ulong rb)
3070{
3071 helper_hfscr_facility_check(env, HFSCR_MSGP, "msgclrp", HFSCR_IC_MSGP);
3072
3073 if (!dbell_type_server(rb)) {
3074 return;
3075 }
3076
3077 ppc_set_irq(env_archcpu(env), PPC_INTERRUPT_HDOORBELL, 0);
3078}
3079
3080
3081
3082
3083
3084void helper_book3s_msgsndp(CPUPPCState *env, target_ulong rb)
3085{
3086 int pir = env->spr_cb[SPR_PIR].default_value;
3087
3088 helper_hfscr_facility_check(env, HFSCR_MSGP, "msgsndp", HFSCR_IC_MSGP);
3089
3090 if (!dbell_type_server(rb)) {
3091 return;
3092 }
3093
3094
3095
3096 book3s_msgsnd_common(pir, PPC_INTERRUPT_DOORBELL);
3097}
3098#endif
3099
3100void ppc_cpu_do_unaligned_access(CPUState *cs, vaddr vaddr,
3101 MMUAccessType access_type,
3102 int mmu_idx, uintptr_t retaddr)
3103{
3104 CPUPPCState *env = cs->env_ptr;
3105 uint32_t insn;
3106
3107
3108 cpu_restore_state(cs, retaddr);
3109 insn = cpu_ldl_code(env, env->nip);
3110
3111 switch (env->mmu_model) {
3112 case POWERPC_MMU_SOFT_4xx:
3113 env->spr[SPR_40x_DEAR] = vaddr;
3114 break;
3115 case POWERPC_MMU_BOOKE:
3116 case POWERPC_MMU_BOOKE206:
3117 env->spr[SPR_BOOKE_DEAR] = vaddr;
3118 break;
3119 default:
3120 env->spr[SPR_DAR] = vaddr;
3121 break;
3122 }
3123
3124 cs->exception_index = POWERPC_EXCP_ALIGN;
3125 env->error_code = insn & 0x03FF0000;
3126 cpu_loop_exit(cs);
3127}
3128#endif
3129#endif
3130