From nobody Mon Sep 28 05:43:26 2026 Received: from mail.mainlining.org (mail.mainlining.org [5.75.144.95]) (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 A47143D75A8; Tue, 25 Aug 2026 20:58:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=5.75.144.95 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787691529; cv=none; b=frESKLenG2r8y2Ve1dhh+9hxFOGscYx6F3A0OXPkMJPdfe4XIDe+xuXaXjIJ3uJqqjmMZcG/UGeZeXtKxR+kaU4gAyxLI6NqkSZZHbmHdxYhTli2VXTr8UYfI9HkYTFo2kRMjXAryD+C7ygVaCvWNNa5e/+TGzj9AnsB39oPT8E= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787691529; c=relaxed/simple; bh=ezbX/LRqC72QwZ54CJev6hPjTLIWfLTcd+nM1mnqj+U=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Gf+4IV6NWkz10wIZF0xVCTp6AWBY+9uqpMZufrM0nvIbnzNXucTJX9zPtx+//y8fxh/bIC+qVAVQK6DivU19CELeVywHC7XUKVCdWA81H99LPt1moRXxUyPX7XKJn5y7chJJpgz0tr09nD4uwRw5EDNbcerszvddceSdONthEkU= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=mainlining.org; spf=pass smtp.mailfrom=mainlining.org; dkim=pass (2048-bit key) header.d=mainlining.org header.i=@mainlining.org header.b=MxPDrAYu; dkim=permerror (0-bit key) header.d=mainlining.org header.i=@mainlining.org header.b=wZJ8sK4y; arc=none smtp.client-ip=5.75.144.95 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=mainlining.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=mainlining.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=mainlining.org header.i=@mainlining.org header.b="MxPDrAYu"; dkim=permerror (0-bit key) header.d=mainlining.org header.i=@mainlining.org header.b="wZJ8sK4y" DKIM-Signature: v=1; a=rsa-sha256; s=202507r; d=mainlining.org; c=relaxed/relaxed; h=Message-ID:Date:Subject:To:From; t=1787691520; bh=x5ptgH1+l+eHmiDjFhFIWK1 AN+3vpULjdQe9ooy3wMI=; b=MxPDrAYuYMDGqzEx/3V8Rd+RVnUqiMnNK/ThqEgl6Fd7M5NJ2H wRk3id6CJ2IKZREVzyoccpxTJM/HKFriHIS+MRXAWbzel+S3McidVpg/yLixbpRUyPiWCMR3nLt i0ySW9tuwShZyX6BuORVL+Fbj0DIDFGHvrXc2AaCHS0wVu5lEp+/fXYiyEqUTS0Wc70sex635An mfkOzG81Vgl1vMApPmq4Iagd5PJEXGx90Auf8AJzJsCunmL2m4vGWA0ucsEYCjj/aFv0f/FYe39 wfZH5i0PJuYXPmydb0Pctb0+tNZIwIxMFot0cI8D3Za2iWJBb7VN/X1jimGThGxWFkw==; DKIM-Signature: v=1; a=ed25519-sha256; s=202507e; d=mainlining.org; c=relaxed/relaxed; h=Message-ID:Date:Subject:To:From; t=1787691520; bh=x5ptgH1+l+eHmiDjFhFIWK1 AN+3vpULjdQe9ooy3wMI=; b=wZJ8sK4ypJ5yYbibF3C2Rlrwt5c6chdBFxa174mQYdxccwGlmR QnunZEAlwjplgEQt0Z1lG3NKALTfO9maCRCg==; From: Bradley Morgan To: Will Deacon Cc: Catalin Marinas , Mark Rutland , James Morse , Marc Zyngier , Ard Biesheuvel , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, brads@mainlining.org, stable@vger.kernel.org Subject: [PATCH 1/7] arm64: hibernate: pass HVC_SET_VECTORS args to the resume hvc Date: Tue, 25 Aug 2026 20:58:33 +0000 Message-ID: <20260825205839.14571-2-brads@mainlining.org> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260825205839.14571-1-brads@mainlining.org> References: <20260825205839.14571-1-brads@mainlining.org> 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 Content-Type: text/plain; charset="utf-8" swsusp_arch_suspend_exit() reinstalls the restored kernel's hyp stub vectors with an hvc, but never passes the arguments. x0 is not set to HVC_SET_VECTORS and x1 is not set to the vector address, so the stub dispatch falls through and returns without writing vbar_el2. EL2 is left pointing at the trans_pgd copy of the vectors, a page that swsusp_free() releases right after resume. Set the arguments up the same way __hyp_set_vectors() does. Fixes: 788bfdd97434 ("arm64: trans_pgd: hibernate: Add trans_pgd_copy_el2_v= ectors") Cc: stable@vger.kernel.org Signed-off-by: Bradley Morgan Tested-by: Ard Biesheuvel --- arch/arm64/kernel/hibernate-asm.S | 2 ++ 1 file changed, 2 insertions(+) diff --git a/arch/arm64/kernel/hibernate-asm.S b/arch/arm64/kernel/hibernat= e-asm.S index 0e1d9c3c6a93..2baefe7a82d3 100644 --- a/arch/arm64/kernel/hibernate-asm.S +++ b/arch/arm64/kernel/hibernate-asm.S @@ -89,6 +89,8 @@ alternative_insn "dc cvau, x4", "dc civac, x4", ARM64_W= ORKAROUND_CLEAN_CACHE isb =20 cbz x24, 3f /* Do we need to re-initialise EL2? */ + mov x1, x24 + mov x0, #HVC_SET_VECTORS hvc #0 3: ret SYM_CODE_END(swsusp_arch_suspend_exit) --=20 2.47.3 From nobody Mon Sep 28 05:43:26 2026 Received: from mail.mainlining.org (mail.mainlining.org [5.75.144.95]) (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 A4677311C35 for ; Tue, 25 Aug 2026 20:58:47 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=5.75.144.95 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787691530; cv=none; b=e4xQ661TUQQNFXI/k+mPT366bcE02CvlqyhH464USp7xfhAbfWQAuIOg4vl48GnrYq4UTRYz2IMhHN0Cy89H2vmZnliEj5FW17BDtUufKWGXOpwlgtH/TWj6Jrnbhxbo7qviBs2OiYQVpb9/ERHnJuuQ7yObN/7qQuAp3scMVOQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787691530; c=relaxed/simple; bh=c1SWEETqf2l0p+tx/WkJBIQVomgRM80hRvx+1LRJBU4=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=or46JbzaRFP3LfRQunIP84ASnKMi4KHgRfXpktTX5+kjfXWSSCzqVtSaNmik4Pq3/DjRBwdDROqylfZN6qz9cbo+2yXNVgE8IOcqdaC4/sJ7AV8FuRGxDdFW4cVGd3z30xUUTuq0gcVC2IrggTUdTM8V0PDhHbCkB7H402Ntr4Q= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=mainlining.org; spf=pass smtp.mailfrom=mainlining.org; dkim=pass (2048-bit key) header.d=mainlining.org header.i=@mainlining.org header.b=M/MJ/HBJ; dkim=permerror (0-bit key) header.d=mainlining.org header.i=@mainlining.org header.b=N72sBd+3; arc=none smtp.client-ip=5.75.144.95 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=mainlining.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=mainlining.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=mainlining.org header.i=@mainlining.org header.b="M/MJ/HBJ"; dkim=permerror (0-bit key) header.d=mainlining.org header.i=@mainlining.org header.b="N72sBd+3" DKIM-Signature: v=1; a=rsa-sha256; s=202507r; d=mainlining.org; c=relaxed/relaxed; h=Message-ID:Date:Subject:To:From; t=1787691521; bh=lsilY3pcpndhM3GC4RwYhLV g2Hao2DERRjYOE6c8cGs=; b=M/MJ/HBJQ+4UZ1l2RmvSWPYWAdLvK1ycEm6DJFK77zBV+/S4HJ qDILleprP2JdyH30UwU9m8coRmGG4XSBHeXVY1hhp61z0HryRse029NvNgD7+3VX1xaVkQ4PN3e k0NhCq+taS+LjWUAXdqtFzuqe0LTucSqHGUknu8WSkn3CZRotJ7EgNyZXdHq4cywUYpFBJtab9y 6sSHak8wAU37OGY4CInzGRs5o3s/MfbwlZGAmha53EHwm0FoMfSMkeIk5Z/vJN1zKw4u1wsBmU8 2DdQNy7rHg/0JvlRHYvhui6oEnAw1K5zyHZ4IQbz6YCAServ0sOm/mMSMohp9e9xPVQ==; DKIM-Signature: v=1; a=ed25519-sha256; s=202507e; d=mainlining.org; c=relaxed/relaxed; h=Message-ID:Date:Subject:To:From; t=1787691521; bh=lsilY3pcpndhM3GC4RwYhLV g2Hao2DERRjYOE6c8cGs=; b=N72sBd+3MF91/FwudEKpSBdcsaleaQ35HTU+sLGJkMxythNVye aiDzIDzeuURnn0PYqGf944r5kwDc9OKiFLDQ==; From: Bradley Morgan To: Will Deacon Cc: Catalin Marinas , Mark Rutland , James Morse , Marc Zyngier , Ard Biesheuvel , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, brads@mainlining.org Subject: [PATCH 2/7] arm64: head: correct comment for init_kernel_el() Date: Tue, 25 Aug 2026 20:58:34 +0000 Message-ID: <20260825205839.14571-3-brads@mainlining.org> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260825205839.14571-1-brads@mainlining.org> References: <20260825205839.14571-1-brads@mainlining.org> 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 Content-Type: text/plain; charset="utf-8" The comment above init_kernel_el() still says the function configures the CPU to execute at the highest reachable EL, but that stopped being true a while back. Ever since commit ae4b7e38e9a94798 ("arm64: Allow sticky E2H when entering EL1"), init_kernel_el() always drops to EL1, and it is finalise_el2() that brings us back up to EL2 when we want it. Update the comment to match what the code actually does. Signed-off-by: Bradley Morgan Cc: Ard Biesheuvel Cc: Catalin Marinas Cc: James Morse Cc: Marc Zyngier Cc: Will Deacon Tested-by: Ard Biesheuvel --- arch/arm64/kernel/head.S | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/arch/arm64/kernel/head.S b/arch/arm64/kernel/head.S index 87a822e5c4ca..c6301557eee1 100644 --- a/arch/arm64/kernel/head.S +++ b/arch/arm64/kernel/head.S @@ -254,9 +254,9 @@ SYM_FUNC_END(__primary_switched) .section ".idmap.text","a" =20 /* - * Starting from EL2 or EL1, configure the CPU to execute at the highest - * reachable EL supported by the kernel in a chosen default state. If drop= ping - * from EL2 to EL1, configure EL2 before configuring EL1. + * Starting from EL2 or EL1, configure the CPU to execute at EL1. + * If dropping from EL2 to EL1, configure EL2 before configuring EL1. + * To use VHE we'll upgrade back to EL2 later in finalise_el2(). * * Since we cannot always rely on ERET synchronizing writes to sysregs (e.= g. if * SCTLR_ELx.EOS is clear), we place an ISB prior to ERET. --=20 2.47.3 From nobody Mon Sep 28 05:43:26 2026 Received: from mail.mainlining.org (mail.mainlining.org [5.75.144.95]) (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 8F42D3D8125 for ; Tue, 25 Aug 2026 20:58:53 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=5.75.144.95 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787691538; cv=none; b=N9o65JzeGnWc/WMM2+bLPYtwmYxpdwEMvN3wvsH1jKKuxgGdpWbhBXDSPL5Aoj+S1KsSG3csNVUmEDx5FnjJudMc/jdQJIZUHSZF3lu4xe98y7wojt0Vrd53bYr1nej1JvYlPme035wlBQt7DfdrRIi68BDJveUSSWSq2tcGd7I= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787691538; c=relaxed/simple; bh=sX+K8VoUPQkmHeS97h8G6+QD9wmkzWqtLleWRh222vU=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=rpry7g2s7WhlU+/cAZlGybH0FMShyRYIDsQ+kRZaNG8rPf2zQdSxSyBgaalcv78PiU2CC0G4lv64VxHMeQp1Pfbd5gnMtRbT8GTIJlIIRuMfZS2B92e4NzJlrPN3i/gamY6uGyd8W60SfaZSI5o2YElffHzzBls0izGmopysoz8= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=mainlining.org; spf=pass smtp.mailfrom=mainlining.org; dkim=pass (2048-bit key) header.d=mainlining.org header.i=@mainlining.org header.b=CcCNa3x5; dkim=permerror (0-bit key) header.d=mainlining.org header.i=@mainlining.org header.b=XCXO5TuF; arc=none smtp.client-ip=5.75.144.95 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=mainlining.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=mainlining.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=mainlining.org header.i=@mainlining.org header.b="CcCNa3x5"; dkim=permerror (0-bit key) header.d=mainlining.org header.i=@mainlining.org header.b="XCXO5TuF" DKIM-Signature: v=1; a=rsa-sha256; s=202507r; d=mainlining.org; c=relaxed/relaxed; h=Message-ID:Date:Subject:To:From; t=1787691521; bh=tcjQYxJSDuzLIJWxbldwZuY iOSwnH8+4AZ5XCME/3vg=; b=CcCNa3x52RoI0/e0OH+7hcs4HFDJkoOwd9ESWola0c+lSe7Lf6 CnSwRptOswVUyIHK/C7TPc0qWfS8/iPkLDG8qnWZXY+x/QDHRrsZoziS53t1yQB6eFHjoHhntzf cmw1HIs9e/0h1g0o2hjQafUQiVvmkxNxkOJI/RSiw9nlf6wINziuKyr1EFj9F5XISYgZ3pjaVAr LPQR++QwnEVzKTrQmxYaUtgDnO8f8WBaiQ5TXt6JL/5VwvQtx85/RTeXzt/o2hagYsTAhh3J9Jn pygMXMcjCj8otGaOMGK3d7rhA62iUL+MtF1ucGdI+UchHyfFWP/mvY/vVGy7JaMtYVA==; DKIM-Signature: v=1; a=ed25519-sha256; s=202507e; d=mainlining.org; c=relaxed/relaxed; h=Message-ID:Date:Subject:To:From; t=1787691521; bh=tcjQYxJSDuzLIJWxbldwZuY iOSwnH8+4AZ5XCME/3vg=; b=XCXO5TuFHBpaNStAIMteueMkdMR+xerG/ycXx00bgQY8i7qniq ngEH7n9BEoM+tyPSwc3hPVM/CJqGVOEIflBQ==; From: Bradley Morgan To: Will Deacon Cc: Catalin Marinas , Mark Rutland , James Morse , Marc Zyngier , Ard Biesheuvel , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, brads@mainlining.org Subject: [PATCH 3/7] arm64: hibernate: free MTE tag pages after saving Date: Tue, 25 Aug 2026 20:58:35 +0000 Message-ID: <20260825205839.14571-4-brads@mainlining.org> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260825205839.14571-1-brads@mainlining.org> References: <20260825205839.14571-1-brads@mainlining.org> 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 Content-Type: text/plain; charset="utf-8" swsusp_arch_suspend() calls swsusp_mte_save_tags() to stash the userspace MTE tags, but we only free them on a successful resume in swsusp_mte_restore_tags(). If hibernation fails partway, the tags stay allocated, and the next time we try to hibernate, swsusp_mte_save_tags() warns about duplicate entries in the mte_pages xarray. Reproducing it is easy, just make a hibernate fail twice in a row. | # echo test_resume > /sys/power/disk | # echo disk > /sys/power/state ... | PM: Cannot find swap device, try swapon -a | PM: Cannot get swap writer ... | # echo disk > /sys/power/state ... | ------------[ cut here ]------------ | swsusp: save_tags: Duplicate entry | WARNING: CPU: 0 PID: 123 at arch/arm64/kernel/hibernate.c:234 \ | swsusp_arch_suspend+0x3f0/0x5b0 ... Free the tag storage right after swsusp_save() has copied it into the hibernation image. Where hibernation succeeds, the tags come back from the image and get consumed by swsusp_mte_restore_tags() as before. Fixes: ee11f332af96 ("arm64: mte: Save tags when hibernating") Signed-off-by: Bradley Morgan Tested-by: Ard Biesheuvel --- arch/arm64/kernel/hibernate.c | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/arch/arm64/kernel/hibernate.c b/arch/arm64/kernel/hibernate.c index 7bf117427777..8ac29058a839 100644 --- a/arch/arm64/kernel/hibernate.c +++ b/arch/arm64/kernel/hibernate.c @@ -241,14 +241,18 @@ static int save_tags(struct page *page, unsigned long= pfn) static void swsusp_mte_free_storage(void) { XA_STATE(xa_state, &mte_pages, 0); + int n =3D 0; void *tags; =20 xa_lock(&mte_pages); xas_for_each(&xa_state, tags, ULONG_MAX) { mte_free_tag_storage(tags); + n++; } xa_unlock(&mte_pages); =20 + pr_info("Freed %d MTE pages\n", n); + xa_destroy(&mte_pages); } =20 @@ -355,6 +359,12 @@ int swsusp_arch_suspend(void) =20 sleep_cpu =3D smp_processor_id(); ret =3D swsusp_save(); + + /* + * Hibernation can still fail from here, so free the tags now, + * a second attempt would warn on duplicate entries otherwise. + */ + swsusp_mte_free_storage(); } else { /* Clean kernel core startup/idle code to PoC*/ dcache_clean_inval_poc((unsigned long)__mmuoff_data_start, --=20 2.47.3 From nobody Mon Sep 28 05:43:26 2026 Received: from mail.mainlining.org (mail.mainlining.org [5.75.144.95]) (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 B3EA43D75C4 for ; Tue, 25 Aug 2026 20:58:56 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=5.75.144.95 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787691538; cv=none; b=tVM6L8a9KVuugrTSUlqe1G9zb6igFLb1yNbyvJHVQQyvAPs8q5W0rqaRC2T2k4NjMRlvOomM0KRZfvzIr+/HwOqhJjvSiTmbw8MHuEcBWOUISgmJb0KvJQd/wXCMKQ5ba14V13DIi8fWcBrcDq5HDsHifHg7TEj+2bIgy3ILG7g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787691538; c=relaxed/simple; bh=wrZPU/vB6yrO2p31oARv3vfmvNsJyjuT2pkHRG4kssA=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=JOOLgNNbr3e3PjnRFZRh5GmazM4WI03egG8t33uuIa13ZahBT/g3UxJg4aOhttBJ88t1FcXoVW8y/zQR/+9/4HGV553Urv/o5OQqI8rWVICEPPtLqcFD+3qvIM9hrtn5JOYuCHZXL//Cv38a5a0Z7dR3QXn80bATnaqjwGOCVEA= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=mainlining.org; spf=pass smtp.mailfrom=mainlining.org; dkim=pass (2048-bit key) header.d=mainlining.org header.i=@mainlining.org header.b=AMjKzy0J; dkim=permerror (0-bit key) header.d=mainlining.org header.i=@mainlining.org header.b=UxxEbtkt; arc=none smtp.client-ip=5.75.144.95 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=mainlining.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=mainlining.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=mainlining.org header.i=@mainlining.org header.b="AMjKzy0J"; dkim=permerror (0-bit key) header.d=mainlining.org header.i=@mainlining.org header.b="UxxEbtkt" DKIM-Signature: v=1; a=rsa-sha256; s=202507r; d=mainlining.org; c=relaxed/relaxed; h=Message-ID:Date:Subject:To:From; t=1787691522; bh=rEGlkv18mRe1qNNtTlr2JCI qchOSWxy0YcEBCLLf6KE=; b=AMjKzy0Jmvstw3XfAeDtfanNVzCtFyAdF/q2+ErvENgGyIgCcQ UWOvIWeYxGS6f5WiPi5UzLLGqWgN3M8UknaG/ZrXnAzluenI2OHsnV7YxLR+AIEFUHr87W7GlB5 1xNb1mYLHum1JJhwPr/9jLkxdRzrxrhgBUzRe7nCT5SQfKZ7eOnXJDEZIcS4S1TUrPz9QHScKk5 602zFGLprRUu3bGGr3Xh17JjgDqGJ/ymYp5qjY3X9agrlGBQf3pDxuwDf6CRMpn14unr9STWmzj 3j9mLwo9QeApOCy28Fd/vpR7eo+IbTrofkUVUefQAoxdoZlanIBHrOwn9mVD3l4xqRA==; DKIM-Signature: v=1; a=ed25519-sha256; s=202507e; d=mainlining.org; c=relaxed/relaxed; h=Message-ID:Date:Subject:To:From; t=1787691522; bh=rEGlkv18mRe1qNNtTlr2JCI qchOSWxy0YcEBCLLf6KE=; b=UxxEbtktDwBAOHGUQbb+V1PU+FoeCibh+Zhog3Px+tdF30povN 2iinhe50EZPD06cC01718+XDk14huWKkLbCw==; From: Bradley Morgan To: Will Deacon Cc: Catalin Marinas , Mark Rutland , James Morse , Marc Zyngier , Ard Biesheuvel , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, brads@mainlining.org Subject: [PATCH 4/7] arm64: hibernate: fix _cpu_resume() calling convention Date: Tue, 25 Aug 2026 20:58:36 +0000 Message-ID: <20260825205839.14571-5-brads@mainlining.org> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260825205839.14571-1-brads@mainlining.org> References: <20260825205839.14571-1-brads@mainlining.org> 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 Content-Type: text/plain; charset="utf-8" The hibernate path borrows bits of the normal idle suspend/resume code and open codes the rest. It skips cpu_resume() and has swsusp_arch_suspend_exit() branch straight into _cpu_resume() at the kernel's native EL with the MMU on. Commit 82e4958800c01daa ("arm64: head: Move all finalise_el2 calls to after __enable_mmu") changed the calling convention for _cpu_resume() to expect EL1 with the boot mode in x19, but we never updated swsusp_arch_suspend_exit() to match. So when swsusp_arch_suspend_exit() calls _cpu_resume(), x19 holds the final struct pbe next pointer, which must be NULL since it marks the end of the list. _cpu_resume() then passes that to finalise_el2() in x0, and finalise_el2() only issues an HVC when the value is BOOT_CPU_MODE_EL2 and we are at EL1, so it happens not to fire. That is the right outcome, but it is pure luck rather than design. Split _cpu_resume() so this is less fragile. __cpu_resume_switched() is the shared part, used by both the idle and hibernate code. It takes no arguments and issues no HVC. The name is meant to match __primary_switched and __secondary_switched. __cpu_resume_switched_finalise_el2() is for the idle path only. It pulls the boot mode from x19 and calls finalise_el2() before __cpu_resume_switched(). It is kept local to sleep.S so the odd calling convention does not leak any further. Fixes: 82e4958800c01daa ("arm64: head: Move all finalise_el2 calls to after= __enable_mmu") Signed-off-by: Bradley Morgan Cc: Ard Biesheuvel Cc: Catalin Marinas Cc: James Morse Cc: Marc Zyngier Cc: Will Deacon Tested-by: Ard Biesheuvel --- arch/arm64/include/asm/suspend.h | 2 +- arch/arm64/kernel/hibernate.c | 2 +- arch/arm64/kernel/sleep.S | 9 ++++++--- 3 files changed, 8 insertions(+), 5 deletions(-) diff --git a/arch/arm64/include/asm/suspend.h b/arch/arm64/include/asm/susp= end.h index e9ce68d50ba4..1b7570902264 100644 --- a/arch/arm64/include/asm/suspend.h +++ b/arch/arm64/include/asm/suspend.h @@ -41,7 +41,7 @@ extern int cpu_suspend(unsigned long arg, int (*fn)(unsig= ned long)); extern void cpu_resume(void); int __cpu_suspend_enter(struct sleep_stack_data *state); void __cpu_suspend_exit(void); -void _cpu_resume(void); +void __cpu_resume_switched(void); =20 int swsusp_arch_suspend(void); int swsusp_arch_resume(void); diff --git a/arch/arm64/kernel/hibernate.c b/arch/arm64/kernel/hibernate.c index 8ac29058a839..30b02e39a397 100644 --- a/arch/arm64/kernel/hibernate.c +++ b/arch/arm64/kernel/hibernate.c @@ -114,7 +114,7 @@ int arch_hibernation_header_save(void *addr, unsigned i= nt max_size) =20 arch_hdr_invariants(&hdr->invariants); hdr->ttbr1_el1 =3D __pa_symbol(swapper_pg_dir); - hdr->reenter_kernel =3D _cpu_resume; + hdr->reenter_kernel =3D __cpu_resume_switched; =20 /* We can't use __hyp_get_vectors() because kvm may still be loaded */ if (el2_reset_needed()) diff --git a/arch/arm64/kernel/sleep.S b/arch/arm64/kernel/sleep.S index f093cdf71be1..da45ab63bd9c 100644 --- a/arch/arm64/kernel/sleep.S +++ b/arch/arm64/kernel/sleep.S @@ -107,16 +107,19 @@ SYM_CODE_START(cpu_resume) adrp x1, swapper_pg_dir adrp x2, idmap_pg_dir bl __enable_mmu - ldr x8, =3D_cpu_resume + ldr x8, =3D__cpu_resume_switched_finalise_el2 br x8 SYM_CODE_END(cpu_resume) .ltorg .popsection =20 -SYM_FUNC_START(_cpu_resume) +SYM_FUNC_START_LOCAL(__cpu_resume_switched_finalise_el2) mov x0, x19 bl finalise_el2 + b __cpu_resume_switched +SYM_FUNC_END(__cpu_resume_switched_finalise_el2) =20 +SYM_FUNC_START(__cpu_resume_switched) mrs x1, mpidr_el1 adr_l x8, mpidr_hash // x8 =3D struct mpidr_hash virt address =20 @@ -152,4 +155,4 @@ SYM_FUNC_START(_cpu_resume) ldp x29, lr, [x29] mov x0, #0 ret -SYM_FUNC_END(_cpu_resume) +SYM_FUNC_END(__cpu_resume_switched) --=20 2.47.3 From nobody Mon Sep 28 05:43:26 2026 Received: from mail.mainlining.org (mail.mainlining.org [5.75.144.95]) (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 A40113D75A8 for ; Tue, 25 Aug 2026 20:58:54 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=5.75.144.95 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787691538; cv=none; b=URnzKoJ60GBpsk3bTE2F7sCyubEIegj1UuUTR7CQ3ova9GS/aBnTVL0Y4L0BfhrkFnrLhxu4yAHFFGpZbbR5X4UT4/4JDylr3ks2rUjZLjpjoPaVF93Tox2mnokTdgVRtb6IuN/Y4odr+6vsBvvZfRBv+NxD14vodk1z4fOVW2k= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787691538; c=relaxed/simple; bh=FKEIjKXBcojqD4mz1MIW3HN2+3QpL3DopPawywzFp/Y=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=rQf0EHK7uQQJaZgZzsyjCzaUCiWOkyv+TMq/wwhUp28CFsxNeqX9igitZ4YsZYAPa2ZeXBMnCsrrxjTDwqrbxNkfsE+TaNFhhZWlwRgoDbItrS99vAjXKXdPUYbrAk/XjCIU5XEt/PZogFmQ7rC4MxbV6IPkZQE1YiDNJdfE+Dc= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=mainlining.org; spf=pass smtp.mailfrom=mainlining.org; dkim=pass (2048-bit key) header.d=mainlining.org header.i=@mainlining.org header.b=HHiOExNa; dkim=permerror (0-bit key) header.d=mainlining.org header.i=@mainlining.org header.b=tEWKBLAO; arc=none smtp.client-ip=5.75.144.95 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=mainlining.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=mainlining.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=mainlining.org header.i=@mainlining.org header.b="HHiOExNa"; dkim=permerror (0-bit key) header.d=mainlining.org header.i=@mainlining.org header.b="tEWKBLAO" DKIM-Signature: v=1; a=rsa-sha256; s=202507r; d=mainlining.org; c=relaxed/relaxed; h=Message-ID:Date:Subject:To:From; t=1787691522; bh=E6ST9MO0xhHKKK61d7KBl+q 5WdV+hnI+lqckETtBROU=; b=HHiOExNagC67Mue4hKwQ0B5MUnPtWrGbsg45GprQpkh307ZKIQ KgadCKPrFoCytd5mSZcaommv5m/eTgI3rMOHxpyQ5P40L/3qcbX21aiAnEMHkwEm2aXpgAURBy2 epBoNcMrXtkCSajJdTreXtNjPfmmf9Psj+pEjMwkxHpxnzfbPslRh2EF2kliJ4Aw01+UdkkOO+W hVXombEqXr2FMfxhpUyjzrkAFbSJzjGMr4ovhlaM5eU9sq85SeJLBsagfm90/Hj0MVhwUjbtw8S lXh1N8GB9g87Y0VqqwehixKI60TsEk1AaC7KohFjbvV6d9yWs0DRcmyXj67c7HxEF7w==; DKIM-Signature: v=1; a=ed25519-sha256; s=202507e; d=mainlining.org; c=relaxed/relaxed; h=Message-ID:Date:Subject:To:From; t=1787691522; bh=E6ST9MO0xhHKKK61d7KBl+q 5WdV+hnI+lqckETtBROU=; b=tEWKBLAOvv0aZDYbFR45is0Xz4W0LeAXh3ss6J0V/o6dz115+a OprdMuGDsMebHWkxgEfna/Fxe655s1hM1SBA==; From: Bradley Morgan To: Will Deacon Cc: Catalin Marinas , Mark Rutland , James Morse , Marc Zyngier , Ard Biesheuvel , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, brads@mainlining.org Subject: [PATCH 5/7] arm64: hibernate: use dcache_by_myline_op Date: Tue, 25 Aug 2026 20:58:37 +0000 Message-ID: <20260825205839.14571-6-brads@mainlining.org> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260825205839.14571-1-brads@mainlining.org> References: <20260825205839.14571-1-brads@mainlining.org> 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 Content-Type: text/plain; charset="utf-8" swsusp_arch_suspend_exit() used to open code its cache maintenance, but the dcache_by_myline_op macro does everything that open coded version did, including the ARM64_WORKAROUND_CLEAN_CACHE handling. So use it. Since this was first written the macro got split, with the trailing DSB moved out into a wrapper, so use dcache_by_myline_op_nosync here and keep relying on the DSB that already sits after the restore loop. That keeps this a true no-op. Signed-off-by: Bradley Morgan Cc: Ard Biesheuvel Cc: Catalin Marinas Cc: James Morse Cc: Marc Zyngier Cc: Will Deacon Tested-by: Ard Biesheuvel --- arch/arm64/kernel/hibernate-asm.S | 11 +++-------- 1 file changed, 3 insertions(+), 8 deletions(-) diff --git a/arch/arm64/kernel/hibernate-asm.S b/arch/arm64/kernel/hibernat= e-asm.S index 2baefe7a82d3..f7613404f99e 100644 --- a/arch/arm64/kernel/hibernate-asm.S +++ b/arch/arm64/kernel/hibernate-asm.S @@ -66,16 +66,11 @@ SYM_CODE_START(swsusp_arch_suspend_exit) =20 copy_page x0, x1, x2, x3, x4, x5, x6, x7, x8, x9 =20 + /* Clean the restored page to the PoU */ + mov x0, x10 add x1, x10, #PAGE_SIZE - /* Clean the copied page to PoU - based on caches_clean_inval_pou() */ raw_dcache_line_size x2, x3 - sub x3, x2, #1 - bic x4, x10, x3 -2: /* clean D line / unified line */ -alternative_insn "dc cvau, x4", "dc civac, x4", ARM64_WORKAROUND_CLEAN_C= ACHE - add x4, x4, x2 - cmp x4, x1 - b.lo 2b + dcache_by_myline_op_nosync cvau, x0, x1, x2, x3 =20 ldr x19, [x19, #HIBERN_PBE_NEXT] cbnz x19, 1b --=20 2.47.3 From nobody Mon Sep 28 05:43:26 2026 Received: from mail.mainlining.org (mail.mainlining.org [5.75.144.95]) (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 919663DA7D1 for ; Tue, 25 Aug 2026 20:58:51 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=5.75.144.95 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787691533; cv=none; b=tzAEHUPUZrL9XZ7bb8Sq1LloitFmJBPYBNztl8stDkdstD2e7A2SbH1m/RfPbdZaQVWcDBzXNZUGOiL8zQsROPcPtXjJ91LK9U4TOZ5ZTtS+mA63glzILVLnAWpLdpMR2fhPWQsfnJ1XWE50otCWmodxbkdGEWOEaihrnMEYajU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787691533; c=relaxed/simple; bh=W+DhMTa+CBrImk6+8Gy936d7JvNsBuKVZ+S7jmVqlWQ=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=T9D9L2hVdwDggkw/lumsJTwJBSNNQ+7+au7ppa2KsmleUXSAlPOdDnPJHNPAceK2OGO2Hf/Bm9gVZlqsszOCLZeq03HcEDsFb9YQu2ybdZRswqcWTa92gNAJvY8amS7GCYsBZkqnyRMnLsSXskl+SKXlIP7e+zUyjZ8qv3e8LKs= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=mainlining.org; spf=pass smtp.mailfrom=mainlining.org; dkim=pass (2048-bit key) header.d=mainlining.org header.i=@mainlining.org header.b=iWF9+jgB; dkim=permerror (0-bit key) header.d=mainlining.org header.i=@mainlining.org header.b=rBIxKT78; arc=none smtp.client-ip=5.75.144.95 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=mainlining.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=mainlining.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=mainlining.org header.i=@mainlining.org header.b="iWF9+jgB"; dkim=permerror (0-bit key) header.d=mainlining.org header.i=@mainlining.org header.b="rBIxKT78" DKIM-Signature: v=1; a=rsa-sha256; s=202507r; d=mainlining.org; c=relaxed/relaxed; h=Message-ID:Date:Subject:To:From; t=1787691523; bh=/dvG8fDOHWdM0omtWZoCkfR i9vcvwSeryRVWH7Ed/eA=; b=iWF9+jgBqpWuT2caZOg1KqUlbwkPytLMdB2DTCjmkP9zbsd/b2 S6oOlZ0c1MjKs+pQrTpht1YuHOIA9K/5ffWM+2P+wFJUjlYS9N1cTTUTa2Vao1SVtDQk0H6yIaC lLAtal59xykEcKDMp8pOZuJ/9B0dAm3BLRoXm51EcnW5xDpu9KQCw4e/bbpqvYs4p1PdV85ERhB iJmGplpMTpklGej0CZwKq+TmDxrG09TNly5BSfNlqqEEr4JY3BlF/c18wanc2XnV8agvEuf4LDQ 43WFz2KS+IHjh/Tszb4UqSD2h+79fCl+d7cSa1hyDBNW3641UCCZk76x7ne5hbdiU/w==; DKIM-Signature: v=1; a=ed25519-sha256; s=202507e; d=mainlining.org; c=relaxed/relaxed; h=Message-ID:Date:Subject:To:From; t=1787691523; bh=/dvG8fDOHWdM0omtWZoCkfR i9vcvwSeryRVWH7Ed/eA=; b=rBIxKT78xLkDYZW6vyVR5Ozc3cNsqYS2hd8VWTZYvR0KGD30Rf m5I5h+aIU1YXMNfestrvUi5otXuPP6HE7kCg==; From: Bradley Morgan To: Will Deacon Cc: Catalin Marinas , Mark Rutland , James Morse , Marc Zyngier , Ard Biesheuvel , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, brads@mainlining.org Subject: [PATCH 6/7] arm64: hibernate: only clean to PoC Date: Tue, 25 Aug 2026 20:58:38 +0000 Message-ID: <20260825205839.14571-7-brads@mainlining.org> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260825205839.14571-1-brads@mainlining.org> References: <20260825205839.14571-1-brads@mainlining.org> 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 Content-Type: text/plain; charset="utf-8" The hibernate code has to clean parts of the kernel to the PoC so they can be used with the MMU off. We only need to clean to the PoC, but we have been using dcache_clean_inval_poc(), which does a clean plus invalidate, just because that is what was available. When hibernate was added in commit 82869ac57b5d ("arm64: kernel: Add support for hibernate/suspend-to-disk"), the only cache maintenance exposed outside the DMA code was __flush_dcache_area(), so that is what got used. Commit d34fdb7081394cbf ("arm64: mm: convert __dma_* routines to = use start, size") later exposed dcache_clean_area_poc(), and commit fade9c2c6ee2baea ("arm64: Rename arm64-internal cache maintenance functions") renamed things again, but the hibernate code never switched over either time. The invalidate is pointless anyway, since the mappings we clean through are cacheable and the CPU can just pull the memory straight back into cache right after. Use dcache_clean_poc() instead. Signed-off-by: Bradley Morgan Cc: Ard Biesheuvel Cc: Catalin Marinas Cc: James Morse Cc: Marc Zyngier Cc: Will Deacon Tested-by: Ard Biesheuvel --- arch/arm64/kernel/hibernate.c | 17 ++++++++--------- 1 file changed, 8 insertions(+), 9 deletions(-) diff --git a/arch/arm64/kernel/hibernate.c b/arch/arm64/kernel/hibernate.c index 30b02e39a397..60e264299a4d 100644 --- a/arch/arm64/kernel/hibernate.c +++ b/arch/arm64/kernel/hibernate.c @@ -367,18 +367,17 @@ int swsusp_arch_suspend(void) swsusp_mte_free_storage(); } else { /* Clean kernel core startup/idle code to PoC*/ - dcache_clean_inval_poc((unsigned long)__mmuoff_data_start, - (unsigned long)__mmuoff_data_end); - dcache_clean_inval_poc((unsigned long)__idmap_text_start, - (unsigned long)__idmap_text_end); + dcache_clean_poc((unsigned long)__mmuoff_data_start, + (unsigned long)__mmuoff_data_end); + dcache_clean_poc((unsigned long)__idmap_text_start, + (unsigned long)__idmap_text_end); =20 /* Clean kvm setup code to PoC? */ if (el2_reset_needed()) { - dcache_clean_inval_poc( - (unsigned long)__hyp_idmap_text_start, - (unsigned long)__hyp_idmap_text_end); - dcache_clean_inval_poc((unsigned long)__hyp_text_start, - (unsigned long)__hyp_text_end); + dcache_clean_poc((unsigned long)__hyp_idmap_text_start, + (unsigned long)__hyp_idmap_text_end); + dcache_clean_poc((unsigned long)__hyp_text_start, + (unsigned long)__hyp_text_end); } =20 swsusp_mte_restore_tags(); --=20 2.47.3 From nobody Mon Sep 28 05:43:26 2026 Received: from mail.mainlining.org (mail.mainlining.org [5.75.144.95]) (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 E09273D9549 for ; Tue, 25 Aug 2026 20:58:52 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=5.75.144.95 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787691539; cv=none; b=cFhUw4ZykN32WmTKb/wMpHo1nJVgai/3qmAMEfI/F5lcqQzcdJx1uBeExweYA5asqpqHPjeQR4I31A/v4MvRD80bXIggtuFDCUyK9qWnTSQ1sCRROVJDxWudnVco4+RLTJVz6o7oHWEJS8ysGU3TAAnnTXHSX8+EbkPvqN55cBY= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1787691539; c=relaxed/simple; bh=ZKhxoCS8f3B9oD0r0VoggCvcczvFpAvIk/qTGExACS8=; h=From:To:Cc:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=io+pefYV4MzzM5Zw+gg0bBdNn9J54Y35ZqqoUyUZROqpdTdCzuBMuq5RbjFeV3GqFZtYQxXyI4DSikzvZuYKleqKykWtir439ShM6TyGN3bzWgSLz5rt/QzUsE7gjNEjJoRaa9R5NJpk/59XpIyvcv1nlgZ/StrWlGM3kfa7/v4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=mainlining.org; spf=pass smtp.mailfrom=mainlining.org; dkim=pass (2048-bit key) header.d=mainlining.org header.i=@mainlining.org header.b=ap/HP+BN; dkim=permerror (0-bit key) header.d=mainlining.org header.i=@mainlining.org header.b=usaB9Gi0; arc=none smtp.client-ip=5.75.144.95 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=mainlining.org Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=mainlining.org Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=mainlining.org header.i=@mainlining.org header.b="ap/HP+BN"; dkim=permerror (0-bit key) header.d=mainlining.org header.i=@mainlining.org header.b="usaB9Gi0" DKIM-Signature: v=1; a=rsa-sha256; s=202507r; d=mainlining.org; c=relaxed/relaxed; h=Message-ID:Date:Subject:To:From; t=1787691523; bh=opptRr7//UiGidu2H6UGZTc w8hOoBerPUAbRLY3tiJw=; b=ap/HP+BNW+k6wBdnH69ELYHtbEBEet2XonacLvJ7v6Gb1NGBJj ELSGd8uTau0+MnipQdPM9KjsYTT96uWbZXT8EmNVUiehOZANpMrerT/KoXABnSnWdX+l6wDNH7G StqUqKbIGF0ZGXipsXysOd1Pjlrqng9cWKiVxNPwnb2sAR1/aQwDuws3CmhbY7eGWMECde26gBt 1qh1DPfyqH03J++erlPE+kJRfASaXH9z+DYmHI7jB942KnYwDKfr/eyif4MCh/ZDSHIO7x5BeHm EdzAI51613IYbGRzkyoRQv5bwSJ2VjexcAfXezdZbDhOU1NWuVIAJ0YNZcsA5BzRQkQ==; DKIM-Signature: v=1; a=ed25519-sha256; s=202507e; d=mainlining.org; c=relaxed/relaxed; h=Message-ID:Date:Subject:To:From; t=1787691523; bh=opptRr7//UiGidu2H6UGZTc w8hOoBerPUAbRLY3tiJw=; b=usaB9Gi0np9VxnbVpERDgcXxU8TitGyJByIaL7vwXHTBzJhLUo r9QV0AUWppH1TtOjw/kGBiET2pDr4AZjOCAQ==; From: Bradley Morgan To: Will Deacon Cc: Catalin Marinas , Mark Rutland , James Morse , Marc Zyngier , Ard Biesheuvel , linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, brads@mainlining.org Subject: [PATCH 7/7] arm64: hibernate: use regular cpu_resume() logic Date: Tue, 25 Aug 2026 20:58:39 +0000 Message-ID: <20260825205839.14571-8-brads@mainlining.org> X-Mailer: git-send-email 2.47.3 In-Reply-To: <20260825205839.14571-1-brads@mainlining.org> References: <20260825205839.14571-1-brads@mainlining.org> 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 Content-Type: text/plain; charset="utf-8" Right now the hibernate path borrows parts of the idle suspend/resume code and writes the rest itself. It skips cpu_resume() and branches straight into __cpu_resume_switched() at the kernel's native EL with the MMU on. That split has been the source of a few subtle bugs, and it makes the code a pain to maintain. Rework it so a resume from hibernate looks like a resume from idle. We enter cpu_resume() at the highest available EL with the MMU off, and leave the resumed kernel responsible for restoring all its CPU state the same way idle does. That makes the handoff cleaner and should be more robust. With this, swsusp_arch_suspend_exit() now cleans the whole kernel Image to the PoC instead of leaving the resumed kernel to clean bits of itself. That is nicer on its own, since we cannot forget to clean some portion of the Image that gets added later, and the maintenance is cheap next to the page copying that dominates resume time anyway. It also means __cpu_resume_switched() no longer needs to be visible outside sleep.S, so it can merge back with __cpu_resume_switched_finalise_el2(). Since this was first written, two things landed upstream and are folded in here. Commit 684bde100117931f ("arm64: hibernate: mask DAIF before restoring hibernated kernel") made swsusp_arch_resume() mask all DAIF exceptions before calling hibernate_exit() and mark it unreachable(), and that masking is kept around the new hibernate_exit() call. Commit 2c92eff008a2 ("arm64: Provide dcache_by_myline_op_nosync helper") split dcache_by_myline_op into a _nosync form, so use that and rely on the existing DSB after the maintenance. swsusp_arch_resume() also keeps its __nocfi annotation from commit e2f8216ca2d8 ("arm64: Set __nocfi on swsusp_arch_resume()"). Signed-off-by: Bradley Morgan Cc: Ard Biesheuvel Cc: Catalin Marinas Cc: James Morse Cc: Marc Zyngier Cc: Will Deacon Tested-by: Ard Biesheuvel --- arch/arm64/include/asm/suspend.h | 1 - arch/arm64/kernel/hibernate-asm.S | 78 ++++++++++++++++++++----------- arch/arm64/kernel/hibernate.c | 55 ++++++++-------------- arch/arm64/kernel/sleep.S | 7 +-- 4 files changed, 71 insertions(+), 70 deletions(-) diff --git a/arch/arm64/include/asm/suspend.h b/arch/arm64/include/asm/susp= end.h index 1b7570902264..3aba69df06b9 100644 --- a/arch/arm64/include/asm/suspend.h +++ b/arch/arm64/include/asm/suspend.h @@ -41,7 +41,6 @@ extern int cpu_suspend(unsigned long arg, int (*fn)(unsig= ned long)); extern void cpu_resume(void); int __cpu_suspend_enter(struct sleep_stack_data *state); void __cpu_suspend_exit(void); -void __cpu_resume_switched(void); =20 int swsusp_arch_suspend(void); int swsusp_arch_resume(void); diff --git a/arch/arm64/kernel/hibernate-asm.S b/arch/arm64/kernel/hibernat= e-asm.S index f7613404f99e..edfab9ce4ed1 100644 --- a/arch/arm64/kernel/hibernate-asm.S +++ b/arch/arm64/kernel/hibernate-asm.S @@ -29,40 +29,48 @@ * * This 'safe' page is mapped via ttbr0, and executed from there. This fun= ction * switches to a copy of the linear map in ttbr1, performs the restore, th= en - * switches ttbr1 to the original kernel's swapper_pg_dir. + * reenters the original kernel with the MMU off. * * All of memory gets written to, including code. We need to clean the ker= nel - * text to the Point of Coherence (PoC) before secondary cores can be boot= ed. + * text to the Point of Coherence (PoC) before reentering it. * Because the kernel modules and executable pages mapped to user space are * also written as data, we clean all pages we touch to the Point of * Unification (PoU). * - * x0: physical address of temporary page tables - * x1: physical address of swapper page tables - * x2: address of cpu_resume - * x3: linear map address of restore_pblist in the current kernel - * x4: physical address of __hyp_stub_vectors, or 0 - * x5: physical address of a zero page that remains zero after resume + * x0: physical address of temporary zero page + * x1: physical address of temporary page tables + * x2: linear map address of restore_pblist in the current kernel + * x3: linear map address of the start of the resumed kernel image + * x4: linear map address of the end of the resumed kernel image + * x5: physical address to reenter the resumed kernel + * x6: whether to return to el2 */ .pushsection ".hibernate_exit.text", "ax" SYM_CODE_START(swsusp_arch_suspend_exit) /* - * We execute from ttbr0, change ttbr1 to our copied linear map tables - * with a break-before-make via the zero page + * Save the arguments, the low numbered registers get clobbered below. */ - break_before_make_ttbr_switch x5, x0, x6, x8 - - mov x21, x1 - mov x30, x2 + mov x22, x2 + mov x23, x3 mov x24, x4 mov x25, x5 + mov x26, x6 =20 - /* walk the restore_pblist and use copy_page() to over-write memory */ - mov x19, x3 + /* + * We run from an idmap in TTBR0 here, install the temporary linear + * map in TTBR1. + */ + break_before_make_ttbr_switch x0, x1, x3, x4 =20 -1: ldr x10, [x19, #HIBERN_PBE_ORIG] - mov x0, x10 - ldr x1, [x19, #HIBERN_PBE_ADDR] + /* + * Walk the restore_pblist and restore each page, cleaning to the PoU + * in case it holds userspace or module code. + */ +.L__next_pbe: + ldr x0, [x22, #HIBERN_PBE_ORIG] + ldr x1, [x22, #HIBERN_PBE_ADDR] + + mov x10, x0 =20 copy_page x0, x1, x2, x3, x4, x5, x6, x7, x8, x9 =20 @@ -72,21 +80,35 @@ SYM_CODE_START(swsusp_arch_suspend_exit) raw_dcache_line_size x2, x3 dcache_by_myline_op_nosync cvau, x0, x1, x2, x3 =20 - ldr x19, [x19, #HIBERN_PBE_NEXT] - cbnz x19, 1b - dsb ish /* wait for PoU cleaning to finish */ + ldr x22, [x22, #HIBERN_PBE_NEXT] + cbnz x22, .L__next_pbe =20 - /* switch to the restored kernels page tables */ - break_before_make_ttbr_switch x25, x21, x6, x8 + /* Clean the kernel image to the PoC, it gets used with the MMU off */ + dcache_by_myline_op_nosync cvac, x23, x24, x2, x3 + + /* Complete all D-cache maintenance above */ + dsb ish =20 ic ialluis dsb ish isb =20 - cbz x24, 3f /* Do we need to re-initialise EL2? */ - mov x1, x24 - mov x0, #HVC_SET_VECTORS + cbz x26, .L__no_el2 + + /* Enter the resumed kernel at EL2 with the MMU disabled. */ + mov x0, #HVC_SOFT_RESTART + mov x1, x25 hvc #0 -3: ret + + /* HVC_SOFT_RESTART should never return */ + b . + +.L__no_el2: + /* Enter the resumed kernel at EL1 with the MMU disabled. */ + mov_q x0, INIT_SCTLR_EL1_MMU_OFF + pre_disable_mmu_workaround + msr sctlr_el1, x0 + isb + br x25 SYM_CODE_END(swsusp_arch_suspend_exit) .popsection diff --git a/arch/arm64/kernel/hibernate.c b/arch/arm64/kernel/hibernate.c index 60e264299a4d..c3556d1c4cef 100644 --- a/arch/arm64/kernel/hibernate.c +++ b/arch/arm64/kernel/hibernate.c @@ -69,15 +69,9 @@ struct arch_hibernate_hdr_invariants { static struct arch_hibernate_hdr { struct arch_hibernate_hdr_invariants invariants; =20 - /* These are needed to find the relocated kernel if built with kaslr */ - phys_addr_t ttbr1_el1; - void (*reenter_kernel)(void); - - /* - * We need to know where the __hyp_stub_vectors are after restore to - * re-configure el2. - */ - phys_addr_t __hyp_stub_vectors; + phys_addr_t kernel_start; + phys_addr_t kernel_end; + phys_addr_t reenter_kernel; =20 u64 sleep_cpu_mpidr; } resume_hdr; @@ -113,14 +107,10 @@ int arch_hibernation_header_save(void *addr, unsigned= int max_size) return -EOVERFLOW; =20 arch_hdr_invariants(&hdr->invariants); - hdr->ttbr1_el1 =3D __pa_symbol(swapper_pg_dir); - hdr->reenter_kernel =3D __cpu_resume_switched; =20 - /* We can't use __hyp_get_vectors() because kvm may still be loaded */ - if (el2_reset_needed()) - hdr->__hyp_stub_vectors =3D __pa_symbol(__hyp_stub_vectors); - else - hdr->__hyp_stub_vectors =3D 0; + hdr->kernel_start =3D __pa_symbol(_text); + hdr->kernel_end =3D __pa_symbol(_end); + hdr->reenter_kernel =3D __pa_symbol(cpu_resume); =20 /* Save the mpidr of the cpu we called cpu_suspend() on... */ if (sleep_cpu < 0) { @@ -366,20 +356,6 @@ int swsusp_arch_suspend(void) */ swsusp_mte_free_storage(); } else { - /* Clean kernel core startup/idle code to PoC*/ - dcache_clean_poc((unsigned long)__mmuoff_data_start, - (unsigned long)__mmuoff_data_end); - dcache_clean_poc((unsigned long)__idmap_text_start, - (unsigned long)__idmap_text_end); - - /* Clean kvm setup code to PoC? */ - if (el2_reset_needed()) { - dcache_clean_poc((unsigned long)__hyp_idmap_text_start, - (unsigned long)__hyp_idmap_text_end); - dcache_clean_poc((unsigned long)__hyp_text_start, - (unsigned long)__hyp_text_end); - } - swsusp_mte_restore_tags(); =20 /* make the crash dump kernel image protected again */ @@ -420,8 +396,12 @@ int __nocfi swsusp_arch_resume(void) size_t exit_size; pgd_t *tmp_pg_dir; phys_addr_t el2_vectors; - void __noreturn (*hibernate_exit)(phys_addr_t, phys_addr_t, void *, - void *, phys_addr_t, phys_addr_t); + + void (*hibernate_exit)(phys_addr_t zero_page, phys_addr_t temp_pgd, + void *pblist, void *kstart, void *kend, + phys_addr_t cpu_resume, + unsigned long el2) __noreturn; + struct trans_pgd_info trans_info =3D { .trans_alloc_page =3D hibernate_page_alloc, .trans_alloc_arg =3D (__force void *)GFP_ATOMIC, @@ -487,11 +467,14 @@ int __nocfi swsusp_arch_resume(void) * same state : with all DAIF exceptions masked. */ local_daif_save(); - hibernate_exit(virt_to_phys(tmp_pg_dir), resume_hdr.ttbr1_el1, - resume_hdr.reenter_kernel, restore_pblist, - resume_hdr.__hyp_stub_vectors, virt_to_phys(zero_page)); + hibernate_exit(virt_to_phys(zero_page), + virt_to_phys(tmp_pg_dir), + restore_pblist, + phys_to_virt(resume_hdr.kernel_start), + phys_to_virt(resume_hdr.kernel_end), + resume_hdr.reenter_kernel, + el2_reset_needed()); unreachable(); - return 0; } =20 diff --git a/arch/arm64/kernel/sleep.S b/arch/arm64/kernel/sleep.S index da45ab63bd9c..8c63ffdf6d75 100644 --- a/arch/arm64/kernel/sleep.S +++ b/arch/arm64/kernel/sleep.S @@ -107,19 +107,16 @@ SYM_CODE_START(cpu_resume) adrp x1, swapper_pg_dir adrp x2, idmap_pg_dir bl __enable_mmu - ldr x8, =3D__cpu_resume_switched_finalise_el2 + ldr x8, =3D__cpu_resume_switched br x8 SYM_CODE_END(cpu_resume) .ltorg .popsection =20 -SYM_FUNC_START_LOCAL(__cpu_resume_switched_finalise_el2) +SYM_FUNC_START_LOCAL(__cpu_resume_switched) mov x0, x19 bl finalise_el2 - b __cpu_resume_switched -SYM_FUNC_END(__cpu_resume_switched_finalise_el2) =20 -SYM_FUNC_START(__cpu_resume_switched) mrs x1, mpidr_el1 adr_l x8, mpidr_hash // x8 =3D struct mpidr_hash virt address =20 --=20 2.47.3