3838/* Exception processing */
3939static inline void dump_syscall (CPUPPCState * env )
4040{
41- qemu_log_mask (CPU_LOG_INT , "syscall r0=%016" PRIx64 " r3=%016" PRIx64
41+ qemu_log_mask (CPU_LOG_INT , "syscall r0=%016" PRIx64
42+ " r3=%016" PRIx64 " r4=%016" PRIx64 " r5=%016" PRIx64
43+ " r6=%016" PRIx64 " r7=%016" PRIx64 " r8=%016" PRIx64
4244 " r4=%016" PRIx64 " r5=%016" PRIx64 " r6=%016" PRIx64
4345 " nip=" TARGET_FMT_lx "\n" ,
4446 ppc_dump_gpr (env , 0 ), ppc_dump_gpr (env , 3 ),
4547 ppc_dump_gpr (env , 4 ), ppc_dump_gpr (env , 5 ),
46- ppc_dump_gpr (env , 6 ), env -> nip );
48+ ppc_dump_gpr (env , 6 ), ppc_dump_gpr (env , 7 ),
49+ ppc_dump_gpr (env , 8 ), env -> nip );
50+ }
51+
52+ static inline void dump_syscall_vectored (CPUPPCState * env )
53+ {
54+ qemu_log_mask (CPU_LOG_INT , "syscall r0=%016" PRIx64
55+ " r3=%016" PRIx64 " r4=%016" PRIx64 " r5=%016" PRIx64
56+ " r6=%016" PRIx64 " r7=%016" PRIx64 " r8=%016" PRIx64
57+ " nip=" TARGET_FMT_lx "\n" ,
58+ ppc_dump_gpr (env , 0 ), ppc_dump_gpr (env , 3 ),
59+ ppc_dump_gpr (env , 4 ), ppc_dump_gpr (env , 5 ),
60+ ppc_dump_gpr (env , 6 ), ppc_dump_gpr (env , 7 ),
61+ ppc_dump_gpr (env , 8 ), env -> nip );
4762}
4863
4964static int powerpc_reset_wakeup (CPUState * cs , CPUPPCState * env , int excp ,
@@ -53,33 +68,33 @@ static int powerpc_reset_wakeup(CPUState *cs, CPUPPCState *env, int excp,
5368 env -> resume_as_sreset = false;
5469
5570 /* Pretend to be returning from doze always as we don't lose state */
56- * msr |= ( 0x1ull << ( 63 - 47 )) ;
71+ * msr |= SRR1_WS_NOLOSS ;
5772
5873 /* Machine checks are sent normally */
5974 if (excp == POWERPC_EXCP_MCHECK ) {
6075 return excp ;
6176 }
6277 switch (excp ) {
6378 case POWERPC_EXCP_RESET :
64- * msr |= 0x4ull << ( 63 - 45 ) ;
79+ * msr |= SRR1_WAKERESET ;
6580 break ;
6681 case POWERPC_EXCP_EXTERNAL :
67- * msr |= 0x8ull << ( 63 - 45 ) ;
82+ * msr |= SRR1_WAKEEE ;
6883 break ;
6984 case POWERPC_EXCP_DECR :
70- * msr |= 0x6ull << ( 63 - 45 ) ;
85+ * msr |= SRR1_WAKEDEC ;
7186 break ;
7287 case POWERPC_EXCP_SDOOR :
73- * msr |= 0x5ull << ( 63 - 45 ) ;
88+ * msr |= SRR1_WAKEDBELL ;
7489 break ;
7590 case POWERPC_EXCP_SDOOR_HV :
76- * msr |= 0x3ull << ( 63 - 45 ) ;
91+ * msr |= SRR1_WAKEHDBELL ;
7792 break ;
7893 case POWERPC_EXCP_HV_MAINT :
79- * msr |= 0xaull << ( 63 - 45 ) ;
94+ * msr |= SRR1_WAKEHMI ;
8095 break ;
8196 case POWERPC_EXCP_HVIRT :
82- * msr |= 0x9ull << ( 63 - 45 ) ;
97+ * msr |= SRR1_WAKEHVI ;
8398 break ;
8499 default :
85100 cpu_abort (cs , "Unsupported exception %d in Power Save mode\n" ,
@@ -149,7 +164,7 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
149164 CPUState * cs = CPU (cpu );
150165 CPUPPCState * env = & cpu -> env ;
151166 target_ulong msr , new_msr , vector ;
152- int srr0 , srr1 , asrr0 , asrr1 , lev , ail ;
167+ int srr0 , srr1 , asrr0 , asrr1 , lev = -1 , ail ;
153168 bool lpes0 ;
154169
155170 qemu_log_mask (CPU_LOG_INT , "Raise exception at " TARGET_FMT_lx
@@ -388,6 +403,13 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
388403 new_msr |= (target_ulong )MSR_HVB ;
389404 }
390405 break ;
406+ case POWERPC_EXCP_SYSCALL_VECTORED : /* scv exception */
407+ lev = env -> error_code ;
408+ dump_syscall_vectored (env );
409+ env -> nip += 4 ;
410+ new_msr |= env -> msr & ((target_ulong )1 << MSR_EE );
411+ new_msr |= env -> msr & ((target_ulong )1 << MSR_RI );
412+ break ;
391413 case POWERPC_EXCP_FPU : /* Floating-point unavailable exception */
392414 case POWERPC_EXCP_APU : /* Auxiliary processor unavailable */
393415 case POWERPC_EXCP_DECR : /* Decrementer exception */
@@ -476,6 +498,7 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
476498 case POWERPC_EXCP_HDECR : /* Hypervisor decrementer exception */
477499 case POWERPC_EXCP_HDSI : /* Hypervisor data storage exception */
478500 case POWERPC_EXCP_HISI : /* Hypervisor instruction storage exception */
501+ msr |= env -> error_code ;
479502 case POWERPC_EXCP_HDSEG : /* Hypervisor data segment exception */
480503 case POWERPC_EXCP_HISEG : /* Hypervisor instruction segment exception */
481504 case POWERPC_EXCP_SDOOR_HV : /* Hypervisor Doorbell interrupt */
@@ -690,12 +713,6 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
690713 break ;
691714 }
692715
693- /* Save PC */
694- env -> spr [srr0 ] = env -> nip ;
695-
696- /* Save MSR */
697- env -> spr [srr1 ] = msr ;
698-
699716 /* Sanity check */
700717 if (!(env -> msr_mask & MSR_HVB )) {
701718 if (new_msr & MSR_HVB ) {
@@ -708,14 +725,6 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
708725 }
709726 }
710727
711- /* If any alternate SRR register are defined, duplicate saved values */
712- if (asrr0 != -1 ) {
713- env -> spr [asrr0 ] = env -> spr [srr0 ];
714- }
715- if (asrr1 != -1 ) {
716- env -> spr [asrr1 ] = env -> spr [srr1 ];
717- }
718-
719728 /*
720729 * Sort out endianness of interrupt, this differs depending on the
721730 * CPU, the HV mode, etc...
@@ -750,18 +759,6 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
750759 }
751760#endif
752761
753- /* Jump to handler */
754- vector = env -> excp_vectors [excp ];
755- #ifdef _MSC_VER
756- if (vector == (target_ulong )(0ULL - 1ULL )) {
757- #else
758- if (vector == (target_ulong )- 1ULL ) {
759- #endif
760- cpu_abort (cs , "Raised an exception without defined vector %d\n" ,
761- excp );
762- }
763- vector |= env -> excp_prefix ;
764-
765762 /*
766763 * AIL only works if there is no HV transition and we are running
767764 * with translations enabled
@@ -770,10 +767,21 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
770767 ((new_msr & MSR_HVB ) && !(msr & MSR_HVB ))) {
771768 ail = 0 ;
772769 }
773- /* Handle AIL */
774- if (ail ) {
775- new_msr |= (1 << MSR_IR ) | (1 << MSR_DR );
776- vector |= ppc_excp_vector_offset (cs , ail );
770+
771+ vector = env -> excp_vectors [excp ];
772+ if (vector == (target_ulong )- 1ULL ) {
773+ cpu_abort (cs , "Raised an exception without defined vector %d\n" ,
774+ excp );
775+ }
776+
777+ vector |= env -> excp_prefix ;
778+
779+ /* If any alternate SRR register are defined, duplicate saved values */
780+ if (asrr0 != -1 ) {
781+ env -> spr [asrr0 ] = env -> nip ;
782+ }
783+ if (asrr1 != -1 ) {
784+ env -> spr [asrr1 ] = msr ;
777785 }
778786
779787#if defined(TARGET_PPC64 )
@@ -793,6 +801,37 @@ static inline void powerpc_excp(PowerPCCPU *cpu, int excp_model, int excp)
793801 }
794802#endif
795803
804+ if (excp != POWERPC_EXCP_SYSCALL_VECTORED ) {
805+ /* Save PC */
806+ env -> spr [srr0 ] = env -> nip ;
807+
808+ /* Save MSR */
809+ env -> spr [srr1 ] = msr ;
810+
811+ /* Handle AIL */
812+ if (ail ) {
813+ new_msr |= (1 << MSR_IR ) | (1 << MSR_DR );
814+ vector |= ppc_excp_vector_offset (cs , ail );
815+ }
816+
817+ #if defined(TARGET_PPC64 )
818+ } else {
819+ /* scv AIL is a little different */
820+ if (ail ) {
821+ new_msr |= (1 << MSR_IR ) | (1 << MSR_DR );
822+ }
823+ if (ail == AIL_C000_0000_0000_4000 ) {
824+ vector |= 0xc000000000003000ull ;
825+ } else {
826+ vector |= 0x0000000000017000ull ;
827+ }
828+ vector += lev * 0x20 ;
829+
830+ env -> lr = env -> nip ;
831+ env -> ctr = msr ;
832+ #endif
833+ }
834+
796835 powerpc_set_excp_state (cpu , vector , new_msr );
797836}
798837
@@ -954,15 +993,12 @@ static void ppc_hw_interrupt(CPUPPCState *env)
954993 }
955994}
956995
957- void ppc_cpu_do_system_reset (CPUState * cs , target_ulong vector )
996+ void ppc_cpu_do_system_reset (CPUState * cs )
958997{
959998 PowerPCCPU * cpu = POWERPC_CPU (cs );
960999 CPUPPCState * env = & cpu -> env ;
9611000
9621001 powerpc_excp (cpu , env -> excp_model , POWERPC_EXCP_RESET );
963- if (vector != -1 ) {
964- env -> nip = vector ;
965- }
9661002}
9671003
9681004void ppc_cpu_do_fwnmi_machine_check (CPUState * cs , target_ulong vector )
@@ -1135,6 +1171,11 @@ void helper_rfid(CPUPPCState *env)
11351171 do_rfi (env , env -> spr [SPR_SRR0 ], env -> spr [SPR_SRR1 ]);
11361172}
11371173
1174+ void helper_rfscv (CPUPPCState * env )
1175+ {
1176+ do_rfi (env , env -> lr , env -> ctr );
1177+ }
1178+
11381179void helper_hrfid (CPUPPCState * env )
11391180{
11401181 do_rfi (env , env -> spr [SPR_HSRR0 ], env -> spr [SPR_HSRR1 ]);
0 commit comments