From patchwork Tue Oct 11 19:41:01 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Richard Henderson X-Patchwork-Id: 680910 Return-Path: X-Original-To: incoming@patchwork.ozlabs.org Delivered-To: patchwork-incoming@bilbo.ozlabs.org Received: from lists.gnu.org (lists.gnu.org [IPv6:2001:4830:134:3::11]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (No client certificate requested) by ozlabs.org (Postfix) with ESMTPS id 3stpR639x0z9s9c for ; Wed, 12 Oct 2016 07:25:54 +1100 (AEDT) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (2048-bit key; unprotected) header.d=gmail.com header.i=@gmail.com header.b=08OmmGmU; dkim-atps=neutral Received: from localhost ([::1]:57863 helo=lists.gnu.org) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bu3cV-0004Qu-9T for incoming@patchwork.ozlabs.org; Tue, 11 Oct 2016 16:25:51 -0400 Received: from eggs.gnu.org ([2001:4830:134:3::10]:38244) by lists.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bu2wT-0003vP-3w for qemu-devel@nongnu.org; Tue, 11 Oct 2016 15:42:26 -0400 Received: from Debian-exim by eggs.gnu.org with spam-scanned (Exim 4.71) (envelope-from ) id 1bu2wP-0002H4-49 for qemu-devel@nongnu.org; Tue, 11 Oct 2016 15:42:24 -0400 Received: from mail-pf0-x242.google.com ([2607:f8b0:400e:c00::242]:35982) by eggs.gnu.org with esmtp (Exim 4.71) (envelope-from ) id 1bu2wO-0002GP-Pi for qemu-devel@nongnu.org; Tue, 11 Oct 2016 15:42:21 -0400 Received: by mail-pf0-x242.google.com with SMTP id r16so937156pfg.3 for ; Tue, 11 Oct 2016 12:42:20 -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=o1Xw3+oXcdurmct/D0pCPRssWz+iI1seZ9VBuED6o+g=; b=08OmmGmUGag73kFVWYKEEq7t733VRn+7xmeDknpNVm4I0wssgYcMXivTbJyJzM3+VV P2MBmSQ5hsmvUaymsVRTP+gPX/gvJZO3nyeuhM1ggo4IBmjzxWy+eEw+C+qOm0cq8oUG xRxruBCxvmBbYQxLhZYoE4TV9NBtvdcTPJtgOJtysKW0/I9/m/Ih009Ggb4AXJZMgVl+ xmoyCLGtqdFThjJCD8BTXRAGKQSs+wQNJpNVQXKH0BPjcD4B8P1x3kWzA3uXqxu8uGhX UrpUTbgNpPVfRr3snUpcHMhFzAIU9zJshCR55gnIj+EIFO7i2S4Zp+rCOzttMf3dnOMl v8Ew== 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=o1Xw3+oXcdurmct/D0pCPRssWz+iI1seZ9VBuED6o+g=; b=iZ2DlMMXdqCs3lepW46LpharN6aC8s96NrG37tggv9W4Cw26rQWRsOGlknCXXStt+C RommBHk2hBDo5iOZL8XZGV3rKpK1VD6kUKS+Vte8p2mr55wUhvnUKGtpGl6sxFvI3go8 ElS3uKh9776pDr477zZIdDYHf/wuHhZBVG4iLtV78tJQZxq2dcpa/Y82uWZcg4zkRYpC S9axw352hwHd90eZ0tKRP7srTULxsQi1XMkhyO0T6r9D7Qhljq033u2QKNxr4Xld26QD SjmyI9uicSkR1nfh/o3E55iK7FWMeq672/7gUF4Tv0cmd5sV/QdmX2CaUcaA660m88bL 27fQ== X-Gm-Message-State: AA6/9Rl2a/BdpxXjwZbauv5a3+qh6+DyrEy13vZxlSEwwUJ4cHUjJV3uKyd6R9rzq6poJA== X-Received: by 10.99.3.197 with SMTP id 188mr3565505pgd.28.1476214939922; Tue, 11 Oct 2016 12:42:19 -0700 (PDT) Received: from bigtime.twiddle.net ([187.217.227.243]) by smtp.gmail.com with ESMTPSA id j63sm6197571pfg.32.2016.10.11.12.42.18 (version=TLS1_2 cipher=ECDHE-RSA-AES128-GCM-SHA256 bits=128/128); Tue, 11 Oct 2016 12:42:19 -0700 (PDT) From: Richard Henderson To: qemu-devel@nongnu.org Date: Tue, 11 Oct 2016 14:41:01 -0500 Message-Id: <1476214861-31658-36-git-send-email-rth@twiddle.net> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1476214861-31658-1-git-send-email-rth@twiddle.net> References: <1476214861-31658-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::242 Subject: [Qemu-devel] [PATCH v6 35/35] target-alpha: Emulate LL/SC using cmpxchg helpers 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: alex.bennee@linaro.org Errors-To: qemu-devel-bounces+incoming=patchwork.ozlabs.org@nongnu.org Sender: "Qemu-devel" Emulating LL/SC with cmpxchg is not correct, since it can suffer from the ABA problem. However, portable parallel code is written assuming only cmpxchg which means that in practice this is a viable alternative. Signed-off-by: Richard Henderson --- linux-user/main.c | 49 ---------------------- target-alpha/cpu.h | 4 -- target-alpha/helper.c | 6 --- target-alpha/machine.c | 2 - target-alpha/translate.c | 104 ++++++++++++++++++++--------------------------- 5 files changed, 45 insertions(+), 120 deletions(-) diff --git a/linux-user/main.c b/linux-user/main.c index 7055e54..bb48260 100644 --- a/linux-user/main.c +++ b/linux-user/main.c @@ -2903,51 +2903,6 @@ void cpu_loop(CPUM68KState *env) #endif /* TARGET_M68K */ #ifdef TARGET_ALPHA -static void do_store_exclusive(CPUAlphaState *env, int reg, int quad) -{ - target_ulong addr, val, tmp; - target_siginfo_t info; - int ret = 0; - - addr = env->lock_addr; - tmp = env->lock_st_addr; - env->lock_addr = -1; - env->lock_st_addr = 0; - - start_exclusive(); - mmap_lock(); - - if (addr == tmp) { - if (quad ? get_user_s64(val, addr) : get_user_s32(val, addr)) { - goto do_sigsegv; - } - - if (val == env->lock_value) { - tmp = env->ir[reg]; - if (quad ? put_user_u64(tmp, addr) : put_user_u32(tmp, addr)) { - goto do_sigsegv; - } - ret = 1; - } - } - env->ir[reg] = ret; - env->pc += 4; - - mmap_unlock(); - end_exclusive(); - return; - - do_sigsegv: - mmap_unlock(); - end_exclusive(); - - info.si_signo = TARGET_SIGSEGV; - info.si_errno = 0; - info.si_code = TARGET_SEGV_MAPERR; - info._sifields._sigfault._addr = addr; - queue_signal(env, TARGET_SIGSEGV, QEMU_SI_FAULT, &info); -} - void cpu_loop(CPUAlphaState *env) { CPUState *cs = CPU(alpha_env_get_cpu(env)); @@ -3122,10 +3077,6 @@ void cpu_loop(CPUAlphaState *env) queue_signal(env, info.si_signo, QEMU_SI_FAULT, &info); } break; - case EXCP_STL_C: - case EXCP_STQ_C: - do_store_exclusive(env, env->error_code, trapnr - EXCP_STL_C); - break; case EXCP_INTERRUPT: /* Just indicate that signals should be handled asap. */ break; diff --git a/target-alpha/cpu.h b/target-alpha/cpu.h index 871d9ba..b08d160 100644 --- a/target-alpha/cpu.h +++ b/target-alpha/cpu.h @@ -230,7 +230,6 @@ struct CPUAlphaState { uint64_t pc; uint64_t unique; uint64_t lock_addr; - uint64_t lock_st_addr; uint64_t lock_value; /* The FPCR, and disassembled portions thereof. */ @@ -346,9 +345,6 @@ enum { EXCP_ARITH, EXCP_FEN, EXCP_CALL_PAL, - /* For Usermode emulation. */ - EXCP_STL_C, - EXCP_STQ_C, }; /* Alpha-specific interrupt pending bits. */ diff --git a/target-alpha/helper.c b/target-alpha/helper.c index 9ba3e1a..2ef6cbe 100644 --- a/target-alpha/helper.c +++ b/target-alpha/helper.c @@ -306,12 +306,6 @@ void alpha_cpu_do_interrupt(CPUState *cs) case EXCP_CALL_PAL: name = "call_pal"; break; - case EXCP_STL_C: - name = "stl_c"; - break; - case EXCP_STQ_C: - name = "stq_c"; - break; } qemu_log("INT %6d: %s(%#x) pc=%016" PRIx64 " sp=%016" PRIx64 "\n", ++count, name, env->error_code, env->pc, env->ir[IR_SP]); diff --git a/target-alpha/machine.c b/target-alpha/machine.c index 710b783..b99a123 100644 --- a/target-alpha/machine.c +++ b/target-alpha/machine.c @@ -45,8 +45,6 @@ static VMStateField vmstate_env_fields[] = { VMSTATE_UINTTL(unique, CPUAlphaState), VMSTATE_UINTTL(lock_addr, CPUAlphaState), VMSTATE_UINTTL(lock_value, CPUAlphaState), - /* Note that lock_st_addr is not saved; it is a temporary - used during the execution of the st[lq]_c insns. */ VMSTATE_UINT8(ps, CPUAlphaState), VMSTATE_UINT8(intr_flag, CPUAlphaState), diff --git a/target-alpha/translate.c b/target-alpha/translate.c index a2e2a62..03e4776 100644 --- a/target-alpha/translate.c +++ b/target-alpha/translate.c @@ -99,7 +99,6 @@ static TCGv cpu_std_ir[31]; static TCGv cpu_fir[31]; static TCGv cpu_pc; static TCGv cpu_lock_addr; -static TCGv cpu_lock_st_addr; static TCGv cpu_lock_value; #ifndef CONFIG_USER_ONLY @@ -116,7 +115,6 @@ void alpha_translate_init(void) static const GlobalVar vars[] = { DEF_VAR(pc), DEF_VAR(lock_addr), - DEF_VAR(lock_st_addr), DEF_VAR(lock_value), }; @@ -198,6 +196,23 @@ static TCGv dest_sink(DisasContext *ctx) return ctx->sink; } +static void free_context_temps(DisasContext *ctx) +{ + if (!TCGV_IS_UNUSED_I64(ctx->sink)) { + tcg_gen_discard_i64(ctx->sink); + tcg_temp_free(ctx->sink); + TCGV_UNUSED_I64(ctx->sink); + } + if (!TCGV_IS_UNUSED_I64(ctx->zero)) { + tcg_temp_free(ctx->zero); + TCGV_UNUSED_I64(ctx->zero); + } + if (!TCGV_IS_UNUSED_I64(ctx->lit)) { + tcg_temp_free(ctx->lit); + TCGV_UNUSED_I64(ctx->lit); + } +} + static TCGv load_gpr(DisasContext *ctx, unsigned reg) { if (likely(reg < 31)) { @@ -395,56 +410,37 @@ static ExitStatus gen_store_conditional(DisasContext *ctx, int ra, int rb, int32_t disp16, int mem_idx, TCGMemOp op) { - TCGv addr; - - if (ra == 31) { - /* ??? Don't bother storing anything. The user can't tell - the difference, since the zero register always reads zero. */ - return NO_EXIT; - } - -#if defined(CONFIG_USER_ONLY) - addr = cpu_lock_st_addr; -#else - addr = tcg_temp_local_new(); -#endif + TCGLabel *lab_fail, *lab_done; + TCGv addr, val; + addr = tcg_temp_new_i64(); tcg_gen_addi_i64(addr, load_gpr(ctx, rb), disp16); + free_context_temps(ctx); -#if defined(CONFIG_USER_ONLY) - /* ??? This is handled via a complicated version of compare-and-swap - in the cpu_loop. Hopefully one day we'll have a real CAS opcode - in TCG so that this isn't necessary. */ - return gen_excp(ctx, (op & MO_SIZE) == MO_64 ? EXCP_STQ_C : EXCP_STL_C, ra); -#else - /* ??? In system mode we are never multi-threaded, so CAS can be - implemented via a non-atomic load-compare-store sequence. */ - { - TCGLabel *lab_fail, *lab_done; - TCGv val; + lab_fail = gen_new_label(); + lab_done = gen_new_label(); + tcg_gen_brcond_i64(TCG_COND_NE, addr, cpu_lock_addr, lab_fail); + tcg_temp_free_i64(addr); - lab_fail = gen_new_label(); - lab_done = gen_new_label(); - tcg_gen_brcond_i64(TCG_COND_NE, addr, cpu_lock_addr, lab_fail); + val = tcg_temp_new_i64(); + tcg_gen_atomic_cmpxchg_i64(val, cpu_lock_addr, cpu_lock_value, + load_gpr(ctx, ra), mem_idx, op); + free_context_temps(ctx); - val = tcg_temp_new(); - tcg_gen_qemu_ld_i64(val, addr, mem_idx, op); - tcg_gen_brcond_i64(TCG_COND_NE, val, cpu_lock_value, lab_fail); - - tcg_gen_qemu_st_i64(ctx->ir[ra], addr, mem_idx, op); - tcg_gen_movi_i64(ctx->ir[ra], 1); - tcg_gen_br(lab_done); + if (ra != 31) { + tcg_gen_setcond_i64(TCG_COND_EQ, ctx->ir[ra], val, cpu_lock_value); + } + tcg_temp_free_i64(val); + tcg_gen_br(lab_done); - gen_set_label(lab_fail); + gen_set_label(lab_fail); + if (ra != 31) { tcg_gen_movi_i64(ctx->ir[ra], 0); - - gen_set_label(lab_done); - tcg_gen_movi_i64(cpu_lock_addr, -1); - - tcg_temp_free(addr); - return NO_EXIT; } -#endif + + gen_set_label(lab_done); + tcg_gen_movi_i64(cpu_lock_addr, -1); + return NO_EXIT; } static bool in_superpage(DisasContext *ctx, int64_t addr) @@ -2914,6 +2910,10 @@ void gen_intermediate_code(CPUAlphaState *env, struct TranslationBlock *tb) /* Similarly for flush-to-zero. */ ctx.tb_ftz = -1; + TCGV_UNUSED_I64(ctx.zero); + TCGV_UNUSED_I64(ctx.sink); + TCGV_UNUSED_I64(ctx.lit); + num_insns = 0; max_insns = tb->cflags & CF_COUNT_MASK; if (max_insns == 0) { @@ -2948,23 +2948,9 @@ void gen_intermediate_code(CPUAlphaState *env, struct TranslationBlock *tb) } insn = cpu_ldl_code(env, ctx.pc); - TCGV_UNUSED_I64(ctx.zero); - TCGV_UNUSED_I64(ctx.sink); - TCGV_UNUSED_I64(ctx.lit); - ctx.pc += 4; ret = translate_one(ctxp, insn); - - if (!TCGV_IS_UNUSED_I64(ctx.sink)) { - tcg_gen_discard_i64(ctx.sink); - tcg_temp_free(ctx.sink); - } - if (!TCGV_IS_UNUSED_I64(ctx.zero)) { - tcg_temp_free(ctx.zero); - } - if (!TCGV_IS_UNUSED_I64(ctx.lit)) { - tcg_temp_free(ctx.lit); - } + free_context_temps(ctxp); /* If we reach a page boundary, are single stepping, or exhaust instruction count, stop generation. */