From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: Received: from mail-lj1-x22a.google.com (mail-lj1-x22a.google.com [IPv6:2a00:1450:4864:20::22a]) by sourceware.org (Postfix) with ESMTPS id A110139C0BF9 for ; Mon, 25 Jan 2021 23:02:09 +0000 (GMT) DMARC-Filter: OpenDMARC Filter v1.3.2 sourceware.org A110139C0BF9 Received: by mail-lj1-x22a.google.com with SMTP id t8so10063678ljk.10 for ; Mon, 25 Jan 2021 15:02:09 -0800 (PST) X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:mime-version :content-transfer-encoding; bh=LNxlqek0r4Gjqd5qTxfcLEwAi45K7cT0IQtVLxKurgo=; b=p3Typ56fFzZOx4SdCsfbNGfPjqwErQiSpcZxGRyo3qIEMEB90W1XvoyAZVIohjrTiy pT/c6nPgBRDpSAsb+0XcKO1EzAZrZs9oy+Q4jJl3B2cQqYHz/GfQdg/1xU1yRB/Gkl46 wENy6vHE6IkAoIJAO6gov995ZcWs/CxdJ7thhMyM2fEgH6aWSCppGery63ijbj/1jjc2 lMC8aH0yUocRJkZ5Kp40ZtZdHLyQ+sYjxuwj55VUHvXC61OnOfsJOpWUDw8GhromLI5t jYdAzre851hg8U6tKxrHB9hAQma7xFjVs4Yt1LRhU/03+eoh78fQuWRavFMKp7jtadXp Kamg== X-Gm-Message-State: AOAM531lrwwC5yVfn1hz2fbYB1N+xIqrsc5xr0dxLkCiTmMuebegDux+ gG7KNK6kmsKLSS+ALZxjbXnwtl+BLyTEgl2t X-Google-Smtp-Source: ABdhPJzn6107Q1xsVQr7ox2T5B8fT4kYX7B6mQZzr5+bBAPPzZtCSkdM5aVtPkV8zeB6f3GgxEqkSg== X-Received: by 2002:a2e:9847:: with SMTP id e7mr1314389ljj.388.1611615728477; Mon, 25 Jan 2021 15:02:08 -0800 (PST) Received: from atlantis.home ([2a03:1b20:5:f011::10d]) by smtp.gmail.com with ESMTPSA id l6sm1497564lje.6.2021.01.25.15.02.07 (version=TLS1_2 cipher=ECDHE-ECDSA-AES128-GCM-SHA256 bits=128/128); Mon, 25 Jan 2021 15:02:07 -0800 (PST) From: Shahab Vahedi To: gdb-patches@sourceware.org Cc: Shahab Vahedi , Shahab Vahedi , Francois Bedard Subject: [PATCH] gdb: Do not interrupt atomic sequences for ARC Date: Tue, 26 Jan 2021 00:02:30 +0100 Message-Id: <20210125230230.12250-1-shahab.vahedi@gmail.com> X-Mailer: git-send-email 2.30.0 MIME-Version: 1.0 Content-Transfer-Encoding: 8bit X-Spam-Status: No, score=-11.7 required=5.0 tests=BAYES_00, DKIM_SIGNED, DKIM_VALID, DKIM_VALID_AU, DKIM_VALID_EF, FREEMAIL_FROM, GIT_PATCH_0, RCVD_IN_DNSWL_NONE, SPF_HELO_NONE, SPF_PASS, TXREP autolearn=ham autolearn_force=no version=3.4.2 X-Spam-Checker-Version: SpamAssassin 3.4.2 (2018-09-13) on server2.sourceware.org X-BeenThere: gdb-patches@sourceware.org X-Mailman-Version: 2.1.29 Precedence: list List-Id: Gdb-patches mailing list List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Mon, 25 Jan 2021 23:02:11 -0000 From: Shahab Vahedi An atomic sequence for ARC looks something like below (For a better understanding of "llock", "scond", and "LF", please read [1]): 50: llock r2,[r0] ; initiate an atomic write by setting LF=1 54: brne.nt r2,0,66 ; somebody else wrote? break if so. 58: scond r3,[r0] ; only write if LF is still 1 62: bne fwrite+50 ; did we succeed? try again if not. 66: brne_s r2,0,148 ; another thread won the game, go waiting 68: st r18,[r13,64] ; welcome to the realm Normally GDB sets breakpoint on every instructions. This means that there are exceptions raised between "llock" and "scond". When that happens the "LF" flag is cleared and we lose the atomicity. This patch teaches GDB the pattern of "llock .. scond" and will set the next breakpoint _after_ scond. No matter if you use "n", "ni", "s", "si"; they all will skip over the atomic sequence now. If you really want to break in between you must explicitly set a breakpoint. [1] "llock" (Load Locked) loads the 32-bit word pointed by the source operand. If the load is completed without any interruption or exception, the physical address is remembered, in Lock Physical Address (LPA), and the Lock Flag (LF) is set to 1. LF is a non-architecturally visible flag and is cleared whenever an interrupt or exception takes place. LF is also cleared (atomically) whenever another process writes to the LPA. "scond" (Store Conditional) will write to the destination address if and only if the LF is set to 1. When finished, with or without a write, it atomically copies the LF value to ZF (Zero Flag). These two instructions together provide the mechanism for entering a critical section. The code snippet above comes from uClibc's fwrite() function. gdb/ChangeLog: * arc-linux-tdep.c (handle_atomic_sequence): New. (arc_linux_software_single_step): Call handle_atomic_sequence(). --- gdb/arc-linux-tdep.c | 64 ++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 64 insertions(+) diff --git a/gdb/arc-linux-tdep.c b/gdb/arc-linux-tdep.c index c9fbd7ddc28..0e485d6b967 100644 --- a/gdb/arc-linux-tdep.c +++ b/gdb/arc-linux-tdep.c @@ -332,6 +332,67 @@ arc_linux_sw_breakpoint_from_kind (struct gdbarch *gdbarch, : arc_linux_trap_s_le); } +/* Check for an atomic sequence of instructions beginning with an + LLOCK instruction and ending with a SCOND instruction: + + main+14: llock r2,[r0] + main+18: brne.nt r2,0,main+30 + main+22: scond r3,[r0] + main+26: bne main+14 + main+30: mov_s r0,0 + + If such a sequence is found, attempt to step over it. + A breakpoint is placed at the end of the sequence. */ + +static std::vector +handle_atomic_sequence (arc_instruction &insn, disassemble_info &di) +{ + const int atomic_seq_len = 24; /* Instruction sequence length. */ + std::vector next_pcs = {}; + + /* Sanity check. */ + if (insn.insn_class != LLOCK) + return next_pcs; + + /* Data size we are dealing with: LLOCK vs. LLOCKD */ + arc_ldst_data_size llock_data_size_mode = insn.data_size_mode; + /* Indicator if any conditional branch is found in the sequence. */ + bool found_bc = false; + /* Becomes true if "LLOCK(D) .. SCOND(D)" sequence is found. */ + bool is_pattern_valid = false; + + for (int insn_count = 0; insn_count < atomic_seq_len; ++insn_count) + { + arc_insn_decode (arc_insn_get_linear_next_pc (insn), + &di, arc_delayed_print_insn, &insn); + + if (insn.insn_class == BRCC) + { + /* If more than one conditial branch is found, this is not + the pattern we are interested in. */ + if (found_bc) + break; + found_bc = true; + continue; + } + + /* This is almost a happy ending. */ + if (insn.insn_class == SCOND) + { + /* SCOND should match the LLOKCK's data size. */ + if (insn.data_size_mode == llock_data_size_mode) + is_pattern_valid = true; + break; + } + } + + if (is_pattern_valid) + /* Get next instruction after scond(d). There is no limm. */ + next_pcs.push_back (insn.address + insn.length); + + return next_pcs; +} + /* Implement the "software_single_step" gdbarch method. */ static std::vector @@ -349,6 +410,9 @@ arc_linux_software_single_step (struct regcache *regcache) std::vector next_pcs; + if (curr_insn.insn_class == LLOCK) + return handle_atomic_sequence (curr_insn, di); + /* For instructions with delay slots, the fall thru is not the instruction immediately after the current instruction, but the one after that. */ -- 2.30.0