linux-user/arm: Handle invalid arm-specific syscalls correctly

The kernel has different handling for syscalls with invalid
numbers that are in the "arm-specific" range 0x9f0000 and up:
 * 0x9f0000..0x9f07ff return -ENOSYS if not implemented
 * other out of range syscalls cause a SIGILL
(see the kernel's arch/arm/kernel/traps.c:arm_syscall())

Implement this distinction. (Note that our code doesn't look
quite like the kernel's, because we have removed the
0x900000 prefix by this point, whereas the kernel retains
it in arm_syscall().)

Signed-off-by: Peter Maydell <peter.maydell@linaro.org>
Reviewed-by: Philippe Mathieu-Daudé <f4bug@amsat.org>
Message-id: 20200420212206.12776-4-peter.maydell@linaro.org
This commit is contained in:
Peter Maydell 2020-04-20 22:22:05 +01:00
parent 62f141a426
commit ab546bd238
1 changed files with 26 additions and 4 deletions

View File

@ -332,10 +332,32 @@ void cpu_loop(CPUARMState *env)
env->regs[0] = cpu_get_tls(env);
break;
default:
qemu_log_mask(LOG_UNIMP,
"qemu: Unsupported ARM syscall: 0x%x\n",
n);
env->regs[0] = -TARGET_ENOSYS;
if (n < 0xf0800) {
/*
* Syscalls 0xf0000..0xf07ff (or 0x9f0000..
* 0x9f07ff in OABI numbering) are defined
* to return -ENOSYS rather than raising
* SIGILL. Note that we have already
* removed the 0x900000 prefix.
*/
qemu_log_mask(LOG_UNIMP,
"qemu: Unsupported ARM syscall: 0x%x\n",
n);
env->regs[0] = -TARGET_ENOSYS;
} else {
/* Otherwise SIGILL */
info.si_signo = TARGET_SIGILL;
info.si_errno = 0;
info.si_code = TARGET_ILL_ILLTRP;
info._sifields._sigfault._addr = env->regs[15];
if (env->thumb) {
info._sifields._sigfault._addr -= 2;
} else {
info._sifields._sigfault._addr -= 4;
}
queue_signal(env, info.si_signo,
QEMU_SI_FAULT, &info);
}
break;
}
} else {