linux-user: Add cpu loop for AArch64
Add the main linux-user cpu loop for AArch64. Since AArch64 has a different system call interface, doesn't need to worry about FPA emulation and may in the future keep the prefetch/data abort information in different system registers, it's simplest just to use a completely separate loop from the 32 bit ARM target, rather than peppering it with ifdefs. Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Message-id: 1378235544-22290-14-git-send-email-peter.maydell@linaro.org
This commit is contained in:
		
							parent
							
								
									067d983127
								
							
						
					
					
						commit
						1861c4543f
					
				| @ -449,6 +449,9 @@ void cpu_loop(CPUX86State *env) | ||||
|         __r;                                            \ | ||||
|     }) | ||||
| 
 | ||||
| #ifdef TARGET_ABI32 | ||||
| /* Commpage handling -- there is no commpage for AArch64 */ | ||||
| 
 | ||||
| /*
 | ||||
|  * See the Linux kernel's Documentation/arm/kernel_user_helpers.txt | ||||
|  * Input: | ||||
| @ -582,6 +585,7 @@ do_kernel_trap(CPUARMState *env) | ||||
| 
 | ||||
|     return 0; | ||||
| } | ||||
| #endif | ||||
| 
 | ||||
| static int do_strex(CPUARMState *env) | ||||
| { | ||||
| @ -661,6 +665,7 @@ done: | ||||
|     return segv; | ||||
| } | ||||
| 
 | ||||
| #ifdef TARGET_ABI32 | ||||
| void cpu_loop(CPUARMState *env) | ||||
| { | ||||
|     CPUState *cs = CPU(arm_env_get_cpu(env)); | ||||
| @ -873,6 +878,83 @@ void cpu_loop(CPUARMState *env) | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| #else | ||||
| 
 | ||||
| /* AArch64 main loop */ | ||||
| void cpu_loop(CPUARMState *env) | ||||
| { | ||||
|     CPUState *cs = CPU(arm_env_get_cpu(env)); | ||||
|     int trapnr, sig; | ||||
|     target_siginfo_t info; | ||||
|     uint32_t addr; | ||||
| 
 | ||||
|     for (;;) { | ||||
|         cpu_exec_start(cs); | ||||
|         trapnr = cpu_arm_exec(env); | ||||
|         cpu_exec_end(cs); | ||||
| 
 | ||||
|         switch (trapnr) { | ||||
|         case EXCP_SWI: | ||||
|             env->xregs[0] = do_syscall(env, | ||||
|                                        env->xregs[8], | ||||
|                                        env->xregs[0], | ||||
|                                        env->xregs[1], | ||||
|                                        env->xregs[2], | ||||
|                                        env->xregs[3], | ||||
|                                        env->xregs[4], | ||||
|                                        env->xregs[5], | ||||
|                                        0, 0); | ||||
|             break; | ||||
|         case EXCP_INTERRUPT: | ||||
|             /* just indicate that signals should be handled asap */ | ||||
|             break; | ||||
|         case EXCP_UDEF: | ||||
|             info.si_signo = SIGILL; | ||||
|             info.si_errno = 0; | ||||
|             info.si_code = TARGET_ILL_ILLOPN; | ||||
|             info._sifields._sigfault._addr = env->pc; | ||||
|             queue_signal(env, info.si_signo, &info); | ||||
|             break; | ||||
|         case EXCP_PREFETCH_ABORT: | ||||
|             addr = env->cp15.c6_insn; | ||||
|             goto do_segv; | ||||
|         case EXCP_DATA_ABORT: | ||||
|             addr = env->cp15.c6_data; | ||||
|         do_segv: | ||||
|             info.si_signo = SIGSEGV; | ||||
|             info.si_errno = 0; | ||||
|             /* XXX: check env->error_code */ | ||||
|             info.si_code = TARGET_SEGV_MAPERR; | ||||
|             info._sifields._sigfault._addr = addr; | ||||
|             queue_signal(env, info.si_signo, &info); | ||||
|             break; | ||||
|         case EXCP_DEBUG: | ||||
|         case EXCP_BKPT: | ||||
|             sig = gdb_handlesig(cs, TARGET_SIGTRAP); | ||||
|             if (sig) { | ||||
|                 info.si_signo = sig; | ||||
|                 info.si_errno = 0; | ||||
|                 info.si_code = TARGET_TRAP_BRKPT; | ||||
|                 queue_signal(env, info.si_signo, &info); | ||||
|             } | ||||
|             break; | ||||
|         case EXCP_STREX: | ||||
|             if (do_strex(env)) { | ||||
|                 addr = env->cp15.c6_data; | ||||
|                 goto do_segv; | ||||
|             } | ||||
|             break; | ||||
|         default: | ||||
|             fprintf(stderr, "qemu: unhandled CPU exception 0x%x - aborting\n", | ||||
|                     trapnr); | ||||
|             cpu_dump_state(cs, stderr, fprintf, 0); | ||||
|             abort(); | ||||
|         } | ||||
|         process_pending_signals(env); | ||||
|     } | ||||
| } | ||||
| #endif /* ndef TARGET_ABI32 */ | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| #ifdef TARGET_UNICORE32 | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user
	 Peter Maydell
						Peter Maydell