Commit 6c36d3fa860b1dfa55de1e8248be6fffcd876f69

Authored by blueswir1
1 parent 4edebb0e

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
exec-all.h
@@ -593,7 +593,11 @@ static inline target_ulong get_phys_addr_code(CPUState *env, target_ulong addr) @@ -593,7 +593,11 @@ static inline target_ulong get_phys_addr_code(CPUState *env, target_ulong addr)
593 } 593 }
594 pd = env->tlb_table[is_user][index].addr_code & ~TARGET_PAGE_MASK; 594 pd = env->tlb_table[is_user][index].addr_code & ~TARGET_PAGE_MASK;
595 if (pd > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) { 595 if (pd > IO_MEM_ROM && !(pd & IO_MEM_ROMD)) {
  596 +#ifdef TARGET_SPARC
  597 + do_unassigned_access(addr, 0, 1, 0);
  598 +#else
596 cpu_abort(env, "Trying to execute code outside RAM or ROM at 0x" TARGET_FMT_lx "\n", addr); 599 cpu_abort(env, "Trying to execute code outside RAM or ROM at 0x" TARGET_FMT_lx "\n", addr);
  600 +#endif
597 } 601 }
598 return addr + env->tlb_table[is_user][index].addend - (unsigned long)phys_ram_base; 602 return addr + env->tlb_table[is_user][index].addend - (unsigned long)phys_ram_base;
599 } 603 }
@@ -1957,11 +1957,10 @@ void qemu_ram_free(ram_addr_t addr) @@ -1957,11 +1957,10 @@ void qemu_ram_free(ram_addr_t addr)
1957 static uint32_t unassigned_mem_readb(void *opaque, target_phys_addr_t addr) 1957 static uint32_t unassigned_mem_readb(void *opaque, target_phys_addr_t addr)
1958 { 1958 {
1959 #ifdef DEBUG_UNASSIGNED 1959 #ifdef DEBUG_UNASSIGNED
1960 - printf("Unassigned mem read 0x%08x\n", (int)addr); 1960 + printf("Unassigned mem read " TARGET_FMT_lx "\n", addr);
1961 #endif 1961 #endif
1962 #ifdef TARGET_SPARC 1962 #ifdef TARGET_SPARC
1963 - // Not enabled yet because of bugs in gdbstub etc.  
1964 - //raise_exception(TT_DATA_ACCESS); 1963 + do_unassigned_access(addr, 0, 0, 0);
1965 #endif 1964 #endif
1966 return 0; 1965 return 0;
1967 } 1966 }
@@ -1969,11 +1968,10 @@ static uint32_t unassigned_mem_readb(void *opaque, target_phys_addr_t addr) @@ -1969,11 +1968,10 @@ static uint32_t unassigned_mem_readb(void *opaque, target_phys_addr_t addr)
1969 static void unassigned_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) 1968 static void unassigned_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val)
1970 { 1969 {
1971 #ifdef DEBUG_UNASSIGNED 1970 #ifdef DEBUG_UNASSIGNED
1972 - printf("Unassigned mem write 0x%08x = 0x%x\n", (int)addr, val); 1971 + printf("Unassigned mem write " TARGET_FMT_lx " = 0x%x\n", addr, val);
1973 #endif 1972 #endif
1974 #ifdef TARGET_SPARC 1973 #ifdef TARGET_SPARC
1975 - // Not enabled yet because of bugs in gdbstub etc.  
1976 - //raise_exception(TT_DATA_ACCESS); 1974 + do_unassigned_access(addr, 1, 0, 0);
1977 #endif 1975 #endif
1978 } 1976 }
1979 1977
target-sparc/cpu.h
@@ -290,6 +290,8 @@ void cpu_set_cwp(CPUSPARCState *env1, int new_cwp); @@ -290,6 +290,8 @@ void cpu_set_cwp(CPUSPARCState *env1, int new_cwp);
290 290
291 int cpu_sparc_signal_handler(int host_signum, void *pinfo, void *puc); 291 int cpu_sparc_signal_handler(int host_signum, void *pinfo, void *puc);
292 void raise_exception(int tt); 292 void raise_exception(int tt);
  293 +void do_unassigned_access(target_ulong addr, int is_write, int is_exec,
  294 + int is_asi);
293 295
294 #include "cpu-all.h" 296 #include "cpu-all.h"
295 297
target-sparc/op_helper.c
@@ -3,6 +3,7 @@ @@ -3,6 +3,7 @@
3 //#define DEBUG_PCALL 3 //#define DEBUG_PCALL
4 //#define DEBUG_MMU 4 //#define DEBUG_MMU
5 //#define DEBUG_UNALIGNED 5 //#define DEBUG_UNALIGNED
  6 +//#define DEBUG_UNASSIGNED
6 7
7 void raise_exception(int tt) 8 void raise_exception(int tt)
8 { 9 {
@@ -151,6 +152,8 @@ void helper_ld_asi(int asi, int size, int sign) @@ -151,6 +152,8 @@ void helper_ld_asi(int asi, int size, int sign)
151 uint32_t ret = 0; 152 uint32_t ret = 0;
152 153
153 switch (asi) { 154 switch (asi) {
  155 + case 2: /* SuperSparc MXCC registers */
  156 + break;
154 case 3: /* MMU probe */ 157 case 3: /* MMU probe */
155 { 158 {
156 int mmulev; 159 int mmulev;
@@ -179,7 +182,30 @@ void helper_ld_asi(int asi, int size, int sign) @@ -179,7 +182,30 @@ void helper_ld_asi(int asi, int size, int sign)
179 #endif 182 #endif
180 } 183 }
181 break; 184 break;
182 - case 0x20 ... 0x2f: /* MMU passthrough */ 185 + case 9: /* Supervisor code access */
  186 + switch(size) {
  187 + case 1:
  188 + ret = ldub_code(T0);
  189 + break;
  190 + case 2:
  191 + ret = lduw_code(T0 & ~1);
  192 + break;
  193 + default:
  194 + case 4:
  195 + ret = ldl_code(T0 & ~3);
  196 + break;
  197 + case 8:
  198 + ret = ldl_code(T0 & ~3);
  199 + T0 = ldl_code((T0 + 4) & ~3);
  200 + break;
  201 + }
  202 + break;
  203 + case 0xc: /* I-cache tag */
  204 + case 0xd: /* I-cache data */
  205 + case 0xe: /* D-cache tag */
  206 + case 0xf: /* D-cache data */
  207 + break;
  208 + case 0x20: /* MMU passthrough */
183 switch(size) { 209 switch(size) {
184 case 1: 210 case 1:
185 ret = ldub_phys(T0); 211 ret = ldub_phys(T0);
@@ -197,7 +223,9 @@ void helper_ld_asi(int asi, int size, int sign) @@ -197,7 +223,9 @@ void helper_ld_asi(int asi, int size, int sign)
197 break; 223 break;
198 } 224 }
199 break; 225 break;
  226 + case 0x21 ... 0x2f: /* MMU passthrough, unassigned */
200 default: 227 default:
  228 + do_unassigned_access(T0, 0, 0, 1);
201 ret = 0; 229 ret = 0;
202 break; 230 break;
203 } 231 }
@@ -207,6 +235,8 @@ void helper_ld_asi(int asi, int size, int sign) @@ -207,6 +235,8 @@ void helper_ld_asi(int asi, int size, int sign)
207 void helper_st_asi(int asi, int size, int sign) 235 void helper_st_asi(int asi, int size, int sign)
208 { 236 {
209 switch(asi) { 237 switch(asi) {
  238 + case 2: /* SuperSparc MXCC registers */
  239 + break;
210 case 3: /* MMU flush */ 240 case 3: /* MMU flush */
211 { 241 {
212 int mmulev; 242 int mmulev;
@@ -271,18 +301,28 @@ void helper_st_asi(int asi, int size, int sign) @@ -271,18 +301,28 @@ void helper_st_asi(int asi, int size, int sign)
271 #endif 301 #endif
272 return; 302 return;
273 } 303 }
  304 + case 0xc: /* I-cache tag */
  305 + case 0xd: /* I-cache data */
  306 + case 0xe: /* D-cache tag */
  307 + case 0xf: /* D-cache data */
  308 + case 0x10: /* I/D-cache flush page */
  309 + case 0x11: /* I/D-cache flush segment */
  310 + case 0x12: /* I/D-cache flush region */
  311 + case 0x13: /* I/D-cache flush context */
  312 + case 0x14: /* I/D-cache flush user */
  313 + break;
274 case 0x17: /* Block copy, sta access */ 314 case 0x17: /* Block copy, sta access */
275 { 315 {
276 // value (T1) = src 316 // value (T1) = src
277 // address (T0) = dst 317 // address (T0) = dst
278 // copy 32 bytes 318 // copy 32 bytes
279 - uint32_t src = T1, dst = T0;  
280 - uint8_t temp[32]; 319 + unsigned int i;
  320 + uint32_t src = T1 & ~3, dst = T0 & ~3, temp;
281 321
282 - tswap32s(&src);  
283 -  
284 - cpu_physical_memory_read(src, (void *) &temp, 32);  
285 - cpu_physical_memory_write(dst, (void *) &temp, 32); 322 + for (i = 0; i < 32; i += 4, src += 4, dst += 4) {
  323 + temp = ldl_kernel(src);
  324 + stl_kernel(dst, temp);
  325 + }
286 } 326 }
287 return; 327 return;
288 case 0x1f: /* Block fill, stda access */ 328 case 0x1f: /* Block fill, stda access */
@@ -290,19 +330,17 @@ void helper_st_asi(int asi, int size, int sign) @@ -290,19 +330,17 @@ void helper_st_asi(int asi, int size, int sign)
290 // value (T1, T2) 330 // value (T1, T2)
291 // address (T0) = dst 331 // address (T0) = dst
292 // fill 32 bytes 332 // fill 32 bytes
293 - int i;  
294 - uint32_t dst = T0;  
295 - uint64_t val;  
296 -  
297 - val = (((uint64_t)T1) << 32) | T2;  
298 - tswap64s(&val); 333 + unsigned int i;
  334 + uint32_t dst = T0 & 7;
  335 + uint64_t val;
299 336
300 - for (i = 0; i < 32; i += 8, dst += 8) {  
301 - cpu_physical_memory_write(dst, (void *) &val, 8);  
302 - } 337 + val = (((uint64_t)T1) << 32) | T2;
  338 +
  339 + for (i = 0; i < 32; i += 8, dst += 8)
  340 + stq_kernel(dst, val);
303 } 341 }
304 return; 342 return;
305 - case 0x20 ... 0x2f: /* MMU passthrough */ 343 + case 0x20: /* MMU passthrough */
306 { 344 {
307 switch(size) { 345 switch(size) {
308 case 1: 346 case 1:
@@ -322,7 +360,14 @@ void helper_st_asi(int asi, int size, int sign) @@ -322,7 +360,14 @@ void helper_st_asi(int asi, int size, int sign)
322 } 360 }
323 } 361 }
324 return; 362 return;
  363 + case 0x31: /* Ross RT620 I-cache flush */
  364 + case 0x36: /* I-cache flash clear */
  365 + case 0x37: /* D-cache flash clear */
  366 + break;
  367 + case 9: /* Supervisor code access, XXX */
  368 + case 0x21 ... 0x2f: /* MMU passthrough, unassigned */
325 default: 369 default:
  370 + do_unassigned_access(T0, 1, 0, 1);
326 return; 371 return;
327 } 372 }
328 } 373 }
@@ -441,6 +486,7 @@ void helper_ld_asi(int asi, int size, int sign) @@ -441,6 +486,7 @@ void helper_ld_asi(int asi, int size, int sign)
441 case 0x5f: // D-MMU demap, WO 486 case 0x5f: // D-MMU demap, WO
442 case 0x77: // Interrupt vector, WO 487 case 0x77: // Interrupt vector, WO
443 default: 488 default:
  489 + do_unassigned_access(T0, 0, 0, 1);
444 ret = 0; 490 ret = 0;
445 break; 491 break;
446 } 492 }
@@ -656,6 +702,7 @@ void helper_st_asi(int asi, int size, int sign) @@ -656,6 +702,7 @@ void helper_st_asi(int asi, int size, int sign)
656 case 0x8a: // Primary no-fault LE, RO 702 case 0x8a: // Primary no-fault LE, RO
657 case 0x8b: // Secondary no-fault LE, RO 703 case 0x8b: // Secondary no-fault LE, RO
658 default: 704 default:
  705 + do_unassigned_access(T0, 1, 0, 1);
659 return; 706 return;
660 } 707 }
661 } 708 }
@@ -986,3 +1033,53 @@ void tlb_fill(target_ulong addr, int is_write, int is_user, void *retaddr) @@ -986,3 +1033,53 @@ void tlb_fill(target_ulong addr, int is_write, int is_user, void *retaddr)
986 } 1033 }
987 1034
988 #endif 1035 #endif
  1036 +
  1037 +#ifndef TARGET_SPARC64
  1038 +void do_unassigned_access(target_ulong addr, int is_write, int is_exec,
  1039 + int is_asi)
  1040 +{
  1041 + CPUState *saved_env;
  1042 +
  1043 + /* XXX: hack to restore env in all cases, even if not called from
  1044 + generated code */
  1045 + saved_env = env;
  1046 + env = cpu_single_env;
  1047 + if (env->mmuregs[3]) /* Fault status register */
  1048 + env->mmuregs[3] = 1; /* overflow (not read before another fault) */
  1049 + if (is_asi)
  1050 + env->mmuregs[3] |= 1 << 16;
  1051 + if (env->psrs)
  1052 + env->mmuregs[3] |= 1 << 5;
  1053 + if (is_exec)
  1054 + env->mmuregs[3] |= 1 << 6;
  1055 + if (is_write)
  1056 + env->mmuregs[3] |= 1 << 7;
  1057 + env->mmuregs[3] |= (5 << 2) | 2;
  1058 + env->mmuregs[4] = addr; /* Fault address register */
  1059 + if ((env->mmuregs[0] & MMU_E) && !(env->mmuregs[0] & MMU_NF)) {
  1060 +#ifdef DEBUG_UNASSIGNED
  1061 + printf("Unassigned mem access to " TARGET_FMT_lx " from " TARGET_FMT_lx
  1062 + "\n", addr, env->pc);
  1063 +#endif
  1064 + raise_exception(TT_DATA_ACCESS);
  1065 + }
  1066 + env = saved_env;
  1067 +}
  1068 +#else
  1069 +void do_unassigned_access(target_ulong addr, int is_write, int is_exec,
  1070 + int is_asi)
  1071 +{
  1072 +#ifdef DEBUG_UNASSIGNED
  1073 + CPUState *saved_env;
  1074 +
  1075 + /* XXX: hack to restore env in all cases, even if not called from
  1076 + generated code */
  1077 + saved_env = env;
  1078 + env = cpu_single_env;
  1079 + printf("Unassigned mem access to " TARGET_FMT_lx " from " TARGET_FMT_lx "\n",
  1080 + addr, env->pc);
  1081 + env = saved_env;
  1082 +#endif
  1083 + raise_exception(TT_DATA_ACCESS);
  1084 +}
  1085 +#endif
target-sparc/translate.c
@@ -3494,6 +3494,8 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr) @@ -3494,6 +3494,8 @@ target_phys_addr_t cpu_get_phys_page_debug(CPUState *env, target_ulong addr)
3494 if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 2, 0) != 0) 3494 if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 2, 0) != 0)
3495 if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 0, 0) != 0) 3495 if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 0, 0) != 0)
3496 return -1; 3496 return -1;
  3497 + if (cpu_get_physical_page_desc(phys_addr) == IO_MEM_UNASSIGNED)
  3498 + return -1;
3497 return phys_addr; 3499 return phys_addr;
3498 } 3500 }
3499 #endif 3501 #endif