From patchwork Fri Jul 1 17:04:33 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 9210259 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id E4941607D6 for ; Fri, 1 Jul 2016 17:18:56 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id D15EC28531 for ; Fri, 1 Jul 2016 17:18:56 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id C6440286A4; Fri, 1 Jul 2016 17:18:56 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-6.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=ham version=3.3.1 Received: from lists.gnu.org (lists.gnu.org [208.118.235.17]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by mail.wl.linuxfoundation.org (Postfix) with ESMTPS id E1C6E28531 for ; Fri, 1 Jul 2016 17:18:55 +0000 (UTC) Received: from localhost ([::1]:34684 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bJ25e-0002Fs-Gu for patchwork-qemu-devel@patchwork.kernel.org; Fri, 01 Jul 2016 13:18:54 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:53560) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bJ1sH-0002CT-FH for qemu-devel@nongnu.org; Fri, 01 Jul 2016 13:05:06 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bJ1sE-0005M5-NW for qemu-devel@nongnu.org; Fri, 01 Jul 2016 13:05:04 -0400 Received: from mail-pf0-x241.google.com ([2607:f8b0:400e:c00::241]:32960) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bJ1sE-0005Lg-Cg for qemu-devel@nongnu.org; Fri, 01 Jul 2016 13:05:02 -0400 Received: by mail-pf0-x241.google.com with SMTP id c74so10476957pfb.0 for ; Fri, 01 Jul 2016 10:05:02 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=sender:from:to:cc:subject:date:message-id:in-reply-to:references; bh=S7iWZgUqayclWfUIqq8iACremLh9iOglkaZeFzbDG0k=; b=Vu82D2JbDgbaRnSCjOBNONWTY4y9Hx80Rtzc09g3EbA2TL2Fyq/P8Deg9yfP2ibmcL AFAPdZlvQChCl5o2BZwWm9GFBCYk5OCzInE3JJGipzVLfrRMA1KA3ddizu2DRxJzm23a /Ms+CR9/FoLK26h/R63jCo767mT4t4R+Vw9kIV8mY5nRtaV/ujNzDBWCJzQ6WBiEmNF3 SAz9+zU4OumHu5dCmYe6+o1sq+eUWpyd+e3pnH8xQqAyyd3njBdzTy8JVMaCLYY3pJJf 3DGLCRSJNo4beCSZxkhUaYEKl79mxC8FVoyKwIz/7TtmhxbJJv4mIZLndXksxjHn7gDg PHFA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20130820; h=x-gm-message-state:sender:from:to:cc:subject:date:message-id :in-reply-to:references; bh=S7iWZgUqayclWfUIqq8iACremLh9iOglkaZeFzbDG0k=; b=RBDvr47JirHDdmluRFHlDNmVUhJhCR3BMaeOIXuy1V/qrXP46FTEgSxsto7lq4MuQs +jtW823jtAQqFRtQLhWAElEbWQJVlB0vqEVIUBaluso96KmAVCnjtyMqdthTREZ+n/qJ 2bohjwb6AFCiDPgbnuyjcDs74wkL92EMVxerZd41Q7Xy7WsXpZjO7mv21YbQFbHJFqOD yXXnKVYVoy2sHvmyize9T4Xjy44jfzT14Knnq4SPl+wS79cxzQRQhE+4jOvrBd9nyi17 Kxn02vodXSK0/zPr+Pz8zML8osod0ZoK/4397nYF/NB8BqqNbROUw7odcoAzcwv1TgCN lE3A== X-Gm-Message-State: ALyK8tJYd0gJJqrbIxdQEdptVNqdKbtIdmqYf8pVRZSbTeKuOjvlcGua29WS/g7Al7KdnQ== X-Received: by 10.98.111.138 with SMTP id k132mr33260517pfc.105.1467392701290; Fri, 01 Jul 2016 10:05:01 -0700 (PDT) Received: from bigtime.twiddle.net (71-37-54-227.tukw.qwest.net. [71.37.54.227]) by smtp.gmail.com with ESMTPSA id ff9sm2652229pac.5.2016.07.01.10.05.00 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Fri, 01 Jul 2016 10:05:00 -0700 (PDT) From: Richard Henderson To: qemu-devel@nongnu.org Date: Fri, 1 Jul 2016 10:04:33 -0700 Message-Id: <1467392693-22715-8-git-send-email-rth@twiddle.net> X-Mailer: git-send-email 2.5.5 In-Reply-To: <1467392693-22715-1-git-send-email-rth@twiddle.net> References: <1467392693-22715-1-git-send-email-rth@twiddle.net> X-detected-operating-system: by eggs.gnu.org: GNU/Linux 2.2.x-3.x [generic] X-Received-From: 2607:f8b0:400e:c00::241 Subject: [Qemu-devel] [PATCH v2 07/27] tcg: Add EXCP_ATOMIC X-BeenThere: qemu-devel@nongnu.org X-Mailman-Version: 2.1.21 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Cc: pbonzini@redhat.com, serge.fdrv@gmail.com, cota@braap.org, alex.bennee@linaro.org, peter.maydell@linaro.org Errors-To: qemu-devel-bounces+patchwork-qemu-devel=patchwork.kernel.org@nongnu.org Sender: "Qemu-devel" X-Virus-Scanned: ClamAV using ClamSMTP When we cannot emulate an atomic operation within a parallel context, this exception allows us to stop the world and try again in a serial context. Signed-off-by: Richard Henderson --- cpu-exec-common.c | 6 +++++ cpu-exec.c | 23 +++++++++++++++++++ cpus.c | 6 +++++ include/exec/cpu-all.h | 1 + include/exec/exec-all.h | 1 + include/qemu-common.h | 1 + linux-user/main.c | 59 ++++++++++++++++++++++++++++++++++++++++++++++++- tcg/tcg.h | 1 + translate-all.c | 1 + 9 files changed, 98 insertions(+), 1 deletion(-) diff --git a/cpu-exec-common.c b/cpu-exec-common.c index 0cb4ae6..767d9c6 100644 --- a/cpu-exec-common.c +++ b/cpu-exec-common.c @@ -77,3 +77,9 @@ void cpu_loop_exit_restore(CPUState *cpu, uintptr_t pc) } siglongjmp(cpu->jmp_env, 1); } + +void cpu_loop_exit_atomic(CPUState *cpu, uintptr_t pc) +{ + cpu->exception_index = EXCP_ATOMIC; + cpu_loop_exit_restore(cpu, pc); +} diff --git a/cpu-exec.c b/cpu-exec.c index b840e1d..041f8b7 100644 --- a/cpu-exec.c +++ b/cpu-exec.c @@ -225,6 +225,29 @@ static void cpu_exec_nocache(CPUState *cpu, int max_cycles, } #endif +void cpu_exec_step(CPUState *cpu) +{ + CPUArchState *env = (CPUArchState *)cpu->env_ptr; + TranslationBlock *tb; + target_ulong cs_base, pc; + uint32_t flags; + bool old_tb_flushed; + + old_tb_flushed = cpu->tb_flushed; + cpu->tb_flushed = false; + + cpu_get_tb_cpu_state(env, &pc, &cs_base, &flags); + tb = tb_gen_code(cpu, pc, cs_base, flags, + 1 | CF_NOCACHE | CF_IGNORE_ICOUNT); + tb->orig_tb = NULL; + cpu->tb_flushed |= old_tb_flushed; + /* execute the generated code */ + trace_exec_tb_nocache(tb, pc); + cpu_tb_exec(cpu, tb); + tb_phys_invalidate(tb, -1); + tb_free(tb); +} + struct tb_desc { target_ulong pc; target_ulong cs_base; diff --git a/cpus.c b/cpus.c index 84c3520..a01bbbd 100644 --- a/cpus.c +++ b/cpus.c @@ -1575,6 +1575,12 @@ static void tcg_exec_all(void) if (r == EXCP_DEBUG) { cpu_handle_guest_debug(cpu); break; + } else if (r == EXCP_ATOMIC) { + /* ??? When we begin running cpus in parallel, we should + stop all cpus, clear parallel_cpus, and interpret a + single insn with cpu_exec_step. In the meantime, + we should never get here. */ + abort(); } } else if (cpu->stop || cpu->stopped) { if (cpu->unplug) { diff --git a/include/exec/cpu-all.h b/include/exec/cpu-all.h index 8007abb..d2aac4b 100644 --- a/include/exec/cpu-all.h +++ b/include/exec/cpu-all.h @@ -31,6 +31,7 @@ #define EXCP_DEBUG 0x10002 /* cpu stopped after a breakpoint or singlestep */ #define EXCP_HALTED 0x10003 /* cpu is halted (waiting for external event) */ #define EXCP_YIELD 0x10004 /* cpu wants to yield timeslice to another */ +#define EXCP_ATOMIC 0x10005 /* stop-the-world and emulate atomic */ /* some important defines: * diff --git a/include/exec/exec-all.h b/include/exec/exec-all.h index c1f59fa..ec72c5a 100644 --- a/include/exec/exec-all.h +++ b/include/exec/exec-all.h @@ -59,6 +59,7 @@ TranslationBlock *tb_gen_code(CPUState *cpu, void cpu_exec_init(CPUState *cpu, Error **errp); void QEMU_NORETURN cpu_loop_exit(CPUState *cpu); void QEMU_NORETURN cpu_loop_exit_restore(CPUState *cpu, uintptr_t pc); +void QEMU_NORETURN cpu_loop_exit_atomic(CPUState *cpu, uintptr_t pc); #if !defined(CONFIG_USER_ONLY) void cpu_reloading_memory_map(void); diff --git a/include/qemu-common.h b/include/qemu-common.h index 1f2cb94..77e379d 100644 --- a/include/qemu-common.h +++ b/include/qemu-common.h @@ -76,6 +76,7 @@ void tcg_exec_init(unsigned long tb_size); bool tcg_enabled(void); void cpu_exec_init_all(void); +void cpu_exec_step(CPUState *cpu); /** * Sends a (part of) iovec down a socket, yielding when the socket is full, or diff --git a/linux-user/main.c b/linux-user/main.c index 78d8d04..54df300 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -179,13 +179,25 @@ static inline void start_exclusive(void) } /* Finish an exclusive operation. */ -static inline void __attribute__((unused)) end_exclusive(void) +static inline void end_exclusive(void) { pending_cpus = 0; pthread_cond_broadcast(&exclusive_resume); pthread_mutex_unlock(&exclusive_lock); } +static void step_atomic(CPUState *cpu) +{ + start_exclusive(); + + /* Since we got here, we know that parallel_cpus must be true. */ + parallel_cpus = false; + cpu_exec_step(cpu); + parallel_cpus = true; + + end_exclusive(); +} + /* Wait for exclusive ops to finish, and begin cpu execution. */ static inline void cpu_exec_start(CPUState *cpu) { @@ -437,6 +449,9 @@ void cpu_loop(CPUX86State *env) } } break; + case EXCP_ATOMIC: + step_atomic(cs); + break; default: pc = env->segs[R_CS].base + env->eip; EXCP_DUMP(env, "qemu: 0x%08lx: unhandled CPU exception 0x%x - aborting\n", @@ -929,6 +944,9 @@ void cpu_loop(CPUARMState *env) case EXCP_YIELD: /* nothing to do here for user-mode, just resume guest code */ break; + case EXCP_ATOMIC: + step_atomic(cs); + break; default: error: EXCP_DUMP(env, "qemu: unhandled CPU exception 0x%x - aborting\n", trapnr); @@ -1128,6 +1146,9 @@ void cpu_loop(CPUARMState *env) case EXCP_YIELD: /* nothing to do here for user-mode, just resume guest code */ break; + case EXCP_ATOMIC: + step_atomic(cs); + break; default: EXCP_DUMP(env, "qemu: unhandled CPU exception 0x%x - aborting\n", trapnr); abort(); @@ -1217,6 +1238,9 @@ void cpu_loop(CPUUniCore32State *env) } } break; + case EXCP_ATOMIC: + step_atomic(cs); + break; default: goto error; } @@ -1489,6 +1513,9 @@ void cpu_loop (CPUSPARCState *env) } } break; + case EXCP_ATOMIC: + step_atomic(cs); + break; default: printf ("Unhandled trap: 0x%x\n", trapnr); cpu_dump_state(cs, stderr, fprintf, 0); @@ -2037,6 +2064,9 @@ void cpu_loop(CPUPPCState *env) case EXCP_INTERRUPT: /* just indicate that signals should be handled asap */ break; + case EXCP_ATOMIC: + step_atomic(cs); + break; default: cpu_abort(cs, "Unknown exception 0x%d. Aborting\n", trapnr); break; @@ -2710,6 +2740,9 @@ done_syscall: } } break; + case EXCP_ATOMIC: + step_atomic(cs); + break; default: error: EXCP_DUMP(env, "qemu: unhandled CPU exception 0x%x - aborting\n", trapnr); @@ -2796,6 +2829,9 @@ void cpu_loop(CPUOpenRISCState *env) case EXCP_NR: qemu_log_mask(CPU_LOG_INT, "\nNR\n"); break; + case EXCP_ATOMIC: + step_atomic(cs); + break; default: EXCP_DUMP(env, "\nqemu: unhandled CPU exception %#x - aborting\n", trapnr); @@ -2871,6 +2907,9 @@ void cpu_loop(CPUSH4State *env) queue_signal(env, info.si_signo, &info); break; + case EXCP_ATOMIC: + step_atomic(cs); + break; default: printf ("Unhandled trap: 0x%x\n", trapnr); cpu_dump_state(cs, stderr, fprintf, 0); @@ -2936,6 +2975,9 @@ void cpu_loop(CPUCRISState *env) } } break; + case EXCP_ATOMIC: + step_atomic(cs); + break; default: printf ("Unhandled trap: 0x%x\n", trapnr); cpu_dump_state(cs, stderr, fprintf, 0); @@ -3050,6 +3092,9 @@ void cpu_loop(CPUMBState *env) } } break; + case EXCP_ATOMIC: + step_atomic(cs); + break; default: printf ("Unhandled trap: 0x%x\n", trapnr); cpu_dump_state(cs, stderr, fprintf, 0); @@ -3151,6 +3196,9 @@ void cpu_loop(CPUM68KState *env) } } break; + case EXCP_ATOMIC: + step_atomic(cs); + break; default: EXCP_DUMP(env, "qemu: unhandled CPU exception 0x%x - aborting\n", trapnr); abort(); @@ -3386,6 +3434,9 @@ void cpu_loop(CPUAlphaState *env) case EXCP_INTERRUPT: /* Just indicate that signals should be handled asap. */ break; + case EXCP_ATOMIC: + step_atomic(cs); + break; default: printf ("Unhandled trap: 0x%x\n", trapnr); cpu_dump_state(cs, stderr, fprintf, 0); @@ -3513,6 +3564,9 @@ void cpu_loop(CPUS390XState *env) queue_signal(env, info.si_signo, &info); break; + case EXCP_ATOMIC: + step_atomic(cs); + break; default: fprintf(stderr, "Unhandled trap: 0x%x\n", trapnr); cpu_dump_state(cs, stderr, fprintf, 0); @@ -3765,6 +3819,9 @@ void cpu_loop(CPUTLGState *env) case TILEGX_EXCP_REG_UDN_ACCESS: gen_sigill_reg(env); break; + case EXCP_ATOMIC: + step_atomic(cs); + break; default: fprintf(stderr, "trapnr is %d[0x%x].\n", trapnr, trapnr); g_assert_not_reached(); diff --git a/tcg/tcg.h b/tcg/tcg.h index 66ae0c7..ab67537 100644 --- a/tcg/tcg.h +++ b/tcg/tcg.h @@ -691,6 +691,7 @@ struct TCGContext { }; extern TCGContext tcg_ctx; +extern bool parallel_cpus; static inline void tcg_set_insn_param(int op_idx, int arg, TCGArg v) { diff --git a/translate-all.c b/translate-all.c index eaa95e4..99ae7f9 100644 --- a/translate-all.c +++ b/translate-all.c @@ -119,6 +119,7 @@ static void *l1_map[V_L1_SIZE]; /* code generation context */ TCGContext tcg_ctx; +bool parallel_cpus; /* translation block context */ #ifdef CONFIG_USER_ONLY