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 Received: from kanga.kvack.org (kanga.kvack.org [205.233.56.17]) by smtp.lore.kernel.org (Postfix) with ESMTP id B0248C369DC for ; Thu, 1 May 2025 22:55:54 +0000 (UTC) Received: by kanga.kvack.org (Postfix) id 5922D6B00B2; Thu, 1 May 2025 18:55:43 -0400 (EDT) Received: by kanga.kvack.org (Postfix, from userid 40) id 52C0B6B00B3; Thu, 1 May 2025 18:55:43 -0400 (EDT) X-Delivered-To: int-list-linux-mm@kvack.org Received: by kanga.kvack.org (Postfix, from userid 63042) id 395186B00B4; Thu, 1 May 2025 18:55:43 -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 111E06B00B2 for ; Thu, 1 May 2025 18:55:43 -0400 (EDT) Received: from smtpin08.hostedemail.com (a10.router.float.18 [10.200.18.1]) by unirelay05.hostedemail.com (Postfix) with ESMTP id EF7E180BA8 for ; Thu, 1 May 2025 22:55:43 +0000 (UTC) X-FDA: 83395847766.08.F46B64E Received: from mail-pl1-f202.google.com (mail-pl1-f202.google.com [209.85.214.202]) by imf20.hostedemail.com (Postfix) with ESMTP id 1EB831C0009 for ; Thu, 1 May 2025 22:55:41 +0000 (UTC) Authentication-Results: imf20.hostedemail.com; dkim=pass header.d=google.com header.s=20230601 header.b=SxgzvXjo; dmarc=pass (policy=reject) header.from=google.com; spf=pass (imf20.hostedemail.com: domain of 37fsTaAoKCHwhmfsl3zfsqlttlqj.htrqnsz2-rrp0fhp.twl@flex--changyuanl.bounces.google.com designates 209.85.214.202 as permitted sender) smtp.mailfrom=37fsTaAoKCHwhmfsl3zfsqlttlqj.htrqnsz2-rrp0fhp.twl@flex--changyuanl.bounces.google.com ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d=hostedemail.com; s=arc-20220608; t=1746140142; 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=MfewFjZZgA0wbLHZ0utjYl4REWcdoeGGCmHLPQc1YQk=; b=bbj0IStLMqkpBlTTgE3trwhhioLvwEXA/5EFZbCGRgO7WgrJWws3qJ2ObWylIRbbrXzWS1 U3MvT1xofsHMiA98zLKrDVY4OXx7CYeyXjiTvYBp/3Nwt2ToDLSEyKeSporX+YoQ6Rz+Gl dV6mS1LTMiHiCO94UM9bdos6fM76PfM= ARC-Authentication-Results: i=1; imf20.hostedemail.com; dkim=pass header.d=google.com header.s=20230601 header.b=SxgzvXjo; dmarc=pass (policy=reject) header.from=google.com; spf=pass (imf20.hostedemail.com: domain of 37fsTaAoKCHwhmfsl3zfsqlttlqj.htrqnsz2-rrp0fhp.twl@flex--changyuanl.bounces.google.com designates 209.85.214.202 as permitted sender) smtp.mailfrom=37fsTaAoKCHwhmfsl3zfsqlttlqj.htrqnsz2-rrp0fhp.twl@flex--changyuanl.bounces.google.com ARC-Seal: i=1; s=arc-20220608; d=hostedemail.com; t=1746140142; a=rsa-sha256; cv=none; b=hyXpm2nFSgLtRKzFeEX5Htf5wzuRILA29ZsPZZ/VdbKvjtxzjAyUwdsz3sl1e7+47YFqZk i1gdFXWRDjxvYq4E4p1PeznWInz7BYtDkkcz6VBOacnMsRp7xSwJQiaHu0IaHyP5qmYRq3 o707DzJoHAJoGNTgvNNNpMkTiYAD33E= Received: by mail-pl1-f202.google.com with SMTP id d9443c01a7336-224364f2492so13167155ad.3 for ; Thu, 01 May 2025 15:55:41 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=google.com; s=20230601; t=1746140141; x=1746744941; 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=MfewFjZZgA0wbLHZ0utjYl4REWcdoeGGCmHLPQc1YQk=; b=SxgzvXjozTIvu8V/LSI63jAqYfXKNmJ9+wiT/NHOZu0YVc/jWPZlm5jvb833moNLYr jb8Ka71FACTMmPMuSVV4zI6/paKE4tnVGVMBY8S5bYJ2piw+G0oG1AmnMtTAeCH3PA6n mDlm+LgzOgISnuRfYBg4QA8ddkGy4VXb+5E76RJIa/Z8BTdGqUTctgNzytHIpi9lFbJw VJfk8WXKPIxj76FQXKdnW7KsfSRAQ+eLgVRXxY/+CFKP3KsJUzOufYwdr9b2IG7FdprE bHokALvG3qXikvNsUq+AS8MdvlIdY0AnpPx1pZIb47+H/3YlonN4lUIxPyLalytfBXEm 8gHQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1746140141; x=1746744941; 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=MfewFjZZgA0wbLHZ0utjYl4REWcdoeGGCmHLPQc1YQk=; b=AMMeLpb829s7hO10Kr5pDrojARzIBUyUVTETZWjhafAarQG5EoRaeondbdaSiVJDGz Dn7fR70FmGeCYvIdwRvRhyd1nvA2gDXhc3UuCOmDh5v5gZzjB105AFFx1sihSud+o5F3 ZFWSTVCOg9mrCbDbDIiTv2at9x7dEDQJrZzfD6UYeJJtxJYqVSlwm5tqOzLFiiio9aDz eLv/FSS0pTTWJgm1zmEOgxMNcv269aPE9xigqZnELX4qm8YZUdiTdJTIZZUv49A4+GzJ +cWUxhEgULehUYNVGRDzs9vik0tCV8GVCTUR5PEr7CD3NcO7bRJIw0jdClY7lkTZOvW8 +J8w== X-Forwarded-Encrypted: i=1; AJvYcCXygQ1M1LYddOO8nD+CHwRAuipcOYCR3x6n6TAgRxF8bfUUBi/RodMZY5AJMUTNU3tWzsB8Bt5LZw==@kvack.org X-Gm-Message-State: AOJu0YyDpRw69y2ewxdWeZsMpHnIXd1eTwynu5oonwNBMjlLdfvMYSRz xc2YgdbrPCLvNcWHU+WOJrKHQ5nb+fzsgc5FJe26qkkkeKYnvrJ8oCEOwUXc2nw1BCabjYFNr2E r3EtoHFlnFldPSx9aNA== X-Google-Smtp-Source: AGHT+IGItHhc8YdkABGJyaGvVxl19Y7R7MBDsRAPRNtryCWPo0I1aAnulHG4c/Jmy4vZoSyaAqXIqrI14d7kkyuV X-Received: from plq10.prod.google.com ([2002:a17:903:2f8a:b0:22c:31cd:5f2e]) (user=changyuanl job=prod-delivery.src-stubby-dispatcher) by 2002:a17:903:1a6b:b0:225:adf8:8634 with SMTP id d9443c01a7336-22e103ca1b3mr10294705ad.51.1746140141096; Thu, 01 May 2025 15:55:41 -0700 (PDT) Date: Thu, 1 May 2025 15:54:23 -0700 In-Reply-To: <20250501225425.635167-1-changyuanl@google.com> Mime-Version: 1.0 References: <20250501225425.635167-1-changyuanl@google.com> X-Mailer: git-send-email 2.49.0.906.g1f30a19c02-goog Message-ID: <20250501225425.635167-17-changyuanl@google.com> Subject: [PATCH v7 16/18] memblock: add KHO support for reserve_mem From: Changyuan Lyu To: linux-kernel@vger.kernel.org Cc: changyuanl@google.com, akpm@linux-foundation.org, anthony.yznaga@oracle.com, arnd@arndb.de, ashish.kalra@amd.com, benh@kernel.crashing.org, bp@alien8.de, catalin.marinas@arm.com, corbet@lwn.net, dave.hansen@linux.intel.com, devicetree@vger.kernel.org, dwmw2@infradead.org, ebiederm@xmission.com, graf@amazon.com, hpa@zytor.com, jgowans@amazon.com, kexec@lists.infradead.org, krzk@kernel.org, linux-arm-kernel@lists.infradead.org, linux-doc@vger.kernel.org, linux-mm@kvack.org, luto@kernel.org, mark.rutland@arm.com, mingo@redhat.com, pasha.tatashin@soleen.com, pbonzini@redhat.com, peterz@infradead.org, ptyadav@amazon.de, robh@kernel.org, rostedt@goodmis.org, rppt@kernel.org, saravanak@google.com, skinsburskii@linux.microsoft.com, tglx@linutronix.de, thomas.lendacky@amd.com, will@kernel.org, x86@kernel.org Content-Type: text/plain; charset="UTF-8" X-Stat-Signature: n1dhss1nremwwim37z3bribkfnn6bc96 X-Rspamd-Queue-Id: 1EB831C0009 X-Rspam-User: X-Rspamd-Server: rspam05 X-HE-Tag: 1746140141-387505 X-HE-Meta: U2FsdGVkX1/8WFfRs/ZDvjOIYvBAnzygqMbL/sOs2lKtuOXcRjfXcoqeQk4gog9VkBjUZ+64rtM+xdwoZ2I/5olmUYhoe3ksr2jeKTSz+kfs9/AqSD/VnaGJHeG7DouMrmtVHfknH+Rdq/xHiNU6OW+GPFUcbBGsesKS4J2rSMZf+kJ7HMYA8359S4HyinVi2yDTU4atagjX9Hgm7wnqZA8EZBG5iqnTmPKA45ENLnjoNBe7btI+kcYi8WdH1ZFsWOagxX4vS7/MelytB8JK8uj7d3r5HCAT6+ThxiJzpa0q73xVNftNZGUwGYAEitR0sTts8V3GZ1OwHwiTnfdQsgNIp1KsIHRNIydVrKULXB4vgz2NdBDDwgzkNaCItqM62XTQTslcHuiGY9IlrAq/uo6g0te/jDgahyZYjPbTneOyARJvbDjZ7B0JSS0oWjwW1vKCnMsf0S6mtIl+udtZw08kpLCtKk8mFQ3Qrq3pkQCexIBpXInj5t6U/mjefiH0/nT+CkYESlgq7yC/Cgq+RF8Zl+lNbUWggQgzWXi7Fk/2DmFLnIxOQBjqtHZ14V+rsIikCzz8RMjTbWYwkruCXxmF+QFpCclBJDfnGMQbHLB5KbkQU8fcgRlwle9kZenWKG2HpVf7jcFY2S3E4Snhbewcm2BbFm9HGYMbZ8jJ80ylNXQwXGj5o6NMrC8kimoIo3Gl3Jz5ftVWr8PzfA+McIXSz+qZlF029nMNucOoY/LI6tS8EQ6EUU3yEy2ozA44JpDBdWTubBapKJMrORH8V3/mdCgLIUZchgDxn90mBjSpIkrOdZxoiDtRKBHkxyC4S62KJ46kh6GrTBHvpB+ywgyQu4VXjYt9DjqX8vNzxqn3njuyQsPG2CG7cCJo17eeDv9Zzht0MtgZRr6WC3pP5YlHt0aFrJcW2bnPOtLLPrfqgvitRxo/z5ngIWJWn2eupYmJ7n25Ho97GIuSe91 kFAuGPjk PnYi8lg9QoFwuckzNlD2a1GhxJHIhig40FDpVGJ5vsVU5+nYT2kBn6yAmbqafZz4dQcJvVuRfuFruOL//Fwh4fA/EZ1vpD/7CPQ9P/NIisTIs+QstC0bYCpF1oTje15RwyJPs9SE3wksCNn+OfFTo7B/Oas/S2cTWU1vgHU5rP5hukEHzG1hKyH4QdYUgw7joDUx6ygR0DyTDDKbmExlIbt/N3C6ceYeLiNDlnoScOIV5dCa8RGXz0n7e8Ey535RuWcJTv2Jm/t2GA9FBkLVfCuxF5TBWDXwxf4solsvoRYb0TePfWI3df1MnPFcIbc1Tam00rELiG7MtNg5gmcDdt3DQF1rxjQjz6i1cHSfYBiM6PCQvG6JpnkUxzX1ZTp0ULHz3FCL/DM6MHMN4WHAKWo3k9euSGGXHR0rrwjGz+1Y26fws+K4nNBWTg9iGvY1Psizf0BqTu/OGmdph1uKLrmls/+gVy1sk6LQ19S70pt/hoJv3V2501ahq05g/W1eQPNcB+LEDCTlmlpdST/iFcLozq1+niKsUyllPTzEbPUwXotz56rcQn7nMt/+E/xChJFOPL8/UoUYeG59glxPWMbUj3Pw+fTBy+65Vvj230oJKilq8u7cHTVT82TG52n9CiJL4OPdM/rNg56NQ2BWnghKpUdY3lBkmTWYWOeEL2T2HJ/A= 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 | 200 ++++++++++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 200 insertions(+) diff --git a/mm/memblock.c b/mm/memblock.c index 9202c3412bb19..27b6325a65b00 100644 --- a/mm/memblock.c +++ b/mm/memblock.c @@ -18,6 +18,11 @@ #include #include +#ifdef CONFIG_KEXEC_HANDOVER +#include +#include +#endif /* CONFIG_KEXEC_HANDOVER */ + #include #include @@ -2475,6 +2480,196 @@ int reserve_mem_release_by_name(const char *name) return 1; } +#ifdef CONFIG_KEXEC_HANDOVER +#define MEMBLOCK_KHO_FDT "memblock" +#define MEMBLOCK_KHO_NODE_COMPATIBLE "memblock-v1" +#define RESERVE_MEM_KHO_NODE_COMPATIBLE "reserve-mem-v1" +static struct page *kho_fdt; + +static int reserve_mem_kho_finalize(struct kho_serialization *ser) +{ + int err = 0, i; + + for (i = 0; i < reserved_mem_count; i++) { + struct reserve_mem_table *map = &reserved_mem_table[i]; + + err |= kho_preserve_phys(map->start, map->size); + } + + err |= kho_preserve_folio(page_folio(kho_fdt)); + err |= kho_add_subtree(ser, MEMBLOCK_KHO_FDT, page_to_virt(kho_fdt)); + + return notifier_from_errno(err); +} + +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((struct kho_serialization *)v); + case KEXEC_KHO_ABORT: + return NOTIFY_DONE; + default: + return NOTIFY_BAD; + } +} + +static struct notifier_block reserve_mem_kho_nb = { + .notifier_call = reserve_mem_kho_notifier, +}; + +static int __init prepare_kho_fdt(void) +{ + int err = 0, i; + void *fdt; + + kho_fdt = alloc_page(GFP_KERNEL); + if (!kho_fdt) + return -ENOMEM; + + fdt = page_to_virt(kho_fdt); + + err |= fdt_create(fdt, PAGE_SIZE); + err |= fdt_finish_reservemap(fdt); + + err |= fdt_begin_node(fdt, ""); + err |= fdt_property_string(fdt, "compatible", MEMBLOCK_KHO_NODE_COMPATIBLE); + for (i = 0; i < reserved_mem_count; i++) { + struct reserve_mem_table *map = &reserved_mem_table[i]; + + err |= fdt_begin_node(fdt, map->name); + err |= fdt_property_string(fdt, "compatible", RESERVE_MEM_KHO_NODE_COMPATIBLE); + err |= fdt_property(fdt, "start", &map->start, sizeof(map->start)); + err |= fdt_property(fdt, "size", &map->size, sizeof(map->size)); + err |= fdt_end_node(fdt); + } + err |= fdt_end_node(fdt); + + err |= fdt_finish(fdt); + + if (err) { + pr_err("failed to prepare memblock FDT for KHO: %d\n", err); + put_page(kho_fdt); + kho_fdt = NULL; + } + + return err; +} + +static int __init reserve_mem_init(void) +{ + int err; + + if (!kho_is_enabled() || !reserved_mem_count) + return 0; + + err = prepare_kho_fdt(); + if (err) + return err; + + err = register_kho_notifier(&reserve_mem_kho_nb); + if (err) { + put_page(kho_fdt); + kho_fdt = NULL; + } + + return err; +} +late_initcall(reserve_mem_init); + +static void *__init reserve_mem_kho_retrieve_fdt(void) +{ + phys_addr_t fdt_phys; + struct folio *fdt_folio; + int err; + static void *fdt; + + if (fdt) + return fdt; + + err = kho_retrieve_subtree(MEMBLOCK_KHO_FDT, &fdt_phys); + if (err) { + if (err != -ENOENT) + pr_warn("failed to retrieve FDT '%s' from KHO: %d\n", + MEMBLOCK_KHO_FDT, err); + return NULL; + } + + fdt_folio = kho_restore_folio(fdt_phys); + if (!fdt_folio) { + pr_warn("failed to restore memblock KHO FDT (0x%llx)\n", fdt_phys); + return NULL; + } + + fdt = folio_address(fdt_folio); + + err = fdt_node_check_compatible(fdt, 0, MEMBLOCK_KHO_NODE_COMPATIBLE); + if (err) { + pr_warn("FDT '%s' is incompatible with '%s': %d\n", + MEMBLOCK_KHO_FDT, MEMBLOCK_KHO_NODE_COMPATIBLE, err); + fdt = NULL; + } + + return fdt; +} + +static bool __init reserve_mem_kho_revive(const char *name, phys_addr_t size, + phys_addr_t align) +{ + int err, len_start, len_size, offset; + const phys_addr_t *p_start, *p_size; + const void *fdt; + + fdt = reserve_mem_kho_retrieve_fdt(); + if (!fdt) + return false; + + offset = fdt_subnode_offset(fdt, 0, name); + if (offset < 0) { + pr_warn("FDT '%s' has no child '%s': %d\n", + MEMBLOCK_KHO_FDT, name, offset); + return false; + } + err = fdt_node_check_compatible(fdt, offset, RESERVE_MEM_KHO_NODE_COMPATIBLE); + if (err) { + pr_warn("Node '%s' is incompatible with '%s': %d\n", + name, RESERVE_MEM_KHO_NODE_COMPATIBLE, err); + return false; + } + + p_start = fdt_getprop(fdt, offset, "start", &len_start); + p_size = fdt_getprop(fdt, offset, "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 */ @@ -2530,6 +2725,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; -- 2.49.0.906.g1f30a19c02-goog