From nobody Sun Feb 8 23:26:19 2026 Received: from mail.loongson.cn (mail.loongson.cn [114.242.206.163]) by smtp.subspace.kernel.org (Postfix) with ESMTP id 8B600624 for ; Mon, 23 Dec 2024 07:47:14 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=114.242.206.163 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1734940039; cv=none; b=SVHuYc/iZzCYiL+A9oZIJewOcJbEX8dkwAmo1dbC+suwgAx2gZxLDQFTEzO6bhpnlkchdelspaBayWReVvGXHb6115i1YE2ChGKBJHqLcc18+B8dEPyMAePKMXY0oxv8zJNtoxcee9AWutuyIGHqeE8N1eSBTBB11rYIjblMwRk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1734940039; c=relaxed/simple; bh=lFENjqg/43hGLLhFi7OFM4ol33HLgNKCH7eLyjVlivs=; h=From:To:Cc:Subject:Date:Message-Id:MIME-Version; b=rTWStsr0ZDnVbgwDJqZ+CgwHnNiy1cjHY4o6EjHcgg/CM0GYk0nL9CpJ6t/xOTE15pO1BHU1PRTvJfhRy+WPh0XoF4nab6f0XwAfrl4PcVPeI/mwb5IdyF4hmVj02IrTjSsBhpr/eEBLSmEKAvN+l0yluEAxfjwOlqygqGEQM9s= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn; spf=pass smtp.mailfrom=loongson.cn; arc=none smtp.client-ip=114.242.206.163 Authentication-Results: smtp.subspace.kernel.org; dmarc=none (p=none dis=none) header.from=loongson.cn Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=loongson.cn Received: from loongson.cn (unknown [10.2.5.213]) by gateway (Coremail) with SMTP id _____8AxaeB6FWlnXa1ZAA--.24560S3; Mon, 23 Dec 2024 15:47:06 +0800 (CST) Received: from localhost.localdomain (unknown [10.2.5.213]) by front1 (Coremail) with SMTP id qMiowMBx38d5FWlnaowGAA--.35855S2; Mon, 23 Dec 2024 15:47:05 +0800 (CST) From: Bibo Mao To: Ingo Molnar , Will Deacon , Waiman Long Cc: Boqun Feng , linux-kernel@vger.kernel.org Subject: [PATCH] locking/pvqspinlock: Use try_cmpxchg() in pv_unhash Date: Mon, 23 Dec 2024 15:47:04 +0800 Message-Id: <20241223074704.18857-1-maobibo@loongson.cn> X-Mailer: git-send-email 2.39.3 Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-CM-TRANSID: qMiowMBx38d5FWlnaowGAA--.35855S2 X-CM-SenderInfo: xpdruxter6z05rqj20fqof0/ X-Coremail-Antispam: 1Uk129KBjDUn29KB7ZKAUJUUUUU529EdanIXcx71UUUUU7KY7 ZEXasCq-sGcSsGvfJ3UbIjqfuFe4nvWSU5nxnvy29KBjDU0xBIdaVrnUUvcSsGvfC2Kfnx nUUI43ZEXa7xR_UUUUUUUUU== Content-Type: text/plain; charset="utf-8" We ported pv spinlock to old linux kernel on LoongArch platform, there is error with some stress tests. The error report is something like this for short: kernel BUG at kernel/locking/qspinlock_paravirt.h:261! Oops - BUG[#1]: CPU: 1 PID: 6613 Comm: pidof Not tainted 4.19.190+ #43 Hardware name: Loongson KVM, BIOS 0.0.0 02/06/2015 ra: 9000000000509cfc do_task_stat+0x29c/0xaf0 ERA: 9000000000291308 __pv_queued_spin_unlock_slowpath+0xf8/0x100 CRMD: 000000b0 (PLV0 -IE -DA +PG DACF=3DCC DACM=3DCC -WE) PRMD: 00000000 (PPLV0 -PIE -PWE) ... Call Trace: [<9000000000291308>] __pv_queued_spin_unlock_slowpath+0xf8/0x100 [<9000000000509cf8>] do_task_stat+0x298/0xaf0 [<9000000000502570>] proc_single_show+0x60/0xe0 The problem is that memory accessing is out of order on LoongArch platform, there is contension between pv_unhash() and pv_hash(). CPU0 pv_unhash: CPU1 pv_hash: for_each_hash_entry(he, offset, hash) { for_each_hash_entry(he, of= fset, hash) { if (READ_ONCE(he->lock) =3D=3D lock) { struct qspinlock *ol= d =3D NULL; node =3D READ_ONCE(he->node); WRITE_ONCE(he->lock, NULL); On LoongArch platform which is out of order, the execution order may be switched like this: > WRITE_ONCE(he->lock, NULL); if (try_cmpxchg(&he->lo= ck, &old, lock)) { WRITE_ONCE(he->node, = node); return &he->lock; CPU1 pv_hash() is executing and watch that lock is set with NULL. Write he->node with node of new lock. > node =3D READ_ONCE(he->node); READ_ONCE(he->node) on CPU0 will return node of new lock rather than itself. Here READ_ONCE/WRITE_ONCE is replaced with try_cmpxchg(). Signed-off-by: Bibo Mao --- kernel/locking/qspinlock_paravirt.h | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/kernel/locking/qspinlock_paravirt.h b/kernel/locking/qspinlock= _paravirt.h index dc1cb90e3644..cc4eabce092d 100644 --- a/kernel/locking/qspinlock_paravirt.h +++ b/kernel/locking/qspinlock_paravirt.h @@ -240,9 +240,10 @@ static struct pv_node *pv_unhash(struct qspinlock *loc= k) struct pv_node *node; =20 for_each_hash_entry(he, offset, hash) { - if (READ_ONCE(he->lock) =3D=3D lock) { + struct qspinlock *old =3D lock; + + if (try_cmpxchg(&he->lock, &old, NULL)) { node =3D READ_ONCE(he->node); - WRITE_ONCE(he->lock, NULL); return node; } } base-commit: 48f506ad0b683d3e7e794efa60c5785c4fdc86fa --=20 2.39.3