net: stellaris_enet: check packet length against receive buffer
[qemu/ar7.git] / target-ppc / excp_helper.c
blobca4ffe8ad660b9419853cb9286fac32a9f297705
1 /*
2 * PowerPC exception emulation helpers for QEMU.
4 * Copyright (c) 2003-2007 Jocelyn Mayer
6 * This library is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU Lesser General Public
8 * License as published by the Free Software Foundation; either
9 * version 2 of the License, or (at your option) any later version.
11 * This library is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU
14 * Lesser General Public License for more details.
16 * You should have received a copy of the GNU Lesser General Public
17 * License along with this library; if not, see <http://www.gnu.org/licenses/>.
19 #include "qemu/osdep.h"
20 #include "cpu.h"
21 #include "exec/helper-proto.h"
22 #include "exec/cpu_ldst.h"
24 #include "helper_regs.h"
26 //#define DEBUG_OP
27 //#define DEBUG_SOFTWARE_TLB
28 //#define DEBUG_EXCEPTIONS
30 #ifdef DEBUG_EXCEPTIONS
31 # define LOG_EXCP(...) qemu_log(__VA_ARGS__)
32 #else
33 # define LOG_EXCP(...) do { } while (0)
34 #endif
36 /*****************************************************************************/
37 /* PowerPC Hypercall emulation */
39 void (*cpu_ppc_hypercall)(PowerPCCPU *);
41 /*****************************************************************************/
42 /* Exception processing */
43 #if defined(CONFIG_USER_ONLY)
44 void ppc_cpu_do_interrupt(CPUState *cs)
46 PowerPCCPU *cpu = POWERPC_CPU(cs);
47 CPUPPCState *env = &cpu->env;
49 cs->exception_index = POWERPC_EXCP_NONE;
50 env->error_code = 0;
53 static void ppc_hw_interrupt(CPUPPCState *env)
55 CPUState *cs = CPU(ppc_env_get_cpu(env));
57 cs->exception_index = POWERPC_EXCP_NONE;
58 env->error_code = 0;
60 #else /* defined(CONFIG_USER_ONLY) */
61 static inline void dump_syscall(CPUPPCState *env)
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);
71 /* Note that this function should be greatly optimized
72 * when called with a constant excp, from ppc_hw_interrupt
74 static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
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;
82 if (0) {
83 /* XXX: find a suitable condition to enable the hypervisor mode */
84 lpes0 = (env->spr[SPR_LPCR] >> 1) & 1;
85 lpes1 = (env->spr[SPR_LPCR] >> 2) & 1;
86 } else {
87 /* Those values ensure we won't enter the hypervisor mode */
88 lpes0 = 0;
89 lpes1 = 1;
92 qemu_log_mask(CPU_LOG_INT, "Raise exception at " TARGET_FMT_lx
93 " => %08x (%02x)\n", env->nip, excp, env->error_code);
95 /* new srr1 value excluding must-be-zero bits */
96 if (excp_model == POWERPC_EXCP_BOOKE) {
97 msr = env->msr;
98 } else {
99 msr = env->msr & ~0x783f0000ULL;
102 /* new interrupt handler msr */
103 new_msr = env->msr & ((target_ulong)1 << MSR_ME);
105 /* target registers */
106 srr0 = SPR_SRR0;
107 srr1 = SPR_SRR1;
108 asrr0 = -1;
109 asrr1 = -1;
111 /* Exception targetting modifiers
113 * AIL is initialized here but can be cleared by
114 * selected exceptions
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;
124 } else
125 #endif /* defined(TARGET_PPC64) */
127 ail = 0;
130 switch (excp) {
131 case POWERPC_EXCP_NONE:
132 /* Should never happen */
133 return;
134 case POWERPC_EXCP_CRITICAL: /* Critical input */
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;
149 goto store_next;
150 case POWERPC_EXCP_MCHECK: /* Machine check exception */
151 if (msr_me == 0) {
152 /* Machine check exception is not enabled.
153 * Enter checkstop state.
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");
161 cs->halted = 1;
162 cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
164 if (0) {
165 /* XXX: find a suitable condition to enable the hypervisor mode */
166 new_msr |= (target_ulong)MSR_HVB;
168 ail = 0;
170 /* machine check exceptions don't have ME set */
171 new_msr &= ~((target_ulong)1 << MSR_ME);
173 /* XXX: should also have something loaded in DAR / DSISR */
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 /* FIXME: choose one or the other based on CPU type */
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;
189 goto store_next;
190 case POWERPC_EXCP_DSI: /* Data storage exception */
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;
196 goto store_next;
197 case POWERPC_EXCP_ISI: /* Instruction storage exception */
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;
203 msr |= env->error_code;
204 goto store_next;
205 case POWERPC_EXCP_EXTERNAL: /* External input */
206 cs = CPU(cpu);
208 if (lpes0 == 1) {
209 new_msr |= (target_ulong)MSR_HVB;
211 if (env->mpic_proxy) {
212 /* IACK the IRQ on delivery */
213 env->spr[SPR_BOOKE_EPR] = ldl_phys(cs->as, env->mpic_iack);
215 goto store_next;
216 case POWERPC_EXCP_ALIGN: /* Alignment exception */
217 if (lpes1 == 0) {
218 new_msr |= (target_ulong)MSR_HVB;
220 /* XXX: this is false */
221 /* Get rS/rD and rA from faulting opcode */
222 env->spr[SPR_DSISR] |= (cpu_ldl_code(env, (env->nip - 4))
223 & 0x03FF0000) >> 16;
224 goto store_next;
225 case POWERPC_EXCP_PROGRAM: /* Program exception */
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;
234 if (lpes1 == 0) {
235 new_msr |= (target_ulong)MSR_HVB;
237 msr |= 0x00100000;
238 if (msr_fe0 == msr_fe1) {
239 goto store_next;
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;
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;
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;
262 msr |= 0x00020000;
263 env->spr[SPR_BOOKE_ESR] = ESR_PTR;
264 break;
265 default:
266 /* Should never occur */
267 cpu_abort(cs, "Invalid program exception %d. Aborting\n",
268 env->error_code);
269 break;
271 goto store_current;
272 case POWERPC_EXCP_FPU: /* Floating-point unavailable exception */
273 if (lpes1 == 0) {
274 new_msr |= (target_ulong)MSR_HVB;
276 goto store_current;
277 case POWERPC_EXCP_SYSCALL: /* System call exception */
278 dump_syscall(env);
279 lev = env->error_code;
280 if ((lev == 1) && cpu_ppc_hypercall) {
281 cpu_ppc_hypercall(cpu);
282 return;
284 if (lev == 1 || (lpes0 == 0 && lpes1 == 0)) {
285 new_msr |= (target_ulong)MSR_HVB;
287 goto store_next;
288 case POWERPC_EXCP_APU: /* Auxiliary processor unavailable */
289 goto store_current;
290 case POWERPC_EXCP_DECR: /* Decrementer exception */
291 if (lpes1 == 0) {
292 new_msr |= (target_ulong)MSR_HVB;
294 goto store_next;
295 case POWERPC_EXCP_FIT: /* Fixed-interval timer interrupt */
296 /* FIT on 4xx */
297 LOG_EXCP("FIT exception\n");
298 goto store_next;
299 case POWERPC_EXCP_WDT: /* Watchdog timer interrupt */
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;
309 goto store_next;
310 case POWERPC_EXCP_DTLB: /* Data TLB error */
311 goto store_next;
312 case POWERPC_EXCP_ITLB: /* Instruction TLB error */
313 goto store_next;
314 case POWERPC_EXCP_DEBUG: /* Debug interrupt */
315 switch (excp_model) {
316 case POWERPC_EXCP_BOOKE:
317 /* FIXME: choose one or the other based on CPU type */
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;
326 /* XXX: TODO */
327 cpu_abort(cs, "Debug exception is not implemented yet !\n");
328 goto store_next;
329 case POWERPC_EXCP_SPEU: /* SPE/embedded floating-point unavailable */
330 env->spr[SPR_BOOKE_ESR] = ESR_SPV;
331 goto store_current;
332 case POWERPC_EXCP_EFPDI: /* Embedded floating-point data interrupt */
333 /* XXX: TODO */
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: /* Embedded floating-point round interrupt */
339 /* XXX: TODO */
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: /* Embedded performance monitor interrupt */
345 /* XXX: TODO */
346 cpu_abort(cs,
347 "Performance counter exception is not implemented yet !\n");
348 goto store_next;
349 case POWERPC_EXCP_DOORI: /* Embedded doorbell interrupt */
350 goto store_next;
351 case POWERPC_EXCP_DOORCI: /* Embedded doorbell critical interrupt */
352 srr0 = SPR_BOOKE_CSRR0;
353 srr1 = SPR_BOOKE_CSRR1;
354 goto store_next;
355 case POWERPC_EXCP_RESET: /* System reset exception */
356 if (msr_pow) {
357 /* indicate that we resumed from power save mode */
358 msr |= 0x10000;
359 } else {
360 new_msr &= ~((target_ulong)1 << MSR_ME);
363 if (0) {
364 /* XXX: find a suitable condition to enable the hypervisor mode */
365 new_msr |= (target_ulong)MSR_HVB;
367 ail = 0;
368 goto store_next;
369 case POWERPC_EXCP_DSEG: /* Data segment exception */
370 if (lpes1 == 0) {
371 new_msr |= (target_ulong)MSR_HVB;
373 goto store_next;
374 case POWERPC_EXCP_ISEG: /* Instruction segment exception */
375 if (lpes1 == 0) {
376 new_msr |= (target_ulong)MSR_HVB;
378 goto store_next;
379 case POWERPC_EXCP_HDECR: /* Hypervisor decrementer exception */
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: /* Trace exception */
386 if (lpes1 == 0) {
387 new_msr |= (target_ulong)MSR_HVB;
389 goto store_next;
390 case POWERPC_EXCP_HDSI: /* Hypervisor data storage exception */
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: /* Hypervisor instruction storage exception */
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: /* Hypervisor data segment exception */
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: /* Hypervisor instruction segment exception */
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: /* Vector unavailable exception */
415 if (lpes1 == 0) {
416 new_msr |= (target_ulong)MSR_HVB;
418 goto store_current;
419 case POWERPC_EXCP_VSXU: /* VSX unavailable exception */
420 if (lpes1 == 0) {
421 new_msr |= (target_ulong)MSR_HVB;
423 goto store_current;
424 case POWERPC_EXCP_FU: /* Facility unavailable exception */
425 if (lpes1 == 0) {
426 new_msr |= (target_ulong)MSR_HVB;
428 goto store_current;
429 case POWERPC_EXCP_PIT: /* Programmable interval timer interrupt */
430 LOG_EXCP("PIT exception\n");
431 goto store_next;
432 case POWERPC_EXCP_IO: /* IO error exception */
433 /* XXX: TODO */
434 cpu_abort(cs, "601 IO error exception is not implemented yet !\n");
435 goto store_next;
436 case POWERPC_EXCP_RUNM: /* Run mode exception */
437 /* XXX: TODO */
438 cpu_abort(cs, "601 run mode exception is not implemented yet !\n");
439 goto store_next;
440 case POWERPC_EXCP_EMUL: /* Emulation trap exception */
441 /* XXX: TODO */
442 cpu_abort(cs, "602 emulation trap exception "
443 "is not implemented yet !\n");
444 goto store_next;
445 case POWERPC_EXCP_IFTLB: /* Instruction fetch TLB error */
446 if (lpes1 == 0) { /* XXX: check this */
447 new_msr |= (target_ulong)MSR_HVB;
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;
463 break;
464 case POWERPC_EXCP_DLTLB: /* Data load TLB miss */
465 if (lpes1 == 0) { /* XXX: check this */
466 new_msr |= (target_ulong)MSR_HVB;
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;
482 break;
483 case POWERPC_EXCP_DSTLB: /* Data store TLB miss */
484 if (lpes1 == 0) { /* XXX: check this */
485 new_msr |= (target_ulong)MSR_HVB;
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 /* Swap temporary saved registers with GPRs */
494 if (!(new_msr & ((target_ulong)1 << MSR_TGPR))) {
495 new_msr |= (target_ulong)1 << MSR_TGPR;
496 hreg_swap_gpr_tgpr(env);
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;
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";
518 en = 'D';
519 miss = &env->spr[SPR_DMISS];
520 cmp = &env->spr[SPR_DCMP];
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);
528 #endif
529 msr |= env->crf[0] << 28;
530 msr |= env->error_code; /* key, D/I, S/L bits */
531 /* Set way using a LRU mechanism */
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;
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";
553 en = 'D';
554 miss = &env->spr[SPR_TLBMISS];
555 cmp = &env->spr[SPR_PTEHI];
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);
561 #endif
562 msr |= env->error_code; /* key bit */
563 break;
564 default:
565 cpu_abort(cs, "Invalid data store TLB miss exception\n");
566 break;
568 goto store_next;
569 case POWERPC_EXCP_FPA: /* Floating-point assist exception */
570 /* XXX: TODO */
571 cpu_abort(cs, "Floating point assist exception "
572 "is not implemented yet !\n");
573 goto store_next;
574 case POWERPC_EXCP_DABR: /* Data address breakpoint */
575 /* XXX: TODO */
576 cpu_abort(cs, "DABR exception is not implemented yet !\n");
577 goto store_next;
578 case POWERPC_EXCP_IABR: /* Instruction address breakpoint */
579 /* XXX: TODO */
580 cpu_abort(cs, "IABR exception is not implemented yet !\n");
581 goto store_next;
582 case POWERPC_EXCP_SMI: /* System management interrupt */
583 /* XXX: TODO */
584 cpu_abort(cs, "SMI exception is not implemented yet !\n");
585 goto store_next;
586 case POWERPC_EXCP_THERM: /* Thermal interrupt */
587 /* XXX: TODO */
588 cpu_abort(cs, "Thermal management exception "
589 "is not implemented yet !\n");
590 goto store_next;
591 case POWERPC_EXCP_PERFM: /* Embedded performance monitor interrupt */
592 if (lpes1 == 0) {
593 new_msr |= (target_ulong)MSR_HVB;
595 /* XXX: TODO */
596 cpu_abort(cs,
597 "Performance counter exception is not implemented yet !\n");
598 goto store_next;
599 case POWERPC_EXCP_VPUA: /* Vector assist exception */
600 /* XXX: TODO */
601 cpu_abort(cs, "VPU assist exception is not implemented yet !\n");
602 goto store_next;
603 case POWERPC_EXCP_SOFTP: /* Soft patch exception */
604 /* XXX: TODO */
605 cpu_abort(cs,
606 "970 soft-patch exception is not implemented yet !\n");
607 goto store_next;
608 case POWERPC_EXCP_MAINT: /* Maintenance exception */
609 /* XXX: TODO */
610 cpu_abort(cs,
611 "970 maintenance exception is not implemented yet !\n");
612 goto store_next;
613 case POWERPC_EXCP_MEXTBR: /* Maskable external breakpoint */
614 /* XXX: TODO */
615 cpu_abort(cs, "Maskable external exception "
616 "is not implemented yet !\n");
617 goto store_next;
618 case POWERPC_EXCP_NMEXTBR: /* Non maskable external breakpoint */
619 /* XXX: TODO */
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 /* save current instruction location */
629 env->spr[srr0] = env->nip - 4;
630 break;
631 store_next:
632 /* save next instruction location */
633 env->spr[srr0] = env->nip;
634 break;
636 /* Save MSR */
637 env->spr[srr1] = msr;
638 /* If any alternate SRR register are defined, duplicate saved values */
639 if (asrr0 != -1) {
640 env->spr[asrr0] = env->spr[srr0];
642 if (asrr1 != -1) {
643 env->spr[asrr1] = env->spr[srr1];
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 /* If we disactivated any translation, flush TLBs */
650 tlb_flush(cs, 1);
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;
659 } else if (msr_ile) {
660 new_msr |= (target_ulong)1 << MSR_LE;
662 #else
663 if (msr_ile) {
664 new_msr |= (target_ulong)1 << MSR_LE;
666 #endif
668 /* Jump to handler */
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);
674 vector |= env->excp_prefix;
676 /* AIL only works if there is no HV transition and we are running with
677 * translations enabled
679 if (!((msr >> MSR_IR) & 1) || !((msr >> MSR_DR) & 1)) {
680 ail = 0;
682 /* Handle AIL */
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;
698 #if defined(TARGET_PPC64)
699 if (excp_model == POWERPC_EXCP_BOOKE) {
700 if (env->spr[SPR_BOOKE_EPCR] & EPCR_ICM) {
701 /* Cat.64-bit: EPCR.ICM is copied to MSR.CM */
702 new_msr |= (target_ulong)1 << MSR_CM;
703 } else {
704 vector = (uint32_t)vector;
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;
713 #endif
714 /* XXX: we don't use hreg_store_msr here as already have treated
715 * any special case that could occur. Just store MSR and update hflags
717 env->msr = new_msr & env->msr_mask;
718 hreg_compute_hflags(env);
719 env->nip = vector;
720 /* Reset exception state */
721 cs->exception_index = POWERPC_EXCP_NONE;
722 env->error_code = 0;
724 if ((env->mmu_model == POWERPC_MMU_BOOKE) ||
725 (env->mmu_model == POWERPC_MMU_BOOKE206)) {
726 /* XXX: The BookE changes address space when switching modes,
727 we should probably implement that as different MMU indexes,
728 but for the moment we do it the slow way and flush all. */
729 tlb_flush(cs, 1);
733 void ppc_cpu_do_interrupt(CPUState *cs)
735 PowerPCCPU *cpu = POWERPC_CPU(cs);
736 CPUPPCState *env = &cpu->env;
738 powerpc_excp(cpu, env->excp_model, cs->exception_index);
741 static void ppc_hw_interrupt(CPUPPCState *env)
743 PowerPCCPU *cpu = ppc_env_get_cpu(env);
744 int hdice;
745 #if 0
746 CPUState *cs = CPU(cpu);
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 /* External reset */
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;
758 /* Machine check exception */
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;
764 #if 0 /* TODO */
765 /* External debug exception */
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;
771 #endif
772 if (0) {
773 /* XXX: find a suitable condition to enable the hypervisor mode */
774 hdice = env->spr[SPR_LPCR] & 1;
775 } else {
776 hdice = 0;
778 if ((msr_ee != 0 || msr_hv == 0 || msr_pr != 0) && hdice != 0) {
779 /* Hypervisor decrementer exception */
780 if (env->pending_interrupts & (1 << PPC_INTERRUPT_HDECR)) {
781 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_HDECR);
782 return;
785 if (msr_ce != 0) {
786 /* External critical interrupt */
787 if (env->pending_interrupts & (1 << PPC_INTERRUPT_CEXT)) {
788 /* Taking a critical external interrupt does not clear the external
789 * critical interrupt status
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;
798 if (msr_ee != 0) {
799 /* Watchdog timer on embedded PowerPC */
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;
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;
810 /* Fixed interval timer on embedded PowerPC */
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;
816 /* Programmable interval timer on embedded PowerPC */
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;
822 /* Decrementer exception */
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);
827 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_DECR);
828 return;
830 /* External interrupt */
831 if (env->pending_interrupts & (1 << PPC_INTERRUPT_EXT)) {
832 /* Taking an external interrupt does not clear the external
833 * interrupt status
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;
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;
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;
851 /* Thermal interrupt */
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;
860 void ppc_cpu_do_system_reset(CPUState *cs)
862 PowerPCCPU *cpu = POWERPC_CPU(cs);
863 CPUPPCState *env = &cpu->env;
865 powerpc_excp(cpu, env->excp_model, POWERPC_EXCP_RESET);
867 #endif /* !CONFIG_USER_ONLY */
869 bool ppc_cpu_exec_interrupt(CPUState *cs, int interrupt_request)
871 PowerPCCPU *cpu = POWERPC_CPU(cs);
872 CPUPPCState *env = &cpu->env;
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;
879 return true;
881 return false;
884 #if defined(DEBUG_OP)
885 static void cpu_dump_rfi(target_ulong RA, target_ulong msr)
887 qemu_log("Return from exception at " TARGET_FMT_lx " with flags "
888 TARGET_FMT_lx "\n", RA, msr);
890 #endif
892 /*****************************************************************************/
893 /* Exceptions processing helpers */
895 void helper_raise_exception_err(CPUPPCState *env, uint32_t exception,
896 uint32_t error_code)
898 CPUState *cs = CPU(ppc_env_get_cpu(env));
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);
908 void helper_raise_exception(CPUPPCState *env, uint32_t exception)
910 helper_raise_exception_err(env, exception, 0);
913 #if !defined(CONFIG_USER_ONLY)
914 void helper_store_msr(CPUPPCState *env, target_ulong val)
916 CPUState *cs;
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);
926 static inline void do_rfi(CPUPPCState *env, target_ulong nip, target_ulong msr,
927 target_ulong msrm, int keep_msrh)
929 CPUState *cs = CPU(ppc_env_get_cpu(env));
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);
942 #else
943 nip = (uint32_t)nip;
944 msr &= (uint32_t)msrm;
945 #endif
946 /* XXX: beware: this is false if VLE is supported */
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 /* No need to raise an exception here,
953 * as rfi is always the last insn of a TB
955 cs->interrupt_request |= CPU_INTERRUPT_EXITTB;
958 void helper_rfi(CPUPPCState *env)
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);
969 #if defined(TARGET_PPC64)
970 void helper_rfid(CPUPPCState *env)
972 do_rfi(env, env->spr[SPR_SRR0], env->spr[SPR_SRR1],
973 ~((target_ulong)0x783F0000), 0);
976 void helper_hrfid(CPUPPCState *env)
978 do_rfi(env, env->spr[SPR_HSRR0], env->spr[SPR_HSRR1],
979 ~((target_ulong)0x783F0000), 0);
981 #endif
983 /*****************************************************************************/
984 /* Embedded PowerPC specific helpers */
985 void helper_40x_rfci(CPUPPCState *env)
987 do_rfi(env, env->spr[SPR_40x_SRR2], env->spr[SPR_40x_SRR3],
988 ~((target_ulong)0xFFFF0000), 0);
991 void helper_rfci(CPUPPCState *env)
993 do_rfi(env, env->spr[SPR_BOOKE_CSRR0], env->spr[SPR_BOOKE_CSRR1],
994 ~((target_ulong)0), 0);
997 void helper_rfdi(CPUPPCState *env)
999 /* FIXME: choose CSRR1 or DSRR1 based on cpu type */
1000 do_rfi(env, env->spr[SPR_BOOKE_DSRR0], env->spr[SPR_BOOKE_DSRR1],
1001 ~((target_ulong)0), 0);
1004 void helper_rfmci(CPUPPCState *env)
1006 /* FIXME: choose CSRR1 or MCSRR1 based on cpu type */
1007 do_rfi(env, env->spr[SPR_BOOKE_MCSRR0], env->spr[SPR_BOOKE_MCSRR1],
1008 ~((target_ulong)0), 0);
1010 #endif
1012 void helper_tw(CPUPPCState *env, target_ulong arg1, target_ulong arg2,
1013 uint32_t flags)
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);
1025 #if defined(TARGET_PPC64)
1026 void helper_td(CPUPPCState *env, target_ulong arg1, target_ulong arg2,
1027 uint32_t flags)
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);
1038 #endif
1040 #if !defined(CONFIG_USER_ONLY)
1041 /*****************************************************************************/
1042 /* PowerPC 601 specific instructions (POWER bridge) */
1044 void helper_rfsvc(CPUPPCState *env)
1046 do_rfi(env, env->lr, env->ctr, 0x0000FFFF, 0);
1049 /* Embedded.Processor Control */
1050 static int dbell2irq(target_ulong rb)
1052 int msg = rb & DBELL_TYPE_MASK;
1053 int irq = -1;
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 /* XXX implement */
1066 default:
1067 break;
1070 return irq;
1073 void helper_msgclr(CPUPPCState *env, target_ulong rb)
1075 int irq = dbell2irq(rb);
1077 if (irq < 0) {
1078 return;
1081 env->pending_interrupts &= ~(1 << irq);
1084 void helper_msgsnd(target_ulong rb)
1086 int irq = dbell2irq(rb);
1087 int pir = rb & DBELL_PIRTAG_MASK;
1088 CPUState *cs;
1090 if (irq < 0) {
1091 return;
1094 CPU_FOREACH(cs) {
1095 PowerPCCPU *cpu = POWERPC_CPU(cs);
1096 CPUPPCState *cenv = &cpu->env;
1098 if ((rb & DBELL_BRDCAST) || (cenv->spr[SPR_BOOKE_PIR] == pir)) {
1099 cenv->pending_interrupts |= 1 << irq;
1100 cpu_interrupt(cs, CPU_INTERRUPT_HARD);
1104 #endif