From nobody Sat Feb 7 05:52:34 2026 Received: from mail-qv1-f50.google.com (mail-qv1-f50.google.com [209.85.219.50]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D9F3B243956 for ; Sat, 18 Oct 2025 17:17:59 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.219.50 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760807881; cv=none; b=Ww4f2A2r90JtxDpzo5ZmOvdTGzEd/hxI2a/ug+4sYx1GFNFd33L3Nf4bdfv/+8B2vy4nRe5xkmCdBoqwAUmEiRu9hVYX+BB1foOdOBENXcLGjsN59g6y32S8FhDA8ZjOJZPjs1syUTQ2ggbsIZS/9Pqisc0QjfVkPkAnCkFKRN8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760807881; c=relaxed/simple; bh=CkP35o2g0f6Yvsli2hyfkcKcXjwIxr/BXO6CQisp2ZM=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=AzKv2PWpmLdUhEW0ED1PFA855tsBOHQWBRz4mZwMxtxMX9mrf01yzUSu8Z93ggYxE2SQvQsLSShKO+viK9g4uGs8BKZmA1eY9AZDGN9g3TXK5hs/Ks8DoBGe/0zuo+XdY6cbQdATlS7iv4gw0q6Sj8uoHVgzKKQlgxNeCpQwIOI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=soleen.com; spf=pass smtp.mailfrom=soleen.com; dkim=pass (2048-bit key) header.d=soleen.com header.i=@soleen.com header.b=A6QbQnPN; arc=none smtp.client-ip=209.85.219.50 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=soleen.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=soleen.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=soleen.com header.i=@soleen.com header.b="A6QbQnPN" Received: by mail-qv1-f50.google.com with SMTP id 6a1803df08f44-87c1a760df5so58504996d6.1 for ; Sat, 18 Oct 2025 10:17:59 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=soleen.com; s=google; t=1760807879; x=1761412679; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=G29XfdiPrhmaQm8Tird4J1gH3HStwZIQQCKqgD0mb8M=; b=A6QbQnPNcYAfbQZLvYTfd+ku2OYEMr1Gyty4wSOevhT2ZgmmQuIjNfrIayvKDbThtC JgH4JA16jBMJf0EgB7juCviHjy+NveUDe8KLe74HUeyH6dEd2Re1hyX0zR7fLNAydspz sIBzeZSmH3BrsdEImyviG/0xvcmOtKA1YGHIu9ElVmOSS6+R/adssyiclS/mm4lxwZZM 9+M94ajaLqwbkkWW/SogK+IZ7Wg9Zy8wrwiFyI698jAim9BCPXq8MtI1X5GX7yJi99DW u5Yyzqv53aVrwht3scSS2ElRNcizuaGLktyPBzugq9YyGCtRbR+/QXuoJX4abuy1lTRi e0dg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1760807879; x=1761412679; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=G29XfdiPrhmaQm8Tird4J1gH3HStwZIQQCKqgD0mb8M=; b=QG11Qj2LhWWD7auC6Fia4kAs8XNx47rtkq3W1jKoaLdRBmauEi9F8EOd23b+RGf3sB HuHpGxnr+kvBraBpQOSUPCbuVGTuipRmUEkChgFPKs5kk6oYHT5+Em9lPwbUgtuDLYM3 +yLwpY/2OWHpPebZPq7rPB5Lr8vJDmSS2XYqQ7rZKPzpc8KikCnpD/ZqUmKhuOfqrpTJ J7FH2NMxrWMpqoYYyPnngt6r01N66aLnwy0ztDBXg6Qmvj0rAuxMO7wgySX0AQ3yob3h wUVnvmwhgqO3iwxEId3hcPjpTczhH9BkPzLpTxPpYVf2ZHxMHoGqfpm6ifp8tkWBDz0b FtgQ== X-Forwarded-Encrypted: i=1; AJvYcCWWMctkzqLDnM4vAZT1wXYWclkL+8GOMGDqLIjqn092eE2I2Qwvmcy9BWrI7+Kz+7ENxcu7orZ7NJrdJ6A=@vger.kernel.org X-Gm-Message-State: AOJu0Yx2Z8pHn+uUzNBiwfZ9o6YOcEgwVRoGyjVNuN0HHUyoZiL18Rvw 1Rw8e0yK76HICjR+zw8fie+d/NAkkp2y7kztJ4EBag/bLD9Nj+DJ8aJYr5In+d+WyIo= X-Gm-Gg: ASbGncvrSjbQMh29szpaOmM/LaQh+9mwsATSbtT0zhYYL3+S2L9d7375ZZur66dmHlN P/NTSN4vM3+LLbaASvgZ+8fRbswEKhSOZKNG6z1X9t4Q4ID9tmR1CHllE2zAbm1V+RLogL7Hl2a wvoqWbI3rrKkec94cBGgYXUHBcqXxPtA4SJ9ArWm+dqPYFB4JCjOt3fH6lA9Temo2SLclzA/Xiw hr7nAHgPYFxan++rT139wQhAdO9abaz31K8qE+n0J7y7RVU4k6CjvNq2e53JD2KVJOE/SIYXhIE vKrvCsL2mF6lQ6RCvyxWgsltFwXKN5OaqqTY7tMhzKSg8iADUmtzSLpTe3GdKyenmq5BhHfNhNn 7nMwMSjZYG4XJOgFFk9ZGGJoo9sJoJHzcpwn5lggZfktjeKa6IVN0yJDHaAFr8h+5LciPEPBbIZ 7UbjNQrD5SKzoR5g8lorgwMWknQfGppQ6e1FSxYlfipiayQHC/iNIKCWzAIRCBICYTYWLEkYxLM sERYyWW8D649nz6EToGdw== X-Google-Smtp-Source: AGHT+IFUrn/ODTICOJeqybc9wpoG1rwCuTkHZDhaNQG6q4OMb39krbHuQ7xa84xnE8FoRgnLNMU84g== X-Received: by 2002:a05:6214:248a:b0:7a3:b6ab:6f2 with SMTP id 6a1803df08f44-87c206612e1mr126599836d6.63.1760807878808; Sat, 18 Oct 2025 10:17:58 -0700 (PDT) Received: from soleen.us-east4-b.c.cloudtop-prod-us-east.internal (53.47.86.34.bc.googleusercontent.com. [34.86.47.53]) by smtp.gmail.com with ESMTPSA id 6a1803df08f44-87d02d8e909sm18478116d6.62.2025.10.18.10.17.57 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 18 Oct 2025 10:17:58 -0700 (PDT) From: Pasha Tatashin To: akpm@linux-foundation.org, brauner@kernel.org, corbet@lwn.net, graf@amazon.com, jgg@ziepe.ca, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-mm@kvack.org, masahiroy@kernel.org, ojeda@kernel.org, pasha.tatashin@soleen.com, pratyush@kernel.org, rdunlap@infradead.org, rppt@kernel.org, tj@kernel.org, jasonmiu@google.com, dmatlack@google.com, skhawaja@google.com Subject: [PATCH v6 01/10] kho: allow to drive kho from within kernel Date: Sat, 18 Oct 2025 13:17:47 -0400 Message-ID: <20251018171756.1724191-2-pasha.tatashin@soleen.com> X-Mailer: git-send-email 2.51.0.915.g61a8936c21-goog In-Reply-To: <20251018171756.1724191-1-pasha.tatashin@soleen.com> References: <20251018171756.1724191-1-pasha.tatashin@soleen.com> 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" Allow to do finalize and abort from kernel modules, so LUO could drive the KHO sequence via its own state machine. Signed-off-by: Pasha Tatashin Reviewed-by: Pratyush Yadav --- include/linux/kexec_handover.h | 15 +++++++ kernel/kexec_handover.c | 74 ++++++++++++++++++++-------------- 2 files changed, 59 insertions(+), 30 deletions(-) diff --git a/include/linux/kexec_handover.h b/include/linux/kexec_handover.h index 25042c1d8d54..04d0108db98e 100644 --- a/include/linux/kexec_handover.h +++ b/include/linux/kexec_handover.h @@ -67,6 +67,10 @@ void kho_memory_init(void); =20 void kho_populate(phys_addr_t fdt_phys, u64 fdt_len, phys_addr_t scratch_p= hys, u64 scratch_len); + +int kho_finalize(void); +int kho_abort(void); + #else static inline bool kho_is_enabled(void) { @@ -139,6 +143,17 @@ static inline void kho_populate(phys_addr_t fdt_phys, = u64 fdt_len, phys_addr_t scratch_phys, u64 scratch_len) { } + +static inline int kho_finalize(void) +{ + return -EOPNOTSUPP; +} + +static inline int kho_abort(void) +{ + return -EOPNOTSUPP; +} + #endif /* CONFIG_KEXEC_HANDOVER */ =20 #endif /* LINUX_KEXEC_HANDOVER_H */ diff --git a/kernel/kexec_handover.c b/kernel/kexec_handover.c index 76f0940fb485..76c34ea923f0 100644 --- a/kernel/kexec_handover.c +++ b/kernel/kexec_handover.c @@ -1067,7 +1067,7 @@ static int kho_out_update_debugfs_fdt(void) return err; } =20 -static int kho_abort(void) +static int __kho_abort(void) { int err; unsigned long order; @@ -1100,7 +1100,27 @@ static int kho_abort(void) return err; } =20 -static int kho_finalize(void) +int kho_abort(void) +{ + int ret =3D 0; + + if (!kho_enable) + return -EOPNOTSUPP; + + guard(mutex)(&kho_out.lock); + if (!kho_out.finalized) + return -ENOENT; + + ret =3D __kho_abort(); + if (ret) + return ret; + + kho_out.finalized =3D false; + + return kho_out_update_debugfs_fdt(); +} + +static int __kho_finalize(void) { int err =3D 0; u64 *preserved_mem_map; @@ -1143,12 +1163,32 @@ static int kho_finalize(void) abort: if (err) { pr_err("Failed to convert KHO state tree: %d\n", err); - kho_abort(); + __kho_abort(); } =20 return err; } =20 +int kho_finalize(void) +{ + int ret; + + if (!kho_enable) + return -EOPNOTSUPP; + + guard(mutex)(&kho_out.lock); + if (kho_out.finalized) + return -EEXIST; + + ret =3D __kho_finalize(); + if (ret) + return ret; + + kho_out.finalized =3D true; + + return kho_out_update_debugfs_fdt(); +} + static int kho_out_finalize_get(void *data, u64 *val) { mutex_lock(&kho_out.lock); @@ -1160,33 +1200,7 @@ static int kho_out_finalize_get(void *data, u64 *val) =20 static int kho_out_finalize_set(void *data, u64 _val) { - int ret =3D 0; - bool val =3D !!_val; - - mutex_lock(&kho_out.lock); - - if (val =3D=3D kho_out.finalized) { - if (kho_out.finalized) - ret =3D -EEXIST; - else - ret =3D -ENOENT; - goto unlock; - } - - if (val) - ret =3D kho_finalize(); - else - ret =3D kho_abort(); - - if (ret) - goto unlock; - - kho_out.finalized =3D val; - ret =3D kho_out_update_debugfs_fdt(); - -unlock: - mutex_unlock(&kho_out.lock); - return ret; + return (!!_val) ? kho_finalize() : kho_abort(); } =20 DEFINE_DEBUGFS_ATTRIBUTE(fops_kho_out_finalize, kho_out_finalize_get, --=20 2.51.0.915.g61a8936c21-goog From nobody Sat Feb 7 05:52:34 2026 Received: from mail-qv1-f54.google.com (mail-qv1-f54.google.com [209.85.219.54]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id AB066257829 for ; Sat, 18 Oct 2025 17:18:01 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.219.54 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760807884; cv=none; b=Z2/PmvX23f0EmBd3XvftE42nzatPOP0jP8lXelDYvgpdRxAtAlUrnkZMV4YAYv5nVkOBSWnopsETq7ySqmWxCgOLzL4kAtl710POPlUlUpckVz/Vgi7/zgRb4ZlheQzawsaex6CAN2owVUPKQG6tIdvb5hOE+SapdCffc4ouUbU= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760807884; c=relaxed/simple; bh=3awqJU3hTbBhGH0yAfmqA+p0PHBDWNhEcz6DCm80zhM=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=lgHkGupQtl3SMqpTRTmmQ87NbPj0mO+s69xLyvVLq6U07TzmHI1kqKjLCVQUDa9IVmjaRRItc6KWA5UlO86n+Y129uwxcKPTnrYfoMVWp9/L5H9J0Hn5UDeS9b5TMbQ+I1ZZcvzbcpz71LIzDmJlwg8T5t2fux02QKpOWTRUbQY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=soleen.com; spf=pass smtp.mailfrom=soleen.com; dkim=pass (2048-bit key) header.d=soleen.com header.i=@soleen.com header.b=TT5p5+IZ; arc=none smtp.client-ip=209.85.219.54 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=soleen.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=soleen.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=soleen.com header.i=@soleen.com header.b="TT5p5+IZ" Received: by mail-qv1-f54.google.com with SMTP id 6a1803df08f44-87d8fa51993so13140216d6.1 for ; Sat, 18 Oct 2025 10:18:01 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=soleen.com; s=google; t=1760807880; x=1761412680; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=jfD7m0Wh+POyh2ZHFs2nL6OUvX1CR9CVkBCFctAX45k=; b=TT5p5+IZev+dxf0vbKSGWkAlpfEFjxj7XD/3w8KTWZLf+S+wamejn0LZoyg98XOSL+ IXFYVsC7EKypTVszJq9H0rJMHJwUgSILPocIRRmyHC4YeoUdfnxDjAyaa6qX2UovIbsG /BGrTb1Zq7Vwn3gNIxilqlmF2Fi6xtjMyURda1gaGZMpB4lzBkIRbLoE/zyWMSIul/rd rXqaKMk1NQD+ZXvIaPA+T9R+c6rci925ewIVVMSNivAhKgaSp866OxH9XzVlFSUPjnmx +ooryDUsIWOQQ2NeWrg2BRvvrRR8+QifGFeFmI8oQ8n4Dpwnx4LBNHsjayQJYw8gT+5Q Ntow== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1760807880; x=1761412680; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=jfD7m0Wh+POyh2ZHFs2nL6OUvX1CR9CVkBCFctAX45k=; b=gHF1ICgLJ1ZTJPGDZzIhtLY10bFzvLSJhEoIqwS8a/C+IvY9PbKjvyeBqOpqcfXfJX K0vntfIW8hISAox7A1JRHghYWtTCYUoj8Rbu8tiqd8XflTJ0fEh/MaNGpirBDBA+LQDT ++iQYI6rNAG6tWA9KlKk/lZnM+GkP264PaRrXge3P+ssBqrDVrGKg/bZbAtIabuH09yE FD7eMUCDtF/KXrr3xtDlGkcbAXm8DpeGkZSf7X+RISh5XUTDOcjjHQrnhBurxgbEkOfD S5Ds6I8Qq6FAdIvgcmzmKdIorl+DwMqT1fIvdgfa61BL0Nb9+e7pffpOByRq6J2mRJfG IxrA== X-Forwarded-Encrypted: i=1; AJvYcCV2+Lw9X/BKvunoWy/X6jtLtVxHhN3M4obw32Qd6LQeCWtPuNfR4s+9p1G/SLSB1f8jbBcYwN9QizXiIuw=@vger.kernel.org X-Gm-Message-State: AOJu0YwwwCZD85rZumQELRNENUjhVUYZGL9kkw3Esc1FPA35pmTj23iI QLFBnTcmvkXE3MUFUUgHpzGBFvEjAxSTGdNQNxJtJHhgnKqeT1nI/oBIHCErLrFMjZk= X-Gm-Gg: ASbGnctIODC6t8sK1oTyog3iaPfDWtheWWuBhmcrQqj8xffbrOB0eKL9/TMOe2HGEcb MLzX02AQpIzivWaLTn8GdPgCrgyMr113d80e3wbFQ7787WTR0vG2B3rfeh/rzTZBMauqFJX7jwl wlZi/myI5vvcOiN+kA+Zjtn6VVJzQSxP+OLfWMOZGkrNmazO1GdRt5TdHUcObRk5ZSYCCQ/6xq9 K6Ox+hil5N0RRZKEYDK4Pi0f7RxnT/E884oH0cia1+Z/IgQFrAcD7NzvBBGToWZdGjQYWbuLnJq fUG6o0U5tMpX4Sq4P/KucDUROXAJWBIfxj8JDOucqnfRAlFb6IVW+ofNLL/mTcL4SyT5sQ6vKT+ ITC5rdD/pzZkdTbkMP6zGFA6bfqVrEPcGBDKa54Mtrx4rPJbemFkkAoOF/E9NJ41p1j3ZMVSRfS lQT0UX9s7zqp8OOcK4uJo/jqabBVfUPkUFDGUH60AacYmFZPUuCq8FVe/7+pVW9HovxXUX88Qvt vS9pgD7AkDXKvxUvCrvGKLztM8aV5Hc X-Google-Smtp-Source: AGHT+IGUmjXuUPhMdy4O9ccNuWprtdGQ/+tq/+k2LIxGLfXNhcxnux///dIcFzrpPBKzztNYEZUp8g== X-Received: by 2002:ad4:5d61:0:b0:856:d1d4:d127 with SMTP id 6a1803df08f44-87c2054ebaamr126459036d6.4.1760807880415; Sat, 18 Oct 2025 10:18:00 -0700 (PDT) Received: from soleen.us-east4-b.c.cloudtop-prod-us-east.internal (53.47.86.34.bc.googleusercontent.com. [34.86.47.53]) by smtp.gmail.com with ESMTPSA id 6a1803df08f44-87d02d8e909sm18478116d6.62.2025.10.18.10.17.58 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 18 Oct 2025 10:17:59 -0700 (PDT) From: Pasha Tatashin To: akpm@linux-foundation.org, brauner@kernel.org, corbet@lwn.net, graf@amazon.com, jgg@ziepe.ca, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-mm@kvack.org, masahiroy@kernel.org, ojeda@kernel.org, pasha.tatashin@soleen.com, pratyush@kernel.org, rdunlap@infradead.org, rppt@kernel.org, tj@kernel.org, jasonmiu@google.com, dmatlack@google.com, skhawaja@google.com Subject: [PATCH v6 02/10] kho: make debugfs interface optional Date: Sat, 18 Oct 2025 13:17:48 -0400 Message-ID: <20251018171756.1724191-3-pasha.tatashin@soleen.com> X-Mailer: git-send-email 2.51.0.915.g61a8936c21-goog In-Reply-To: <20251018171756.1724191-1-pasha.tatashin@soleen.com> References: <20251018171756.1724191-1-pasha.tatashin@soleen.com> 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" Currently, KHO is controlled via debugfs interface, but once LUO is introduced, it can control KHO, and the debug interface becomes optional. Add a separate config CONFIG_KEXEC_HANDOVER_DEBUGFS that enables the debugfs interface, and allows to inspect the tree. Move all debugfs related code to a new file to keep the .c files clear of ifdefs. Co-developed-by: Mike Rapoport (Microsoft) Signed-off-by: Mike Rapoport (Microsoft) Signed-off-by: Pasha Tatashin --- MAINTAINERS | 3 +- kernel/Kconfig.kexec | 10 ++ kernel/Makefile | 1 + kernel/kexec_handover.c | 223 +++----------------------- kernel/kexec_handover_debugfs.c | 213 ++++++++++++++++++++++++ kernel/kexec_handover_internal.h | 44 +++++ tools/testing/selftests/kho/vmtest.sh | 1 + 7 files changed, 290 insertions(+), 205 deletions(-) create mode 100644 kernel/kexec_handover_debugfs.c create mode 100644 kernel/kexec_handover_internal.h diff --git a/MAINTAINERS b/MAINTAINERS index 545a4776795e..54f627a639b1 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -13775,13 +13775,14 @@ KEXEC HANDOVER (KHO) M: Alexander Graf M: Mike Rapoport M: Changyuan Lyu +M: Pasha Tatashin L: kexec@lists.infradead.org L: linux-mm@kvack.org S: Maintained F: Documentation/admin-guide/mm/kho.rst F: Documentation/core-api/kho/* F: include/linux/kexec_handover.h -F: kernel/kexec_handover.c +F: kernel/kexec_handover* F: tools/testing/selftests/kho/ =20 KEYS-ENCRYPTED diff --git a/kernel/Kconfig.kexec b/kernel/Kconfig.kexec index 422270d64820..03c3aa6263d3 100644 --- a/kernel/Kconfig.kexec +++ b/kernel/Kconfig.kexec @@ -109,6 +109,16 @@ config KEXEC_HANDOVER to keep data or state alive across the kexec. For this to work, both source and target kernels need to have this option enabled. =20 +config KEXEC_HANDOVER_DEBUGFS + bool "kexec handover debugfs interface" + depends on KEXEC_HANDOVER + depends on DEBUG_FS + help + Allow to control kexec handover device tree via debugfs + interface, i.e. finalize the state or aborting the finalization. + Also, enables inspecting the KHO fdt trees with the debugfs binary + blobs. + config CRASH_DUMP bool "kernel crash dumps" default ARCH_DEFAULT_CRASH_DUMP diff --git a/kernel/Makefile b/kernel/Makefile index df3dd8291bb6..06bfe691439b 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -83,6 +83,7 @@ obj-$(CONFIG_KEXEC) +=3D kexec.o obj-$(CONFIG_KEXEC_FILE) +=3D kexec_file.o obj-$(CONFIG_KEXEC_ELF) +=3D kexec_elf.o obj-$(CONFIG_KEXEC_HANDOVER) +=3D kexec_handover.o +obj-$(CONFIG_KEXEC_HANDOVER_DEBUGFS) +=3D kexec_handover_debugfs.o obj-$(CONFIG_BACKTRACE_SELF_TEST) +=3D backtracetest.o obj-$(CONFIG_COMPAT) +=3D compat.o obj-$(CONFIG_CGROUPS) +=3D cgroup/ diff --git a/kernel/kexec_handover.c b/kernel/kexec_handover.c index 76c34ea923f0..f3627430b3c3 100644 --- a/kernel/kexec_handover.c +++ b/kernel/kexec_handover.c @@ -10,7 +10,6 @@ =20 #include #include -#include #include #include #include @@ -28,6 +27,7 @@ */ #include "../mm/internal.h" #include "kexec_internal.h" +#include "kexec_handover_internal.h" =20 #define KHO_FDT_COMPATIBLE "kho-v1" #define PROP_PRESERVED_MEMORY_MAP "preserved-memory-map" @@ -101,8 +101,6 @@ struct khoser_mem_chunk; =20 struct kho_serialization { struct page *fdt; - struct list_head fdt_list; - struct dentry *sub_fdt_dir; struct kho_mem_track track; /* First chunk of serialized preserved memory map */ struct khoser_mem_chunk *preserved_mem_map; @@ -110,20 +108,16 @@ struct kho_serialization { =20 struct kho_out { struct blocking_notifier_head chain_head; - - struct dentry *dir; - struct mutex lock; /* protects KHO FDT finalization */ - struct kho_serialization ser; bool finalized; + struct kho_debugfs dbg; }; =20 static struct kho_out kho_out =3D { .chain_head =3D BLOCKING_NOTIFIER_INIT(kho_out.chain_head), .lock =3D __MUTEX_INITIALIZER(kho_out.lock), .ser =3D { - .fdt_list =3D LIST_HEAD_INIT(kho_out.ser.fdt_list), .track =3D { .orders =3D XARRAY_INIT(kho_out.ser.track.orders, 0), }, @@ -465,8 +459,8 @@ static void __init kho_mem_deserialize(const void *fdt) * area for early allocations that happen before page allocator is * initialized. */ -static struct kho_scratch *kho_scratch; -static unsigned int kho_scratch_cnt; +struct kho_scratch *kho_scratch; +unsigned int kho_scratch_cnt; =20 /* * The scratch areas are scaled by default as percent of memory allocated = from @@ -662,37 +656,6 @@ static void __init kho_reserve_scratch(void) kho_enable =3D false; } =20 -struct fdt_debugfs { - struct list_head list; - struct debugfs_blob_wrapper wrapper; - struct dentry *file; -}; - -static int kho_debugfs_fdt_add(struct list_head *list, struct dentry *dir, - const char *name, const void *fdt) -{ - struct fdt_debugfs *f; - struct dentry *file; - - f =3D kmalloc(sizeof(*f), GFP_KERNEL); - if (!f) - return -ENOMEM; - - f->wrapper.data =3D (void *)fdt; - f->wrapper.size =3D fdt_totalsize(fdt); - - file =3D debugfs_create_blob(name, 0400, dir, &f->wrapper); - if (IS_ERR(file)) { - kfree(f); - return PTR_ERR(file); - } - - f->file =3D file; - list_add(&f->list, list); - - return 0; -} - /** * kho_add_subtree - record the physical address of a sub FDT in KHO root = tree. * @ser: serialization control object passed by KHO notifiers. @@ -704,7 +667,8 @@ static int kho_debugfs_fdt_add(struct list_head *list, = struct dentry *dir, * by KHO for the new kernel to retrieve it after kexec. * * A debugfs blob entry is also created at - * ``/sys/kernel/debug/kho/out/sub_fdts/@name``. + * ``/sys/kernel/debug/kho/out/sub_fdts/@name`` when kernel is configured = with + * CONFIG_KEXEC_HANDOVER_DEBUGFS * * Return: 0 on success, error code on failure */ @@ -721,7 +685,7 @@ int kho_add_subtree(struct kho_serialization *ser, cons= t char *name, void *fdt) if (err) return err; =20 - return kho_debugfs_fdt_add(&ser->fdt_list, ser->sub_fdt_dir, name, fdt); + return kho_debugfs_fdt_add(&kho_out.dbg, name, fdt, false); } EXPORT_SYMBOL_GPL(kho_add_subtree); =20 @@ -1044,29 +1008,6 @@ void *kho_restore_vmalloc(const struct kho_vmalloc *= preservation) } EXPORT_SYMBOL_GPL(kho_restore_vmalloc); =20 -/* Handling for debug/kho/out */ - -static struct dentry *debugfs_root; - -static int kho_out_update_debugfs_fdt(void) -{ - int err =3D 0; - struct fdt_debugfs *ff, *tmp; - - if (kho_out.finalized) { - err =3D kho_debugfs_fdt_add(&kho_out.ser.fdt_list, kho_out.dir, - "fdt", page_to_virt(kho_out.ser.fdt)); - } else { - list_for_each_entry_safe(ff, tmp, &kho_out.ser.fdt_list, list) { - debugfs_remove(ff->file); - list_del(&ff->list); - kfree(ff); - } - } - - return err; -} - static int __kho_abort(void) { int err; @@ -1116,8 +1057,9 @@ int kho_abort(void) return ret; =20 kho_out.finalized =3D false; + kho_debugfs_cleanup(&kho_out.dbg); =20 - return kho_out_update_debugfs_fdt(); + return 0; } =20 static int __kho_finalize(void) @@ -1186,89 +1128,23 @@ int kho_finalize(void) =20 kho_out.finalized =3D true; =20 - return kho_out_update_debugfs_fdt(); -} - -static int kho_out_finalize_get(void *data, u64 *val) -{ - mutex_lock(&kho_out.lock); - *val =3D kho_out.finalized; - mutex_unlock(&kho_out.lock); - - return 0; -} - -static int kho_out_finalize_set(void *data, u64 _val) -{ - return (!!_val) ? kho_finalize() : kho_abort(); -} - -DEFINE_DEBUGFS_ATTRIBUTE(fops_kho_out_finalize, kho_out_finalize_get, - kho_out_finalize_set, "%llu\n"); - -static int scratch_phys_show(struct seq_file *m, void *v) -{ - for (int i =3D 0; i < kho_scratch_cnt; i++) - seq_printf(m, "0x%llx\n", kho_scratch[i].addr); - - return 0; -} -DEFINE_SHOW_ATTRIBUTE(scratch_phys); - -static int scratch_len_show(struct seq_file *m, void *v) -{ - for (int i =3D 0; i < kho_scratch_cnt; i++) - seq_printf(m, "0x%llx\n", kho_scratch[i].size); - - return 0; + return kho_debugfs_fdt_add(&kho_out.dbg, "fdt", + page_to_virt(kho_out.ser.fdt), true); } -DEFINE_SHOW_ATTRIBUTE(scratch_len); =20 -static __init int kho_out_debugfs_init(void) +bool kho_finalized(void) { - struct dentry *dir, *f, *sub_fdt_dir; - - dir =3D debugfs_create_dir("out", debugfs_root); - if (IS_ERR(dir)) - return -ENOMEM; - - sub_fdt_dir =3D debugfs_create_dir("sub_fdts", dir); - if (IS_ERR(sub_fdt_dir)) - goto err_rmdir; - - f =3D debugfs_create_file("scratch_phys", 0400, dir, NULL, - &scratch_phys_fops); - if (IS_ERR(f)) - goto err_rmdir; - - f =3D debugfs_create_file("scratch_len", 0400, dir, NULL, - &scratch_len_fops); - if (IS_ERR(f)) - goto err_rmdir; - - f =3D debugfs_create_file("finalize", 0600, dir, NULL, - &fops_kho_out_finalize); - if (IS_ERR(f)) - goto err_rmdir; - - kho_out.dir =3D dir; - kho_out.ser.sub_fdt_dir =3D sub_fdt_dir; - return 0; - -err_rmdir: - debugfs_remove_recursive(dir); - return -ENOENT; + guard(mutex)(&kho_out.lock); + return kho_out.finalized; } =20 struct kho_in { - struct dentry *dir; phys_addr_t fdt_phys; phys_addr_t scratch_phys; - struct list_head fdt_list; + struct kho_debugfs dbg; }; =20 static struct kho_in kho_in =3D { - .fdt_list =3D LIST_HEAD_INIT(kho_in.fdt_list), }; =20 static const void *kho_get_fdt(void) @@ -1332,56 +1208,6 @@ int kho_retrieve_subtree(const char *name, phys_addr= _t *phys) } EXPORT_SYMBOL_GPL(kho_retrieve_subtree); =20 -/* Handling for debugfs/kho/in */ - -static __init int kho_in_debugfs_init(const void *fdt) -{ - struct dentry *sub_fdt_dir; - int err, child; - - kho_in.dir =3D debugfs_create_dir("in", debugfs_root); - if (IS_ERR(kho_in.dir)) - return PTR_ERR(kho_in.dir); - - sub_fdt_dir =3D debugfs_create_dir("sub_fdts", kho_in.dir); - if (IS_ERR(sub_fdt_dir)) { - err =3D PTR_ERR(sub_fdt_dir); - goto err_rmdir; - } - - err =3D kho_debugfs_fdt_add(&kho_in.fdt_list, kho_in.dir, "fdt", fdt); - if (err) - goto err_rmdir; - - fdt_for_each_subnode(child, fdt, 0) { - int len =3D 0; - const char *name =3D fdt_get_name(fdt, child, NULL); - const u64 *fdt_phys; - - fdt_phys =3D fdt_getprop(fdt, child, "fdt", &len); - if (!fdt_phys) - continue; - if (len !=3D sizeof(*fdt_phys)) { - pr_warn("node `%s`'s prop `fdt` has invalid length: %d\n", - name, len); - continue; - } - err =3D kho_debugfs_fdt_add(&kho_in.fdt_list, sub_fdt_dir, name, - phys_to_virt(*fdt_phys)); - if (err) { - pr_warn("failed to add fdt `%s` to debugfs: %d\n", name, - err); - continue; - } - } - - return 0; - -err_rmdir: - debugfs_remove_recursive(kho_in.dir); - return err; -} - static __init int kho_init(void) { int err =3D 0; @@ -1396,27 +1222,16 @@ static __init int kho_init(void) goto err_free_scratch; } =20 - debugfs_root =3D debugfs_create_dir("kho", NULL); - if (IS_ERR(debugfs_root)) { - err =3D -ENOENT; + err =3D kho_debugfs_init(); + if (err) goto err_free_fdt; - } =20 - err =3D kho_out_debugfs_init(); + err =3D kho_out_debugfs_init(&kho_out.dbg); if (err) goto err_free_fdt; =20 if (fdt) { - err =3D kho_in_debugfs_init(fdt); - /* - * Failure to create /sys/kernel/debug/kho/in does not prevent - * reviving state from KHO and setting up KHO for the next - * kexec. - */ - if (err) - pr_err("failed exposing handover FDT in debugfs: %d\n", - err); - + kho_in_debugfs_init(&kho_in.dbg, fdt); return 0; } =20 diff --git a/kernel/kexec_handover_debugfs.c b/kernel/kexec_handover_debugf= s.c new file mode 100644 index 000000000000..96fb9afd8af6 --- /dev/null +++ b/kernel/kexec_handover_debugfs.c @@ -0,0 +1,213 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * kexec_handover_debugfs.c - kexec handover debugfs interfaces + * Copyright (C) 2023 Alexander Graf + * Copyright (C) 2025 Microsoft Corporation, Mike Rapoport + * Copyright (C) 2025 Google LLC, Changyuan Lyu + * Copyright (C) 2025 Google LLC, Pasha Tatashin + */ + +#define pr_fmt(fmt) "KHO: " fmt + +#include +#include +#include +#include +#include "kexec_handover_internal.h" + +static struct dentry *debugfs_root; + +struct fdt_debugfs { + struct list_head list; + struct debugfs_blob_wrapper wrapper; + struct dentry *file; +}; + +static int __kho_debugfs_fdt_add(struct list_head *list, struct dentry *di= r, + const char *name, const void *fdt) +{ + struct fdt_debugfs *f; + struct dentry *file; + + f =3D kmalloc(sizeof(*f), GFP_KERNEL); + if (!f) + return -ENOMEM; + + f->wrapper.data =3D (void *)fdt; + f->wrapper.size =3D fdt_totalsize(fdt); + + file =3D debugfs_create_blob(name, 0400, dir, &f->wrapper); + if (IS_ERR(file)) { + kfree(f); + return PTR_ERR(file); + } + + f->file =3D file; + list_add(&f->list, list); + + return 0; +} + +int kho_debugfs_fdt_add(struct kho_debugfs *dbg, const char *name, + const void *fdt, bool root) +{ + struct dentry *dir; + + if (root) + dir =3D dbg->dir; + else + dir =3D dbg->sub_fdt_dir; + + return __kho_debugfs_fdt_add(&dbg->fdt_list, dir, name, fdt); +} + +void kho_debugfs_cleanup(struct kho_debugfs *dbg) +{ + struct fdt_debugfs *ff, *tmp; + + list_for_each_entry_safe(ff, tmp, &dbg->fdt_list, list) { + debugfs_remove(ff->file); + list_del(&ff->list); + kfree(ff); + } +} + +static int kho_out_finalize_get(void *data, u64 *val) +{ + *val =3D kho_finalized(); + + return 0; +} + +static int kho_out_finalize_set(void *data, u64 _val) +{ + return (!!_val) ? kho_finalize() : kho_abort(); +} + +DEFINE_DEBUGFS_ATTRIBUTE(kho_out_finalize_fops, kho_out_finalize_get, + kho_out_finalize_set, "%llu\n"); + +static int scratch_phys_show(struct seq_file *m, void *v) +{ + for (int i =3D 0; i < kho_scratch_cnt; i++) + seq_printf(m, "0x%llx\n", kho_scratch[i].addr); + + return 0; +} +DEFINE_SHOW_ATTRIBUTE(scratch_phys); + +static int scratch_len_show(struct seq_file *m, void *v) +{ + for (int i =3D 0; i < kho_scratch_cnt; i++) + seq_printf(m, "0x%llx\n", kho_scratch[i].size); + + return 0; +} +DEFINE_SHOW_ATTRIBUTE(scratch_len); + +__init void kho_in_debugfs_init(struct kho_debugfs *dbg, const void *fdt) +{ + struct dentry *dir, *sub_fdt_dir; + int err, child; + + INIT_LIST_HEAD(&dbg->fdt_list); + + dir =3D debugfs_create_dir("in", debugfs_root); + if (IS_ERR(dir)) { + err =3D PTR_ERR(dir); + goto err_out; + } + + sub_fdt_dir =3D debugfs_create_dir("sub_fdts", dir); + if (IS_ERR(sub_fdt_dir)) { + err =3D PTR_ERR(sub_fdt_dir); + goto err_rmdir; + } + + err =3D __kho_debugfs_fdt_add(&dbg->fdt_list, dir, "fdt", fdt); + if (err) + goto err_rmdir; + + fdt_for_each_subnode(child, fdt, 0) { + int len =3D 0; + const char *name =3D fdt_get_name(fdt, child, NULL); + const u64 *fdt_phys; + + fdt_phys =3D fdt_getprop(fdt, child, "fdt", &len); + if (!fdt_phys) + continue; + if (len !=3D sizeof(*fdt_phys)) { + pr_warn("node %s prop fdt has invalid length: %d\n", + name, len); + continue; + } + err =3D __kho_debugfs_fdt_add(&dbg->fdt_list, sub_fdt_dir, name, + phys_to_virt(*fdt_phys)); + if (err) { + pr_warn("failed to add fdt %s to debugfs: %d\n", name, + err); + continue; + } + } + + dbg->dir =3D dir; + dbg->sub_fdt_dir =3D sub_fdt_dir; + + return; +err_rmdir: + debugfs_remove_recursive(dir); +err_out: + /* + * Failure to create /sys/kernel/debug/kho/in does not prevent + * reviving state from KHO and setting up KHO for the next + * kexec. + */ + if (err) + pr_err("failed exposing handover FDT in debugfs: %d\n", err); +} + +__init int kho_out_debugfs_init(struct kho_debugfs *dbg) +{ + struct dentry *dir, *f, *sub_fdt_dir; + + INIT_LIST_HEAD(&dbg->fdt_list); + + dir =3D debugfs_create_dir("out", debugfs_root); + if (IS_ERR(dir)) + return -ENOMEM; + + sub_fdt_dir =3D debugfs_create_dir("sub_fdts", dir); + if (IS_ERR(sub_fdt_dir)) + goto err_rmdir; + + f =3D debugfs_create_file("scratch_phys", 0400, dir, NULL, + &scratch_phys_fops); + if (IS_ERR(f)) + goto err_rmdir; + + f =3D debugfs_create_file("scratch_len", 0400, dir, NULL, + &scratch_len_fops); + if (IS_ERR(f)) + goto err_rmdir; + + f =3D debugfs_create_file("finalize", 0600, dir, NULL, + &kho_out_finalize_fops); + if (IS_ERR(f)) + goto err_rmdir; + + dbg->dir =3D dir; + dbg->sub_fdt_dir =3D sub_fdt_dir; + return 0; + +err_rmdir: + debugfs_remove_recursive(dir); + return -ENOENT; +} + +__init int kho_debugfs_init(void) +{ + debugfs_root =3D debugfs_create_dir("kho", NULL); + if (IS_ERR(debugfs_root)) + return -ENOENT; + return 0; +} diff --git a/kernel/kexec_handover_internal.h b/kernel/kexec_handover_inter= nal.h new file mode 100644 index 000000000000..042c189af768 --- /dev/null +++ b/kernel/kexec_handover_internal.h @@ -0,0 +1,44 @@ +/* SPDX-License-Identifier: GPL-2.0 */ +#ifndef LINUX_KEXEC_HANDOVER_INTERNAL_H +#define LINUX_KEXEC_HANDOVER_INTERNAL_H + +#include +#include +#include + +#ifdef CONFIG_KEXEC_HANDOVER_DEBUGFS +#include + +struct kho_debugfs { + struct dentry *dir; + struct dentry *sub_fdt_dir; + struct list_head fdt_list; +}; + +#else +struct kho_debugfs {}; +#endif + +extern struct kho_scratch *kho_scratch; +extern unsigned int kho_scratch_cnt; + +bool kho_finalized(void); + +#ifdef CONFIG_KEXEC_HANDOVER_DEBUGFS +int kho_debugfs_init(void); +void kho_in_debugfs_init(struct kho_debugfs *dbg, const void *fdt); +int kho_out_debugfs_init(struct kho_debugfs *dbg); +int kho_debugfs_fdt_add(struct kho_debugfs *dbg, const char *name, + const void *fdt, bool root); +void kho_debugfs_cleanup(struct kho_debugfs *dbg); +#else +static inline int kho_debugfs_init(void) { return 0; } +static inline void kho_in_debugfs_init(struct kho_debugfs *dbg, + const void *fdt) { } +static inline int kho_out_debugfs_init(struct kho_debugfs *dbg) { return 0= ; } +static inline int kho_debugfs_fdt_add(struct kho_debugfs *dbg, const char = *name, + const void *fdt, bool root) { return 0; } +static inline void kho_debugfs_cleanup(struct kho_debugfs *dbg) {} +#endif /* CONFIG_KEXEC_HANDOVER_DEBUGFS */ + +#endif /* LINUX_KEXEC_HANDOVER_INTERNAL_H */ diff --git a/tools/testing/selftests/kho/vmtest.sh b/tools/testing/selftest= s/kho/vmtest.sh index 3f6c17166846..49fdac8e8b15 100755 --- a/tools/testing/selftests/kho/vmtest.sh +++ b/tools/testing/selftests/kho/vmtest.sh @@ -59,6 +59,7 @@ function build_kernel() { tee "$kconfig" > "$kho_config" <; Sat, 18 Oct 2025 17:18:03 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.219.50 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760807885; cv=none; b=nAGA5GHA/XLOoFzftra2ggpulapPkcRSD5J4m+NzvQINsISwM6CIpIuvN25/1dOhW1JtXAVxi73NZwIl8KVT/AL/zI7e1oFLU8lpPVUvlioxla4YqhPtZO/AjE3CViqBz9yDNfSzOILuJK+S30wVhvNjJkE6kaV8XrMJI1A91Y4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760807885; c=relaxed/simple; bh=6Xpc6HJ7a5YKOy7bpb1pi7fghAeRIgjJUnApjHIBWSw=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=CZOipF7qAHRO5+h6Pnjau0ekjBot81a5sK0Tz7/FM5U1BA6kHjeWZLBeHRszM0pcUE3BH8vT1mt5v9uHHhuploQ43yb/AJjBHQIJbLRAJoc7cV2OBqm5Em94dawIxwMGrqMxV9kdqKh6hKVB9EmIJNP0kOFRnqMxvkfmnKK51z0= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=soleen.com; spf=pass smtp.mailfrom=soleen.com; dkim=pass (2048-bit key) header.d=soleen.com header.i=@soleen.com header.b=A3XASFMN; arc=none smtp.client-ip=209.85.219.50 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=soleen.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=soleen.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=soleen.com header.i=@soleen.com header.b="A3XASFMN" Received: by mail-qv1-f50.google.com with SMTP id 6a1803df08f44-87bb66dd224so40340876d6.3 for ; Sat, 18 Oct 2025 10:18:03 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=soleen.com; s=google; t=1760807882; x=1761412682; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=ZY/HjXpMYmQ0uSsMwFz5AY8mYULbafnePj9I1rlgRgo=; b=A3XASFMNUEg9JlGinUc4NQzbHhg1QsHWc0LtMoWSsmbtXogQe3IKON728xj1ttUE0q NVk39T6Pn2NO2vH3DFVlw+w77GFJCUKuDSSf94ZrCUupjOXUE6K9rcWp8EMJslcz/4UX /YQECqfX4F1JMikZ0xr2kbjBsnZEBTrHhYVaM7Zz+5jQGi4levvLSmU3XN49SujGgKxm ko5HBjebw2ziQtOdygKbdNioMyDtR2SgQWS1SjcCazlfph+Bi0/wntYikt8hCKxUUJKw RKNyCgCB/OpWouWFxpGTNGX4O9SdPIS13mVo9jIiLQVyBe1vjaVYafG+gNUFl0lYFd4u ICAA== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1760807882; x=1761412682; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=ZY/HjXpMYmQ0uSsMwFz5AY8mYULbafnePj9I1rlgRgo=; b=tTAZ6NOxl3t8f+0BfjIz6feBflI4ghqmIylhds6Af/znRlLj5B8eI8GntANRXzVIIf NuQaubKNyUhdRzBkjGEQburBmk3s7Dr67opPEqStC5LXXUFCAgi/hm5V/dsJYeY39fTV HER3AVgsl+VdsAFMygK3th5HWmxpFpxZM2yyoAuWoX4OOCb3sdgiEHjCXRNxnLzeyNlD Kmncstso+WHR4U6jd2TgEM6aou1KBe0scdQyHgMY3v9TuJD12BecqUZlVET3zVbacmM9 HpPjELh7yffIVVoNfDm1BWpKJlrDyU/QTa3SI414XGKzRA2bDhuL7pixkcdRVLh7n62t FPSg== X-Forwarded-Encrypted: i=1; AJvYcCUnnPFvaqOHC+rpAE4M13hAEngcM0fZLmCnGmFJHmUsmKdaXyG+78dy/NSicRW9hs+BNERtBEWZh5pbbac=@vger.kernel.org X-Gm-Message-State: AOJu0YzeubaS0OnkhftZETwI3ASha7kFynU/XzvH6WMi1ZR7XTJRCBgD gdTgX+oX/EPk8n5Jao9gBu7K+SpWahY+ewIpq5x82ESrE0fe4srbZFsIAqSMWX4HY8Y= X-Gm-Gg: ASbGnctL5R/0c78lC5kTsyq+rjntU2osKmhFSr7zBxab99a0UQ+KbFFEDeOxsGeWcp3 NwMaW9qhP/akKiXAg0DZ5C+RkMs5dXzTIpasxGzsLp6ROly6fNo4G91aos0SYE4D9inYGsz8Oqx Vl0GfGsCAq3CcKZlJhfIfTpeLQms9qPOt+kXM92CZg4ZsTQE15UQiNGpqdzb2fXJpfFaq8FTJmL NEoaR0imu9rGzEC5Ixe6kLdn1REnwHeW6bq8kxSRAcYMV6eWica9XKAezWXrq8yc8a/vIF3upsO HED12TNakZZ6khkoG5isOPc4EiE8yuf6vdV3zs15bLRwwylBic6A1CtytRXr+gQOEjA+iISGDMo o4saLwr4kfTrhNw4Qyjokc9O4TDD6f1/wg4K4jl0occdxP+MG80gMMVBvSIGCLD+lAgvV5X790P NJacvx0L4n6Xsh0uDO6pF1sL5z/i86L4a3WQzcuUqp7tjfZsmoCrbtxCluBL0gqrpdaukSImVmz RqOvBB/UBcrAl3TTrb45y9V3QgPG2qo X-Google-Smtp-Source: AGHT+IEmfOOiW8srLwk1lm0jxUxxXdkIwDR6niHlzuMAgc/RIDwCL+Bi+LrRDYrYfHkzcneqwF/bjg== X-Received: by 2002:a05:6214:5196:b0:87c:1fd9:da4a with SMTP id 6a1803df08f44-87c2055e680mr144656946d6.2.1760807882033; Sat, 18 Oct 2025 10:18:02 -0700 (PDT) Received: from soleen.us-east4-b.c.cloudtop-prod-us-east.internal (53.47.86.34.bc.googleusercontent.com. [34.86.47.53]) by smtp.gmail.com with ESMTPSA id 6a1803df08f44-87d02d8e909sm18478116d6.62.2025.10.18.10.18.00 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 18 Oct 2025 10:18:01 -0700 (PDT) From: Pasha Tatashin To: akpm@linux-foundation.org, brauner@kernel.org, corbet@lwn.net, graf@amazon.com, jgg@ziepe.ca, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-mm@kvack.org, masahiroy@kernel.org, ojeda@kernel.org, pasha.tatashin@soleen.com, pratyush@kernel.org, rdunlap@infradead.org, rppt@kernel.org, tj@kernel.org, jasonmiu@google.com, dmatlack@google.com, skhawaja@google.com Subject: [PATCH v6 03/10] kho: drop notifiers Date: Sat, 18 Oct 2025 13:17:49 -0400 Message-ID: <20251018171756.1724191-4-pasha.tatashin@soleen.com> X-Mailer: git-send-email 2.51.0.915.g61a8936c21-goog In-Reply-To: <20251018171756.1724191-1-pasha.tatashin@soleen.com> References: <20251018171756.1724191-1-pasha.tatashin@soleen.com> 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" From: "Mike Rapoport (Microsoft)" The KHO framework uses a notifier chain as the mechanism for clients to participate in the finalization process. While this works for a single, central state machine, it is too restrictive for kernel-internal components like pstore/reserve_mem or IMA. These components need a simpler, direct way to register their state for preservation (e.g., during their initcall) without being part of a complex, shutdown-time notifier sequence. The notifier model forces all participants into a single finalization flow and makes direct preservation from an arbitrary context difficult. This patch refactors the client participation model by removing the notifier chain and introducing a direct API for managing FDT subtrees. The core kho_finalize() and kho_abort() state machine remains, but clients now register their data with KHO beforehand. Signed-off-by: Mike Rapoport (Microsoft) Co-developed-by: Pasha Tatashin Signed-off-by: Pasha Tatashin --- include/linux/kexec_handover.h | 28 +----- kernel/kexec_handover.c | 164 +++++++++++++++++-------------- kernel/kexec_handover_debugfs.c | 17 ++-- kernel/kexec_handover_internal.h | 5 +- lib/test_kho.c | 30 +----- mm/memblock.c | 62 +++--------- 6 files changed, 127 insertions(+), 179 deletions(-) diff --git a/include/linux/kexec_handover.h b/include/linux/kexec_handover.h index 04d0108db98e..2faf290803ce 100644 --- a/include/linux/kexec_handover.h +++ b/include/linux/kexec_handover.h @@ -10,14 +10,7 @@ struct kho_scratch { phys_addr_t size; }; =20 -/* KHO Notifier index */ -enum kho_event { - KEXEC_KHO_FINALIZE =3D 0, - KEXEC_KHO_ABORT =3D 1, -}; - struct folio; -struct notifier_block; struct page; =20 #define DECLARE_KHOSER_PTR(name, type) \ @@ -37,8 +30,6 @@ struct page; (typeof((s).ptr))((s).phys ? phys_to_virt((s).phys) : NULL); \ }) =20 -struct kho_serialization; - struct kho_vmalloc_chunk; struct kho_vmalloc { DECLARE_KHOSER_PTR(first, struct kho_vmalloc_chunk *); @@ -57,12 +48,10 @@ int kho_preserve_vmalloc(void *ptr, struct kho_vmalloc = *preservation); struct folio *kho_restore_folio(phys_addr_t phys); struct page *kho_restore_pages(phys_addr_t phys, unsigned int nr_pages); void *kho_restore_vmalloc(const struct kho_vmalloc *preservation); -int kho_add_subtree(struct kho_serialization *ser, const char *name, void = *fdt); +int kho_add_subtree(const char *name, void *fdt); +void kho_remove_subtree(void *fdt); int kho_retrieve_subtree(const char *name, phys_addr_t *phys); =20 -int register_kho_notifier(struct notifier_block *nb); -int unregister_kho_notifier(struct notifier_block *nb); - void kho_memory_init(void); =20 void kho_populate(phys_addr_t fdt_phys, u64 fdt_len, phys_addr_t scratch_p= hys, @@ -114,23 +103,16 @@ static inline void *kho_restore_vmalloc(const struct = kho_vmalloc *preservation) return NULL; } =20 -static inline int kho_add_subtree(struct kho_serialization *ser, - const char *name, void *fdt) +static inline int kho_add_subtree(const char *name, void *fdt) { return -EOPNOTSUPP; } =20 -static inline int kho_retrieve_subtree(const char *name, phys_addr_t *phys) +static inline void kho_remove_subtree(void *fdt) { - return -EOPNOTSUPP; } =20 -static inline int register_kho_notifier(struct notifier_block *nb) -{ - return -EOPNOTSUPP; -} - -static inline int unregister_kho_notifier(struct notifier_block *nb) +static inline int kho_retrieve_subtree(const char *name, phys_addr_t *phys) { return -EOPNOTSUPP; } diff --git a/kernel/kexec_handover.c b/kernel/kexec_handover.c index f3627430b3c3..e6890fe6a171 100644 --- a/kernel/kexec_handover.c +++ b/kernel/kexec_handover.c @@ -15,7 +15,6 @@ #include #include #include -#include #include #include =20 @@ -99,29 +98,34 @@ struct kho_mem_track { =20 struct khoser_mem_chunk; =20 -struct kho_serialization { - struct page *fdt; - struct kho_mem_track track; - /* First chunk of serialized preserved memory map */ - struct khoser_mem_chunk *preserved_mem_map; +struct kho_sub_fdt { + struct list_head l; + const char *name; + void *fdt; }; =20 struct kho_out { - struct blocking_notifier_head chain_head; - struct mutex lock; /* protects KHO FDT finalization */ - struct kho_serialization ser; + void *fdt; bool finalized; + struct mutex lock; /* protects KHO FDT finalization */ + + struct list_head sub_fdts; + struct mutex fdts_lock; + + struct kho_mem_track track; + /* First chunk of serialized preserved memory map */ + struct khoser_mem_chunk *preserved_mem_map; + struct kho_debugfs dbg; }; =20 static struct kho_out kho_out =3D { - .chain_head =3D BLOCKING_NOTIFIER_INIT(kho_out.chain_head), .lock =3D __MUTEX_INITIALIZER(kho_out.lock), - .ser =3D { - .track =3D { - .orders =3D XARRAY_INIT(kho_out.ser.track.orders, 0), - }, + .track =3D { + .orders =3D XARRAY_INIT(kho_out.track.orders, 0), }, + .sub_fdts =3D LIST_HEAD_INIT(kho_out.sub_fdts), + .fdts_lock =3D __MUTEX_INITIALIZER(kho_out.fdts_lock), .finalized =3D false, }; =20 @@ -362,14 +366,14 @@ static void kho_mem_ser_free(struct khoser_mem_chunk = *first_chunk) } } =20 -static int kho_mem_serialize(struct kho_serialization *ser) +static int kho_mem_serialize(struct kho_out *kho_out) { struct khoser_mem_chunk *first_chunk =3D NULL; struct khoser_mem_chunk *chunk =3D NULL; struct kho_mem_phys *physxa; unsigned long order; =20 - xa_for_each(&ser->track.orders, order, physxa) { + xa_for_each(&kho_out->track.orders, order, physxa) { struct kho_mem_phys_bits *bits; unsigned long phys; =20 @@ -397,7 +401,7 @@ static int kho_mem_serialize(struct kho_serialization *= ser) } } =20 - ser->preserved_mem_map =3D first_chunk; + kho_out->preserved_mem_map =3D first_chunk; =20 return 0; =20 @@ -658,7 +662,6 @@ static void __init kho_reserve_scratch(void) =20 /** * kho_add_subtree - record the physical address of a sub FDT in KHO root = tree. - * @ser: serialization control object passed by KHO notifiers. * @name: name of the sub tree. * @fdt: the sub tree blob. * @@ -672,34 +675,45 @@ static void __init kho_reserve_scratch(void) * * Return: 0 on success, error code on failure */ -int kho_add_subtree(struct kho_serialization *ser, const char *name, void = *fdt) +int kho_add_subtree(const char *name, void *fdt) { - int err =3D 0; - u64 phys =3D (u64)virt_to_phys(fdt); - void *root =3D page_to_virt(ser->fdt); + struct kho_sub_fdt *sub_fdt; + int err; =20 - err |=3D fdt_begin_node(root, name); - err |=3D fdt_property(root, PROP_SUB_FDT, &phys, sizeof(phys)); - err |=3D fdt_end_node(root); + sub_fdt =3D kmalloc(sizeof(*sub_fdt), GFP_KERNEL); + if (!sub_fdt) + return -ENOMEM; =20 - if (err) - return err; + INIT_LIST_HEAD(&sub_fdt->l); + sub_fdt->name =3D name; + sub_fdt->fdt =3D fdt; =20 - return kho_debugfs_fdt_add(&kho_out.dbg, name, fdt, false); + mutex_lock(&kho_out.fdts_lock); + list_add_tail(&sub_fdt->l, &kho_out.sub_fdts); + err =3D kho_debugfs_fdt_add(&kho_out.dbg, name, fdt, false); + mutex_unlock(&kho_out.fdts_lock); + + return err; } EXPORT_SYMBOL_GPL(kho_add_subtree); =20 -int register_kho_notifier(struct notifier_block *nb) +void kho_remove_subtree(void *fdt) { - return blocking_notifier_chain_register(&kho_out.chain_head, nb); -} -EXPORT_SYMBOL_GPL(register_kho_notifier); + struct kho_sub_fdt *sub_fdt; + + mutex_lock(&kho_out.fdts_lock); + list_for_each_entry(sub_fdt, &kho_out.sub_fdts, l) { + if (sub_fdt->fdt =3D=3D fdt) { + list_del(&sub_fdt->l); + kfree(sub_fdt); + kho_debugfs_fdt_remove(&kho_out.dbg, fdt); + break; + } + } + mutex_unlock(&kho_out.fdts_lock); =20 -int unregister_kho_notifier(struct notifier_block *nb) -{ - return blocking_notifier_chain_unregister(&kho_out.chain_head, nb); } -EXPORT_SYMBOL_GPL(unregister_kho_notifier); +EXPORT_SYMBOL_GPL(kho_remove_subtree); =20 /** * kho_preserve_folio - preserve a folio across kexec. @@ -714,7 +728,7 @@ int kho_preserve_folio(struct folio *folio) { const unsigned long pfn =3D folio_pfn(folio); const unsigned int order =3D folio_order(folio); - struct kho_mem_track *track =3D &kho_out.ser.track; + struct kho_mem_track *track =3D &kho_out.track; =20 return __kho_preserve_order(track, pfn, order); } @@ -732,7 +746,7 @@ EXPORT_SYMBOL_GPL(kho_preserve_folio); */ int kho_preserve_pages(struct page *page, unsigned int nr_pages) { - struct kho_mem_track *track =3D &kho_out.ser.track; + struct kho_mem_track *track =3D &kho_out.track; const unsigned long start_pfn =3D page_to_pfn(page); const unsigned long end_pfn =3D start_pfn + nr_pages; unsigned long pfn =3D start_pfn; @@ -828,7 +842,7 @@ static struct kho_vmalloc_chunk *new_vmalloc_chunk(stru= ct kho_vmalloc_chunk *cur =20 static void kho_vmalloc_unpreserve_chunk(struct kho_vmalloc_chunk *chunk) { - struct kho_mem_track *track =3D &kho_out.ser.track; + struct kho_mem_track *track =3D &kho_out.track; unsigned long pfn =3D PHYS_PFN(virt_to_phys(chunk)); =20 __kho_unpreserve(track, pfn, pfn + 1); @@ -1010,11 +1024,11 @@ EXPORT_SYMBOL_GPL(kho_restore_vmalloc); =20 static int __kho_abort(void) { - int err; + int err =3D 0; unsigned long order; struct kho_mem_phys *physxa; =20 - xa_for_each(&kho_out.ser.track.orders, order, physxa) { + xa_for_each(&kho_out.track.orders, order, physxa) { struct kho_mem_phys_bits *bits; unsigned long phys; =20 @@ -1024,17 +1038,13 @@ static int __kho_abort(void) xa_destroy(&physxa->phys_bits); kfree(physxa); } - xa_destroy(&kho_out.ser.track.orders); + xa_destroy(&kho_out.track.orders); =20 - if (kho_out.ser.preserved_mem_map) { - kho_mem_ser_free(kho_out.ser.preserved_mem_map); - kho_out.ser.preserved_mem_map =3D NULL; + if (kho_out.preserved_mem_map) { + kho_mem_ser_free(kho_out.preserved_mem_map); + kho_out.preserved_mem_map =3D NULL; } =20 - err =3D blocking_notifier_call_chain(&kho_out.chain_head, KEXEC_KHO_ABORT, - NULL); - err =3D notifier_to_errno(err); - if (err) pr_err("Failed to abort KHO finalization: %d\n", err); =20 @@ -1057,7 +1067,8 @@ int kho_abort(void) return ret; =20 kho_out.finalized =3D false; - kho_debugfs_cleanup(&kho_out.dbg); + + kho_debugfs_fdt_remove(&kho_out.dbg, kho_out.fdt); =20 return 0; } @@ -1066,41 +1077,46 @@ static int __kho_finalize(void) { int err =3D 0; u64 *preserved_mem_map; - void *fdt =3D page_to_virt(kho_out.ser.fdt); + void *root =3D kho_out.fdt; + struct kho_sub_fdt *fdt; =20 - err |=3D fdt_create(fdt, PAGE_SIZE); - err |=3D fdt_finish_reservemap(fdt); - err |=3D fdt_begin_node(fdt, ""); - err |=3D fdt_property_string(fdt, "compatible", KHO_FDT_COMPATIBLE); + err |=3D fdt_create(root, PAGE_SIZE); + err |=3D fdt_finish_reservemap(root); + err |=3D fdt_begin_node(root, ""); + err |=3D fdt_property_string(root, "compatible", KHO_FDT_COMPATIBLE); /** * Reserve the preserved-memory-map property in the root FDT, so * that all property definitions will precede subnodes created by * KHO callers. */ - err |=3D fdt_property_placeholder(fdt, PROP_PRESERVED_MEMORY_MAP, + err |=3D fdt_property_placeholder(root, PROP_PRESERVED_MEMORY_MAP, sizeof(*preserved_mem_map), (void **)&preserved_mem_map); if (err) goto abort; =20 - err =3D kho_preserve_folio(page_folio(kho_out.ser.fdt)); + err =3D kho_preserve_folio(virt_to_folio(kho_out.fdt)); if (err) goto abort; =20 - err =3D blocking_notifier_call_chain(&kho_out.chain_head, - KEXEC_KHO_FINALIZE, &kho_out.ser); - err =3D notifier_to_errno(err); + err =3D kho_mem_serialize(&kho_out); if (err) goto abort; =20 - err =3D kho_mem_serialize(&kho_out.ser); - if (err) - goto abort; + *preserved_mem_map =3D (u64)virt_to_phys(kho_out.preserved_mem_map); + + mutex_lock(&kho_out.fdts_lock); + list_for_each_entry(fdt, &kho_out.sub_fdts, l) { + phys_addr_t phys =3D virt_to_phys(fdt->fdt); =20 - *preserved_mem_map =3D (u64)virt_to_phys(kho_out.ser.preserved_mem_map); + err |=3D fdt_begin_node(root, fdt->name); + err |=3D fdt_property(root, PROP_SUB_FDT, &phys, sizeof(phys)); + err |=3D fdt_end_node(root); + } + mutex_unlock(&kho_out.fdts_lock); =20 - err |=3D fdt_end_node(fdt); - err |=3D fdt_finish(fdt); + err |=3D fdt_end_node(root); + err |=3D fdt_finish(root); =20 abort: if (err) { @@ -1129,7 +1145,7 @@ int kho_finalize(void) kho_out.finalized =3D true; =20 return kho_debugfs_fdt_add(&kho_out.dbg, "fdt", - page_to_virt(kho_out.ser.fdt), true); + kho_out.fdt, true); } =20 bool kho_finalized(void) @@ -1212,15 +1228,17 @@ static __init int kho_init(void) { int err =3D 0; const void *fdt =3D kho_get_fdt(); + struct page *fdt_page; =20 if (!kho_enable) return 0; =20 - kho_out.ser.fdt =3D alloc_page(GFP_KERNEL); - if (!kho_out.ser.fdt) { + fdt_page =3D alloc_page(GFP_KERNEL); + if (!fdt_page) { err =3D -ENOMEM; goto err_free_scratch; } + kho_out.fdt =3D page_to_virt(fdt_page); =20 err =3D kho_debugfs_init(); if (err) @@ -1248,8 +1266,8 @@ static __init int kho_init(void) return 0; =20 err_free_fdt: - put_page(kho_out.ser.fdt); - kho_out.ser.fdt =3D NULL; + put_page(fdt_page); + kho_out.fdt =3D NULL; err_free_scratch: for (int i =3D 0; i < kho_scratch_cnt; i++) { void *start =3D __va(kho_scratch[i].addr); @@ -1260,7 +1278,7 @@ static __init int kho_init(void) kho_enable =3D false; return err; } -late_initcall(kho_init); +fs_initcall(kho_init); =20 static void __init kho_release_scratch(void) { @@ -1396,7 +1414,7 @@ int kho_fill_kimage(struct kimage *image) if (!kho_out.finalized) return 0; =20 - image->kho.fdt =3D page_to_phys(kho_out.ser.fdt); + image->kho.fdt =3D virt_to_phys(kho_out.fdt); =20 scratch_size =3D sizeof(*kho_scratch) * kho_scratch_cnt; scratch =3D (struct kexec_buf){ diff --git a/kernel/kexec_handover_debugfs.c b/kernel/kexec_handover_debugf= s.c index 96fb9afd8af6..6ddcd17fac3c 100644 --- a/kernel/kexec_handover_debugfs.c +++ b/kernel/kexec_handover_debugfs.c @@ -61,14 +61,17 @@ int kho_debugfs_fdt_add(struct kho_debugfs *dbg, const = char *name, return __kho_debugfs_fdt_add(&dbg->fdt_list, dir, name, fdt); } =20 -void kho_debugfs_cleanup(struct kho_debugfs *dbg) +void kho_debugfs_fdt_remove(struct kho_debugfs *dbg, void *fdt) { - struct fdt_debugfs *ff, *tmp; - - list_for_each_entry_safe(ff, tmp, &dbg->fdt_list, list) { - debugfs_remove(ff->file); - list_del(&ff->list); - kfree(ff); + struct fdt_debugfs *ff; + + list_for_each_entry(ff, &dbg->fdt_list, list) { + if (ff->wrapper.data =3D=3D fdt) { + debugfs_remove(ff->file); + list_del(&ff->list); + kfree(ff); + break; + } } } =20 diff --git a/kernel/kexec_handover_internal.h b/kernel/kexec_handover_inter= nal.h index 042c189af768..de90a678274d 100644 --- a/kernel/kexec_handover_internal.h +++ b/kernel/kexec_handover_internal.h @@ -30,7 +30,7 @@ void kho_in_debugfs_init(struct kho_debugfs *dbg, const v= oid *fdt); int kho_out_debugfs_init(struct kho_debugfs *dbg); int kho_debugfs_fdt_add(struct kho_debugfs *dbg, const char *name, const void *fdt, bool root); -void kho_debugfs_cleanup(struct kho_debugfs *dbg); +void kho_debugfs_fdt_remove(struct kho_debugfs *dbg, void *fdt); #else static inline int kho_debugfs_init(void) { return 0; } static inline void kho_in_debugfs_init(struct kho_debugfs *dbg, @@ -38,7 +38,8 @@ static inline void kho_in_debugfs_init(struct kho_debugfs= *dbg, static inline int kho_out_debugfs_init(struct kho_debugfs *dbg) { return 0= ; } static inline int kho_debugfs_fdt_add(struct kho_debugfs *dbg, const char = *name, const void *fdt, bool root) { return 0; } -static inline void kho_debugfs_cleanup(struct kho_debugfs *dbg) {} +static inline void kho_debugfs_fdt_remove(struct kho_debugfs *dbg, + void *fdt) { } #endif /* CONFIG_KEXEC_HANDOVER_DEBUGFS */ =20 #endif /* LINUX_KEXEC_HANDOVER_INTERNAL_H */ diff --git a/lib/test_kho.c b/lib/test_kho.c index 60cd899ea745..8d57049e8c8c 100644 --- a/lib/test_kho.c +++ b/lib/test_kho.c @@ -39,33 +39,17 @@ struct kho_test_state { =20 static struct kho_test_state kho_test_state; =20 -static int kho_test_notifier(struct notifier_block *self, unsigned long cm= d, - void *v) +static int kho_test(void) { struct kho_test_state *state =3D &kho_test_state; - struct kho_serialization *ser =3D v; int err =3D 0; =20 - switch (cmd) { - case KEXEC_KHO_ABORT: - return NOTIFY_DONE; - case KEXEC_KHO_FINALIZE: - /* Handled below */ - break; - default: - return NOTIFY_BAD; - } - err |=3D kho_preserve_folio(state->fdt); - err |=3D kho_add_subtree(ser, KHO_TEST_FDT, folio_address(state->fdt)); + err |=3D kho_add_subtree(KHO_TEST_FDT, folio_address(state->fdt)); =20 return err ? NOTIFY_BAD : NOTIFY_DONE; } =20 -static struct notifier_block kho_test_nb =3D { - .notifier_call =3D kho_test_notifier, -}; - static int kho_test_save_data(struct kho_test_state *state, void *fdt) { phys_addr_t *folios_info __free(kvfree) =3D NULL; @@ -102,6 +86,9 @@ static int kho_test_save_data(struct kho_test_state *sta= te, void *fdt) if (!err) state->folios_info =3D no_free_ptr(folios_info); =20 + if (!err) + err =3D kho_test(); + return err; } =20 @@ -203,14 +190,8 @@ static int kho_test_save(void) if (err) goto err_free_folios; =20 - err =3D register_kho_notifier(&kho_test_nb); - if (err) - goto err_free_fdt; - return 0; =20 -err_free_fdt: - folio_put(state->fdt); err_free_folios: kvfree(folios); return err; @@ -326,7 +307,6 @@ static void kho_test_cleanup(void) =20 static void __exit kho_test_exit(void) { - unregister_kho_notifier(&kho_test_nb); kho_test_cleanup(); } module_exit(kho_test_exit); diff --git a/mm/memblock.c b/mm/memblock.c index e23e16618e9b..e3bef9b35d63 100644 --- a/mm/memblock.c +++ b/mm/memblock.c @@ -2444,53 +2444,18 @@ int reserve_mem_release_by_name(const char *name) #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 =3D 0, i; - - for (i =3D 0; i < reserved_mem_count; i++) { - struct reserve_mem_table *map =3D &reserved_mem_table[i]; - struct page *page =3D phys_to_page(map->start); - unsigned int nr_pages =3D map->size >> PAGE_SHIFT; - - err |=3D kho_preserve_pages(page, nr_pages); - } - - err |=3D kho_preserve_folio(page_folio(kho_fdt)); - err |=3D 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 =3D { - .notifier_call =3D reserve_mem_kho_notifier, -}; =20 static int __init prepare_kho_fdt(void) { int err =3D 0, i; + struct page *fdt_page; void *fdt; =20 - kho_fdt =3D alloc_page(GFP_KERNEL); - if (!kho_fdt) + fdt_page =3D alloc_page(GFP_KERNEL); + if (!fdt_page) return -ENOMEM; =20 - fdt =3D page_to_virt(kho_fdt); + fdt =3D page_to_virt(fdt_page); =20 err |=3D fdt_create(fdt, PAGE_SIZE); err |=3D fdt_finish_reservemap(fdt); @@ -2499,7 +2464,10 @@ static int __init prepare_kho_fdt(void) err |=3D fdt_property_string(fdt, "compatible", MEMBLOCK_KHO_NODE_COMPATI= BLE); for (i =3D 0; i < reserved_mem_count; i++) { struct reserve_mem_table *map =3D &reserved_mem_table[i]; + struct page *page =3D phys_to_page(map->start); + unsigned int nr_pages =3D map->size >> PAGE_SHIFT; =20 + err |=3D kho_preserve_pages(page, nr_pages); err |=3D fdt_begin_node(fdt, map->name); err |=3D fdt_property_string(fdt, "compatible", RESERVE_MEM_KHO_NODE_COM= PATIBLE); err |=3D fdt_property(fdt, "start", &map->start, sizeof(map->start)); @@ -2507,13 +2475,16 @@ static int __init prepare_kho_fdt(void) err |=3D fdt_end_node(fdt); } err |=3D fdt_end_node(fdt); - err |=3D fdt_finish(fdt); =20 + err |=3D kho_preserve_folio(page_folio(fdt_page)); + + if (!err) + err =3D kho_add_subtree(MEMBLOCK_KHO_FDT, fdt); + if (err) { pr_err("failed to prepare memblock FDT for KHO: %d\n", err); - put_page(kho_fdt); - kho_fdt =3D NULL; + put_page(fdt_page); } =20 return err; @@ -2529,13 +2500,6 @@ static int __init reserve_mem_init(void) err =3D prepare_kho_fdt(); if (err) return err; - - err =3D register_kho_notifier(&reserve_mem_kho_nb); - if (err) { - put_page(kho_fdt); - kho_fdt =3D NULL; - } - return err; } late_initcall(reserve_mem_init); --=20 2.51.0.915.g61a8936c21-goog From nobody Sat Feb 7 05:52:34 2026 Received: from mail-qv1-f41.google.com (mail-qv1-f41.google.com [209.85.219.41]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id B2DF0253F3D for ; Sat, 18 Oct 2025 17:18:04 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.219.41 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760807886; cv=none; b=LxIY3z0P+IT93aDo9ZDlvPs6DHo8PaYuYT+nj1nb4EXHztUq280mPlwE2Faz69SyyOoSGn/Pf6+e6aECBD5o6W4D51xkzcSekl79pHBSRy7xvZcT+2gXj+HZxujo9gKcYw2nDBrK2Tn+0t0UgNDkaOw/j9he8Ll6DQc3FEYb+i8= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760807886; c=relaxed/simple; bh=UfAjUKOmtRahZzYSzroX9h10xJO3sdQqYWdEbTdGpjU=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=ENzsldxFeFmormtPJLiJWPxZedyoXtqxR2X2OnllU9ceP9gYsyxRb0Mh/mBDBdDoBojRlDfFY0xWY9s04OPuUcJ3MuoQNTS1P8HCNY9PLb6URvV0+llMImWFkohS0NIMtQBUqQGn6OpEKFw4A9DzQjL+oLEP16O6wCHLZMOfepo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=soleen.com; spf=pass smtp.mailfrom=soleen.com; dkim=pass (2048-bit key) header.d=soleen.com header.i=@soleen.com header.b=HtRAWs/Z; arc=none smtp.client-ip=209.85.219.41 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=soleen.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=soleen.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=soleen.com header.i=@soleen.com header.b="HtRAWs/Z" Received: by mail-qv1-f41.google.com with SMTP id 6a1803df08f44-87c0ea50881so63674676d6.2 for ; Sat, 18 Oct 2025 10:18:04 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=soleen.com; s=google; t=1760807884; x=1761412684; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=e5WHxfW3SzIizo02A/UzhAYaawAGGPcI6431h04qDCk=; b=HtRAWs/ZmlLfwWURKigzWitdugmxD0ORBrwivOZsE9pzooMmsm9WsQCzGZAbb4F5wR w7WzHYBrAzMqP4Yj5xPx4Ir/XLjGLKPanEiMQtLQBZYUUA6P1xtfOYYpKULu16LxEc2+ uSUOqvtCqpyYR1MZ2LyuGDnl6kPoj+0IX8mDDlX9cqHMAO6utwXDJXHRdWVIJmeVWRUz spwcQ8tQloP0C4KCsMsr/gSVBaxMTlhJUl/v7Lqh7aeMQ/bNzME6rZXvoKId3CmmRedS DIJ0mIxj7bmzEqh5X9X1h3SwB1YXpeM8wCByIF1LqSIICBTpSc2f1hil2RKKU/NA4q5W FXfQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1760807884; x=1761412684; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=e5WHxfW3SzIizo02A/UzhAYaawAGGPcI6431h04qDCk=; b=nniPO0yKal7LmpkltkOuAUMWBlxG/REL8ffUhRzN/SSzT+tLSNgyt87SkxY9VALHeu LY3jKNr50NJLPFaWI2urPCgBWHlIK1uUXKmPebhhd8ynn84YgH+aBlaJQNgnrxn7ZqD7 sO6VDDEVHbyCz/O+M+YkA2g1xlV6VqMRBMEVwwPwypsEDXe2HLUfFy/WRDiQm8HyluDO h7Me3ssbLGCVNpWz7FIcD1Y5yU7DFLZRgzRuCyLQleZZaXUcQgSHq8S1zvTRUid6ni05 KmwJUwGjELnKT/N5QnGyiT/OiGY87qka3gBx89mMFiZ+xeJKKnK/jKUsrRxHCTo3C3f3 dT4Q== X-Forwarded-Encrypted: i=1; AJvYcCX7JhiLUHMRN3KQsWuPtGAuSUWbceGhSzfK9a5iAsC1GbSXlLTrRp8J4zibV7b72HkeCc8VSyZ8m4Cs62g=@vger.kernel.org X-Gm-Message-State: AOJu0Yw5M0EvrL2J280WiX6998dVEi5YVFCrEasIfWap4k401WxgI16c gkw1F7f+12DXwIQ1jd1fwhRfHAA2FJky9x5IQ+WUPVTHV9v7+lM1oBuZLYeNBLIc6Fq7nvs4+HT YNdy8 X-Gm-Gg: ASbGnctaEu6a+h4kXM3XahIJdtFtEPjdsQAeh2BjEFnkUbtDTAGUdgGGsG0jvJcLmuC PDn0fgSc5jpUxr6QhGJd6QvBNlhhvoy3OtCiPfPT+Hru1XkPCBk6lMQ81HgzLiwoLnBB7lzR1Xf Lqk2+mLkZ5PfAGWs/vD1yXEOq5aFgmVZA8+fxaKyGiI9mh5VJjMCzRDQ/VauA5IszjD4zdwxAS2 yf/dz47HMhH5e7AHKi6Yg5zdY0XcDYOOMgnLfxqX/ORQ1m42VTYVxk2RogT5ygofByvrffqnINj IQwVsDNm7ejUeVF9KOTEdiVDrQ3ywzAcrGUFRpOThm6VifCmj6HpNWaCwUoaL8XG6SLCiKvnTBu w8w9a1Ng3GedvTbiSYHDiHTcS2K9NMyg/Xkb+/HGZXaaMfs/jJ47gZtfZVqR05JJmjHI9iUgp5i inm8O9zbpUpgga/brUbl/BD7R4yjVxTS6lYdW59kJQXficE/JWYlOrqFpUwH6HYIfyuCWdJ9uSR /dwcdax7hISyw1Xy+ALLw== X-Google-Smtp-Source: AGHT+IG0KpOyqwiHpmU8fcJJ9o2guHulcSg9jALnJeFdUCRHHRENhNr850M5g3dIeP0VTEoRasLhkQ== X-Received: by 2002:a05:6214:d04:b0:87d:cabd:d4a3 with SMTP id 6a1803df08f44-87dcabdd615mr25975966d6.49.1760807883659; Sat, 18 Oct 2025 10:18:03 -0700 (PDT) Received: from soleen.us-east4-b.c.cloudtop-prod-us-east.internal (53.47.86.34.bc.googleusercontent.com. [34.86.47.53]) by smtp.gmail.com with ESMTPSA id 6a1803df08f44-87d02d8e909sm18478116d6.62.2025.10.18.10.18.02 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 18 Oct 2025 10:18:03 -0700 (PDT) From: Pasha Tatashin To: akpm@linux-foundation.org, brauner@kernel.org, corbet@lwn.net, graf@amazon.com, jgg@ziepe.ca, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-mm@kvack.org, masahiroy@kernel.org, ojeda@kernel.org, pasha.tatashin@soleen.com, pratyush@kernel.org, rdunlap@infradead.org, rppt@kernel.org, tj@kernel.org, jasonmiu@google.com, dmatlack@google.com, skhawaja@google.com Subject: [PATCH v6 04/10] kho: add interfaces to unpreserve folios and page ranes Date: Sat, 18 Oct 2025 13:17:50 -0400 Message-ID: <20251018171756.1724191-5-pasha.tatashin@soleen.com> X-Mailer: git-send-email 2.51.0.915.g61a8936c21-goog In-Reply-To: <20251018171756.1724191-1-pasha.tatashin@soleen.com> References: <20251018171756.1724191-1-pasha.tatashin@soleen.com> 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" Allow users of KHO to cancel the previous preservation by adding the necessary interfaces to unpreserve folio and pages. Signed-off-by: Pasha Tatashin --- include/linux/kexec_handover.h | 12 +++++ kernel/kexec_handover.c | 85 ++++++++++++++++++++++++++++------ 2 files changed, 84 insertions(+), 13 deletions(-) diff --git a/include/linux/kexec_handover.h b/include/linux/kexec_handover.h index 2faf290803ce..4ba145713838 100644 --- a/include/linux/kexec_handover.h +++ b/include/linux/kexec_handover.h @@ -43,7 +43,9 @@ bool kho_is_enabled(void); bool is_kho_boot(void); =20 int kho_preserve_folio(struct folio *folio); +int kho_unpreserve_folio(struct folio *folio); int kho_preserve_pages(struct page *page, unsigned int nr_pages); +int kho_unpreserve_pages(struct page *page, unsigned int nr_pages); int kho_preserve_vmalloc(void *ptr, struct kho_vmalloc *preservation); struct folio *kho_restore_folio(phys_addr_t phys); struct page *kho_restore_pages(phys_addr_t phys, unsigned int nr_pages); @@ -76,11 +78,21 @@ static inline int kho_preserve_folio(struct folio *foli= o) return -EOPNOTSUPP; } =20 +static inline int kho_unpreserve_folio(struct folio *folio) +{ + return -EOPNOTSUPP; +} + static inline int kho_preserve_pages(struct page *page, unsigned int nr_pa= ges) { return -EOPNOTSUPP; } =20 +static inline int kho_unpreserve_pages(struct page *page, unsigned int nr_= pages) +{ + return -EOPNOTSUPP; +} + static inline int kho_preserve_vmalloc(void *ptr, struct kho_vmalloc *preservation) { diff --git a/kernel/kexec_handover.c b/kernel/kexec_handover.c index e6890fe6a171..78acaa218c12 100644 --- a/kernel/kexec_handover.c +++ b/kernel/kexec_handover.c @@ -153,26 +153,33 @@ static void *xa_load_or_alloc(struct xarray *xa, unsi= gned long index, size_t sz) return elm; } =20 -static void __kho_unpreserve(struct kho_mem_track *track, unsigned long pf= n, - unsigned long end_pfn) +static void __kho_unpreserve_order(struct kho_mem_track *track, unsigned l= ong pfn, + unsigned int order) { struct kho_mem_phys_bits *bits; struct kho_mem_phys *physxa; + const unsigned long pfn_high =3D pfn >> order; =20 - while (pfn < end_pfn) { - const unsigned int order =3D - min(count_trailing_zeros(pfn), ilog2(end_pfn - pfn)); - const unsigned long pfn_high =3D pfn >> order; + physxa =3D xa_load(&track->orders, order); + if (!physxa) + return; + + bits =3D xa_load(&physxa->phys_bits, pfn_high / PRESERVE_BITS); + if (!bits) + return; =20 - physxa =3D xa_load(&track->orders, order); - if (!physxa) - continue; + clear_bit(pfn_high % PRESERVE_BITS, bits->preserve); +} + +static void __kho_unpreserve(struct kho_mem_track *track, unsigned long pf= n, + unsigned long end_pfn) +{ + unsigned int order; =20 - bits =3D xa_load(&physxa->phys_bits, pfn_high / PRESERVE_BITS); - if (!bits) - continue; + while (pfn < end_pfn) { + order =3D min(count_trailing_zeros(pfn), ilog2(end_pfn - pfn)); =20 - clear_bit(pfn_high % PRESERVE_BITS, bits->preserve); + __kho_unpreserve_order(track, pfn, order); =20 pfn +=3D 1 << order; } @@ -734,6 +741,30 @@ int kho_preserve_folio(struct folio *folio) } EXPORT_SYMBOL_GPL(kho_preserve_folio); =20 +/** + * kho_unpreserve_folio - unpreserve a folio. + * @folio: folio to unpreserve. + * + * Instructs KHO to unpreserve a folio that was preserved by + * kho_preserve_folio() before. The provided @folio (pfn and order) + * must exactly match a previously preserved folio. + * + * Return: 0 on success, error code on failure + */ +int kho_unpreserve_folio(struct folio *folio) +{ + const unsigned long pfn =3D folio_pfn(folio); + const unsigned int order =3D folio_order(folio); + struct kho_mem_track *track =3D &kho_out.track; + + if (kho_out.finalized) + return -EBUSY; + + __kho_unpreserve_order(track, pfn, order); + return 0; +} +EXPORT_SYMBOL_GPL(kho_unpreserve_folio); + /** * kho_preserve_pages - preserve contiguous pages across kexec * @page: first page in the list. @@ -773,6 +804,34 @@ int kho_preserve_pages(struct page *page, unsigned int= nr_pages) } EXPORT_SYMBOL_GPL(kho_preserve_pages); =20 +/** + * kho_unpreserve_pages - unpreserve contiguous pages. + * @page: first page in the list. + * @nr_pages: number of pages. + * + * Instructs KHO to unpreserve @nr_pages contigious pages starting from @= page. + * This call must exactly match a granularity at which memory was original= ly + * preserved by kho_preserve_pages, call with the same @page and + * @nr_pages). Unpreserving arbitrary sub-ranges of larger preserved block= s is + * not supported. + * + * Return: 0 on success, error code on failure + */ +int kho_unpreserve_pages(struct page *page, unsigned int nr_pages) +{ + struct kho_mem_track *track =3D &kho_out.track; + const unsigned long start_pfn =3D page_to_pfn(page); + const unsigned long end_pfn =3D start_pfn + nr_pages; + + if (kho_out.finalized) + return -EBUSY; + + __kho_unpreserve(track, start_pfn, end_pfn); + + return 0; +} +EXPORT_SYMBOL_GPL(kho_unpreserve_pages); + struct kho_vmalloc_hdr { DECLARE_KHOSER_PTR(next, struct kho_vmalloc_chunk *); }; --=20 2.51.0.915.g61a8936c21-goog From nobody Sat Feb 7 05:52:34 2026 Received: from mail-qv1-f43.google.com (mail-qv1-f43.google.com [209.85.219.43]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id CA88425B1C7 for ; Sat, 18 Oct 2025 17:18:05 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.219.43 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760807887; cv=none; b=eOP3MowUGwZcyNVuTnhB+Epeaee5NZE7HsXVm15/3nommjM0wJZm095barkdne1p6Bry0vt84Zgt1MeKGKbKh4BeS+n7Vg1xP67lFBnr6vey8kL8i0v/78FRMyepgmvxwZXruHOXlgAaDo95zxXA/U7iE+SdDAsPnp8pHy3nHZA= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760807887; c=relaxed/simple; bh=C9Ra1j+hNcxx2B5cYdmhSumT/vB9fFQNVijx1jxEqF0=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=QnBrGLtXvfDH4VVro6/q0Q8bR15yCrNQRIMNYqjwDDLV0DK8S0bWqQy5cNrB0h5Px3B+/QxOXnMPhJvSWFeHcWhnugswIIU48Csta8ccChSx0ytqXh/Ye7Np11b72ikR2GgplhlKaLO2oUVd3czboeqZWOYGYPbVxcZD6e1vdI4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=soleen.com; spf=pass smtp.mailfrom=soleen.com; dkim=pass (2048-bit key) header.d=soleen.com header.i=@soleen.com header.b=cIuEA7cj; arc=none smtp.client-ip=209.85.219.43 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=soleen.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=soleen.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=soleen.com header.i=@soleen.com header.b="cIuEA7cj" Received: by mail-qv1-f43.google.com with SMTP id 6a1803df08f44-87d8fa51993so13140686d6.1 for ; Sat, 18 Oct 2025 10:18:05 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=soleen.com; s=google; t=1760807885; x=1761412685; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=MeSkThIp0BgOUgzAnruASuFbTYnRMFC8HwaL1xWtkt0=; b=cIuEA7cjKePY6w50215cBWsvRroZwjvzGJUyQIcJIDLMfSIUZhCCCCoatlfjEr9keA nVfhfbBxkx2EgIarigcZsPY2ZEROyiu+1zBwHCZ8LkCo3QGCT3sizv1Nz6HezPjFMexX upjeCg9/skrvGzMla+RfW6q1u3EsVmaqpZeLU9lt8jJzmVsQOdmtV5H1uUHCcaqj1HGs IBFLnKtSZN7HI9LDWzaFjzRfM70n4AlzurCNEJYeWqH27mScG6h6FKXiOIiTBCMluGE+ BR9zq5lAOrOyuFuaQFR3UV2EtEKwTZpDq8fQ1mcYEHJ0b3Zt6yQHQ2EyvT6AeJ7s6bja MV0w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1760807885; x=1761412685; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=MeSkThIp0BgOUgzAnruASuFbTYnRMFC8HwaL1xWtkt0=; b=KRs+zZJVV6xp67+6IcquTAJYCokKzqQ8gvI1d7CDlCeRmCGnz/y8L+5y2yk2xH3AWg CL6BS016aaEEf/niBXrSCYr4PkAL437CIgYLewS1wZZn7dP/mBwTA60YR3m1FXtp8wZ4 zE7taa2q/3mGrRfsufXazvplweZBRe/TVLzEcSzyuf0AmnYtDDry+JBOFdByX9vmEsGL ejLL41C0g1Ymy2+YXaVKYREWIjb17l8ExyDrcAv1qtj3nB2Vg4H+TBKcCln3h8GxEhIw u6UkDYbWYC5pOqqk4oFb/1TIrHYVhMzZCZoXLtkGVIZCo+QP/oPlCV34CDmKSq+1YWZ+ 5tyg== X-Forwarded-Encrypted: i=1; AJvYcCVd/vU4mLb1jAYvBXFss5/HXJzRN1SNYeNeQh2MEbgJyc3JWfzO9KLlaDKiBiZwn9ZL+heXHqs2eXAgeGA=@vger.kernel.org X-Gm-Message-State: AOJu0YypwlVZs2VhhWcd2i3b6qrTJEsxtHrEKU75ZADleqDtn7fjhE0C vAkDBPh+WOhjz8+bJyWlVvct+2aKf3lxk2YAoWZVJQXVTW9hK1DOneFtSqiCHRGzbJs= X-Gm-Gg: ASbGncvr0PKNfBCHsqgy8sgkO/DC3ASnXBy6+duHWNe6FhH1epQsOr+/zY19DZezYro yjYTZ+kp9hYkMTjcq1G2AZxziQTDb9LcinJEh9vrY7cm4QkJIS9xMMv3d6v6LIqGm1CulI6o+sq Qt1BZXPYaI4uTcXOH/LUzwG7CPVhmKqVC8yvqYWjx5q/ZTDNLXZCgTrJx4SN6jlvtE6MvnYtPN0 6Ckmmzdia6XuFZyy0FtAD7mIrmE41LFiZCOxrlU2dmV5WeYuFMrNqgblpgA30EDyJCmq1wc1o02 vSQjZvEgn5Li5RJfeX3eOLMvPhWYM2Yr+A2c5GLSJ042L7AMGCnA/SDhsBJm1aaooyf+GnP+dRj 9Fua+UffMRbO1tRo5+k8PAqhSi0RpYO6hN1KY9jt8iYgugKwF3g3F3ckGKFGZYOr0NOFHAcSKmq g49SIGAKmhvm8XL8ZpZmiPBh+zZNzNSQTl/9MYWuQ0NXVHdqGutw/58Kx0ul8cBiF956O+9Npae xM3YF7sPTjZ31tvV4x5yg== X-Google-Smtp-Source: AGHT+IFdBNVKA7wbdhBQt+CIgKi8/22s9Ed+9OmPWE+pFu/N1e12A5/0MkyaV4HSpQyJ88+n0QIffQ== X-Received: by 2002:a05:6214:319a:b0:87c:20b5:6685 with SMTP id 6a1803df08f44-87c20b56795mr116436546d6.55.1760807884708; Sat, 18 Oct 2025 10:18:04 -0700 (PDT) Received: from soleen.us-east4-b.c.cloudtop-prod-us-east.internal (53.47.86.34.bc.googleusercontent.com. [34.86.47.53]) by smtp.gmail.com with ESMTPSA id 6a1803df08f44-87d02d8e909sm18478116d6.62.2025.10.18.10.18.03 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 18 Oct 2025 10:18:04 -0700 (PDT) From: Pasha Tatashin To: akpm@linux-foundation.org, brauner@kernel.org, corbet@lwn.net, graf@amazon.com, jgg@ziepe.ca, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-mm@kvack.org, masahiroy@kernel.org, ojeda@kernel.org, pasha.tatashin@soleen.com, pratyush@kernel.org, rdunlap@infradead.org, rppt@kernel.org, tj@kernel.org, jasonmiu@google.com, dmatlack@google.com, skhawaja@google.com Subject: [PATCH v6 05/10] kho: don't unpreserve memory during abort Date: Sat, 18 Oct 2025 13:17:51 -0400 Message-ID: <20251018171756.1724191-6-pasha.tatashin@soleen.com> X-Mailer: git-send-email 2.51.0.915.g61a8936c21-goog In-Reply-To: <20251018171756.1724191-1-pasha.tatashin@soleen.com> References: <20251018171756.1724191-1-pasha.tatashin@soleen.com> 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" KHO allows clients to preserve memory regions at any point before the KHO state is finalized. The finalization process itself involves KHO performing its own actions, such as serializing the overall preserved memory map. If this finalization process is aborted, the current implementation destroys KHO's internal memory tracking structures (`kho_out.ser.track.orders`). This behavior effectively unpreserves all memory from KHO's perspective, regardless of whether those preservations were made by clients before the finalization attempt or by KHO itself during finalization. This premature unpreservation is incorrect. An abort of the finalization process should only undo actions taken by KHO as part of that specific finalization attempt. Individual memory regions preserved by clients prior to finalization should remain preserved, as their lifecycle is managed by the clients themselves. These clients might still need to call kho_unpreserve_folio() or kho_unpreserve_phys() based on their own logic, even after a KHO finalization attempt is aborted. Signed-off-by: Pasha Tatashin --- kernel/kexec_handover.c | 21 +-------------------- 1 file changed, 1 insertion(+), 20 deletions(-) diff --git a/kernel/kexec_handover.c b/kernel/kexec_handover.c index 78acaa218c12..89a8f839346b 100644 --- a/kernel/kexec_handover.c +++ b/kernel/kexec_handover.c @@ -1083,31 +1083,12 @@ EXPORT_SYMBOL_GPL(kho_restore_vmalloc); =20 static int __kho_abort(void) { - int err =3D 0; - unsigned long order; - struct kho_mem_phys *physxa; - - xa_for_each(&kho_out.track.orders, order, physxa) { - struct kho_mem_phys_bits *bits; - unsigned long phys; - - xa_for_each(&physxa->phys_bits, phys, bits) - kfree(bits); - - xa_destroy(&physxa->phys_bits); - kfree(physxa); - } - xa_destroy(&kho_out.track.orders); - if (kho_out.preserved_mem_map) { kho_mem_ser_free(kho_out.preserved_mem_map); kho_out.preserved_mem_map =3D NULL; } =20 - if (err) - pr_err("Failed to abort KHO finalization: %d\n", err); - - return err; + return 0; } =20 int kho_abort(void) --=20 2.51.0.915.g61a8936c21-goog From nobody Sat Feb 7 05:52:34 2026 Received: from mail-qv1-f53.google.com (mail-qv1-f53.google.com [209.85.219.53]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5E95E25CC4D for ; Sat, 18 Oct 2025 17:18:07 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.219.53 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760807889; cv=none; b=osQBBl2xh1egi83nVpDMIj0XkIuiSJqfaGXlHjqLylCy83ICc9NZDCQe2XFVOgHwtRO+aVUyFa9fg1pRMhhCHkDRd074UF5EEAtSoMyXtiUu5k8RVShBUWjsw3I91sM7+XqQSqnFxFQs1ik3AlhCNXRqhGryFzRID3U+iLN/Mnw= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760807889; c=relaxed/simple; bh=MTi0PLVYRQoSgU/xLE7NK8rQO/u6PQp/64/TJWga1Do=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=hnNo9/BoNVhYw0TIMgNFv/Oj2Mdr9IAYIvL1b24OzROnZH4B05vC6CiA8kwcsL0vICliS+C37+GMuYbg9tiIz07fO47dvE1wdUk5tV8jJZgnhN6wvdhCbkfLMuaanxvcSmI6o/pd6qoqFRp7Q8X9KmXbgMbIxyXSKSu66EugvPI= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=soleen.com; spf=pass smtp.mailfrom=soleen.com; dkim=pass (2048-bit key) header.d=soleen.com header.i=@soleen.com header.b=XjeXptLz; arc=none smtp.client-ip=209.85.219.53 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=soleen.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=soleen.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=soleen.com header.i=@soleen.com header.b="XjeXptLz" Received: by mail-qv1-f53.google.com with SMTP id 6a1803df08f44-791fd6bffbaso49428646d6.3 for ; Sat, 18 Oct 2025 10:18:07 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=soleen.com; s=google; t=1760807886; x=1761412686; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=v0KGeztv4ESSWdWBh1iCylNw/kUGS87Mw2BS9HYjfV8=; b=XjeXptLzKhefRvc4jkE4ncJdGi5t4IxoAoBb/wzRNrugMrzODGfB3l2ogwcS4puAb+ eHqxL1UnEKV8JF73W4dWWN/0YN+8l+Qo4+yeLwzbTRBkWEOwm7DpyCntm4DuthVR8fbc 80hrT9L5Yve7FLwvisO2RsdCdu1+hVx6wWh51CS9Zr0vUxI+ZRTK4W5sJ7TmJuE4TCaX W62KGxM026Kk/zfq8+8QcXldjOOZPXoM45kvfv57m5CxgcrZgIsCVsxgOcNkISKcfBTM qi3e4B8Ji7FvzW60O3/swGuqtV7CFjvKlOpIF/AdLhkSctNLixpWWTD9jzEtcADtoQe0 Qyxg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1760807886; x=1761412686; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=v0KGeztv4ESSWdWBh1iCylNw/kUGS87Mw2BS9HYjfV8=; b=JBI8IcOdk7Xknk3FW/qmsBBxtFEi+tJuN8d8oJsTOEwlWuSBdx7aUBnx4uc9PLSh0R ITYiEfzZ+KypIfwHzHfDbS/yxe9ixqIZlRy4VRc5PbpwD2JpOUPk2VeHL1cAgJhKFkRm lchJOLS5rhONwCQByymgcX87W8XT24MnN7Qr4zAo4C64/BeZAluwpx6hFIsr8QX4sWUJ dcL1GI+4l7Pckpe5iVLbmmKYyUr4GgFVP56guKebguTqvfMpIwODH1KmmJhkyDMMydF9 sQB3QBPN1CY0EC314PNCMBTedVzSsa0PezHL5CpGLv2LdArCgrVNbmW0oalqRSSarRHP DqYQ== X-Forwarded-Encrypted: i=1; AJvYcCV/Fet3XvYzBEoAJL7QAMtjngSZWOIq3o7WGkwlpFFLN1NSiQe1Cb0qBJ3ZF+OQ1GHZEABp44rwPiTAV2Y=@vger.kernel.org X-Gm-Message-State: AOJu0Yzcr8peLhX19ezC4sAy8IK4PQRWJ8BvkUs9Ug/oT0HDda7lX/CJ EbfKOIpzuJSmZ8GgYzMB+J0A65NPePnC8JBIV4QhQASewRiNhRYralNwgWKVIBHdm0w= X-Gm-Gg: ASbGncs6uAVi8rkd9GHby+Dlx756GG/hxjI8W6i6qVrqGIP9tl3GG0l5je6jzRUYBRH AqYY3+Kb6XXHZaKM6T6Vm1eNngYBJLvER/PkMVOQaa7bAB5uZwMQqKKvgUEuCseD36WLCCUlaD6 1olCW91kXGIvaGtHGJGDLyd4AsX/Pj931/+Mh17HGAuADykaWWlw2k4gJB1RzWhb4ex8M5SFWrC pmd0DAfqLlPHh+KcxaogZYbyXxyfRzVt31SrO4z68VOHmdmogNuo6RkYlFciKAg8gqCYLo5uNoY dx10W13/niZHLCiVImMNb4JYAUncIKU2P1Yk4Jw4Fbhsg8+cpvuV1kjXpl9Z0E4+McB8IcnkNCg n/0nSYuAJgdj6LyoOWSH6xlcVK7k2Ec27oDqfcP7gA4xjVGkcIxRv9Pidj9ke6rWtxAA+YU39zN WkjDRWQKtjRGN/jL5F0QTOtbQaSYIyE5ILqG9SttURGfEGdIXrVnqIIRYFudX91au+gpi3cyrlm CXzadEmmZfg5HPt7vkq7KVeRWuYaQNZ33Dlyb2BM2o= X-Google-Smtp-Source: AGHT+IErd3wQdsBbdwbR5WTIdnOJzNl17T2SsFZBA1bPXFw2Ejn8Q8idBkGg/OwcTd1BnjUf8btzoQ== X-Received: by 2002:ad4:5ecb:0:b0:710:9995:ced4 with SMTP id 6a1803df08f44-87c2057f40amr111039536d6.17.1760807886240; Sat, 18 Oct 2025 10:18:06 -0700 (PDT) Received: from soleen.us-east4-b.c.cloudtop-prod-us-east.internal (53.47.86.34.bc.googleusercontent.com. [34.86.47.53]) by smtp.gmail.com with ESMTPSA id 6a1803df08f44-87d02d8e909sm18478116d6.62.2025.10.18.10.18.04 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 18 Oct 2025 10:18:05 -0700 (PDT) From: Pasha Tatashin To: akpm@linux-foundation.org, brauner@kernel.org, corbet@lwn.net, graf@amazon.com, jgg@ziepe.ca, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-mm@kvack.org, masahiroy@kernel.org, ojeda@kernel.org, pasha.tatashin@soleen.com, pratyush@kernel.org, rdunlap@infradead.org, rppt@kernel.org, tj@kernel.org, jasonmiu@google.com, dmatlack@google.com, skhawaja@google.com Subject: [PATCH v6 06/10] liveupdate: kho: move to kernel/liveupdate Date: Sat, 18 Oct 2025 13:17:52 -0400 Message-ID: <20251018171756.1724191-7-pasha.tatashin@soleen.com> X-Mailer: git-send-email 2.51.0.915.g61a8936c21-goog In-Reply-To: <20251018171756.1724191-1-pasha.tatashin@soleen.com> References: <20251018171756.1724191-1-pasha.tatashin@soleen.com> 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" Move KHO to kernel/liveupdate/ in preparation of placing all Live Update core kernel related files to the same place. Signed-off-by: Pasha Tatashin Reviewed-by: Jason Gunthorpe Reviewed-by: Mike Rapoport (Microsoft) --- Documentation/core-api/kho/concepts.rst | 2 +- MAINTAINERS | 2 +- init/Kconfig | 2 ++ kernel/Kconfig.kexec | 25 ---------------- kernel/Makefile | 3 +- kernel/liveupdate/Kconfig | 30 +++++++++++++++++++ kernel/liveupdate/Makefile | 4 +++ kernel/{ =3D> liveupdate}/kexec_handover.c | 6 ++-- .../{ =3D> liveupdate}/kexec_handover_debugfs.c | 0 .../kexec_handover_internal.h | 0 10 files changed, 42 insertions(+), 32 deletions(-) create mode 100644 kernel/liveupdate/Kconfig create mode 100644 kernel/liveupdate/Makefile rename kernel/{ =3D> liveupdate}/kexec_handover.c (99%) rename kernel/{ =3D> liveupdate}/kexec_handover_debugfs.c (100%) rename kernel/{ =3D> liveupdate}/kexec_handover_internal.h (100%) diff --git a/Documentation/core-api/kho/concepts.rst b/Documentation/core-a= pi/kho/concepts.rst index 36d5c05cfb30..d626d1dbd678 100644 --- a/Documentation/core-api/kho/concepts.rst +++ b/Documentation/core-api/kho/concepts.rst @@ -70,5 +70,5 @@ in the FDT. That state is called the KHO finalization pha= se. =20 Public API =3D=3D=3D=3D=3D=3D=3D=3D=3D=3D -.. kernel-doc:: kernel/kexec_handover.c +.. kernel-doc:: kernel/liveupdate/kexec_handover.c :export: diff --git a/MAINTAINERS b/MAINTAINERS index 54f627a639b1..0e7fa104422c 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -13782,7 +13782,7 @@ S: Maintained F: Documentation/admin-guide/mm/kho.rst F: Documentation/core-api/kho/* F: include/linux/kexec_handover.h -F: kernel/kexec_handover* +F: kernel/liveupdate/kexec_handover* F: tools/testing/selftests/kho/ =20 KEYS-ENCRYPTED diff --git a/init/Kconfig b/init/Kconfig index cab3ad28ca49..0605de5d96c0 100644 --- a/init/Kconfig +++ b/init/Kconfig @@ -2138,6 +2138,8 @@ config TRACEPOINTS =20 source "kernel/Kconfig.kexec" =20 +source "kernel/liveupdate/Kconfig" + endmenu # General setup =20 source "arch/Kconfig" diff --git a/kernel/Kconfig.kexec b/kernel/Kconfig.kexec index 03c3aa6263d3..15632358bcf7 100644 --- a/kernel/Kconfig.kexec +++ b/kernel/Kconfig.kexec @@ -94,31 +94,6 @@ config KEXEC_JUMP Jump between original kernel and kexeced kernel and invoke code in physical address mode via KEXEC =20 -config KEXEC_HANDOVER - bool "kexec handover" - depends on ARCH_SUPPORTS_KEXEC_HANDOVER && ARCH_SUPPORTS_KEXEC_FILE - depends on !DEFERRED_STRUCT_PAGE_INIT - select MEMBLOCK_KHO_SCRATCH - select KEXEC_FILE - select DEBUG_FS - select LIBFDT - select CMA - help - Allow kexec to hand over state across kernels by generating and - passing additional metadata to the target kernel. This is useful - to keep data or state alive across the kexec. For this to work, - both source and target kernels need to have this option enabled. - -config KEXEC_HANDOVER_DEBUGFS - bool "kexec handover debugfs interface" - depends on KEXEC_HANDOVER - depends on DEBUG_FS - help - Allow to control kexec handover device tree via debugfs - interface, i.e. finalize the state or aborting the finalization. - Also, enables inspecting the KHO fdt trees with the debugfs binary - blobs. - config CRASH_DUMP bool "kernel crash dumps" default ARCH_DEFAULT_CRASH_DUMP diff --git a/kernel/Makefile b/kernel/Makefile index 06bfe691439b..e83669841b8c 100644 --- a/kernel/Makefile +++ b/kernel/Makefile @@ -52,6 +52,7 @@ obj-y +=3D printk/ obj-y +=3D irq/ obj-y +=3D rcu/ obj-y +=3D livepatch/ +obj-y +=3D liveupdate/ obj-y +=3D dma/ obj-y +=3D entry/ obj-y +=3D unwind/ @@ -82,8 +83,6 @@ obj-$(CONFIG_CRASH_DUMP_KUNIT_TEST) +=3D crash_core_test.o obj-$(CONFIG_KEXEC) +=3D kexec.o obj-$(CONFIG_KEXEC_FILE) +=3D kexec_file.o obj-$(CONFIG_KEXEC_ELF) +=3D kexec_elf.o -obj-$(CONFIG_KEXEC_HANDOVER) +=3D kexec_handover.o -obj-$(CONFIG_KEXEC_HANDOVER_DEBUGFS) +=3D kexec_handover_debugfs.o obj-$(CONFIG_BACKTRACE_SELF_TEST) +=3D backtracetest.o obj-$(CONFIG_COMPAT) +=3D compat.o obj-$(CONFIG_CGROUPS) +=3D cgroup/ diff --git a/kernel/liveupdate/Kconfig b/kernel/liveupdate/Kconfig new file mode 100644 index 000000000000..cea287842475 --- /dev/null +++ b/kernel/liveupdate/Kconfig @@ -0,0 +1,30 @@ +# SPDX-License-Identifier: GPL-2.0-only + +menu "Live Update and Kexec HandOver" + +config KEXEC_HANDOVER + bool "kexec handover" + depends on ARCH_SUPPORTS_KEXEC_HANDOVER && ARCH_SUPPORTS_KEXEC_FILE + depends on !DEFERRED_STRUCT_PAGE_INIT + select MEMBLOCK_KHO_SCRATCH + select KEXEC_FILE + select DEBUG_FS + select LIBFDT + select CMA + help + Allow kexec to hand over state across kernels by generating and + passing additional metadata to the target kernel. This is useful + to keep data or state alive across the kexec. For this to work, + both source and target kernels need to have this option enabled. + +config KEXEC_HANDOVER_DEBUGFS + bool "kexec handover debugfs interface" + depends on KEXEC_HANDOVER + depends on DEBUG_FS + help + Allow to control kexec handover device tree via debugfs + interface, i.e. finalize the state or aborting the finalization. + Also, enables inspecting the KHO fdt trees with the debugfs binary + blobs. + +endmenu diff --git a/kernel/liveupdate/Makefile b/kernel/liveupdate/Makefile new file mode 100644 index 000000000000..fcdf163b4b0e --- /dev/null +++ b/kernel/liveupdate/Makefile @@ -0,0 +1,4 @@ +# SPDX-License-Identifier: GPL-2.0 + +obj-$(CONFIG_KEXEC_HANDOVER) +=3D kexec_handover.o +obj-$(CONFIG_KEXEC_HANDOVER_DEBUGFS) +=3D kexec_handover_debugfs.o diff --git a/kernel/kexec_handover.c b/kernel/liveupdate/kexec_handover.c similarity index 99% rename from kernel/kexec_handover.c rename to kernel/liveupdate/kexec_handover.c index 89a8f839346b..c87d00c40c82 100644 --- a/kernel/kexec_handover.c +++ b/kernel/liveupdate/kexec_handover.c @@ -24,8 +24,8 @@ * KHO is tightly coupled with mm init and needs access to some of mm * internal APIs. */ -#include "../mm/internal.h" -#include "kexec_internal.h" +#include "../../mm/internal.h" +#include "../kexec_internal.h" #include "kexec_handover_internal.h" =20 #define KHO_FDT_COMPATIBLE "kho-v1" @@ -1124,7 +1124,7 @@ static int __kho_finalize(void) err |=3D fdt_finish_reservemap(root); err |=3D fdt_begin_node(root, ""); err |=3D fdt_property_string(root, "compatible", KHO_FDT_COMPATIBLE); - /** + /* * Reserve the preserved-memory-map property in the root FDT, so * that all property definitions will precede subnodes created by * KHO callers. diff --git a/kernel/kexec_handover_debugfs.c b/kernel/liveupdate/kexec_hand= over_debugfs.c similarity index 100% rename from kernel/kexec_handover_debugfs.c rename to kernel/liveupdate/kexec_handover_debugfs.c diff --git a/kernel/kexec_handover_internal.h b/kernel/liveupdate/kexec_han= dover_internal.h similarity index 100% rename from kernel/kexec_handover_internal.h rename to kernel/liveupdate/kexec_handover_internal.h --=20 2.51.0.915.g61a8936c21-goog From nobody Sat Feb 7 05:52:34 2026 Received: from mail-qv1-f54.google.com (mail-qv1-f54.google.com [209.85.219.54]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 45D2A25EF81 for ; Sat, 18 Oct 2025 17:18:08 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.219.54 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760807890; cv=none; b=PXMUDhxnajwhe1wRKYYGr6MOecvZnYjB+cYnU94SQsqiFUEUuFKmi0Ul5uSlgsMOuIg6OVHWwsDFf3Y4fa1GjijtCRegz1cWApOwIK3yez/Z8Q3gtVsX0Yl29+r+f9lKLbu75O43m2h0Od5vkiLX3tBxIX2/vGvtfBQFslhBL1c= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760807890; c=relaxed/simple; bh=BgJDaSS37AfTWmdC+Ced4iT0wmfV6rKUobcozTNQ4QM=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=I7CkOwedjZ66dvwb3eu3fVAyaoL96Hqhi+fI5zFVbX9+YF0xhXI8av/SP0PYor6eFhHjOKCiPQespKtWEgLJwvF4wKK9JJqcbMdQa3PBGkFsMqtvX8w9KUUoKjkFWCGVWEqGycoUsEBsAPq9k55yuoTmvu72JKGOJRmAVsAeVHM= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=soleen.com; spf=pass smtp.mailfrom=soleen.com; dkim=pass (2048-bit key) header.d=soleen.com header.i=@soleen.com header.b=TfmjLqBp; arc=none smtp.client-ip=209.85.219.54 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=soleen.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=soleen.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=soleen.com header.i=@soleen.com header.b="TfmjLqBp" Received: by mail-qv1-f54.google.com with SMTP id 6a1803df08f44-78e4056623fso38714896d6.2 for ; Sat, 18 Oct 2025 10:18:08 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=soleen.com; s=google; t=1760807887; x=1761412687; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=i2rPu3rJk61NsUDORe6hfrEPNayKm6hvJ8nWbKNdE/g=; b=TfmjLqBpedvNsbuDQW857+8qakFh01u3qpDjNE64rIPulwsCwZZTf/jcBNpxNtZP+R 6YSophr+QGwMrkl1etOf7CWGimqtmB75hf8i71riI1Eo4Medjb/cdxNYiGOeMv00Dro9 O960OH942J3z+HwPPFfQRqsyIyWDIX1WZdgB9V+dJC/tebuSpGmm7U3OvP5/FGoAkAlQ lkwz1eBULSwdtLJ/8cJXDFOR6yWKwlMBGw/kAyb7Ew4mpVPMgIyNG9vDqMTq3ODGpMsA nC7MS7yri3b2nz3EEH5rasEWPs6lE/3jhpHweehnzbLsUZvo6f/h2P9r9KWZkII9I/q6 dyZg== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1760807887; x=1761412687; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=i2rPu3rJk61NsUDORe6hfrEPNayKm6hvJ8nWbKNdE/g=; b=UYwQlIronUcsKP915mqOh1Ywc87nmLmdmPEe9rJbbWnxhkBsMP8uPe+IStyGjkNEH4 mYL2l9Lre4OlwrekKW11yNDDVOvdxsC9fCZGz3GYnd+rWo9+qsgJ5QeDT6J5NChOlgTk U4Npt/LNTRn6fYZIWqK/gx21w/yVtXGeQ1nUN0jP210549Vp47WCZwwzbUcxVvKEylki jY9PGmwI3p3kfe2zu2979OgkHE9sa0xxYdS6Dza+EmZjIIu6sbIYh5wBmhzOSWBtEsw/ E1VIlxd/BkIe8a61PTnWYgq8aK4radwOSxPuv+Y/P7KxOlWMvQs9X9XBSzxI6EeD9EaB Z6Iw== X-Forwarded-Encrypted: i=1; AJvYcCUmLGD+iTT5e0aAPj4WYCthK/5GVZKtCoh/WJO2QsyZB0UrsjG7X1A9EW9ObKCCJdLUXn7me+uJXKq27lE=@vger.kernel.org X-Gm-Message-State: AOJu0YySOvHrVT+sJCkpf6w+DOIu5Ef2PH+dAtMQkYHfrWOEwGRKeNM4 wf1wlPQSv/cQn9AvRnuqZ69c2QQUHlDOc85e6F4hgv3x3+oC6N/g7am+wBjyVcmTG0w= X-Gm-Gg: ASbGncvEwIH2r8LqUtoZ51Uhi3gfdkMO2IXg5DSUnVaN5qZcm3Wzmah7KqRFm9Ktg/7 SikAqoB4BXUoe85hJzbtIdF4Hig2WilkGFtvz0ayq/bnAB48SbUeNJNyxWu+msq4LUSfF+MR10Q d2N+QruR+zzoU8hmexDitFDPIxF2qG8G2FC74Xj9uBoZG3z9uLCuSB5IKJi/6Gr78tEeMkheTnW KIfg30pLT+q2JUkvpNJ7WYqVwz7A508YrTYGJxZnHU6fmjHMEevYPUHvQiuwESbtRtrMD6bbhvR FlzSG3LBXsYUlwM+O8t/s9XJ1C1ALUajYUWmZNiiIiAUMAxb0pj7CpA2xG25cDs2HDAJXa8mmZN fF0UDmnOOcujFnN0NY61ts1t4HyBAaOwDhjzQAbWyzRaHOpJvMGKuZffzjQymekn3Jo0O2sNzKu cdxOyt642+SV9CMXJflFio0Eyms2JrNTYa4BR94AkWbH50pHI3FeoGwitNf3UHxVZRUhvJ7jvtu Qv6mRzJ5jDixzhjg/Ge1LrmsIzC/xn+ X-Google-Smtp-Source: AGHT+IFVF7YTAGmDUxpNHm20v159jaCZkyWRtFxoFzlU1BR8eeX69kBkAQ/hkjYMJqzT0Bo97bEDpg== X-Received: by 2002:a05:622a:1a18:b0:4e8:b889:5c3c with SMTP id d75a77b69052e-4e8b8895f08mr10843041cf.33.1760807887246; Sat, 18 Oct 2025 10:18:07 -0700 (PDT) Received: from soleen.us-east4-b.c.cloudtop-prod-us-east.internal (53.47.86.34.bc.googleusercontent.com. [34.86.47.53]) by smtp.gmail.com with ESMTPSA id 6a1803df08f44-87d02d8e909sm18478116d6.62.2025.10.18.10.18.06 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 18 Oct 2025 10:18:06 -0700 (PDT) From: Pasha Tatashin To: akpm@linux-foundation.org, brauner@kernel.org, corbet@lwn.net, graf@amazon.com, jgg@ziepe.ca, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-mm@kvack.org, masahiroy@kernel.org, ojeda@kernel.org, pasha.tatashin@soleen.com, pratyush@kernel.org, rdunlap@infradead.org, rppt@kernel.org, tj@kernel.org, jasonmiu@google.com, dmatlack@google.com, skhawaja@google.com Subject: [PATCH v6 07/10] kho: move kho debugfs directory to liveupdate Date: Sat, 18 Oct 2025 13:17:53 -0400 Message-ID: <20251018171756.1724191-8-pasha.tatashin@soleen.com> X-Mailer: git-send-email 2.51.0.915.g61a8936c21-goog In-Reply-To: <20251018171756.1724191-1-pasha.tatashin@soleen.com> References: <20251018171756.1724191-1-pasha.tatashin@soleen.com> 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" Now, that LUO and KHO both live under kernel/liveupdate, it makes sense to also move the kho debugfs files to liveupdate/ The old names: /sys/kernel/debug/kho/out/ /sys/kernel/debug/kho/in/ The new names: /sys/kernel/debug/liveupdate/kho_out/ /sys/kernel/debug/liveupdate/kho_in/ Also, export the liveupdate_debufs_root, so future LUO selftests could use it as well. Signed-off-by: Pasha Tatashin --- kernel/liveupdate/kexec_handover_debugfs.c | 10 +++++----- kernel/liveupdate/kexec_handover_internal.h | 2 ++ tools/testing/selftests/kho/init.c | 2 +- 3 files changed, 8 insertions(+), 6 deletions(-) diff --git a/kernel/liveupdate/kexec_handover_debugfs.c b/kernel/liveupdate= /kexec_handover_debugfs.c index 6ddcd17fac3c..63447564dbe8 100644 --- a/kernel/liveupdate/kexec_handover_debugfs.c +++ b/kernel/liveupdate/kexec_handover_debugfs.c @@ -15,7 +15,7 @@ #include #include "kexec_handover_internal.h" =20 -static struct dentry *debugfs_root; +struct dentry *liveupdate_debugfs_root; =20 struct fdt_debugfs { struct list_head list; @@ -115,7 +115,7 @@ __init void kho_in_debugfs_init(struct kho_debugfs *dbg= , const void *fdt) =20 INIT_LIST_HEAD(&dbg->fdt_list); =20 - dir =3D debugfs_create_dir("in", debugfs_root); + dir =3D debugfs_create_dir("kho_in", liveupdate_debugfs_root); if (IS_ERR(dir)) { err =3D PTR_ERR(dir); goto err_out; @@ -175,7 +175,7 @@ __init int kho_out_debugfs_init(struct kho_debugfs *dbg) =20 INIT_LIST_HEAD(&dbg->fdt_list); =20 - dir =3D debugfs_create_dir("out", debugfs_root); + dir =3D debugfs_create_dir("kho_out", liveupdate_debugfs_root); if (IS_ERR(dir)) return -ENOMEM; =20 @@ -209,8 +209,8 @@ __init int kho_out_debugfs_init(struct kho_debugfs *dbg) =20 __init int kho_debugfs_init(void) { - debugfs_root =3D debugfs_create_dir("kho", NULL); - if (IS_ERR(debugfs_root)) + liveupdate_debugfs_root =3D debugfs_create_dir("liveupdate", NULL); + if (IS_ERR(liveupdate_debugfs_root)) return -ENOENT; return 0; } diff --git a/kernel/liveupdate/kexec_handover_internal.h b/kernel/liveupdat= e/kexec_handover_internal.h index de90a678274d..b3fc1957affa 100644 --- a/kernel/liveupdate/kexec_handover_internal.h +++ b/kernel/liveupdate/kexec_handover_internal.h @@ -15,6 +15,8 @@ struct kho_debugfs { struct list_head fdt_list; }; =20 +extern struct dentry *liveupdate_debugfs_root; + #else struct kho_debugfs {}; #endif diff --git a/tools/testing/selftests/kho/init.c b/tools/testing/selftests/k= ho/init.c index 6d9e91d55d68..f0136a30ce8b 100644 --- a/tools/testing/selftests/kho/init.c +++ b/tools/testing/selftests/kho/init.c @@ -11,7 +11,7 @@ /* from arch/x86/include/asm/setup.h */ #define COMMAND_LINE_SIZE 2048 =20 -#define KHO_FINALIZE "/debugfs/kho/out/finalize" +#define KHO_FINALIZE "/debugfs/liveupdate/kho_out/finalize" #define KERNEL_IMAGE "/kernel" =20 static int mount_filesystems(void) --=20 2.51.0.915.g61a8936c21-goog From nobody Sat Feb 7 05:52:34 2026 Received: from mail-qv1-f45.google.com (mail-qv1-f45.google.com [209.85.219.45]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 6468B2580F3 for ; Sat, 18 Oct 2025 17:18:09 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.219.45 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760807891; cv=none; b=E95X5l5/X2dZkfbIOTFjtPC6A4RliCkisFK1W/z9/sfUzrD8A3/w05k9sBB9bBjnJkXhCLLCYURcRtE1L/MeDGnptku8IBTWetNAiWnygL1/yvwqKYoQuPkufpgzSZwaaNGEBARPg+KiGD+LGv8bopfZWNMs5PksqWvrABSFGWQ= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760807891; c=relaxed/simple; bh=2jRwSZNaT85zOYi82myc+8ZAEywVWJKueEb4d5JJk74=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Oqvx0Y+8X6JQusnDa9ZerwJ/2Cf2PvMldM7bAILaYB6kuWWeGK/rknhggvhzmyC5tem4n6nO4LGk3MWnoGoDpA1j9V6+Hq2qAtE7J6Ef9JyeaUtgB6aBzRCNTwxXHpxswsDoGm5nya3fHqGRc/zN/dHTe7+ieCmL1H8Z9sijp6Y= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=soleen.com; spf=pass smtp.mailfrom=soleen.com; dkim=pass (2048-bit key) header.d=soleen.com header.i=@soleen.com header.b=JOSef1cE; arc=none smtp.client-ip=209.85.219.45 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=soleen.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=soleen.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=soleen.com header.i=@soleen.com header.b="JOSef1cE" Received: by mail-qv1-f45.google.com with SMTP id 6a1803df08f44-78e4056623fso38715026d6.2 for ; Sat, 18 Oct 2025 10:18:09 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=soleen.com; s=google; t=1760807888; x=1761412688; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=o7YtyqkoqKD6VWdGbdex27QCyhVfB5yWUVWWXB11RvY=; b=JOSef1cEnkLkOj3kp5bf2gq+Sr9c4et/S0rYGpXRdK8jK2E4dtzzHmyGlndPkEjKn2 j7+HDzR0oOkSndeCF9dDobRepAoDMgOONfb82i364FW4tY2z8wyYyKgDS3WAX63dJVxF zTx8bx/rtJdpsWBSU8r5RCGTun7akWWOBnZolIaKw72AwC4DnYnhSt6Pf6TWkgRV9Bbq YV3TacyfUr1kOM/K4AuJKDYNXK3fcvhTw/Lt8Vtm1AqcRz8s9IAIclQ0ojO9smFLeNox V9oozrN/z6SXJSdgXeIlRnmtKgYWuX2CDeLtGYHVAoQEQe9I4YWNMA2HwB+4i0RPwNlC l/gQ== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1760807888; x=1761412688; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=o7YtyqkoqKD6VWdGbdex27QCyhVfB5yWUVWWXB11RvY=; b=RKBqPjM+0RhP9fbp2dWxHrmmfyr9U7jNXhVfXHZe3nSvSEoNsEpsTZQ2XpxSWwo1GD 5GXEauz5xmFoMABb2Yhba2zIA4NY1Anv/GziG81bs9NkHt1N/wn9ne1Obn0/BtqqkUC1 gEEujAOXsl+MK5rYPqJPWbGHsa6Dv2AGgQ12d6fG64yVxvdr1m8juWw393tMSDMFl07q DIk5UN4K+yBnaTTgUqDpQnag+Zj/XPDbS/IjUBhUZcssgXqv0bf2eSGUZ9u8vBkbxQWA S3R9aUOAlh+C8BnB2y/puaK5FCmESNAvPHF53V/ZE1r99dh8m/3TO/oUsg40IsznEjX9 rwZw== X-Forwarded-Encrypted: i=1; AJvYcCU8sH3p+j2dXZsONMjUmnToMOoVSYA3X+cK3miRjHBW8p1BdHIm1t0ahMm5bWHYQCKyo3NhZ4zcSBCPf2E=@vger.kernel.org X-Gm-Message-State: AOJu0YzR4t6rGaNtAI5HQByAJte/3xZ5I32qobICXYigJ1c9wg6GkPPg zfrkyOfw6gfBFiL2BOcit5y9I9JGoSodg5ECD98HI9pQ+wgPorTtk6ORQWwr6S7+Wck= X-Gm-Gg: ASbGncubCgV4ihhY7zzxkJyyjTU9uYy19VDdjXajVfnwHazgqQBlF2G1Xc2OI+WAo6S 18qrjz2At3ayhTjqs4iyoHlq72PyGsz9hMkonKgS5tQZdJx57XF3puviss/bEUvON2calRq4Yhn 4cxn14NUd9LQLhKPtxcvJvg+kE7Pv1vXu8JHCiHuL5lNDCMMticYSNISAjD3whB4iS/9tss+GDy Wbk8yDBwY7AwMDFcCNICKhRoOWzZ925LCxFNhkh07bHgHVMK3gAcq9ngg144YXSwpk4hcNhWi3H ljV+jmGfqhFvm65RNqry71LFYFrN4amo6WGg0/hv3v7eRt7odc0Um8b2m+Uu6t2aVe/9UKlqVwa 7R22nT2MW8qJW2fIWO+MbmsSgpWsSQzzIeDukwGQxuggKqyHjnCpY/Qgs2TDjT9zZIFKoidYL0x bvvmTsD/I4ubZJvE5PzAdX/7VARnBq9NQP5gSHf7LL+9fon9vT0/gt9qoZTk2uU/s3gsHmVm8SP V8sBVmZvCq9jtyvX5cT4z4JEzFd+vTX X-Google-Smtp-Source: AGHT+IGtzHn/6DD3dWiswCVgFR84KeOf4/Bt9Z7b+lVvn1HSzoZWElRRGyMVVN30USlthvsHs20ChA== X-Received: by 2002:ad4:5e86:0:b0:87c:43f0:373d with SMTP id 6a1803df08f44-87c43f039damr68609776d6.39.1760807888207; Sat, 18 Oct 2025 10:18:08 -0700 (PDT) Received: from soleen.us-east4-b.c.cloudtop-prod-us-east.internal (53.47.86.34.bc.googleusercontent.com. [34.86.47.53]) by smtp.gmail.com with ESMTPSA id 6a1803df08f44-87d02d8e909sm18478116d6.62.2025.10.18.10.18.07 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 18 Oct 2025 10:18:07 -0700 (PDT) From: Pasha Tatashin To: akpm@linux-foundation.org, brauner@kernel.org, corbet@lwn.net, graf@amazon.com, jgg@ziepe.ca, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-mm@kvack.org, masahiroy@kernel.org, ojeda@kernel.org, pasha.tatashin@soleen.com, pratyush@kernel.org, rdunlap@infradead.org, rppt@kernel.org, tj@kernel.org, jasonmiu@google.com, dmatlack@google.com, skhawaja@google.com Subject: [PATCH v6 08/10] liveupdate: kho: warn and fail on metadata or preserved memory in scratch area Date: Sat, 18 Oct 2025 13:17:54 -0400 Message-ID: <20251018171756.1724191-9-pasha.tatashin@soleen.com> X-Mailer: git-send-email 2.51.0.915.g61a8936c21-goog In-Reply-To: <20251018171756.1724191-1-pasha.tatashin@soleen.com> References: <20251018171756.1724191-1-pasha.tatashin@soleen.com> 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" It is invalid for KHO metadata or preserved memory regions to be located within the KHO scratch area, as this area is overwritten when the next kernel is loaded, and used early in boot by the next kernel. This can lead to memory corruption. Adds checks to kho_preserve_* and KHO's internal metadata allocators (xa_load_or_alloc, new_chunk) to verify that the physical address of the memory does not overlap with any defined scratch region. If an overlap is detected, the operation will fail and a WARN_ON is triggered. To avoid performance overhead in production kernels, these checks are enabled only when CONFIG_KEXEC_HANDOVER_DEBUG is selected. Signed-off-by: Pasha Tatashin --- kernel/liveupdate/Kconfig | 8 ++++ kernel/liveupdate/Makefile | 1 + kernel/liveupdate/kexec_handover.c | 52 ++++++++++++++------- kernel/liveupdate/kexec_handover_debug.c | 25 ++++++++++ kernel/liveupdate/kexec_handover_internal.h | 9 ++++ 5 files changed, 78 insertions(+), 17 deletions(-) create mode 100644 kernel/liveupdate/kexec_handover_debug.c diff --git a/kernel/liveupdate/Kconfig b/kernel/liveupdate/Kconfig index cea287842475..851d1a22b4c5 100644 --- a/kernel/liveupdate/Kconfig +++ b/kernel/liveupdate/Kconfig @@ -27,4 +27,12 @@ config KEXEC_HANDOVER_DEBUGFS Also, enables inspecting the KHO fdt trees with the debugfs binary blobs. =20 +config KEXEC_HANDOVER_DEBUG + bool "Enable Kexec Handover debug checks" + depends on KEXEC_HANDOVER_DEBUGFS + help + This option enables extra sanity checks for the Kexec Handover + subsystem. Since, KHO performance is crucial in live update + scenarios and the extra code might be adding overhead it is + only optionally enabled. endmenu diff --git a/kernel/liveupdate/Makefile b/kernel/liveupdate/Makefile index fcdf163b4b0e..f52ce1ebcf86 100644 --- a/kernel/liveupdate/Makefile +++ b/kernel/liveupdate/Makefile @@ -1,4 +1,5 @@ # SPDX-License-Identifier: GPL-2.0 =20 obj-$(CONFIG_KEXEC_HANDOVER) +=3D kexec_handover.o +obj-$(CONFIG_KEXEC_HANDOVER_DEBUG) +=3D kexec_handover_debug.o obj-$(CONFIG_KEXEC_HANDOVER_DEBUGFS) +=3D kexec_handover_debugfs.o diff --git a/kernel/liveupdate/kexec_handover.c b/kernel/liveupdate/kexec_h= andover.c index c87d00c40c82..ebfc31814d16 100644 --- a/kernel/liveupdate/kexec_handover.c +++ b/kernel/liveupdate/kexec_handover.c @@ -8,6 +8,7 @@ =20 #define pr_fmt(fmt) "KHO: " fmt =20 +#include #include #include #include @@ -131,26 +132,26 @@ static struct kho_out kho_out =3D { =20 static void *xa_load_or_alloc(struct xarray *xa, unsigned long index, size= _t sz) { - void *elm, *res; + void *res =3D xa_load(xa, index); =20 - elm =3D xa_load(xa, index); - if (elm) - return elm; + if (res) + return res; + + void *elm __free(kfree) =3D kzalloc(sz, GFP_KERNEL); =20 - elm =3D kzalloc(sz, GFP_KERNEL); if (!elm) return ERR_PTR(-ENOMEM); =20 + if (WARN_ON(kho_scratch_overlap(virt_to_phys(elm), sz))) + return ERR_PTR(-EINVAL); + res =3D xa_cmpxchg(xa, index, NULL, elm, GFP_KERNEL); if (xa_is_err(res)) - res =3D ERR_PTR(xa_err(res)); - - if (res) { - kfree(elm); + return ERR_PTR(xa_err(res)); + else if (res) return res; - } =20 - return elm; + return no_free_ptr(elm); } =20 static void __kho_unpreserve_order(struct kho_mem_track *track, unsigned l= ong pfn, @@ -350,15 +351,19 @@ static_assert(sizeof(struct khoser_mem_chunk) =3D=3D = PAGE_SIZE); static struct khoser_mem_chunk *new_chunk(struct khoser_mem_chunk *cur_chu= nk, unsigned long order) { - struct khoser_mem_chunk *chunk; + struct khoser_mem_chunk *chunk __free(kfree) =3D NULL; =20 chunk =3D kzalloc(PAGE_SIZE, GFP_KERNEL); if (!chunk) - return NULL; + return ERR_PTR(-ENOMEM); + + if (WARN_ON(kho_scratch_overlap(virt_to_phys(chunk), PAGE_SIZE))) + return ERR_PTR(-EINVAL); + chunk->hdr.order =3D order; if (cur_chunk) KHOSER_STORE_PTR(cur_chunk->hdr.next, chunk); - return chunk; + return no_free_ptr(chunk); } =20 static void kho_mem_ser_free(struct khoser_mem_chunk *first_chunk) @@ -379,14 +384,17 @@ static int kho_mem_serialize(struct kho_out *kho_out) struct khoser_mem_chunk *chunk =3D NULL; struct kho_mem_phys *physxa; unsigned long order; + int ret =3D -ENOMEM; =20 xa_for_each(&kho_out->track.orders, order, physxa) { struct kho_mem_phys_bits *bits; unsigned long phys; =20 chunk =3D new_chunk(chunk, order); - if (!chunk) + if (IS_ERR(chunk)) { + ret =3D PTR_ERR(chunk); goto err_free; + } =20 if (!first_chunk) first_chunk =3D chunk; @@ -396,8 +404,10 @@ static int kho_mem_serialize(struct kho_out *kho_out) =20 if (chunk->hdr.num_elms =3D=3D ARRAY_SIZE(chunk->bitmaps)) { chunk =3D new_chunk(chunk, order); - if (!chunk) + if (IS_ERR(chunk)) { + ret =3D PTR_ERR(chunk); goto err_free; + } } =20 elm =3D &chunk->bitmaps[chunk->hdr.num_elms]; @@ -414,7 +424,7 @@ static int kho_mem_serialize(struct kho_out *kho_out) =20 err_free: kho_mem_ser_free(first_chunk); - return -ENOMEM; + return ret; } =20 static void __init deserialize_bitmap(unsigned int order, @@ -737,6 +747,9 @@ int kho_preserve_folio(struct folio *folio) const unsigned int order =3D folio_order(folio); struct kho_mem_track *track =3D &kho_out.track; =20 + if (WARN_ON(kho_scratch_overlap(pfn << PAGE_SHIFT, PAGE_SIZE << order))) + return -EINVAL; + return __kho_preserve_order(track, pfn, order); } EXPORT_SYMBOL_GPL(kho_preserve_folio); @@ -784,6 +797,11 @@ int kho_preserve_pages(struct page *page, unsigned int= nr_pages) unsigned long failed_pfn =3D 0; int err =3D 0; =20 + if (WARN_ON(kho_scratch_overlap(start_pfn << PAGE_SHIFT, + nr_pages << PAGE_SHIFT))) { + return -EINVAL; + } + while (pfn < end_pfn) { const unsigned int order =3D min(count_trailing_zeros(pfn), ilog2(end_pfn - pfn)); diff --git a/kernel/liveupdate/kexec_handover_debug.c b/kernel/liveupdate/k= exec_handover_debug.c new file mode 100644 index 000000000000..7986dcc63047 --- /dev/null +++ b/kernel/liveupdate/kexec_handover_debug.c @@ -0,0 +1,25 @@ +// SPDX-License-Identifier: GPL-2.0-only +/* + * kexec_handover_debug.c - kexec handover optional debug functionality + * Copyright (C) 2025 Google LLC, Pasha Tatashin + */ + +#define pr_fmt(fmt) "KHO: " fmt + +#include "kexec_handover_internal.h" + +bool kho_scratch_overlap(phys_addr_t phys, size_t size) +{ + phys_addr_t scratch_start, scratch_end; + unsigned int i; + + for (i =3D 0; i < kho_scratch_cnt; i++) { + scratch_start =3D kho_scratch[i].addr; + scratch_end =3D kho_scratch[i].addr + kho_scratch[i].size - 1; + + if (phys <=3D scratch_end && (phys + size) > scratch_start) + return true; + } + + return false; +} diff --git a/kernel/liveupdate/kexec_handover_internal.h b/kernel/liveupdat= e/kexec_handover_internal.h index b3fc1957affa..92798346fa5a 100644 --- a/kernel/liveupdate/kexec_handover_internal.h +++ b/kernel/liveupdate/kexec_handover_internal.h @@ -44,4 +44,13 @@ static inline void kho_debugfs_fdt_remove(struct kho_deb= ugfs *dbg, void *fdt) { } #endif /* CONFIG_KEXEC_HANDOVER_DEBUGFS */ =20 +#ifdef CONFIG_KEXEC_HANDOVER_DEBUG +bool kho_scratch_overlap(phys_addr_t phys, size_t size); +#else +static inline bool kho_scratch_overlap(phys_addr_t phys, size_t size) +{ + return false; +} +#endif /* CONFIG_KEXEC_HANDOVER_DEBUG */ + #endif /* LINUX_KEXEC_HANDOVER_INTERNAL_H */ --=20 2.51.0.915.g61a8936c21-goog From nobody Sat Feb 7 05:52:34 2026 Received: from mail-qv1-f46.google.com (mail-qv1-f46.google.com [209.85.219.46]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5B83A261B92 for ; Sat, 18 Oct 2025 17:18:10 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.219.46 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760807892; cv=none; b=jSQEPng+zy5s0S1iJ2SC/QBnaMTCDSqMCxjWO2pfjD0nxGloMdsMLjC8yc3Mzv5oLxoHneaOFkOlwnmt5Bxc83FgSXFopG5+DqlRJ+Dxcg4ZwYSNKfFDGKiBiD4ydseVEFiZ1D4VJK8So8OmyBUx6VVA78z46a0Yp5P0ZAa3f2U= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760807892; c=relaxed/simple; bh=3WWC3nv053Mu9XPdOFn+xrlFtzqec5hSHDB0nXy9HI8=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=b0wnh09FeFc/Qkmj9GZB7itf/2ZhGoyZIh8aeeMlu6d8Ys8OVv53m3NUH+NqGrClHTmvfT1ed1WuDz/a2grWW5JyJ15+9lMnxrGh0hMkz2MsZg9v0FNLlSWuinECBLB1ZD1K5isoQbJyrHlzaSTDSgDWknwR2sXfz+y+HVXa2bo= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=soleen.com; spf=pass smtp.mailfrom=soleen.com; dkim=pass (2048-bit key) header.d=soleen.com header.i=@soleen.com header.b=E1aY8Eou; arc=none smtp.client-ip=209.85.219.46 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=soleen.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=soleen.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=soleen.com header.i=@soleen.com header.b="E1aY8Eou" Received: by mail-qv1-f46.google.com with SMTP id 6a1803df08f44-7946137e7a2so52664686d6.0 for ; Sat, 18 Oct 2025 10:18:10 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=soleen.com; s=google; t=1760807889; x=1761412689; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=9+4s/LMKH18C3S9kWxUuCFP/sSm2GXOGXRSXRIxgHJg=; b=E1aY8EouFucyW8bbwCYfa7o6TUN9ne+AiwHCYZyJ2uCnz2WIcfUfUPEyibc7OPOQTU GJMV7RkQlgzLpDb5TzZEH51P4uFBVHRaUK1rfbwcGXi8youOEoXnaRa7NRkT3RO+DOPW nvMj7OoycEjd3Ty0mjofSCmviQxq8ImZMnMpNjE8qDipGMbHULaBxYVXit6VjcMZf4UR AImhFMgUukD4NV8NwvESBUIIKKY0IHytL+tV3KgCz4yfsWmINhc98hv3v2e/4S5NFWl6 UiIIIpipcA4ChFrJgRDoGbKetVPG8tcizaWosX1DFtr19PA2aytKlwy3sTEwOgQUZaMm Wr5w== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1760807889; x=1761412689; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=9+4s/LMKH18C3S9kWxUuCFP/sSm2GXOGXRSXRIxgHJg=; b=s6leyrT68Krva3zyErSebtdQNyUf++W1JuUYj+S+pIGaWwRitEEe/foSIiLngDE6UZ 5DRFyBGsJt0fcmG6mnlj6fBC9ekJeUPFrSGF8vQ1wEZ/Pti5UlN6fEHZm6JQ6oIRB6PA 2oP5mzf9uZ1eJoS0gjwiUddoYrDzVdkKYLpQQ6DuZYcDPgj+rkPuY03VwNzzmqvIfbvc Jm7T0own1NmdxzFtV7L9MCJGuJQzk9Wbj5O1v0xnf7AHpq8pjY+iX/r55VV1nCKZGT8E dk/+iuhPSlHJT8tEc4Xc+Gdbxh20plqoKnfhdUswPYBGDMF10igsfGH6/XLQ/P5LaZns GLIA== X-Forwarded-Encrypted: i=1; AJvYcCUJn+pBPdAsmLjydDa9SVrD+SgItRSgktT1UxguQiI0vk3zgDor068RaZR2Zz/om6DZck/xeZYW2YpDmIQ=@vger.kernel.org X-Gm-Message-State: AOJu0YzobJUc1LJPkQDtE5PKyqoR69dl8H+xXfLEToJGwlAWg4dqcO8M 7kq3FJVqT4utDAIuklsi1zxe22whuMQTvORnuci7mt6dPC66e6CcrUEAzfvkEQrYPuw= X-Gm-Gg: ASbGncsqKPA2cKdOKvxB6HWnHV/NwhAKBtWv3zbDsi8i3EZxighVZLSrpkzuZA4pl0b jiw+GNFuERRskmE4SYmD/Yggpdr+dhOdZFioeJ439uO6nFLchn4nfB4JNI+7YZ3lkYolmqX7eSV vN7I1uVEoIMpOR1w5aPgnQBe9N58LB90SU8rJ7Hifb2OvJLWPx2nj5rorT6cBfs2W2naRKD1RcP oM9U0+rxz48cly/dvVHraHdLV5dZWhQ15GEwuMRHYMx2X4DyjBQOwYtKN36V1pEXTasnNCMnzU0 65JQ+orRa+UvMvyMirXpMF4upUe4SbZH3JRA/zLBaG/HkFi6DiDeDYpykQq8x8ENvwCvmRcIWjK 2Da6RLUQNSzi0wBPpM+E9ttGTy4u0jtz2V79crmOV0n1k1mwlO7Eurmtb2Ese+hRAwe09J2kRcA k0PnNXpTkMLF1Sp1gBR0mdao1TrrnAZIhJ+0c06ZRRYqOsi9SubPDty11NlK481ib950j4cspT4 C/eCD+g79WcpdrcvBQenKPZjislnQiP1O277bVDwQ8= X-Google-Smtp-Source: AGHT+IGwicpZ/o0IuY1PRlF5+Xwpp0Zedm9EU1jTpFbIRqEFcd5qCkFHdNzCn7aZrNCsS7eWlfmhaw== X-Received: by 2002:ad4:5b85:0:b0:7ea:1156:def3 with SMTP id 6a1803df08f44-87c205b103cmr120184846d6.28.1760807889222; Sat, 18 Oct 2025 10:18:09 -0700 (PDT) Received: from soleen.us-east4-b.c.cloudtop-prod-us-east.internal (53.47.86.34.bc.googleusercontent.com. [34.86.47.53]) by smtp.gmail.com with ESMTPSA id 6a1803df08f44-87d02d8e909sm18478116d6.62.2025.10.18.10.18.08 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 18 Oct 2025 10:18:08 -0700 (PDT) From: Pasha Tatashin To: akpm@linux-foundation.org, brauner@kernel.org, corbet@lwn.net, graf@amazon.com, jgg@ziepe.ca, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-mm@kvack.org, masahiroy@kernel.org, ojeda@kernel.org, pasha.tatashin@soleen.com, pratyush@kernel.org, rdunlap@infradead.org, rppt@kernel.org, tj@kernel.org, jasonmiu@google.com, dmatlack@google.com, skhawaja@google.com Subject: [PATCH v6 09/10] liveupdate: kho: Increase metadata bitmap size to PAGE_SIZE Date: Sat, 18 Oct 2025 13:17:55 -0400 Message-ID: <20251018171756.1724191-10-pasha.tatashin@soleen.com> X-Mailer: git-send-email 2.51.0.915.g61a8936c21-goog In-Reply-To: <20251018171756.1724191-1-pasha.tatashin@soleen.com> References: <20251018171756.1724191-1-pasha.tatashin@soleen.com> 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" Metadata is preserved via 512-bytes, which requires using slabs. Slabs are not safe to be used with KHO because of kfence, and because partial slabs may lead leaks to the next kernel. Change the size to be PAGE_SIZE. While this change could potentially increase metadata overhead on systems with sparsely preserved memory, this is being mitigated by ongoing work to reduce sparseness during preservation via 1G guest pages. Furthermore, this change aligns with future work on a stateless KHO, which will also use page-sized bitmaps for its radix tree metadata. Signed-off-by: Pasha Tatashin --- kernel/liveupdate/kexec_handover.c | 21 +++++++++++---------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/kernel/liveupdate/kexec_handover.c b/kernel/liveupdate/kexec_h= andover.c index ebfc31814d16..7c8e89a6b953 100644 --- a/kernel/liveupdate/kexec_handover.c +++ b/kernel/liveupdate/kexec_handover.c @@ -67,10 +67,10 @@ early_param("kho", kho_parse_enable); * Keep track of memory that is to be preserved across KHO. * * The serializing side uses two levels of xarrays to manage chunks of per= -order - * 512 byte bitmaps. For instance if PAGE_SIZE =3D 4096, the entire 1G ord= er of a - * 1TB system would fit inside a single 512 byte bitmap. For order 0 alloc= ations - * each bitmap will cover 16M of address space. Thus, for 16G of memory at= most - * 512K of bitmap memory will be needed for order 0. + * PAGE_SIZE byte bitmaps. For instance if PAGE_SIZE =3D 4096, the entire = 1G order + * of a 8TB system would fit inside a single 4096 byte bitmap. For order 0 + * allocations each bitmap will cover 128M of address space. Thus, for 16G= of + * memory at most 512K of bitmap memory will be needed for order 0. * * This approach is fully incremental, as the serialization progresses fol= ios * can continue be aggregated to the tracker. The final step, immediately = prior @@ -78,12 +78,14 @@ early_param("kho", kho_parse_enable); * successor kernel to parse. */ =20 -#define PRESERVE_BITS (512 * 8) +#define PRESERVE_BITS (PAGE_SIZE * 8) =20 struct kho_mem_phys_bits { DECLARE_BITMAP(preserve, PRESERVE_BITS); }; =20 +static_assert(sizeof(struct kho_mem_phys_bits) =3D=3D PAGE_SIZE); + struct kho_mem_phys { /* * Points to kho_mem_phys_bits, a sparse bitmap array. Each bit is sized @@ -130,19 +132,19 @@ static struct kho_out kho_out =3D { .finalized =3D false, }; =20 -static void *xa_load_or_alloc(struct xarray *xa, unsigned long index, size= _t sz) +static void *xa_load_or_alloc(struct xarray *xa, unsigned long index) { void *res =3D xa_load(xa, index); =20 if (res) return res; =20 - void *elm __free(kfree) =3D kzalloc(sz, GFP_KERNEL); + void *elm __free(kfree) =3D kzalloc(PAGE_SIZE, GFP_KERNEL); =20 if (!elm) return ERR_PTR(-ENOMEM); =20 - if (WARN_ON(kho_scratch_overlap(virt_to_phys(elm), sz))) + if (WARN_ON(kho_scratch_overlap(virt_to_phys(elm), PAGE_SIZE))) return ERR_PTR(-EINVAL); =20 res =3D xa_cmpxchg(xa, index, NULL, elm, GFP_KERNEL); @@ -222,8 +224,7 @@ static int __kho_preserve_order(struct kho_mem_track *t= rack, unsigned long pfn, } } =20 - bits =3D xa_load_or_alloc(&physxa->phys_bits, pfn_high / PRESERVE_BITS, - sizeof(*bits)); + bits =3D xa_load_or_alloc(&physxa->phys_bits, pfn_high / PRESERVE_BITS); if (IS_ERR(bits)) return PTR_ERR(bits); =20 --=20 2.51.0.915.g61a8936c21-goog From nobody Sat Feb 7 05:52:34 2026 Received: from mail-qv1-f53.google.com (mail-qv1-f53.google.com [209.85.219.53]) (using TLSv1.2 with cipher ECDHE-RSA-AES128-GCM-SHA256 (128/128 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 00521268C73 for ; Sat, 18 Oct 2025 17:18:11 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=209.85.219.53 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760807893; cv=none; b=G+Hk1nL5pFwR3Iqu4O55M3TNYFRTD9XacubCoWtrdnq5D+rUCCg0irtZtXMmoSMkk9z8ik8Ry95n7uUfaUKwq1r356obMKloM89E86/zbll+X7jhGmMMN81Titkxc+E+t9fMBv1S08bV8Gm33/StEjiWcGtHNoCgsjf3EWPSxnI= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1760807893; c=relaxed/simple; bh=0XF6mZTda3Mo3Xc5oEB8STcY3fJXR4+QE6+7PIztyAs=; h=From:To:Subject:Date:Message-ID:In-Reply-To:References: MIME-Version; b=Rs+IVpIBqsW5ITVG/dPykCs2o6BVC4tC1tQqSsOJt3OhNFq8GD3eAkaJ2J+5NpAxlwXfIDo5hqpPw+iMUoGPijskkYESuBeF2hnB9oB4McveYK/4KSULIlJteKoNKIcomIUmYy3DzuZlZG1RgIrNvsbSHi9FHD3AVGfyB4Q47gQ= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=soleen.com; spf=pass smtp.mailfrom=soleen.com; dkim=pass (2048-bit key) header.d=soleen.com header.i=@soleen.com header.b=TCfpxQND; arc=none smtp.client-ip=209.85.219.53 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=soleen.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=soleen.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=soleen.com header.i=@soleen.com header.b="TCfpxQND" Received: by mail-qv1-f53.google.com with SMTP id 6a1803df08f44-87be45cba29so43327016d6.2 for ; Sat, 18 Oct 2025 10:18:11 -0700 (PDT) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=soleen.com; s=google; t=1760807891; x=1761412691; darn=vger.kernel.org; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:from:to:cc:subject:date:message-id :reply-to; bh=QFLCF5XN9yDZ1vXn52PKQdU8GeSc6NQJh3Hjw9F38C4=; b=TCfpxQNDL1Il6ExdScCLbtwdSyRZGplQ+lsfZWZW/Soflhx/a9cYn2M4UTtxxFR0IC sM4FMAwWc8jDMJfUPzViZAlWGpmXJO7kANxMo2s/C+wQoM7cuWKaJHdDsfUhW35l9b1m +i5QdKE1PHPPb/hWw/dxPZB2/3j6/P692Y5BiPxmS3ecM46YTQGmiUI7eL+oHHrQBzpB pKOVmfLs94+Io91Y+35dIMe9jryFn1X8ocely1Hdi+iR//T3oCObW7JXTq6+Lb9je7BJ bKyYwe+AILl7cY2qbXibR0ag5bPla9NxHt8lR7Y9rKpTW9OQ8xqnrM8eQBkwTuAnokja eFow== X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20230601; t=1760807891; x=1761412691; h=content-transfer-encoding:mime-version:references:in-reply-to :message-id:date:subject:to:from:x-gm-message-state:from:to:cc :subject:date:message-id:reply-to; bh=QFLCF5XN9yDZ1vXn52PKQdU8GeSc6NQJh3Hjw9F38C4=; b=pvRgtoomFMQc0275sQH7L+6uLUGyM2n1dKOeq8v6/DUhW7n0zeIw14nPr12LIl9sd7 Mmd8VDVwoxVTOjgW6nuFN0INCdP02m+fN3bF1htZOyeNHx/U08P+JL1bkS0hQy3lw8MT 2G4Elih0e5P3/H0cjNzu9xgIW2/jYdKcteykQ5W2aV+/MrnZodMfU/Hyb92MvoFdyKzF gLaRycxX/veZ/dWp5h4xeje45OWql/QkT/dx1+IHB1888yd3jX1w5vN5xRQfOHRZbNS2 lurfLKtjOaUehiNrTecmA9pyHBXOiftD4XQLY9C1YtFZ/Ip8iEIq4UkVqtmIrvD6XsFa 7qdQ== X-Forwarded-Encrypted: i=1; AJvYcCUuqUqNXtpqNuPFEGYAuWn6WWm34/1s1ihWhE99hAxt65N8Mip4fVOMf2JQSOh3szYz67MEMgs/63P78kY=@vger.kernel.org X-Gm-Message-State: AOJu0Yx6u/rVcrCsuylI/28KdhrwMekCATUSQ236R3ZR91rEdDPvk2d6 J47N3wGqg09GvbYgZ47WyLHOx3Y8jn4+CcrzvMeG/bYqwhKI89uUWzWXaqWkAtZMv0E= X-Gm-Gg: ASbGncsDglxVnIDu7EQXppOW5szGq/ynFYVf9WyWji4eIEnz1ljKXR6hDGDGbVw82IH PuAVNFblrAsNALnwrLCAMgWa5QfjmnMOe5kqvwFk57jJ013tNI/M343gDMRPydzW8VkjYeX9AzC zvCAc3eFV5pUwsbbDoxl7VqstkFpDh6XyEIVlu7MA1lqhDi4wHz8WEVSaZHrqSuIcxoyF9eXfZZ R7YuPFiszV1DY7CId9HMgdv+YeSd4GK4VJ+2TRN5ha9fi1KU1B2v9dW+eCtpDEMu8YVN6PeuW8l 1P0yafrh/GgHZj5lgCelrFEMbL09hw4Wm+6bKAOfd4E1LFJb4sE2tOABhDHFMsekj9EWRNC82+v 8RtXBd7hyhmpBBa/kHrTVuABXbH493yEwD1Lb76f+CTHAbS3aqi7a0QyrzbMxODcvrVlBdggAcM tR78hJeHf+hyVKvmQB/Hd0DoJ8y0Php4C48oFPiM+N2lH/LbqxhQHpvg/baNzt29LL/Gm97jl1t SwcqwjH7MTUu1xfo1GNsh+ilenzrJ9E X-Google-Smtp-Source: AGHT+IEbH67r1bkBBr2fGDtH2iJYzk5qXpz4ZuAYuqM7y3IYRwB0Hgi7HzGfKIjAQO2jFT0oN/PwUA== X-Received: by 2002:a05:6214:8017:b0:87c:226f:f5c7 with SMTP id 6a1803df08f44-87c226ffc83mr105442856d6.38.1760807890764; Sat, 18 Oct 2025 10:18:10 -0700 (PDT) Received: from soleen.us-east4-b.c.cloudtop-prod-us-east.internal (53.47.86.34.bc.googleusercontent.com. [34.86.47.53]) by smtp.gmail.com with ESMTPSA id 6a1803df08f44-87d02d8e909sm18478116d6.62.2025.10.18.10.18.09 (version=TLS1_3 cipher=TLS_AES_256_GCM_SHA384 bits=256/256); Sat, 18 Oct 2025 10:18:10 -0700 (PDT) From: Pasha Tatashin To: akpm@linux-foundation.org, brauner@kernel.org, corbet@lwn.net, graf@amazon.com, jgg@ziepe.ca, linux-kernel@vger.kernel.org, linux-kselftest@vger.kernel.org, linux-mm@kvack.org, masahiroy@kernel.org, ojeda@kernel.org, pasha.tatashin@soleen.com, pratyush@kernel.org, rdunlap@infradead.org, rppt@kernel.org, tj@kernel.org, jasonmiu@google.com, dmatlack@google.com, skhawaja@google.com Subject: [PATCH v6 10/10] liveupdate: kho: allocate metadata directly from the buddy allocator Date: Sat, 18 Oct 2025 13:17:56 -0400 Message-ID: <20251018171756.1724191-11-pasha.tatashin@soleen.com> X-Mailer: git-send-email 2.51.0.915.g61a8936c21-goog In-Reply-To: <20251018171756.1724191-1-pasha.tatashin@soleen.com> References: <20251018171756.1724191-1-pasha.tatashin@soleen.com> 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" KHO allocates metadata for its preserved memory map using the slab allocator via kzalloc(). This metadata is temporary and is used by the next kernel during early boot to find preserved memory. A problem arises when KFENCE is enabled. kzalloc() calls can be randomly intercepted by kfence_alloc(), which services the allocation from a dedicated KFENCE memory pool. This pool is allocated early in boot via memblock. When booting via KHO, the memblock allocator is restricted to a "scratch area", forcing the KFENCE pool to be allocated within it. This creates a conflict, as the scratch area is expected to be ephemeral and overwriteable by a subsequent kexec. If KHO metadata is placed in this KFENCE pool, it leads to memory corruption when the next kernel is loaded. To fix this, modify KHO to allocate its metadata directly from the buddy allocator instead of slab. Fixes: fc33e4b44b27 ("kexec: enable KHO support for memory preservation") Signed-off-by: Pasha Tatashin Reviewed-by: Pratyush Yadav --- kernel/liveupdate/kexec_handover.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/kernel/liveupdate/kexec_handover.c b/kernel/liveupdate/kexec_h= andover.c index 7c8e89a6b953..92662739a3a2 100644 --- a/kernel/liveupdate/kexec_handover.c +++ b/kernel/liveupdate/kexec_handover.c @@ -132,6 +132,8 @@ static struct kho_out kho_out =3D { .finalized =3D false, }; =20 +DEFINE_FREE(kho_free_page, void *, free_page((unsigned long)_T)) + static void *xa_load_or_alloc(struct xarray *xa, unsigned long index) { void *res =3D xa_load(xa, index); @@ -139,7 +141,7 @@ static void *xa_load_or_alloc(struct xarray *xa, unsign= ed long index) if (res) return res; =20 - void *elm __free(kfree) =3D kzalloc(PAGE_SIZE, GFP_KERNEL); + void *elm __free(kho_free_page) =3D (void *)get_zeroed_page(GFP_KERNEL); =20 if (!elm) return ERR_PTR(-ENOMEM); @@ -352,9 +354,9 @@ static_assert(sizeof(struct khoser_mem_chunk) =3D=3D PA= GE_SIZE); static struct khoser_mem_chunk *new_chunk(struct khoser_mem_chunk *cur_chu= nk, unsigned long order) { - struct khoser_mem_chunk *chunk __free(kfree) =3D NULL; + struct khoser_mem_chunk *chunk __free(kho_free_page) =3D NULL; =20 - chunk =3D kzalloc(PAGE_SIZE, GFP_KERNEL); + chunk =3D (void *)get_zeroed_page(GFP_KERNEL); if (!chunk) return ERR_PTR(-ENOMEM); =20 --=20 2.51.0.915.g61a8936c21-goog