qemu with hax to log dma reads & writes jcs.org/2018/11/12/vfio

target/arm: only update pc after semihosting completes

Before we introduce blocking semihosting calls we need to ensure we
can restart the system on semi hosting exception. To be able to do
this the EXCP_SEMIHOST operation should be idempotent until it finally
completes. Practically this means ensureing we only update the pc
after the semihosting call has completed.

Signed-off-by: Alex Bennée <alex.bennee@linaro.org>
Reviewed-by: Richard Henderson <richard.henderson@linaro.org>
Reviewed-by: Keith Packard <keithp@keithp.com>
Tested-by: Keith Packard <keithp@keithp.com>

+9 -4
+1
linux-user/aarch64/cpu_loop.c
··· 130 130 break; 131 131 case EXCP_SEMIHOST: 132 132 env->xregs[0] = do_arm_semihosting(env); 133 + env->pc += 4; 133 134 break; 134 135 case EXCP_YIELD: 135 136 /* nothing to do here for user-mode, just resume guest code */
+1
linux-user/arm/cpu_loop.c
··· 377 377 break; 378 378 case EXCP_SEMIHOST: 379 379 env->regs[0] = do_arm_semihosting(env); 380 + env->regs[15] += env->thumb ? 2 : 4; 380 381 break; 381 382 case EXCP_INTERRUPT: 382 383 /* just indicate that signals should be handled asap */
+2
target/arm/helper.c
··· 8614 8614 "...handling as semihosting call 0x%" PRIx64 "\n", 8615 8615 env->xregs[0]); 8616 8616 env->xregs[0] = do_arm_semihosting(env); 8617 + env->pc += 4; 8617 8618 } else { 8618 8619 qemu_log_mask(CPU_LOG_INT, 8619 8620 "...handling as semihosting call 0x%x\n", 8620 8621 env->regs[0]); 8621 8622 env->regs[0] = do_arm_semihosting(env); 8623 + env->regs[15] += env->thumb ? 2 : 4; 8622 8624 } 8623 8625 } 8624 8626 #endif
+1
target/arm/m_helper.c
··· 2185 2185 "...handling as semihosting call 0x%x\n", 2186 2186 env->regs[0]); 2187 2187 env->regs[0] = do_arm_semihosting(env); 2188 + env->regs[15] += env->thumb ? 2 : 4; 2188 2189 return; 2189 2190 case EXCP_BKPT: 2190 2191 armv7m_nvic_set_pending(env->nvic, ARMV7M_EXCP_DEBUG, false);
+1 -1
target/arm/translate-a64.c
··· 1937 1937 break; 1938 1938 } 1939 1939 #endif 1940 - gen_exception_internal_insn(s, s->base.pc_next, EXCP_SEMIHOST); 1940 + gen_exception_internal_insn(s, s->pc_curr, EXCP_SEMIHOST); 1941 1941 } else { 1942 1942 unsupported_encoding(s, insn); 1943 1943 }
+3 -3
target/arm/translate.c
··· 1124 1124 s->current_el != 0 && 1125 1125 #endif 1126 1126 (imm == (s->thumb ? 0x3c : 0xf000))) { 1127 - gen_exception_internal_insn(s, s->base.pc_next, EXCP_SEMIHOST); 1127 + gen_exception_internal_insn(s, s->pc_curr, EXCP_SEMIHOST); 1128 1128 return; 1129 1129 } 1130 1130 ··· 8457 8457 !IS_USER(s) && 8458 8458 #endif 8459 8459 (a->imm == 0xab)) { 8460 - gen_exception_internal_insn(s, s->base.pc_next, EXCP_SEMIHOST); 8460 + gen_exception_internal_insn(s, s->pc_curr, EXCP_SEMIHOST); 8461 8461 } else { 8462 8462 gen_exception_bkpt_insn(s, syn_aa32_bkpt(a->imm, false)); 8463 8463 } ··· 10266 10266 !IS_USER(s) && 10267 10267 #endif 10268 10268 (a->imm == semihost_imm)) { 10269 - gen_exception_internal_insn(s, s->base.pc_next, EXCP_SEMIHOST); 10269 + gen_exception_internal_insn(s, s->pc_curr, EXCP_SEMIHOST); 10270 10270 } else { 10271 10271 gen_set_pc_im(s, s->base.pc_next); 10272 10272 s->svc_imm = a->imm;