mirror of
https://github.com/Motorhead1991/qemu.git
synced 2025-08-11 03:24:58 -06:00
linux-user/arm: Fix identification of syscall numbers
Our code to identify syscall numbers has some issues: * for Thumb mode, we never need the immediate value from the insn, but we always read it anyway * bad immediate values in the svc insn should cause a SIGILL, but we were abort()ing instead (via "goto error") We can fix both these things by refactoring the code that identifies the syscall number to more closely follow the kernel COMPAT_OABI code: * for Thumb it is always r7 * for Arm, if the immediate value is 0, then this is an EABI call with the syscall number in r7 * otherwise, we XOR the immediate value with 0x900000 (ARM_SYSCALL_BASE for QEMU; __NR_OABI_SYSCALL_BASE in the kernel), which converts valid syscall immediates into the desired value, and puts all invalid immediates in the range 0x100000 or above * then we can just let the existing "value too large, deliver SIGILL" case handle invalid numbers, and drop the 'goto error' Signed-off-by: Peter Maydell <peter.maydell@linaro.org> Reviewed-by: Edgar E. Iglesias <edgar.iglesias@xilinx.com> Message-id: 20200420212206.12776-5-peter.maydell@linaro.org
This commit is contained in:
parent
ab546bd238
commit
3986a1721e
1 changed files with 77 additions and 66 deletions
|
@ -299,24 +299,34 @@ void cpu_loop(CPUARMState *env)
|
||||||
env->eabi = 1;
|
env->eabi = 1;
|
||||||
/* system call */
|
/* system call */
|
||||||
if (env->thumb) {
|
if (env->thumb) {
|
||||||
/* FIXME - what to do if get_user() fails? */
|
/* Thumb is always EABI style with syscall number in r7 */
|
||||||
get_user_code_u16(insn, env->regs[15] - 2, env);
|
n = env->regs[7];
|
||||||
n = insn & 0xff;
|
|
||||||
} else {
|
} else {
|
||||||
|
/*
|
||||||
|
* Equivalent of kernel CONFIG_OABI_COMPAT: read the
|
||||||
|
* Arm SVC insn to extract the immediate, which is the
|
||||||
|
* syscall number in OABI.
|
||||||
|
*/
|
||||||
/* FIXME - what to do if get_user() fails? */
|
/* FIXME - what to do if get_user() fails? */
|
||||||
get_user_code_u32(insn, env->regs[15] - 4, env);
|
get_user_code_u32(insn, env->regs[15] - 4, env);
|
||||||
n = insn & 0xffffff;
|
n = insn & 0xffffff;
|
||||||
}
|
if (n == 0) {
|
||||||
|
/* zero immediate: EABI, syscall number in r7 */
|
||||||
if (n == 0 || n >= ARM_SYSCALL_BASE || env->thumb) {
|
|
||||||
/* linux syscall */
|
|
||||||
if (env->thumb || n == 0) {
|
|
||||||
n = env->regs[7];
|
n = env->regs[7];
|
||||||
} else {
|
} else {
|
||||||
n -= ARM_SYSCALL_BASE;
|
/*
|
||||||
|
* This XOR matches the kernel code: an immediate
|
||||||
|
* in the valid range (0x900000 .. 0x9fffff) is
|
||||||
|
* converted into the correct EABI-style syscall
|
||||||
|
* number; invalid immediates end up as values
|
||||||
|
* > 0xfffff and are handled below as out-of-range.
|
||||||
|
*/
|
||||||
|
n ^= ARM_SYSCALL_BASE;
|
||||||
env->eabi = 0;
|
env->eabi = 0;
|
||||||
}
|
}
|
||||||
if ( n > ARM_NR_BASE) {
|
}
|
||||||
|
|
||||||
|
if (n > ARM_NR_BASE) {
|
||||||
switch (n) {
|
switch (n) {
|
||||||
case ARM_NR_cacheflush:
|
case ARM_NR_cacheflush:
|
||||||
/* nop */
|
/* nop */
|
||||||
|
@ -345,7 +355,11 @@ void cpu_loop(CPUARMState *env)
|
||||||
n);
|
n);
|
||||||
env->regs[0] = -TARGET_ENOSYS;
|
env->regs[0] = -TARGET_ENOSYS;
|
||||||
} else {
|
} else {
|
||||||
/* Otherwise SIGILL */
|
/*
|
||||||
|
* Otherwise SIGILL. This includes any SWI with
|
||||||
|
* immediate not originally 0x9fxxxx, because
|
||||||
|
* of the earlier XOR.
|
||||||
|
*/
|
||||||
info.si_signo = TARGET_SIGILL;
|
info.si_signo = TARGET_SIGILL;
|
||||||
info.si_errno = 0;
|
info.si_errno = 0;
|
||||||
info.si_code = TARGET_ILL_ILLTRP;
|
info.si_code = TARGET_ILL_ILLTRP;
|
||||||
|
@ -376,9 +390,6 @@ void cpu_loop(CPUARMState *env)
|
||||||
env->regs[0] = ret;
|
env->regs[0] = ret;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
|
||||||
goto error;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case EXCP_SEMIHOST:
|
case EXCP_SEMIHOST:
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue