From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-9.8 required=3.0 tests=HEADER_FROM_DIFFERENT_DOMAINS, INCLUDES_PATCH,MAILING_LIST_MULTI,SIGNED_OFF_BY,SPF_HELO_NONE,SPF_PASS, USER_AGENT_GIT autolearn=ham autolearn_force=no version=3.4.0 Received: from mail.kernel.org (mail.kernel.org [198.145.29.99]) by smtp.lore.kernel.org (Postfix) with ESMTP id CB4A4C5518B for ; Wed, 22 Apr 2020 14:25:53 +0000 (UTC) Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by mail.kernel.org (Postfix) with ESMTP id 955FE2076E for ; Wed, 22 Apr 2020 14:25:53 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.3.2 mail.kernel.org 955FE2076E Authentication-Results: mail.kernel.org; dmarc=none (p=none dis=none) header.from=arm.com Authentication-Results: mail.kernel.org; spf=pass smtp.mailfrom=owner-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix) id C34588E002C; Wed, 22 Apr 2020 10:25:49 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id BBDC88E0003; Wed, 22 Apr 2020 10:25:49 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id A5FC98E002C; Wed, 22 Apr 2020 10:25:49 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from forelay.hostedemail.com (smtprelay0014.hostedemail.com [216.40.44.14]) by kanga.kvack.org (Postfix) with ESMTP id 8DE1F8E0003 for ; Wed, 22 Apr 2020 10:25:49 -0400 (EDT) Received: from smtpin13.hostedemail.com (10.5.19.251.rfc1918.com [10.5.19.251]) by forelay01.hostedemail.com (Postfix) with ESMTP id 45CC6180AD806 for ; Wed, 22 Apr 2020 14:25:49 +0000 (UTC) X-FDA: 76735714818.13.trade42_4fde26704741e X-HE-Tag: trade42_4fde26704741e X-Filterd-Recvd-Size: 5251 Received: from foss.arm.com (foss.arm.com [217.140.110.172]) by imf23.hostedemail.com (Postfix) with ESMTP for ; Wed, 22 Apr 2020 14:25:48 +0000 (UTC) Received: from usa-sjc-imap-foss1.foss.arm.com (unknown [10.121.207.14]) by usa-sjc-mx-foss1.foss.arm.com (Postfix) with ESMTP id 036B91042; Wed, 22 Apr 2020 07:25:48 -0700 (PDT) Received: from e112269-lin.arm.com (unknown [172.31.20.19]) by usa-sjc-imap-foss1.foss.arm.com (Postfix) with ESMTPSA id 8D26A3F68F; Wed, 22 Apr 2020 07:25:46 -0700 (PDT) From: Steven Price To: linux-arm-kernel@lists.infradead.org, linux-mm@kvack.org Cc: Steven Price , linux-arch@vger.kernel.org, Andrew Morton , Arnd Bergmann , Catalin Marinas , Hugh Dickins , Vincenzo Frascino , Will Deacon Subject: [PATCH 4/4] arm64: mte: Save tags when hibernating Date: Wed, 22 Apr 2020 15:25:30 +0100 Message-Id: <20200422142530.32619-5-steven.price@arm.com> X-Mailer: git-send-email 2.20.1 In-Reply-To: <20200422142530.32619-1-steven.price@arm.com> References: <20200422142530.32619-1-steven.price@arm.com> MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable X-Bogosity: Ham, tests=bogofilter, spamicity=0.000000, version=1.2.4 Sender: owner-linux-mm@kvack.org Precedence: bulk X-Loop: owner-majordomo@kvack.org List-ID: When hibernating the contents of all pages in the system are written to disk, however the MTE tags are not visible to the generic hibernation code. So just before the hibernation image is created copy the tags out of the physical tag storage into standard memory so they will be included in the hibernation image. After hibernation apply the tags back into the physical tag storage. Signed-off-by: Steven Price --- arch/arm64/kernel/hibernate.c | 116 ++++++++++++++++++++++++++++++++++ 1 file changed, 116 insertions(+) diff --git a/arch/arm64/kernel/hibernate.c b/arch/arm64/kernel/hibernate.= c index 5b73e92c99e3..b89429778b5d 100644 --- a/arch/arm64/kernel/hibernate.c +++ b/arch/arm64/kernel/hibernate.c @@ -31,6 +31,7 @@ #include #include #include +#include #include #include #include @@ -277,6 +278,115 @@ static int create_safe_exec_page(void *src_start, s= ize_t length, =20 #define dcache_clean_range(start, end) __flush_dcache_area(start, (end -= start)) =20 +#ifdef CONFIG_ARM64_MTE + +static DEFINE_XARRAY(mte_pages); + +static int save_tags(struct page *page, unsigned long pfn) +{ + void *tag_storage, *ret; + + tag_storage =3D mte_allocate_tag_storage(); + if (!tag_storage) + return -ENOMEM; + + mte_save_page_tags(page_address(page), tag_storage); + + ret =3D xa_store(&mte_pages, pfn, tag_storage, GFP_KERNEL); + if (WARN(xa_is_err(ret), "Failed to store MTE tags")) { + mte_free_tag_storage(tag_storage); + return xa_err(ret); + } else if (WARN(ret, "swsusp: %s: Duplicate entry", __func__)) { + mte_free_tag_storage(ret); + } + + return 0; +} + +static void swsusp_mte_free_storage(void) +{ + XA_STATE(xa_state, &mte_pages, 0); + void *tags; + + xa_lock(&mte_pages); + xas_for_each(&xa_state, tags, ULONG_MAX) { + mte_free_tag_storage(tags); + } + xa_unlock(&mte_pages); + + xa_destroy(&mte_pages); +} + +static int swsusp_mte_save_tags(void) +{ + struct zone *zone; + unsigned long pfn, max_zone_pfn; + int ret =3D 0; + int n =3D 0; + + if (!system_supports_mte()) + return 0; + + for_each_populated_zone(zone) { + max_zone_pfn =3D zone_end_pfn(zone); + for (pfn =3D zone->zone_start_pfn; pfn < max_zone_pfn; pfn++) { + struct page *page =3D pfn_to_online_page(pfn); + + if (!page) + continue; + + if (!test_bit(PG_mte_tagged, &page->flags)) + continue; + + ret =3D save_tags(page, pfn); + n++; + + if (ret) { + swsusp_mte_free_storage(); + goto out; + } + } + } + + pr_info("Saved %d MTE pages\n", n); + +out: + return ret; +} + +static void swsusp_mte_restore_tags(void) +{ + XA_STATE(xa_state, &mte_pages, 0); + int n =3D 0; + void *tags; + + xa_lock(&mte_pages); + xas_for_each(&xa_state, tags, ULONG_MAX) { + unsigned long pfn =3D xa_state.xa_index; + struct page *page =3D pfn_to_online_page(pfn); + + mte_restore_page_tags(page_address(page), tags); + + mte_free_tag_storage(tags); + n++; + } + xa_unlock(&mte_pages); + + pr_info("Restored %d MTE pages\n", n); + + xa_destroy(&mte_pages); +} +#else +static int swsusp_mte_save_tags(void) +{ + return 0; +} + +static void swsusp_mte_restore_tags(void) +{ +} +#endif + int swsusp_arch_suspend(void) { int ret =3D 0; @@ -294,6 +404,10 @@ int swsusp_arch_suspend(void) /* make the crash dump kernel image visible/saveable */ crash_prepare_suspend(); =20 + ret =3D swsusp_mte_save_tags(); + if (ret) + return ret; + sleep_cpu =3D smp_processor_id(); ret =3D swsusp_save(); } else { @@ -307,6 +421,8 @@ int swsusp_arch_suspend(void) dcache_clean_range(__hyp_text_start, __hyp_text_end); } =20 + swsusp_mte_restore_tags(); + /* make the crash dump kernel image protected again */ crash_post_resume(); =20 --=20 2.20.1