From nobody Sat Jun 13 17:35:29 2026 Received: from mx0b-0031df01.pphosted.com (mx0b-0031df01.pphosted.com [205.220.180.131]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 9525B3D904E for ; Wed, 6 May 2026 09:03:31 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=205.220.180.131 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778058213; cv=none; b=k5hmzu/Mb4c8XF9iOvxfaZbbrGD/c7yGLGoEZon0mN8GGLC9H1ruDfBSDQUEFWqhJrjanfpFl9GX75jNnTl7GMbcOjsTSLpKPH1IPMaMfca+EMbD3YuNosUfQK6hTAPtXwB6dle3i1tnLXzCq2bVzRb1xOJdYX+hfQnWpFisURw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1778058213; c=relaxed/simple; bh=iyACEZr9tNu0J6Ll/OsHtjOciu11vmKknt4AOlYRNOk=; h=From:Date:Subject:MIME-Version:Content-Type:Message-Id:To:Cc; b=Le47wy0RtbP1163w/5VhriHCevokYWUzppGMuT1ATe4pBh7HKUJBvaUF78c0wz/d+tHzh2keqxofzbHYCNC4pXlYx5RdwlKZYtA9211sqc2asYt7oqVLoo/kVGZnrJzgkglL9nj3ACC5NsF8fe4XrQQjhHgYFc01wBcQdRxegQY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com; spf=pass smtp.mailfrom=oss.qualcomm.com; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b=a9Brw7sn; dkim=pass (2048-bit key) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b=gUJibBKe; arc=none smtp.client-ip=205.220.180.131 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=oss.qualcomm.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=qualcomm.com header.i=@qualcomm.com header.b="a9Brw7sn"; dkim=pass (2048-bit key) header.d=oss.qualcomm.com header.i=@oss.qualcomm.com header.b="gUJibBKe" Received: from pps.filterd (m0279873.ppops.net [127.0.0.1]) by mx0a-0031df01.pphosted.com (8.18.1.11/8.18.1.11) with ESMTP id 6465hIDx3501672 for ; Wed, 6 May 2026 09:03:30 GMT DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=qualcomm.com; h= cc:content-transfer-encoding:content-type:date:from:message-id :mime-version:subject:to; s=qcppdkim1; bh=xNHOgmPVFPAixApqaWJUYe 8lvxM9jzb7c9bkv+MyW04=; b=a9Brw7sny3EKlU+BlcL6QlOdaYkkkJ59TefCao y/lOnxFlpD7SpbiQ0IhUB5qJdBqFnO+LgVZJzbN4qes8Os15tAmlD4rAAjI+8cVJ QQ+gNIOytFA8hLxZLkNPPcdktWyRf8nUspTpY9i++pUQLEq1liaU3OLpNMkvEr26 w/LJCEK2hPtA/LaspBOkMfHqBsQOUxqLAstflDKOdz2u4I4JcOL5qwfJ1ER3t9Q8 BJU0V2SWrmhd3d6FlTdS/Mum93Oui0cxPuQPSpoEKVA+ebXMx0AC5By+1qzvgYIo iupVOm/J8Sl+cKPT39NT4VQTz7XLLBJBSxQvVgYjwdd9KWyw== Received: from mail-dl1-f69.google.com (mail-dl1-f69.google.com [74.125.82.69]) by mx0a-0031df01.pphosted.com (PPS) with ESMTPS id 4dyhqfc2n2-1 (version=TLSv1.3 cipher=TLS_AES_128_GCM_SHA256 bits=128 verify=NOT) for ; Wed, 06 May 2026 09:03:30 +0000 (GMT) Received: by mail-dl1-f69.google.com with SMTP id a92af1059eb24-1270dcd11c1so12466916c88.0 for ; Wed, 06 May 2026 02:03:30 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=oss.qualcomm.com; s=google; t=1778058209; x=1778663009; darn=vger.kernel.org; h=cc:to:message-id:content-transfer-encoding:mime-version:subject :date:from:from:to:cc:subject:date:message-id:reply-to; bh=xNHOgmPVFPAixApqaWJUYe8lvxM9jzb7c9bkv+MyW04=; b=gUJibBKe6qSY5Qe/zTlUWuxy8X4IbadivW02QSyvl07pVL5i8YshBRcWA/uDt4lyLC xq//xlyQL6QcpiHxHeyCH44OtgU3fuHWFB1glI1uTwOP4u8kuq9L6MILyBN8D2eddwH3 Z9+SdWbKkxFrP61mnA9spsEE7DDSSHvcYogWzZ3+bsE5KqUmFOEjYja1Vbi8VT5P9UhU xqbfPmebbJJS1Ro0J7xYRxxc+dFtGy4EkSf3E8hkNXcOI/r5AQuU519YjHe4kJVHO7x4 /beqrQk2vhzQvFYpklKWRWsOvfLGSe/RHe3LnpVohQGxLA1gVfLn6yvBOOtGkClkVExV AAoQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20251104; t=1778058209; x=1778663009; h=cc:to:message-id:content-transfer-encoding:mime-version:subject :date:from:x-gm-gg:x-gm-message-state:from:to:cc:subject:date :message-id:reply-to; bh=xNHOgmPVFPAixApqaWJUYe8lvxM9jzb7c9bkv+MyW04=; b=g2CIivQAL8lqJcF/+Z7SOFJZag0T7AF1PV5Y8zoIBobWRlYlWxHPF+4d5un68sNUhz 9iljc7JRDQn4RYGPGSj1HEM05WYutS76SDBhZdtcnerpv1DoBClSgsFVQjAM4oh41PRi XJXOb9p8/8TVggkRoJGmD+1Eqo6tsstA1MJsdh1ciRtRAlsZm3ULPpR4YRkXcpPaxpC1 zbcBfxBEbNBfDri8eMg9iTqqyaWYqsF8eorThvkkRhsJ9W0+t4uAveizYsZdYu3JvmNH O40RuuW1FCtB3CQFvELiwMykDlX4moFuMk5N4ueglKKYtUNsfhB+SGBirzCprXfXBsKA Ogdg== X-Forwarded-Encrypted: i=1; AFNElJ/M8p9WfCETR7yizLLApZWojeQrPs7aH2vn0s2JDIdLk2U87LSji+nrI7Q4gqPNIfLPiujkVPz6ktfEvFk=@vger.kernel.org X-Gm-Message-State: AOJu0YxXCzppVZhGm4qvs1gsVg3p1uuc4YPWqptmAc/voyMZgh9QdQZB ZDaFqZMwbzSrjPdPj9ysSRqwx2hsicGqWXuxt/2s+B+0CTPuiS52ofd8uLYcRxAik9yD5OZiYli /4Tu4tFW5Aco3vBhxuxNV8NJD9B0z55cO8N4pdq8Z+g5NOhzXccssHpSjhNRar8rT1Fk= X-Gm-Gg: AeBDiett2z7TBiVR2bGE14IbuU1DM/yQbJ4M1Q+DXFDcx9mNBitCazU3ND63P4x3YrL WfrumI/ka6P6vxIr3zZvvtym0dRkovI1uJzVI5/h6wrHkLOlAxncwi51F5BzkrobjeFaYCW7wcU gDZF3Wfce98p14D4PmkPntJBQgPD+uZONg+Vh/hBCN0UiBEVa2WzDjBnIQqgVCxihfEr7oAzTXr /DRhdv4WYcvO0UB1X9JckwXuJVSuXkohtQlVuNupRf6YTx14ulf+9nnpaMMSdQ9ON24L9uhKIFg 8m/8zfcVONkpxvmQEcn6U4eaezegvlH6jN0nnlUm00QfMR+p3AyfoEvj1hS6WKVM8Yx2k3MzC+A +n0wxuTToC/+rghCTpO9GhiGpE80cvdKxzG8QO+uFgU+np1fD4eI3X8to2Eqi5YJrScV/ac9G5d jQ84/C X-Received: by 2002:a05:7022:fa8:b0:12d:ccf5:271c with SMTP id a92af1059eb24-1319cf59173mr989116c88.22.1778058209406; Wed, 06 May 2026 02:03:29 -0700 (PDT) X-Received: by 2002:a05:7022:fa8:b0:12d:ccf5:271c with SMTP id a92af1059eb24-1319cf59173mr989093c88.22.1778058208689; Wed, 06 May 2026 02:03:28 -0700 (PDT) Received: from hu-penyan-lv.qualcomm.com (Global_NAT1.qualcomm.com. [129.46.96.20]) by smtp.gmail.com with ESMTPSA id a92af1059eb24-131f9788eb4sm2473753c88.7.2026.05.06.02.03.27 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Wed, 06 May 2026 02:03:28 -0700 (PDT) From: Peng Yang Date: Wed, 06 May 2026 02:03:12 -0700 Subject: [PATCH v3] virtio_console: bound __send_to_port() spin loop to prevent watchdog bite Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20260506-add_timeout_to___send_to_port-v3-1-8ad046fc3dc3@oss.qualcomm.com> X-B4-Tracking: v=1; b=H4sIAM8D+2kC/43OQQrCMBAF0KtI1qY0k1KrK+8hEtpkYiO2qUlal NK7m9SNC0E3w3z4vJmZeHQGPTlsZuJwMt7YPga+3RDZ1v0FqVExE8ihzAvIaa2UCKZDOwYRrBD CY6/SNlgXKMsLibtGaigYicbgUJvH6p/O7+zH5ooyJDQ1WuODdc/1gYml3r+3JkYZLSUHxXmjC w1H6312H+ubtF2XxUHSyQk+0f0vFCLKFXDUqkReVV/QZVlexqjXUjgBAAA= X-Change-ID: 20260420-add_timeout_to___send_to_port-104ce7bcf241 To: Amit Shah , Arnd Bergmann , Greg Kroah-Hartman Cc: kernel@quicinc.com, virtualization@lists.linux.dev, linux-kernel@vger.kernel.org, kernel@oss.qualcomm.com, Peng Yang X-Mailer: b4 0.16-dev-3bfbc X-Developer-Signature: v=1; a=ed25519-sha256; t=1778058207; l=6870; i=peng.yang@oss.qualcomm.com; s=20260420; h=from:subject:message-id; bh=iyACEZr9tNu0J6Ll/OsHtjOciu11vmKknt4AOlYRNOk=; b=aB3Zn2LRG9GMh+WjxfeyAQoQyFSL888qgy6Gj5NmTWiVSDNFPFtFQ7C0aMN8YzAjwIvB1azui Y00Ld113fgNCI09RgjsZpWUQ+6ulbedfVIBvfLWZpXpwNFiPew7Qthu X-Developer-Key: i=peng.yang@oss.qualcomm.com; a=ed25519; pk=fY34c9+z3TbzFLgw2yql3bT/tbmxDEuxiVPTYAbRSTY= X-Proofpoint-Spam-Details-Enc: AW1haW4tMjYwNTA2MDA4NyBTYWx0ZWRfX+Gfv8JjGLphb 9XXDrvVvp04nCKKCfA+HQ1YQ60w2cwlXqraRbLpxtWdmQ8wHM9LQr17LhQstGfpHN8iK1jD56ud HoEK/yzByvD23/orEWt7OGWWK3X+ftk8i7uJltukiepYxqgecAzbwt0fhPHCGUH+3n5bwi0O0cR 5K7TUtWd7iAk1Ig8712FWv6WCA1E8FyqVWShqVJT8yWip72oSsN8H+GM2crVDHAIGFWceD84Tr1 jjW2UtW6yntkizMjFFQtaJ2t/WhsX3NvaZW7/plvna9EX+VIM8eBCq5KbgIG74aTRT1H2gtpXZf HuY0lJl5eYbs2xuUFZ+C8ILOEvKV7BT1hcLmLjJ4kOpViSPz14eqinTsaAwz3S9z2XUZ6DWhINk kkkhYTk7fur79VtK/I31h5pCFD5ih080+nD5/Fmaqe98T936MRp8vTAKTkE+g7HMuMNt9p0qF3i kxUGDKSvp4jcC/Xk+Hw== X-Proofpoint-ORIG-GUID: Xr6p8Dw24yKCpfk3TvLedECmgboRI5eO X-Proofpoint-GUID: Xr6p8Dw24yKCpfk3TvLedECmgboRI5eO X-Authority-Analysis: v=2.4 cv=NPvlPU6g c=1 sm=1 tr=0 ts=69fb03e2 cx=c_pps a=kVLUcbK0zfr7ocalXnG1qA==:117 a=ouPCqIW2jiPt+lZRy3xVPw==:17 a=IkcTkHD0fZMA:10 a=NGcC8JguVDcA:10 a=s4-Qcg_JpJYA:10 a=VkNPw1HP01LnGYTKEx00:22 a=u7WPNUs3qKkmUXheDGA7:22 a=rJkE3RaqiGZ5pbrm-msn:22 a=bC-a23v3AAAA:8 a=EUspDBNiAAAA:8 a=VwQbUJbxAAAA:8 a=ag1SF4gXAAAA:8 a=NWbpyqog06wjIlyGQJwA:9 a=QEXdDO2ut3YA:10 a=vr4QvYf-bLy2KjpDp97w:22 a=FO4_E8m0qiDe52t0p3_H:22 a=Yupwre4RP9_Eg_Bd0iYG:22 X-Proofpoint-Virus-Version: vendor=baseguard engine=ICAP:2.0.293,Aquarius:18.0.1143,Hydra:6.1.51,FMLib:17.12.100.49 definitions=2026-05-05_03,2026-04-30_02,2025-10-01_01 X-Proofpoint-Spam-Details: rule=outbound_notspam policy=outbound score=0 malwarescore=0 lowpriorityscore=0 spamscore=0 priorityscore=1501 clxscore=1015 suspectscore=0 phishscore=0 bulkscore=0 adultscore=0 impostorscore=0 classifier=typeunknown authscore=0 authtc= authcc= route=outbound adjust=0 reason=mlx scancount=1 engine=8.22.0-2604200000 definitions=main-2605060087 __send_to_port() acquires outvq_lock with IRQs disabled via spin_lock_irqsave(), then spins in virtqueue_get_buf() waiting for the host to consume the TX descriptor. When the host is slow to respond (e.g. under heavy load from concurrent virtio_mem plug operations during secondary VM boot), the spin never exits. The watchdog bark ISR fires on another CPU and tries to printk(), which calls hvc_console_print() -> put_chars() -> __send_to_port(), attempting to acquire outvq_lock. With outvq_lock already held and IRQs disabled, all CPUs stall and the watchdog cannot be pet, triggering a bite. Add a 200ms deadline using ktime_get_mono_fast_ns() to break out of the spin loop as a fallback. Since __send_to_port() may now return before the host has consumed the TX descriptor, put_chars() is changed to allocate a struct port_buffer (GFP_ATOMIC) as the virtqueue token instead of a raw kmemdup() pointer, so that reclaim_consumed_buffers() can safely call free_buf() on it regardless of whether a timeout occurred. put_chars() frees the buffer only when virtqueue_add_outbuf() fails and the token was never submitted. Signed-off-by: Peng Yang --- Changes in v3: - Fix token leak in __send_to_port(): capture virtqueue_get_buf() return value and call free_buf() after the spin loop exits normally. - Link to v2: https://patch.msgid.link/20260429-add_timeout_to___send_to_po= rt-v2-1-3d23efd6e388@oss.qualcomm.com Changes in v2: - Rework put_chars() to allocate full struct port_buffer (GFP_ATOMIC) so free_buf() can safely reclaim the token on timeout. - Transfer buffer ownership to virtqueue on success; free immediately on virtqueue_add_outbuf() failure. - Link to v1: https://patch.msgid.link/20260420-add_timeout_to___send_to_po= rt-v1-1-6c32d33bf4f2@oss.qualcomm.com To: Amit Shah To: Arnd Bergmann To: Greg Kroah-Hartman Cc: kernel@oss.qualcomm.com Cc: virtualization@lists.linux.dev Cc: linux-kernel@vger.kernel.org --- drivers/char/virtio_console.c | 81 +++++++++++++++++++++++++++++++++++----= ---- 1 file changed, 67 insertions(+), 14 deletions(-) diff --git a/drivers/char/virtio_console.c b/drivers/char/virtio_console.c index 9a33217c68d9..4d6b3e144e7f 100644 --- a/drivers/char/virtio_console.c +++ b/drivers/char/virtio_console.c @@ -27,6 +27,7 @@ #include #include #include +#include #include "../tty/hvc/hvc_console.h" =20 #define is_rproc_enabled IS_ENABLED(CONFIG_REMOTEPROC) @@ -601,6 +602,8 @@ static ssize_t __send_to_port(struct port *port, struct= scatterlist *sg, int err; unsigned long flags; unsigned int len; + void *token; + u64 deadline; =20 out_vq =3D port->out_vq; =20 @@ -632,10 +635,20 @@ static ssize_t __send_to_port(struct port *port, stru= ct scatterlist *sg, * buffer and relax the spinning requirement. The downside is * we need to kmalloc a GFP_ATOMIC buffer each time the * console driver writes something out. + * + * To avoid spinning forever if the host stops processing the + * TX virtqueue (e.g. during VM shutdown), a 200ms deadline is + * used to break out of the loop as a fallback. */ - while (!virtqueue_get_buf(out_vq, &len) - && !virtqueue_is_broken(out_vq)) + deadline =3D ktime_get_mono_fast_ns() + 200ULL * NSEC_PER_MSEC; + while (!(token =3D virtqueue_get_buf(out_vq, &len)) && + !virtqueue_is_broken(out_vq)) { + if (ktime_get_mono_fast_ns() >=3D deadline) + break; cpu_relax(); + } + if (token) + free_buf(token, false); done: spin_unlock_irqrestore(&port->outvq_lock, flags); =20 @@ -1097,31 +1110,71 @@ static const struct file_operations port_fops =3D { }; =20 /* - * The put_chars() callback is pretty straightforward. + * The put_chars() callback writes characters to the virtio console port. * - * We turn the characters into a scatter-gather list, add it to the - * output queue and then kick the Host. Then we sit here waiting for - * it to finish: inefficient in theory, but in practice - * implementations will do it immediately. + * We allocate a struct port_buffer (with GFP_ATOMIC) to wrap the data so + * that reclaim_consumed_buffers() can safely call free_buf() on the token + * returned by virtqueue_get_buf(), even if __send_to_port() timed out + * before observing the used-ring update. + * + * On success, ownership of the buffer is transferred to the virtqueue as + * the descriptor token; it will be reclaimed by reclaim_consumed_buffers(= ). + * On failure (virtqueue_add_outbuf() error), the buffer was never submitt= ed + * and must be freed explicitly here. */ static ssize_t put_chars(u32 vtermno, const u8 *buf, size_t count) { struct port *port; struct scatterlist sg[1]; - void *data; - int ret; + struct port_buffer *pbuf; + ssize_t ret; + + if (!count) + return 0; =20 port =3D find_port_by_vtermno(vtermno); if (!port) return -EPIPE; =20 - data =3D kmemdup(buf, count, GFP_ATOMIC); - if (!data) + /* + * Allocate a struct port_buffer with GFP_ATOMIC so that + * reclaim_consumed_buffers() can safely call free_buf() on the token + * returned by virtqueue_get_buf(), whether or not __send_to_port() + * timed out. alloc_buf() uses GFP_KERNEL internally, so we open-code + * the allocation here. + */ + pbuf =3D kmalloc(struct_size(pbuf, sg, 0), GFP_ATOMIC); + if (!pbuf) return -ENOMEM; =20 - sg_init_one(sg, data, count); - ret =3D __send_to_port(port, sg, 1, count, data, false); - kfree(data); + pbuf->buf =3D kmalloc(count, GFP_ATOMIC); + if (!pbuf->buf) { + kfree(pbuf); + return -ENOMEM; + } + pbuf->dev =3D NULL; + pbuf->sgpages =3D 0; + pbuf->len =3D count; + pbuf->offset =3D 0; + pbuf->size =3D count; + memcpy(pbuf->buf, buf, count); + + sg_init_one(sg, pbuf->buf, count); + ret =3D __send_to_port(port, sg, 1, count, pbuf, false); + + /* + * If virtqueue_add_outbuf() failed inside __send_to_port() (ret <=3D 0), + * the token was never submitted to the virtqueue, so reclaim_consumed_ + * buffers() will never see it. Free pbuf explicitly in that case. + * + * On success (ret > 0), ownership of pbuf has been transferred to the + * virtqueue as the descriptor token. It will be reclaimed and freed + * by reclaim_consumed_buffers() -> free_buf() when the host marks the + * descriptor as used, even if __send_to_port() timed out before + * observing the used-ring update. Do NOT free pbuf here in that case. + */ + if (ret <=3D 0) + free_buf(pbuf, false); return ret; } =20 --- base-commit: 97e797263a5e963da3d1e66e743fd518567dfe37 change-id: 20260420-add_timeout_to___send_to_port-104ce7bcf241 Best regards, -- =20 Peng Yang