From nobody Thu Nov 5 07:30:48 2026 Delivered-To: importer@patchew.org Received-SPF: pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) client-ip=192.237.175.120; envelope-from=xen-devel-bounces@lists.xenproject.org; helo=lists.xenproject.org; Authentication-Results: mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass(p=quarantine dis=none) header.from=runbox.com ARC-Seal: i=1; a=rsa-sha256; t=1793633605; cv=none; d=zohomail.com; s=zohoarc; b=QDEN5CiP2bDUuhT7ALQXKWJ53hTGeUyduqHVUqkef/rRFXFsHkrlwLVpfBZCaIed1Dk2mIYYxQqS3X8FL/Uzxwp5GPtA4+samjF76jdXyZ0mmcaZsFp9braep8jmFF74TVBBAa/8D6gnrojLKXoU9fNU+pyhLptqKauJrk7qync= ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=zohomail.com; s=zohoarc; t=1793633605; h=Content-Type:Content-Transfer-Encoding:Cc:Cc:Date:Date:From:From:List-Subscribe:List-Post:List-Id:List-Help:List-Unsubscribe:MIME-Version:Message-ID:Sender:Subject:Subject:To:To:Message-Id:Reply-To; bh=OWA2XPF4LToFYnO4yT1hL4MsaiF9uOHmMKnDy9Fz0JI=; b=n3sfzh6YMdyMaIzyiZvCQdOCw8SHrg5soGQKSHXlMN56VKV/xYF25tcJN00QsN3uJ1t2eIzLHGJRulTmTzT5ltfRGj7nXTOqi2uQdyrZy87nNz2T8yURetW8zSDA1ozOoHyVD1iRkHPCSNnhOsTDOFv5yb0MZF8rC48diGQNy8M= ARC-Authentication-Results: i=1; mx.zohomail.com; dkim=pass; spf=pass (zohomail.com: domain of lists.xenproject.org designates 192.237.175.120 as permitted sender) smtp.mailfrom=xen-devel-bounces@lists.xenproject.org; dmarc=pass header.from= (p=quarantine dis=none) Return-Path: Received: from lists.xenproject.org (lists.xenproject.org [192.237.175.120]) by mx.zohomail.com with SMTPS id 1793633605319723.6662317845696; Mon, 2 Nov 2026 07:33:25 -0800 (PST) Received: from list by lists.xenproject.org with outflank-mailman.1468452.1677548 (Exim 4.92) (envelope-from ) id 1xNu1p-0006Jr-OA; Mon, 02 Nov 2026 15:32:57 +0000 Received: by outflank-mailman (output) from mailman id 1468452.1677548; Mon, 02 Nov 2026 15:32:57 +0000 Received: from localhost ([127.0.0.1] helo=lists.xenproject.org) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1xNu1p-0006Ji-KG; Mon, 02 Nov 2026 15:32:57 +0000 Received: by outflank-mailman (input) for mailman id 1468452; Mon, 02 Nov 2026 15:32:56 +0000 Received: from mx.expurgate.net ([195.190.135.10]) by lists.xenproject.org with esmtp (Exim 4.92) (envelope-from ) id 1xNu1m-0006Jc-2N for xen-devel@lists.xenproject.org; Mon, 02 Nov 2026 15:32:56 +0000 Received: from mx.expurgate.net (helo=localhost) by mx.expurgate.net with esmtp id 1xNu1l-007oBt-9f for xen-devel@lists.xenproject.org; Mon, 02 Nov 2026 16:32:53 +0100 Received: from [10.42.69.6] (helo=localhost) by localhost with ESMTP (eXpurgate MTA 0.9.1) (envelope-from ) id 6ae8ad15-8faa-0a2a0a5109dd-0a2a45068d46-44 for ; Mon, 02 Nov 2026 16:32:53 +0100 Received: from [185.226.149.38] (helo=mailtransmit05.runbox.com) by tlsNG-16d1c6.mxtls.expurgate.net with ESMTPS (eXpurgate 4.57.1) (envelope-from ) id 6ae8ad24-195a-0a2a45060019-b9e29526e85a-3 for ; Mon, 02 Nov 2026 16:32:52 +0100 Received: from mailtransmit02.runbox ([10.9.9.162] helo=aibo.runbox.com) by mailtransmit05.runbox.com with esmtps (TLS1.2) tls TLS_ECDHE_RSA_WITH_AES_128_GCM_SHA256 (Exim 4.93) (envelope-from ) id 1xNu1j-00C0kq-Fu; Mon, 02 Nov 2026 16:32:51 +0100 Received: from [10.9.9.74] (helo=submission03.runbox) by mailtransmit02.runbox with esmtp (Exim 4.86_2) (envelope-from ) id 1xNu1L-0006cC-C6; Mon, 02 Nov 2026 16:32:27 +0100 Received: by submission03.runbox with esmtpsa [Authenticated ID (536975)] (TLS1.2:ECDHE_SECP256R1__RSA_PSS_RSAE_SHA256__AES_256_GCM:256) (Exim 4.95) id 1xNu1I-00CPK3-46; Mon, 02 Nov 2026 16:32:24 +0100 X-Outflank-Mailman: Message body and most headers restored to incoming version X-BeenThere: xen-devel@lists.xenproject.org List-Id: Xen developer discussion List-Unsubscribe: , List-Post: List-Help: List-Subscribe: , Errors-To: xen-devel-bounces@lists.xenproject.org Precedence: list Sender: "Xen-devel" Authentication-Results: eu.smtp.expurgate.cloud; dkim=pass header.s=selector1 header.d=runbox.com header.i="@runbox.com" header.h="Cc:To:Message-Id:Content-Transfer-Encoding:Content-Type:MIME-Version:Subject:Date:From" DKIM-Signature: v=1; a=rsa-sha256; q=dns/txt; c=relaxed/relaxed; d=runbox.com; s=selector1; h=Cc:To:Message-Id:Content-Transfer-Encoding:Content-Type: MIME-Version:Subject:Date:From; bh=OWA2XPF4LToFYnO4yT1hL4MsaiF9uOHmMKnDy9Fz0JI=; b=YVqdIVIjvx3mLyxidi6v4t9gMc Z8oB/yZeWggp5/Vm+IVTnA1L0Hgp3ZQXarF40oYHbjfIL0yhFPZyEk7lAHIda3o2Ece8Q5Yzm1JYb gi2D8lNfKPHPz4KX5In5+waa+NbQo8xqbh2f7wLNZW++DJbUvB6EqnlorPG0XAoStia2xw22Fj+BO YaCqoo5ehX/op6UET2f3vWf/bFziVO4cfiwp6vklC10p4QRSE2HITX1eVDGCQ50PnRyxTU/Mu48Tp tYaq+Sl+Pu6hNgTtfHicMBx0Xo4MJ4BK3vhOuhjYDPeA8dQo7VCcSkPm0c0sz94oYelvRmIkEBX4t 8ADz1CLg==; From: "M. Vefa Bicakci" Date: Mon, 02 Nov 2026 07:31:55 -0800 Subject: [PATCH] x86/xen: Fix lazy MMU pause count wrap-around MIME-Version: 1.0 Content-Type: text/plain; charset="utf-8" Content-Transfer-Encoding: quoted-printable Message-Id: <20261102-xen-lazy-mmu-v1-1-d99a3050b76d@runbox.com> X-B4-Tracking: v=1; b=H4sIAAAAAAAC/6tWKk4tykwtVrJSqFYqSi3LLM7MzwNyDHUUlJIzE vPSU3UzU4B8JSMDIzNDAyNz3YrUPN2cxKpK3dzcUl1zi0RjM4vkxGRjQ1MloJaCotS0zAqwcdG xEH5xaVJWanIJyAyl2loABmMaTXAAAAA= X-Change-ID: 20261027-xen-lazy-mmu-78a368cac315 To: Juergen Gross , Boris Ostrovsky , Thomas Gleixner , Ingo Molnar , Borislav Petkov , Dave Hansen , x86@kernel.org, "H. Peter Anvin" , Peter Zijlstra , Juri Lelli , Vincent Guittot , Dietmar Eggemann , Steven Rostedt , Ben Segall , Mel Gorman , Valentin Schneider , K Prateek Nayak Cc: xen-devel@lists.xenproject.org, linux-kernel@vger.kernel.org, stable@vger.kernel.org, "M. Vefa Bicakci" X-Mailer: b4 0.16.0 X-purgate-ID: tlsNG-16d1c6/1793633572-F5E0E77B-5419DD35/0/0 X-purgate-type: clean X-purgate-size: 5521 X-ZohoMail-DKIM: pass (identity @runbox.com) X-ZM-MESSAGEID: 1793633606906158500 Commit bec6f41a6fe5 ("x86/xen: Get rid of last XEN_LAZY_MMU uses") unintentionally prevents the activation of lazy MMU mode for most tasks running on Xen PV VMs (including dom0). That commit made xen_end_context_switch() call __task_lazy_mmu_mode_resume() with the task being switched to. However, the latter function decrements the pause_count field of the task without checking whether that task's lazy MMU mode was paused or not. A task being switched to for the first time has never been switched from, so attempting to resume lazy MMU mode can wrap-around (underflow) the pause_count from 0 to 255 (U8_MAX). Furthermore, the non-zero pause_count is copied to child tasks at fork, so all descendants (including the idle tasks of the non-boot CPUs) inherit the non-zero pause_count. This prevents enabling lazy MMU mode for them, because lazy_mmu_mode_enable() does not do anything when pause_count is non-zero. Hence, call __task_lazy_mmu_mode_resume() from xen_end_context_switch() only if lazy MMU mode was paused. This issue was discovered with CONFIG_DEBUG_VM=3Dy, which enables pause_count underflow and overflow warnings. In the examples quoted below, the first warning shows the underflow with PID 1. The second warning shows the overflow from 255 (U8_MAX) to 0, also for PID 1, as indicated by the same RDI register value. Example pause_count underflow warning: WARNING: include/linux/pgtable.h:362 at xen_end_context_switch+0x4e/0x60,= CPU#0: swapper/0/0 CPU: 0 UID: 0 PID: 0 Comm: swapper/0 Not tainted 7.2.4-1 #2 PREEMPT(full) RIP: e030:xen_end_context_switch+0x4e/0x60 ... RDX: 0000000000000000 RSI: 0000000000000000 RDI: ffff888004930000 Note: The PID is shown as 0 above, because current_task is updated in __switch_to() after arch_end_context_switch(). arch_end_context_switch() calls xen_end_context_switch() indirectly. Example pause_count overflow warning: WARNING: include/linux/pgtable.h:319 at xen_start_context_switch+0x64/0x7= 0, CPU#0: swapper/0/1 CPU: 0 UID: 0 PID: 1 Comm: swapper/0 Tainted: G W 7.2.4-1 #2 PREE= MPT(full) ... RIP: e030:xen_start_context_switch+0x64/0x70 ... RDX: 0000000000000000 RSI: 0000000013f7894d RDI: ffff888004930000 ... Call Trace: __schedule+0x36a/0x1a90 schedule+0x27/0xa0 schedule_timeout+0xbd/0x100 __wait_for_common+0x97/0x1b0 wait_for_completion_killable+0x24/0x40 __kthread_create_on_node+0x13e/0x240 kthread_create_worker_on_node+0xee/0x1c0 workqueue_init+0x26/0x420 kernel_init_freeable+0x101/0x360 kernel_init+0x1a/0x130 ret_from_fork+0x2b0/0x340 ret_from_fork_asm+0x1a/0x30 Fixes: bec6f41a6fe5 ("x86/xen: Get rid of last XEN_LAZY_MMU uses") Cc: stable@vger.kernel.org # 7.2.x Signed-off-by: M. Vefa Bicakci --- =3D=3D=3D Testing notes =3D=3D=3D This commit was tested with kernel v7.3-16755-gd135ab453a74 and v7.4-rc1 with a domU PV VM, and versions from v7.2.4 to v7.2.14 with dom0 and domU PV VMs running on Xen v4.19.5. CONFIG_DEBUG_VM=3Dy was set for all tests, and no warnings were observed. =3D=3D=3D Debugging notes =3D=3D=3D For debugging, I instrumented xen_start_context_switch(), xen_end_context_switch() and copy_process(), and I confirmed that the inherited pause_count value is decremented for each level of the process tree, starting from 255. =3D=3D=3D Credits =3D=3D=3D The patch was hand-written, but the commit message was polished with a few rounds of LLM review. --- arch/x86/xen/enlighten_pv.c | 10 +++++++++- include/linux/sched.h | 19 +++++++++++++++++++ 2 files changed, 28 insertions(+), 1 deletion(-) diff --git a/arch/x86/xen/enlighten_pv.c b/arch/x86/xen/enlighten_pv.c index c5117a7730d6..68f8a977999b 100644 --- a/arch/x86/xen/enlighten_pv.c +++ b/arch/x86/xen/enlighten_pv.c @@ -431,7 +431,15 @@ static void xen_end_context_switch(struct task_struct = *next) =20 xen_mc_flush(); this_cpu_write(xen_cpu_lazy_mode, false); - __task_lazy_mmu_mode_resume(next); + + /* + * A newly created task can be switched to without ever having been + * switched from, so it will not have a prior lazy MMU pause to undo + * from xen_start_context_switch(). Hence, resume lazy MMU only if it + * was paused. + */ + if (__task_lazy_mmu_mode_paused(next)) + __task_lazy_mmu_mode_resume(next); } =20 static unsigned long xen_store_tr(void) diff --git a/include/linux/sched.h b/include/linux/sched.h index 1c93da75226e..3f9341f1f827 100644 --- a/include/linux/sched.h +++ b/include/linux/sched.h @@ -1791,6 +1791,25 @@ static inline bool is_lazy_mmu_mode_active(void) =20 return __task_lazy_mmu_mode_active(current); } + +/** + * __task_lazy_mmu_mode_paused() - Return a task's lazy MMU mode pause sta= te + * @tsk: The task to check. + * + * Test whether @tsk has its lazy MMU mode state set to paused + * (i.e., pause_count > 0). + * + * This function is intended for architectures that implement the lazy MMU + * mode; it must not be called from generic code. + * + * Return: Whether task @tsk has paused lazy MMU mode. + */ +static inline bool __task_lazy_mmu_mode_paused(struct task_struct *tsk) +{ + struct lazy_mmu_state *state =3D &tsk->lazy_mmu_state; + + return state->pause_count > 0; +} #endif =20 extern struct pid __rcu *cad_pid; --- base-commit: 6628e7d4c6b25c8d18f1345e3a20d21829aae7e4 change-id: 20261027-xen-lazy-mmu-78a368cac315 Best regards, -- =20 M. Vefa Bicakci