Commit 6c36d3fa860b1dfa55de1e8248be6fffcd876f69
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
Showing
5 changed files
with
126 additions
and
23 deletions
exec-all.h
... | ... | @@ -593,7 +593,11 @@ static inline target_ulong get_phys_addr_code(CPUState *env, target_ulong addr) |
593 | 593 | } |
594 | 594 | pd = env->tlb_table[is_user][index].addr_code & ~TARGET_PAGE_MASK; |
595 | 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 | 599 | cpu_abort(env, "Trying to execute code outside RAM or ROM at 0x" TARGET_FMT_lx "\n", addr); |
600 | +#endif | |
597 | 601 | } |
598 | 602 | return addr + env->tlb_table[is_user][index].addend - (unsigned long)phys_ram_base; |
599 | 603 | } | ... | ... |
exec.c
... | ... | @@ -1957,11 +1957,10 @@ void qemu_ram_free(ram_addr_t addr) |
1957 | 1957 | static uint32_t unassigned_mem_readb(void *opaque, target_phys_addr_t addr) |
1958 | 1958 | { |
1959 | 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 | 1961 | #endif |
1962 | 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 | 1964 | #endif |
1966 | 1965 | return 0; |
1967 | 1966 | } |
... | ... | @@ -1969,11 +1968,10 @@ static uint32_t unassigned_mem_readb(void *opaque, target_phys_addr_t addr) |
1969 | 1968 | static void unassigned_mem_writeb(void *opaque, target_phys_addr_t addr, uint32_t val) |
1970 | 1969 | { |
1971 | 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 | 1972 | #endif |
1974 | 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 | 1975 | #endif |
1978 | 1976 | } |
1979 | 1977 | ... | ... |
target-sparc/cpu.h
... | ... | @@ -290,6 +290,8 @@ void cpu_set_cwp(CPUSPARCState *env1, int new_cwp); |
290 | 290 | |
291 | 291 | int cpu_sparc_signal_handler(int host_signum, void *pinfo, void *puc); |
292 | 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 | 296 | #include "cpu-all.h" |
295 | 297 | ... | ... |
target-sparc/op_helper.c
... | ... | @@ -3,6 +3,7 @@ |
3 | 3 | //#define DEBUG_PCALL |
4 | 4 | //#define DEBUG_MMU |
5 | 5 | //#define DEBUG_UNALIGNED |
6 | +//#define DEBUG_UNASSIGNED | |
6 | 7 | |
7 | 8 | void raise_exception(int tt) |
8 | 9 | { |
... | ... | @@ -151,6 +152,8 @@ void helper_ld_asi(int asi, int size, int sign) |
151 | 152 | uint32_t ret = 0; |
152 | 153 | |
153 | 154 | switch (asi) { |
155 | + case 2: /* SuperSparc MXCC registers */ | |
156 | + break; | |
154 | 157 | case 3: /* MMU probe */ |
155 | 158 | { |
156 | 159 | int mmulev; |
... | ... | @@ -179,7 +182,30 @@ void helper_ld_asi(int asi, int size, int sign) |
179 | 182 | #endif |
180 | 183 | } |
181 | 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 | 209 | switch(size) { |
184 | 210 | case 1: |
185 | 211 | ret = ldub_phys(T0); |
... | ... | @@ -197,7 +223,9 @@ void helper_ld_asi(int asi, int size, int sign) |
197 | 223 | break; |
198 | 224 | } |
199 | 225 | break; |
226 | + case 0x21 ... 0x2f: /* MMU passthrough, unassigned */ | |
200 | 227 | default: |
228 | + do_unassigned_access(T0, 0, 0, 1); | |
201 | 229 | ret = 0; |
202 | 230 | break; |
203 | 231 | } |
... | ... | @@ -207,6 +235,8 @@ void helper_ld_asi(int asi, int size, int sign) |
207 | 235 | void helper_st_asi(int asi, int size, int sign) |
208 | 236 | { |
209 | 237 | switch(asi) { |
238 | + case 2: /* SuperSparc MXCC registers */ | |
239 | + break; | |
210 | 240 | case 3: /* MMU flush */ |
211 | 241 | { |
212 | 242 | int mmulev; |
... | ... | @@ -271,18 +301,28 @@ void helper_st_asi(int asi, int size, int sign) |
271 | 301 | #endif |
272 | 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 | 314 | case 0x17: /* Block copy, sta access */ |
275 | 315 | { |
276 | 316 | // value (T1) = src |
277 | 317 | // address (T0) = dst |
278 | 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 | 327 | return; |
288 | 328 | case 0x1f: /* Block fill, stda access */ |
... | ... | @@ -290,19 +330,17 @@ void helper_st_asi(int asi, int size, int sign) |
290 | 330 | // value (T1, T2) |
291 | 331 | // address (T0) = dst |
292 | 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 | 342 | return; |
305 | - case 0x20 ... 0x2f: /* MMU passthrough */ | |
343 | + case 0x20: /* MMU passthrough */ | |
306 | 344 | { |
307 | 345 | switch(size) { |
308 | 346 | case 1: |
... | ... | @@ -322,7 +360,14 @@ void helper_st_asi(int asi, int size, int sign) |
322 | 360 | } |
323 | 361 | } |
324 | 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 | 369 | default: |
370 | + do_unassigned_access(T0, 1, 0, 1); | |
326 | 371 | return; |
327 | 372 | } |
328 | 373 | } |
... | ... | @@ -441,6 +486,7 @@ void helper_ld_asi(int asi, int size, int sign) |
441 | 486 | case 0x5f: // D-MMU demap, WO |
442 | 487 | case 0x77: // Interrupt vector, WO |
443 | 488 | default: |
489 | + do_unassigned_access(T0, 0, 0, 1); | |
444 | 490 | ret = 0; |
445 | 491 | break; |
446 | 492 | } |
... | ... | @@ -656,6 +702,7 @@ void helper_st_asi(int asi, int size, int sign) |
656 | 702 | case 0x8a: // Primary no-fault LE, RO |
657 | 703 | case 0x8b: // Secondary no-fault LE, RO |
658 | 704 | default: |
705 | + do_unassigned_access(T0, 1, 0, 1); | |
659 | 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 | 1033 | } |
987 | 1034 | |
988 | 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 | 3494 | if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 2, 0) != 0) |
3495 | 3495 | if (get_physical_address(env, &phys_addr, &prot, &access_index, addr, 0, 0) != 0) |
3496 | 3496 | return -1; |
3497 | + if (cpu_get_physical_page_desc(phys_addr) == IO_MEM_UNASSIGNED) | |
3498 | + return -1; | |
3497 | 3499 | return phys_addr; |
3498 | 3500 | } |
3499 | 3501 | #endif | ... | ... |