1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19#include "cpu.h"
20#include "helper.h"
21
22#include "helper_regs.h"
23
24
25
26
27#ifdef DEBUG_EXCEPTIONS
28# define LOG_EXCP(...) qemu_log(__VA_ARGS__)
29#else
30# define LOG_EXCP(...) do { } while (0)
31#endif
32
33
34
35
36void (*cpu_ppc_hypercall)(PowerPCCPU *);
37
38
39
40#if defined(CONFIG_USER_ONLY)
41void ppc_cpu_do_interrupt(CPUState *cs)
42{
43 PowerPCCPU *cpu = POWERPC_CPU(cs);
44 CPUPPCState *env = &cpu->env;
45
46 env->exception_index = POWERPC_EXCP_NONE;
47 env->error_code = 0;
48}
49
50void ppc_hw_interrupt(CPUPPCState *env)
51{
52 env->exception_index = POWERPC_EXCP_NONE;
53 env->error_code = 0;
54}
55#else
56static inline void dump_syscall(CPUPPCState *env)
57{
58 qemu_log_mask(CPU_LOG_INT, "syscall r0=%016" PRIx64 " r3=%016" PRIx64
59 " r4=%016" PRIx64 " r5=%016" PRIx64 " r6=%016" PRIx64
60 " nip=" TARGET_FMT_lx "\n",
61 ppc_dump_gpr(env, 0), ppc_dump_gpr(env, 3),
62 ppc_dump_gpr(env, 4), ppc_dump_gpr(env, 5),
63 ppc_dump_gpr(env, 6), env->nip);
64}
65
66
67
68
69static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
70{
71 CPUPPCState *env = &cpu->env;
72 CPUState *cs;
73 target_ulong msr, new_msr, vector;
74 int srr0, srr1, asrr0, asrr1;
75 int lpes0, lpes1, lev;
76
77 if (0) {
78
79 lpes0 = (env->spr[SPR_LPCR] >> 1) & 1;
80 lpes1 = (env->spr[SPR_LPCR] >> 2) & 1;
81 } else {
82
83 lpes0 = 0;
84 lpes1 = 1;
85 }
86
87 qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx
88 " => %08x (%02x)\n", env->nip, excp, env->error_code);
89
90
91 if (excp_model == POWERPC_EXCP_BOOKE) {
92 msr = env->msr;
93 } else {
94 msr = env->msr & ~0x783f0000ULL;
95 }
96
97
98 new_msr = env->msr & ((target_ulong)1 << MSR_ME);
99
100
101 srr0 = SPR_SRR0;
102 srr1 = SPR_SRR1;
103 asrr0 = -1;
104 asrr1 = -1;
105
106 switch (excp) {
107 case POWERPC_EXCP_NONE:
108
109 return;
110 case POWERPC_EXCP_CRITICAL:
111 switch (excp_model) {
112 case POWERPC_EXCP_40x:
113 srr0 = SPR_40x_SRR2;
114 srr1 = SPR_40x_SRR3;
115 break;
116 case POWERPC_EXCP_BOOKE:
117 srr0 = SPR_BOOKE_CSRR0;
118 srr1 = SPR_BOOKE_CSRR1;
119 break;
120 case POWERPC_EXCP_G2:
121 break;
122 default:
123 goto excp_invalid;
124 }
125 goto store_next;
126 case POWERPC_EXCP_MCHECK:
127 if (msr_me == 0) {
128
129
130
131 if (qemu_log_enabled()) {
132 qemu_log("Machine check while not allowed. "
133 "Entering checkstop state\n");
134 } else {
135 fprintf(stderr, "Machine check while not allowed. "
136 "Entering checkstop state\n");
137 }
138 cs = CPU(cpu);
139 cs->halted = 1;
140 cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
141 }
142 if (0) {
143
144 new_msr |= (target_ulong)MSR_HVB;
145 }
146
147
148 new_msr &= ~((target_ulong)1 << MSR_ME);
149
150
151 switch (excp_model) {
152 case POWERPC_EXCP_40x:
153 srr0 = SPR_40x_SRR2;
154 srr1 = SPR_40x_SRR3;
155 break;
156 case POWERPC_EXCP_BOOKE:
157
158 srr0 = SPR_BOOKE_MCSRR0;
159 srr1 = SPR_BOOKE_MCSRR1;
160 asrr0 = SPR_BOOKE_CSRR0;
161 asrr1 = SPR_BOOKE_CSRR1;
162 break;
163 default:
164 break;
165 }
166 goto store_next;
167 case POWERPC_EXCP_DSI:
168 LOG_EXCP("DSI exception: DSISR=" TARGET_FMT_lx" DAR=" TARGET_FMT_lx
169 "\n", env->spr[SPR_DSISR], env->spr[SPR_DAR]);
170 if (lpes1 == 0) {
171 new_msr |= (target_ulong)MSR_HVB;
172 }
173 goto store_next;
174 case POWERPC_EXCP_ISI:
175 LOG_EXCP("ISI exception: msr=" TARGET_FMT_lx ", nip=" TARGET_FMT_lx
176 "\n", msr, env->nip);
177 if (lpes1 == 0) {
178 new_msr |= (target_ulong)MSR_HVB;
179 }
180 msr |= env->error_code;
181 goto store_next;
182 case POWERPC_EXCP_EXTERNAL:
183 if (lpes0 == 1) {
184 new_msr |= (target_ulong)MSR_HVB;
185 }
186 if (env->mpic_proxy) {
187
188 env->spr[SPR_BOOKE_EPR] = ldl_phys(env->mpic_iack);
189 }
190 goto store_next;
191 case POWERPC_EXCP_ALIGN:
192 if (lpes1 == 0) {
193 new_msr |= (target_ulong)MSR_HVB;
194 }
195
196
197 env->spr[SPR_DSISR] |= (cpu_ldl_code(env, (env->nip - 4))
198 & 0x03FF0000) >> 16;
199 goto store_current;
200 case POWERPC_EXCP_PROGRAM:
201 switch (env->error_code & ~0xF) {
202 case POWERPC_EXCP_FP:
203 if ((msr_fe0 == 0 && msr_fe1 == 0) || msr_fp == 0) {
204 LOG_EXCP("Ignore floating point exception\n");
205 env->exception_index = POWERPC_EXCP_NONE;
206 env->error_code = 0;
207 return;
208 }
209 if (lpes1 == 0) {
210 new_msr |= (target_ulong)MSR_HVB;
211 }
212 msr |= 0x00100000;
213 if (msr_fe0 == msr_fe1) {
214 goto store_next;
215 }
216 msr |= 0x00010000;
217 break;
218 case POWERPC_EXCP_INVAL:
219 LOG_EXCP("Invalid instruction at " TARGET_FMT_lx "\n", env->nip);
220 if (lpes1 == 0) {
221 new_msr |= (target_ulong)MSR_HVB;
222 }
223 msr |= 0x00080000;
224 env->spr[SPR_BOOKE_ESR] = ESR_PIL;
225 break;
226 case POWERPC_EXCP_PRIV:
227 if (lpes1 == 0) {
228 new_msr |= (target_ulong)MSR_HVB;
229 }
230 msr |= 0x00040000;
231 env->spr[SPR_BOOKE_ESR] = ESR_PPR;
232 break;
233 case POWERPC_EXCP_TRAP:
234 if (lpes1 == 0) {
235 new_msr |= (target_ulong)MSR_HVB;
236 }
237 msr |= 0x00020000;
238 env->spr[SPR_BOOKE_ESR] = ESR_PTR;
239 break;
240 default:
241
242 cpu_abort(env, "Invalid program exception %d. Aborting\n",
243 env->error_code);
244 break;
245 }
246 goto store_current;
247 case POWERPC_EXCP_FPU:
248 if (lpes1 == 0) {
249 new_msr |= (target_ulong)MSR_HVB;
250 }
251 goto store_current;
252 case POWERPC_EXCP_SYSCALL:
253 dump_syscall(env);
254 lev = env->error_code;
255 if ((lev == 1) && cpu_ppc_hypercall) {
256 cpu_ppc_hypercall(cpu);
257 return;
258 }
259 if (lev == 1 || (lpes0 == 0 && lpes1 == 0)) {
260 new_msr |= (target_ulong)MSR_HVB;
261 }
262 goto store_next;
263 case POWERPC_EXCP_APU:
264 goto store_current;
265 case POWERPC_EXCP_DECR:
266 if (lpes1 == 0) {
267 new_msr |= (target_ulong)MSR_HVB;
268 }
269 goto store_next;
270 case POWERPC_EXCP_FIT:
271
272 LOG_EXCP("FIT exception\n");
273 goto store_next;
274 case POWERPC_EXCP_WDT:
275 LOG_EXCP("WDT exception\n");
276 switch (excp_model) {
277 case POWERPC_EXCP_BOOKE:
278 srr0 = SPR_BOOKE_CSRR0;
279 srr1 = SPR_BOOKE_CSRR1;
280 break;
281 default:
282 break;
283 }
284 goto store_next;
285 case POWERPC_EXCP_DTLB:
286 goto store_next;
287 case POWERPC_EXCP_ITLB:
288 goto store_next;
289 case POWERPC_EXCP_DEBUG:
290 switch (excp_model) {
291 case POWERPC_EXCP_BOOKE:
292
293 srr0 = SPR_BOOKE_DSRR0;
294 srr1 = SPR_BOOKE_DSRR1;
295 asrr0 = SPR_BOOKE_CSRR0;
296 asrr1 = SPR_BOOKE_CSRR1;
297 break;
298 default:
299 break;
300 }
301
302 cpu_abort(env, "Debug exception is not implemented yet !\n");
303 goto store_next;
304 case POWERPC_EXCP_SPEU:
305 env->spr[SPR_BOOKE_ESR] = ESR_SPV;
306 goto store_current;
307 case POWERPC_EXCP_EFPDI:
308
309 cpu_abort(env, "Embedded floating point data exception "
310 "is not implemented yet !\n");
311 env->spr[SPR_BOOKE_ESR] = ESR_SPV;
312 goto store_next;
313 case POWERPC_EXCP_EFPRI:
314
315 cpu_abort(env, "Embedded floating point round exception "
316 "is not implemented yet !\n");
317 env->spr[SPR_BOOKE_ESR] = ESR_SPV;
318 goto store_next;
319 case POWERPC_EXCP_EPERFM:
320
321 cpu_abort(env,
322 "Performance counter exception is not implemented yet !\n");
323 goto store_next;
324 case POWERPC_EXCP_DOORI:
325 goto store_next;
326 case POWERPC_EXCP_DOORCI:
327 srr0 = SPR_BOOKE_CSRR0;
328 srr1 = SPR_BOOKE_CSRR1;
329 goto store_next;
330 case POWERPC_EXCP_RESET:
331 if (msr_pow) {
332
333 msr |= 0x10000;
334 } else {
335 new_msr &= ~((target_ulong)1 << MSR_ME);
336 }
337
338 if (0) {
339
340 new_msr |= (target_ulong)MSR_HVB;
341 }
342 goto store_next;
343 case POWERPC_EXCP_DSEG:
344 if (lpes1 == 0) {
345 new_msr |= (target_ulong)MSR_HVB;
346 }
347 goto store_next;
348 case POWERPC_EXCP_ISEG:
349 if (lpes1 == 0) {
350 new_msr |= (target_ulong)MSR_HVB;
351 }
352 goto store_next;
353 case POWERPC_EXCP_HDECR:
354 srr0 = SPR_HSRR0;
355 srr1 = SPR_HSRR1;
356 new_msr |= (target_ulong)MSR_HVB;
357 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
358 goto store_next;
359 case POWERPC_EXCP_TRACE:
360 if (lpes1 == 0) {
361 new_msr |= (target_ulong)MSR_HVB;
362 }
363 goto store_next;
364 case POWERPC_EXCP_HDSI:
365 srr0 = SPR_HSRR0;
366 srr1 = SPR_HSRR1;
367 new_msr |= (target_ulong)MSR_HVB;
368 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
369 goto store_next;
370 case POWERPC_EXCP_HISI:
371 srr0 = SPR_HSRR0;
372 srr1 = SPR_HSRR1;
373 new_msr |= (target_ulong)MSR_HVB;
374 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
375 goto store_next;
376 case POWERPC_EXCP_HDSEG:
377 srr0 = SPR_HSRR0;
378 srr1 = SPR_HSRR1;
379 new_msr |= (target_ulong)MSR_HVB;
380 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
381 goto store_next;
382 case POWERPC_EXCP_HISEG:
383 srr0 = SPR_HSRR0;
384 srr1 = SPR_HSRR1;
385 new_msr |= (target_ulong)MSR_HVB;
386 new_msr |= env->msr & ((target_ulong)1 << MSR_RI);
387 goto store_next;
388 case POWERPC_EXCP_VPU:
389 if (lpes1 == 0) {
390 new_msr |= (target_ulong)MSR_HVB;
391 }
392 goto store_current;
393 case POWERPC_EXCP_PIT:
394 LOG_EXCP("PIT exception\n");
395 goto store_next;
396 case POWERPC_EXCP_IO:
397
398 cpu_abort(env, "601 IO error exception is not implemented yet !\n");
399 goto store_next;
400 case POWERPC_EXCP_RUNM:
401
402 cpu_abort(env, "601 run mode exception is not implemented yet !\n");
403 goto store_next;
404 case POWERPC_EXCP_EMUL:
405
406 cpu_abort(env, "602 emulation trap exception "
407 "is not implemented yet !\n");
408 goto store_next;
409 case POWERPC_EXCP_IFTLB:
410 if (lpes1 == 0) {
411 new_msr |= (target_ulong)MSR_HVB;
412 }
413 switch (excp_model) {
414 case POWERPC_EXCP_602:
415 case POWERPC_EXCP_603:
416 case POWERPC_EXCP_603E:
417 case POWERPC_EXCP_G2:
418 goto tlb_miss_tgpr;
419 case POWERPC_EXCP_7x5:
420 goto tlb_miss;
421 case POWERPC_EXCP_74xx:
422 goto tlb_miss_74xx;
423 default:
424 cpu_abort(env, "Invalid instruction TLB miss exception\n");
425 break;
426 }
427 break;
428 case POWERPC_EXCP_DLTLB:
429 if (lpes1 == 0) {
430 new_msr |= (target_ulong)MSR_HVB;
431 }
432 switch (excp_model) {
433 case POWERPC_EXCP_602:
434 case POWERPC_EXCP_603:
435 case POWERPC_EXCP_603E:
436 case POWERPC_EXCP_G2:
437 goto tlb_miss_tgpr;
438 case POWERPC_EXCP_7x5:
439 goto tlb_miss;
440 case POWERPC_EXCP_74xx:
441 goto tlb_miss_74xx;
442 default:
443 cpu_abort(env, "Invalid data load TLB miss exception\n");
444 break;
445 }
446 break;
447 case POWERPC_EXCP_DSTLB:
448 if (lpes1 == 0) {
449 new_msr |= (target_ulong)MSR_HVB;
450 }
451 switch (excp_model) {
452 case POWERPC_EXCP_602:
453 case POWERPC_EXCP_603:
454 case POWERPC_EXCP_603E:
455 case POWERPC_EXCP_G2:
456 tlb_miss_tgpr:
457
458 if (!(new_msr & ((target_ulong)1 << MSR_TGPR))) {
459 new_msr |= (target_ulong)1 << MSR_TGPR;
460 hreg_swap_gpr_tgpr(env);
461 }
462 goto tlb_miss;
463 case POWERPC_EXCP_7x5:
464 tlb_miss:
465#if defined(DEBUG_SOFTWARE_TLB)
466 if (qemu_log_enabled()) {
467 const char *es;
468 target_ulong *miss, *cmp;
469 int en;
470
471 if (excp == POWERPC_EXCP_IFTLB) {
472 es = "I";
473 en = 'I';
474 miss = &env->spr[SPR_IMISS];
475 cmp = &env->spr[SPR_ICMP];
476 } else {
477 if (excp == POWERPC_EXCP_DLTLB) {
478 es = "DL";
479 } else {
480 es = "DS";
481 }
482 en = 'D';
483 miss = &env->spr[SPR_DMISS];
484 cmp = &env->spr[SPR_DCMP];
485 }
486 qemu_log("6xx %sTLB miss: %cM " TARGET_FMT_lx " %cC "
487 TARGET_FMT_lx " H1 " TARGET_FMT_lx " H2 "
488 TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp,
489 env->spr[SPR_HASH1], env->spr[SPR_HASH2],
490 env->error_code);
491 }
492#endif
493 msr |= env->crf[0] << 28;
494 msr |= env->error_code;
495
496 msr |= ((env->last_way + 1) & (env->nb_ways - 1)) << 17;
497 break;
498 case POWERPC_EXCP_74xx:
499 tlb_miss_74xx:
500#if defined(DEBUG_SOFTWARE_TLB)
501 if (qemu_log_enabled()) {
502 const char *es;
503 target_ulong *miss, *cmp;
504 int en;
505
506 if (excp == POWERPC_EXCP_IFTLB) {
507 es = "I";
508 en = 'I';
509 miss = &env->spr[SPR_TLBMISS];
510 cmp = &env->spr[SPR_PTEHI];
511 } else {
512 if (excp == POWERPC_EXCP_DLTLB) {
513 es = "DL";
514 } else {
515 es = "DS";
516 }
517 en = 'D';
518 miss = &env->spr[SPR_TLBMISS];
519 cmp = &env->spr[SPR_PTEHI];
520 }
521 qemu_log("74xx %sTLB miss: %cM " TARGET_FMT_lx " %cC "
522 TARGET_FMT_lx " %08x\n", es, en, *miss, en, *cmp,
523 env->error_code);
524 }
525#endif
526 msr |= env->error_code;
527 break;
528 default:
529 cpu_abort(env, "Invalid data store TLB miss exception\n");
530 break;
531 }
532 goto store_next;
533 case POWERPC_EXCP_FPA:
534
535 cpu_abort(env, "Floating point assist exception "
536 "is not implemented yet !\n");
537 goto store_next;
538 case POWERPC_EXCP_DABR:
539
540 cpu_abort(env, "DABR exception is not implemented yet !\n");
541 goto store_next;
542 case POWERPC_EXCP_IABR:
543
544 cpu_abort(env, "IABR exception is not implemented yet !\n");
545 goto store_next;
546 case POWERPC_EXCP_SMI:
547
548 cpu_abort(env, "SMI exception is not implemented yet !\n");
549 goto store_next;
550 case POWERPC_EXCP_THERM:
551
552 cpu_abort(env, "Thermal management exception "
553 "is not implemented yet !\n");
554 goto store_next;
555 case POWERPC_EXCP_PERFM:
556 if (lpes1 == 0) {
557 new_msr |= (target_ulong)MSR_HVB;
558 }
559
560 cpu_abort(env,
561 "Performance counter exception is not implemented yet !\n");
562 goto store_next;
563 case POWERPC_EXCP_VPUA:
564
565 cpu_abort(env, "VPU assist exception is not implemented yet !\n");
566 goto store_next;
567 case POWERPC_EXCP_SOFTP:
568
569 cpu_abort(env,
570 "970 soft-patch exception is not implemented yet !\n");
571 goto store_next;
572 case POWERPC_EXCP_MAINT:
573
574 cpu_abort(env,
575 "970 maintenance exception is not implemented yet !\n");
576 goto store_next;
577 case POWERPC_EXCP_MEXTBR:
578
579 cpu_abort(env, "Maskable external exception "
580 "is not implemented yet !\n");
581 goto store_next;
582 case POWERPC_EXCP_NMEXTBR:
583
584 cpu_abort(env, "Non maskable external exception "
585 "is not implemented yet !\n");
586 goto store_next;
587 default:
588 excp_invalid:
589 cpu_abort(env, "Invalid PowerPC exception %d. Aborting\n", excp);
590 break;
591 store_current:
592
593 env->spr[srr0] = env->nip - 4;
594 break;
595 store_next:
596
597 env->spr[srr0] = env->nip;
598 break;
599 }
600
601 env->spr[srr1] = msr;
602
603 if (asrr0 != -1) {
604 env->spr[asrr0] = env->spr[srr0];
605 }
606 if (asrr1 != -1) {
607 env->spr[asrr1] = env->spr[srr1];
608 }
609
610 if (msr & ((1 << MSR_IR) | (1 << MSR_DR))) {
611 tlb_flush(env, 1);
612 }
613
614 if (msr_ile) {
615 new_msr |= (target_ulong)1 << MSR_LE;
616 }
617
618
619 vector = env->excp_vectors[excp];
620 if (vector == (target_ulong)-1ULL) {
621 cpu_abort(env, "Raised an exception without defined vector %d\n",
622 excp);
623 }
624 vector |= env->excp_prefix;
625#if defined(TARGET_PPC64)
626 if (excp_model == POWERPC_EXCP_BOOKE) {
627 if (env->spr[SPR_BOOKE_EPCR] & EPCR_ICM) {
628
629 new_msr |= (target_ulong)1 << MSR_CM;
630 } else {
631 vector = (uint32_t)vector;
632 }
633 } else {
634 if (!msr_isf && !(env->mmu_model & POWERPC_MMU_64)) {
635 vector = (uint32_t)vector;
636 } else {
637 new_msr |= (target_ulong)1 << MSR_SF;
638 }
639 }
640#endif
641
642
643
644 env->msr = new_msr & env->msr_mask;
645 hreg_compute_hflags(env);
646 env->nip = vector;
647
648 env->exception_index = POWERPC_EXCP_NONE;
649 env->error_code = 0;
650
651 if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
652 (env->mmu_model == POWERPC_MMU_BOOKE206)) {
653
654
655
656 tlb_flush(env, 1);
657 }
658}
659
660void ppc_cpu_do_interrupt(CPUState *cs)
661{
662 PowerPCCPU *cpu = POWERPC_CPU(cs);
663 CPUPPCState *env = &cpu->env;
664
665 powerpc_excp(cpu, env->excp_model, env->exception_index);
666}
667
668void ppc_hw_interrupt(CPUPPCState *env)
669{
670 PowerPCCPU *cpu = ppc_env_get_cpu(env);
671 int hdice;
672#if 0
673 CPUState *cs = CPU(cpu);
674
675 qemu_log_mask(CPU_LOG_INT, "%s: %p pending %08x req %08x me %d ee %d\n",
676 __func__, env, env->pending_interrupts,
677 cs->interrupt_request, (int)msr_me, (int)msr_ee);
678#endif
679
680 if (env->pending_interrupts & (1 << PPC_INTERRUPT_RESET)) {
681 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_RESET);
682 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_RESET);
683 return;
684 }
685
686 if (env->pending_interrupts & (1 << PPC_INTERRUPT_MCK)) {
687 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_MCK);
688 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_MCHECK);
689 return;
690 }
691#if 0
692
693 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DEBUG)) {
694 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DEBUG);
695 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DEBUG);
696 return;
697 }
698#endif
699 if (0) {
700
701 hdice = env->spr[SPR_LPCR] & 1;
702 } else {
703 hdice = 0;
704 }
705 if ((msr_ee != 0 || msr_hv == 0 || msr_pr != 0) && hdice != 0) {
706
707 if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDECR)) {
708 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_HDECR);
709 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_HDECR);
710 return;
711 }
712 }
713 if (msr_ce != 0) {
714
715 if (env->pending_interrupts & (1 << PPC_INTERRUPT_CEXT)) {
716
717
718
719#if 0
720 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CEXT);
721#endif
722 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_CRITICAL);
723 return;
724 }
725 }
726 if (msr_ee != 0) {
727
728 if (env->pending_interrupts & (1 << PPC_INTERRUPT_WDT)) {
729 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_WDT);
730 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_WDT);
731 return;
732 }
733 if (env->pending_interrupts & (1 << PPC_INTERRUPT_CDOORBELL)) {
734 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_CDOORBELL);
735 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DOORCI);
736 return;
737 }
738
739 if (env->pending_interrupts & (1 << PPC_INTERRUPT_FIT)) {
740 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_FIT);
741 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_FIT);
742 return;
743 }
744
745 if (env->pending_interrupts & (1 << PPC_INTERRUPT_PIT)) {
746 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PIT);
747 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_PIT);
748 return;
749 }
750
751 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DECR)) {
752 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DECR);
753 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DECR);
754 return;
755 }
756
757 if (env->pending_interrupts & (1 << PPC_INTERRUPT_EXT)) {
758
759
760
761#if 0
762 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_EXT);
763#endif
764 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_EXTERNAL);
765 return;
766 }
767 if (env->pending_interrupts & (1 << PPC_INTERRUPT_DOORBELL)) {
768 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_DOORBELL);
769 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DOORI);
770 return;
771 }
772 if (env->pending_interrupts & (1 << PPC_INTERRUPT_PERFM)) {
773 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_PERFM);
774 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_PERFM);
775 return;
776 }
777
778 if (env->pending_interrupts & (1 << PPC_INTERRUPT_THERM)) {
779 env->pending_interrupts &= ~(1 << PPC_INTERRUPT_THERM);
780 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_THERM);
781 return;
782 }
783 }
784}
785#endif
786
787#if defined(DEBUG_OP)
788static void cpu_dump_rfi(target_ulong RA, target_ulong msr)
789{
790 qemu_log("Return from exception at " TARGET_FMT_lx " with flags "
791 TARGET_FMT_lx "\n", RA, msr);
792}
793#endif
794
795
796
797
798void helper_raise_exception_err(CPUPPCState *env, uint32_t exception,
799 uint32_t error_code)
800{
801#if 0
802 printf("Raise exception %3x code : %d\n", exception, error_code);
803#endif
804 env->exception_index = exception;
805 env->error_code = error_code;
806 cpu_loop_exit(env);
807}
808
809void helper_raise_exception(CPUPPCState *env, uint32_t exception)
810{
811 helper_raise_exception_err(env, exception, 0);
812}
813
814#if !defined(CONFIG_USER_ONLY)
815void helper_store_msr(CPUPPCState *env, target_ulong val)
816{
817 CPUState *cs;
818
819 val = hreg_store_msr(env, val, 0);
820 if (val != 0) {
821 cs = CPU(ppc_env_get_cpu(env));
822 cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
823 helper_raise_exception(env, val);
824 }
825}
826
827static inline void do_rfi(CPUPPCState *env, target_ulong nip, target_ulong msr,
828 target_ulong msrm, int keep_msrh)
829{
830 CPUState *cs = CPU(ppc_env_get_cpu(env));
831
832#if defined(TARGET_PPC64)
833 if (msr_is_64bit(env, msr)) {
834 nip = (uint64_t)nip;
835 msr &= (uint64_t)msrm;
836 } else {
837 nip = (uint32_t)nip;
838 msr = (uint32_t)(msr & msrm);
839 if (keep_msrh) {
840 msr |= env->msr & ~((uint64_t)0xFFFFFFFF);
841 }
842 }
843#else
844 nip = (uint32_t)nip;
845 msr &= (uint32_t)msrm;
846#endif
847
848 env->nip = nip & ~((target_ulong)0x00000003);
849 hreg_store_msr(env, msr, 1);
850#if defined(DEBUG_OP)
851 cpu_dump_rfi(env->nip, env->msr);
852#endif
853
854
855
856 cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
857}
858
859void helper_rfi(CPUPPCState *env)
860{
861 if (env->excp_model == POWERPC_EXCP_BOOKE) {
862 do_rfi(env, env->spr[SPR_SRR0], env->spr[SPR_SRR1],
863 ~((target_ulong)0), 0);
864 } else {
865 do_rfi(env, env->spr[SPR_SRR0], env->spr[SPR_SRR1],
866 ~((target_ulong)0x783F0000), 1);
867 }
868}
869
870#if defined(TARGET_PPC64)
871void helper_rfid(CPUPPCState *env)
872{
873 do_rfi(env, env->spr[SPR_SRR0], env->spr[SPR_SRR1],
874 ~((target_ulong)0x783F0000), 0);
875}
876
877void helper_hrfid(CPUPPCState *env)
878{
879 do_rfi(env, env->spr[SPR_HSRR0], env->spr[SPR_HSRR1],
880 ~((target_ulong)0x783F0000), 0);
881}
882#endif
883
884
885
886void helper_40x_rfci(CPUPPCState *env)
887{
888 do_rfi(env, env->spr[SPR_40x_SRR2], env->spr[SPR_40x_SRR3],
889 ~((target_ulong)0xFFFF0000), 0);
890}
891
892void helper_rfci(CPUPPCState *env)
893{
894 do_rfi(env, env->spr[SPR_BOOKE_CSRR0], env->spr[SPR_BOOKE_CSRR1],
895 ~((target_ulong)0), 0);
896}
897
898void helper_rfdi(CPUPPCState *env)
899{
900
901 do_rfi(env, env->spr[SPR_BOOKE_DSRR0], env->spr[SPR_BOOKE_DSRR1],
902 ~((target_ulong)0), 0);
903}
904
905void helper_rfmci(CPUPPCState *env)
906{
907
908 do_rfi(env, env->spr[SPR_BOOKE_MCSRR0], env->spr[SPR_BOOKE_MCSRR1],
909 ~((target_ulong)0), 0);
910}
911#endif
912
913void helper_tw(CPUPPCState *env, target_ulong arg1, target_ulong arg2,
914 uint32_t flags)
915{
916 if (!likely(!(((int32_t)arg1 < (int32_t)arg2 && (flags & 0x10)) ||
917 ((int32_t)arg1 > (int32_t)arg2 && (flags & 0x08)) ||
918 ((int32_t)arg1 == (int32_t)arg2 && (flags & 0x04)) ||
919 ((uint32_t)arg1 < (uint32_t)arg2 && (flags & 0x02)) ||
920 ((uint32_t)arg1 > (uint32_t)arg2 && (flags & 0x01))))) {
921 helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
922 POWERPC_EXCP_TRAP);
923 }
924}
925
926#if defined(TARGET_PPC64)
927void helper_td(CPUPPCState *env, target_ulong arg1, target_ulong arg2,
928 uint32_t flags)
929{
930 if (!likely(!(((int64_t)arg1 < (int64_t)arg2 && (flags & 0x10)) ||
931 ((int64_t)arg1 > (int64_t)arg2 && (flags & 0x08)) ||
932 ((int64_t)arg1 == (int64_t)arg2 && (flags & 0x04)) ||
933 ((uint64_t)arg1 < (uint64_t)arg2 && (flags & 0x02)) ||
934 ((uint64_t)arg1 > (uint64_t)arg2 && (flags & 0x01))))) {
935 helper_raise_exception_err(env, POWERPC_EXCP_PROGRAM,
936 POWERPC_EXCP_TRAP);
937 }
938}
939#endif
940
941#if !defined(CONFIG_USER_ONLY)
942
943
944
945void helper_rfsvc(CPUPPCState *env)
946{
947 do_rfi(env, env->lr, env->ctr, 0x0000FFFF, 0);
948}
949
950
951static int dbell2irq(target_ulong rb)
952{
953 int msg = rb & DBELL_TYPE_MASK;
954 int irq = -1;
955
956 switch (msg) {
957 case DBELL_TYPE_DBELL:
958 irq = PPC_INTERRUPT_DOORBELL;
959 break;
960 case DBELL_TYPE_DBELL_CRIT:
961 irq = PPC_INTERRUPT_CDOORBELL;
962 break;
963 case DBELL_TYPE_G_DBELL:
964 case DBELL_TYPE_G_DBELL_CRIT:
965 case DBELL_TYPE_G_DBELL_MC:
966
967 default:
968 break;
969 }
970
971 return irq;
972}
973
974void helper_msgclr(CPUPPCState *env, target_ulong rb)
975{
976 int irq = dbell2irq(rb);
977
978 if (irq < 0) {
979 return;
980 }
981
982 env->pending_interrupts &= ~(1 << irq);
983}
984
985void helper_msgsnd(target_ulong rb)
986{
987 int irq = dbell2irq(rb);
988 int pir = rb & DBELL_PIRTAG_MASK;
989 CPUState *cs;
990
991 if (irq < 0) {
992 return;
993 }
994
995 for (cs = first_cpu; cs != NULL; cs = cs->next_cpu) {
996 PowerPCCPU *cpu = POWERPC_CPU(cs);
997 CPUPPCState *cenv = &cpu->env;
998
999 if ((rb & DBELL_BRDCAST) || (cenv->spr[SPR_BOOKE_PIR] == pir)) {
1000 cenv->pending_interrupts |= 1 << irq;
1001 cpu_interrupt(cs, CPU_INTERRUPT_HARD);
1002 }
1003 }
1004}
1005#endif
1006