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