Commit 355fb23d83aad9ffae376cac09c6b52656e7d083
1 parent
9854bc46
SH usermode fault handling.
git-svn-id: svn://svn.savannah.nongnu.org/qemu/trunk@1988 c046a42c-6fe2-441c-8c8c-71466251a162
Showing
4 changed files
with
81 additions
and
27 deletions
cpu-exec.c
| ... | ... | @@ -1172,19 +1172,14 @@ static inline int handle_cpu_signal(unsigned long pc, unsigned long address, |
| 1172 | 1172 | a virtual CPU fault */ |
| 1173 | 1173 | cpu_restore_state(tb, env, pc, puc); |
| 1174 | 1174 | } |
| 1175 | - if (ret == 1) { | |
| 1176 | 1175 | #if 0 |
| 1177 | 1176 | printf("PF exception: NIP=0x%08x error=0x%x %p\n", |
| 1178 | 1177 | env->nip, env->error_code, tb); |
| 1179 | 1178 | #endif |
| 1180 | 1179 | /* we restore the process signal mask as the sigreturn should |
| 1181 | 1180 | do it (XXX: use sigsetjmp) */ |
| 1182 | - sigprocmask(SIG_SETMASK, old_set, NULL); | |
| 1183 | - // do_raise_exception_err(env->exception_index, env->error_code); | |
| 1184 | - } else { | |
| 1185 | - /* activate soft MMU for this block */ | |
| 1186 | - cpu_resume_from_signal(env, puc); | |
| 1187 | - } | |
| 1181 | + sigprocmask(SIG_SETMASK, old_set, NULL); | |
| 1182 | + cpu_loop_exit(); | |
| 1188 | 1183 | /* never comes here */ |
| 1189 | 1184 | return 1; |
| 1190 | 1185 | } | ... | ... |
linux-user/main.c
| ... | ... | @@ -1362,7 +1362,7 @@ void cpu_loop(CPUMIPSState *env) |
| 1362 | 1362 | void cpu_loop (CPUState *env) |
| 1363 | 1363 | { |
| 1364 | 1364 | int trapnr, ret; |
| 1365 | - // target_siginfo_t info; | |
| 1365 | + target_siginfo_t info; | |
| 1366 | 1366 | |
| 1367 | 1367 | while (1) { |
| 1368 | 1368 | trapnr = cpu_sh4_exec (env); |
| ... | ... | @@ -1380,6 +1380,20 @@ void cpu_loop (CPUState *env) |
| 1380 | 1380 | env->gregs[0x10] = ret; |
| 1381 | 1381 | env->pc += 2; |
| 1382 | 1382 | break; |
| 1383 | + case EXCP_DEBUG: | |
| 1384 | + { | |
| 1385 | + int sig; | |
| 1386 | + | |
| 1387 | + sig = gdb_handlesig (env, TARGET_SIGTRAP); | |
| 1388 | + if (sig) | |
| 1389 | + { | |
| 1390 | + info.si_signo = sig; | |
| 1391 | + info.si_errno = 0; | |
| 1392 | + info.si_code = TARGET_TRAP_BRKPT; | |
| 1393 | + queue_signal(info.si_signo, &info); | |
| 1394 | + } | |
| 1395 | + } | |
| 1396 | + break; | |
| 1383 | 1397 | default: |
| 1384 | 1398 | printf ("Unhandled trap: 0x%x\n", trapnr); |
| 1385 | 1399 | cpu_dump_state(env, stderr, fprintf, 0); | ... | ... |
target-sh4/helper.c
| ... | ... | @@ -28,6 +28,38 @@ |
| 28 | 28 | #include "cpu.h" |
| 29 | 29 | #include "exec-all.h" |
| 30 | 30 | |
| 31 | +#if defined(CONFIG_USER_ONLY) | |
| 32 | + | |
| 33 | +void do_interrupt (CPUState *env) | |
| 34 | +{ | |
| 35 | + env->exception_index = -1; | |
| 36 | +} | |
| 37 | + | |
| 38 | +int cpu_sh4_handle_mmu_fault(CPUState * env, target_ulong address, int rw, | |
| 39 | + int is_user, int is_softmmu) | |
| 40 | +{ | |
| 41 | + env->tea = address; | |
| 42 | + switch (rw) { | |
| 43 | + case 0: | |
| 44 | + env->exception_index = 0x0a0; | |
| 45 | + break; | |
| 46 | + case 1: | |
| 47 | + env->exception_index = 0x0c0; | |
| 48 | + break; | |
| 49 | + case 2: | |
| 50 | + env->exception_index = 0x0a0; | |
| 51 | + break; | |
| 52 | + } | |
| 53 | + return 1; | |
| 54 | +} | |
| 55 | + | |
| 56 | +target_ulong cpu_get_phys_page_debug(CPUState * env, target_ulong addr) | |
| 57 | +{ | |
| 58 | + return addr; | |
| 59 | +} | |
| 60 | + | |
| 61 | +#else /* !CONFIG_USER_ONLY */ | |
| 62 | + | |
| 31 | 63 | #define MMU_OK 0 |
| 32 | 64 | #define MMU_ITLB_MISS (-1) |
| 33 | 65 | #define MMU_ITLB_MULTIPLE (-2) |
| ... | ... | @@ -396,3 +428,14 @@ int cpu_sh4_handle_mmu_fault(CPUState * env, target_ulong address, int rw, |
| 396 | 428 | |
| 397 | 429 | return tlb_set_page(env, address, physical, prot, is_user, is_softmmu); |
| 398 | 430 | } |
| 431 | + | |
| 432 | +target_ulong cpu_get_phys_page_debug(CPUState * env, target_ulong addr) | |
| 433 | +{ | |
| 434 | + target_ulong physical; | |
| 435 | + int prot; | |
| 436 | + | |
| 437 | + get_physical_address(env, &physical, &prot, addr, PAGE_READ, 0); | |
| 438 | + return physical; | |
| 439 | +} | |
| 440 | + | |
| 441 | +#endif | ... | ... |
target-sh4/translate.c
| ... | ... | @@ -144,22 +144,6 @@ CPUSH4State *cpu_sh4_init(void) |
| 144 | 144 | return env; |
| 145 | 145 | } |
| 146 | 146 | |
| 147 | -#ifdef CONFIG_USER_ONLY | |
| 148 | -target_ulong cpu_get_phys_page_debug(CPUState * env, target_ulong addr) | |
| 149 | -{ | |
| 150 | - return addr; | |
| 151 | -} | |
| 152 | -#else | |
| 153 | -target_ulong cpu_get_phys_page_debug(CPUState * env, target_ulong addr) | |
| 154 | -{ | |
| 155 | - target_ulong physical; | |
| 156 | - int prot; | |
| 157 | - | |
| 158 | - get_physical_address(env, &physical, &prot, addr, PAGE_READ, 0); | |
| 159 | - return physical; | |
| 160 | -} | |
| 161 | -#endif | |
| 162 | - | |
| 163 | 147 | static void gen_goto_tb(DisasContext * ctx, int n, target_ulong dest) |
| 164 | 148 | { |
| 165 | 149 | TranslationBlock *tb; |
| ... | ... | @@ -1108,7 +1092,7 @@ int gen_intermediate_code_internal(CPUState * env, TranslationBlock * tb, |
| 1108 | 1092 | target_ulong pc_start; |
| 1109 | 1093 | static uint16_t *gen_opc_end; |
| 1110 | 1094 | uint32_t old_flags; |
| 1111 | - int i; | |
| 1095 | + int i, ii; | |
| 1112 | 1096 | |
| 1113 | 1097 | pc_start = tb->pc; |
| 1114 | 1098 | gen_opc_ptr = gen_opc_buf; |
| ... | ... | @@ -1135,6 +1119,7 @@ int gen_intermediate_code_internal(CPUState * env, TranslationBlock * tb, |
| 1135 | 1119 | } |
| 1136 | 1120 | #endif |
| 1137 | 1121 | |
| 1122 | + ii = -1; | |
| 1138 | 1123 | while ((old_flags & (DELAY_SLOT | DELAY_SLOT_CONDITIONAL)) == 0 && |
| 1139 | 1124 | (ctx.flags & (BRANCH | BRANCH_CONDITIONAL | MODE_CHANGE | |
| 1140 | 1125 | BRANCH_EXCEPTION)) == 0 && |
| ... | ... | @@ -1151,6 +1136,16 @@ int gen_intermediate_code_internal(CPUState * env, TranslationBlock * tb, |
| 1151 | 1136 | } |
| 1152 | 1137 | } |
| 1153 | 1138 | } |
| 1139 | + if (search_pc) { | |
| 1140 | + i = gen_opc_ptr - gen_opc_buf; | |
| 1141 | + if (ii < i) { | |
| 1142 | + ii++; | |
| 1143 | + while (ii < i) | |
| 1144 | + gen_opc_instr_start[ii++] = 0; | |
| 1145 | + } | |
| 1146 | + gen_opc_pc[ii] = ctx.pc; | |
| 1147 | + gen_opc_instr_start[ii] = 1; | |
| 1148 | + } | |
| 1154 | 1149 | #if 0 |
| 1155 | 1150 | fprintf(stderr, "Loading opcode at address 0x%08x\n", ctx.pc); |
| 1156 | 1151 | fflush(stderr); |
| ... | ... | @@ -1192,7 +1187,15 @@ int gen_intermediate_code_internal(CPUState * env, TranslationBlock * tb, |
| 1192 | 1187 | gen_op_debug(); |
| 1193 | 1188 | } |
| 1194 | 1189 | *gen_opc_ptr = INDEX_op_end; |
| 1195 | - tb->size = ctx.pc - pc_start; | |
| 1190 | + if (search_pc) { | |
| 1191 | + i = gen_opc_ptr - gen_opc_buf; | |
| 1192 | + ii++; | |
| 1193 | + while (ii <= i) | |
| 1194 | + gen_opc_instr_start[ii++] = 0; | |
| 1195 | + tb->size = 0; | |
| 1196 | + } else { | |
| 1197 | + tb->size = ctx.pc - pc_start; | |
| 1198 | + } | |
| 1196 | 1199 | |
| 1197 | 1200 | #ifdef DEBUG_DISAS |
| 1198 | 1201 | #ifdef SH4_DEBUG_DISAS |
| ... | ... | @@ -1220,6 +1223,5 @@ int gen_intermediate_code(CPUState * env, struct TranslationBlock *tb) |
| 1220 | 1223 | |
| 1221 | 1224 | int gen_intermediate_code_pc(CPUState * env, struct TranslationBlock *tb) |
| 1222 | 1225 | { |
| 1223 | - assert(0); | |
| 1224 | 1226 | return gen_intermediate_code_internal(env, tb, 1); |
| 1225 | 1227 | } | ... | ... |