Enable faults for unassigned memory accesses and unimplemented ASIs
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@2824 c046a42c-6fe2-441c-8c8c-71466251a162
This commit is contained in:
		
							parent
							
								
									4edebb0e8e
								
							
						
					
					
						commit
						6c36d3fa86
					
				|  | @ -593,7 +593,11 @@ static inline target_ulong get_phys_addr_code(CPUState *env, target_ulong addr) | |||
|     } | ||||
|     pd = env->tlb_table[is_user][index].addr_code & ~TARGET_PAGE_MASK; | ||||
|     if (pd > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) { | ||||
| #ifdef TARGET_SPARC | ||||
|         do_unassigned_access(addr, 0, 1, 0); | ||||
| #else | ||||
|         cpu_abort(env, "Trying to execute code outside RAM or ROM at 0x" TARGET_FMT_lx "\n", addr); | ||||
| #endif | ||||
|     } | ||||
|     return addr + env->tlb_table[is_user][index].addend - (unsigned long)phys_ram_base; | ||||
| } | ||||
|  |  | |||
							
								
								
									
										10
									
								
								exec.c
								
								
								
								
							
							
						
						
									
										10
									
								
								exec.c
								
								
								
								
							|  | @ -1957,11 +1957,10 @@ void qemu_ram_free(ram_addr_t addr) | |||
| static uint32_t unassigned_mem_readb(void *opaque, target_phys_addr_t addr) | ||||
| { | ||||
| #ifdef DEBUG_UNASSIGNED | ||||
|     printf("Unassigned mem read  0x%08x\n", (int)addr); | ||||
|     printf("Unassigned mem read " TARGET_FMT_lx "\n", addr); | ||||
| #endif | ||||
| #ifdef TARGET_SPARC | ||||
|     // Not enabled yet because of bugs in gdbstub etc.
 | ||||
|     //raise_exception(TT_DATA_ACCESS);
 | ||||
|     do_unassigned_access(addr, 0, 0, 0); | ||||
| #endif | ||||
|     return 0; | ||||
| } | ||||
|  | @ -1969,11 +1968,10 @@ static uint32_t unassigned_mem_readb(void *opaque, target_phys_addr_t addr) | |||
| static void unassigned_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) | ||||
| { | ||||
| #ifdef DEBUG_UNASSIGNED | ||||
|     printf("Unassigned mem write 0x%08x = 0x%x\n", (int)addr, val); | ||||
|     printf("Unassigned mem write " TARGET_FMT_lx " = 0x%x\n", addr, val); | ||||
| #endif | ||||
| #ifdef TARGET_SPARC | ||||
|     // Not enabled yet because of bugs in gdbstub etc.
 | ||||
|     //raise_exception(TT_DATA_ACCESS);
 | ||||
|     do_unassigned_access(addr, 1, 0, 0); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -290,6 +290,8 @@ void cpu_set_cwp(CPUSPARCState *env1, int new_cwp); | |||
| 
 | ||||
| int cpu_sparc_signal_handler(int host_signum, void *pinfo, void *puc); | ||||
| void raise_exception(int tt); | ||||
| void do_unassigned_access(target_ulong addr, int is_write, int is_exec, | ||||
|                           int is_asi); | ||||
| 
 | ||||
| #include "cpu-all.h" | ||||
| 
 | ||||
|  |  | |||
|  | @ -3,6 +3,7 @@ | |||
| //#define DEBUG_PCALL
 | ||||
| //#define DEBUG_MMU
 | ||||
| //#define DEBUG_UNALIGNED
 | ||||
| //#define DEBUG_UNASSIGNED
 | ||||
| 
 | ||||
| void raise_exception(int tt) | ||||
| { | ||||
|  | @ -151,6 +152,8 @@ void helper_ld_asi(int asi, int size, int sign) | |||
|     uint32_t ret = 0; | ||||
| 
 | ||||
|     switch (asi) { | ||||
|     case 2: /* SuperSparc MXCC registers */ | ||||
|         break; | ||||
|     case 3: /* MMU probe */ | ||||
| 	{ | ||||
| 	    int mmulev; | ||||
|  | @ -179,7 +182,30 @@ void helper_ld_asi(int asi, int size, int sign) | |||
| #endif | ||||
| 	} | ||||
| 	break; | ||||
|     case 0x20 ... 0x2f: /* MMU passthrough */ | ||||
|     case 9: /* Supervisor code access */ | ||||
|         switch(size) { | ||||
|         case 1: | ||||
|             ret = ldub_code(T0); | ||||
|             break; | ||||
|         case 2: | ||||
|             ret = lduw_code(T0 & ~1); | ||||
|             break; | ||||
|         default: | ||||
|         case 4: | ||||
|             ret = ldl_code(T0 & ~3); | ||||
|             break; | ||||
|         case 8: | ||||
|             ret = ldl_code(T0 & ~3); | ||||
|             T0 = ldl_code((T0 + 4) & ~3); | ||||
|             break; | ||||
|         } | ||||
|         break; | ||||
|     case 0xc: /* I-cache tag */ | ||||
|     case 0xd: /* I-cache data */ | ||||
|     case 0xe: /* D-cache tag */ | ||||
|     case 0xf: /* D-cache data */ | ||||
|         break; | ||||
|     case 0x20: /* MMU passthrough */ | ||||
|         switch(size) { | ||||
|         case 1: | ||||
|             ret = ldub_phys(T0); | ||||
|  | @ -197,7 +223,9 @@ void helper_ld_asi(int asi, int size, int sign) | |||
| 	    break; | ||||
|         } | ||||
| 	break; | ||||
|     case 0x21 ... 0x2f: /* MMU passthrough, unassigned */ | ||||
|     default: | ||||
|         do_unassigned_access(T0, 0, 0, 1); | ||||
| 	ret = 0; | ||||
| 	break; | ||||
|     } | ||||
|  | @ -207,6 +235,8 @@ void helper_ld_asi(int asi, int size, int sign) | |||
| void helper_st_asi(int asi, int size, int sign) | ||||
| { | ||||
|     switch(asi) { | ||||
|     case 2: /* SuperSparc MXCC registers */ | ||||
|         break; | ||||
|     case 3: /* MMU flush */ | ||||
| 	{ | ||||
| 	    int mmulev; | ||||
|  | @ -271,18 +301,28 @@ void helper_st_asi(int asi, int size, int sign) | |||
| #endif | ||||
| 	    return; | ||||
| 	} | ||||
|     case 0xc: /* I-cache tag */ | ||||
|     case 0xd: /* I-cache data */ | ||||
|     case 0xe: /* D-cache tag */ | ||||
|     case 0xf: /* D-cache data */ | ||||
|     case 0x10: /* I/D-cache flush page */ | ||||
|     case 0x11: /* I/D-cache flush segment */ | ||||
|     case 0x12: /* I/D-cache flush region */ | ||||
|     case 0x13: /* I/D-cache flush context */ | ||||
|     case 0x14: /* I/D-cache flush user */ | ||||
|         break; | ||||
|     case 0x17: /* Block copy, sta access */ | ||||
| 	{ | ||||
| 	    // value (T1) = src
 | ||||
| 	    // address (T0) = dst
 | ||||
| 	    // copy 32 bytes
 | ||||
| 	    uint32_t src = T1, dst = T0; | ||||
| 	    uint8_t temp[32]; | ||||
|             unsigned int i; | ||||
|             uint32_t src = T1 & ~3, dst = T0 & ~3, temp; | ||||
| 	     | ||||
| 	    tswap32s(&src); | ||||
| 
 | ||||
| 	    cpu_physical_memory_read(src, (void *) &temp, 32); | ||||
| 	    cpu_physical_memory_write(dst, (void *) &temp, 32); | ||||
|             for (i = 0; i < 32; i += 4, src += 4, dst += 4) { | ||||
|                 temp = ldl_kernel(src); | ||||
|                 stl_kernel(dst, temp); | ||||
|             } | ||||
| 	} | ||||
| 	return; | ||||
|     case 0x1f: /* Block fill, stda access */ | ||||
|  | @ -290,19 +330,17 @@ void helper_st_asi(int asi, int size, int sign) | |||
| 	    // value (T1, T2)
 | ||||
| 	    // address (T0) = dst
 | ||||
| 	    // fill 32 bytes
 | ||||
| 	    int i; | ||||
| 	    uint32_t dst = T0; | ||||
| 	    uint64_t val; | ||||
| 	     | ||||
| 	    val = (((uint64_t)T1) << 32) | T2; | ||||
| 	    tswap64s(&val); | ||||
|             unsigned int i; | ||||
|             uint32_t dst = T0 & 7; | ||||
|             uint64_t val; | ||||
| 
 | ||||
| 	    for (i = 0; i < 32; i += 8, dst += 8) { | ||||
| 		cpu_physical_memory_write(dst, (void *) &val, 8); | ||||
| 	    } | ||||
|             val = (((uint64_t)T1) << 32) | T2; | ||||
| 
 | ||||
|             for (i = 0; i < 32; i += 8, dst += 8) | ||||
|                 stq_kernel(dst, val); | ||||
| 	} | ||||
| 	return; | ||||
|     case 0x20 ... 0x2f: /* MMU passthrough */ | ||||
|     case 0x20: /* MMU passthrough */ | ||||
| 	{ | ||||
|             switch(size) { | ||||
|             case 1: | ||||
|  | @ -322,7 +360,14 @@ void helper_st_asi(int asi, int size, int sign) | |||
|             } | ||||
| 	} | ||||
| 	return; | ||||
|     case 0x31: /* Ross RT620 I-cache flush */ | ||||
|     case 0x36: /* I-cache flash clear */ | ||||
|     case 0x37: /* D-cache flash clear */ | ||||
|         break; | ||||
|     case 9: /* Supervisor code access, XXX */ | ||||
|     case 0x21 ... 0x2f: /* MMU passthrough, unassigned */ | ||||
|     default: | ||||
|         do_unassigned_access(T0, 1, 0, 1); | ||||
| 	return; | ||||
|     } | ||||
| } | ||||
|  | @ -441,6 +486,7 @@ void helper_ld_asi(int asi, int size, int sign) | |||
|     case 0x5f: // D-MMU demap, WO
 | ||||
|     case 0x77: // Interrupt vector, WO
 | ||||
|     default: | ||||
|         do_unassigned_access(T0, 0, 0, 1); | ||||
| 	ret = 0; | ||||
| 	break; | ||||
|     } | ||||
|  | @ -656,6 +702,7 @@ void helper_st_asi(int asi, int size, int sign) | |||
|     case 0x8a: // Primary no-fault LE, RO
 | ||||
|     case 0x8b: // Secondary no-fault LE, RO
 | ||||
|     default: | ||||
|         do_unassigned_access(T0, 1, 0, 1); | ||||
| 	return; | ||||
|     } | ||||
| } | ||||
|  | @ -986,3 +1033,53 @@ void tlb_fill(target_ulong addr, int is_write, int is_user, void *retaddr) | |||
| } | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| #ifndef TARGET_SPARC64 | ||||
| void do_unassigned_access(target_ulong addr, int is_write, int is_exec, | ||||
|                           int is_asi) | ||||
| { | ||||
|     CPUState *saved_env; | ||||
| 
 | ||||
|     /* XXX: hack to restore env in all cases, even if not called from
 | ||||
|        generated code */ | ||||
|     saved_env = env; | ||||
|     env = cpu_single_env; | ||||
|     if (env->mmuregs[3]) /* Fault status register */ | ||||
| 	env->mmuregs[3] = 1; /* overflow (not read before another fault) */ | ||||
|     if (is_asi) | ||||
|         env->mmuregs[3] |= 1 << 16; | ||||
|     if (env->psrs) | ||||
|         env->mmuregs[3] |= 1 << 5; | ||||
|     if (is_exec) | ||||
|         env->mmuregs[3] |= 1 << 6; | ||||
|     if (is_write) | ||||
|         env->mmuregs[3] |= 1 << 7; | ||||
|     env->mmuregs[3] |= (5 << 2) | 2; | ||||
|     env->mmuregs[4] = addr; /* Fault address register */ | ||||
|     if ((env->mmuregs[0] & MMU_E) && !(env->mmuregs[0] & MMU_NF)) { | ||||
| #ifdef DEBUG_UNASSIGNED | ||||
|         printf("Unassigned mem access to " TARGET_FMT_lx " from " TARGET_FMT_lx | ||||
|                "\n", addr, env->pc); | ||||
| #endif | ||||
|         raise_exception(TT_DATA_ACCESS); | ||||
|     } | ||||
|     env = saved_env; | ||||
| } | ||||
| #else | ||||
| void do_unassigned_access(target_ulong addr, int is_write, int is_exec, | ||||
|                           int is_asi) | ||||
| { | ||||
| #ifdef DEBUG_UNASSIGNED | ||||
|     CPUState *saved_env; | ||||
| 
 | ||||
|     /* XXX: hack to restore env in all cases, even if not called from
 | ||||
|        generated code */ | ||||
|     saved_env = env; | ||||
|     env = cpu_single_env; | ||||
|     printf("Unassigned mem access to " TARGET_FMT_lx " from " TARGET_FMT_lx "\n", | ||||
|            addr, env->pc); | ||||
|     env = saved_env; | ||||
| #endif | ||||
|     raise_exception(TT_DATA_ACCESS); | ||||
| } | ||||
| #endif | ||||
|  |  | |||
|  | @ -3494,6 +3494,8 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr) | |||
|     if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 2, 0) != 0) | ||||
|         if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 0, 0) != 0) | ||||
|             return -1; | ||||
|     if (cpu_get_physical_page_desc(phys_addr) == IO_MEM_UNASSIGNED) | ||||
|         return -1; | ||||
|     return phys_addr; | ||||
| } | ||||
| #endif | ||||
|  |  | |||
		Loading…
	
		Reference in New Issue
	
	 blueswir1
						blueswir1