Commit 2be0071f22f5719eb5e2800f070547227ba37e5a

Authored by bellard
1 parent f68c781c

simplified PowerPC exception handling (Jocelyn Mayer)


git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1492 c046a42c-6fe2-441c-8c8c-71466251a162
cpu-defs.h
... ... @@ -68,9 +68,9 @@ typedef uint64_t target_phys_addr_t;
68 68  
69 69 #define HOST_LONG_SIZE (HOST_LONG_BITS / 8)
70 70  
71   -#define EXCP_INTERRUPT 256 /* async interruption */
72   -#define EXCP_HLT 257 /* hlt instruction reached */
73   -#define EXCP_DEBUG 258 /* cpu stopped after a breakpoint or singlestep */
  71 +#define EXCP_INTERRUPT 0x10000 /* async interruption */
  72 +#define EXCP_HLT 0x10001 /* hlt instruction reached */
  73 +#define EXCP_DEBUG 0x10002 /* cpu stopped after a breakpoint or singlestep */
74 74  
75 75 #define MAX_BREAKPOINTS 32
76 76  
... ...
linux-user/main.c
... ... @@ -706,28 +706,22 @@ void cpu_loop(CPUPPCState *env)
706 706 fprintf(logfile, "Invalid data memory access: 0x%08x\n",
707 707 env->spr[SPR_DAR]);
708 708 }
709   - switch (env->error_code & 0xF) {
710   - case EXCP_DSI_TRANSLATE:
  709 + switch (env->error_code & 0xFF000000) {
  710 + case 0x40000000:
711 711 info.si_signo = TARGET_SIGSEGV;
712 712 info.si_errno = 0;
713 713 info.si_code = TARGET_SEGV_MAPERR;
714 714 break;
715   - case EXCP_DSI_NOTSUP:
716   - case EXCP_DSI_EXTERNAL:
  715 + case 0x04000000:
717 716 info.si_signo = TARGET_SIGILL;
718 717 info.si_errno = 0;
719 718 info.si_code = TARGET_ILL_ILLADR;
720 719 break;
721   - case EXCP_DSI_PROT:
  720 + case 0x08000000:
722 721 info.si_signo = TARGET_SIGSEGV;
723 722 info.si_errno = 0;
724 723 info.si_code = TARGET_SEGV_ACCERR;
725 724 break;
726   - case EXCP_DSI_DABR:
727   - info.si_signo = TARGET_SIGTRAP;
728   - info.si_errno = 0;
729   - info.si_code = TARGET_TRAP_BRKPT;
730   - break;
731 725 default:
732 726 /* Let's send a regular segfault... */
733 727 fprintf(stderr, "Invalid segfault errno (%02x)\n",
... ... @@ -748,19 +742,14 @@ void cpu_loop(CPUPPCState *env)
748 742 fprintf(stderr, "Invalid instruction fetch\n");
749 743 if (loglevel)
750 744 fprintf(logfile, "Invalid instruction fetch\n");
751   - switch (env->error_code) {
752   - case EXCP_ISI_TRANSLATE:
  745 + switch (env->error_code & 0xFF000000) {
  746 + case 0x40000000:
753 747 info.si_signo = TARGET_SIGSEGV;
754 748 info.si_errno = 0;
755 749 info.si_code = TARGET_SEGV_MAPERR;
756 750 break;
757   - case EXCP_ISI_GUARD:
758   - info.si_signo = TARGET_SIGILL;
759   - info.si_errno = 0;
760   - info.si_code = TARGET_ILL_ILLADR;
761   - break;
762   - case EXCP_ISI_NOEXEC:
763   - case EXCP_ISI_PROT:
  751 + case 0x10000000:
  752 + case 0x08000000:
764 753 info.si_signo = TARGET_SIGSEGV;
765 754 info.si_errno = 0;
766 755 info.si_code = TARGET_SEGV_ACCERR;
... ... @@ -930,18 +919,6 @@ void cpu_loop(CPUPPCState *env)
930 919 if (loglevel)
931 920 fprintf(logfile, "Decrementer exception\n");
932 921 abort();
933   - case EXCP_RESA: /* Implementation specific */
934   - /* Should not happen ! */
935   - fprintf(stderr, "RESA exception should never happen !\n");
936   - if (loglevel)
937   - fprintf(logfile, "RESA exception should never happen !\n");
938   - abort();
939   - case EXCP_RESB: /* Implementation specific */
940   - /* Should not happen ! */
941   - fprintf(stderr, "RESB exception should never happen !\n");
942   - if (loglevel)
943   - fprintf(logfile, "RESB exception should never happen !\n");
944   - abort();
945 922 case EXCP_TRACE:
946 923 /* Do nothing: we use this to trace execution */
947 924 break;
... ... @@ -963,12 +940,6 @@ void cpu_loop(CPUPPCState *env)
963 940 case EXCP_BRANCH:
964 941 /* We stopped because of a jump... */
965 942 break;
966   - case EXCP_RFI:
967   - /* Should not occur: we always are in user mode */
968   - fprintf(stderr, "Return from interrupt ?\n");
969   - if (loglevel)
970   - fprintf(logfile, "Return from interrupt ?\n");
971   - abort();
972 943 case EXCP_INTERRUPT:
973 944 /* Don't know why this should ever happen... */
974 945 break;
... ...
target-ppc/cpu.h
... ... @@ -924,62 +924,72 @@ enum {
924 924  
925 925 /*****************************************************************************/
926 926 /* Exceptions */
927   -enum {
928   - EXCP_NONE = -1,
929   - /* PowerPC hardware exceptions : exception vector / 0x100 */
930   - EXCP_RESET = 0x01, /* System reset */
931   - EXCP_MACHINE_CHECK = 0x02, /* Machine check exception */
932   - EXCP_DSI = 0x03, /* Impossible memory access */
933   - EXCP_ISI = 0x04, /* Impossible instruction fetch */
934   - EXCP_EXTERNAL = 0x05, /* External interruption */
935   - EXCP_ALIGN = 0x06, /* Alignment exception */
936   - EXCP_PROGRAM = 0x07, /* Program exception */
937   - EXCP_NO_FP = 0x08, /* No floating point */
938   - EXCP_DECR = 0x09, /* Decrementer exception */
939   - EXCP_RESA = 0x0A, /* Implementation specific */
940   - EXCP_RESB = 0x0B, /* Implementation specific */
941   - EXCP_SYSCALL = 0x0C, /* System call */
942   - EXCP_TRACE = 0x0D, /* Trace exception (optional) */
943   - EXCP_FP_ASSIST = 0x0E, /* Floating-point assist (optional) */
944   - /* MPC740/745/750 & IBM 750 */
945   - EXCP_PERF = 0x0F, /* Performance monitor */
946   - EXCP_IABR = 0x13, /* Instruction address breakpoint */
947   - EXCP_SMI = 0x14, /* System management interrupt */
948   - EXCP_THRM = 0x15, /* Thermal management interrupt */
949   - /* MPC755 */
950   - EXCP_TLBMISS = 0x10, /* Instruction TLB miss */
951   - EXCP_TLBMISS_DL = 0x11, /* Data TLB miss for load */
952   - EXCP_TLBMISS_DS = 0x12, /* Data TLB miss for store */
953   - EXCP_PPC_MAX = 0x16,
954   - /* Qemu exception */
955   - EXCP_OFCALL = 0x20, /* Call open-firmware emulator */
956   - EXCP_RTASCALL = 0x21, /* Call RTAS emulator */
957   - /* Special cases where we want to stop translation */
958   - EXCP_MTMSR = 0x104, /* mtmsr instruction: */
  927 +#define EXCP_NONE -1
  928 +/* PowerPC hardware exceptions : exception vectors defined in PowerPC book 3 */
  929 +#define EXCP_RESET 0x0100 /* System reset */
  930 +#define EXCP_MACHINE_CHECK 0x0200 /* Machine check exception */
  931 +#define EXCP_DSI 0x0300 /* Data storage exception */
  932 +#define EXCP_DSEG 0x0380 /* Data segment exception */
  933 +#define EXCP_ISI 0x0400 /* Instruction storage exception */
  934 +#define EXCP_ISEG 0x0480 /* Instruction segment exception */
  935 +#define EXCP_EXTERNAL 0x0500 /* External interruption */
  936 +#define EXCP_ALIGN 0x0600 /* Alignment exception */
  937 +#define EXCP_PROGRAM 0x0700 /* Program exception */
  938 +#define EXCP_NO_FP 0x0800 /* Floating point unavailable exception */
  939 +#define EXCP_DECR 0x0900 /* Decrementer exception */
  940 +#define EXCP_HDECR 0x0980 /* Hypervisor decrementer exception */
  941 +#define EXCP_SYSCALL 0x0C00 /* System call */
  942 +#define EXCP_TRACE 0x0D00 /* Trace exception */
  943 +#define EXCP_PERF 0x0F00 /* Performance monitor exception */
  944 +/* Exceptions defined in PowerPC 32 bits programming environment manual */
  945 +#define EXCP_FP_ASSIST 0x0E00 /* Floating-point assist */
  946 +/* Implementation specific exceptions */
  947 +/* 40x exceptions */
  948 +#define EXCP_40x_PIT 0x1000 /* Programmable interval timer interrupt */
  949 +#define EXCP_40x_FIT 0x1010 /* Fixed interval timer interrupt */
  950 +#define EXCP_40x_WATCHDOG 0x1020 /* Watchdog timer exception */
  951 +#define EXCP_40x_DTLBMISS 0x1100 /* Data TLB miss exception */
  952 +#define EXCP_40x_ITLBMISS 0x1200 /* Instruction TLB miss exception */
  953 +#define EXCP_40x_DEBUG 0x2000 /* Debug exception */
  954 +/* 405 specific exceptions */
  955 +#define EXCP_405_APU 0x0F20 /* APU unavailable exception */
  956 +/* TLB assist exceptions (602/603) */
  957 +#define EXCP_I_TLBMISS 0x1000 /* Instruction TLB miss */
  958 +#define EXCP_DL_TLBMISS 0x1100 /* Data load TLB miss */
  959 +#define EXCP_DS_TLBMISS 0x1200 /* Data store TLB miss */
  960 +/* Breakpoint exceptions (602/603/604/620/740/745/750/755...) */
  961 +#define EXCP_IABR 0x1300 /* Instruction address breakpoint */
  962 +#define EXCP_SMI 0x1400 /* System management interrupt */
  963 +/* Altivec related exceptions */
  964 +#define EXCP_VPU 0x0F20 /* VPU unavailable exception */
  965 +/* 601 specific exceptions */
  966 +#define EXCP_601_IO 0x0600 /* IO error exception */
  967 +#define EXCP_601_RUNM 0x2000 /* Run mode exception */
  968 +/* 602 specific exceptions */
  969 +#define EXCP_602_WATCHDOG 0x1500 /* Watchdog exception */
  970 +#define EXCP_602_EMUL 0x1600 /* Emulation trap exception */
  971 +/* G2 specific exceptions */
  972 +#define EXCP_G2_CRIT 0x0A00 /* Critical interrupt */
  973 +/* MPC740/745/750 & IBM 750 specific exceptions */
  974 +#define EXCP_THRM 0x1700 /* Thermal management interrupt */
  975 +/* 74xx specific exceptions */
  976 +#define EXCP_74xx_VPUA 0x1600 /* VPU assist exception */
  977 +/* 970FX specific exceptions */
  978 +#define EXCP_970_SOFTP 0x1500 /* Soft patch exception */
  979 +#define EXCP_970_MAINT 0x1600 /* Maintenance exception */
  980 +#define EXCP_970_THRM 0x1800 /* Thermal exception */
  981 +#define EXCP_970_VPUA 0x1700 /* VPU assist exception */
  982 +/* End of exception vectors area */
  983 +#define EXCP_PPC_MAX 0x4000
  984 +/* Qemu exceptions: special cases we want to stop translation */
  985 +#define EXCP_MTMSR 0x11000 /* mtmsr instruction: */
959 986 /* may change privilege level */
960   - EXCP_BRANCH = 0x108, /* branch instruction */
961   - EXCP_RFI = 0x10C, /* return from interrupt */
962   - EXCP_SYSCALL_USER = 0x110, /* System call in user mode only */
963   -};
  987 +#define EXCP_BRANCH 0x11001 /* branch instruction */
  988 +#define EXCP_SYSCALL_USER 0x12000 /* System call in user mode only */
  989 +#define EXCP_INTERRUPT_CRITICAL 0x13000 /* critical IRQ */
  990 +
964 991 /* Error codes */
965 992 enum {
966   - /* Exception subtypes for EXCP_DSI */
967   - EXCP_DSI_TRANSLATE = 0x01, /* Data address can't be translated */
968   - EXCP_DSI_NOTSUP = 0x02, /* Access type not supported */
969   - EXCP_DSI_PROT = 0x03, /* Memory protection violation */
970   - EXCP_DSI_EXTERNAL = 0x04, /* External access disabled */
971   - EXCP_DSI_DABR = 0x05, /* Data address breakpoint */
972   - /* flags for EXCP_DSI */
973   - EXCP_DSI_DIRECT = 0x10,
974   - EXCP_DSI_STORE = 0x20,
975   - EXCP_DSI_ECXW = 0x40,
976   - /* Exception subtypes for EXCP_ISI */
977   - EXCP_ISI_TRANSLATE = 0x01, /* Code address can't be translated */
978   - EXCP_ISI_NOEXEC = 0x02, /* Try to fetch from a data segment */
979   - EXCP_ISI_GUARD = 0x03, /* Fetch from guarded memory */
980   - EXCP_ISI_PROT = 0x04, /* Memory protection violation */
981   - EXCP_ISI_DIRECT = 0x05, /* Trying to fetch from *
982   - * a direct store segment */
983 993 /* Exception subtypes for EXCP_ALIGN */
984 994 EXCP_ALIGN_FP = 0x01, /* FP alignment exception */
985 995 EXCP_ALIGN_LST = 0x02, /* Unaligned mult/extern load/store */
... ...
target-ppc/helper.c
... ... @@ -22,8 +22,6 @@
22 22 //#define DEBUG_MMU
23 23 //#define DEBUG_BATS
24 24 //#define DEBUG_EXCEPTIONS
25   -/* accurate but slower TLB flush in exceptions */
26   -//#define ACCURATE_TLB_FLUSH
27 25  
28 26 /*****************************************************************************/
29 27 /* PowerPC MMU emulation */
... ... @@ -524,20 +522,25 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, uint32_t address, int rw,
524 522 switch (ret) {
525 523 case -1:
526 524 /* No matches in page tables */
527   - error_code = EXCP_ISI_TRANSLATE;
  525 + error_code = 0x40000000;
528 526 break;
529 527 case -2:
530 528 /* Access rights violation */
531   - error_code = EXCP_ISI_PROT;
  529 + error_code = 0x08000000;
532 530 break;
533 531 case -3:
534 532 /* No execute protection violation */
535   - error_code = EXCP_ISI_NOEXEC;
  533 + error_code = 0x10000000;
536 534 break;
537 535 case -4:
538 536 /* Direct store exception */
539 537 /* No code fetch is allowed in direct-store areas */
540   - error_code = EXCP_ISI_DIRECT;
  538 + error_code = 0x10000000;
  539 + break;
  540 + case -5:
  541 + /* No match in segment table */
  542 + exception = EXCP_ISEG;
  543 + error_code = 0;
541 544 break;
542 545 }
543 546 } else {
... ... @@ -545,11 +548,11 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, uint32_t address, int rw,
545 548 switch (ret) {
546 549 case -1:
547 550 /* No matches in page tables */
548   - error_code = EXCP_DSI_TRANSLATE;
  551 + error_code = 0x40000000;
549 552 break;
550 553 case -2:
551 554 /* Access rights violation */
552   - error_code = EXCP_DSI_PROT;
  555 + error_code = 0x08000000;
553 556 break;
554 557 case -4:
555 558 /* Direct store exception */
... ... @@ -561,14 +564,11 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, uint32_t address, int rw,
561 564 break;
562 565 case ACCESS_RES:
563 566 /* lwarx, ldarx or srwcx. */
564   - exception = EXCP_DSI;
565   - error_code = EXCP_DSI_NOTSUP | EXCP_DSI_DIRECT;
  567 + error_code = 0x04000000;
566 568 break;
567 569 case ACCESS_EXT:
568 570 /* eciwx or ecowx */
569   - exception = EXCP_DSI;
570   - error_code = EXCP_DSI_NOTSUP | EXCP_DSI_DIRECT |
571   - EXCP_DSI_ECXW;
  571 + error_code = 0x04100000;
572 572 break;
573 573 default:
574 574 printf("DSI: invalid exception (%d)\n", ret);
... ... @@ -576,11 +576,17 @@ int cpu_ppc_handle_mmu_fault (CPUState *env, uint32_t address, int rw,
576 576 error_code = EXCP_INVAL | EXCP_INVAL_INVAL;
577 577 break;
578 578 }
  579 + case -5:
  580 + /* No match in segment table */
  581 + exception = EXCP_DSEG;
  582 + error_code = 0;
  583 + break;
579 584 }
580 585 if (rw)
581   - error_code |= EXCP_DSI_STORE;
  586 + error_code |= 0x02000000;
582 587 /* Store fault address */
583 588 env->spr[SPR_DAR] = address;
  589 + env->spr[SPR_DSISR] = error_code;
584 590 }
585 591 #if 0
586 592 printf("%s: set exception to %d %02x\n",
... ... @@ -985,119 +991,107 @@ static void dump_syscall(CPUState *env)
985 991  
986 992 void do_interrupt (CPUState *env)
987 993 {
988   - uint32_t msr;
  994 + target_ulong msr, *srr_0, *srr_1, tmp;
989 995 int excp;
990 996  
991 997 excp = env->exception_index;
992 998 msr = do_load_msr(env);
  999 + /* The default is to use SRR0 & SRR1 to save the exception context */
  1000 + srr_0 = &env->spr[SPR_SRR0];
  1001 + srr_1 = &env->spr[SPR_SRR1];
993 1002 #if defined (DEBUG_EXCEPTIONS)
994   - if ((excp == EXCP_PROGRAM || excp == EXCP_DSI) && msr_pr == 1)
995   - {
996   - if (loglevel > 0) {
997   - fprintf(logfile, "Raise exception at 0x%08x => 0x%08x (%02x)\n",
998   - env->nip, excp << 8, env->error_code);
  1003 + if ((excp == EXCP_PROGRAM || excp == EXCP_DSI) && msr_pr == 1) {
  1004 + if (loglevel != 0) {
  1005 + fprintf(logfile, "Raise exception at 0x%08lx => 0x%08x (%02x)\n",
  1006 + (unsigned long)env->nip, excp, env->error_code);
  1007 + cpu_dump_state(env, logfile, fprintf, 0);
999 1008 }
1000   - if (loglevel > 0)
1001   - cpu_dump_state(env, logfile, fprintf, 0);
1002 1009 }
1003 1010 #endif
1004 1011 if (loglevel & CPU_LOG_INT) {
1005   - fprintf(logfile, "Raise exception at 0x%08x => 0x%08x (%02x)\n",
1006   - env->nip, excp << 8, env->error_code);
  1012 + fprintf(logfile, "Raise exception at 0x%08lx => 0x%08x (%02x)\n",
  1013 + (unsigned long)env->nip, excp, env->error_code);
1007 1014 }
  1015 + msr_pow = 0;
1008 1016 /* Generate informations in save/restore registers */
1009 1017 switch (excp) {
1010   - case EXCP_NONE:
1011   - /* Do nothing */
1012   -#if defined (DEBUG_EXCEPTIONS)
1013   - printf("%s: escape EXCP_NONE\n", __func__);
1014   -#endif
1015   - return;
1016   - case EXCP_RESET:
1017   - if (msr_ip)
1018   - excp += 0xFFC00;
  1018 + /* Generic PowerPC exceptions */
  1019 + case EXCP_RESET: /* 0x0100 */
  1020 + if (PPC_EXCP(env) != PPC_FLAGS_EXCP_40x) {
  1021 + if (msr_ip)
  1022 + excp += 0xFFC00;
  1023 + excp |= 0xFFC00000;
  1024 + } else {
  1025 + srr_0 = &env->spr[SPR_40x_SRR2];
  1026 + srr_1 = &env->spr[SPR_40x_SRR3];
  1027 + }
1019 1028 goto store_next;
1020   - case EXCP_MACHINE_CHECK:
  1029 + case EXCP_MACHINE_CHECK: /* 0x0200 */
1021 1030 if (msr_me == 0) {
1022 1031 cpu_abort(env, "Machine check exception while not allowed\n");
1023 1032 }
  1033 + if (PPC_EXCP(env) == PPC_FLAGS_EXCP_40x) {
  1034 + srr_0 = &env->spr[SPR_40x_SRR2];
  1035 + srr_1 = &env->spr[SPR_40x_SRR3];
  1036 + }
1024 1037 msr_me = 0;
1025 1038 break;
1026   - case EXCP_DSI:
  1039 + case EXCP_DSI: /* 0x0300 */
1027 1040 /* Store exception cause */
1028 1041 /* data location address has been stored
1029 1042 * when the fault has been detected
1030   - */
  1043 + */
1031 1044 msr &= ~0xFFFF0000;
1032   - env->spr[SPR_DSISR] = 0;
1033   - if ((env->error_code & 0x0f) == EXCP_DSI_TRANSLATE)
1034   - env->spr[SPR_DSISR] |= 0x40000000;
1035   - else if ((env->error_code & 0x0f) == EXCP_DSI_PROT)
1036   - env->spr[SPR_DSISR] |= 0x08000000;
1037   - else if ((env->error_code & 0x0f) == EXCP_DSI_NOTSUP) {
1038   - env->spr[SPR_DSISR] |= 0x80000000;
1039   - if (env->error_code & EXCP_DSI_DIRECT)
1040   - env->spr[SPR_DSISR] |= 0x04000000;
1041   - }
1042   - if (env->error_code & EXCP_DSI_STORE)
1043   - env->spr[SPR_DSISR] |= 0x02000000;
1044   - if ((env->error_code & 0xF) == EXCP_DSI_DABR)
1045   - env->spr[SPR_DSISR] |= 0x00400000;
1046   - if (env->error_code & EXCP_DSI_ECXW)
1047   - env->spr[SPR_DSISR] |= 0x00100000;
1048 1045 #if defined (DEBUG_EXCEPTIONS)
1049 1046 if (loglevel) {
1050 1047 fprintf(logfile, "DSI exception: DSISR=0x%08x, DAR=0x%08x\n",
1051 1048 env->spr[SPR_DSISR], env->spr[SPR_DAR]);
1052 1049 } else {
1053   - printf("DSI exception: DSISR=0x%08x, DAR=0x%08x nip=0x%08x\n",
1054   - env->spr[SPR_DSISR], env->spr[SPR_DAR], env->nip);
  1050 + printf("DSI exception: DSISR=0x%08x, DAR=0x%08x\n",
  1051 + env->spr[SPR_DSISR], env->spr[SPR_DAR]);
1055 1052 }
1056 1053 #endif
1057 1054 goto store_next;
1058   - case EXCP_ISI:
  1055 + case EXCP_ISI: /* 0x0400 */
1059 1056 /* Store exception cause */
1060 1057 msr &= ~0xFFFF0000;
1061   - if (env->error_code == EXCP_ISI_TRANSLATE)
1062   - msr |= 0x40000000;
1063   - else if (env->error_code == EXCP_ISI_NOEXEC ||
1064   - env->error_code == EXCP_ISI_GUARD ||
1065   - env->error_code == EXCP_ISI_DIRECT)
1066   - msr |= 0x10000000;
1067   - else
1068   - msr |= 0x08000000;
  1058 + msr |= env->error_code;
1069 1059 #if defined (DEBUG_EXCEPTIONS)
1070   - if (loglevel) {
  1060 + if (loglevel != 0) {
1071 1061 fprintf(logfile, "ISI exception: msr=0x%08x, nip=0x%08x\n",
1072 1062 msr, env->nip);
1073   - } else {
1074   - printf("ISI exception: msr=0x%08x, nip=0x%08x tbl:0x%08x\n",
1075   - msr, env->nip, env->spr[V_TBL]);
1076 1063 }
1077 1064 #endif
1078 1065 goto store_next;
1079   - case EXCP_EXTERNAL:
  1066 + case EXCP_EXTERNAL: /* 0x0500 */
1080 1067 if (msr_ee == 0) {
1081 1068 #if defined (DEBUG_EXCEPTIONS)
1082 1069 if (loglevel > 0) {
1083 1070 fprintf(logfile, "Skipping hardware interrupt\n");
1084   - }
  1071 + }
1085 1072 #endif
1086 1073 /* Requeue it */
1087   - do_raise_exception(EXCP_EXTERNAL);
  1074 + env->interrupt_request |= CPU_INTERRUPT_HARD;
1088 1075 return;
1089   - }
  1076 + }
1090 1077 goto store_next;
1091   - case EXCP_ALIGN:
1092   - /* Store exception cause */
1093   - /* Get rS/rD and rA from faulting opcode */
1094   - env->spr[SPR_DSISR] |=
1095   - (ldl_code((env->nip - 4)) & 0x03FF0000) >> 16;
1096   - /* data location address has been stored
1097   - * when the fault has been detected
1098   - */
  1078 + case EXCP_ALIGN: /* 0x0600 */
  1079 + if (PPC_EXCP(env) != PPC_FLAGS_EXCP_601) {
  1080 + /* Store exception cause */
  1081 + /* Get rS/rD and rA from faulting opcode */
  1082 + env->spr[SPR_DSISR] |=
  1083 + (ldl_code((env->nip - 4)) & 0x03FF0000) >> 16;
  1084 + /* data location address has been stored
  1085 + * when the fault has been detected
  1086 + */
  1087 + } else {
  1088 + /* IO error exception on PowerPC 601 */
  1089 + /* XXX: TODO */
  1090 + cpu_abort(env,
  1091 + "601 IO error exception is not implemented yet !\n");
  1092 + }
1099 1093 goto store_current;
1100   - case EXCP_PROGRAM:
  1094 + case EXCP_PROGRAM: /* 0x0700 */
1101 1095 msr &= ~0xFFFF0000;
1102 1096 switch (env->error_code & ~0xF) {
1103 1097 case EXCP_FP:
... ... @@ -1131,17 +1125,19 @@ void do_interrupt (CPUState *env)
1131 1125 }
1132 1126 msr |= 0x00010000;
1133 1127 goto store_current;
1134   - case EXCP_NO_FP:
  1128 + case EXCP_NO_FP: /* 0x0800 */
1135 1129 msr &= ~0xFFFF0000;
1136 1130 goto store_current;
1137 1131 case EXCP_DECR:
1138 1132 if (msr_ee == 0) {
  1133 +#if 1
1139 1134 /* Requeue it */
1140   - do_raise_exception(EXCP_DECR);
  1135 + env->interrupt_request |= CPU_INTERRUPT_TIMER;
  1136 +#endif
1141 1137 return;
1142 1138 }
1143 1139 goto store_next;
1144   - case EXCP_SYSCALL:
  1140 + case EXCP_SYSCALL: /* 0x0C00 */
1145 1141 /* NOTE: this is a temporary hack to support graphics OSI
1146 1142 calls from the MOL driver */
1147 1143 if (env->gpr[3] == 0x113724fa && env->gpr[4] == 0x77810f9b &&
... ... @@ -1153,35 +1149,332 @@ void do_interrupt (CPUState *env)
1153 1149 dump_syscall(env);
1154 1150 }
1155 1151 goto store_next;
1156   - case EXCP_TRACE:
  1152 + case EXCP_TRACE: /* 0x0D00 */
  1153 + /* XXX: TODO */
  1154 + cpu_abort(env, "Trace exception is not implemented yet !\n");
  1155 + goto store_next;
  1156 + case EXCP_PERF: /* 0x0F00 */
  1157 + /* XXX: TODO */
  1158 + cpu_abort(env,
  1159 + "Performance counter exception is not implemented yet !\n");
  1160 + goto store_next;
  1161 + /* 32 bits PowerPC specific exceptions */
  1162 + case EXCP_FP_ASSIST: /* 0x0E00 */
  1163 + /* XXX: TODO */
  1164 + cpu_abort(env, "Floating point assist exception "
  1165 + "is not implemented yet !\n");
  1166 + goto store_next;
  1167 + /* 64 bits PowerPC exceptions */
  1168 + case EXCP_DSEG: /* 0x0380 */
  1169 + /* XXX: TODO */
  1170 + cpu_abort(env, "Data segment exception is not implemented yet !\n");
1157 1171 goto store_next;
1158   - case EXCP_FP_ASSIST:
  1172 + case EXCP_ISEG: /* 0x0480 */
  1173 + /* XXX: TODO */
  1174 + cpu_abort(env,
  1175 + "Instruction segment exception is not implemented yet !\n");
1159 1176 goto store_next;
1160   - case EXCP_MTMSR:
1161   - /* Nothing to do */
  1177 + case EXCP_HDECR: /* 0x0980 */
  1178 + if (msr_ee == 0) {
  1179 +#if 1
  1180 + /* Requeue it */
  1181 + env->interrupt_request |= CPU_INTERRUPT_TIMER;
  1182 +#endif
1162 1183 return;
1163   - case EXCP_BRANCH:
1164   - /* Nothing to do */
  1184 + }
  1185 + cpu_abort(env,
  1186 + "Hypervisor decrementer exception is not implemented yet !\n");
  1187 + goto store_next;
  1188 + /* Implementation specific exceptions */
  1189 + case 0x0A00:
  1190 + if (PPC_EXCP(env) != PPC_FLAGS_EXCP_602) {
  1191 + /* Critical interrupt on G2 */
  1192 + /* XXX: TODO */
  1193 + cpu_abort(env, "G2 critical interrupt is not implemented yet !\n");
  1194 + goto store_next;
  1195 + } else {
  1196 + cpu_abort(env, "Invalid exception 0x0A00 !\n");
  1197 + }
1165 1198 return;
1166   - case EXCP_RFI:
1167   - /* Restore user-mode state */
1168   -#if defined (DEBUG_EXCEPTIONS)
1169   - if (msr_pr == 1)
1170   - printf("Return from exception => 0x%08x\n", (uint32_t)env->nip);
  1199 + case 0x0F20:
  1200 + switch (PPC_EXCP(env)) {
  1201 + case PPC_FLAGS_EXCP_40x:
  1202 + /* APU unavailable on 405 */
  1203 + /* XXX: TODO */
  1204 + cpu_abort(env,
  1205 + "APU unavailable exception is not implemented yet !\n");
  1206 + goto store_next;
  1207 + case PPC_FLAGS_EXCP_74xx:
  1208 + /* Altivec unavailable */
  1209 + /* XXX: TODO */
  1210 + cpu_abort(env, "Altivec unavailable exception "
  1211 + "is not implemented yet !\n");
  1212 + goto store_next;
  1213 + default:
  1214 + cpu_abort(env, "Invalid exception 0x0F20 !\n");
  1215 + break;
  1216 + }
  1217 + return;
  1218 + case 0x1000:
  1219 + switch (PPC_EXCP(env)) {
  1220 + case PPC_FLAGS_EXCP_40x:
  1221 + /* PIT on 4xx */
  1222 + /* XXX: TODO */
  1223 + cpu_abort(env, "40x PIT exception is not implemented yet !\n");
  1224 + goto store_next;
  1225 + case PPC_FLAGS_EXCP_602:
  1226 + case PPC_FLAGS_EXCP_603:
  1227 + /* ITLBMISS on 602/603 */
  1228 + msr &= ~0xF00F0000;
  1229 + msr_tgpr = 1;
  1230 + goto store_gprs;
  1231 + default:
  1232 + cpu_abort(env, "Invalid exception 0x1000 !\n");
  1233 + break;
  1234 + }
  1235 + return;
  1236 + case 0x1010:
  1237 + switch (PPC_EXCP(env)) {
  1238 + case PPC_FLAGS_EXCP_40x:
  1239 + /* FIT on 4xx */
  1240 + cpu_abort(env, "40x FIT exception is not implemented yet !\n");
  1241 + /* XXX: TODO */
  1242 + goto store_next;
  1243 + default:
  1244 + cpu_abort(env, "Invalid exception 0x1010 !\n");
  1245 + break;
  1246 + }
  1247 + return;
  1248 + case 0x1020:
  1249 + switch (PPC_EXCP(env)) {
  1250 + case PPC_FLAGS_EXCP_40x:
  1251 + /* Watchdog on 4xx */
  1252 + /* XXX: TODO */
  1253 + cpu_abort(env,
  1254 + "40x watchdog exception is not implemented yet !\n");
  1255 + goto store_next;
  1256 + default:
  1257 + cpu_abort(env, "Invalid exception 0x1020 !\n");
  1258 + break;
  1259 + }
  1260 + return;
  1261 + case 0x1100:
  1262 + switch (PPC_EXCP(env)) {
  1263 + case PPC_FLAGS_EXCP_40x:
  1264 + /* DTLBMISS on 4xx */
  1265 + /* XXX: TODO */
  1266 + cpu_abort(env,
  1267 + "40x DTLBMISS exception is not implemented yet !\n");
  1268 + goto store_next;
  1269 + case PPC_FLAGS_EXCP_602:
  1270 + case PPC_FLAGS_EXCP_603:
  1271 + /* DLTLBMISS on 602/603 */
  1272 + msr &= ~0xF00F0000;
  1273 + msr_tgpr = 1;
  1274 + goto store_gprs;
  1275 + default:
  1276 + cpu_abort(env, "Invalid exception 0x1100 !\n");
  1277 + break;
  1278 + }
  1279 + return;
  1280 + case 0x1200:
  1281 + switch (PPC_EXCP(env)) {
  1282 + case PPC_FLAGS_EXCP_40x:
  1283 + /* ITLBMISS on 4xx */
  1284 + /* XXX: TODO */
  1285 + cpu_abort(env,
  1286 + "40x ITLBMISS exception is not implemented yet !\n");
  1287 + goto store_next;
  1288 + case PPC_FLAGS_EXCP_602:
  1289 + case PPC_FLAGS_EXCP_603:
  1290 + /* DSTLBMISS on 602/603 */
  1291 + msr &= ~0xF00F0000;
  1292 + msr_tgpr = 1;
  1293 + store_gprs:
  1294 +#if defined (DEBUG_SOFTWARE_TLB)
  1295 + if (loglevel != 0) {
  1296 + fprintf(logfile, "6xx %sTLB miss: IM %08x DM %08x IC %08x "
  1297 + "DC %08x H1 %08x H2 %08x %08x\n",
  1298 + excp == 0x1000 ? "I" : excp == 0x1100 ? "DL" : "DS",
  1299 + env->spr[SPR_IMISS], env->spr[SPR_DMISS],
  1300 + env->spr[SPR_ICMP], env->spr[SPR_DCMP],
  1301 + env->spr[SPR_DHASH1], env->spr[SPR_DHASH2],
  1302 + env->error_code);
  1303 + }
1171 1304 #endif
  1305 + /* Swap temporary saved registers with GPRs */
  1306 + tmp = env->gpr[0];
  1307 + env->gpr[0] = env->tgpr[0];
  1308 + env->tgpr[0] = tmp;
  1309 + tmp = env->gpr[1];
  1310 + env->gpr[1] = env->tgpr[1];
  1311 + env->tgpr[1] = tmp;
  1312 + tmp = env->gpr[2];
  1313 + env->gpr[2] = env->tgpr[2];
  1314 + env->tgpr[2] = tmp;
  1315 + tmp = env->gpr[3];
  1316 + env->gpr[3] = env->tgpr[3];
  1317 + env->tgpr[3] = tmp;
  1318 + msr |= env->crf[0] << 28;
  1319 + msr |= env->error_code; /* key, D/I, S/L bits */
  1320 + /* Set way using a LRU mechanism */
  1321 + msr |= (env->last_way ^ 1) << 17;
  1322 + goto store_next;
  1323 + default:
  1324 + cpu_abort(env, "Invalid exception 0x1200 !\n");
  1325 + break;
  1326 + }
  1327 + return;
  1328 + case 0x1300:
  1329 + switch (PPC_EXCP(env)) {
  1330 + case PPC_FLAGS_EXCP_601:
  1331 + case PPC_FLAGS_EXCP_602:
  1332 + case PPC_FLAGS_EXCP_603:
  1333 + case PPC_FLAGS_EXCP_604:
  1334 + case PPC_FLAGS_EXCP_7x0:
  1335 + case PPC_FLAGS_EXCP_7x5:
  1336 + /* IABR on 6xx/7xx */
  1337 + /* XXX: TODO */
  1338 + cpu_abort(env, "IABR exception is not implemented yet !\n");
  1339 + goto store_next;
  1340 + default:
  1341 + cpu_abort(env, "Invalid exception 0x1300 !\n");
  1342 + break;
  1343 + }
  1344 + return;
  1345 + case 0x1400:
  1346 + switch (PPC_EXCP(env)) {
  1347 + case PPC_FLAGS_EXCP_601:
  1348 + case PPC_FLAGS_EXCP_602:
  1349 + case PPC_FLAGS_EXCP_603:
  1350 + case PPC_FLAGS_EXCP_604:
  1351 + case PPC_FLAGS_EXCP_7x0:
  1352 + case PPC_FLAGS_EXCP_7x5:
  1353 + /* SMI on 6xx/7xx */
  1354 + /* XXX: TODO */
  1355 + cpu_abort(env, "SMI exception is not implemented yet !\n");
  1356 + goto store_next;
  1357 + default:
  1358 + cpu_abort(env, "Invalid exception 0x1400 !\n");
  1359 + break;
  1360 + }
  1361 + return;
  1362 + case 0x1500:
  1363 + switch (PPC_EXCP(env)) {
  1364 + case PPC_FLAGS_EXCP_602:
  1365 + /* Watchdog on 602 */
  1366 + cpu_abort(env,
  1367 + "602 watchdog exception is not implemented yet !\n");
  1368 + goto store_next;
  1369 + case PPC_FLAGS_EXCP_970:
  1370 + /* Soft patch exception on 970 */
  1371 + /* XXX: TODO */
  1372 + cpu_abort(env,
  1373 + "970 soft-patch exception is not implemented yet !\n");
  1374 + goto store_next;
  1375 + case PPC_FLAGS_EXCP_74xx:
  1376 + /* VPU assist on 74xx */
  1377 + /* XXX: TODO */
  1378 + cpu_abort(env, "VPU assist exception is not implemented yet !\n");
  1379 + goto store_next;
  1380 + default:
  1381 + cpu_abort(env, "Invalid exception 0x1500 !\n");
  1382 + break;
  1383 + }
  1384 + return;
  1385 + case 0x1600:
  1386 + switch (PPC_EXCP(env)) {
  1387 + case PPC_FLAGS_EXCP_602:
  1388 + /* Emulation trap on 602 */
  1389 + /* XXX: TODO */
  1390 + cpu_abort(env, "602 emulation trap exception "
  1391 + "is not implemented yet !\n");
  1392 + goto store_next;
  1393 + case PPC_FLAGS_EXCP_970:
  1394 + /* Maintenance exception on 970 */
  1395 + /* XXX: TODO */
  1396 + cpu_abort(env,
  1397 + "970 maintenance exception is not implemented yet !\n");
  1398 + goto store_next;
  1399 + default:
  1400 + cpu_abort(env, "Invalid exception 0x1600 !\n");
  1401 + break;
  1402 + }
  1403 + return;
  1404 + case 0x1700:
  1405 + switch (PPC_EXCP(env)) {
  1406 + case PPC_FLAGS_EXCP_7x0:
  1407 + case PPC_FLAGS_EXCP_7x5:
  1408 + /* Thermal management interrupt on G3 */
  1409 + /* XXX: TODO */
  1410 + cpu_abort(env, "G3 thermal management exception "
  1411 + "is not implemented yet !\n");
  1412 + goto store_next;
  1413 + case PPC_FLAGS_EXCP_970:
  1414 + /* VPU assist on 970 */
  1415 + /* XXX: TODO */
  1416 + cpu_abort(env,
  1417 + "970 VPU assist exception is not implemented yet !\n");
  1418 + goto store_next;
  1419 + default:
  1420 + cpu_abort(env, "Invalid exception 0x1700 !\n");
  1421 + break;
  1422 + }
  1423 + return;
  1424 + case 0x1800:
  1425 + switch (PPC_EXCP(env)) {
  1426 + case PPC_FLAGS_EXCP_970:
  1427 + /* Thermal exception on 970 */
  1428 + /* XXX: TODO */
  1429 + cpu_abort(env, "970 thermal management exception "
  1430 + "is not implemented yet !\n");
  1431 + goto store_next;
  1432 + default:
  1433 + cpu_abort(env, "Invalid exception 0x1800 !\n");
  1434 + break;
  1435 + }
  1436 + return;
  1437 + case 0x2000:
  1438 + switch (PPC_EXCP(env)) {
  1439 + case PPC_FLAGS_EXCP_40x:
  1440 + /* DEBUG on 4xx */
  1441 + /* XXX: TODO */
  1442 + cpu_abort(env, "40x debug exception is not implemented yet !\n");
  1443 + goto store_next;
  1444 + case PPC_FLAGS_EXCP_601:
  1445 + /* Run mode exception on 601 */
  1446 + /* XXX: TODO */
  1447 + cpu_abort(env,
  1448 + "601 run mode exception is not implemented yet !\n");
  1449 + goto store_next;
  1450 + default:
  1451 + cpu_abort(env, "Invalid exception 0x1800 !\n");
  1452 + break;
  1453 + }
  1454 + return;
  1455 + /* Other exceptions */
  1456 + /* Qemu internal exceptions:
  1457 + * we should never come here with those values: abort execution
  1458 + */
  1459 + default:
  1460 + cpu_abort(env, "Invalid exception: code %d (%04x)\n", excp, excp);
1172 1461 return;
1173 1462 store_current:
1174   - /* SRR0 is set to current instruction */
1175   - env->spr[SPR_SRR0] = (uint32_t)env->nip - 4;
  1463 + /* save current instruction location */
  1464 + *srr_0 = (env->nip - 4) & 0xFFFFFFFFULL;
1176 1465 break;
1177 1466 store_next:
1178   - /* SRR0 is set to next instruction */
1179   - env->spr[SPR_SRR0] = (uint32_t)env->nip;
  1467 + /* save next instruction location */
  1468 + *srr_0 = env->nip & 0xFFFFFFFFULL;
1180 1469 break;
1181 1470 }
1182   - env->spr[SPR_SRR1] = msr;
  1471 + /* Save msr */
  1472 + *srr_1 = msr;
  1473 + /* If we disactivated any translation, flush TLBs */
  1474 + if (msr_ir || msr_dr) {
  1475 + tlb_flush(env, 1);
  1476 + }
1183 1477 /* reload MSR with correct bits */
1184   - msr_pow = 0;
1185 1478 msr_ee = 0;
1186 1479 msr_pr = 0;
1187 1480 msr_fp = 0;
... ... @@ -1193,14 +1486,11 @@ void do_interrupt (CPUState *env)
1193 1486 msr_dr = 0;
1194 1487 msr_ri = 0;
1195 1488 msr_le = msr_ile;
  1489 + msr_sf = msr_isf;
1196 1490 do_compute_hflags(env);
1197 1491 /* Jump to handler */
1198   - env->nip = excp << 8;
  1492 + env->nip = excp;
1199 1493 env->exception_index = EXCP_NONE;
1200   - /* Invalidate all TLB as we may have changed translation mode */
1201   -#ifdef ACCURATE_TLB_FLUSH
1202   - tlb_flush(env, 1);
1203   -#endif
1204 1494 /* ensure that no TB jump will be modified as
1205 1495 the program flow was changed */
1206 1496 #ifdef __sparc__
... ... @@ -1208,6 +1498,6 @@ void do_interrupt (CPUState *env)
1208 1498 #else
1209 1499 T0 = 0;
1210 1500 #endif
1211   - env->exception_index = -1;
  1501 + env->interrupt_request |= CPU_INTERRUPT_EXITTB;
1212 1502 }
1213 1503 #endif /* !CONFIG_USER_ONLY */
... ...
target-ppc/op.c
... ... @@ -204,16 +204,6 @@ PPC_OP(update_nip)
204 204 env->nip = PARAM(1);
205 205 }
206 206  
207   -PPC_OP(debug)
208   -{
209   - env->nip = PARAM(1);
210   -#if defined (DEBUG_OP)
211   - dump_state();
212   -#endif
213   - do_raise_exception(EXCP_DEBUG);
214   - RETURN();
215   -}
216   -
217 207 /* Segment registers load and store with immediate index */
218 208 PPC_OP(load_srin)
219 209 {
... ... @@ -1384,14 +1374,10 @@ PPC_OP(check_reservation)
1384 1374 /* Return from interrupt */
1385 1375 PPC_OP(rfi)
1386 1376 {
1387   - regs->nip = regs->spr[SPR_SRR0] & ~0x00000003;
1388   -#if 1 // TRY
1389   - T0 = regs->spr[SPR_SRR1] & ~0xFFF00000;
1390   -#else
1391   - T0 = regs->spr[SPR_SRR1] & ~0xFFFF0000;
1392   -#endif
  1377 + env->nip = env->spr[SPR_SRR0] & ~0x00000003;
  1378 + T0 = env->spr[SPR_SRR1] & ~0xFFFF0000UL;
1393 1379 do_store_msr(env, T0);
1394   - do_raise_exception(EXCP_RFI);
  1380 + env->interrupt_request |= CPU_INTERRUPT_EXITTB;
1395 1381 RETURN();
1396 1382 }
1397 1383  
... ...
target-ppc/op_helper.c
... ... @@ -42,12 +42,6 @@ void do_raise_exception_err (uint32_t exception, int error_code)
42 42 printf("Raise exception %3x code : %d\n", exception, error_code);
43 43 #endif
44 44 switch (exception) {
45   - case EXCP_EXTERNAL:
46   - case EXCP_DECR:
47   - printf("DECREMENTER & EXTERNAL exceptions should be hard interrupts !\n");
48   - if (msr_ee == 0)
49   - return;
50   - break;
51 45 case EXCP_PROGRAM:
52 46 if (error_code == EXCP_FP && msr_fe0 == 0 && msr_fe1 == 0)
53 47 return;
... ...
target-ppc/translate.c
... ... @@ -179,6 +179,12 @@ static inline void RET_STOP (DisasContext *ctx)
179 179 RET_EXCP(ctx, EXCP_MTMSR, 0);
180 180 }
181 181  
  182 +static inline void RET_CHG_FLOW (DisasContext *ctx)
  183 +{
  184 + gen_op_raise_exception_err(EXCP_MTMSR, 0);
  185 + ctx->exception = EXCP_MTMSR;
  186 +}
  187 +
182 188 #define GEN_HANDLER(name, opc1, opc2, opc3, inval, type) \
183 189 static void gen_##name (DisasContext *ctx); \
184 190 GEN_OPCODE(name, opc1, opc2, opc3, inval, type); \
... ... @@ -1895,7 +1901,7 @@ GEN_HANDLER(rfi, 0x13, 0x12, 0xFF, 0x03FF8001, PPC_FLOW)
1895 1901 return;
1896 1902 }
1897 1903 gen_op_rfi();
1898   - RET_EXCP(ctx, EXCP_RFI, 0);
  1904 + RET_CHG_FLOW(ctx);
1899 1905 #endif
1900 1906 }
1901 1907  
... ... @@ -2555,7 +2561,8 @@ int gen_intermediate_code_internal (CPUState *env, TranslationBlock *tb,
2555 2561 (msr_se && (ctx.nip < 0x100 ||
2556 2562 ctx.nip > 0xF00 ||
2557 2563 (ctx.nip & 0xFC) != 0x04) &&
2558   - ctx.exception != EXCP_SYSCALL && ctx.exception != EXCP_RFI &&
  2564 + ctx.exception != EXCP_SYSCALL &&
  2565 + ctx.exception != EXCP_SYSCALL_USER &&
2559 2566 ctx.exception != EXCP_TRAP)) {
2560 2567 RET_EXCP(ctxp, EXCP_TRACE, 0);
2561 2568 }
... ...