From patchwork Thu Mar 20 01:55:50 2025 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Changyuan Lyu X-Patchwork-Id: 14023315 Return-Path: X-Spam-Checker-Version: SpamAssassin 3.4.0 (2014-02-07) on aws-us-west-2-korg-lkml-1.web.codeaurora.org Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id D4645C36002 for ; Thu, 20 Mar 2025 01:56:49 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 04712280011; Wed, 19 Mar 2025 21:56:27 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id F116B280001; Wed, 19 Mar 2025 21:56:26 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id D64DF280011; Wed, 19 Mar 2025 21:56:26 -0400 (EDT) X-Delivered-To: linux-mm@kvack.org Received: from relay.hostedemail.com (smtprelay0016.hostedemail.com [216.40.44.16]) by kanga.kvack.org (Postfix) with ESMTP id B4E2B280001 for ; Wed, 19 Mar 2025 21:56:26 -0400 (EDT) Received: from smtpin03.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay10.hostedemail.com (Postfix) with ESMTP id 3410AC08E1 for ; Thu, 20 Mar 2025 01:56:27 +0000 (UTC) X-FDA: 83240264814.03.C6BB0D4 Received: from mail-pl1-f201.google.com (mail-pl1-f201.google.com [209.85.214.201]) by imf30.hostedemail.com (Postfix) with ESMTP id 978F580002 for ; Thu, 20 Mar 2025 01:56:25 +0000 (UTC) Authentication-Results: imf30.hostedemail.com; dkim=pass header.d=google.com header.s=20230601 header.b=KICoNkro; spf=pass (imf30.hostedemail.com: domain of 3yHXbZwoKCGcHMFSLdZFSQLTTLQJ.HTRQNSZc-RRPaFHP.TWL@flex--changyuanl.bounces.google.com designates 209.85.214.201 as permitted sender) smtp.mailfrom=3yHXbZwoKCGcHMFSLdZFSQLTTLQJ.HTRQNSZc-RRPaFHP.TWL@flex--changyuanl.bounces.google.com; dmarc=pass (policy=reject) header.from=google.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1742435785; h=from:from:sender:reply-to:subject:subject:date:date: message-id:message-id:to:to:cc:cc:mime-version:mime-version: content-type:content-type:content-transfer-encoding: in-reply-to:in-reply-to:references:references:dkim-signature; bh=+uiHbtbR2+LTCG9tPghyUo9+PEq69RRB7eOXIX8kmmQ=; b=cFo5P5X3bUAjV32D8+mlAlNWy2YNfrGMioCsoVNeD+HH77RQNZLS469hWMB10LHVaTdsrf iHrAB3Z/8mW/ypA8mgRFovNtmAWuO3JejBx2+U+Ec+5YbbkcMR4uCfDC5Zt1SfCJkm9qAE LKN9vP/m2Ue41gEmNhhAh0NGS0iLvMk= ARC-Authentication-Results: i=1; imf30.hostedemail.com; dkim=pass header.d=google.com header.s=20230601 header.b=KICoNkro; spf=pass (imf30.hostedemail.com: domain of 3yHXbZwoKCGcHMFSLdZFSQLTTLQJ.HTRQNSZc-RRPaFHP.TWL@flex--changyuanl.bounces.google.com designates 209.85.214.201 as permitted sender) smtp.mailfrom=3yHXbZwoKCGcHMFSLdZFSQLTTLQJ.HTRQNSZc-RRPaFHP.TWL@flex--changyuanl.bounces.google.com; dmarc=pass (policy=reject) header.from=google.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1742435785; a=rsa-sha256; cv=none; b=aChAUFmxyxYchEyzUk9epCgpKJurSttdToHEya9dWAvYfKEjx8FIe5A2IAkQUEMMiKbU56 BEEAmavqLzSlWVZh5QINsh359+2MvilYEmoFl89GFJPdPK9CKaszr/TfRUAeJ/sqtzJHnQ 89u3LRPwZlDawv9YXoJnOEa02EszX0Q= Received: by mail-pl1-f201.google.com with SMTP id d9443c01a7336-2255ae39f8fso26184295ad.0 for ; Wed, 19 Mar 2025 18:56:25 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1742435784; x=1743040584; darn=kvack.org; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:from:to:cc:subject:date:message-id:reply-to; bh=+uiHbtbR2+LTCG9tPghyUo9+PEq69RRB7eOXIX8kmmQ=; b=KICoNkroLqPmO/4SDmOgwynUy6CiOLsC6pk2ezM7zF/B3g4O1cx6seFT5LfLhh299m et/DYQee+zYFX+IxWN4VDSoiBCJ/aSNMsQoOQI4kP5j6+npCV4i3miNTA301t9fjiyOE rdk60P5U7WNio+Fhk24Xt6XEPWovs4/3w8A9ZHO212GYpNNzpKcyWuno/MbH/RCnzk9p QG+Fedr/LxfD32NeQF9riXDRNI2r3s5gW3B6KNe7iJYk2ZVD92R9bSh2QI2FnsrSzf+p +a5KduR/yxHzAqN9/NKcgZP6YXorXZmwn8vEj9HNPV4+Zg3ffR8n4BU1oIlv91bNhBbz Q1Ww== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1742435784; x=1743040584; h=cc:to:from:subject:message-id:references:mime-version:in-reply-to :date:x-gm-message-state:from:to:cc:subject:date:message-id:reply-to; bh=+uiHbtbR2+LTCG9tPghyUo9+PEq69RRB7eOXIX8kmmQ=; b=FKXkdq5oM+HMsOVzxEPv/adJEsyq+C3kx6pFtCkRE6ZFoNqiyeVj7zBZPSuE6RsdpF wfNV7finzCkSnYuVkR0ZQLRVSkjTMo0esSIO7Ywa/MU22X4EFdZcJCNiG92UiRv4anlY /Y10gbAwJ/fNrbEtE4XB1KPVd6E5WWZ91dyZFl7TQblyhgio+UdKIVNmmea6Ostoyw8X 5Xutn1Mj451QLQqTHWsfGbNuZbxoe5khZSvhX5QFwRyu5JQOCjS15mErx064VXgcAyjJ uTC560Iv+fHS5lhBwkQ8w+yutO1PZgeN5DmIbMjko070pVBt1DvaKaOr+mGdY0kxDaEU wUcQ== X-Forwarded-Encrypted: i=1; AJvYcCWe1jV6mIyAuju6zqFIjaHOG2/HgMUo7UTUCZJyF4YcM+WUkAahxRf3vLQ8g0ytGZmLWfbiIQdgLA==@kvack.org X-Gm-Message-State: AOJu0Yzd51RzYgwiOYw1AHAG3dO3T9o5iflAlf9L0cB+c3gm0vKE9ZOL 9QksAYfKz9b8CwSX8l4JUI8sc0Ujc6o1TSxuJkGNQCyvNTpkayc2ea536nGgnKSwMfTC+ZjHscW 4Q75B08iPunv24/Rhkg== X-Google-Smtp-Source: AGHT+IGco0TbFvrpWaz7RU09LVDLIbrwQOB0hzzeh7i66UCW7yrWSDQtXXKFJgzbGrQWcK/LzqGUCqggvCd+K/bd X-Received: from pgvr15.prod.google.com ([2002:a65:60cf:0:b0:ad8:bdc2:8a33]) (user=changyuanl job=prod-delivery.src-stubby-dispatcher) by 2002:a05:6a21:69c:b0:1f5:8bf4:fde0 with SMTP id adf61e73a8af0-1fd0904c18cmr2493103637.9.1742435784427; Wed, 19 Mar 2025 18:56:24 -0700 (PDT) Date: Wed, 19 Mar 2025 18:55:50 -0700 In-Reply-To: <20250320015551.2157511-1-changyuanl@google.com> Mime-Version: 1.0 References: <20250320015551.2157511-1-changyuanl@google.com> X-Mailer: git-send-email 2.49.0.rc1.451.g8f38331e32-goog Message-ID: <20250320015551.2157511-16-changyuanl@google.com> Subject: [PATCH v5 15/16] memblock: add KHO support for reserve_mem From: Changyuan Lyu To: linux-kernel@vger.kernel.org Cc: graf@amazon.com, akpm@linux-foundation.org, luto@kernel.org, anthony.yznaga@oracle.com, arnd@arndb.de, ashish.kalra@amd.com, benh@kernel.crashing.org, bp@alien8.de, catalin.marinas@arm.com, dave.hansen@linux.intel.com, dwmw2@infradead.org, ebiederm@xmission.com, mingo@redhat.com, jgowans@amazon.com, corbet@lwn.net, krzk@kernel.org, rppt@kernel.org, mark.rutland@arm.com, pbonzini@redhat.com, pasha.tatashin@soleen.com, hpa@zytor.com, peterz@infradead.org, ptyadav@amazon.de, robh+dt@kernel.org, robh@kernel.org, saravanak@google.com, skinsburskii@linux.microsoft.com, rostedt@goodmis.org, tglx@linutronix.de, thomas.lendacky@amd.com, usama.arif@bytedance.com, will@kernel.org, devicetree@vger.kernel.org, kexec@lists.infradead.org, linux-arm-kernel@lists.infradead.org, linux-doc@vger.kernel.org, linux-mm@kvack.org, x86@kernel.org, Changyuan Lyu X-Rspam-User: X-Rspamd-Queue-Id: 978F580002 X-Rspamd-Server: rspam08 X-Stat-Signature: mi8umushbpj4ygf44487qrfsxc6r45jj X-HE-Tag: 1742435785-450515 X-HE-Meta: U2FsdGVkX1/zxSosrJFEMya2LjWIP7hwjpafGCjjuQ4h2uEF0JpAAL8O7JXAO0QT9UgeO8wC3O17uyoJImHzLcyO+KAdrVRprcsfyIaMq/Dk3yhGNcKiUQSBin5HVhLdYC/vQ6Nrzj2CJsVdNn5pPh+nrwcvPjvKeKGUxIra0ET449l5oa2jKK3eZv5LCjsRdwhl7ZvfoBk5CdtBhOuCsfU8jHVbwI494RIgoSI/kwap1bIaSq8nmn4c6pkEXj2ryHpay62f04Ac/YzfPd1qFXdTb9GbkUPxx3dFlCJ9U+iEdkup28tNX7w4HzeAoHDRYpjqLPcfL7nyR0BUtCuwc9QrzhDYh7hjx9QFWQRONASrJvxhAgx7T219VmHzvw+Hau7+4HsmbwY/TgRvPxCwgo+WQNDI3l/1XwZWuFj3gHqLSn8O9bhrGKbHkAxpCyvctHt36xog4Frd2OmMd1c6QtbRRFN1QvGbvVjtjRDzmP2jWCXYxului4Yp7Kzjvi1FbOhQrxYvCJscjqAPDsGRRXaKitWXM7aYVDUgucLZIWQSjSlZDeVrkHg+aDtiRVCDuZDx7s5UdLxXMrXfmG7SvXlCwSxziFqGZZoh15ipdcyqDqNiFzsVIqrYP0yk+J+S3WCjiReVknZ9mB2aEJKzvRHN2R1bNp3m+Up9T/wUG0dJIzJMiNQOq27DhzMX42zqkg2L81fNBQ4hAPhuqo//1Yiu0HSMb+j9WKuPORdUnSrvMVUrwvLS3ncZKaeFiHmRE75xzmK01MF0gZU98ahoScxh7YYdANmUTf+zAA2P1kpjq23XGU8Ne45aYCCVnjxVc1HlYgCwxqmlsLC36Xc4NLw7KgKSd+RajoL3KxS1czMWZKuGVtf7yyWvJXaOXC9RqxMw+HMglGR0B4Rqas5bcgsMQYDs5E/3cH3DB3Yh2Noyo0YYUtxeWCH9XXQxVURqsx4f+qEM7aHLjh3WazG nDMymkey SV8G4gxMsy8vjC6H23Yt0q3RA43wH9jhIjoF3iIKNyayO3N9mPT/TLIrAg0nYerf+5kq9cotXA+QnElPtNMSRmNmTabMMnY/qEB7TegDbqS2j7x4EqT0QG8NH3LP7PZWIaZuFFM99/mmcFZDa2Ex0gazaap71Z6aAoU1JW9JdBacf0FqtMg1yEp6VrSnUuN7O1/tkskjY1USrxVSAAvqlm2HldvMt9G2u1szBcs8i4Tlhyj+qnRkygGm8OGVOiFAp5Nu8n4uygYtOkN14qh7TNVGtHKTYxmdMcslhAIpiaKWNakHEGdnZ9yn50AfRFiyAAk7Hki/gj6YaVobk4h7LKb9jNY+6V/wPCs5hBA8BQmeVi1H8/yJHpIqUzJC+zzUasNYieR2RR+OyQK93DGILtj2VwlzXoUqXwnKk 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: List-Subscribe: List-Unsubscribe: From: Alexander Graf Linux has recently gained support for "reserve_mem": A mechanism to allocate a region of memory early enough in boot that we can cross our fingers and hope it stays at the same location during most boots, so we can store for example ftrace buffers into it. Thanks to KASLR, we can never be really sure that "reserve_mem" allocations are static across kexec. Let's teach it KHO awareness so that it serializes its reservations on kexec exit and deserializes them again on boot, preserving the exact same mapping across kexec. This is an example user for KHO in the KHO patch set to ensure we have at least one (not very controversial) user in the tree before extending KHO's use to more subsystems. Signed-off-by: Alexander Graf Co-developed-by: Mike Rapoport (Microsoft) Signed-off-by: Mike Rapoport (Microsoft) Co-developed-by: Changyuan Lyu Signed-off-by: Changyuan Lyu --- mm/memblock.c | 179 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 179 insertions(+) diff --git a/mm/memblock.c b/mm/memblock.c index d28abf3def1c..dd698c55b87e 100644 --- a/mm/memblock.c +++ b/mm/memblock.c @@ -17,6 +17,10 @@ #include #include +#ifdef CONFIG_KEXEC_HANDOVER +#include +#endif /* CONFIG_KEXEC_HANDOVER */ + #include #include @@ -2431,6 +2435,176 @@ int reserve_mem_find_by_name(const char *name, phys_addr_t *start, phys_addr_t * } EXPORT_SYMBOL_GPL(reserve_mem_find_by_name); +#ifdef CONFIG_KEXEC_HANDOVER +#define MEMBLOCK_KHO_NODE "memblock" +#define MEMBLOCK_KHO_NODE_COMPATIBLE "memblock-v1" +#define RESERVE_MEM_KHO_NODE_COMPATIBLE "reserve-mem-v1" + +static struct kho_node memblock_kho_node = KHO_NODE_INIT; + +static void reserve_mem_kho_reset(void) +{ + int i; + struct kho_node *node; + + kho_remove_node(NULL, MEMBLOCK_KHO_NODE); + kho_remove_prop(&memblock_kho_node, "compatible", NULL); + + for (i = 0; i < reserved_mem_count; i++) { + struct reserve_mem_table *map = &reserved_mem_table[i]; + + node = kho_remove_node(&memblock_kho_node, map->name); + if (IS_ERR(node)) + continue; + + kho_unpreserve_phys(map->start, map->size); + + kho_remove_prop(node, "compatible", NULL); + kho_remove_prop(node, "start", NULL); + kho_remove_prop(node, "size", NULL); + + kfree(node); + } +} + +static int reserve_mem_kho_finalize(void) +{ + int i, err = 0; + struct kho_node *node; + + if (!reserved_mem_count) + return NOTIFY_DONE; + + err = kho_add_node(NULL, MEMBLOCK_KHO_NODE, &memblock_kho_node); + if (err == 1) + return NOTIFY_DONE; + + err |= kho_add_string_prop(&memblock_kho_node, "compatible", + MEMBLOCK_KHO_NODE_COMPATIBLE); + + for (i = 0; i < reserved_mem_count; i++) { + struct reserve_mem_table *map = &reserved_mem_table[i]; + + node = kmalloc(sizeof(*node), GFP_KERNEL); + if (!node) { + err = -ENOMEM; + break; + } + + err |= kho_preserve_phys(map->start, map->size); + + kho_init_node(node); + err |= kho_add_string_prop(node, "compatible", + RESERVE_MEM_KHO_NODE_COMPATIBLE); + err |= kho_add_prop(node, "start", &map->start, + sizeof(map->start)); + err |= kho_add_prop(node, "size", &map->size, + sizeof(map->size)); + err |= kho_add_node(&memblock_kho_node, map->name, node); + + if (err) + break; + } + + if (err) { + pr_err("failed to save reserve_mem to KHO: %d\n", err); + reserve_mem_kho_reset(); + return NOTIFY_STOP; + } + + return NOTIFY_DONE; +} + +static int reserve_mem_kho_notifier(struct notifier_block *self, + unsigned long cmd, void *v) +{ + switch (cmd) { + case KEXEC_KHO_FINALIZE: + return reserve_mem_kho_finalize(); + case KEXEC_KHO_UNFREEZE: + return NOTIFY_DONE; + default: + return NOTIFY_BAD; + } +} + +static struct notifier_block reserve_mem_kho_nb = { + .notifier_call = reserve_mem_kho_notifier, +}; + +static int __init reserve_mem_init(void) +{ + if (!kho_is_enabled()) + return 0; + + return register_kho_notifier(&reserve_mem_kho_nb); +} +core_initcall(reserve_mem_init); + +static bool __init reserve_mem_kho_revive(const char *name, phys_addr_t size, + phys_addr_t align) +{ + int err, len_start, len_size; + struct kho_in_node node, child; + const phys_addr_t *p_start, *p_size; + + err = kho_get_node(NULL, MEMBLOCK_KHO_NODE, &node); + if (err) + return false; + + err = kho_node_check_compatible(&node, MEMBLOCK_KHO_NODE_COMPATIBLE); + if (err) { + pr_warn("Node '%s' is incompatible with %s: %d\n", + MEMBLOCK_KHO_NODE, MEMBLOCK_KHO_NODE_COMPATIBLE, err); + return false; + } + + err = kho_get_node(&node, name, &child); + if (err) { + pr_warn("Node '%s' has no child '%s': %d\n", + MEMBLOCK_KHO_NODE, name, err); + return false; + } + err = kho_node_check_compatible(&child, RESERVE_MEM_KHO_NODE_COMPATIBLE); + if (err) { + pr_warn("Node '%s/%s' is incompatible with %s: %d\n", + MEMBLOCK_KHO_NODE, name, + RESERVE_MEM_KHO_NODE_COMPATIBLE, err); + return false; + } + + p_start = kho_get_prop(&child, "start", &len_start); + p_size = kho_get_prop(&child, "size", &len_size); + if (!p_start || len_start != sizeof(*p_start) || !p_size || + len_size != sizeof(*p_size)) { + return false; + } + + if (*p_start & (align - 1)) { + pr_warn("KHO reserve-mem '%s' has wrong alignment (0x%lx, 0x%lx)\n", + name, (long)align, (long)*p_start); + return false; + } + + if (*p_size != size) { + pr_warn("KHO reserve-mem '%s' has wrong size (0x%lx != 0x%lx)\n", + name, (long)*p_size, (long)size); + return false; + } + + reserved_mem_add(*p_start, size, name); + pr_info("Revived memory reservation '%s' from KHO\n", name); + + return true; +} +#else +static bool __init reserve_mem_kho_revive(const char *name, phys_addr_t size, + phys_addr_t align) +{ + return false; +} +#endif /* CONFIG_KEXEC_HANDOVER */ + /* * Parse reserve_mem=nn:align:name */ @@ -2486,6 +2660,11 @@ static int __init reserve_mem(char *p) if (reserve_mem_find_by_name(name, &start, &tmp)) return -EBUSY; + /* Pick previous allocations up from KHO if available */ + if (reserve_mem_kho_revive(name, size, align)) + return 1; + + /* TODO: Allocation must be outside of scratch region */ start = memblock_phys_alloc(size, align); if (!start) return -ENOMEM;