From e404c06a2da3d65e6c0a899fb70f7ae94c86dd38 Mon Sep 17 00:00:00 2001 From: Denis Drakhnya Date: Fri, 12 Feb 2021 16:08:06 +0200 Subject: [PATCH] e2k: Fix syscall restart. We cannot just change the IP address in E2K to restart the instruction because the same register can be read and written in the same instruction (and many more situations), but we can create a fake syscall instruction and restart it. Signed-off-by: Denis Drakhnya --- linux-user/e2k/cpu_loop.c | 12 ++++++------ target/e2k/translate.c | 1 - 2 files changed, 6 insertions(+), 7 deletions(-) diff --git a/linux-user/e2k/cpu_loop.c b/linux-user/e2k/cpu_loop.c index d9adfeca5c..7f1c8df12e 100644 --- a/linux-user/e2k/cpu_loop.c +++ b/linux-user/e2k/cpu_loop.c @@ -47,18 +47,18 @@ void cpu_loop(CPUE2KState *env) // TODO: check what happens if env->wd.size is zero memcpy(args, env->regs, psize * sizeof(args[0])); - do { - ret = do_syscall(env, args[0], args[1], args[2], args[3], - args[4], args[5], args[6], args[7], args[8]); - // FIXME: I don't know how to properly handle syscall restart - } while (ret == -TARGET_ERESTARTSYS); + ret = do_syscall(env, args[0], args[1], args[2], args[3], + args[4], args[5], args[6], args[7], args[8]); - if (ret != -TARGET_QEMU_ESIGRETURN && env->wd.psize > 0) { + if (ret == -QEMU_ERESTARTSYS) { + /* do not set sysret address and syscall will be restarted */ + } else if (ret != -QEMU_ESIGRETURN && env->wd.psize > 0) { memset(env->tags, E2K_TAG_NON_NUMBER64, psize * sizeof(env->tags[0])); env->regs[0] = ret; env->tags[0] = E2K_TAG_NUMBER64; + env->ip = E2K_SYSRET_ADDR; } break; } diff --git a/target/e2k/translate.c b/target/e2k/translate.c index 88ee336abc..ed7d4fa29a 100644 --- a/target/e2k/translate.c +++ b/target/e2k/translate.c @@ -1158,7 +1158,6 @@ static void e2k_tr_translate_insn(DisasContextBase *db, CPUState *cs) ctx->base.is_jmp = DISAS_NORETURN; /* force non-zero tb size */ pc_next = ctx->base.pc_next + 8; - e2k_gen_save_pc(E2K_SYSRET_ADDR); gen_helper_syscall(cpu_env); tcg_gen_exit_tb(NULL, TB_EXIT_IDX0); break;