target/arm: remove run time semihosting checks
Now we do all our checking and use a common EXCP_SEMIHOST for semihosting operations we can make helper code a lot simpler. Signed-off-by: Alex Bennée <alex.bennee@linaro.org> Reviewed-by: Richard Henderson <richard.henderson@linaro.org> Message-id: 20190913151845.12582-5-alex.bennee@linaro.org Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
This commit is contained in:
parent
5651697f1f
commit
ed6e6ba9c4
|
@ -8352,88 +8352,32 @@ static void arm_cpu_do_interrupt_aarch64(CPUState *cs)
|
|||
new_el, env->pc, pstate_read(env));
|
||||
}
|
||||
|
||||
static inline bool check_for_semihosting(CPUState *cs)
|
||||
{
|
||||
#ifdef CONFIG_TCG
|
||||
/* Check whether this exception is a semihosting call; if so
|
||||
* then handle it and return true; otherwise return false.
|
||||
/*
|
||||
* Do semihosting call and set the appropriate return value. All the
|
||||
* permission and validity checks have been done at translate time.
|
||||
*
|
||||
* We only see semihosting exceptions in TCG only as they are not
|
||||
* trapped to the hypervisor in KVM.
|
||||
*/
|
||||
#ifdef CONFIG_TCG
|
||||
static void handle_semihosting(CPUState *cs)
|
||||
{
|
||||
ARMCPU *cpu = ARM_CPU(cs);
|
||||
CPUARMState *env = &cpu->env;
|
||||
|
||||
if (is_a64(env)) {
|
||||
if (cs->exception_index == EXCP_SEMIHOST) {
|
||||
/* This is always the 64-bit semihosting exception.
|
||||
* The "is this usermode" and "is semihosting enabled"
|
||||
* checks have been done at translate time.
|
||||
*/
|
||||
qemu_log_mask(CPU_LOG_INT,
|
||||
"...handling as semihosting call 0x%" PRIx64 "\n",
|
||||
env->xregs[0]);
|
||||
env->xregs[0] = do_arm_semihosting(env);
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
} else {
|
||||
uint32_t imm;
|
||||
|
||||
/* Only intercept calls from privileged modes, to provide some
|
||||
* semblance of security.
|
||||
*/
|
||||
if (cs->exception_index != EXCP_SEMIHOST &&
|
||||
(!semihosting_enabled() ||
|
||||
((env->uncached_cpsr & CPSR_M) == ARM_CPU_MODE_USR))) {
|
||||
return false;
|
||||
}
|
||||
|
||||
switch (cs->exception_index) {
|
||||
case EXCP_SEMIHOST:
|
||||
/* This is always a semihosting call; the "is this usermode"
|
||||
* and "is semihosting enabled" checks have been done at
|
||||
* translate time.
|
||||
*/
|
||||
break;
|
||||
case EXCP_SWI:
|
||||
/* Check for semihosting interrupt. */
|
||||
if (env->thumb) {
|
||||
imm = arm_lduw_code(env, env->regs[15] - 2, arm_sctlr_b(env))
|
||||
& 0xff;
|
||||
if (imm == 0xab) {
|
||||
break;
|
||||
}
|
||||
} else {
|
||||
imm = arm_ldl_code(env, env->regs[15] - 4, arm_sctlr_b(env))
|
||||
& 0xffffff;
|
||||
if (imm == 0x123456) {
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
case EXCP_BKPT:
|
||||
/* See if this is a semihosting syscall. */
|
||||
if (env->thumb) {
|
||||
imm = arm_lduw_code(env, env->regs[15], arm_sctlr_b(env))
|
||||
& 0xff;
|
||||
if (imm == 0xab) {
|
||||
env->regs[15] += 2;
|
||||
break;
|
||||
}
|
||||
}
|
||||
return false;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
|
||||
qemu_log_mask(CPU_LOG_INT,
|
||||
"...handling as semihosting call 0x%x\n",
|
||||
env->regs[0]);
|
||||
env->regs[0] = do_arm_semihosting(env);
|
||||
return true;
|
||||
}
|
||||
#else
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Handle a CPU exception for A and R profile CPUs.
|
||||
* Do any appropriate logging, handle PSCI calls, and then hand off
|
||||
|
@ -8464,13 +8408,17 @@ void arm_cpu_do_interrupt(CPUState *cs)
|
|||
return;
|
||||
}
|
||||
|
||||
/* Semihosting semantics depend on the register width of the
|
||||
* code that caused the exception, not the target exception level,
|
||||
* so must be handled here.
|
||||
/*
|
||||
* Semihosting semantics depend on the register width of the code
|
||||
* that caused the exception, not the target exception level, so
|
||||
* must be handled here.
|
||||
*/
|
||||
if (check_for_semihosting(cs)) {
|
||||
#ifdef CONFIG_TCG
|
||||
if (cs->exception_index == EXCP_SEMIHOST) {
|
||||
handle_semihosting(cs);
|
||||
return;
|
||||
}
|
||||
#endif
|
||||
|
||||
/* Hooks may change global state so BQL should be held, also the
|
||||
* BQL needs to be held for any modification of
|
||||
|
|
Loading…
Reference in a new issue